#include "CFGFileParser.h" CFGFileParser::CFGFileParser(SDCardManager &sdCardManager, const char *file):AbstractParser(file), _state(INIT), _type(PARAMETER), _quotedParameter(false), _quotedValue(false), _sdCardManager(sdCardManager) { } void *CFGFileParser::parseFile() { //Here is the logic for the file parser File file; CFGDictionary *dictioRef = new CFGDictionary; char readChar(0), *parsedParameter(NULL), *parsedValue(NULL); if(!_sdCardManager.isMounted()) return NULL; file = _sdCardManager.open(_resource); if(!file) { delete dictioRef; return NULL; } _state = INIT; while(file.available()) { readChar = (char)file.read(); //Do work switch(_state) { case INIT: if(readChar == '#') _state = COMMENT_SECTION; else if((readChar >= 65 && readChar <= 90) || (readChar >= 97 && readChar <= 122) || (readChar >= 48 && readChar <= 57)) { _state = PARAM_SECTION; parsedParameter = addChar(parsedParameter, readChar); if(parsedParameter == NULL) _state = ERROR; //printf("%c",readChar); } else if(readChar == '\'') { _state = OPENING_QUOTE; _type = PARAMETER; } else _state = ERROR; break; case COMMENT_SECTION: if(readChar == '\r' || readChar == '\n') _state = LINE_BREAK; break; case LINE_BREAK: if(readChar == '#') _state = COMMENT_SECTION; else if(readChar == '\r' || readChar == '\n') _state = LINE_BREAK; else if((readChar >= 65 && readChar <= 90) || (readChar >= 97 && readChar <= 122) || (readChar >= 48 && readChar <= 57)) { _state = PARAM_SECTION; //printf("%c",readChar); _type = PARAMETER; parsedParameter = addChar(parsedParameter, readChar); if(parsedParameter == NULL) _state = ERROR; } else if(readChar == '\'') { _state = OPENING_QUOTE; _type = PARAMETER; } else _state = ERROR; break; case PARAM_SECTION: if(readChar == '\'')_state = OPENING_QUOTE; else if(readChar == ':') _state = SEPARATION; else if(readChar == '\r' || readChar == '\n') { _state = LINE_BREAK; if(parsedParameter != NULL) { //printf("%s --> %s\n", parsedParameter, parsedValue); dictioRef->add(parsedParameter, new CFGParameterValue(parsedParameter, parsedValue == NULL ? "":parsedValue, _quotedParameter, _quotedValue)); free(parsedParameter);free(parsedValue); parsedParameter = NULL;parsedValue = NULL; _quotedParameter = false;_quotedValue = false; } } else if(readChar == ' ') _state = PARAM_SECTION; else if((readChar >= 65 && readChar <= 90) || (readChar >= 97 && readChar <= 122) || readChar == '_' || (readChar >= 48 && readChar <= 57)) { if(_type == PARAMETER) { parsedParameter = addChar(parsedParameter, readChar); if(parsedParameter == NULL) _state = ERROR; } else { parsedValue = addChar(parsedValue, readChar); if(parsedValue == NULL) _state = ERROR; } //printf("%c",readChar); } else _state = ERROR; break; case OPENING_QUOTE: if(readChar == '\'') { _state = PARAM_SECTION; if(_type == PARAMETER) _quotedParameter = true; else _quotedValue = true; } else if((readChar >= 65 && readChar <= 90) || (readChar >= 97 && readChar <= 122) || readChar == ' ' || readChar == '_' || (readChar >= 48 && readChar <= 57)) { //printf("%c",readChar); if(_type == PARAMETER) { parsedParameter = addChar(parsedParameter, readChar); if(parsedParameter == NULL) _state = ERROR; } else { parsedValue = addChar(parsedValue, readChar); if(parsedValue == NULL) _state = ERROR; } } else _state = ERROR; break; case SEPARATION: _type = VALUE; if(readChar == '\'')_state = OPENING_QUOTE; else if(readChar == ' ') _state = PARAM_SECTION; else if((readChar >= 65 && readChar <= 90) || (readChar >= 97 && readChar <= 122) || (readChar >= 48 && readChar <= 57)) { _state = PARAM_SECTION; parsedValue = addChar(parsedValue, readChar); if(parsedValue == NULL) _state = ERROR; } else _state = ERROR; break; case ERROR: dictioRef->dispose(); delete dictioRef; free(parsedValue); free(parsedParameter); parsedValue = NULL; parsedParameter = NULL; return NULL; break; } } file.close(); return dictioRef; } boolean CFGFileParser::save(void *data) { if(data == NULL) return false; Dictionary *ref = (Dictionary *) data; uint64_t truncateHere(0); char readChar(0); if(!_sdCardManager.isMounted()) return NULL; File file = _sdCardManager.open(_resource, FILE_READWRITE); if(!file) { return false; } file.seek(0); _state = INIT; //We find out where to truncate the file while(file.available()) { readChar = (char)file.read(); switch(_state) { case INIT: if(readChar == '#') { truncateHere++; _state = COMMENT_SECTION; } else _state = DONE; break; case COMMENT_SECTION: truncateHere++; if(readChar == '\n') _state = LINE_BREAK; break; case LINE_BREAK: truncateHere++; if(readChar == '#') _state = COMMENT_SECTION; else if(readChar == '\n') _state = DONE; break; } } if(!file.truncate(truncateHere)) { file.close(); return false; } //Let's write the settings for(int i = 0; i < ref->count(); i++) { CFGParameterValue *cfgPV = ref->getAt(i); if(cfgPV->isQuotedParameter()) { file.write('\''); file.print(cfgPV->getParameter()); file.write('\''); } else { file.print(cfgPV->getParameter()); } file.print(F(" : ")); if(cfgPV->isQuotedValue()) { file.write('\''); file.print(cfgPV->stringValue()); file.println('\''); } else { file.println(cfgPV->stringValue()); } } file.close(); return true; }