akmenu-next/arm9/source/inifile.cpp
Kei e7f1ade105 Fixed INI issues
Fixed INI settings
Changed how INI files get written
2025-06-07 20:55:39 +01:00

339 lines
10 KiB
C++

/*
inifile.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "inifile.h"
#include <fat.h>
#include <cstdio>
#include <cstdlib>
#include "dbgtool.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;
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;
// 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::SaveIniFile(const std::string& FileName) {
if (FileName != "") m_sFileName = FileName;
FILE* f = fopen(m_sFileName.c_str(), "w");
if (f == NULL) {
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(' ');
if (notSpace != std::string::npos) {
strline = strline.substr(notSpace);
}
if (strline.find('[') == 0 && ii > 0) {
if (!m_FileContainer[ii - 1].empty())
fprintf(f, "\n");
}
if (!strline.empty()) {
fprintf(f, "%s\n", strline.c_str());
}
}
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;
}