ESP8266_swiss_army_board/src/app/CFGFileParser.cpp

256 lines
7.3 KiB
C++

#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<CFGParameterValue> *dictioRef = new CFGDictionary<CFGParameterValue>;
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<CFGParameterValue> *ref = (Dictionary<CFGParameterValue> *) 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;
}