Create new ini handling class using cpp stuff

This commit is contained in:
edo9300 2019-02-13 23:32:22 +01:00
parent 82eda30cfd
commit 7a0dc2ef4b
5 changed files with 185 additions and 421 deletions

View file

@ -1,343 +0,0 @@
/*
inifile.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdio>
#include <cstdlib>
#include "inifile.h"
//#include "stringtool.h"
static bool freadLine(FILE* f, std::string& str) {
str.clear();
__read:
char p = 0;
size_t readed = fread(&p, 1, 1, f);
if(0 == readed) {
str = "";
return false;
}
if('\n' == p || '\r' == p) {
str = "";
return true;
}
while(p != '\n'&&p != '\r'&&readed) {
str += p;
readed = fread(&p, 1, 1, f);
}
if(str.empty() || "" == str) {
goto __read;
}
return true;
}
static void trimString(std::string& str) {
size_t first = str.find_first_not_of(" \t"), last;
if(first == str.npos) {
str = "";
} else {
last = str.find_last_not_of(" \t");
if(first > 0 || (last + 1) < str.length()) str = str.substr(first, last - first + 1);
}
}
CIniFile::CIniFile() {
m_bLastResult = false;
m_bModified = false;
m_bReadOnly = false;
}
CIniFile::CIniFile(const std::string& filename) {
m_sFileName = filename;
m_bLastResult = false;
m_bModified = false;
m_bReadOnly = false;
m_bHasHandle = false;
LoadIniFile(m_sFileName);
}
CIniFile::~CIniFile() {
if(m_FileContainer.size() > 0) {
m_FileContainer.clear();
}
}
void CIniFile::SetString(const std::string& Section, const std::string& Item, const std::string& Value) {
if(GetFileString(Section, Item) != Value) {
SetFileString(Section, Item, Value);
m_bModified = true;
}
}
/*void CIniFile::SetInt(const std::string& Section,const std::string& Item,int Value)
{
std::string strtemp=formatString("%d",Value);
if(GetFileString(Section,Item)!=strtemp)
{
SetFileString(Section,Item,strtemp);
m_bModified=true;
}
}*/
std::string CIniFile::GetString(const std::string& Section, const std::string& Item) {
return GetFileString(Section, Item);
}
std::string CIniFile::GetString(const std::string& Section, const std::string& Item, const std::string& DefaultValue) {
std::string temp = GetString(Section, Item);
if(!m_bLastResult) {
SetString(Section, Item, DefaultValue);
temp = DefaultValue;
}
return temp;
}
void CIniFile::GetStringVector(const std::string& Section, const std::string& Item, std::vector< std::string >& strings, char delimiter) {
std::string strValue = GetFileString(Section, Item);
strings.clear();
size_t pos;
while((pos = strValue.find(delimiter), strValue.npos != pos)) {
const std::string string = strValue.substr(0, pos);
if(string.length()) {
strings.push_back(string);
}
strValue = strValue.substr(pos + 1, strValue.npos);
}
if(strValue.length()) {
strings.push_back(strValue);
}
}
void CIniFile::SetStringVector(const std::string& Section, const std::string& Item, std::vector<std::string>& strings, char delimiter) {
std::string strValue;
for(size_t ii = 0; ii < strings.size(); ++ii) {
if(ii) strValue += delimiter;
strValue += strings[ii];
}
SetString(Section, Item, strValue);
}
/*int CIniFile::GetInt(const std::string& Section,const std::string& Item)
{
std::string value=GetFileString(Section,Item);
if(value.size()>2&&'0'==value[0]&&('x'==value[1]||'X'==value[1]))
return strtol(value.c_str(),NULL,16);
else
return strtol(value.c_str(),NULL,10);
}
int CIniFile::GetInt(const std::string& Section,const std::string& Item,int DefaultValue)
{
int temp;
temp=GetInt(Section,Item);
if(!m_bLastResult)
{
SetInt(Section,Item,DefaultValue);
temp=DefaultValue;
}
return temp;
}*/
bool CIniFile::LoadIniFile(const std::string& FileName) {
//dbg_printf("load %s\n",FileName.c_str());
if(FileName != "") m_sFileName = FileName;
FILE* f = fopen(FileName.c_str(), "rb");
if(NULL == f) return false;
m_bHasHandle = true;
//check for utf8 bom.
char bom[3];
if(fread(bom, 3, 1, f) == 1 && bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf);
else fseek(f, 0, SEEK_SET);
std::string strline("");
m_FileContainer.clear();
while(freadLine(f, strline)) {
trimString(strline);
if(strline != ""&&';' != strline[0] && '/' != strline[0] && '!' != strline[0]) m_FileContainer.push_back(strline);
}
fclose(f);
m_bLastResult = false;
m_bModified = false;
return true;
}
bool CIniFile::SaveIniFileModified(const std::string& FileName) {
if(m_bModified == true) {
return SaveIniFile(FileName);
}
return true;
}
bool CIniFile::HasFileHandle() {
return m_bHasHandle;
}
bool CIniFile::SaveIniFile(const std::string& FileName) {
if(FileName != "")
m_sFileName = FileName;
FILE* f = fopen(m_sFileName.c_str(), "wb");
if(NULL == f) {
return false;
}
for(size_t ii = 0; ii < m_FileContainer.size(); ii++) {
std::string& strline = m_FileContainer[ii];
size_t notSpace = strline.find_first_not_of(' ');
strline = strline.substr(notSpace);
if(strline.find('[') == 0 && ii > 0) {
if(!m_FileContainer[ii - 1].empty() && m_FileContainer[ii - 1] != "")
fwrite("\r\n", 1, 2, f);
}
if(!strline.empty() && strline != "") {
fwrite(strline.c_str(), 1, strline.length(), f);
fwrite("\r\n", 1, 2, f);
}
}
fclose(f);
m_bModified = false;
return true;
}
std::string CIniFile::GetFileString(const std::string& Section, const std::string& Item) {
std::string strline;
std::string strSection;
std::string strItem;
std::string strValue;
size_t ii = 0;
size_t iFileLines = m_FileContainer.size();
if(m_bReadOnly) {
cSectionCache::iterator it = m_Cache.find(Section);
if((it != m_Cache.end())) ii = it->second;
}
m_bLastResult = false;
if(iFileLines >= 0) {
while(ii < iFileLines) {
strline = m_FileContainer[ii++];
size_t rBracketPos = 0;
if('[' == strline[0]) rBracketPos = strline.find(']');
if(rBracketPos > 0 && rBracketPos != std::string::npos) {
strSection = strline.substr(1, rBracketPos - 1);
if(m_bReadOnly) m_Cache.insert(std::make_pair(strSection, ii - 1));
if(strSection == Section) {
while(ii < iFileLines) {
strline = m_FileContainer[ii++];
size_t equalsignPos = strline.find('=');
if(equalsignPos != strline.npos) {
size_t last = equalsignPos ? strline.find_last_not_of(" \t", equalsignPos - 1) : strline.npos;
if(last == strline.npos) strItem = "";
else strItem = strline.substr(0, last + 1);
if(strItem == Item) {
size_t first = strline.find_first_not_of(" \t", equalsignPos + 1);
if(first == strline.npos) strValue = "";
else strValue = strline.substr(first);
m_bLastResult = true;
return strValue;
}
} else if('[' == strline[0]) {
break;
}
}
break;
}
}
}
}
return std::string("");
}
void CIniFile::SetFileString(const std::string& Section, const std::string& Item, const std::string& Value) {
std::string strline;
std::string strSection;
std::string strItem;
if(m_bReadOnly) return;
size_t ii = 0;
size_t iFileLines = m_FileContainer.size();
while(ii < iFileLines) {
strline = m_FileContainer[ii++];
size_t rBracketPos = 0;
if('[' == strline[0]) rBracketPos = strline.find(']');
if(rBracketPos > 0 && rBracketPos != std::string::npos) {
strSection = strline.substr(1, rBracketPos - 1);
if(strSection == Section) {
while(ii < iFileLines) {
strline = m_FileContainer[ii++];
size_t equalsignPos = strline.find('=');
if(equalsignPos != strline.npos) {
size_t last = equalsignPos ? strline.find_last_not_of(" \t", equalsignPos - 1) : strline.npos;
if(last == strline.npos) strItem = "";
else strItem = strline.substr(0, last + 1);
if(Item == strItem) {
ReplaceLine(ii - 1, Item + " = " + Value);
return;
}
} else if('[' == strline[0]) {
InsertLine(ii - 1, Item + " = " + Value);
return;
}
}
InsertLine(ii, Item + " = " + Value);
return;
}
}
}
InsertLine(ii, "[" + Section + "]");
InsertLine(ii + 1, Item + " = " + Value);
return;
}
bool CIniFile::InsertLine(size_t line, const std::string& str) {
m_FileContainer.insert(m_FileContainer.begin() + line, str);
return true;
}
bool CIniFile::ReplaceLine(size_t line, const std::string& str) {
m_FileContainer[line] = str;
return true;
}

