From 7a5c90ccca3b311537c74dbfbaf89586b751b3ba Mon Sep 17 00:00:00 2001 From: Jan Holthuis Date: Tue, 18 Aug 2015 19:36:19 +0200 Subject: [PATCH] cfg: Reimplement ConfigFile using C++ maps and strings --- core/cfg/cfg.cpp | 58 ++++--- core/cfg/ini.cpp | 409 +++++++++++++++++++++-------------------------- core/cfg/ini.h | 72 +++++---- 3 files changed, 255 insertions(+), 284 deletions(-) diff --git a/core/cfg/cfg.cpp b/core/cfg/cfg.cpp index a162d2eb6..e5c10f885 100644 --- a/core/cfg/cfg.cpp +++ b/core/cfg/cfg.cpp @@ -28,13 +28,13 @@ void savecfgf() printf("Error : Unable to open file for saving \n"); else { - cfgdb.SaveFile(cfgfile); + cfgdb.save(cfgfile); fclose(cfgfile); } } void cfgSaveStr(const wchar * Section, const wchar * Key, const wchar * String) { - cfgdb.GetEntry(Section)->SetEntry(Key,String,CEM_SAVE); + cfgdb.set(string(Section), string(Key), string(String)); savecfgf(); //WritePrivateProfileString(Section,Key,String,cfgPath); } @@ -42,7 +42,7 @@ void cfgSaveStr(const wchar * Section, const wchar * Key, const wchar * String) /* I want config to be really flexible .. so , here is the new implementation : - + Functions : cfgLoadInt : Load an int , if it does not exist save the default value to it and return it cfgSaveInt : Save an int @@ -84,28 +84,28 @@ bool cfgOpen() FILE* cfgfile = fopen(cfgPath.c_str(),"r"); if(!cfgfile) { cfgfile = fopen(cfgPath.c_str(),"wt"); - if(!cfgfile) + if(!cfgfile) printf("Unable to open the config file for reading or writing\nfile : %s\n",cfgPath.c_str()); else { fseek(cfgfile,0,SEEK_SET); fclose(cfgfile); cfgfile = fopen(cfgPath.c_str(),"r"); - if(!cfgfile) + if(!cfgfile) printf("Unable to open the config file for reading\nfile : %s\n",cfgPath.c_str()); } } - cfgdb.ParseFile(cfgfile); + cfgdb.parse(cfgfile); - for (size_t i=0;iSetEntry(vlist[i].n,vlist[i].v,CEM_VIRTUAL); - } + }*/ if (cfgfile) { - cfgdb.SaveFile(cfgfile); + cfgdb.save(cfgfile); fclose(cfgfile); } return true; @@ -119,32 +119,48 @@ bool cfgOpen() //2 : found section & key s32 cfgExists(const wchar * Section, const wchar * Key) { - return cfgdb.Exists(Section, Key); + if(cfgdb.has_entry(string(Section), string(Key))) + { + return 2; + } + else + { + return (cfgdb.has_section(string(Section)) ? 1 : 0); + } } void cfgLoadStr(const wchar * Section, const wchar * Key, wchar * Return,const wchar* Default) { - return cfgdb.LoadStr(Section, Key, Return, Default); + string value = cfgdb.get(Section, Key, Default); + strcpy(Return, value.c_str()); } string cfgLoadStr(const wchar * Section, const wchar * Key, const wchar* Default) { - return cfgdb.LoadStr(Section, Key, Default); + if(!cfgdb.has_entry(string(Section), string(Key))) + { + cfgSaveStr(Section, Key, Default); + } + return cfgdb.get(string(Section), string(Key), string(Default)); } //These are helpers , mainly :) -s32 cfgLoadInt(const wchar * Section, const wchar * Key,s32 Default) -{ - return cfgdb.LoadInt(Section, Key, Default); -} - void cfgSaveInt(const wchar * Section, const wchar * Key, s32 Int) { - wchar tmp[32]; - sprintf(tmp,"%d", Int); - cfgSaveStr(Section,Key,tmp); + return cfgdb.set_int(string(Section), string(Key), Int); } + +s32 cfgLoadInt(const wchar * Section, const wchar * Key,s32 Default) +{ + if(!cfgdb.has_entry(string(Section), string(Key))) + { + cfgSaveInt(Section, Key, Default); + } + return cfgdb.get_int(string(Section), string(Key), Default); +} + void cfgSetVirtual(const wchar * Section, const wchar * Key, const wchar * String) { - vlist.push_back(vitem(Section,Key,String)); + //vlist.push_back(vitem(Section,Key,String)); //cfgdb.GetEntry(Section,CEM_VIRTUAL)->SetEntry(Key,String,CEM_VIRTUAL); } + diff --git a/core/cfg/ini.cpp b/core/cfg/ini.cpp index 03bc4e9ae..c6f9be940 100644 --- a/core/cfg/ini.cpp +++ b/core/cfg/ini.cpp @@ -1,299 +1,252 @@ #include "ini.h" +#include wchar* trim_ws(wchar* str); -ConfigEntry::ConfigEntry(ConfigEntry* pp) +/* ConfigEntry */ + +string ConfigEntry::get_string() { - next=pp; - flags=0; + return this->value; } -void ConfigEntry::SaveFile(FILE* file) +int ConfigEntry::get_int() { - if (flags & CEM_SAVE) - fprintf(file,"%s=%s\n",name.c_str(),value.c_str()); -} - -string ConfigEntry::GetValue() -{ - if (flags&CEM_VIRTUAL) - return valueVirtual; - else - return value; -} - -ConfigSection::ConfigSection(ConfigSection* pp) -{ - next=pp; - flags=0; - entrys=0; -} - -ConfigEntry* ConfigSection::FindEntry(string name) -{ - ConfigEntry* c= entrys; - while(c) + if (strstr(this->value.c_str(), "0x") != NULL) { - if (stricmp(name.c_str(),c->name.c_str())==0) - return c; - c=c->next; - } - return 0; -} - -void ConfigSection::SetEntry(string name,string value,u32 eflags) -{ - ConfigEntry* c=FindEntry(name); - if (c) - { - //readonly is read only =) - if (c->flags & CEM_READONLY) - return; - - //virtual : save only if different value - if (c->flags & CEM_VIRTUAL) - { - - if(stricmp(c->valueVirtual.c_str(),value.c_str())==0) - return; - c->flags&=~CEM_VIRTUAL; - } + return strtol(this->value.c_str(), NULL, 16); } else { - entrys=c= new ConfigEntry(entrys); - c->name=name; + return atoi(this->value.c_str()); } +} - verify(!(c->flags&(CEM_VIRTUAL|CEM_READONLY))); - //Virtual - //Virtual | ReadOnly - //Save - if (eflags & CEM_VIRTUAL) +bool ConfigEntry::get_bool() +{ + if (strcmp(this->value.c_str(), "yes") == 0 || + strcmp(this->value.c_str(), "true") == 0 || + strcmp(this->value.c_str(), "on") == 0 || + strcmp(this->value.c_str(), "1") == 0) { - verify(!(eflags & CEM_SAVE)); - c->flags|=eflags; - c->valueVirtual=value; - } - else if (eflags & CEM_SAVE) - { - verify(!(eflags & (CEM_VIRTUAL|CEM_READONLY))); - flags|=CEM_SAVE; - c->flags|=CEM_SAVE; - - c->value=value; + return true; } else { - die("Invalid eflags value"); + return false; } - } -ConfigSection::~ConfigSection() +/* ConfigSection */ + +bool ConfigSection::has_entry(string name) { - ConfigEntry* n=entrys; - - while(n) + return (this->entries.count(name) == 1); +}; + +ConfigEntry* ConfigSection::get_entry(string name) +{ + if(this->has_entry(name)) { - ConfigEntry* p=n; - n=n->next; - delete p; + return &this->entries[name]; } + return NULL; +}; + +void ConfigSection::set(string name, string value, int flags) +{ + ConfigEntry new_entry = { value, flags }; + this->entries[name] = new_entry; +}; + +/* ConfigFile */ + +bool ConfigFile::has_section(string name) +{ + return (this->sections.count(name) == 1); +}; + +bool ConfigFile::has_entry(string section_name, string entry_name) +{ + ConfigSection* section = this->get_section(section_name); + return ((section == NULL) ? false : section->has_entry(entry_name)); } -void ConfigSection::SaveFile(FILE* file) +ConfigSection* ConfigFile::add_section(string name) { - if (flags&CEM_SAVE) + ConfigSection new_section; + this->sections.insert(std::make_pair(name, new_section)); + return &this->sections[name]; +}; + +ConfigSection* ConfigFile::get_section(string name) +{ + if(this->has_section(name)) { - fprintf(file,"[%s]\n",name.c_str()); - - vector stuff; - - ConfigEntry* n=entrys; - - while(n) - { - stuff.push_back(n); - n=n->next; - } - - for (int i=stuff.size()-1;i>=0;i--) - { - stuff[i]->SaveFile(file); - } - - fprintf(file,"\n"); + return &this->sections[name]; } -} + return NULL; +}; -ConfigSection* ConfigFile::FindSection(string name) +ConfigEntry* ConfigFile::get_entry(string section_name, string entry_name) { - ConfigSection* c= entrys; - while(c) + ConfigSection* section = this->get_section(section_name); + if(section == NULL) { - if (stricmp(name.c_str(),c->name.c_str())==0) - return c; - c=c->next; + return NULL; } - return 0; + return section->get_entry(entry_name); } -ConfigSection* ConfigFile::GetEntry(string name) +string ConfigFile::get(string section_name, string entry_name, string default_value) { - ConfigSection* c=FindSection(name); - if (!c) + ConfigEntry* entry = this->get_entry(section_name, entry_name); + if (entry == NULL) { - entrys=c= new ConfigSection(entrys); - c->name=name; + return default_value; } - - return c; -} - -ConfigFile::~ConfigFile() -{ - ConfigSection* n=entrys; - - while(n) + else { - ConfigSection* p=n; - n=n->next; - delete p; + return entry->get_string(); } } -void ConfigFile::ParseFile(FILE* file) +int ConfigFile::get_int(string section_name, string entry_name, int default_value) { - wchar line[512]; - wchar cur_sect[512]={0}; - int cline=0; + ConfigEntry* entry = this->get_entry(section_name, entry_name); + if (entry == NULL) + { + return default_value; + } + else + { + return entry->get_int(); + } +} + +bool ConfigFile::get_bool(string section_name, string entry_name, bool default_value) +{ + ConfigEntry* entry = this->get_entry(section_name, entry_name); + if (entry == NULL) + { + return default_value; + } + else + { + return entry->get_bool(); + } +} + +void ConfigFile::set(string section_name, string entry_name, string value, int flags) +{ + ConfigSection* section = this->get_section(section_name); + if(section == NULL) + { + section = this->add_section(section_name); + } + section->set(entry_name, value, flags); +}; + +void ConfigFile::set_int(string section_name, string entry_name, int value, int flags) +{ + std::stringstream str_value; + str_value << value; + this->set(section_name, entry_name, str_value.str()); +} + +void ConfigFile::set_bool(string section_name, string entry_name, bool value, int flags) +{ + string str_value = (value ? "yes" : "no"); + this->set(section_name, entry_name, str_value); +} + +void ConfigFile::parse(FILE* file) +{ + if(file == NULL) + { + return; + } + char line[512]; + char current_section[512] = { '\0' }; + int cline = 0; while(file && !feof(file)) { - fgets(line,512,file); + fgets(line, 512, file); if (feof(file)) + { break; + } cline++; - if (strlen(line)<3) - continue; - if (line[strlen(line)-1]=='\r' || line[strlen(line)-1]=='\n') - line[strlen(line)-1]=0; - - wchar* tl=trim_ws(line); - if (tl[0]=='[' && tl[strlen(tl)-1]==']') + if (strlen(line) < 3) { - tl[strlen(tl)-1]=0; - strcpy(cur_sect,tl+1); - trim_ws(cur_sect); + continue; + } + + if (line[strlen(line)-1] == '\r' || + line[strlen(line)-1] == '\n') + { + line[strlen(line)-1] = '\0'; + } + + char* tl = trim_ws(line); + + if (tl[0] == '[' && tl[strlen(tl)-1] == ']') + { + tl[strlen(tl)-1] = '\0'; + strcpy(current_section, tl+1); + trim_ws(current_section); } else { - if (cur_sect[0]==0) - continue;//no open section - wchar* str1=strstr(tl,"="); - if (!str1) + if (strlen(current_section) == 0) { - printf("Malformed entry on config - ignoring @ %d(%s)\n",cline,tl); + continue; //no open section + } + + char* separator = strstr(tl, "="); + + if (!separator) + { + printf("Malformed entry on config - ignoring @ %d(%s)\n",cline, tl); continue; } - *str1=0; - str1++; - wchar* v=trim_ws(str1); - wchar* k=trim_ws(tl); - if (v && k) + + *separator = '\0'; + + char* name = trim_ws(tl); + char* value = trim_ws(separator + 1); + if (name == NULL || value == NULL) { - ConfigSection*cs=this->GetEntry(cur_sect); - - //if (!cs->FindEntry(k)) - cs->SetEntry(k,v,CEM_SAVE|CEM_LOAD); + printf("Malformed entry on config - ignoring @ %d(%s)\n",cline, tl); + continue; } else { - printf("Malformed entry on config - ignoring @ %d(%s)\n",cline,tl); + this->set(string(current_section), string(name), string(value)); } } } } -void ConfigFile::SaveFile(FILE* file) +void ConfigFile::save(FILE* file) { - vector stuff; - - ConfigSection* n=entrys; - - while(n) + for(std::map::iterator section_it = this->sections.begin(); + section_it != this->sections.end(); section_it++) { - stuff.push_back(n); - n=n->next; - } + string section_name = section_it->first; + ConfigSection section = section_it->second; + fprintf(file, "[%s]\n", section_name.c_str()); - for (int i=stuff.size()-1;i>=0;i--) - { - if (stuff[i]->name!="emu") - stuff[i]->SaveFile(file); - } -} - -s32 ConfigFile::Exists(const wchar * Section, const wchar * Key) -{ - if (Section==0) - return -1; - //return cfgRead(Section,Key,0); - ConfigSection*cs= this->FindSection(Section); - if (cs == 0) - return 0; - - if (Key==0) - return 1; - - ConfigEntry* ce=cs->FindEntry(Key); - if (ce!=0) - return 2; - else - return 0; -} - -void ConfigFile::LoadStr(const wchar * Section, const wchar * Key, wchar * Return,const wchar* Default) -{ - verify(Return!=0); - string value = this->LoadStr(Section, Key, Default); - strcpy(Return, value.c_str()); -} - -string ConfigFile::LoadStr(const wchar * Section, const wchar * Key, const wchar* Default) -{ - verify(Section != 0 && strlen(Section) != 0); - verify(Key != 0 && strlen(Key) != 0); - - if (Default == 0) - Default = ""; - ConfigSection* cs = this->GetEntry(Section); - ConfigEntry* ce = cs->FindEntry(Key); - if (!ce) - { - cs->SetEntry(Key, Default, CEM_SAVE); - return Default; - } - else - { - return ce->GetValue(); - } -} - -s32 ConfigFile::LoadInt(const wchar * Section, const wchar * Key,s32 Default) -{ - wchar temp_d[30]; - wchar temp_o[30]; - sprintf(temp_d,"%d",Default); - this->LoadStr(Section,Key,temp_o,temp_d); - if (strstr(temp_o, "0x") != NULL) - { - return strtol(temp_o, NULL, 16); - } - else - { - return atoi(temp_o); + for(std::map::iterator entry_it = section.entries.begin(); + entry_it != section.entries.end(); entry_it++) + { + string entry_name = entry_it->first; + ConfigEntry entry = entry_it->second; + fprintf(file, "%s = %s\n", entry_name.c_str(), entry.get_string().c_str()); + } + + fputs("\n", file); } } diff --git a/core/cfg/ini.h b/core/cfg/ini.h index 05ae15fbc..cc0f53d76 100644 --- a/core/cfg/ini.h +++ b/core/cfg/ini.h @@ -1,5 +1,6 @@ #pragma once #include "types.h" +#include //A config remains virtual only as long as a write at it //doesn't override the virtual value.While a config is virtual, a copy of its 'real' value is held and preserved @@ -7,47 +8,48 @@ //Is this a virtual entry ? #define CEM_VIRTUAL 1 //Should the value be saved ? -#define CEM_SAVE 2 -//is this entry readonly ? +#define CEM_SAVE 2 +//is this entry readonly ? #define CEM_READONLY 4 //the move is from loading ? #define CEM_LOAD 8 -struct ConfigEntry -{ - u32 flags; - string name; +struct ConfigEntry { string value; - string valueVirtual; - ConfigEntry* next; - ConfigEntry(ConfigEntry*); - string GetValue(); - void SaveFile(FILE*); + int flags; //TODO: These have no effect right now + string get_string(); + int get_int(); + bool get_bool(); }; -struct ConfigSection -{ - u32 flags; - string name; - ConfigEntry* entrys; - ConfigSection* next; - ~ConfigSection(); - ConfigSection(ConfigSection*); - ConfigEntry* FindEntry(string); - void SetEntry(string, string, u32); - void SaveFile(FILE*); +struct ConfigSection { + std::map entries; + bool has_entry(string name); + void set(string name, string value, int flags); + ConfigEntry* get_entry(string name); }; -struct ConfigFile -{ - ConfigSection* entrys; - ~ConfigFile(); - void ParseFile(FILE*); - void SaveFile(FILE*); - ConfigSection* FindSection(string); - ConfigSection* GetEntry(string); - s32 Exists(const wchar *, const wchar *); - void LoadStr(const wchar *, const wchar *, wchar *,const wchar*); - string LoadStr(const wchar *, const wchar *, const wchar*); - s32 LoadInt(const wchar *, const wchar *,s32); -}; \ No newline at end of file +struct ConfigFile { + private: + std::map sections; + ConfigSection* add_section(string name); + ConfigSection* get_section(string name); + ConfigEntry* get_entry(string section_name, string entry_name); + + + public: + bool has_section(string name); + bool has_entry(string section_name, string entry_name); + + void parse(FILE* fd); + void save(FILE* fd); + + /* getting values */ + string get(string section_name, string entry_name, string default_value = ""); + int get_int(string section_name, string entry_name, int default_value = 0); + bool get_bool(string section_name, string entry_name, bool default_value = false); + /* setting values */ + void set(string section_name, string entry_name, string value, int flags = 0); + void set_int(string section_name, string entry_name, int value, int flags = 0); + void set_bool(string section_name, string entry_name, bool value, int flags = 0); +};