Rev 1 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "settings.h"#include "../common/strutils.h"#include <stdio.h>#include <windows.h>static Settings *g_settings;//---------------------------------------------------------------------------------#ifdef X2BC_USE_INI_FORMATSbool settings_parse_pair_const(const char *pszSectionName, Settings::conststringpair &p){return g_settings->parseConstant(pszSectionName, p);}//---------------------------------------------------------------------------------bool settings_parse_pair_format(const char *pszSectionName, Settings::conststringpair &p){return g_settings->parseFormat(pszSectionName, p);}//---------------------------------------------------------------------------------int CompareStatFormats(const void *a, const void *b){int ida, idb;ida=((Settings::StatFormat*)a)->id;idb=((Settings::StatFormat*)b)->id;return ((Settings::StatFormat*)a)->id - ((Settings::StatFormat*)b)->id;}#endif // defined(X2BC_USE_INI_FORMATS )//---------------------------------------------------------------------------------bool Settings::loadINI(const char *pszFileName){bool bRes;char szSectionName[50];g_settings=this;clearErrors();GetPrivateProfileString(L"library", L"WriteWarnings", L"off", (LPWSTR)szSectionName, sizeof(szSectionName), (LPCWSTR)pszFileName);m_bOutputWarnings=(_stricmp(szSectionName, "on")==0);GetPrivateProfileString(L"library", L"Convert", L"on", (LPWSTR)szSectionName, sizeof(szSectionName), (LPCWSTR)pszFileName);m_bConvert=(_stricmp(szSectionName, "on")==0);GetPrivateProfileString(L"library", L"FrameWarnings", L"on", (LPWSTR)szSectionName, sizeof(szSectionName), (LPCWSTR)pszFileName);m_bStatFormatWarnings=(_stricmp(szSectionName, "on")==0);GetPrivateProfileString(L"library", L"XtraPointInfo", L"on", (LPWSTR)szSectionName, sizeof(szSectionName), (LPCWSTR)pszFileName);m_bXtraPntInfo=(_stricmp(szSectionName, "on")==0);GetPrivateProfileString(L"library", L"XtraX3BobInfo", L"off", (LPWSTR)szSectionName, sizeof(szSectionName), (LPCWSTR)pszFileName);m_bXtraX3BobInfo=(_stricmp(szSectionName, "on")==0);#ifdef X2BC_USE_INI_FORMATSsize_t size;GetPrivateProfileString("library", "Constants", "Const", szSectionName, sizeof(szSectionName), pszFileName);char *pszConstants=readSection(szSectionName, pszFileName, &size);if(size==0){error(Error, E_SectionEmpty, "Section with constants '%s' not defined or empty.", szSectionName);bRes=false;}elsebRes=parseLines(szSectionName, pszConstants, size, settings_parse_pair_const);delete[] pszConstants;if(bRes){GetPrivateProfileString("library", "Default", "Format", szSectionName, sizeof(szSectionName), pszFileName);char *pszFormat=readSection(szSectionName, pszFileName, &size);if(size==0){error(Error, E_SectionEmpty, "Section with frame formats '%s' not defined or empty.", szSectionName);bRes=false;}elsebRes=parseLines(szSectionName, pszFormat, size, settings_parse_pair_format);delete[] pszFormat;}#elsebRes=true;#endif // !defined(X2BC_USE_INI_FORMATS)return bRes;}//---------------------------------------------------------------------------------void Settings::error(ErrorType type, ErrorCodes code, const char *format, ...){va_list ap;va_start(ap, format);ErrorMsg *e=new ErrorMsg();e->type=type;e->code=code;_vsnprintf(e->message, sizeof(e->message), format, ap);va_end(ap);errors.push_back(e);}//---------------------------------------------------------------------------------#ifdef X2BC_USE_INI_FORMATSchar * Settings::readSection(const char *pszSection, const char *pszFileName, size_t *size){char *data;int _size=0, res;do{_size+=1500;data=new char[_size];if(data==NULL) break;res=GetPrivateProfileSection(pszSection, data, _size, pszFileName);if(res==_size - 2){delete[] data;}}while(res==_size - 2);if(size) *size=res;return data;}//---------------------------------------------------------------------------------bool Settings::parseLines(const char *pszSectionName, char *pszData, size_t size, ParsePairCallback *callback){size_t count;char **lines=lineexplode(pszData, size, &count);bool bRes=true;for(size_t i=0; i < count; i++){char *line=lines[i];int j=0;bool bComment=false;char *equal, *left, *right;left=right=equal=0;while(line[j]!=0){switch(line[j]){case '=':line[j]=0;equal=line + j;left=line;break;case ';':line[j]=0;j--; // so the main while(...) will encouter this added 0 and terminatebreak;}j++;}if(equal){right=equal + 1;conststringpair p=parsePair(left, right);if(callback(pszSectionName, p)==false) {bRes=false;break; // break if parsing fails}}elseerror(Warning, W_LineIgnored, "Section \"%s\": line '%s' ignored.", pszSectionName, line);}delete[] lines;return bRes;}//---------------------------------------------------------------------------------// trim white spaces from left and rightSettings::conststringpair Settings::parsePair(const char *left, const char *right){conststringpair p;p.left=trim((char*)left);p.right=trim((char*)right);return p;}//---------------------------------------------------------------------------------bool Settings::parseConstant(const char *pszSectionName, Settings::conststringpair &p){bool res=true;NumberFormat *f=new NumberFormat();const char *pszMultiplier=0, *pszFormat=0;char *left, *right;// backup the original strings for error reportingsize_t len=strlen(p.left);left=new char[len + 1];memcpy(left, p.left, len + 1);len=strlen(p.right);right=new char[len + 1];memcpy(right, p.right, len + 1);// the left operand (constant name)if(*p.left==0){error(ErrorType::Error, E_BadConstantDeclaration, "Section \"%s\": line: '%s = %s':\nMissing constant name.", pszSectionName, left, right);res=false;}else if(strlen(p.left) > 1){error(ErrorType::Error, E_BadConstantDeclaration, "Section \"%s\": line: '%s = %s':\nConstant name must be exactly 1 character.", pszSectionName, left, right);res=false;}else if(!((*p.left | 0x20) > 'a') && ((*p.left | 0x20) < 'z')){error(Error, E_BadConstantDeclaration, "Section \"%s\": Constant \"%c\": constant name must be a upper or lowercase character (A - Z).", pszSectionName, *p.left);res=false;}if(res==false){delete[] left; delete[] right;return res;}f->type=*p.left;// the right operand (constant multiplier and format)pszMultiplier=p.right;char *pos=strchr(p.right, ',');if(pos){*pos=0;pszFormat=trim(++pos);}if(pszMultiplier==0 || *pszMultiplier==0){error(ErrorType::Error, E_BadConstantDeclaration, "Section \"%s\": line: '%s = %s':\nMissing constant multiplier.", pszSectionName, left, right);res=false;}else if(pszFormat==0 || *pszFormat==0){error(ErrorType::Error, E_BadConstantDeclaration, "Section \"%s\": line: '%s = %s':\nMissing output format specifier.", pszSectionName, left, right);res=false;}else{f->multiplier=atof(pszMultiplier);if(f->multiplier==0){error(ErrorType::Warning, W_ConstantAlwaysZero, "Section \"%s\": line: '%s = %s':\nMultiplier is 0. Result will be always zero. Is this the intent?", pszSectionName, left, right);}}if(res==true){if(stricmp(pszFormat, "integer")==0)f->outformat=NumberFormat::Integer;else if(stricmp(pszFormat, "float")==0)f->outformat=NumberFormat::Float;else{error(ErrorType::Error, E_BadConstantDeclaration, "Section \"%s\": line: '%s = %s':\nUnknown output format '%s'.", pszSectionName, left, right, pszFormat);res=false;}}delete[] left;delete[] right;if(res)m_constants.push_back(f);return res;}//---------------------------------------------------------------------------------bool Settings::parseFormat(const char *pszSectionName, conststringpair &p){bool bRes;switch(p.left[0]){case 0:error(ErrorType::Error, E_BadFormatDeclaration, "Section \"%s\": invalid line format: '%s = %s':\nID expected.", pszSectionName, p.left, p.right);bRes=false;break;case '$':bRes=parseStatFormat(pszSectionName, p);break;case 'N': // don't read the N constants - we use algorithm instead if INIbRes=true;break;default:error(Warning, W_LineIgnored, "Section \"%s\": ignoring line '%s = %s':\nUnknown ID type.", pszSectionName, p.left, p.right);bRes=true;}return bRes;}//---------------------------------------------------------------------------------bool Settings::parseStatFormat(const char *pszSectionName, conststringpair &p){char *left, *right;bool bRes=true;// backup the original strings for error reportingsize_t len=strlen(p.left);left=new char[len + 1];memcpy(left, p.left, len + 1);len=strlen(p.right);right=new char[len + 1];memcpy(right, p.right, len + 1);StatFormat *f=new StatFormat();if(p.left[0]==0){error(ErrorType::Error, E_BadFormatDeclaration, "Section \"%s\": line '%s = %s':\nMissing ID.", pszSectionName, left, right);bRes=false;}else{if(p.left[0]=='$') p.left++;f->id=hextoi(p.left);}if(bRes){char *ch=(char*)p.right;if(*ch!='"'){error(ErrorType::Error, E_BadFormatDeclaration, "Section \"%s\": line '%s = %s':\nExpected begining of string after \"%s =\".", pszSectionName, left, right, left);bRes=false;}else{ch++;while(*ch!=0 && *ch!='"') ch++;if(*ch==0){error(ErrorType::Error, E_BadFormatDeclaration, "Section \"%s\": line '%s = %s':\nExpected end of string after \"%s\".", pszSectionName, left, right, right);bRes=false;}else{*ch=0;bRes=parseFormatString(pszSectionName, f, (char*)p.right + 1);if(bRes) formats.push_back(f);}}}return bRes;}//---------------------------------------------------------------------------------bool isnum(char c){return (c >= '0' && c <= '9');}//---------------------------------------------------------------------------------bool Settings::parseFormatString(const char *pszSectionName, Settings::StatFormat *f, char *format){bool bRes=true;char *ch, *start;start=format;// if format begins with - a warning will be issued if such format is used in bob fileif(*start!=0 && *start=='-') {start++;f->issueWarning=true;}// skip any spaces after the '-'while(*start==' ') start++;while(*start!=0){ch=start;if(isnum(*ch)==false){error(Error, E_BadFormatDeclaration, "Section \"%s\": line id $%x:\nMissing number at start of '%s'.", pszSectionName, f->id, format);return false;}else{while(isnum(*ch)) ch++;if(*ch==0){error(Error, E_BadFormatDeclaration, "Section \"%s\": line id $%x:\nMissing constant after '%s'.", pszSectionName, f->id, ch);return false;}else{StatFormat::token *t=new StatFormat::token();char old=*ch;*ch=0;t->count=atoi(start);t->type=old;*ch=old;t->numFormat=findNumberFormat(t->type);if(t->numFormat==0){error(Error, E_BadFormatDeclaration, "Section \"%s\": line id $%x:\nConstant \"%c\" not defined in '%s'.", pszSectionName, f->id, t->type, format);delete t;return false;}f->tokens.push_back(t);// increase the cumulative count so it's easy to tell how many numbers is needed// to match the formatf->cumulativeTokenCount+=t->count;start=ch+1;while(*ch!=0 && isnum(*ch)==false) ch++;old=*ch;*ch=0;size_t size=ch-start;if(size){t->data=new char[size + 1];memcpy(t->data, start, size + 1);}*ch=old;start=ch;}}}return bRes;}//---------------------------------------------------------------------------------Settings::NumberFormat * Settings::findNumberFormat(char ch){char c;for(NumberFormatList::iterator &it=m_constants.begin(); it!=m_constants.end(); ++it){c=it->type;if(c==ch) return *it;}return NULL;}//---------------------------------------------------------------------------------#endif // defined(X2BC_USE_INI_FORMATS)