View file

@ -1,68 +0,0 @@
/*
inifile.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009-2010 yellow wood goblin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _INIFILE_H_
#define _INIFILE_H_
#include <string>
#include <vector>
#include <map>
class CIniFile {
public:
CIniFile();
CIniFile(const std::string& filename);
virtual ~CIniFile();
public:
bool LoadIniFile(const std::string& FileName);
bool SaveIniFile(const std::string& FileName);
bool SaveIniFileModified(const std::string& FileName);
bool HasFileHandle();
std::string GetString(const std::string& Section, const std::string& Item, const std::string& DefaultValue);
void SetString(const std::string& Section, const std::string& Item, const std::string& Value);
int GetInt(const std::string& Section, const std::string& Item, int DefaultValue);
void SetInt(const std::string& Section, const std::string& Item, int Value);
void GetStringVector(const std::string& Section, const std::string& Item, std::vector<std::string>& strings, char delimiter = ',');
void SetStringVector(const std::string& Section, const std::string& Item, std::vector<std::string>& strings, char delimiter = ',');
protected:
std::string m_sFileName;
typedef std::vector<std::string> cStringArray;
cStringArray m_FileContainer;
bool m_bLastResult;
bool m_bModified;
bool m_bReadOnly;
bool m_bHasHandle;
typedef std::map<std::string, size_t> cSectionCache;
cSectionCache m_Cache;
bool InsertLine(size_t line, const std::string& str);
bool ReplaceLine(size_t line, const std::string& str);
void SetFileString(const std::string& Section, const std::string& Item, const std::string& Value);
std::string GetFileString(const std::string& Section, const std::string& Item);
std::string GetString(const std::string& Section, const std::string& Item);
int GetInt(const std::string& Section, const std::string& Item);
};
#endif // _INIFILE_H_

View file

@ -0,0 +1,97 @@
/*
inihandler.cpp
Copyright (C) 2019 edo9300
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "inihandler.h"
#include <fstream>
bool IniFile::LoadFile(const std::string & filename) {
std::ifstream inifile(filename, std::ifstream::in);
if(!inifile.is_open())
return false;
is_from_file = true;
cur_filename = filename;
std::string cur_str;
std::string cur_field("");
auto remove_trailing_space = [](const std::string& str) {
auto pos = str.find_last_of(" ");
if(pos != std::string::npos)
return str.substr(0, pos);
return str;
};
auto remove_leading_space = [](const std::string& str) {
auto pos = str.find_first_of(" ");
if(pos != std::string::npos)
return str.substr(pos + 1);
return str;
};
while(std::getline(inifile, cur_str)) {
auto pos = cur_str.find_first_of("\n\r");
if(cur_str.size() && pos != std::string::npos)
cur_str = cur_str.substr(0, pos);
pos = cur_str.find('[');
if(pos != std::string::npos) {
auto endpos = cur_str.find(']');
cur_field = cur_str.substr(pos + 1, endpos - pos - 1);
continue;
}
if(cur_field == "")
continue;
pos = cur_str.find('=');
if(pos == std::string::npos)
continue;
auto key = remove_trailing_space(cur_str.substr(0, pos));
auto val = remove_leading_space(cur_str.substr(pos + 1, cur_str.size() - pos));
contents[cur_field].Set(key, val);
}
return true;
}
bool IniFile::SaveFile(const std::string & filename) {
if(filename != "")
cur_filename = filename;
std::ofstream inifile(cur_filename, std::ofstream::out);
if(!inifile.is_open())
return false;
modified = false;
for(auto& content : contents) {
inifile << "[" << content.first << "]\n";
for(auto& obj : content.second.GetHandle()) {
inifile << obj.first << " = " << obj.second << "\n";
}
}
return true;
}
void IniFile::SetValue(const std::string& field, const std::string& key, const std::string& _val) {
modified = true;
contents[field].Set(key, _val);
}
std::string IniFile::GetValueString(const std::string & field, const std::string & key, const std::string & _default) {
if(contents.find(key) != contents.end())
return contents[field].GetValString(key);
return _default;
}
int IniFile::GetValueInt(const std::string & field, const std::string & key, int _default) {
if(contents.find(key) != contents.end())
return contents[field].GetValInt(key);
return _default;
}

78
arm9/source/inihandler.h Normal file
View file

@ -0,0 +1,78 @@
/*
inihandler.h
Copyright (C) 2019 edo9300
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _BETTER_INIFILE_H_
#define _BETTER_INIFILE_H_
#include <string>
#include <map>
#include <functional>
class IniObj {
public:
IniObj(){};
void Set(const std::string& _key, const std::string& _val) {
val[_key] = _val;
}
void Set(const std::string& _key, int _val) {
val[_key] = std::to_string(_val);
}
std::string GetValString(const std::string& _key) {
if(val.find(_key) != val.end())
return val[_key];
return "";
}
int GetValInt(const std::string& _key) {
if(val.find(_key) != val.end())
return std::stoi(val[_key]);
return 0;
}
std::map<std::string, std::string>& GetHandle() {
return std::ref(val);
}
private:
std::map<std::string /*key*/, std::string /*val*/> val;
};
class IniFile {
public:
IniFile():is_from_file(false), modified(false){};
IniFile(const std::string& filename) :is_from_file(false), modified(false) {
LoadFile(filename);
};
bool LoadFile(const std::string& filename);
bool SaveFile(const std::string& filename = "");
bool SaveFileIfModified(const std::string& filename = "") {
return modified ? SaveFile(filename) : true;
};
void SetValue(const std::string& field, const std::string& key, const std::string& _val);
void SetValue(const std::string& field, const std::string& key, int _val) {
SetValue(field, key, std::to_string(_val));
};
std::string GetValueString(const std::string& field, const std::string& key, const std::string& _default = "");
int GetValueInt(const std::string& field, const std::string& key, int _default = 0);
bool HasFileHandle() {
return is_from_file;
};
private:
std::map<std::string/*field*/, IniObj> contents;
std::string cur_filename;
bool is_from_file;
bool modified;
};
#endif

