/* 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 #include #include #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& 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& 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; }