View file

@ -14,11 +14,11 @@
#include "headers.h"
#include "utils.h"
#include "menu.h"
#include "inifile.h"
#include "inihandler.h"
#include "apppatch.h"
CIniFile bootsrtapconfig;
CIniFile bootstrap_template;
IniFile bootsrtapconfig;
IniFile bootstrap_template;
PrintConsole upperScreen;
PrintConsole lowerScreen;
@ -203,11 +203,11 @@ void CreateForwarder() {
Movefile("sd:/MakeForwarder/banner.nds", folderpath + "/content/00000000.app");
Movefile("sd:/MakeForwarder/title.tmd", folderpath + "/content/title.tmd");
if(bootstrap_template.HasFileHandle()) {
bootsrtapconfig.SaveIniFile((folderpath + "/data/config.ini").c_str());
bootstrap_template.SetString("NDS-BOOTSTRAP", "NDS_PATH", file.c_str());
bootsrtapconfig.SaveFile(folderpath + "/data/config.ini");
bootstrap_template.SetValue("NDS-BOOTSTRAP", "NDS_PATH", file.c_str());
std::string savePath = ReplaceAll(file, ".nds", ".sav");
bootstrap_template.SetString("NDS-BOOTSTRAP", "SAV_PATH", savePath.c_str());
bootstrap_template.SaveIniFile((folderpath + "/data/bootstrap.ini").c_str());
bootstrap_template.SetValue("NDS-BOOTSTRAP", "SAV_PATH", savePath.c_str());
bootstrap_template.SaveFile(folderpath + "/data/bootstrap.ini");
}
}
}
@ -224,10 +224,10 @@ void SetBootstrap() {
std::string bootstrappath = file.substr(0, found + 1);
std::string bootstrapversion = file.substr(found + 1);
bootsrtapconfig.SetString("NDS-FORWARDER", "BOOTSTRAP_PATH", bootstrappath.c_str());
bootsrtapconfig.SetString("NDS-FORWARDER", "BOOTSTRAP_VERSION", bootstrapversion.c_str());
bootsrtapconfig.SetValue("NDS-FORWARDER", "BOOTSTRAP_PATH", bootstrappath.c_str());
bootsrtapconfig.SetValue("NDS-FORWARDER", "BOOTSTRAP_VERSION", bootstrapversion.c_str());
bootstrap_template.LoadIniFile((bootstrappath + "nds-bootstrap.ini").c_str());
bootstrap_template.LoadFile(bootstrappath + "nds-bootstrap.ini");
}
void CheckResources() {