From f6638a173e21fbee3cc961d3dea82cc89382b873 Mon Sep 17 00:00:00 2001 From: Zaba999 Date: Wed, 26 Sep 2012 22:57:43 +0200 Subject: Work in progress on opening files, and listing dirs Fixed includes profile changed from SimpleIni to boost::ptree -> not finished yet --- src/app/app.cpp | 20 ++-- src/common/global.h | 8 +- src/common/profile.cpp | 118 +++++++++++++++---- src/common/profile.h | 6 +- src/object/robotmain.cpp | 47 ++++---- src/object/robotmain.h | 16 +-- src/plugins/pluginloader.h | 2 +- src/plugins/pluginmanager.h | 6 +- src/script/script.cpp | 4 +- src/sound/plugins/oalsound/CMakeLists.txt | 2 +- src/sound/plugins/oalsound/alsound.h | 6 +- src/sound/plugins/oalsound/buffer.h | 4 +- src/sound/plugins/oalsound/channel.h | 2 +- src/sound/plugins/oalsound/check.h | 2 +- src/sound/sound.h | 8 +- src/ui/maindialog.cpp | 183 ++++++++++++++++++------------ src/ui/maindialog.h | 49 ++++---- 17 files changed, 296 insertions(+), 187 deletions(-) diff --git a/src/app/app.cpp b/src/app/app.cpp index 00977d1..8c2dd43 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -132,7 +132,7 @@ CApplication::CApplication() m_dataPath = "./data"; - m_language = LANG_ENGLISH; + m_language = LANGUAGE_ENGLISH; m_lowCPU = true; @@ -215,13 +215,13 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[]) { waitLanguage = false; if (arg == "en") - m_language = LANG_ENGLISH; + m_language = LANGUAGE_ENGLISH; else if (arg == "de") - m_language = LANG_GERMAN; + m_language = LANGUAGE_GERMAN; else if (arg == "fr") - m_language = LANG_FRENCH; + m_language = LANGUAGE_FRENCH; else if (arg == "pl") - m_language = LANG_POLISH; + m_language = LANGUAGE_POLISH; else return PARSE_ARGS_FAIL; continue; @@ -293,19 +293,19 @@ bool CApplication::Create() std::string locale = "C"; switch (m_language) { - case LANG_ENGLISH: + case LANGUAGE_ENGLISH: locale = "en_US.utf8"; break; - case LANG_GERMAN: + case LANGUAGE_GERMAN: locale = "de_DE.utf8"; break; - case LANG_FRENCH: + case LANGUAGE_FRENCH: locale = "fr_FR.utf8"; break; - case LANG_POLISH: + case LANGUAGE_POLISH: locale = "pl_PL.utf8"; break; } @@ -326,7 +326,7 @@ bool CApplication::Create() // Temporarily -- only in windowed mode m_deviceConfig.fullScreen = false; - // Create the sound instance. + //Create the sound instance. if (!GetProfile()->InitCurrentDirectory()) { GetLogger()->Warn("Config not found. Default values will be used!\n"); m_sound = new CSoundInterface(); diff --git a/src/common/global.h b/src/common/global.h index 2f2104a..9704a2b 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -29,10 +29,10 @@ */ enum Language { - LANG_ENGLISH = 0, - LANG_FRENCH = 1, - LANG_GERMAN = 2, - LANG_POLISH = 3 + LANGUAGE_ENGLISH = 0, + LANGUAGE_FRENCH = 1, + LANGUAGE_GERMAN = 2, + LANGUAGE_POLISH = 3 }; /** diff --git a/src/common/profile.cpp b/src/common/profile.cpp index 1025567..0881c92 100644 --- a/src/common/profile.cpp +++ b/src/common/profile.cpp @@ -18,76 +18,132 @@ #include "common/profile.h" +#include "common/logger.h" #include #include +#include template<> CProfile* CSingleton::mInstance = nullptr; +namespace bp = boost::property_tree; CProfile::CProfile() { - m_ini = new CSimpleIniA(); - m_ini->SetUnicode(); - m_ini->SetMultiKey(); + // m_ini = new CSimpleIniA(); + // m_ini->SetUnicode(); + // m_ini->SetMultiKey(); } CProfile::~CProfile() { - m_ini->Reset(); - delete m_ini; + // m_ini->Reset(); + // delete m_ini; } bool CProfile::InitCurrentDirectory() { - bool result = m_ini->LoadFile("colobot.ini") == SI_OK; - return result; + try + { + bp::ini_parser::read_ini("colobot.ini", m_propertyTree); + } + catch (std::exception & e) + { + GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + } + // return result; + return true; } bool CProfile::SetLocalProfileString(std::string section, std::string key, std::string value) { - return (m_ini->SetValue(section.c_str(), key.c_str(), value.c_str()) == SI_OK); + try + { + m_propertyTree.put(section + "." + key, value); + } + catch (std::exception & e) + { + GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + } + // return (m_ini->SetValue(section.c_str(), key.c_str(), value.c_str()) == SI_OK); + return true; } bool CProfile::GetLocalProfileString(std::string section, std::string key, std::string &buffer) { - const char* value = m_ini->GetValue(section.c_str(), key.c_str(), nullptr); - if (value != nullptr && strlen(value) > 0) { - buffer = std::string(value); - return true; + try + { + buffer = m_propertyTree.get(section + "." + key); } - - return false; + catch (std::exception & e) + { + GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + } + return true; } bool CProfile::SetLocalProfileInt(std::string section, std::string key, int value) { - return (m_ini->SetLongValue(section.c_str(), key.c_str(), value) == SI_OK); + try + { + m_propertyTree.put(section + "." + key, value); + } + catch (std::exception & e) + { + GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + } + // return (m_ini->SetLongValue(section.c_str(), key.c_str(), value) == SI_OK); + return true; } bool CProfile::GetLocalProfileInt(std::string section, std::string key, int &value) { - value = m_ini->GetLongValue(section.c_str(), key.c_str(), 0L); + try + { + value = m_propertyTree.get(section + "." + key); + } + catch (std::exception & e) + { + GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + } + // value = m_ini->GetLongValue(section.c_str(), key.c_str(), 0L); return true; } bool CProfile::SetLocalProfileFloat(std::string section, std::string key, float value) { - return (m_ini->SetDoubleValue(section.c_str(), key.c_str(), value) == SI_OK); + try + { + m_propertyTree.put(section + "." + key, value); + } + catch (std::exception & e) + { + GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + } + // return (m_ini->SetDoubleValue(section.c_str(), key.c_str(), value) == SI_OK); + return true; } bool CProfile::GetLocalProfileFloat(std::string section, std::string key, float &value) { - value = m_ini->GetDoubleValue(section.c_str(), key.c_str(), 0.0d); + try + { + value = m_propertyTree.get(section + "." + key); + } + catch (std::exception & e) + { + GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + } + // value = m_ini->GetDoubleValue(section.c_str(), key.c_str(), 0.0d); return true; } @@ -96,13 +152,27 @@ std::vector< std::string > CProfile::GetLocalProfileSection(std::string section, { std::vector< std::string > ret_list; - CSimpleIniA::TNamesDepend values; - m_ini->GetAllValues(section.c_str(), key.c_str(), values); - values.sort(CSimpleIniA::Entry::LoadOrder()); - - for (auto item : values) { - ret_list.push_back(item.pItem); + try + { + for(bp::ptree::value_type const & v : m_propertyTree.get_child(section)) + { + if (v.first == key) + { + ret_list.push_back(v.second.get_value()); + } + } } + catch (std::exception & e) + { + GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + } + // CSimpleIniA::TNamesDepend values; + // m_ini->GetAllValues(section.c_str(), key.c_str(), values); + // values.sort(CSimpleIniA::Entry::LoadOrder()); + + // for (auto item : values) { + // ret_list.push_back(item.pItem); + // } return ret_list; } diff --git a/src/common/profile.h b/src/common/profile.h index 7a23d94..de30a63 100644 --- a/src/common/profile.h +++ b/src/common/profile.h @@ -21,7 +21,7 @@ #pragma once -#include "lib/simpleini/SimpleIni.h" +#include #include "common/singleton.h" @@ -102,7 +102,9 @@ class CProfile : public CSingleton std::vector< std::string > GetLocalProfileSection(std::string section, std::string key); private: - CSimpleIniA *m_ini; + // bpt::ptree m_pt; + boost::property_tree::ptree m_propertyTree; + // CSimpleIniA *m_ini; }; //! Global function to get profile instance diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp index d6f2d2d..3bc886b 100644 --- a/src/object/robotmain.cpp +++ b/src/object/robotmain.cpp @@ -109,7 +109,7 @@ float g_unit; // conversion factor static CBotClass* m_pClassFILE; static CBotProgram* m_pFuncFile; static int m_CompteurFileOpen = 0; -static char* m_filesDir; +static std::string m_filesDir; @@ -135,7 +135,7 @@ void PrepareFilename(CBotString &filename) filename = filename.Mid(pos+1); // also removes the drive letter C: } - filename = CBotString(m_filesDir) + CBotString("/") + filename; + filename = CBotString(m_filesDir.c_str()) + CBotString("/") + filename; } @@ -1097,8 +1097,7 @@ void CRobotMain::ChangePhase(Phase phase) m_app->SetLowCPU(false); // high CPU for simulation - char* read = m_dialog->GetSceneRead(); - bool loading = (read[0] != 0); + bool loading = (m_dialog->GetSceneRead()[0] != 0); m_map->CreateMap(); CreateScene(m_dialog->GetSceneSoluce(), false, false); // interactive scene @@ -3457,9 +3456,12 @@ void CRobotMain::Convert() char* base = m_dialog->GetSceneName(); int rank = m_dialog->GetSceneRank(); + //TODO change line to string char line[500]; + std::string tempLine; - m_dialog->BuildSceneName(line, base, rank); + m_dialog->BuildSceneName(tempLine, base, rank); + strcpy(line, tempLine.c_str()); FILE* file = fopen(line, "r"); if (file == NULL) return; @@ -3676,10 +3678,10 @@ void CRobotMain::ScenePerso() //! Creates the whole scene void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) { - char* base = m_dialog->GetSceneName(); - int rank = m_dialog->GetSceneRank(); - char* read = m_dialog->GetSceneRead(); - char* stack = m_dialog->GetStackRead(); + char* base = m_dialog->GetSceneName(); + int rank = m_dialog->GetSceneRank(); + const char* read = m_dialog->GetSceneRead().c_str(); + const char* stack = m_dialog->GetStackRead().c_str(); m_dialog->SetUserDir(base, rank); /* @@ -3756,8 +3758,9 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) memset(name, 0, 200); memset(dir, 0, 100); memset(op, 0, 100); - - m_dialog->BuildSceneName(line, base, rank); + std::string tempLine; + m_dialog->BuildSceneName(tempLine, base, rank); + strcpy(line, tempLine.c_str()); FILE* file = fopen(line, "r"); if (file == NULL) return; @@ -5504,7 +5507,7 @@ void CRobotMain::LoadOneScript(CObject *obj, int &nbError) } //! Load all programs of the robot -void CRobotMain::LoadFileScript(CObject *obj, char* filename, int objRank, +void CRobotMain::LoadFileScript(CObject *obj, const char* filename, int objRank, int &nbError) { if (objRank == -1) return; @@ -5572,7 +5575,7 @@ void CRobotMain::SaveOneScript(CObject *obj) //! Saves all programs of the robot. //! If a program does not exist, the corresponding file is destroyed. -void CRobotMain::SaveFileScript(CObject *obj, char* filename, int objRank) +void CRobotMain::SaveFileScript(CObject *obj, const char* filename, int objRank) { if (objRank == -1) return; @@ -5779,7 +5782,7 @@ void CRobotMain::IOWriteObject(FILE *file, CObject* obj, const char *cmd) } //! Saves the current game -bool CRobotMain::IOWriteScene(char *filename, char *filecbot, char *info) +bool CRobotMain::IOWriteScene(const char *filename, const char *filecbot, char *info) { FILE* file = fopen(filename, "w"); if (file == NULL) return false; @@ -5877,7 +5880,7 @@ bool CRobotMain::IOWriteScene(char *filename, char *filecbot, char *info) } //! Resumes the game -CObject* CRobotMain::IOReadObject(char *line, char* filename, int objRank) +CObject* CRobotMain::IOReadObject(char *line, const char* filename, int objRank) { Math::Vector pos = OpDir(line, "pos")*g_unit; Math::Vector dir = OpDir(line, "angle")*(Math::PI/180.0f); @@ -5957,7 +5960,7 @@ CObject* CRobotMain::IOReadObject(char *line, char* filename, int objRank) } //! Resumes some part of the game -CObject* CRobotMain::IOReadScene(char *filename, char *filecbot) +CObject* CRobotMain::IOReadScene(const char *filename, const char *filecbot) { m_base = false; @@ -6510,19 +6513,19 @@ bool CRobotMain::GetCheatRadar() return m_cheatRadar; } -char* CRobotMain::GetSavegameDir() +const char* CRobotMain::GetSavegameDir() { - return m_dialog->GetSavegameDir(); + return m_dialog->GetSavegameDir().c_str(); } -char* CRobotMain::GetPublicDir() +const char* CRobotMain::GetPublicDir() { - return m_dialog->GetPublicDir(); + return m_dialog->GetPublicDir().c_str(); } -char* CRobotMain::GetFilesDir() +const char* CRobotMain::GetFilesDir() { - return m_dialog->GetFilesDir(); + return m_dialog->GetFilesDir().c_str(); } diff --git a/src/object/robotmain.h b/src/object/robotmain.h index 0a5a5a2..8724b90 100644 --- a/src/object/robotmain.h +++ b/src/object/robotmain.h @@ -295,9 +295,9 @@ public: bool GetSceneSoluce(); bool GetShowAll(); bool GetCheatRadar(); - char* GetSavegameDir(); - char* GetPublicDir(); - char* GetFilesDir(); + const char* GetSavegameDir(); + const char* GetPublicDir(); + const char* GetFilesDir(); void SetGamerName(const char *name); char* GetGamerName(); @@ -324,10 +324,10 @@ public: void CompileScript(bool soluce); void LoadOneScript(CObject *pObj, int &nerror); - void LoadFileScript(CObject *pObj, char* filename, int objRank, int &nerror); + void LoadFileScript(CObject *pObj, const char* filename, int objRank, int &nerror); void SaveAllScript(); void SaveOneScript(CObject *pObj); - void SaveFileScript(CObject *pObj, char* filename, int objRank); + void SaveFileScript(CObject *pObj, const char* filename, int objRank); bool SaveFileStack(CObject *pObj, FILE *file, int objRank); bool ReadFileStack(CObject *pObj, FILE *file, int objRank); @@ -339,10 +339,10 @@ public: void ReadFreeParam(); bool IsBusy(); - bool IOWriteScene(char *filename, char *filecbot, char *info); - CObject* IOReadScene(char *filename, char *filecbot); + bool IOWriteScene(const char *filename, const char *filecbot, char *info); + CObject* IOReadScene(const char *filename, const char *filecbot); void IOWriteObject(FILE *file, CObject* pObj, const char *cmd); - CObject* IOReadObject(char *line, char* filename, int objRank); + CObject* IOReadObject(char *line, const char* filename, int objRank); int CreateSpot(Math::Vector pos, Gfx::Color color); diff --git a/src/plugins/pluginloader.h b/src/plugins/pluginloader.h index 40b19da..3dfa20b 100644 --- a/src/plugins/pluginloader.h +++ b/src/plugins/pluginloader.h @@ -26,7 +26,7 @@ #include #include -#include +#include "common/logger.h" #include "plugininterface.h" diff --git a/src/plugins/pluginmanager.h b/src/plugins/pluginmanager.h index e425c62..7a69820 100644 --- a/src/plugins/pluginmanager.h +++ b/src/plugins/pluginmanager.h @@ -27,10 +27,10 @@ #include #include -#include -#include +#include "common/logger.h" +#include "common/profile.h" -#include +#include "common/singleton.h" #include "pluginloader.h" diff --git a/src/script/script.cpp b/src/script/script.cpp index b29c625..5dbab56 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -2415,7 +2415,7 @@ bool CScript::rAbsTime(CBotVar* var, CBotVar* result, int& exception, void* user // Prepares a file name. -void PrepareFilename(CBotString &filename, char *dir) +void PrepareFilename(CBotString &filename, const char *dir) { int pos; @@ -2447,7 +2447,7 @@ bool CScript::rDeleteFile(CBotVar* var, CBotVar* result, int& exception, void* u CScript* script = (static_cast(user))->GetRunScript(); CBotString cbs; const char* filename; - char* dir; + const char* dir; cbs = var->GetValString(); dir = script->m_main->GetFilesDir(); diff --git a/src/sound/plugins/oalsound/CMakeLists.txt b/src/sound/plugins/oalsound/CMakeLists.txt index e36f3ac..12ab5e3 100644 --- a/src/sound/plugins/oalsound/CMakeLists.txt +++ b/src/sound/plugins/oalsound/CMakeLists.txt @@ -4,6 +4,7 @@ set(SOURCES alsound.cpp buffer.cpp channel.cpp + logger.cpp ) SET (CMAKE_CXX_FLAGS "-Wall -g -std=c++0x -fPIC") @@ -17,7 +18,6 @@ set(OPENAL_LIBRARIES alut ) - include_directories(../../..) include_directories(.) add_library(openalsound SHARED ${SOURCES}) diff --git a/src/sound/plugins/oalsound/alsound.h b/src/sound/plugins/oalsound/alsound.h index 01ccc71..a1128e0 100644 --- a/src/sound/plugins/oalsound/alsound.h +++ b/src/sound/plugins/oalsound/alsound.h @@ -24,9 +24,9 @@ #include -#include -#include -#include +#include "common/iman.h" +#include "common/logger.h" +#include "sound/sound.h" #include "buffer.h" #include "channel.h" diff --git a/src/sound/plugins/oalsound/buffer.h b/src/sound/plugins/oalsound/buffer.h index 6eefe72..8c4a2d3 100644 --- a/src/sound/plugins/oalsound/buffer.h +++ b/src/sound/plugins/oalsound/buffer.h @@ -22,8 +22,8 @@ #include -#include -#include +#include "sound/sound.h" +#include "common/logger.h" #include "check.h" diff --git a/src/sound/plugins/oalsound/channel.h b/src/sound/plugins/oalsound/channel.h index 3099931..165ff50 100644 --- a/src/sound/plugins/oalsound/channel.h +++ b/src/sound/plugins/oalsound/channel.h @@ -25,7 +25,7 @@ #include #include -#include +#include "sound/sound.h" #include "buffer.h" #include "check.h" diff --git a/src/sound/plugins/oalsound/check.h b/src/sound/plugins/oalsound/check.h index cb6b4a1..cf3e468 100644 --- a/src/sound/plugins/oalsound/check.h +++ b/src/sound/plugins/oalsound/check.h @@ -21,7 +21,7 @@ #include #include -#include +#include "common/logger.h" static ALenum CODE = AL_NO_ERROR; diff --git a/src/sound/sound.h b/src/sound/sound.h index 11138c3..1f3fea9 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -24,12 +24,12 @@ #pragma once -#include +#include "math/vector.h" -#include -#include +#include "common/iman.h" +#include "common/logger.h" -#include +#include "plugins/plugininterface.h" #include #include diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp index 6395acf..3be934a 100644 --- a/src/ui/maindialog.cpp +++ b/src/ui/maindialog.cpp @@ -18,6 +18,7 @@ #include "ui/maindialog.h" +#include "app/app.h" #include "common/global.h" #include "common/event.h" #include "common/logger.h" @@ -46,8 +47,11 @@ #include #include -// #include +#include +#include +#include +//TODO Get rid of all sprintf's namespace Ui { @@ -58,7 +62,7 @@ const int KEY_TOTAL = 21; // total number of keys redefinable const float WELCOME_LENGTH = 2.0f; - +const int MAX_FNAME = 255; // TODO: remove after rewrite to std::string static int perso_color[3*10*3] = { @@ -97,7 +101,7 @@ static int perso_color[3*10*3] = 0, 0, 0, // }; - +namespace fs = boost::filesystem; // Constructor of robot application. @@ -169,11 +173,12 @@ CMainDialog::CMainDialog(CInstanceManager* iMan) m_partiTime[i] = 0.0f; } - strcpy(m_sceneDir, "levels"); - strcpy(m_savegameDir, "savegame"); - strcpy(m_publicDir, "program"); - strcpy(m_userDir, "user"); - strcpy(m_filesDir, "files"); + + m_sceneDir = "levels"; + m_savegameDir = "savegame"; + m_publicDir = "program"; + m_userDir = "user"; + m_filesDir = "files"; m_bDialog = false; } @@ -3573,7 +3578,7 @@ void CMainDialog::SetUserDir(char *base, int rank) if ( strcmp(base, "user") == 0 && rank >= 100 ) { - sprintf(dir, "%s/%s", m_userDir, m_userList[rank/100-1]); + sprintf(dir, "%s/%s", m_userDir.c_str(), m_userList[rank/100-1]); UserDir(true, dir); } else @@ -3584,17 +3589,22 @@ void CMainDialog::SetUserDir(char *base, int rank) // Builds the file name of a mission. -void CMainDialog::BuildSceneName(char *filename, char *base, int rank) +void CMainDialog::BuildSceneName(std::string &filename, char *base, int rank) { - std::string dataDir = m_app->GetDataDirPath(); - + std::ostringstream rankStream; if ( strcmp(base, "user") == 0 ) { - sprintf(filename, "%s/%s/%s/scene%.2d.txt", dataDir.c_str(), m_userDir, m_userList[rank/100-1], rank%100); + //TODO: Change this to point user dir acocrding to operating system + rankStream << std::setfill('0') << std::setw(2) << rank%100; + filename = m_userDir + "/" + m_userList[rank/100-1] + "/" + rankStream.str() + ".txt"; + // sprintf(filename, "%s\\%s\\scene%.2d.txt", m_userDir.c_str(), m_userList[rank/100-1], rank%100); } else { - sprintf(filename, "%s/%s/%s%.3d.txt", dataDir.c_str(), m_sceneDir, base, rank); + rankStream << std::setfill('0') << std::setw(3) << rank; + filename = base + rankStream.str() + ".txt"; + filename = CApplication::GetInstance().GetDataFilePath(DIR_LEVEL, filename); + // sprintf(filename, "%s\\%s%.3d.txt", m_sceneDir, base, rank); } } @@ -3607,7 +3617,7 @@ void CMainDialog::BuildResumeName(char *filename, char *base, int rank) // Returns the name of the file or save the files. -char* CMainDialog::GetFilesDir() +std::string & CMainDialog::GetFilesDir() { return m_filesDir; } @@ -3635,9 +3645,10 @@ void CMainDialog::ReadNameList() nbFilenames = 0; - sprintf(dir, "./%s", m_savegameDir); + //TODO list files + // sprintf(dir, ".\\%s", m_savegameDir); - // if (! boost::filesystem::exists(dir)) + // if (! fs::exists(dir)) // { // GetLogger()->Error("Savegame dir does not exist %s\n",dir); // } @@ -3645,7 +3656,6 @@ void CMainDialog::ReadNameList() // { // GetLogger()->Info("Opening file"); // } - //TODO list files // hFile = _findfirst(dir, &fBuffer); // if ( hFile != -1 ) @@ -3852,7 +3862,7 @@ void CMainDialog::NameSelect() GetGamerFace(m_main->GetGamerName()); - // TODO: SetLocalProfileString("Gamer", "LastName", m_main->GetGamerName()); + GetProfile()->SetLocalProfileString("Gamer", "LastName", m_main->GetGamerName()); } // Creates a new player. @@ -3866,6 +3876,7 @@ void CMainDialog::NameCreate() char c; int len, i, j; + GetLogger()->Debug("Creating new player\n"); pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == 0 ) return; pe = static_cast(pw->SearchControl(EVENT_INTERFACE_NEDIT)); @@ -3904,7 +3915,7 @@ void CMainDialog::NameCreate() // TODO: _mkdir(m_savegameDir); // if does not exist yet! - sprintf(dir, "%s/%s", m_savegameDir, name); + sprintf(dir, "%s/%s", m_savegameDir.c_str(), name); // TODO: if ( _mkdir(dir) != 0 ) { m_sound->Play(SOUND_TZOING); @@ -3983,7 +3994,7 @@ void CMainDialog::NameDelete() gamer = pl->GetName(sel); // Deletes all the contents of the file. - sprintf(dir, "%s/%s", m_savegameDir, gamer); + sprintf(dir, "%s/%s", m_savegameDir.c_str(), gamer); if ( !RemoveDir(dir) ) { m_sound->Play(SOUND_TZOING); @@ -4295,10 +4306,13 @@ void CMainDialog::DefPerso() bool CMainDialog::IsIOReadScene() { FILE* file; - char filename[100]; + // char filename[100]; + std::string filename; - sprintf(filename, "%s/%s/save%c%.3d/data.sav", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], 0); - file = fopen(filename, "r"); + //TODO: Change this to point user dir acocrding to operating system + filename = m_savegameDir + "/" + m_main->GetGamerName() + "/" + "save" + m_sceneName[0] + "000/data.sav"; + // sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], 0); + file = fopen(filename.c_str(), "r"); if ( file == NULL ) return false; fclose(file); return true; @@ -4311,7 +4325,7 @@ void CMainDialog::IOReadName() FILE* file; CWindow* pw; CEdit* pe; - char filename[MAX_FNAME]; + std::string filename; char op[100]; char line[500]; char resume[100]; @@ -4326,7 +4340,7 @@ void CMainDialog::IOReadName() sprintf(resume, "%s %d", m_sceneName, m_chap[m_index]+1); BuildSceneName(filename, m_sceneName, (m_chap[m_index]+1)*100); - file = fopen(filename, "r"); + file = fopen(filename.c_str(), "r"); if ( file != NULL ) { while ( fgets(line, 500, file) != NULL ) @@ -4367,7 +4381,6 @@ void CMainDialog::IOReadList() FILE* file = NULL; CWindow* pw; CList* pl; - char filename[100]; char line[500]; char name[100]; int i, j; @@ -4381,8 +4394,13 @@ void CMainDialog::IOReadList() for ( j=0 ; j<999 ; j++ ) { - sprintf(filename, "%s/%s/save%c%.3d/data.sav", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], j); - file = fopen(filename, "r"); + std::string filename; + std::ostringstream rankStream; + rankStream << std::setfill('0') << std::setw(3) << j; + filename = m_savegameDir + "/" + m_main->GetGamerName() + "/save" + m_sceneName[0] + rankStream.str()+ "/data.sav"; + + // sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], j); + file = fopen(filename.c_str(), "r"); if ( file == NULL ) break; while ( fgets(line, 500, file) != NULL ) @@ -4429,7 +4447,6 @@ void CMainDialog::IOUpdateList() CList* pl; CButton* pb; CImage* pi; - char filename[100]; int sel, max; pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); @@ -4442,14 +4459,18 @@ void CMainDialog::IOUpdateList() sel = pl->GetSelect(); max = pl->GetTotal(); - sprintf(filename, "%s/%s/save%c%.3d/screen.png", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], sel); + std::string filename; + std::ostringstream rankStream; + rankStream << std::setfill('0') << std::setw(3) << sel; + filename = m_savegameDir + "/" + m_main->GetGamerName() + "/save" + m_sceneName[0] + rankStream.str()+ "/screen.png"; + // sprintf(filename, "%s\\%s\\save%c%.3d\\screen.png", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], sel); if ( m_phase == PHASE_WRITE || m_phase == PHASE_WRITEs ) { if ( sel < max-1 ) { - pi->SetFilenameImage(filename); + pi->SetFilenameImage(filename.c_str()); } else { @@ -4464,7 +4485,7 @@ void CMainDialog::IOUpdateList() } else { - pi->SetFilenameImage(filename); + pi->SetFilenameImage(filename.c_str()); } } @@ -4534,8 +4555,6 @@ bool CMainDialog::IOWriteScene() CWindow* pw; CList* pl; CEdit* pe; - char filename[100]; - char filecbot[100]; char info[100]; int sel; @@ -4549,19 +4568,28 @@ bool CMainDialog::IOWriteScene() sel = pl->GetSelect(); if ( sel == -1 ) return false; - // TODO: _mkdir("Savegame"); // if doesn't exist yet! - sprintf(filename, "%s/%s", m_savegameDir, m_main->GetGamerName()); - // TODO: _mkdir(filename); - sprintf(filename, "%s/%s/save%c%.3d", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], sel); - // TODO: _mkdir(filename); + std::string directoryName; + std::string fileName; + std::string fileCBot; + std::ostringstream selectStream; + + //TODO: Change this to point user dir according to operating system + // sprintf(filename, "%s\\%s\\save%c%.3d", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], sel); + GetLogger()->Info("Creating save directory\n"); + selectStream << std::setfill('0') << std::setw(3) << sel; + directoryName = m_savegameDir + "/" + m_main->GetGamerName() + "/" + "save" + m_sceneName[0] + selectStream.str(); + if (!fs::exists(directoryName)) + { + fs::create_directories(directoryName); + } - sprintf(filename, "%s/%s/save%c%.3d/data.sav", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], sel); - sprintf(filecbot, "%s/%s/save%c%.3d/cbot.run", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], sel); + fileName = directoryName + "/data.sav"; + fileCBot = directoryName + "/cbot.run"; pe->GetText(info, 100); - m_main->IOWriteScene(filename, filecbot, info); + m_main->IOWriteScene(fileName.c_str(), fileCBot.c_str(), info); m_shotDelay = 3; - sprintf(m_shotName, "%s/%s/save%c%.3d/screen.png", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], sel); + m_shotName = directoryName + "/screen.png"; return true; } @@ -4573,8 +4601,6 @@ bool CMainDialog::IOReadScene() FILE* file; CWindow* pw; CList* pl; - char filename[100]; - char filecbot[100]; char line[500]; char dir[100]; int sel, i; @@ -4587,10 +4613,19 @@ bool CMainDialog::IOReadScene() sel = pl->GetSelect(); if ( sel == -1 ) return false; - sprintf(filename, "%s/%s/save%c%.3d/data.sav", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], sel); - sprintf(filecbot, "%s/%s/save%c%.3d/cbot.run", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], sel); + //TODO: Change this to point user dir according to operating system + // sprintf(filename, "%s\\%s\\save%c%.3d", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], sel); + std::string fileName; + std::string fileCbot; + std::string directoryName; + std::ostringstream selectStream; + selectStream << std::setfill('0') << std::setw(3) << sel; + directoryName = m_savegameDir + "/" + m_main->GetGamerName() + "/" + "save" + m_sceneName[0] + selectStream.str(); - file = fopen(filename, "r"); + fileName = directoryName + "/data.sav"; + fileCbot = directoryName + "/cbot.run"; + + file = fopen(fileName.c_str(), "r"); if ( file == NULL ) return false; while ( fgets(line, 500, file) != NULL ) @@ -4635,8 +4670,8 @@ bool CMainDialog::IOReadScene() m_chap[m_index] = (m_sceneRank/100)-1; m_sel[m_index] = (m_sceneRank%100)-1; - strcpy(m_sceneRead, filename); - strcpy(m_stackRead, filecbot); + m_sceneRead = fileName; + m_stackRead = fileCbot; return true; } @@ -4685,7 +4720,7 @@ void CMainDialog::UpdateSceneChap(int &chap) CList* pl; long hFile; //struct _finddata_t fileBuffer; - char filename[MAX_FNAME]; + std::string fileName; char op[100]; char line[500]; char name[100]; @@ -4740,8 +4775,8 @@ void CMainDialog::UpdateSceneChap(int &chap) for ( j=0 ; j= 4 ) break; if ( m_phase == PHASE_TRAINER && j >= 1 ) break; #endif */ - BuildSceneName(filename, m_sceneName, (j+1)*100); - file = fopen(filename, "r"); + BuildSceneName(fileName, m_sceneName, (j+1)*100); + file = fopen(fileName.c_str(), "r"); if ( file == NULL ) break; BuildResumeName(name, m_sceneName, j+1); // default name @@ -4859,7 +4894,7 @@ void CMainDialog::UpdateSceneList(int chap, int &sel) FILE* file = NULL; CWindow* pw; CList* pl; - char filename[MAX_FNAME]; + std::string fileName; char op[100]; char line[500]; char name[100]; @@ -4894,8 +4929,8 @@ void CMainDialog::UpdateSceneList(int chap, int &sel) if ( m_phase == PHASE_MISSION && j >= 3 ) break; if ( m_phase == PHASE_TRAINER && j >= 5 ) break; #endif */ - BuildSceneName(filename, m_sceneName, (chap+1)*100+(j+1)); - file = fopen(filename, "r"); + BuildSceneName(fileName, m_sceneName, (chap+1)*100+(j+1)); + file = fopen(fileName.c_str(), "r"); if ( file == NULL ) break; BuildResumeName(name, m_sceneName, j+1); // default name @@ -4942,8 +4977,8 @@ void CMainDialog::UpdateSceneList(int chap, int &sel) #endif*/ } - BuildSceneName(filename, m_sceneName, (chap+1)*100+(j+1)); - file = fopen(filename, "r"); + BuildSceneName(fileName, m_sceneName, (chap+1)*100+(j+1)); + file = fopen(fileName.c_str(), "r"); if ( file == NULL ) { m_maxList = j; @@ -5008,7 +5043,7 @@ void CMainDialog::UpdateSceneResume(int rank) CWindow* pw; CEdit* pe; CCheck* pc; - char filename[MAX_FNAME]; + std::string fileName; char op[100]; char line[500]; char name[500]; @@ -5039,8 +5074,8 @@ void CMainDialog::UpdateSceneResume(int rank) } } - BuildSceneName(filename, m_sceneName, rank); - file = fopen(filename, "r"); + BuildSceneName(fileName, m_sceneName, rank); + file = fopen(fileName.c_str(), "r"); if ( file == NULL ) return; name[0] = 0; @@ -6522,12 +6557,12 @@ bool CMainDialog::IsDialog() void CMainDialog::SetSceneRead(const char* name) { - strcpy(m_sceneRead, name); + m_sceneRead = name; } // Returns the name of the scene to read. -char* CMainDialog::GetSceneRead() +std::string & CMainDialog::GetSceneRead() { return m_sceneRead; } @@ -6536,12 +6571,12 @@ char* CMainDialog::GetSceneRead() void CMainDialog::SetStackRead(const char* name) { - strcpy(m_stackRead, name); + m_stackRead = name; } // Returns the name of the scene to read. -char* CMainDialog::GetStackRead() +std::string & CMainDialog::GetStackRead() { return m_stackRead; } @@ -6595,14 +6630,14 @@ bool CMainDialog::GetSceneSoluce() // Returns the name of the folder to save. -char* CMainDialog::GetSavegameDir() +std::string & CMainDialog::GetSavegameDir() { return m_savegameDir; } // Returns the name of public folder. -char* CMainDialog::GetPublicDir() +std::string & CMainDialog::GetPublicDir() { return m_publicDir; } @@ -6653,7 +6688,7 @@ void CMainDialog::WriteGamerPerso(char *gamer) char filename[100]; char line[100]; - sprintf(filename, "%s/%s/face.gam", m_savegameDir, gamer); + sprintf(filename, "%s/%s/face.gam", m_savegameDir.c_str(), gamer); file = fopen(filename, "w"); if ( file == NULL ) return; @@ -6682,7 +6717,7 @@ void CMainDialog::ReadGamerPerso(char *gamer) m_perso.face = 0; DefPerso(); - sprintf(filename, "%s/%s/face.gam", m_savegameDir, gamer); + sprintf(filename, "%s/%s/face.gam", m_savegameDir.c_str(), gamer); file = fopen(filename, "r"); if ( file == NULL ) return; @@ -6787,7 +6822,7 @@ bool CMainDialog::ReadGamerInfo() m_sceneInfo[i].bPassed = false; } - sprintf(line, "%s/%s/%s.gam", m_savegameDir, m_main->GetGamerName(), m_sceneName); + sprintf(line, "%s/%s/%s.gam", m_savegameDir.c_str(), m_main->GetGamerName(), m_sceneName); file = fopen(line, "r"); if ( file == NULL ) return false; @@ -6823,7 +6858,7 @@ bool CMainDialog::WriteGamerInfo() char line[100]; int i; - sprintf(line, "%s/%s/%s.gam", m_savegameDir, m_main->GetGamerName(), m_sceneName); + sprintf(line, "%s/%s/%s.gam", m_savegameDir.c_str(), m_main->GetGamerName(), m_sceneName); file = fopen(line, "w"); if ( file == NULL ) return false; diff --git a/src/ui/maindialog.h b/src/ui/maindialog.h index 8b0ef81..c67ca37 100644 --- a/src/ui/maindialog.h +++ b/src/ui/maindialog.h @@ -43,7 +43,6 @@ class CControl; const int USERLISTMAX = 100; const int MAXSCENE = 1000; -const int MAX_FNAME = 255; // TODO: remove after rewrite to std::string struct SceneInfo { @@ -71,18 +70,18 @@ public: bool EventProcess(const Event &event); void ChangePhase(Phase phase); - void SetSceneRead(const char* name); - void SetStackRead(const char* name); - void SetSceneName(const char* name); - void SetSceneRank(int rank); - char* GetSceneRead(); - char* GetStackRead(); - char* GetSceneName(); - int GetSceneRank(); - char* GetSceneDir(); - bool GetSceneSoluce(); - char* GetSavegameDir(); - char* GetPublicDir(); + void SetSceneRead(const char* name); + void SetStackRead(const char* name); + void SetSceneName(const char* name); + void SetSceneRank(int rank); + std::string & GetSceneRead(); + std::string & GetStackRead(); + char* GetSceneName(); + int GetSceneRank(); + char* GetSceneDir(); + bool GetSceneSoluce(); + std::string & GetSavegameDir(); + std::string & GetPublicDir(); bool GetTooltip(); bool GetGlint(); @@ -91,10 +90,10 @@ public: bool GetNiceReset(); bool GetHimselfDamage(); - void SetUserDir(char *base, int rank); - void BuildSceneName(char *filename, char *base, int rank); - void BuildResumeName(char *filename, char *base, int rank); - char* GetFilesDir(); + void SetUserDir(char *base, int rank); + void BuildSceneName(std::string &filename, char *base, int rank); + void BuildResumeName(char *filename, char *base, int rank); + std::string & GetFilesDir(); void StartAbort(); void StartDeleteObject(); @@ -193,19 +192,19 @@ protected: int m_persoTab; // perso: tab selected float m_persoAngle; // perso: angle of presentation - char m_sceneDir[MAX_FNAME]; // scene folder - char m_savegameDir[MAX_FNAME]; // savegame folder - char m_publicDir[MAX_FNAME]; // program folder - char m_userDir[MAX_FNAME]; // user folder - char m_filesDir[MAX_FNAME]; // case files + std::string m_sceneDir; // scene folder + std::string m_savegameDir; // savegame folder + std::string m_publicDir; // program folder + std::string m_userDir; // user folder + std::string m_filesDir; // case files int m_index; // 0..4 int m_chap[10]; // selected chapter (0..8) int m_sel[10]; // chosen mission (0..98) int m_maxList; int m_accessChap; - char m_sceneRead[100]; // name of the scene to read - char m_stackRead[100]; // name of the scene to read + std::string m_sceneRead; // name of the scene to read + std::string m_stackRead; // name of the scene to read char m_sceneName[20]; // name of the scene to play int m_sceneRank; // rank of the scene to play bool m_bSceneSoluce; // shows the solution @@ -219,7 +218,7 @@ protected: char m_userList[USERLISTMAX][100]; int m_shotDelay; // number of frames before copy - char m_shotName[100]; // generate a file name + std::string m_shotName; // generate a file name int m_setupSelDevice; int m_setupSelMode; -- cgit v1.2.3-1-g7c22 From cc9a5070544bbac127df45ca73810a03ed2fa9d2 Mon Sep 17 00:00:00 2001 From: Zaba999 Date: Thu, 27 Sep 2012 00:30:47 +0200 Subject: Profile rewritten to boost. Read/write to ini should work. Load/Save should work. --- CMakeLists.txt | 2 +- lib/simpleini/ConvertUTF.c | 539 ----- lib/simpleini/ConvertUTF.h | 149 -- lib/simpleini/Makefile | 28 - lib/simpleini/SimpleIni.h | 3370 ----------------------------- lib/simpleini/SimpleIni.sln | 29 - lib/simpleini/SimpleIni.vcproj | 291 --- lib/simpleini/ini.syn | 36 - lib/simpleini/package.cmd | 26 - lib/simpleini/simpleini.doxy | 1321 ----------- lib/simpleini/simpleini.dsp | 178 -- lib/simpleini/simpleini.dsw | 29 - lib/simpleini/snippets.cpp | 123 -- lib/simpleini/test.cmd | 24 - lib/simpleini/test1-expected.ini | 85 - lib/simpleini/test1-input.ini | 76 - lib/simpleini/test1.cpp | 166 -- lib/simpleini/testsi-EUCJP.ini | 52 - lib/simpleini/testsi-SJIS.ini | 51 - lib/simpleini/testsi-UTF8.ini | 50 - lib/simpleini/testsi.cpp | 309 --- src/common/profile.cpp | 45 +- src/common/profile.h | 3 +- src/sound/plugins/oalsound/CMakeLists.txt | 1 - 24 files changed, 27 insertions(+), 6956 deletions(-) delete mode 100644 lib/simpleini/ConvertUTF.c delete mode 100644 lib/simpleini/ConvertUTF.h delete mode 100644 lib/simpleini/Makefile delete mode 100644 lib/simpleini/SimpleIni.h delete mode 100644 lib/simpleini/SimpleIni.sln delete mode 100644 lib/simpleini/SimpleIni.vcproj delete mode 100644 lib/simpleini/ini.syn delete mode 100644 lib/simpleini/package.cmd delete mode 100644 lib/simpleini/simpleini.doxy delete mode 100644 lib/simpleini/simpleini.dsp delete mode 100644 lib/simpleini/simpleini.dsw delete mode 100644 lib/simpleini/snippets.cpp delete mode 100644 lib/simpleini/test.cmd delete mode 100644 lib/simpleini/test1-expected.ini delete mode 100644 lib/simpleini/test1-input.ini delete mode 100644 lib/simpleini/test1.cpp delete mode 100644 lib/simpleini/testsi-EUCJP.ini delete mode 100644 lib/simpleini/testsi-SJIS.ini delete mode 100644 lib/simpleini/testsi-UTF8.ini delete mode 100644 lib/simpleini/testsi.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b5dfa67..eee86fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) set(Boost_ADDITIONALVERSION "1.51" "1.51.0") -find_package(Boost COMPONENTS system filesystem REQUIRED) +find_package(Boost COMPONENTS system filesystem regex REQUIRED) # GLEW requirement depends on platform diff --git a/lib/simpleini/ConvertUTF.c b/lib/simpleini/ConvertUTF.c deleted file mode 100644 index 4351b15..0000000 --- a/lib/simpleini/ConvertUTF.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -/* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Source code file. - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - Sept 2001: fixed const & error conditions per - mods suggested by S. Parent & A. Lillich. - June 2002: Tim Dodd added detection and handling of incomplete - source sequences, enhanced error detection, added casts - to eliminate compiler warnings. - July 2003: slight mods to back out aggressive FFFE detection. - Jan 2004: updated switches in from-UTF8 conversions. - Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. - - See the header file "ConvertUTF.h" for complete documentation. - ------------------------------------------------------------------------- */ - - -#include "ConvertUTF.h" -#ifdef CVTUTF_DEBUG -#include -#endif - -static const int halfShift = 10; /* used for shifting by 10 bits */ - -static const UTF32 halfBase = 0x0010000UL; -static const UTF32 halfMask = 0x3FFUL; - -#define UNI_SUR_HIGH_START (UTF32)0xD800 -#define UNI_SUR_HIGH_END (UTF32)0xDBFF -#define UNI_SUR_LOW_START (UTF32)0xDC00 -#define UNI_SUR_LOW_END (UTF32)0xDFFF -#define false 0 -#define true 1 - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF32toUTF16 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF32* source = *sourceStart; - UTF16* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - if (target >= targetEnd) { - result = targetExhausted; break; - } - ch = *source++; - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_LEGAL_UTF32) { - if (flags == strictConversion) { - result = sourceIllegal; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - --source; /* Back up source pointer! */ - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF16toUTF32 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF16* source = *sourceStart; - UTF32* target = *targetStart; - UTF32 ch, ch2; - while (source < sourceEnd) { - const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - if (target >= targetEnd) { - source = oldSource; /* Back up source pointer! */ - result = targetExhausted; break; - } - *target++ = ch; - } - *sourceStart = source; - *targetStart = target; -#ifdef CVTUTF_DEBUG -if (result == sourceIllegal) { - fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); - fflush(stderr); -} -#endif - return result; -} - -/* --------------------------------------------------------------------- */ - -/* - * Index into the table below with the first byte of a UTF-8 sequence to - * get the number of trailing bytes that are supposed to follow it. - * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is - * left as-is for anyone who may want to do such conversion, which was - * allowed in earlier algorithms. - */ -static const char trailingBytesForUTF8[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 -}; - -/* - * Magic values subtracted from a buffer value during UTF8 conversion. - * This table contains as many values as there might be trailing bytes - * in a UTF-8 sequence. - */ -static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; - -/* - * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed - * into the first byte, depending on how many bytes follow. There are - * as many entries in this table as there are UTF-8 sequence types. - * (I.e., one byte sequence, two byte... etc.). Remember that sequencs - * for *legal* UTF-8 will be 4 or fewer bytes total. - */ -static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - -/* --------------------------------------------------------------------- */ - -/* The interface converts a whole buffer to avoid function-call overhead. - * Constants have been gathered. Loops & conditionals have been removed as - * much as possible for efficiency, in favor of drop-through switches. - * (See "Note A" at the bottom of the file for equivalent code.) - * If your compiler supports it, the "isLegalUTF8" call can be turned - * into an inline function. - */ - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF16toUTF8 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF16* source = *sourceStart; - UTF8* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - UTF32 ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* Figure out how many bytes the result will require */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; - } else { bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - } - - target += bytesToWrite; - if (target > targetEnd) { - source = oldSource; /* Back up source pointer! */ - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -/* - * Utility routine to tell whether a sequence of bytes is legal UTF-8. - * This must be called with the length pre-determined by the first byte. - * If not calling this from ConvertUTF8to*, then the length can be set by: - * length = trailingBytesForUTF8[*source]+1; - * and the sequence is illegal right away if there aren't that many bytes - * available. - * If presented with a length > 4, this returns false. The Unicode - * definition of UTF-8 goes up to 4-byte sequences. - */ - -static Boolean isLegalUTF8(const UTF8 *source, int length) { - UTF8 a; - const UTF8 *srcptr = source+length; - switch (length) { - default: return false; - /* Everything else falls through when "true"... */ - case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 2: if ((a = (*--srcptr)) > 0xBF) return false; - - switch (*source) { - /* no fall-through in this inner switch */ - case 0xE0: if (a < 0xA0) return false; break; - case 0xED: if (a > 0x9F) return false; break; - case 0xF0: if (a < 0x90) return false; break; - case 0xF4: if (a > 0x8F) return false; break; - default: if (a < 0x80) return false; - } - - case 1: if (*source >= 0x80 && *source < 0xC2) return false; - } - if (*source > 0xF4) return false; - return true; -} - -/* --------------------------------------------------------------------- */ - -/* - * Exported function to return whether a UTF-8 sequence is legal or not. - * This is not used here; it's just exported. - */ -Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { - int length = trailingBytesForUTF8[*source]+1; - if (source+length > sourceEnd) { - return false; - } - return isLegalUTF8(source, length); -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF8toUTF16 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF8* source = *sourceStart; - UTF16* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up source pointer! */ - result = targetExhausted; break; - } - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_UTF16) { - if (flags == strictConversion) { - result = sourceIllegal; - source -= (extraBytesToRead+1); /* return to the start */ - break; /* Bail out; shouldn't continue */ - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up source pointer! */ - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF32toUTF8 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF32* source = *sourceStart; - UTF8* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - ch = *source++; - if (flags == strictConversion ) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* - * Figure out how many bytes the result will require. Turn any - * illegally large UTF32 things (> Plane 17) into replacement chars. - */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; - } else { bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - result = sourceIllegal; - } - - target += bytesToWrite; - if (target > targetEnd) { - --source; /* Back up source pointer! */ - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF8toUTF32 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF8* source = *sourceStart; - UTF32* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; - case 4: ch += *source++; ch <<= 6; - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up the source pointer! */ - result = targetExhausted; break; - } - if (ch <= UNI_MAX_LEGAL_UTF32) { - /* - * UTF-16 surrogate values are illegal in UTF-32, and anything - * over Plane 17 (> 0x10FFFF) is illegal. - */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = ch; - } - } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ - result = sourceIllegal; - *target++ = UNI_REPLACEMENT_CHAR; - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- - - Note A. - The fall-through switches in UTF-8 reading code save a - temp variable, some decrements & conditionals. The switches - are equivalent to the following loop: - { - int tmpBytesToRead = extraBytesToRead+1; - do { - ch += *source++; - --tmpBytesToRead; - if (tmpBytesToRead) ch <<= 6; - } while (tmpBytesToRead > 0); - } - In UTF-8 writing code, the switches on "bytesToWrite" are - similarly unrolled loops. - - --------------------------------------------------------------------- */ diff --git a/lib/simpleini/ConvertUTF.h b/lib/simpleini/ConvertUTF.h deleted file mode 100644 index f1230ee..0000000 --- a/lib/simpleini/ConvertUTF.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -/* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Header file. - - Several funtions are included here, forming a complete set of - conversions between the three formats. UTF-7 is not included - here, but is handled in a separate source file. - - Each of these routines takes pointers to input buffers and output - buffers. The input buffers are const. - - Each routine converts the text between *sourceStart and sourceEnd, - putting the result into the buffer between *targetStart and - targetEnd. Note: the end pointers are *after* the last item: e.g. - *(sourceEnd - 1) is the last item. - - The return result indicates whether the conversion was successful, - and if not, whether the problem was in the source or target buffers. - (Only the first encountered problem is indicated.) - - After the conversion, *sourceStart and *targetStart are both - updated to point to the end of last text successfully converted in - the respective buffers. - - Input parameters: - sourceStart - pointer to a pointer to the source buffer. - The contents of this are modified on return so that - it points at the next thing to be converted. - targetStart - similarly, pointer to pointer to the target buffer. - sourceEnd, targetEnd - respectively pointers to the ends of the - two buffers, for overflow checking only. - - These conversion functions take a ConversionFlags argument. When this - flag is set to strict, both irregular sequences and isolated surrogates - will cause an error. When the flag is set to lenient, both irregular - sequences and isolated surrogates are converted. - - Whether the flag is strict or lenient, all illegal sequences will cause - an error return. This includes sequences such as: , , - or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code - must check for illegal sequences. - - When the flag is set to lenient, characters over 0x10FFFF are converted - to the replacement character; otherwise (when the flag is set to strict) - they constitute an error. - - Output parameters: - The value "sourceIllegal" is returned from some routines if the input - sequence is malformed. When "sourceIllegal" is returned, the source - value will point to the illegal value that caused the problem. E.g., - in UTF-8 when a sequence is malformed, it points to the start of the - malformed sequence. - - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - Fixes & updates, Sept 2001. - ------------------------------------------------------------------------- */ - -/* --------------------------------------------------------------------- - The following 4 definitions are compiler-specific. - The C standard does not guarantee that wchar_t has at least - 16 bits, so wchar_t is no less portable than unsigned short! - All should be unsigned values to avoid sign extension during - bit mask & shift operations. ------------------------------------------------------------------------- */ - -typedef unsigned int UTF32; /* at least 32 bits */ -typedef unsigned short UTF16; /* at least 16 bits */ -typedef unsigned char UTF8; /* typically 8 bits */ -typedef unsigned char Boolean; /* 0 or 1 */ - -/* Some fundamental constants */ -#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD -#define UNI_MAX_BMP (UTF32)0x0000FFFF -#define UNI_MAX_UTF16 (UTF32)0x0010FFFF -#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF -#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF - -typedef enum { - conversionOK, /* conversion successful */ - sourceExhausted, /* partial character in source, but hit end */ - targetExhausted, /* insuff. room in target for conversion */ - sourceIllegal /* source sequence is illegal/malformed */ -} ConversionResult; - -typedef enum { - strictConversion = 0, - lenientConversion -} ConversionFlags; - -/* This is for C++ and does no harm in C */ -#ifdef __cplusplus -extern "C" { -#endif - -ConversionResult ConvertUTF8toUTF16 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF16toUTF8 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF8toUTF32 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF32toUTF8 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF16toUTF32 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF32toUTF16 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); - -Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); - -#ifdef __cplusplus -} -#endif - -/* --------------------------------------------------------------------- */ diff --git a/lib/simpleini/Makefile b/lib/simpleini/Makefile deleted file mode 100644 index a04b5e3..0000000 --- a/lib/simpleini/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -CC=g++ -CFLAGS=-Wall -CPPFLAGS=-Wall - -OBJS=testsi.o test1.o snippets.o ConvertUTF.o - -help: - @echo This makefile is just for the test program \(use \"make clean all test\"\) - @echo Just include the SimpleIni.h header file to use it. - -all: $(OBJS) - $(CC) -o testsi $(OBJS) - -clean: - rm -f core *.o testsi - -data: - sed 's/\r\n$$/\n/g' < test1-expected.ini > unix.out - mv unix.out test1-expected.ini - -test: testsi - ./testsi -u -m -l test1-input.ini > test1-blah.ini - diff test1-output.ini test1-expected.ini - -install: - @echo No install required. Just include the SimpleIni.h header file to use it. - -testsi.o test1.o snippets.o : SimpleIni.h diff --git a/lib/simpleini/SimpleIni.h b/lib/simpleini/SimpleIni.h deleted file mode 100644 index ab4749f..0000000 --- a/lib/simpleini/SimpleIni.h +++ /dev/null @@ -1,3370 +0,0 @@ -/** @mainpage - - -
Library SimpleIni -
File SimpleIni.h -
Author Brodie Thiesfield [code at jellycan dot com] -
Source http://code.jellycan.com/simpleini/ -
Version 4.15 -
- - Jump to the @link CSimpleIniTempl CSimpleIni @endlink interface documentation. - - @section intro INTRODUCTION - - This component allows an INI-style configuration file to be used on both - Windows and Linux/Unix. It is fast, simple and source code using this - component will compile unchanged on either OS. - - - @section features FEATURES - - - MIT Licence allows free use in all software (including GPL and commercial) - - multi-platform (Windows 95/98/ME/NT/2K/XP/2003, Windows CE, Linux, Unix) - - loading and saving of INI-style configuration files - - configuration files can have any newline format on all platforms - - liberal acceptance of file format - - key/values with no section - - removal of whitespace around sections, keys and values - - support for multi-line values (values with embedded newline characters) - - optional support for multiple keys with the same name - - optional case-insensitive sections and keys (for ASCII characters only) - - saves files with sections and keys in the same order as they were loaded - - preserves comments on the file, section and keys where possible. - - supports both char or wchar_t programming interfaces - - supports both MBCS (system locale) and UTF-8 file encodings - - system locale does not need to be UTF-8 on Linux/Unix to load UTF-8 file - - support for non-ASCII characters in section, keys, values and comments - - support for non-standard character types or file encodings - via user-written converter classes - - support for adding/modifying values programmatically - - compiles cleanly in the following compilers: - - Windows/VC6 (warning level 3) - - Windows/VC.NET 2003 (warning level 4) - - Windows/VC 2005 (warning level 4) - - Linux/gcc (-Wall) - - - @section usage USAGE SUMMARY - - -# Define the appropriate symbol for the converter you wish to use and - include the SimpleIni.h header file. If no specific converter is defined - then the default converter is used. The default conversion mode uses - SI_CONVERT_WIN32 on Windows and SI_CONVERT_GENERIC on all other - platforms. If you are using ICU then SI_CONVERT_ICU is supported on all - platforms. - -# Declare an instance the appropriate class. Note that the following - definitions are just shortcuts for commonly used types. Other types - (PRUnichar, unsigned short, unsigned char) are also possible. - -
Interface Case-sensitive Load UTF-8 Load MBCS Typedef -
SI_CONVERT_GENERIC -
char No Yes Yes #1 CSimpleIniA -
char Yes Yes Yes CSimpleIniCaseA -
wchar_t No Yes Yes CSimpleIniW -
wchar_t Yes Yes Yes CSimpleIniCaseW -
SI_CONVERT_WIN32 -
char No No #2 Yes CSimpleIniA -
char Yes Yes Yes CSimpleIniCaseA -
wchar_t No Yes Yes CSimpleIniW -
wchar_t Yes Yes Yes CSimpleIniCaseW -
SI_CONVERT_ICU -
char No Yes Yes CSimpleIniA -
char Yes Yes Yes CSimpleIniCaseA -
UChar No Yes Yes CSimpleIniW -
UChar Yes Yes Yes CSimpleIniCaseW -
- #1 On Windows you are better to use CSimpleIniA with SI_CONVERT_WIN32.
- #2 Only affects Windows. On Windows this uses MBCS functions and - so may fold case incorrectly leading to uncertain results. - -# Call LoadData() or LoadFile() to load and parse the INI configuration file - -# Access and modify the data of the file using the following functions - -
GetAllSections Return all section names -
GetAllKeys Return all key names within a section -
GetAllValues Return all values within a section & key -
GetSection Return all key names and values in a section -
GetSectionSize Return the number of keys in a section -
GetValue Return a value for a section & key -
SetValue Add or update a value for a section & key -
Delete Remove a section, or a key from a section -
- -# Call Save() or SaveFile() to save the INI configuration data - - @section iostreams IO STREAMS - - SimpleIni supports reading from and writing to STL IO streams. Enable this - by defining SI_SUPPORT_IOSTREAMS before including the SimpleIni.h header - file. Ensure that if the streams are backed by a file (e.g. ifstream or - ofstream) then the flag ios_base::binary has been used when the file was - opened. - - @section multiline MULTI-LINE VALUES - - Values that span multiple lines are created using the following format. - -
-        key = <<
-
-    Note the following:
-    - The text used for ENDTAG can be anything and is used to find
-      where the multi-line text ends.
-    - The newline after ENDTAG in the start tag, and the newline
-      before ENDTAG in the end tag is not included in the data value.
-    - The ending tag must be on it's own line with no whitespace before
-      or after it.
-    - The multi-line value is modified at load so that each line in the value
-      is delimited by a single '\\n' character on all platforms. At save time
-      it will be converted into the newline format used by the current
-      platform.
-
-    @section comments COMMENTS
-
-    Comments are preserved in the file within the following restrictions:
-    - Every file may have a single "file comment". It must start with the
-      first character in the file, and will end with the first non-comment
-      line in the file.
-    - Every section may have a single "section comment". It will start
-      with the first comment line following the file comment, or the last
-      data entry. It ends at the beginning of the section.
-    - Every key may have a single "key comment". This comment will start
-      with the first comment line following the section start, or the file
-      comment if there is no section name.
-    - Comments are set at the time that the file, section or key is first
-      created. The only way to modify a comment on a section or a key is to
-      delete that entry and recreate it with the new comment. There is no
-      way to change the file comment.
-
-    @section save SAVE ORDER
-
-    The sections and keys are written out in the same order as they were
-    read in from the file. Sections and keys added to the data after the
-    file has been loaded will be added to the end of the file when it is
-    written. There is no way to specify the location of a section or key
-    other than in first-created, first-saved order.
-
-    @section notes NOTES
-
-    - To load UTF-8 data on Windows 95, you need to use Microsoft Layer for
-      Unicode, or SI_CONVERT_GENERIC, or SI_CONVERT_ICU.
-    - When using SI_CONVERT_GENERIC, ConvertUTF.c must be compiled and linked.
-    - When using SI_CONVERT_ICU, ICU header files must be on the include
-      path and icuuc.lib must be linked in.
-    - To load a UTF-8 file on Windows AND expose it with SI_CHAR == char,
-      you should use SI_CONVERT_GENERIC.
-    - The collation (sorting) order used for sections and keys returned from
-      iterators is NOT DEFINED. If collation order of the text is important
-      then it should be done yourself by either supplying a replacement
-      SI_STRLESS class, or by sorting the strings external to this library.
-    - Usage of the  header on Windows can be disabled by defining
-      SI_NO_MBCS. This is defined automatically on Windows CE platforms.
-
-    @section contrib CONTRIBUTIONS
-    
-    - 2010/05/03: Tobias Gehrig: added GetDoubleValue()
-
-    @section licence MIT LICENCE
-
-    The licence text below is the boilerplate "MIT Licence" used from:
-    http://www.opensource.org/licenses/mit-license.php
-
-    Copyright (c) 2006-2012, Brodie Thiesfield
-
-    Permission is hereby granted, free of charge, to any person obtaining a copy
-    of this software and associated documentation files (the "Software"), to deal
-    in the Software without restriction, including without limitation the rights
-    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-    copies of the Software, and to permit persons to whom the Software is furnished
-    to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be included in
-    all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-    FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-    COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#ifndef INCLUDED_SimpleIni_h
-#define INCLUDED_SimpleIni_h
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-// Disable these warnings in MSVC:
-//  4127 "conditional expression is constant" as the conversion classes trigger
-//  it with the statement if (sizeof(SI_CHAR) == sizeof(char)). This test will
-//  be optimized away in a release build.
-//  4503 'insert' : decorated name length exceeded, name was truncated
-//  4702 "unreachable code" as the MS STL header causes it in release mode.
-//  Again, the code causing the warning will be cleaned up by the compiler.
-//  4786 "identifier truncated to 256 characters" as this is thrown hundreds
-//  of times VC6 as soon as STL is used.
-#ifdef _MSC_VER
-# pragma warning (push)
-# pragma warning (disable: 4127 4503 4702 4786)
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#ifdef SI_SUPPORT_IOSTREAMS
-# include 
-#endif // SI_SUPPORT_IOSTREAMS
-
-#ifdef _DEBUG
-# ifndef assert
-#  include 
-# endif
-# define SI_ASSERT(x)   assert(x)
-#else
-# define SI_ASSERT(x)
-#endif
-
-enum SI_Error {
-    SI_OK       =  0,   //!< No error
-    SI_UPDATED  =  1,   //!< An existing value was updated
-    SI_INSERTED =  2,   //!< A new value was inserted
-
-    // note: test for any error with (retval < 0)
-    SI_FAIL     = -1,   //!< Generic failure
-    SI_NOMEM    = -2,   //!< Out of memory error
-    SI_FILE     = -3    //!< File error (see errno for detail error)
-};
-
-#define SI_UTF8_SIGNATURE     "\xEF\xBB\xBF"
-
-#ifdef _WIN32
-# define SI_NEWLINE_A   "\r\n"
-# define SI_NEWLINE_W   L"\r\n"
-#else // !_WIN32
-# define SI_NEWLINE_A   "\n"
-# define SI_NEWLINE_W   L"\n"
-#endif // _WIN32
-
-#if defined(SI_CONVERT_ICU)
-# include 
-#endif
-
-#if defined(_WIN32)
-# define SI_HAS_WIDE_FILE
-# define SI_WCHAR_T     wchar_t
-#elif defined(SI_CONVERT_ICU)
-# define SI_HAS_WIDE_FILE
-# define SI_WCHAR_T     UChar
-#endif
-
-
-// ---------------------------------------------------------------------------
-//                              MAIN TEMPLATE CLASS
-// ---------------------------------------------------------------------------
-
-/** Simple INI file reader.
-
-    This can be instantiated with the choice of unicode or native characterset,
-    and case sensitive or insensitive comparisons of section and key names.
-    The supported combinations are pre-defined with the following typedefs:
-
-    
-        
Interface Case-sensitive Typedef -
char No CSimpleIniA -
char Yes CSimpleIniCaseA -
wchar_t No CSimpleIniW -
wchar_t Yes CSimpleIniCaseW -
- - Note that using other types for the SI_CHAR is supported. For instance, - unsigned char, unsigned short, etc. Note that where the alternative type - is a different size to char/wchar_t you may need to supply new helper - classes for SI_STRLESS and SI_CONVERTER. - */ -template -class CSimpleIniTempl -{ -public: - /** key entry */ - struct Entry { - const SI_CHAR * pItem; - const SI_CHAR * pComment; - int nOrder; - - Entry(const SI_CHAR * a_pszItem = NULL, int a_nOrder = 0) - : pItem(a_pszItem) - , pComment(NULL) - , nOrder(a_nOrder) - { } - Entry(const SI_CHAR * a_pszItem, const SI_CHAR * a_pszComment, int a_nOrder) - : pItem(a_pszItem) - , pComment(a_pszComment) - , nOrder(a_nOrder) - { } - Entry(const Entry & rhs) { operator=(rhs); } - Entry & operator=(const Entry & rhs) { - pItem = rhs.pItem; - pComment = rhs.pComment; - nOrder = rhs.nOrder; - return *this; - } - -#if defined(_MSC_VER) && _MSC_VER <= 1200 - /** STL of VC6 doesn't allow me to specify my own comparator for list::sort() */ - bool operator<(const Entry & rhs) const { return LoadOrder()(*this, rhs); } - bool operator>(const Entry & rhs) const { return LoadOrder()(rhs, *this); } -#endif - - /** Strict less ordering by name of key only */ - struct KeyOrder : std::binary_function { - bool operator()(const Entry & lhs, const Entry & rhs) const { - const static SI_STRLESS isLess = SI_STRLESS(); - return isLess(lhs.pItem, rhs.pItem); - } - }; - - /** Strict less ordering by order, and then name of key */ - struct LoadOrder : std::binary_function { - bool operator()(const Entry & lhs, const Entry & rhs) const { - if (lhs.nOrder != rhs.nOrder) { - return lhs.nOrder < rhs.nOrder; - } - return KeyOrder()(lhs.pItem, rhs.pItem); - } - }; - }; - - /** map keys to values */ - typedef std::multimap TKeyVal; - - /** map sections to key/value map */ - typedef std::map TSection; - - /** set of dependent string pointers. Note that these pointers are - dependent on memory owned by CSimpleIni. - */ - typedef std::list TNamesDepend; - - /** interface definition for the OutputWriter object to pass to Save() - in order to output the INI file data. - */ - class OutputWriter { - public: - OutputWriter() { } - virtual ~OutputWriter() { } - virtual void Write(const char * a_pBuf) = 0; - private: - OutputWriter(const OutputWriter &); // disable - OutputWriter & operator=(const OutputWriter &); // disable - }; - - /** OutputWriter class to write the INI data to a file */ - class FileWriter : public OutputWriter { - FILE * m_file; - public: - FileWriter(FILE * a_file) : m_file(a_file) { } - void Write(const char * a_pBuf) { - fputs(a_pBuf, m_file); - } - private: - FileWriter(const FileWriter &); // disable - FileWriter & operator=(const FileWriter &); // disable - }; - - /** OutputWriter class to write the INI data to a string */ - class StringWriter : public OutputWriter { - std::string & m_string; - public: - StringWriter(std::string & a_string) : m_string(a_string) { } - void Write(const char * a_pBuf) { - m_string.append(a_pBuf); - } - private: - StringWriter(const StringWriter &); // disable - StringWriter & operator=(const StringWriter &); // disable - }; - -#ifdef SI_SUPPORT_IOSTREAMS - /** OutputWriter class to write the INI data to an ostream */ - class StreamWriter : public OutputWriter { - std::ostream & m_ostream; - public: - StreamWriter(std::ostream & a_ostream) : m_ostream(a_ostream) { } - void Write(const char * a_pBuf) { - m_ostream << a_pBuf; - } - private: - StreamWriter(const StreamWriter &); // disable - StreamWriter & operator=(const StreamWriter &); // disable - }; -#endif // SI_SUPPORT_IOSTREAMS - - /** Characterset conversion utility class to convert strings to the - same format as is used for the storage. - */ - class Converter : private SI_CONVERTER { - public: - Converter(bool a_bStoreIsUtf8) : SI_CONVERTER(a_bStoreIsUtf8) { - m_scratch.resize(1024); - } - Converter(const Converter & rhs) { operator=(rhs); } - Converter & operator=(const Converter & rhs) { - m_scratch = rhs.m_scratch; - return *this; - } - bool ConvertToStore(const SI_CHAR * a_pszString) { - size_t uLen = SizeToStore(a_pszString); - if (uLen == static_cast(-1)) { - return false; - } - while (uLen > m_scratch.size()) { - m_scratch.resize(m_scratch.size() * 2); - } - return SI_CONVERTER::ConvertToStore( - a_pszString, - const_cast(m_scratch.data()), - m_scratch.size()); - } - const char * Data() { return m_scratch.data(); } - private: - std::string m_scratch; - }; - -public: - /*-----------------------------------------------------------------------*/ - - /** Default constructor. - - @param a_bIsUtf8 See the method SetUnicode() for details. - @param a_bMultiKey See the method SetMultiKey() for details. - @param a_bMultiLine See the method SetMultiLine() for details. - */ - CSimpleIniTempl( - bool a_bIsUtf8 = false, - bool a_bMultiKey = false, - bool a_bMultiLine = false - ); - - /** Destructor */ - ~CSimpleIniTempl(); - - /** Deallocate all memory stored by this object */ - void Reset(); - - /** Has any data been loaded */ - bool IsEmpty() const { return m_data.empty(); } - - /*-----------------------------------------------------------------------*/ - /** @{ @name Settings */ - - /** Set the storage format of the INI data. This affects both the loading - and saving of the INI data using all of the Load/Save API functions. - This value cannot be changed after any INI data has been loaded. - - If the file is not set to Unicode (UTF-8), then the data encoding is - assumed to be the OS native encoding. This encoding is the system - locale on Linux/Unix and the legacy MBCS encoding on Windows NT/2K/XP. - If the storage format is set to Unicode then the file will be loaded - as UTF-8 encoded data regardless of the native file encoding. If - SI_CHAR == char then all of the char* parameters take and return UTF-8 - encoded data regardless of the system locale. - - \param a_bIsUtf8 Assume UTF-8 encoding for the source? - */ - void SetUnicode(bool a_bIsUtf8 = true) { - if (!m_pData) m_bStoreIsUtf8 = a_bIsUtf8; - } - - /** Get the storage format of the INI data. */ - bool IsUnicode() const { return m_bStoreIsUtf8; } - - /** Should multiple identical keys be permitted in the file. If set to false - then the last value encountered will be used as the value of the key. - If set to true, then all values will be available to be queried. For - example, with the following input: - -
-        [section]
-        test=value1
-        test=value2
-        
- - Then with SetMultiKey(true), both of the values "value1" and "value2" - will be returned for the key test. If SetMultiKey(false) is used, then - the value for "test" will only be "value2". This value may be changed - at any time. - - \param a_bAllowMultiKey Allow multi-keys in the source? - */ - void SetMultiKey(bool a_bAllowMultiKey = true) { - m_bAllowMultiKey = a_bAllowMultiKey; - } - - /** Get the storage format of the INI data. */ - bool IsMultiKey() const { return m_bAllowMultiKey; } - - /** Should data values be permitted to span multiple lines in the file. If - set to false then the multi-line construct << - SI_CHAR FORMAT - char same format as when loaded (MBCS or UTF-8) - wchar_t UTF-8 - other UTF-8 - - - Note that comments from the original data is preserved as per the - documentation on comments. The order of the sections and values - from the original file will be preserved. - - Any data prepended or appended to the output device must use the the - same format (MBCS or UTF-8). You may use the GetConverter() method to - convert text to the correct format regardless of the output format - being used by SimpleIni. - - To add a BOM to UTF-8 data, write it out manually at the very beginning - like is done in SaveFile when a_bUseBOM is true. - - @param a_oOutput Output writer to write the data to. - - @param a_bAddSignature Prepend the UTF-8 BOM if the output data is in - UTF-8 format. If it is not UTF-8 then this value is - ignored. Do not set this to true if anything has - already been written to the OutputWriter. - - @return SI_Error See error definitions - */ - SI_Error Save( - OutputWriter & a_oOutput, - bool a_bAddSignature = false - ) const; - -#ifdef SI_SUPPORT_IOSTREAMS - /** Save the INI data to an ostream. See Save() for details. - - @param a_ostream String to have the INI data appended to. - - @param a_bAddSignature Prepend the UTF-8 BOM if the output data is in - UTF-8 format. If it is not UTF-8 then this value is - ignored. Do not set this to true if anything has - already been written to the stream. - - @return SI_Error See error definitions - */ - SI_Error Save( - std::ostream & a_ostream, - bool a_bAddSignature = false - ) const - { - StreamWriter writer(a_ostream); - return Save(writer, a_bAddSignature); - } -#endif // SI_SUPPORT_IOSTREAMS - - /** Append the INI data to a string. See Save() for details. - - @param a_sBuffer String to have the INI data appended to. - - @param a_bAddSignature Prepend the UTF-8 BOM if the output data is in - UTF-8 format. If it is not UTF-8 then this value is - ignored. Do not set this to true if anything has - already been written to the string. - - @return SI_Error See error definitions - */ - SI_Error Save( - std::string & a_sBuffer, - bool a_bAddSignature = false - ) const - { - StringWriter writer(a_sBuffer); - return Save(writer, a_bAddSignature); - } - - /*-----------------------------------------------------------------------*/ - /** @} - @{ @name Accessing INI Data */ - - /** Retrieve all section names. The list is returned as an STL vector of - names and can be iterated or searched as necessary. Note that the - sort order of the returned strings is NOT DEFINED. You can sort - the names into the load order if desired. Search this file for ".sort" - for an example. - - NOTE! This structure contains only pointers to strings. The actual - string data is stored in memory owned by CSimpleIni. Ensure that the - CSimpleIni object is not destroyed or Reset() while these pointers - are in use! - - @param a_names Vector that will receive all of the section - names. See note above! - */ - void GetAllSections( - TNamesDepend & a_names - ) const; - - /** Retrieve all unique key names in a section. The sort order of the - returned strings is NOT DEFINED. You can sort the names into the load - order if desired. Search this file for ".sort" for an example. Only - unique key names are returned. - - NOTE! This structure contains only pointers to strings. The actual - string data is stored in memory owned by CSimpleIni. Ensure that the - CSimpleIni object is not destroyed or Reset() while these strings - are in use! - - @param a_pSection Section to request data for - @param a_names List that will receive all of the key - names. See note above! - - @return true Section was found. - @return false Matching section was not found. - */ - bool GetAllKeys( - const SI_CHAR * a_pSection, - TNamesDepend & a_names - ) const; - - /** Retrieve all values for a specific key. This method can be used when - multiple keys are both enabled and disabled. Note that the sort order - of the returned strings is NOT DEFINED. You can sort the names into - the load order if desired. Search this file for ".sort" for an example. - - NOTE! The returned values are pointers to string data stored in memory - owned by CSimpleIni. Ensure that the CSimpleIni object is not destroyed - or Reset while you are using this pointer! - - @param a_pSection Section to search - @param a_pKey Key to search for - @param a_values List to return if the key is not found - - @return true Key was found. - @return false Matching section/key was not found. - */ - bool GetAllValues( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - TNamesDepend & a_values - ) const; - - /** Query the number of keys in a specific section. Note that if multiple - keys are enabled, then this value may be different to the number of - keys returned by GetAllKeys. - - @param a_pSection Section to request data for - - @return -1 Section does not exist in the file - @return >=0 Number of keys in the section - */ - int GetSectionSize( - const SI_CHAR * a_pSection - ) const; - - /** Retrieve all key and value pairs for a section. The data is returned - as a pointer to an STL map and can be iterated or searched as - desired. Note that multiple entries for the same key may exist when - multiple keys have been enabled. - - NOTE! This structure contains only pointers to strings. The actual - string data is stored in memory owned by CSimpleIni. Ensure that the - CSimpleIni object is not destroyed or Reset() while these strings - are in use! - - @param a_pSection Name of the section to return - @return boolean Was a section matching the supplied - name found. - */ - const TKeyVal * GetSection( - const SI_CHAR * a_pSection - ) const; - - /** Retrieve the value for a specific key. If multiple keys are enabled - (see SetMultiKey) then only the first value associated with that key - will be returned, see GetAllValues for getting all values with multikey. - - NOTE! The returned value is a pointer to string data stored in memory - owned by CSimpleIni. Ensure that the CSimpleIni object is not destroyed - or Reset while you are using this pointer! - - @param a_pSection Section to search - @param a_pKey Key to search for - @param a_pDefault Value to return if the key is not found - @param a_pHasMultiple Optionally receive notification of if there are - multiple entries for this key. - - @return a_pDefault Key was not found in the section - @return other Value of the key - */ - const SI_CHAR * GetValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - const SI_CHAR * a_pDefault = NULL, - bool * a_pHasMultiple = NULL - ) const; - - /** Retrieve a numeric value for a specific key. If multiple keys are enabled - (see SetMultiKey) then only the first value associated with that key - will be returned, see GetAllValues for getting all values with multikey. - - @param a_pSection Section to search - @param a_pKey Key to search for - @param a_nDefault Value to return if the key is not found - @param a_pHasMultiple Optionally receive notification of if there are - multiple entries for this key. - - @return a_nDefault Key was not found in the section - @return other Value of the key - */ - long GetLongValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - long a_nDefault = 0, - bool * a_pHasMultiple = NULL - ) const; - - /** Retrieve a numeric value for a specific key. If multiple keys are enabled - (see SetMultiKey) then only the first value associated with that key - will be returned, see GetAllValues for getting all values with multikey. - - @param a_pSection Section to search - @param a_pKey Key to search for - @param a_nDefault Value to return if the key is not found - @param a_pHasMultiple Optionally receive notification of if there are - multiple entries for this key. - - @return a_nDefault Key was not found in the section - @return other Value of the key - */ - double GetDoubleValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - double a_nDefault = 0, - bool * a_pHasMultiple = NULL - ) const; - - /** Retrieve a boolean value for a specific key. If multiple keys are enabled - (see SetMultiKey) then only the first value associated with that key - will be returned, see GetAllValues for getting all values with multikey. - - Strings starting with "t", "y", "on" or "1" are returned as logically true. - Strings starting with "f", "n", "of" or "0" are returned as logically false. - For all other values the default is returned. Character comparisons are - case-insensitive. - - @param a_pSection Section to search - @param a_pKey Key to search for - @param a_bDefault Value to return if the key is not found - @param a_pHasMultiple Optionally receive notification of if there are - multiple entries for this key. - - @return a_nDefault Key was not found in the section - @return other Value of the key - */ - bool GetBoolValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - bool a_bDefault = false, - bool * a_pHasMultiple = NULL - ) const; - - /** Add or update a section or value. This will always insert - when multiple keys are enabled. - - @param a_pSection Section to add or update - @param a_pKey Key to add or update. Set to NULL to - create an empty section. - @param a_pValue Value to set. Set to NULL to create an - empty section. - @param a_pComment Comment to be associated with the section or the - key. If a_pKey is NULL then it will be associated - with the section, otherwise the key. Note that a - comment may be set ONLY when the section or key is - first created (i.e. when this function returns the - value SI_INSERTED). If you wish to create a section - with a comment then you need to create the section - separately to the key. The comment string must be - in full comment form already (have a comment - character starting every line). - @param a_bForceReplace Should all existing values in a multi-key INI - file be replaced with this entry. This option has - no effect if not using multi-key files. The - difference between Delete/SetValue and SetValue - with a_bForceReplace = true, is that the load - order and comment will be preserved this way. - - @return SI_Error See error definitions - @return SI_UPDATED Value was updated - @return SI_INSERTED Value was inserted - */ - SI_Error SetValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - const SI_CHAR * a_pValue, - const SI_CHAR * a_pComment = NULL, - bool a_bForceReplace = false - ) - { - return AddEntry(a_pSection, a_pKey, a_pValue, a_pComment, a_bForceReplace, true); - } - - /** Add or update a numeric value. This will always insert - when multiple keys are enabled. - - @param a_pSection Section to add or update - @param a_pKey Key to add or update. - @param a_nValue Value to set. - @param a_pComment Comment to be associated with the key. See the - notes on SetValue() for comments. - @param a_bUseHex By default the value will be written to the file - in decimal format. Set this to true to write it - as hexadecimal. - @param a_bForceReplace Should all existing values in a multi-key INI - file be replaced with this entry. This option has - no effect if not using multi-key files. The - difference between Delete/SetLongValue and - SetLongValue with a_bForceReplace = true, is that - the load order and comment will be preserved this - way. - - @return SI_Error See error definitions - @return SI_UPDATED Value was updated - @return SI_INSERTED Value was inserted - */ - SI_Error SetLongValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - long a_nValue, - const SI_CHAR * a_pComment = NULL, - bool a_bUseHex = false, - bool a_bForceReplace = false - ); - - /** Add or update a double value. This will always insert - when multiple keys are enabled. - - @param a_pSection Section to add or update - @param a_pKey Key to add or update. - @param a_nValue Value to set. - @param a_pComment Comment to be associated with the key. See the - notes on SetValue() for comments. - @param a_bForceReplace Should all existing values in a multi-key INI - file be replaced with this entry. This option has - no effect if not using multi-key files. The - difference between Delete/SetDoubleValue and - SetDoubleValue with a_bForceReplace = true, is that - the load order and comment will be preserved this - way. - - @return SI_Error See error definitions - @return SI_UPDATED Value was updated - @return SI_INSERTED Value was inserted - */ - SI_Error SetDoubleValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - double a_nValue, - const SI_CHAR * a_pComment = NULL, - bool a_bForceReplace = false - ); - - /** Add or update a boolean value. This will always insert - when multiple keys are enabled. - - @param a_pSection Section to add or update - @param a_pKey Key to add or update. - @param a_bValue Value to set. - @param a_pComment Comment to be associated with the key. See the - notes on SetValue() for comments. - @param a_bForceReplace Should all existing values in a multi-key INI - file be replaced with this entry. This option has - no effect if not using multi-key files. The - difference between Delete/SetBoolValue and - SetBoolValue with a_bForceReplace = true, is that - the load order and comment will be preserved this - way. - - @return SI_Error See error definitions - @return SI_UPDATED Value was updated - @return SI_INSERTED Value was inserted - */ - SI_Error SetBoolValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - bool a_bValue, - const SI_CHAR * a_pComment = NULL, - bool a_bForceReplace = false - ); - - /** Delete an entire section, or a key from a section. Note that the - data returned by GetSection is invalid and must not be used after - anything has been deleted from that section using this method. - Note when multiple keys is enabled, this will delete all keys with - that name; there is no way to selectively delete individual key/values - in this situation. - - @param a_pSection Section to delete key from, or if - a_pKey is NULL, the section to remove. - @param a_pKey Key to remove from the section. Set to - NULL to remove the entire section. - @param a_bRemoveEmpty If the section is empty after this key has - been deleted, should the empty section be - removed? - - @return true Key or section was deleted. - @return false Key or section was not found. - */ - bool Delete( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - bool a_bRemoveEmpty = false - ); - - /*-----------------------------------------------------------------------*/ - /** @} - @{ @name Converter */ - - /** Return a conversion object to convert text to the same encoding - as is used by the Save(), SaveFile() and SaveString() functions. - Use this to prepare the strings that you wish to append or prepend - to the output INI data. - */ - Converter GetConverter() const { - return Converter(m_bStoreIsUtf8); - } - - /*-----------------------------------------------------------------------*/ - /** @} */ - -private: - // copying is not permitted - CSimpleIniTempl(const CSimpleIniTempl &); // disabled - CSimpleIniTempl & operator=(const CSimpleIniTempl &); // disabled - - /** Parse the data looking for a file comment and store it if found. - */ - SI_Error FindFileComment( - SI_CHAR *& a_pData, - bool a_bCopyStrings - ); - - /** Parse the data looking for the next valid entry. The memory pointed to - by a_pData is modified by inserting NULL characters. The pointer is - updated to the current location in the block of text. - */ - bool FindEntry( - SI_CHAR *& a_pData, - const SI_CHAR *& a_pSection, - const SI_CHAR *& a_pKey, - const SI_CHAR *& a_pVal, - const SI_CHAR *& a_pComment - ) const; - - /** Add the section/key/value to our data. - - @param a_pSection Section name. Sections will be created if they - don't already exist. - @param a_pKey Key name. May be NULL to create an empty section. - Existing entries will be updated. New entries will - be created. - @param a_pValue Value for the key. - @param a_pComment Comment to be associated with the section or the - key. If a_pKey is NULL then it will be associated - with the section, otherwise the key. This must be - a string in full comment form already (have a - comment character starting every line). - @param a_bForceReplace Should all existing values in a multi-key INI - file be replaced with this entry. This option has - no effect if not using multi-key files. The - difference between Delete/AddEntry and AddEntry - with a_bForceReplace = true, is that the load - order and comment will be preserved this way. - @param a_bCopyStrings Should copies of the strings be made or not. - If false then the pointers will be used as is. - */ - SI_Error AddEntry( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - const SI_CHAR * a_pValue, - const SI_CHAR * a_pComment, - bool a_bForceReplace, - bool a_bCopyStrings - ); - - /** Is the supplied character a whitespace character? */ - inline bool IsSpace(SI_CHAR ch) const { - return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'); - } - - /** Does the supplied character start a comment line? */ - inline bool IsComment(SI_CHAR ch) const { - return (ch == ';' || ch == '#'); - } - - - /** Skip over a newline character (or characters) for either DOS or UNIX */ - inline void SkipNewLine(SI_CHAR *& a_pData) const { - a_pData += (*a_pData == '\r' && *(a_pData+1) == '\n') ? 2 : 1; - } - - /** Make a copy of the supplied string, replacing the original pointer */ - SI_Error CopyString(const SI_CHAR *& a_pString); - - /** Delete a string from the copied strings buffer if necessary */ - void DeleteString(const SI_CHAR * a_pString); - - /** Internal use of our string comparison function */ - bool IsLess(const SI_CHAR * a_pLeft, const SI_CHAR * a_pRight) const { - const static SI_STRLESS isLess = SI_STRLESS(); - return isLess(a_pLeft, a_pRight); - } - - bool IsMultiLineTag(const SI_CHAR * a_pData) const; - bool IsMultiLineData(const SI_CHAR * a_pData) const; - bool LoadMultiLineText( - SI_CHAR *& a_pData, - const SI_CHAR *& a_pVal, - const SI_CHAR * a_pTagName, - bool a_bAllowBlankLinesInComment = false - ) const; - bool IsNewLineChar(SI_CHAR a_c) const; - - bool OutputMultiLineText( - OutputWriter & a_oOutput, - Converter & a_oConverter, - const SI_CHAR * a_pText - ) const; - -private: - /** Copy of the INI file data in our character format. This will be - modified when parsed to have NULL characters added after all - interesting string entries. All of the string pointers to sections, - keys and values point into this block of memory. - */ - SI_CHAR * m_pData; - - /** Length of the data that we have stored. Used when deleting strings - to determine if the string is stored here or in the allocated string - buffer. - */ - size_t m_uDataLen; - - /** File comment for this data, if one exists. */ - const SI_CHAR * m_pFileComment; - - /** Parsed INI data. Section -> (Key -> Value). */ - TSection m_data; - - /** This vector stores allocated memory for copies of strings that have - been supplied after the file load. It will be empty unless SetValue() - has been called. - */ - TNamesDepend m_strings; - - /** Is the format of our datafile UTF-8 or MBCS? */ - bool m_bStoreIsUtf8; - - /** Are multiple values permitted for the same key? */ - bool m_bAllowMultiKey; - - /** Are data values permitted to span multiple lines? */ - bool m_bAllowMultiLine; - - /** Should spaces be written out surrounding the equals sign? */ - bool m_bSpaces; - - /** Next order value, used to ensure sections and keys are output in the - same order that they are loaded/added. - */ - int m_nOrder; -}; - -// --------------------------------------------------------------------------- -// IMPLEMENTATION -// --------------------------------------------------------------------------- - -template -CSimpleIniTempl::CSimpleIniTempl( - bool a_bIsUtf8, - bool a_bAllowMultiKey, - bool a_bAllowMultiLine - ) - : m_pData(0) - , m_uDataLen(0) - , m_pFileComment(NULL) - , m_bStoreIsUtf8(a_bIsUtf8) - , m_bAllowMultiKey(a_bAllowMultiKey) - , m_bAllowMultiLine(a_bAllowMultiLine) - , m_bSpaces(true) - , m_nOrder(0) -{ } - -template -CSimpleIniTempl::~CSimpleIniTempl() -{ - Reset(); -} - -template -void -CSimpleIniTempl::Reset() -{ - // remove all data - delete[] m_pData; - m_pData = NULL; - m_uDataLen = 0; - m_pFileComment = NULL; - if (!m_data.empty()) { - m_data.erase(m_data.begin(), m_data.end()); - } - - // remove all strings - if (!m_strings.empty()) { - typename TNamesDepend::iterator i = m_strings.begin(); - for (; i != m_strings.end(); ++i) { - delete[] const_cast(i->pItem); - } - m_strings.erase(m_strings.begin(), m_strings.end()); - } -} - -template -SI_Error -CSimpleIniTempl::LoadFile( - const char * a_pszFile - ) -{ - FILE * fp = NULL; -#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE - fopen_s(&fp, a_pszFile, "rb"); -#else // !__STDC_WANT_SECURE_LIB__ - fp = fopen(a_pszFile, "rb"); -#endif // __STDC_WANT_SECURE_LIB__ - if (!fp) { - return SI_FILE; - } - SI_Error rc = LoadFile(fp); - fclose(fp); - return rc; -} - -#ifdef SI_HAS_WIDE_FILE -template -SI_Error -CSimpleIniTempl::LoadFile( - const SI_WCHAR_T * a_pwszFile - ) -{ -#ifdef _WIN32 - FILE * fp = NULL; -#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE - _wfopen_s(&fp, a_pwszFile, L"rb"); -#else // !__STDC_WANT_SECURE_LIB__ - fp = _wfopen(a_pwszFile, L"rb"); -#endif // __STDC_WANT_SECURE_LIB__ - if (!fp) return SI_FILE; - SI_Error rc = LoadFile(fp); - fclose(fp); - return rc; -#else // !_WIN32 (therefore SI_CONVERT_ICU) - char szFile[256]; - u_austrncpy(szFile, a_pwszFile, sizeof(szFile)); - return LoadFile(szFile); -#endif // _WIN32 -} -#endif // SI_HAS_WIDE_FILE - -template -SI_Error -CSimpleIniTempl::LoadFile( - FILE * a_fpFile - ) -{ - // load the raw file data - int retval = fseek(a_fpFile, 0, SEEK_END); - if (retval != 0) { - return SI_FILE; - } - long lSize = ftell(a_fpFile); - if (lSize < 0) { - return SI_FILE; - } - if (lSize == 0) { - return SI_OK; - } - char * pData = new char[lSize]; - if (!pData) { - return SI_NOMEM; - } - fseek(a_fpFile, 0, SEEK_SET); - size_t uRead = fread(pData, sizeof(char), lSize, a_fpFile); - if (uRead != static_cast(lSize)) { - delete[] pData; - return SI_FILE; - } - - // convert the raw data to unicode - SI_Error rc = LoadData(pData, uRead); - delete[] pData; - return rc; -} - -template -SI_Error -CSimpleIniTempl::LoadData( - const char * a_pData, - size_t a_uDataLen - ) -{ - SI_CONVERTER converter(m_bStoreIsUtf8); - - if (a_uDataLen == 0) { - return SI_OK; - } - - // consume the UTF-8 BOM if it exists - if (m_bStoreIsUtf8 && a_uDataLen >= 3) { - if (memcmp(a_pData, SI_UTF8_SIGNATURE, 3) == 0) { - a_pData += 3; - a_uDataLen -= 3; - } - } - - // determine the length of the converted data - size_t uLen = converter.SizeFromStore(a_pData, a_uDataLen); - if (uLen == static_cast(-1)) { - return SI_FAIL; - } - - // allocate memory for the data, ensure that there is a NULL - // terminator wherever the converted data ends - SI_CHAR * pData = new SI_CHAR[uLen+1]; - if (!pData) { - return SI_NOMEM; - } - memset(pData, 0, sizeof(SI_CHAR)*(uLen+1)); - - // convert the data - if (!converter.ConvertFromStore(a_pData, a_uDataLen, pData, uLen)) { - delete[] pData; - return SI_FAIL; - } - - // parse it - const static SI_CHAR empty = 0; - SI_CHAR * pWork = pData; - const SI_CHAR * pSection = ∅ - const SI_CHAR * pItem = NULL; - const SI_CHAR * pVal = NULL; - const SI_CHAR * pComment = NULL; - - // We copy the strings if we are loading data into this class when we - // already have stored some. - bool bCopyStrings = (m_pData != NULL); - - // find a file comment if it exists, this is a comment that starts at the - // beginning of the file and continues until the first blank line. - SI_Error rc = FindFileComment(pWork, bCopyStrings); - if (rc < 0) return rc; - - // add every entry in the file to the data table - while (FindEntry(pWork, pSection, pItem, pVal, pComment)) { - rc = AddEntry(pSection, pItem, pVal, pComment, false, bCopyStrings); - if (rc < 0) return rc; - } - - // store these strings if we didn't copy them - if (bCopyStrings) { - delete[] pData; - } - else { - m_pData = pData; - m_uDataLen = uLen+1; - } - - return SI_OK; -} - -#ifdef SI_SUPPORT_IOSTREAMS -template -SI_Error -CSimpleIniTempl::LoadData( - std::istream & a_istream - ) -{ - std::string strData; - char szBuf[512]; - do { - a_istream.get(szBuf, sizeof(szBuf), '\0'); - strData.append(szBuf); - } - while (a_istream.good()); - return LoadData(strData); -} -#endif // SI_SUPPORT_IOSTREAMS - -template -SI_Error -CSimpleIniTempl::FindFileComment( - SI_CHAR *& a_pData, - bool a_bCopyStrings - ) -{ - // there can only be a single file comment - if (m_pFileComment) { - return SI_OK; - } - - // Load the file comment as multi-line text, this will modify all of - // the newline characters to be single \n chars - if (!LoadMultiLineText(a_pData, m_pFileComment, NULL, false)) { - return SI_OK; - } - - // copy the string if necessary - if (a_bCopyStrings) { - SI_Error rc = CopyString(m_pFileComment); - if (rc < 0) return rc; - } - - return SI_OK; -} - -template -bool -CSimpleIniTempl::FindEntry( - SI_CHAR *& a_pData, - const SI_CHAR *& a_pSection, - const SI_CHAR *& a_pKey, - const SI_CHAR *& a_pVal, - const SI_CHAR *& a_pComment - ) const -{ - a_pComment = NULL; - - SI_CHAR * pTrail = NULL; - while (*a_pData) { - // skip spaces and empty lines - while (*a_pData && IsSpace(*a_pData)) { - ++a_pData; - } - if (!*a_pData) { - break; - } - - // skip processing of comment lines but keep a pointer to - // the start of the comment. - if (IsComment(*a_pData)) { - LoadMultiLineText(a_pData, a_pComment, NULL, true); - continue; - } - - // process section names - if (*a_pData == '[') { - // skip leading spaces - ++a_pData; - while (*a_pData && IsSpace(*a_pData)) { - ++a_pData; - } - - // find the end of the section name (it may contain spaces) - // and convert it to lowercase as necessary - a_pSection = a_pData; - while (*a_pData && *a_pData != ']' && !IsNewLineChar(*a_pData)) { - ++a_pData; - } - - // if it's an invalid line, just skip it - if (*a_pData != ']') { - continue; - } - - // remove trailing spaces from the section - pTrail = a_pData - 1; - while (pTrail >= a_pSection && IsSpace(*pTrail)) { - --pTrail; - } - ++pTrail; - *pTrail = 0; - - // skip to the end of the line - ++a_pData; // safe as checked that it == ']' above - while (*a_pData && !IsNewLineChar(*a_pData)) { - ++a_pData; - } - - a_pKey = NULL; - a_pVal = NULL; - return true; - } - - // find the end of the key name (it may contain spaces) - // and convert it to lowercase as necessary - a_pKey = a_pData; - while (*a_pData && *a_pData != '=' && !IsNewLineChar(*a_pData)) { - ++a_pData; - } - - // if it's an invalid line, just skip it - if (*a_pData != '=') { - continue; - } - - // empty keys are invalid - if (a_pKey == a_pData) { - while (*a_pData && !IsNewLineChar(*a_pData)) { - ++a_pData; - } - continue; - } - - // remove trailing spaces from the key - pTrail = a_pData - 1; - while (pTrail >= a_pKey && IsSpace(*pTrail)) { - --pTrail; - } - ++pTrail; - *pTrail = 0; - - // skip leading whitespace on the value - ++a_pData; // safe as checked that it == '=' above - while (*a_pData && !IsNewLineChar(*a_pData) && IsSpace(*a_pData)) { - ++a_pData; - } - - // find the end of the value which is the end of this line - a_pVal = a_pData; - while (*a_pData && !IsNewLineChar(*a_pData)) { - ++a_pData; - } - - // remove trailing spaces from the value - pTrail = a_pData - 1; - if (*a_pData) { // prepare for the next round - SkipNewLine(a_pData); - } - while (pTrail >= a_pVal && IsSpace(*pTrail)) { - --pTrail; - } - ++pTrail; - *pTrail = 0; - - // check for multi-line entries - if (m_bAllowMultiLine && IsMultiLineTag(a_pVal)) { - // skip the "<<<" to get the tag that will end the multiline - const SI_CHAR * pTagName = a_pVal + 3; - return LoadMultiLineText(a_pData, a_pVal, pTagName); - } - - // return the standard entry - return true; - } - - return false; -} - -template -bool -CSimpleIniTempl::IsMultiLineTag( - const SI_CHAR * a_pVal - ) const -{ - // check for the "<<<" prefix for a multi-line entry - if (*a_pVal++ != '<') return false; - if (*a_pVal++ != '<') return false; - if (*a_pVal++ != '<') return false; - return true; -} - -template -bool -CSimpleIniTempl::IsMultiLineData( - const SI_CHAR * a_pData - ) const -{ - // data is multi-line if it has any of the following features: - // * whitespace prefix - // * embedded newlines - // * whitespace suffix - - // empty string - if (!*a_pData) { - return false; - } - - // check for prefix - if (IsSpace(*a_pData)) { - return true; - } - - // embedded newlines - while (*a_pData) { - if (IsNewLineChar(*a_pData)) { - return true; - } - ++a_pData; - } - - // check for suffix - if (IsSpace(*--a_pData)) { - return true; - } - - return false; -} - -template -bool -CSimpleIniTempl::IsNewLineChar( - SI_CHAR a_c - ) const -{ - return (a_c == '\n' || a_c == '\r'); -} - -template -bool -CSimpleIniTempl::LoadMultiLineText( - SI_CHAR *& a_pData, - const SI_CHAR *& a_pVal, - const SI_CHAR * a_pTagName, - bool a_bAllowBlankLinesInComment - ) const -{ - // we modify this data to strip all newlines down to a single '\n' - // character. This means that on Windows we need to strip out some - // characters which will make the data shorter. - // i.e. LINE1-LINE1\r\nLINE2-LINE2\0 will become - // LINE1-LINE1\nLINE2-LINE2\0 - // The pDataLine entry is the pointer to the location in memory that - // the current line needs to start to run following the existing one. - // This may be the same as pCurrLine in which case no move is needed. - SI_CHAR * pDataLine = a_pData; - SI_CHAR * pCurrLine; - - // value starts at the current line - a_pVal = a_pData; - - // find the end tag. This tag must start in column 1 and be - // followed by a newline. No whitespace removal is done while - // searching for this tag. - SI_CHAR cEndOfLineChar = *a_pData; - for(;;) { - // if we are loading comments then we need a comment character as - // the first character on every line - if (!a_pTagName && !IsComment(*a_pData)) { - // if we aren't allowing blank lines then we're done - if (!a_bAllowBlankLinesInComment) { - break; - } - - // if we are allowing blank lines then we only include them - // in this comment if another comment follows, so read ahead - // to find out. - SI_CHAR * pCurr = a_pData; - int nNewLines = 0; - while (IsSpace(*pCurr)) { - if (IsNewLineChar(*pCurr)) { - ++nNewLines; - SkipNewLine(pCurr); - } - else { - ++pCurr; - } - } - - // we have a comment, add the blank lines to the output - // and continue processing from here - if (IsComment(*pCurr)) { - for (; nNewLines > 0; --nNewLines) *pDataLine++ = '\n'; - a_pData = pCurr; - continue; - } - - // the comment ends here - break; - } - - // find the end of this line - pCurrLine = a_pData; - while (*a_pData && !IsNewLineChar(*a_pData)) ++a_pData; - - // move this line down to the location that it should be if necessary - if (pDataLine < pCurrLine) { - size_t nLen = static_cast (a_pData - pCurrLine); - memmove(pDataLine, pCurrLine, nLen * sizeof(SI_CHAR)); - pDataLine[nLen] = '\0'; - } - - // end the line with a NULL - cEndOfLineChar = *a_pData; - *a_pData = 0; - - // if are looking for a tag then do the check now. This is done before - // checking for end of the data, so that if we have the tag at the end - // of the data then the tag is removed correctly. - if (a_pTagName && - (!IsLess(pDataLine, a_pTagName) && !IsLess(a_pTagName, pDataLine))) - { - break; - } - - // if we are at the end of the data then we just automatically end - // this entry and return the current data. - if (!cEndOfLineChar) { - return true; - } - - // otherwise we need to process this newline to ensure that it consists - // of just a single \n character. - pDataLine += (a_pData - pCurrLine); - *a_pData = cEndOfLineChar; - SkipNewLine(a_pData); - *pDataLine++ = '\n'; - } - - // if we didn't find a comment at all then return false - if (a_pVal == a_pData) { - a_pVal = NULL; - return false; - } - - // the data (which ends at the end of the last line) needs to be - // null-terminated BEFORE before the newline character(s). If the - // user wants a new line in the multi-line data then they need to - // add an empty line before the tag. - *--pDataLine = '\0'; - - // if looking for a tag and if we aren't at the end of the data, - // then move a_pData to the start of the next line. - if (a_pTagName && cEndOfLineChar) { - SI_ASSERT(IsNewLineChar(cEndOfLineChar)); - *a_pData = cEndOfLineChar; - SkipNewLine(a_pData); - } - - return true; -} - -template -SI_Error -CSimpleIniTempl::CopyString( - const SI_CHAR *& a_pString - ) -{ - size_t uLen = 0; - if (sizeof(SI_CHAR) == sizeof(char)) { - uLen = strlen(static_cast(a_pString)); - } - else if (sizeof(SI_CHAR) == sizeof(wchar_t)) { - uLen = wcslen(reinterpret_cast(a_pString)); - } - else { - for ( ; a_pString[uLen]; ++uLen) /*loop*/ ; - } - ++uLen; // NULL character - SI_CHAR * pCopy = new SI_CHAR[uLen]; - if (!pCopy) { - return SI_NOMEM; - } - memcpy(pCopy, a_pString, sizeof(SI_CHAR)*uLen); - m_strings.push_back(pCopy); - a_pString = pCopy; - return SI_OK; -} - -template -SI_Error -CSimpleIniTempl::AddEntry( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - const SI_CHAR * a_pValue, - const SI_CHAR * a_pComment, - bool a_bForceReplace, - bool a_bCopyStrings - ) -{ - SI_Error rc; - bool bInserted = false; - - SI_ASSERT(!a_pComment || IsComment(*a_pComment)); - - // if we are copying strings then make a copy of the comment now - // because we will need it when we add the entry. - if (a_bCopyStrings && a_pComment) { - rc = CopyString(a_pComment); - if (rc < 0) return rc; - } - - // create the section entry if necessary - typename TSection::iterator iSection = m_data.find(a_pSection); - if (iSection == m_data.end()) { - // if the section doesn't exist then we need a copy as the - // string needs to last beyond the end of this function - if (a_bCopyStrings) { - rc = CopyString(a_pSection); - if (rc < 0) return rc; - } - - // only set the comment if this is a section only entry - Entry oSection(a_pSection, ++m_nOrder); - if (a_pComment && (!a_pKey || !a_pValue)) { - oSection.pComment = a_pComment; - } - - typename TSection::value_type oEntry(oSection, TKeyVal()); - typedef typename TSection::iterator SectionIterator; - std::pair i = m_data.insert(oEntry); - iSection = i.first; - bInserted = true; - } - if (!a_pKey || !a_pValue) { - // section only entries are specified with pItem and pVal as NULL - return bInserted ? SI_INSERTED : SI_UPDATED; - } - - // check for existence of the key - TKeyVal & keyval = iSection->second; - typename TKeyVal::iterator iKey = keyval.find(a_pKey); - - // remove all existing entries but save the load order and - // comment of the first entry - int nLoadOrder = ++m_nOrder; - if (iKey != keyval.end() && m_bAllowMultiKey && a_bForceReplace) { - const SI_CHAR * pComment = NULL; - while (iKey != keyval.end() && !IsLess(a_pKey, iKey->first.pItem)) { - if (iKey->first.nOrder < nLoadOrder) { - nLoadOrder = iKey->first.nOrder; - pComment = iKey->first.pComment; - } - ++iKey; - } - if (pComment) { - DeleteString(a_pComment); - a_pComment = pComment; - CopyString(a_pComment); - } - Delete(a_pSection, a_pKey); - iKey = keyval.end(); - } - - // make string copies if necessary - bool bForceCreateNewKey = m_bAllowMultiKey && !a_bForceReplace; - if (a_bCopyStrings) { - if (bForceCreateNewKey || iKey == keyval.end()) { - // if the key doesn't exist then we need a copy as the - // string needs to last beyond the end of this function - // because we will be inserting the key next - rc = CopyString(a_pKey); - if (rc < 0) return rc; - } - - // we always need a copy of the value - rc = CopyString(a_pValue); - if (rc < 0) return rc; - } - - // create the key entry - if (iKey == keyval.end() || bForceCreateNewKey) { - Entry oKey(a_pKey, nLoadOrder); - if (a_pComment) { - oKey.pComment = a_pComment; - } - typename TKeyVal::value_type oEntry(oKey, static_cast(NULL)); - iKey = keyval.insert(oEntry); - bInserted = true; - } - iKey->second = a_pValue; - return bInserted ? SI_INSERTED : SI_UPDATED; -} - -template -const SI_CHAR * -CSimpleIniTempl::GetValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - const SI_CHAR * a_pDefault, - bool * a_pHasMultiple - ) const -{ - if (a_pHasMultiple) { - *a_pHasMultiple = false; - } - if (!a_pSection || !a_pKey) { - return a_pDefault; - } - typename TSection::const_iterator iSection = m_data.find(a_pSection); - if (iSection == m_data.end()) { - return a_pDefault; - } - typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey); - if (iKeyVal == iSection->second.end()) { - return a_pDefault; - } - - // check for multiple entries with the same key - if (m_bAllowMultiKey && a_pHasMultiple) { - typename TKeyVal::const_iterator iTemp = iKeyVal; - if (++iTemp != iSection->second.end()) { - if (!IsLess(a_pKey, iTemp->first.pItem)) { - *a_pHasMultiple = true; - } - } - } - - return iKeyVal->second; -} - -template -long -CSimpleIniTempl::GetLongValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - long a_nDefault, - bool * a_pHasMultiple - ) const -{ - // return the default if we don't have a value - const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple); - if (!pszValue || !*pszValue) return a_nDefault; - - // convert to UTF-8/MBCS which for a numeric value will be the same as ASCII - char szValue[64] = { 0 }; - SI_CONVERTER c(m_bStoreIsUtf8); - if (!c.ConvertToStore(pszValue, szValue, sizeof(szValue))) { - return a_nDefault; - } - - // handle the value as hex if prefaced with "0x" - long nValue = a_nDefault; - char * pszSuffix = szValue; - if (szValue[0] == '0' && (szValue[1] == 'x' || szValue[1] == 'X')) { - if (!szValue[2]) return a_nDefault; - nValue = strtol(&szValue[2], &pszSuffix, 16); - } - else { - nValue = strtol(szValue, &pszSuffix, 10); - } - - // any invalid strings will return the default value - if (*pszSuffix) { - return a_nDefault; - } - - return nValue; -} - -template -SI_Error -CSimpleIniTempl::SetLongValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - long a_nValue, - const SI_CHAR * a_pComment, - bool a_bUseHex, - bool a_bForceReplace - ) -{ - // use SetValue to create sections - if (!a_pSection || !a_pKey) return SI_FAIL; - - // convert to an ASCII string - char szInput[64]; -#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE - sprintf_s(szInput, a_bUseHex ? "0x%lx" : "%ld", a_nValue); -#else // !__STDC_WANT_SECURE_LIB__ - sprintf(szInput, a_bUseHex ? "0x%lx" : "%ld", a_nValue); -#endif // __STDC_WANT_SECURE_LIB__ - - // convert to output text - SI_CHAR szOutput[64]; - SI_CONVERTER c(m_bStoreIsUtf8); - c.ConvertFromStore(szInput, strlen(szInput) + 1, - szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); - - // actually add it - return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); -} - -template -double -CSimpleIniTempl::GetDoubleValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - double a_nDefault, - bool * a_pHasMultiple - ) const -{ - // return the default if we don't have a value - const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple); - if (!pszValue || !*pszValue) return a_nDefault; - - // convert to UTF-8/MBCS which for a numeric value will be the same as ASCII - char szValue[64] = { 0 }; - SI_CONVERTER c(m_bStoreIsUtf8); - if (!c.ConvertToStore(pszValue, szValue, sizeof(szValue))) { - return a_nDefault; - } - - char * pszSuffix = NULL; - double nValue = strtod(szValue, &pszSuffix); - - // any invalid strings will return the default value - if (!pszSuffix || *pszSuffix) { - return a_nDefault; - } - - return nValue; -} - -template -SI_Error -CSimpleIniTempl::SetDoubleValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - double a_nValue, - const SI_CHAR * a_pComment, - bool a_bForceReplace - ) -{ - // use SetValue to create sections - if (!a_pSection || !a_pKey) return SI_FAIL; - - // convert to an ASCII string - char szInput[64]; -#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE - sprintf_s(szInput, "%f", a_nValue); -#else // !__STDC_WANT_SECURE_LIB__ - sprintf(szInput, "%f", a_nValue); -#endif // __STDC_WANT_SECURE_LIB__ - - // convert to output text - SI_CHAR szOutput[64]; - SI_CONVERTER c(m_bStoreIsUtf8); - c.ConvertFromStore(szInput, strlen(szInput) + 1, - szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); - - // actually add it - return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); -} - -template -bool -CSimpleIniTempl::GetBoolValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - bool a_bDefault, - bool * a_pHasMultiple - ) const -{ - // return the default if we don't have a value - const SI_CHAR * pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple); - if (!pszValue || !*pszValue) return a_bDefault; - - // we only look at the minimum number of characters - switch (pszValue[0]) { - case 't': case 'T': // true - case 'y': case 'Y': // yes - case '1': // 1 (one) - return true; - - case 'f': case 'F': // false - case 'n': case 'N': // no - case '0': // 0 (zero) - return false; - - case 'o': case 'O': - if (pszValue[1] == 'n' || pszValue[1] == 'N') return true; // on - if (pszValue[1] == 'f' || pszValue[1] == 'F') return false; // off - break; - } - - // no recognized value, return the default - return a_bDefault; -} - -template -SI_Error -CSimpleIniTempl::SetBoolValue( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - bool a_bValue, - const SI_CHAR * a_pComment, - bool a_bForceReplace - ) -{ - // use SetValue to create sections - if (!a_pSection || !a_pKey) return SI_FAIL; - - // convert to an ASCII string - const char * pszInput = a_bValue ? "true" : "false"; - - // convert to output text - SI_CHAR szOutput[64]; - SI_CONVERTER c(m_bStoreIsUtf8); - c.ConvertFromStore(pszInput, strlen(pszInput) + 1, - szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); - - // actually add it - return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); -} - -template -bool -CSimpleIniTempl::GetAllValues( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - TNamesDepend & a_values - ) const -{ - a_values.clear(); - - if (!a_pSection || !a_pKey) { - return false; - } - typename TSection::const_iterator iSection = m_data.find(a_pSection); - if (iSection == m_data.end()) { - return false; - } - typename TKeyVal::const_iterator iKeyVal = iSection->second.find(a_pKey); - if (iKeyVal == iSection->second.end()) { - return false; - } - - // insert all values for this key - a_values.push_back(Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder)); - if (m_bAllowMultiKey) { - ++iKeyVal; - while (iKeyVal != iSection->second.end() && !IsLess(a_pKey, iKeyVal->first.pItem)) { - a_values.push_back(Entry(iKeyVal->second, iKeyVal->first.pComment, iKeyVal->first.nOrder)); - ++iKeyVal; - } - } - - return true; -} - -template -int -CSimpleIniTempl::GetSectionSize( - const SI_CHAR * a_pSection - ) const -{ - if (!a_pSection) { - return -1; - } - - typename TSection::const_iterator iSection = m_data.find(a_pSection); - if (iSection == m_data.end()) { - return -1; - } - const TKeyVal & section = iSection->second; - - // if multi-key isn't permitted then the section size is - // the number of keys that we have. - if (!m_bAllowMultiKey || section.empty()) { - return static_cast (section.size()); - } - - // otherwise we need to count them - int nCount = 0; - const SI_CHAR * pLastKey = NULL; - typename TKeyVal::const_iterator iKeyVal = section.begin(); - for (int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n) { - if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) { - ++nCount; - pLastKey = iKeyVal->first.pItem; - } - } - return nCount; -} - -template -const typename CSimpleIniTempl::TKeyVal * -CSimpleIniTempl::GetSection( - const SI_CHAR * a_pSection - ) const -{ - if (a_pSection) { - typename TSection::const_iterator i = m_data.find(a_pSection); - if (i != m_data.end()) { - return &(i->second); - } - } - return 0; -} - -template -void -CSimpleIniTempl::GetAllSections( - TNamesDepend & a_names - ) const -{ - a_names.clear(); - typename TSection::const_iterator i = m_data.begin(); - for (int n = 0; i != m_data.end(); ++i, ++n ) { - a_names.push_back(i->first); - } -} - -template -bool -CSimpleIniTempl::GetAllKeys( - const SI_CHAR * a_pSection, - TNamesDepend & a_names - ) const -{ - a_names.clear(); - - if (!a_pSection) { - return false; - } - - typename TSection::const_iterator iSection = m_data.find(a_pSection); - if (iSection == m_data.end()) { - return false; - } - - const TKeyVal & section = iSection->second; - const SI_CHAR * pLastKey = NULL; - typename TKeyVal::const_iterator iKeyVal = section.begin(); - for (int n = 0; iKeyVal != section.end(); ++iKeyVal, ++n ) { - if (!pLastKey || IsLess(pLastKey, iKeyVal->first.pItem)) { - a_names.push_back(iKeyVal->first); - pLastKey = iKeyVal->first.pItem; - } - } - - return true; -} - -template -SI_Error -CSimpleIniTempl::SaveFile( - const char * a_pszFile, - bool a_bAddSignature - ) const -{ - FILE * fp = NULL; -#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE - fopen_s(&fp, a_pszFile, "wb"); -#else // !__STDC_WANT_SECURE_LIB__ - fp = fopen(a_pszFile, "wb"); -#endif // __STDC_WANT_SECURE_LIB__ - if (!fp) return SI_FILE; - SI_Error rc = SaveFile(fp, a_bAddSignature); - fclose(fp); - return rc; -} - -#ifdef SI_HAS_WIDE_FILE -template -SI_Error -CSimpleIniTempl::SaveFile( - const SI_WCHAR_T * a_pwszFile, - bool a_bAddSignature - ) const -{ -#ifdef _WIN32 - FILE * fp = NULL; -#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE - _wfopen_s(&fp, a_pwszFile, L"wb"); -#else // !__STDC_WANT_SECURE_LIB__ - fp = _wfopen(a_pwszFile, L"wb"); -#endif // __STDC_WANT_SECURE_LIB__ - if (!fp) return SI_FILE; - SI_Error rc = SaveFile(fp, a_bAddSignature); - fclose(fp); - return rc; -#else // !_WIN32 (therefore SI_CONVERT_ICU) - char szFile[256]; - u_austrncpy(szFile, a_pwszFile, sizeof(szFile)); - return SaveFile(szFile, a_bAddSignature); -#endif // _WIN32 -} -#endif // SI_HAS_WIDE_FILE - -template -SI_Error -CSimpleIniTempl::SaveFile( - FILE * a_pFile, - bool a_bAddSignature - ) const -{ - FileWriter writer(a_pFile); - return Save(writer, a_bAddSignature); -} - -template -SI_Error -CSimpleIniTempl::Save( - OutputWriter & a_oOutput, - bool a_bAddSignature - ) const -{ - Converter convert(m_bStoreIsUtf8); - - // add the UTF-8 signature if it is desired - if (m_bStoreIsUtf8 && a_bAddSignature) { - a_oOutput.Write(SI_UTF8_SIGNATURE); - } - - // get all of the sections sorted in load order - TNamesDepend oSections; - GetAllSections(oSections); -#if defined(_MSC_VER) && _MSC_VER <= 1200 - oSections.sort(); -#elif defined(__BORLANDC__) - oSections.sort(Entry::LoadOrder()); -#else - oSections.sort(typename Entry::LoadOrder()); -#endif - - // write the file comment if we have one - bool bNeedNewLine = false; - if (m_pFileComment) { - if (!OutputMultiLineText(a_oOutput, convert, m_pFileComment)) { - return SI_FAIL; - } - bNeedNewLine = true; - } - - // iterate through our sections and output the data - typename TNamesDepend::const_iterator iSection = oSections.begin(); - for ( ; iSection != oSections.end(); ++iSection ) { - // write out the comment if there is one - if (iSection->pComment) { - if (bNeedNewLine) { - a_oOutput.Write(SI_NEWLINE_A); - a_oOutput.Write(SI_NEWLINE_A); - } - if (!OutputMultiLineText(a_oOutput, convert, iSection->pComment)) { - return SI_FAIL; - } - bNeedNewLine = false; - } - - if (bNeedNewLine) { - a_oOutput.Write(SI_NEWLINE_A); - a_oOutput.Write(SI_NEWLINE_A); - bNeedNewLine = false; - } - - // write the section (unless there is no section name) - if (*iSection->pItem) { - if (!convert.ConvertToStore(iSection->pItem)) { - return SI_FAIL; - } - a_oOutput.Write("["); - a_oOutput.Write(convert.Data()); - a_oOutput.Write("]"); - a_oOutput.Write(SI_NEWLINE_A); - } - - // get all of the keys sorted in load order - TNamesDepend oKeys; - GetAllKeys(iSection->pItem, oKeys); -#if defined(_MSC_VER) && _MSC_VER <= 1200 - oKeys.sort(); -#elif defined(__BORLANDC__) - oKeys.sort(Entry::LoadOrder()); -#else - oKeys.sort(typename Entry::LoadOrder()); -#endif - - // write all keys and values - typename TNamesDepend::const_iterator iKey = oKeys.begin(); - for ( ; iKey != oKeys.end(); ++iKey) { - // get all values for this key - TNamesDepend oValues; - GetAllValues(iSection->pItem, iKey->pItem, oValues); - - typename TNamesDepend::const_iterator iValue = oValues.begin(); - for ( ; iValue != oValues.end(); ++iValue) { - // write out the comment if there is one - if (iValue->pComment) { - a_oOutput.Write(SI_NEWLINE_A); - if (!OutputMultiLineText(a_oOutput, convert, iValue->pComment)) { - return SI_FAIL; - } - } - - // write the key - if (!convert.ConvertToStore(iKey->pItem)) { - return SI_FAIL; - } - a_oOutput.Write(convert.Data()); - - // write the value - if (!convert.ConvertToStore(iValue->pItem)) { - return SI_FAIL; - } - a_oOutput.Write(m_bSpaces ? " = " : "="); - if (m_bAllowMultiLine && IsMultiLineData(iValue->pItem)) { - // multi-line data needs to be processed specially to ensure - // that we use the correct newline format for the current system - a_oOutput.Write("<<pItem)) { - return SI_FAIL; - } - a_oOutput.Write("END_OF_TEXT"); - } - else { - a_oOutput.Write(convert.Data()); - } - a_oOutput.Write(SI_NEWLINE_A); - } - } - - bNeedNewLine = true; - } - - return SI_OK; -} - -template -bool -CSimpleIniTempl::OutputMultiLineText( - OutputWriter & a_oOutput, - Converter & a_oConverter, - const SI_CHAR * a_pText - ) const -{ - const SI_CHAR * pEndOfLine; - SI_CHAR cEndOfLineChar = *a_pText; - while (cEndOfLineChar) { - // find the end of this line - pEndOfLine = a_pText; - for (; *pEndOfLine && *pEndOfLine != '\n'; ++pEndOfLine) /*loop*/ ; - cEndOfLineChar = *pEndOfLine; - - // temporarily null terminate, convert and output the line - *const_cast(pEndOfLine) = 0; - if (!a_oConverter.ConvertToStore(a_pText)) { - return false; - } - *const_cast(pEndOfLine) = cEndOfLineChar; - a_pText += (pEndOfLine - a_pText) + 1; - a_oOutput.Write(a_oConverter.Data()); - a_oOutput.Write(SI_NEWLINE_A); - } - return true; -} - -template -bool -CSimpleIniTempl::Delete( - const SI_CHAR * a_pSection, - const SI_CHAR * a_pKey, - bool a_bRemoveEmpty - ) -{ - if (!a_pSection) { - return false; - } - - typename TSection::iterator iSection = m_data.find(a_pSection); - if (iSection == m_data.end()) { - return false; - } - - // remove a single key if we have a keyname - if (a_pKey) { - typename TKeyVal::iterator iKeyVal = iSection->second.find(a_pKey); - if (iKeyVal == iSection->second.end()) { - return false; - } - - // remove any copied strings and then the key - typename TKeyVal::iterator iDelete; - do { - iDelete = iKeyVal++; - - DeleteString(iDelete->first.pItem); - DeleteString(iDelete->second); - iSection->second.erase(iDelete); - } - while (iKeyVal != iSection->second.end() - && !IsLess(a_pKey, iKeyVal->first.pItem)); - - // done now if the section is not empty or we are not pruning away - // the empty sections. Otherwise let it fall through into the section - // deletion code - if (!a_bRemoveEmpty || !iSection->second.empty()) { - return true; - } - } - else { - // delete all copied strings from this section. The actual - // entries will be removed when the section is removed. - typename TKeyVal::iterator iKeyVal = iSection->second.begin(); - for ( ; iKeyVal != iSection->second.end(); ++iKeyVal) { - DeleteString(iKeyVal->first.pItem); - DeleteString(iKeyVal->second); - } - } - - // delete the section itself - DeleteString(iSection->first.pItem); - m_data.erase(iSection); - - return true; -} - -template -void -CSimpleIniTempl::DeleteString( - const SI_CHAR * a_pString - ) -{ - // strings may exist either inside the data block, or they will be - // individually allocated and stored in m_strings. We only physically - // delete those stored in m_strings. - if (a_pString < m_pData || a_pString >= m_pData + m_uDataLen) { - typename TNamesDepend::iterator i = m_strings.begin(); - for (;i != m_strings.end(); ++i) { - if (a_pString == i->pItem) { - delete[] const_cast(i->pItem); - m_strings.erase(i); - break; - } - } - } -} - -// --------------------------------------------------------------------------- -// CONVERSION FUNCTIONS -// --------------------------------------------------------------------------- - -// Defines the conversion classes for different libraries. Before including -// SimpleIni.h, set the converter that you wish you use by defining one of the -// following symbols. -// -// SI_CONVERT_GENERIC Use the Unicode reference conversion library in -// the accompanying files ConvertUTF.h/c -// SI_CONVERT_ICU Use the IBM ICU conversion library. Requires -// ICU headers on include path and icuuc.lib -// SI_CONVERT_WIN32 Use the Win32 API functions for conversion. - -#if !defined(SI_CONVERT_GENERIC) && !defined(SI_CONVERT_WIN32) && !defined(SI_CONVERT_ICU) -# ifdef _WIN32 -# define SI_CONVERT_WIN32 -# else -# define SI_CONVERT_GENERIC -# endif -#endif - -/** - * Generic case-sensitive less than comparison. This class returns numerically - * ordered ASCII case-sensitive text for all possible sizes and types of - * SI_CHAR. - */ -template -struct SI_GenericCase { - bool operator()(const SI_CHAR * pLeft, const SI_CHAR * pRight) const { - long cmp; - for ( ;*pLeft && *pRight; ++pLeft, ++pRight) { - cmp = static_cast (*pLeft) - static_cast (*pRight); - if (cmp != 0) { - return cmp < 0; - } - } - return *pRight != 0; - } -}; - -/** - * Generic ASCII case-insensitive less than comparison. This class returns - * numerically ordered ASCII case-insensitive text for all possible sizes - * and types of SI_CHAR. It is not safe for MBCS text comparison where - * ASCII A-Z characters are used in the encoding of multi-byte characters. - */ -template -struct SI_GenericNoCase { - inline SI_CHAR locase(SI_CHAR ch) const { - return (ch < 'A' || ch > 'Z') ? ch : (ch - 'A' + 'a'); - } - bool operator()(const SI_CHAR * pLeft, const SI_CHAR * pRight) const { - long cmp; - for ( ;*pLeft && *pRight; ++pLeft, ++pRight) { - cmp = static_cast (locase(*pLeft)) - static_cast (locase(*pRight)); - if (cmp != 0) { - return cmp < 0; - } - } - return *pRight != 0; - } -}; - -/** - * Null conversion class for MBCS/UTF-8 to char (or equivalent). - */ -template -class SI_ConvertA { - bool m_bStoreIsUtf8; -protected: - SI_ConvertA() { } -public: - SI_ConvertA(bool a_bStoreIsUtf8) : m_bStoreIsUtf8(a_bStoreIsUtf8) { } - - /* copy and assignment */ - SI_ConvertA(const SI_ConvertA & rhs) { operator=(rhs); } - SI_ConvertA & operator=(const SI_ConvertA & rhs) { - m_bStoreIsUtf8 = rhs.m_bStoreIsUtf8; - return *this; - } - - /** Calculate the number of SI_CHAR required for converting the input - * from the storage format. The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData Data in storage format to be converted to SI_CHAR. - * @param a_uInputDataLen Length of storage format data in bytes. This - * must be the actual length of the data, including - * NULL byte if NULL terminated string is required. - * @return Number of SI_CHAR required by the string when - * converted. If there are embedded NULL bytes in the - * input data, only the string up and not including - * the NULL byte will be converted. - * @return -1 cast to size_t on a conversion error. - */ - size_t SizeFromStore( - const char * a_pInputData, - size_t a_uInputDataLen) - { - (void)a_pInputData; - SI_ASSERT(a_uInputDataLen != (size_t) -1); - - // ASCII/MBCS/UTF-8 needs no conversion - return a_uInputDataLen; - } - - /** Convert the input string from the storage format to SI_CHAR. - * The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData Data in storage format to be converted to SI_CHAR. - * @param a_uInputDataLen Length of storage format data in bytes. This - * must be the actual length of the data, including - * NULL byte if NULL terminated string is required. - * @param a_pOutputData Pointer to the output buffer to received the - * converted data. - * @param a_uOutputDataSize Size of the output buffer in SI_CHAR. - * @return true if all of the input data was successfully - * converted. - */ - bool ConvertFromStore( - const char * a_pInputData, - size_t a_uInputDataLen, - SI_CHAR * a_pOutputData, - size_t a_uOutputDataSize) - { - // ASCII/MBCS/UTF-8 needs no conversion - if (a_uInputDataLen > a_uOutputDataSize) { - return false; - } - memcpy(a_pOutputData, a_pInputData, a_uInputDataLen); - return true; - } - - /** Calculate the number of char required by the storage format of this - * data. The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData NULL terminated string to calculate the number of - * bytes required to be converted to storage format. - * @return Number of bytes required by the string when - * converted to storage format. This size always - * includes space for the terminating NULL character. - * @return -1 cast to size_t on a conversion error. - */ - size_t SizeToStore( - const SI_CHAR * a_pInputData) - { - // ASCII/MBCS/UTF-8 needs no conversion - return strlen(static_cast(a_pInputData)) + 1; - } - - /** Convert the input string to the storage format of this data. - * The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData NULL terminated source string to convert. All of - * the data will be converted including the - * terminating NULL character. - * @param a_pOutputData Pointer to the buffer to receive the converted - * string. - * @param a_uOutputDataSize Size of the output buffer in char. - * @return true if all of the input data, including the - * terminating NULL character was successfully - * converted. - */ - bool ConvertToStore( - const SI_CHAR * a_pInputData, - char * a_pOutputData, - size_t a_uOutputDataSize) - { - // calc input string length (SI_CHAR type and size independent) - size_t uInputLen = strlen(static_cast(a_pInputData)) + 1; - if (uInputLen > a_uOutputDataSize) { - return false; - } - - // ascii/UTF-8 needs no conversion - memcpy(a_pOutputData, a_pInputData, uInputLen); - return true; - } -}; - - -// --------------------------------------------------------------------------- -// SI_CONVERT_GENERIC -// --------------------------------------------------------------------------- -#ifdef SI_CONVERT_GENERIC - -#define SI_Case SI_GenericCase -#define SI_NoCase SI_GenericNoCase - -#include -#include "ConvertUTF.h" - -/** - * Converts UTF-8 to a wchar_t (or equivalent) using the Unicode reference - * library functions. This can be used on all platforms. - */ -template -class SI_ConvertW { - bool m_bStoreIsUtf8; -protected: - SI_ConvertW() { } -public: - SI_ConvertW(bool a_bStoreIsUtf8) : m_bStoreIsUtf8(a_bStoreIsUtf8) { } - - /* copy and assignment */ - SI_ConvertW(const SI_ConvertW & rhs) { operator=(rhs); } - SI_ConvertW & operator=(const SI_ConvertW & rhs) { - m_bStoreIsUtf8 = rhs.m_bStoreIsUtf8; - return *this; - } - - /** Calculate the number of SI_CHAR required for converting the input - * from the storage format. The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData Data in storage format to be converted to SI_CHAR. - * @param a_uInputDataLen Length of storage format data in bytes. This - * must be the actual length of the data, including - * NULL byte if NULL terminated string is required. - * @return Number of SI_CHAR required by the string when - * converted. If there are embedded NULL bytes in the - * input data, only the string up and not including - * the NULL byte will be converted. - * @return -1 cast to size_t on a conversion error. - */ - size_t SizeFromStore( - const char * a_pInputData, - size_t a_uInputDataLen) - { - SI_ASSERT(a_uInputDataLen != (size_t) -1); - - if (m_bStoreIsUtf8) { - // worst case scenario for UTF-8 to wchar_t is 1 char -> 1 wchar_t - // so we just return the same number of characters required as for - // the source text. - return a_uInputDataLen; - } - else { - return mbstowcs(NULL, a_pInputData, a_uInputDataLen); - } - } - - /** Convert the input string from the storage format to SI_CHAR. - * The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData Data in storage format to be converted to SI_CHAR. - * @param a_uInputDataLen Length of storage format data in bytes. This - * must be the actual length of the data, including - * NULL byte if NULL terminated string is required. - * @param a_pOutputData Pointer to the output buffer to received the - * converted data. - * @param a_uOutputDataSize Size of the output buffer in SI_CHAR. - * @return true if all of the input data was successfully - * converted. - */ - bool ConvertFromStore( - const char * a_pInputData, - size_t a_uInputDataLen, - SI_CHAR * a_pOutputData, - size_t a_uOutputDataSize) - { - if (m_bStoreIsUtf8) { - // This uses the Unicode reference implementation to do the - // conversion from UTF-8 to wchar_t. The required files are - // ConvertUTF.h and ConvertUTF.c which should be included in - // the distribution but are publically available from unicode.org - // at http://www.unicode.org/Public/PROGRAMS/CVTUTF/ - ConversionResult retval; - const UTF8 * pUtf8 = static_cast(a_pInputData); - if (sizeof(wchar_t) == sizeof(UTF32)) { - UTF32 * pUtf32 = static_cast(a_pOutputData); - retval = ConvertUTF8toUTF32( - &pUtf8, pUtf8 + a_uInputDataLen, - &pUtf32, pUtf32 + a_uOutputDataSize, - lenientConversion); - } - else if (sizeof(wchar_t) == sizeof(UTF16)) { - UTF16 * pUtf16 = static_cast(a_pOutputData); - retval = ConvertUTF8toUTF16( - &pUtf8, pUtf8 + a_uInputDataLen, - &pUtf16, pUtf16 + a_uOutputDataSize, - lenientConversion); - } - return retval == conversionOK; - } - else { - size_t retval = mbstowcs(a_pOutputData, - a_pInputData, a_uOutputDataSize); - return retval != static_cast(-1); - } - } - - /** Calculate the number of char required by the storage format of this - * data. The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData NULL terminated string to calculate the number of - * bytes required to be converted to storage format. - * @return Number of bytes required by the string when - * converted to storage format. This size always - * includes space for the terminating NULL character. - * @return -1 cast to size_t on a conversion error. - */ - size_t SizeToStore( - const SI_CHAR * a_pInputData) - { - if (m_bStoreIsUtf8) { - // worst case scenario for wchar_t to UTF-8 is 1 wchar_t -> 6 char - size_t uLen = 0; - while (a_pInputData[uLen]) { - ++uLen; - } - return (6 * uLen) + 1; - } - else { - size_t uLen = wcstombs(NULL, a_pInputData, 0); - if (uLen == static_cast(-1)) { - return uLen; - } - return uLen + 1; // include NULL terminator - } - } - - /** Convert the input string to the storage format of this data. - * The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData NULL terminated source string to convert. All of - * the data will be converted including the - * terminating NULL character. - * @param a_pOutputData Pointer to the buffer to receive the converted - * string. - * @param a_uOutputDataSize Size of the output buffer in char. - * @return true if all of the input data, including the - * terminating NULL character was successfully - * converted. - */ - bool ConvertToStore( - const SI_CHAR * a_pInputData, - char * a_pOutputData, - size_t a_uOutputDataSize - ) - { - if (m_bStoreIsUtf8) { - // calc input string length (SI_CHAR type and size independent) - size_t uInputLen = 0; - while (a_pInputData[uInputLen]) { - ++uInputLen; - } - ++uInputLen; // include the NULL char - - // This uses the Unicode reference implementation to do the - // conversion from wchar_t to UTF-8. The required files are - // ConvertUTF.h and ConvertUTF.c which should be included in - // the distribution but are publically available from unicode.org - // at http://www.unicode.org/Public/PROGRAMS/CVTUTF/ - ConversionResult retval; - UTF8 * pUtf8 = static_cast (a_pOutputData); - if (sizeof(wchar_t) == sizeof(UTF32)) { - const UTF32 * pUtf32 = static_cast (a_pInputData); - retval = ConvertUTF32toUTF8( - &pUtf32, pUtf32 + uInputLen, - &pUtf8, pUtf8 + a_uOutputDataSize, - lenientConversion); - } - else if (sizeof(wchar_t) == sizeof(UTF16)) { - const UTF16 * pUtf16 = static_cast (a_pInputData); - retval = ConvertUTF16toUTF8( - &pUtf16, pUtf16 + uInputLen, - &pUtf8, pUtf8 + a_uOutputDataSize, - lenientConversion); - } - return retval == conversionOK; - } - else { - size_t retval = wcstombs(a_pOutputData, - a_pInputData, a_uOutputDataSize); - return retval != static_cast (-1); - } - } -}; - -#endif // SI_CONVERT_GENERIC - - -// --------------------------------------------------------------------------- -// SI_CONVERT_ICU -// --------------------------------------------------------------------------- -#ifdef SI_CONVERT_ICU - -#define SI_Case SI_GenericCase -#define SI_NoCase SI_GenericNoCase - -#include - -/** - * Converts MBCS/UTF-8 to UChar using ICU. This can be used on all platforms. - */ -template -class SI_ConvertW { - const char * m_pEncoding; - UConverter * m_pConverter; -protected: - SI_ConvertW() : m_pEncoding(NULL), m_pConverter(NULL) { } -public: - SI_ConvertW(bool a_bStoreIsUtf8) : m_pConverter(NULL) { - m_pEncoding = a_bStoreIsUtf8 ? "UTF-8" : NULL; - } - - /* copy and assignment */ - SI_ConvertW(const SI_ConvertW & rhs) { operator=(rhs); } - SI_ConvertW & operator=(const SI_ConvertW & rhs) { - m_pEncoding = rhs.m_pEncoding; - m_pConverter = NULL; - return *this; - } - ~SI_ConvertW() { if (m_pConverter) ucnv_close(m_pConverter); } - - /** Calculate the number of UChar required for converting the input - * from the storage format. The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData Data in storage format to be converted to UChar. - * @param a_uInputDataLen Length of storage format data in bytes. This - * must be the actual length of the data, including - * NULL byte if NULL terminated string is required. - * @return Number of UChar required by the string when - * converted. If there are embedded NULL bytes in the - * input data, only the string up and not including - * the NULL byte will be converted. - * @return -1 cast to size_t on a conversion error. - */ - size_t SizeFromStore( - const char * a_pInputData, - size_t a_uInputDataLen) - { - SI_ASSERT(a_uInputDataLen != (size_t) -1); - - UErrorCode nError; - - if (!m_pConverter) { - nError = U_ZERO_ERROR; - m_pConverter = ucnv_open(m_pEncoding, &nError); - if (U_FAILURE(nError)) { - return (size_t) -1; - } - } - - nError = U_ZERO_ERROR; - int32_t nLen = ucnv_toUChars(m_pConverter, NULL, 0, - a_pInputData, (int32_t) a_uInputDataLen, &nError); - if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) { - return (size_t) -1; - } - - return (size_t) nLen; - } - - /** Convert the input string from the storage format to UChar. - * The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData Data in storage format to be converted to UChar. - * @param a_uInputDataLen Length of storage format data in bytes. This - * must be the actual length of the data, including - * NULL byte if NULL terminated string is required. - * @param a_pOutputData Pointer to the output buffer to received the - * converted data. - * @param a_uOutputDataSize Size of the output buffer in UChar. - * @return true if all of the input data was successfully - * converted. - */ - bool ConvertFromStore( - const char * a_pInputData, - size_t a_uInputDataLen, - UChar * a_pOutputData, - size_t a_uOutputDataSize) - { - UErrorCode nError; - - if (!m_pConverter) { - nError = U_ZERO_ERROR; - m_pConverter = ucnv_open(m_pEncoding, &nError); - if (U_FAILURE(nError)) { - return false; - } - } - - nError = U_ZERO_ERROR; - ucnv_toUChars(m_pConverter, - a_pOutputData, (int32_t) a_uOutputDataSize, - a_pInputData, (int32_t) a_uInputDataLen, &nError); - if (U_FAILURE(nError)) { - return false; - } - - return true; - } - - /** Calculate the number of char required by the storage format of this - * data. The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData NULL terminated string to calculate the number of - * bytes required to be converted to storage format. - * @return Number of bytes required by the string when - * converted to storage format. This size always - * includes space for the terminating NULL character. - * @return -1 cast to size_t on a conversion error. - */ - size_t SizeToStore( - const UChar * a_pInputData) - { - UErrorCode nError; - - if (!m_pConverter) { - nError = U_ZERO_ERROR; - m_pConverter = ucnv_open(m_pEncoding, &nError); - if (U_FAILURE(nError)) { - return (size_t) -1; - } - } - - nError = U_ZERO_ERROR; - int32_t nLen = ucnv_fromUChars(m_pConverter, NULL, 0, - a_pInputData, -1, &nError); - if (U_FAILURE(nError) && nError != U_BUFFER_OVERFLOW_ERROR) { - return (size_t) -1; - } - - return (size_t) nLen + 1; - } - - /** Convert the input string to the storage format of this data. - * The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData NULL terminated source string to convert. All of - * the data will be converted including the - * terminating NULL character. - * @param a_pOutputData Pointer to the buffer to receive the converted - * string. - * @param a_pOutputDataSize Size of the output buffer in char. - * @return true if all of the input data, including the - * terminating NULL character was successfully - * converted. - */ - bool ConvertToStore( - const UChar * a_pInputData, - char * a_pOutputData, - size_t a_uOutputDataSize) - { - UErrorCode nError; - - if (!m_pConverter) { - nError = U_ZERO_ERROR; - m_pConverter = ucnv_open(m_pEncoding, &nError); - if (U_FAILURE(nError)) { - return false; - } - } - - nError = U_ZERO_ERROR; - ucnv_fromUChars(m_pConverter, - a_pOutputData, (int32_t) a_uOutputDataSize, - a_pInputData, -1, &nError); - if (U_FAILURE(nError)) { - return false; - } - - return true; - } -}; - -#endif // SI_CONVERT_ICU - - -// --------------------------------------------------------------------------- -// SI_CONVERT_WIN32 -// --------------------------------------------------------------------------- -#ifdef SI_CONVERT_WIN32 - -#define SI_Case SI_GenericCase - -// Windows CE doesn't have errno or MBCS libraries -#ifdef _WIN32_WCE -# ifndef SI_NO_MBCS -# define SI_NO_MBCS -# endif -#endif - -#include -#ifdef SI_NO_MBCS -# define SI_NoCase SI_GenericNoCase -#else // !SI_NO_MBCS -/** - * Case-insensitive comparison class using Win32 MBCS functions. This class - * returns a case-insensitive semi-collation order for MBCS text. It may not - * be safe for UTF-8 text returned in char format as we don't know what - * characters will be folded by the function! Therefore, if you are using - * SI_CHAR == char and SetUnicode(true), then you need to use the generic - * SI_NoCase class instead. - */ -#include -template -struct SI_NoCase { - bool operator()(const SI_CHAR * pLeft, const SI_CHAR * pRight) const { - if (sizeof(SI_CHAR) == sizeof(char)) { - return _mbsicmp(reinterpret_cast(pLeft), - reinterpret_cast(pRight)) < 0; - } - if (sizeof(SI_CHAR) == sizeof(wchar_t)) { - return _wcsicmp(reinterpret_cast(pLeft), - reinterpret_cast(pRight)) < 0; - } - return SI_GenericNoCase()(pLeft, pRight); - } -}; -#endif // SI_NO_MBCS - -/** - * Converts MBCS and UTF-8 to a wchar_t (or equivalent) on Windows. This uses - * only the Win32 functions and doesn't require the external Unicode UTF-8 - * conversion library. It will not work on Windows 95 without using Microsoft - * Layer for Unicode in your application. - */ -template -class SI_ConvertW { - UINT m_uCodePage; -protected: - SI_ConvertW() { } -public: - SI_ConvertW(bool a_bStoreIsUtf8) { - m_uCodePage = a_bStoreIsUtf8 ? CP_UTF8 : CP_ACP; - } - - /* copy and assignment */ - SI_ConvertW(const SI_ConvertW & rhs) { operator=(rhs); } - SI_ConvertW & operator=(const SI_ConvertW & rhs) { - m_uCodePage = rhs.m_uCodePage; - return *this; - } - - /** Calculate the number of SI_CHAR required for converting the input - * from the storage format. The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData Data in storage format to be converted to SI_CHAR. - * @param a_uInputDataLen Length of storage format data in bytes. This - * must be the actual length of the data, including - * NULL byte if NULL terminated string is required. - * @return Number of SI_CHAR required by the string when - * converted. If there are embedded NULL bytes in the - * input data, only the string up and not including - * the NULL byte will be converted. - * @return -1 cast to size_t on a conversion error. - */ - size_t SizeFromStore( - const char * a_pInputData, - size_t a_uInputDataLen) - { - SI_ASSERT(a_uInputDataLen != (size_t) -1); - - int retval = MultiByteToWideChar( - m_uCodePage, 0, - a_pInputData, static_cast (a_uInputDataLen), - 0, 0); - return static_cast(retval > 0 ? retval : -1); - } - - /** Convert the input string from the storage format to SI_CHAR. - * The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData Data in storage format to be converted to SI_CHAR. - * @param a_uInputDataLen Length of storage format data in bytes. This - * must be the actual length of the data, including - * NULL byte if NULL terminated string is required. - * @param a_pOutputData Pointer to the output buffer to received the - * converted data. - * @param a_uOutputDataSize Size of the output buffer in SI_CHAR. - * @return true if all of the input data was successfully - * converted. - */ - bool ConvertFromStore( - const char * a_pInputData, - size_t a_uInputDataLen, - SI_CHAR * a_pOutputData, - size_t a_uOutputDataSize) - { - int nSize = MultiByteToWideChar( - m_uCodePage, 0, - a_pInputData, static_cast (a_uInputDataLen), - static_cast (a_pOutputData), static_cast (a_uOutputDataSize)); - return (nSize > 0); - } - - /** Calculate the number of char required by the storage format of this - * data. The storage format is always UTF-8. - * - * @param a_pInputData NULL terminated string to calculate the number of - * bytes required to be converted to storage format. - * @return Number of bytes required by the string when - * converted to storage format. This size always - * includes space for the terminating NULL character. - * @return -1 cast to size_t on a conversion error. - */ - size_t SizeToStore( - const SI_CHAR * a_pInputData) - { - int retval = WideCharToMultiByte( - m_uCodePage, 0, - static_cast (a_pInputData), -1, - 0, 0, 0, 0); - return static_cast (retval > 0 ? retval : -1); - } - - /** Convert the input string to the storage format of this data. - * The storage format is always UTF-8 or MBCS. - * - * @param a_pInputData NULL terminated source string to convert. All of - * the data will be converted including the - * terminating NULL character. - * @param a_pOutputData Pointer to the buffer to receive the converted - * string. - * @param a_pOutputDataSize Size of the output buffer in char. - * @return true if all of the input data, including the - * terminating NULL character was successfully - * converted. - */ - bool ConvertToStore( - const SI_CHAR * a_pInputData, - char * a_pOutputData, - size_t a_uOutputDataSize) - { - int retval = WideCharToMultiByte( - m_uCodePage, 0, - static_cast (a_pInputData), -1, - a_pOutputData, static_cast (a_uOutputDataSize), 0, 0); - return retval > 0; - } -}; - -#endif // SI_CONVERT_WIN32 - - -// --------------------------------------------------------------------------- -// TYPE DEFINITIONS -// --------------------------------------------------------------------------- - -typedef CSimpleIniTempl,SI_ConvertA > CSimpleIniA; -typedef CSimpleIniTempl,SI_ConvertA > CSimpleIniCaseA; - -#if defined(SI_CONVERT_ICU) -typedef CSimpleIniTempl,SI_ConvertW > CSimpleIniW; -typedef CSimpleIniTempl,SI_ConvertW > CSimpleIniCaseW; -#else -typedef CSimpleIniTempl,SI_ConvertW > CSimpleIniW; -typedef CSimpleIniTempl,SI_ConvertW > CSimpleIniCaseW; -#endif - -#ifdef _UNICODE -# define CSimpleIni CSimpleIniW -# define CSimpleIniCase CSimpleIniCaseW -# define SI_NEWLINE SI_NEWLINE_W -#else // !_UNICODE -# define CSimpleIni CSimpleIniA -# define CSimpleIniCase CSimpleIniCaseA -# define SI_NEWLINE SI_NEWLINE_A -#endif // _UNICODE - -#ifdef _MSC_VER -# pragma warning (pop) -#endif - -#endif // INCLUDED_SimpleIni_h - diff --git a/lib/simpleini/SimpleIni.sln b/lib/simpleini/SimpleIni.sln deleted file mode 100644 index 6fd8a73..0000000 --- a/lib/simpleini/SimpleIni.sln +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleIni", "SimpleIni.vcproj", "{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Debug Unicode = Debug Unicode - Release = Release - Release Unicode = Release Unicode - EndGlobalSection - GlobalSection(ProjectDependencies) = postSolution - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Debug.ActiveCfg = Debug|Win32 - {C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Debug.Build.0 = Debug|Win32 - {C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Debug Unicode.ActiveCfg = Debug Unicode|Win32 - {C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Debug Unicode.Build.0 = Debug Unicode|Win32 - {C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Release.ActiveCfg = Release|Win32 - {C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Release.Build.0 = Release|Win32 - {C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Release Unicode.ActiveCfg = Release Unicode|Win32 - {C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Release Unicode.Build.0 = Release Unicode|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/lib/simpleini/SimpleIni.vcproj b/lib/simpleini/SimpleIni.vcproj deleted file mode 100644 index e5ee0db..0000000 --- a/lib/simpleini/SimpleIni.vcproj +++ /dev/null @@ -1,291 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/simpleini/ini.syn b/lib/simpleini/ini.syn deleted file mode 100644 index 718c560..0000000 --- a/lib/simpleini/ini.syn +++ /dev/null @@ -1,36 +0,0 @@ -; Syntax file for ini files - contributed by Brodie Thiesfield -; -; Suggested Colors: -; Comments (;#) Comments, Comments 2 Green -; Sections Characters Red -; Values Strings Blue - -C=1 - -[Syntax] -Namespace1 = 6 -IgnoreCase = Yes -KeyWordLength = 1 -BracketChars = -OperatorChars = -PreprocStart = -SyntaxStart = -SyntaxEnd = -HexPrefix = -CommentStart = -CommentEnd = -CommentStartAlt = -CommentEndAlt = -SingleComment = # -SingleCommentCol = -SingleCommentAlt = ; -SingleCommentColAlt = -SingleCommentEsc = -StringsSpanLines = No -StringStart = -StringEnd = -StringAlt = = -StringEsc = -CharStart = [ -CharEnd = ] -CharEsc = diff --git a/lib/simpleini/package.cmd b/lib/simpleini/package.cmd deleted file mode 100644 index 2ae29db..0000000 --- a/lib/simpleini/package.cmd +++ /dev/null @@ -1,26 +0,0 @@ -set VERSION=4.15 - -set SEVENZIP="C:\Program Files\7-Zip\7z.exe" - -FOR /F "tokens=*" %%G IN ('DIR /AD /B /S Debug*') DO ( - DEL /S /Q "%%G" - RD "%%G" -) -FOR /F "tokens=*" %%G IN ('DIR /AD /B /S Release*') DO ( - DEL /S /Q "%%G" - RD "%%G" -) -DEL /Q "SimpleIni.ncb" -ATTRIB -H "SimpleIni.suo" -DEL /Q "SimpleIni.suo" -DEL /Q "SimpleIni.opt" -DEL /Q testsi-out*.ini -DEL /Q test1-blah.ini -DEL /Q test1-output.ini -START "Generate documentation" /WAIT "C:\Program Files (x86)\doxygen\bin\doxygen.exe" SimpleIni.doxy -cd .. -del simpleini-%VERSION%.zip -%SEVENZIP% a -tzip -r- -x!simpleini\.svn simpleini-%VERSION%.zip simpleini\* -del simpleini-doc.zip -%SEVENZIP% a -tzip -r simpleini-doc.zip simpleini-doc\* -cd simpleini diff --git a/lib/simpleini/simpleini.doxy b/lib/simpleini/simpleini.doxy deleted file mode 100644 index 6a27221..0000000 --- a/lib/simpleini/simpleini.doxy +++ /dev/null @@ -1,1321 +0,0 @@ -# Doxyfile 1.5.4 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file that -# follow. The default is UTF-8 which is also the encoding used for all text before -# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into -# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of -# possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = SimpleIni - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = D:/src/simpleini-doc - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, -# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, -# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, -# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = "The $name class " \ - "The $name widget " \ - "The $name file " \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = "D:/src/simpleini/ " - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the DETAILS_AT_TOP tag is set to YES then Doxygen -# will output the detailed description near the top, like JavaDoc. -# If set to NO, the detailed description appears after the member -# documentation. - -DETAILS_AT_TOP = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for Java. -# For instance, namespaces will be presented as packages, qualified scopes -# will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to -# include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct (or union) is -# documented as struct with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code where the coding convention is that all structs are -# typedef'ed and only the typedef is referenced never the struct's name. - -TYPEDEF_HIDES_STRUCT = NO - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be extracted -# and appear in the documentation as a namespace called 'anonymous_namespace{file}', -# where file will be replaced with the base name of the file that contains the anonymous -# namespace. By default anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from the -# version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file($line) : $text " - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = D:/src/simpleini/SimpleIni.h - -# This tag can be used to specify the character encoding of the source files that -# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default -# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. -# See http://www.gnu.org/software/libiconv for the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = *.h - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the output. -# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, -# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = * - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH -# then you must also enable this option. If you don't then doxygen will produce -# a warning and turn it on anyway - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentstion. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = SI_HAS_WIDE_FILE \ - SI_SUPPORT_IOSTREAMS - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to -# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to -# specify the directory where the mscgen tool resides. If left empty the tool is assumed to -# be found in the default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will -# generate a call dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will -# generate a caller dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable caller graphs for selected -# functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the number -# of direct children of the root node in a graph is already larger than -# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 1000 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, which results in a white background. -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/lib/simpleini/simpleini.dsp b/lib/simpleini/simpleini.dsp deleted file mode 100644 index 97c386a..0000000 --- a/lib/simpleini/simpleini.dsp +++ /dev/null @@ -1,178 +0,0 @@ -# Microsoft Developer Studio Project File - Name="simpleini" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=simpleini - Win32 Debug Unicode -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "simpleini.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "simpleini.mak" CFG="simpleini - Win32 Debug Unicode" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "simpleini - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "simpleini - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE "simpleini - Win32 Debug Unicode" (based on "Win32 (x86) Console Application") -!MESSAGE "simpleini - Win32 Release Unicode" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "simpleini - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0xc09 /d "NDEBUG" -# ADD RSC /l 0xc09 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/testsi.exe" - -!ELSEIF "$(CFG)" == "simpleini - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "simpleini___Win32_Debug" -# PROP BASE Intermediate_Dir "simpleini___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c -# SUBTRACT CPP /Fr /YX -# ADD BASE RSC /l 0xc09 /d "_DEBUG" -# ADD RSC /l 0xc09 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/testsi.exe" /pdbtype:sept - -!ELSEIF "$(CFG)" == "simpleini - Win32 Debug Unicode" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug Unicode" -# PROP BASE Intermediate_Dir "Debug Unicode" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug Unicode" -# PROP Intermediate_Dir "Debug Unicode" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "SI_USE_GENERIC_CONVERSION" /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0xc09 /d "_DEBUG" -# ADD RSC /l 0xc09 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug Unicode/testsi.exe" /pdbtype:sept - -!ELSEIF "$(CFG)" == "simpleini - Win32 Release Unicode" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release Unicode" -# PROP BASE Intermediate_Dir "Release Unicode" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release Unicode" -# PROP Intermediate_Dir "Release Unicode" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "SI_USE_GENERIC_CONVERSION" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0xc09 /d "NDEBUG" -# ADD RSC /l 0xc09 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release Unicode/testsi.exe" - -!ENDIF - -# Begin Target - -# Name "simpleini - Win32 Release" -# Name "simpleini - Win32 Debug" -# Name "simpleini - Win32 Debug Unicode" -# Name "simpleini - Win32 Release Unicode" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\snippets.cpp -# End Source File -# Begin Source File - -SOURCE=.\test1.cpp -# End Source File -# Begin Source File - -SOURCE=.\testsi.cpp -# End Source File -# End Group -# Begin Group "Library Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\SimpleIni.h -# End Source File -# End Group -# Begin Group "Generic Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\ConvertUTF.c -# End Source File -# Begin Source File - -SOURCE=.\ConvertUTF.h -# End Source File -# End Group -# End Target -# End Project diff --git a/lib/simpleini/simpleini.dsw b/lib/simpleini/simpleini.dsw deleted file mode 100644 index 2d593ed..0000000 --- a/lib/simpleini/simpleini.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "simpleini"=.\simpleini.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/lib/simpleini/snippets.cpp b/lib/simpleini/snippets.cpp deleted file mode 100644 index 646f4ff..0000000 --- a/lib/simpleini/snippets.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// File: snippets.cpp -// Library: SimpleIni -// Author: Brodie Thiesfield -// Source: http://code.jellycan.com/simpleini/ -// -// Snippets that are used on the website - -#ifdef _WIN32 -# pragma warning(disable: 4786) -#endif - -#ifndef _WIN32 -# include -#endif -#include - -#define SI_SUPPORT_IOSTREAMS -#include "SimpleIni.h" - -bool -snippets( - const char * a_pszFile, - bool a_bIsUtf8, - bool a_bUseMultiKey, - bool a_bUseMultiLine - ) -{ - // LOADING DATA - - // load from a data file - CSimpleIniA ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine); - SI_Error rc = ini.LoadFile(a_pszFile); - if (rc < 0) return false; - - // load from a string - std::string strData; - rc = ini.LoadData(strData.c_str(), strData.size()); - if (rc < 0) return false; - - // GETTING SECTIONS AND KEYS - - // get all sections - CSimpleIniA::TNamesDepend sections; - ini.GetAllSections(sections); - - // get all keys in a section - CSimpleIniA::TNamesDepend keys; - ini.GetAllKeys("section-name", keys); - - // GETTING VALUES - - // get the value of a key - const char * pszValue = ini.GetValue("section-name", - "key-name", NULL /*default*/); - - // get the value of a key which may have multiple - // values. If bHasMultipleValues is true, then just - // one value has been returned - bool bHasMultipleValues; - pszValue = ini.GetValue("section-name", "key-name", - NULL /*default*/, &bHasMultipleValues); - - // get all values of a key with multiple values - CSimpleIniA::TNamesDepend values; - ini.GetAllValues("section-name", "key-name", values); - - // sort the values into the original load order -#if defined(_MSC_VER) && _MSC_VER <= 1200 - /** STL of VC6 doesn't allow me to specify my own comparator for list::sort() */ - values.sort(); -#else - values.sort(CSimpleIniA::Entry::LoadOrder()); -#endif - - // output all of the items - CSimpleIniA::TNamesDepend::const_iterator i; - for (i = values.begin(); i != values.end(); ++i) { - printf("key-name = '%s'\n", i->pItem); - } - - // MODIFYING DATA - - // adding a new section - rc = ini.SetValue("new-section", NULL, NULL); - if (rc < 0) return false; - printf("section: %s\n", rc == SI_INSERTED ? - "inserted" : "updated"); - - // adding a new key ("new-section" will be added - // automatically if it doesn't already exist. - rc = ini.SetValue("new-section", "new-key", "value"); - if (rc < 0) return false; - printf("key: %s\n", rc == SI_INSERTED ? - "inserted" : "updated"); - - // changing the value of a key - rc = ini.SetValue("section", "key", "updated-value"); - if (rc < 0) return false; - printf("key: %s\n", rc == SI_INSERTED ? - "inserted" : "updated"); - - // DELETING DATA - - // deleting a key from a section. Optionally the entire - // section may be deleted if it is now empty. - ini.Delete("section-name", "key-name", - true /*delete the section if empty*/); - - // deleting an entire section and all keys in it - ini.Delete("section-name", NULL); - - // SAVING DATA - - // save the data to a string - rc = ini.Save(strData); - if (rc < 0) return false; - - // save the data back to the file - rc = ini.SaveFile(a_pszFile); - if (rc < 0) return false; - - return true; -} diff --git a/lib/simpleini/test.cmd b/lib/simpleini/test.cmd deleted file mode 100644 index f5d64ea..0000000 --- a/lib/simpleini/test.cmd +++ /dev/null @@ -1,24 +0,0 @@ -@echo off - -Debug\testsi.exe -u -m -l test1-input.ini > test1-blah.ini -fc test1-expected.ini test1-output.ini -if errorlevel 1 goto error - -"Debug Unicode\testsi.exe" -u -m -l test1-input.ini > test1-blah.ini -fc test1-expected.ini test1-output.ini -if errorlevel 1 goto error - -Release\testsi.exe -u -m -l test1-input.ini > test1-blah.ini -fc test1-expected.ini test1-output.ini -if errorlevel 1 goto error - -"Release Unicode\testsi.exe" -u -m -l test1-input.ini > test1-blah.ini -fc test1-expected.ini test1-output.ini -if errorlevel 1 goto error - -exit /b 0 - -:error -echo Failed during test run. Output file doesn't match expected file. -pause -exit /b 1 diff --git a/lib/simpleini/test1-expected.ini b/lib/simpleini/test1-expected.ini deleted file mode 100644 index 6b26c6c..0000000 --- a/lib/simpleini/test1-expected.ini +++ /dev/null @@ -1,85 +0,0 @@ -; testsi-UTF8-std.ini : standard UTF-8 test file for SimpleIni automated testing -; -; The number after a section or key is the order that it is defined in this file -; to make it easier to see if it has been written out correctly. This file should -; be loaded with Unicode / MultiKey / MultiLine turned on. - - - -; This comment should be joined on to the one below it about the key -; with no section. - -; Key with no section -lonely-key = nosection -another = nosection either - -; This key has no value -empty = - - -; This should be joined with the comment below about japanese. -; Another line which will be un-indented. - -; This is a section of keys showing the word Japanese in different syllabies. -[ordered-1] -a-1 = blah - -; this is in kanji -japanese-2 = 日本語 - -; this is in hiragana -japanese-3 = にほんご - -; this is in katakana -japanese-4 = ニホンゴ - -; this is in romaji -japanese-5 = nihongo - -; kanji as the key -日本語-6 = japanese - - -[multi-2] - -; value a -test = a - -; value b -test = b - -; value c -test = c - -; value d -test = d - - -[multiline-3] - -; This is obviously a multi-line entry -multiline-1 = << -// Source: http://code.jellycan.com/simpleini/ -// -// Automated testing for SimpleIni streams - -#ifdef _WIN32 -# pragma warning(disable: 4786) -#endif - -#ifdef _WIN32 -# include -# define DELETE_FILE DeleteFileA -#else -# include -# define DELETE_FILE unlink -#endif -#include - -#define SI_SUPPORT_IOSTREAMS -#include "SimpleIni.h" - -class Test -{ - std::string m_strTest; - -public: - Test(const char * a_pszName) - : m_strTest(a_pszName) - { - printf("%s: test starting\n", m_strTest.c_str()); - } - - bool Success() - { - printf("%s: test succeeded\n", m_strTest.c_str()); - return false; - } - - bool Failure(const char * pszReason) - { - printf("%s: test FAILED (%s)\n", m_strTest.c_str(), pszReason); - return false; - } -}; - -bool FileComparisonTest(const char * a_pszFile1, const char * a_pszFile2) { - // ensure that the two files are the same - try { - std::string strFile1, strFile2; - - char szBuf[1024]; - FILE * fp = NULL; - -#if __STDC_WANT_SECURE_LIB__ - fopen_s(&fp, a_pszFile1, "rb"); -#else - fp = fopen(a_pszFile1, "rb"); -#endif - if (!fp) throw false; - while (!feof(fp)) { - size_t n = fread(szBuf, 1, sizeof(szBuf), fp); - strFile1.append(szBuf, n); - } - fclose(fp); - - fp = NULL; -#if __STDC_WANT_SECURE_LIB__ - fopen_s(&fp, a_pszFile2, "rb"); -#else - fp = fopen(a_pszFile2, "rb"); -#endif - if (!fp) throw false; - while (!feof(fp)) { - size_t n = fread(szBuf, 1, sizeof(szBuf), fp); - strFile2.append(szBuf, n); - } - fclose(fp); - - if (strFile1 != strFile2) throw false; - } - catch (...) { - return false; - } - - return true; -} - -bool FileLoadTest(const char * a_pszFile1, const char * a_pszFile2) { - // ensure that the two files load into simpleini the same - CSimpleIniA ini(true, true, true); - bool b; - try { - ini.Reset(); - if (ini.LoadFile(a_pszFile1) < 0) throw "Load failed for file 1"; - if (ini.SaveFile("test1.ini") < 0) throw "Save failed for file 1"; - - ini.Reset(); - if (ini.LoadFile(a_pszFile2) < 0) throw "Load failed for file 2"; - if (ini.SaveFile("test2.ini") < 0) throw "Save failed for file 2"; - - b = FileComparisonTest("test1.ini", "test2.ini"); - DELETE_FILE("test1.ini"); - DELETE_FILE("test2.ini"); - if (!b) throw "File comparison failed in FileLoadTest"; - } - catch (...) { - return false; - } - - return true; -} - -bool TestStreams() -{ - const char * rgszTestFile[3] = { - "test1-input.ini", - "test1-output.ini", - "test1-expected.ini" - }; - - Test oTest("TestStreams"); - - CSimpleIniW ini; - ini.SetUnicode(true); - ini.SetMultiKey(true); - ini.SetMultiLine(true); - - // load the file - try { - std::ifstream instream; - instream.open(rgszTestFile[0], std::ifstream::in | std::ifstream::binary); - if (ini.LoadData(instream) < 0) throw false; - instream.close(); - } - catch (...) { - return oTest.Failure("Failed to load file"); - } - - // standard contents test - //if (!StandardContentsTest(ini, oTest)) { - // return false; - //} - - // save the file - try { - std::ofstream outfile; - outfile.open(rgszTestFile[1], std::ofstream::out | std::ofstream::binary); - if (ini.Save(outfile, true) < 0) throw false; - outfile.close(); - } - catch (...) { - return oTest.Failure("Failed to save file"); - } - - // file comparison test - if (!FileComparisonTest(rgszTestFile[1], rgszTestFile[2])) { - return oTest.Failure("Failed file comparison"); - } - if (!FileLoadTest(rgszTestFile[1], rgszTestFile[2])) { - return oTest.Failure("Failed file load comparison"); - } - - return oTest.Success(); -} diff --git a/lib/simpleini/testsi-EUCJP.ini b/lib/simpleini/testsi-EUCJP.ini deleted file mode 100644 index ee9e987..0000000 --- a/lib/simpleini/testsi-EUCJP.ini +++ /dev/null @@ -1,52 +0,0 @@ -; test file for SimpleIni - -nosection=ok -NOSECTION=still ok - whitespace = ok - -[standard] -foo=foo1 -standard-1=foo -ܸ=ok1 - -[Standard] -Foo=foo2 -standard-2=foo -ܸ=ok2 - - [ Whitespace ] - -a= - -[ whitespace in section name ] - whitespace in key name = whitespace in value name - -; comments - ; more comments - -invalid -=invalid -====invalid - -[Japanese] -nihongo = ܸ -ܸ = ܸ - -[ܸ] -nihongo = ܸ -ܸ = ܸ - -[] -more=no section name - - - -[MultiLine] -single = This is a single line. -multi = << -// Source: http://code.jellycan.com/simpleini/ -// -// Demo of usage - -#ifdef _WIN32 -# pragma warning(disable: 4786) -#endif - -#include -#include -#include - -#define SI_SUPPORT_IOSTREAMS -#if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE) -# include -#endif - -//#define SI_CONVERT_GENERIC -//#define SI_CONVERT_ICU -//#define SI_CONVERT_WIN32 -#include "SimpleIni.h" - -#ifdef SI_CONVERT_ICU -// if converting using ICU then we need the ICU library -# pragma comment(lib, "icuuc.lib") -#endif - -#ifdef _WIN32 -# include -#else // !_WIN32 -# define TCHAR char -# define _T(x) x -# define _tprintf printf -# define _tmain main -#endif // _WIN32 - -static void -Test( - CSimpleIni & ini - ) -{ - const TCHAR *pszSection = 0; - const TCHAR *pItem = 0; - const TCHAR *pszVal = 0; - - // get the value of the key "foo" in section "standard" - bool bHasMulti; - pszVal = ini.GetValue(_T("standard"), _T("foo"), 0, &bHasMulti); - _tprintf(_T("\n-- Value of standard::foo is '%s' (hasMulti = %d)\n"), - pszVal ? pszVal : _T("(null)"), bHasMulti); - - // set the value of the key "foo" in section "standard" - ini.SetValue(_T("standard"), _T("foo"), _T("wibble")); - pszVal = ini.GetValue(_T("standard"), _T("foo"), 0, &bHasMulti); - _tprintf(_T("\n-- Value of standard::foo is '%s' (hasMulti = %d)\n"), - pszVal ? pszVal : _T("(null)"), bHasMulti); - - // get all values of the key "foo" in section "standard" - CSimpleIni::TNamesDepend values; - if (ini.GetAllValues(_T("standard"), _T("foo"), values)) { - _tprintf(_T("\n-- Values of standard::foo are:\n")); - CSimpleIni::TNamesDepend::const_iterator i = values.begin(); - for (; i != values.end(); ++i) { - pszVal = i->pItem; - _tprintf(_T(" -> '%s'\n"), pszVal); - } - } - - // get the size of the section [standard] - _tprintf(_T("\n-- Number of keys in section [standard] = %d\n"), - ini.GetSectionSize(_T("standard"))); - - // delete the key "foo" in section "standard" - ini.Delete(_T("standard"), _T("foo")); - pszVal = ini.GetValue(_T("standard"), _T("foo"), 0); - _tprintf(_T("\n-- Value of standard::foo is now '%s'\n"), - pszVal ? pszVal : _T("(null)")); - - // get the size of the section [standard] - _tprintf(_T("\n-- Number of keys in section [standard] = %d\n"), - ini.GetSectionSize(_T("standard"))); - - // get the list of all key names for the section "standard" - _tprintf(_T("\n-- Dumping keys of section: [standard]\n")); - CSimpleIni::TNamesDepend keys; - ini.GetAllKeys(_T("standard"), keys); - - // dump all of the key names - CSimpleIni::TNamesDepend::const_iterator iKey = keys.begin(); - for ( ; iKey != keys.end(); ++iKey ) { - pItem = iKey->pItem; - _tprintf(_T("Key: %s\n"), pItem); - } - - // add a decimal value - ini.SetLongValue(_T("integer"), _T("dec"), 42, NULL, false); - ini.SetLongValue(_T("integer"), _T("hex"), 42, NULL, true); - - // add some bool values - ini.SetBoolValue(_T("bool"), _T("t"), true); - ini.SetBoolValue(_T("bool"), _T("f"), false); - - // get the values back - assert(42 == ini.GetLongValue(_T("integer"), _T("dec"))); - assert(42 == ini.GetLongValue(_T("integer"), _T("hex"))); - assert(true == ini.GetBoolValue(_T("bool"), _T("t"))); - assert(false == ini.GetBoolValue(_T("bool"), _T("f"))); - - // delete the section "standard" - ini.Delete(_T("standard"), NULL); - _tprintf(_T("\n-- Number of keys in section [standard] = %d\n"), - ini.GetSectionSize(_T("standard"))); - - // iterate through every section in the file - _tprintf(_T("\n-- Dumping all sections\n")); - CSimpleIni::TNamesDepend sections; - ini.GetAllSections(sections); - CSimpleIni::TNamesDepend::const_iterator iSection = sections.begin(); - for ( ; iSection != sections.end(); ++iSection ) { - pszSection = iSection->pItem; - - // print the section name - printf("\n"); - if (*pszSection) { - _tprintf(_T("[%s]\n"), pszSection); - } - - // if there are keys and values... - const CSimpleIni::TKeyVal * pSectionData = ini.GetSection(pszSection); - if (pSectionData) { - // iterate over all keys and dump the key name and value - CSimpleIni::TKeyVal::const_iterator iKeyVal = pSectionData->begin(); - for ( ;iKeyVal != pSectionData->end(); ++iKeyVal) { - pItem = iKeyVal->first.pItem; - pszVal = iKeyVal->second; - _tprintf(_T("%s=%s\n"), pItem, pszVal); - } - } - } -} - -#if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE) -static bool -TestStreams( - const TCHAR * a_pszFile, - bool a_bIsUtf8, - bool a_bUseMultiKey, - bool a_bUseMultiLine - ) -{ - // load the file - CSimpleIni ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine); - _tprintf(_T("Loading file: %s\n"), a_pszFile); - std::ifstream instream; - instream.open(a_pszFile, std::ifstream::in | std::ifstream::binary); - SI_Error rc = ini.LoadData(instream); - instream.close(); - if (rc < 0) { - printf("Failed to open file.\n"); - return false; - } - - Test(ini); - - // save the file (simple) - _tprintf(_T("\n-- Saving file to: testsi-out-streams.ini\n")); - std::ofstream outstream; - outstream.open("testsi-out-streams.ini", std::ofstream::out | std::ofstream::binary); - ini.Save(outstream); - outstream.close(); - - return true; -} -#endif // SI_SUPPORT_IOSTREAMS - -static bool -TestFile( - const TCHAR * a_pszFile, - bool a_bIsUtf8, - bool a_bUseMultiKey, - bool a_bUseMultiLine - ) -{ - // load the file - CSimpleIni ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine); - _tprintf(_T("Loading file: %s\n"), a_pszFile); - SI_Error rc = ini.LoadFile(a_pszFile); - if (rc < 0) { - printf("Failed to open file.\n"); - return false; - } - - // run the tests - Test(ini); - - // save the file (simple) - _tprintf(_T("\n-- Saving file to: testsi-out.ini\n")); - ini.SaveFile("testsi-out.ini"); - - // save the file (with comments) - // Note: to save the file and add a comment to the beginning, use - // code such as the following. - _tprintf(_T("\n-- Saving file to: testsi-out-comment.ini\n")); - FILE * fp = NULL; -#if __STDC_WANT_SECURE_LIB__ - fopen_s(&fp, "testsi-out-comment.ini", "wb"); -#else - fp = fopen("testsi-out-comment.ini", "wb"); -#endif - if (fp) { - CSimpleIni::FileWriter writer(fp); - if (a_bIsUtf8) { - writer.Write(SI_UTF8_SIGNATURE); - } - - // add a string to the file in the correct text format - CSimpleIni::Converter convert = ini.GetConverter(); - convert.ConvertToStore(_T("; output from testsi.cpp test program") - SI_NEWLINE SI_NEWLINE); - writer.Write(convert.Data()); - - ini.Save(writer, false); - fclose(fp); - } - - return true; -} - -static bool -ParseCommandLine( - int argc, - TCHAR * argv[], - const TCHAR * & a_pszFile, - bool & a_bIsUtf8, - bool & a_bUseMultiKey, - bool & a_bUseMultiLine - ) -{ - a_pszFile = 0; - a_bIsUtf8 = false; - a_bUseMultiKey = false; - a_bUseMultiLine = false; - for (--argc; argc > 0; --argc) { - if (argv[argc][0] == '-') { - switch (argv[argc][1]) { - case TCHAR('u'): - a_bIsUtf8 = true; - break; - case TCHAR('m'): - a_bUseMultiKey = true; - break; - case TCHAR('l'): - a_bUseMultiLine = true; - break; - } - } - else { - a_pszFile = argv[argc]; - } - } - if (!a_pszFile) { - _tprintf( - _T("Usage: testsi [-u] [-m] [-l] iniFile\n") - _T(" -u Load file as UTF-8 (Default is to use system locale)\n") - _T(" -m Enable multiple keys\n") - _T(" -l Enable multiple line values\n") - ); - return false; - } - - return true; -} - -extern bool TestStreams(); - -int -_tmain( - int argc, - TCHAR * argv[] - ) -{ - setlocale(LC_ALL, ""); - - // start of automated testing... - TestStreams(); - - // parse the command line - const TCHAR * pszFile; - bool bIsUtf8, bUseMultiKey, bUseMultiLine; - if (!ParseCommandLine(argc, argv, pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) { - return 1; - } - - // run the test - if (!TestFile(pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) { - return 1; - } -#if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE) - if (!TestStreams(pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) { - return 1; - } -#endif - - return 0; -} - diff --git a/src/common/profile.cpp b/src/common/profile.cpp index 0881c92..c66725f 100644 --- a/src/common/profile.cpp +++ b/src/common/profile.cpp @@ -23,24 +23,32 @@ #include #include #include +#include template<> CProfile* CSingleton::mInstance = nullptr; namespace bp = boost::property_tree; -CProfile::CProfile() +CProfile::CProfile() : + m_profileNeedSave(false) { - // m_ini = new CSimpleIniA(); - // m_ini->SetUnicode(); - // m_ini->SetMultiKey(); } CProfile::~CProfile() { - // m_ini->Reset(); - // delete m_ini; + if (m_profileNeedSave) + { + try + { + bp::ini_parser::write_ini("colobot.ini", m_propertyTree); + } + catch (std::exception & e) + { + GetLogger()->Info("Error on storing profile: %s\n", e.what()); + } + } } @@ -53,23 +61,25 @@ bool CProfile::InitCurrentDirectory() catch (std::exception & e) { GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + return false; } - // return result; return true; } + bool CProfile::SetLocalProfileString(std::string section, std::string key, std::string value) { try { m_propertyTree.put(section + "." + key, value); + m_profileNeedSave = true; } catch (std::exception & e) { GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + return false; } - // return (m_ini->SetValue(section.c_str(), key.c_str(), value.c_str()) == SI_OK); return true; } @@ -83,6 +93,7 @@ bool CProfile::GetLocalProfileString(std::string section, std::string key, std:: catch (std::exception & e) { GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + return false; } return true; } @@ -97,8 +108,8 @@ bool CProfile::SetLocalProfileInt(std::string section, std::string key, int valu catch (std::exception & e) { GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + return false; } - // return (m_ini->SetLongValue(section.c_str(), key.c_str(), value) == SI_OK); return true; } @@ -112,8 +123,8 @@ bool CProfile::GetLocalProfileInt(std::string section, std::string key, int &val catch (std::exception & e) { GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + return false; } - // value = m_ini->GetLongValue(section.c_str(), key.c_str(), 0L); return true; } @@ -127,8 +138,8 @@ bool CProfile::SetLocalProfileFloat(std::string section, std::string key, float catch (std::exception & e) { GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + return false; } - // return (m_ini->SetDoubleValue(section.c_str(), key.c_str(), value) == SI_OK); return true; } @@ -142,8 +153,8 @@ bool CProfile::GetLocalProfileFloat(std::string section, std::string key, float catch (std::exception & e) { GetLogger()->Info("Error on parsing profile: %s\n", e.what()); + return false; } - // value = m_ini->GetDoubleValue(section.c_str(), key.c_str(), 0.0d); return true; } @@ -151,12 +162,13 @@ bool CProfile::GetLocalProfileFloat(std::string section, std::string key, float std::vector< std::string > CProfile::GetLocalProfileSection(std::string section, std::string key) { std::vector< std::string > ret_list; + boost::regex re(key + "[0-9]*"); //we want to match all key followed my any number try { for(bp::ptree::value_type const & v : m_propertyTree.get_child(section)) { - if (v.first == key) + if (boost::regex_search(v.first, re)) { ret_list.push_back(v.second.get_value()); } @@ -166,13 +178,6 @@ std::vector< std::string > CProfile::GetLocalProfileSection(std::string section, { GetLogger()->Info("Error on parsing profile: %s\n", e.what()); } - // CSimpleIniA::TNamesDepend values; - // m_ini->GetAllValues(section.c_str(), key.c_str(), values); - // values.sort(CSimpleIniA::Entry::LoadOrder()); - - // for (auto item : values) { - // ret_list.push_back(item.pItem); - // } return ret_list; } diff --git a/src/common/profile.h b/src/common/profile.h index de30a63..ed948ff 100644 --- a/src/common/profile.h +++ b/src/common/profile.h @@ -102,9 +102,8 @@ class CProfile : public CSingleton std::vector< std::string > GetLocalProfileSection(std::string section, std::string key); private: - // bpt::ptree m_pt; boost::property_tree::ptree m_propertyTree; - // CSimpleIniA *m_ini; + bool m_profileNeedSave; }; //! Global function to get profile instance diff --git a/src/sound/plugins/oalsound/CMakeLists.txt b/src/sound/plugins/oalsound/CMakeLists.txt index 12ab5e3..0bc9482 100644 --- a/src/sound/plugins/oalsound/CMakeLists.txt +++ b/src/sound/plugins/oalsound/CMakeLists.txt @@ -4,7 +4,6 @@ set(SOURCES alsound.cpp buffer.cpp channel.cpp - logger.cpp ) SET (CMAKE_CXX_FLAGS "-Wall -g -std=c++0x -fPIC") -- cgit v1.2.3-1-g7c22 From 099f6c4f0b472840ae38aed1042db32481cc142d Mon Sep 17 00:00:00 2001 From: erihel Date: Fri, 28 Sep 2012 00:05:49 +0200 Subject: * Fixed Issue #54: flags don't show in 3D view --- src/object/task/taskflag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object/task/taskflag.cpp b/src/object/task/taskflag.cpp index d45fff4..c88b5c0 100644 --- a/src/object/task/taskflag.cpp +++ b/src/object/task/taskflag.cpp @@ -253,7 +253,7 @@ Error CTaskFlag::CreateFlag(int rank) delete pNew; return ERR_TOOMANY; } - pNew->SetZoom(0, 0.0f); + //pNew->SetZoom(0, 0.0f); m_sound->Play(SOUND_WAYPOINT, pos); pyro = new Gfx::CPyro(m_iMan); -- cgit v1.2.3-1-g7c22 From df4e3dfb6e623889757afe79fc4dfd29ae85748e Mon Sep 17 00:00:00 2001 From: Zaba999 Date: Fri, 28 Sep 2012 21:03:28 +0200 Subject: Small fix in profile + profile_test rewritten to gtest. --- src/CMakeLists.txt | 1 + src/common/profile.cpp | 2 ++ src/common/test/CMakeLists.txt | 16 +++++++---- src/common/test/colobot.ini | 10 +++---- src/common/test/profile_test.cpp | 59 ++++++++++++++++++++-------------------- 5 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 751f51c..fe42c62 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory(CBot) add_subdirectory(tools) # Tests +add_subdirectory(common/test) add_subdirectory(graphics/engine/test) add_subdirectory(math/test) diff --git a/src/common/profile.cpp b/src/common/profile.cpp index c66725f..2c78f9f 100644 --- a/src/common/profile.cpp +++ b/src/common/profile.cpp @@ -104,6 +104,7 @@ bool CProfile::SetLocalProfileInt(std::string section, std::string key, int valu try { m_propertyTree.put(section + "." + key, value); + m_profileNeedSave = true; } catch (std::exception & e) { @@ -134,6 +135,7 @@ bool CProfile::SetLocalProfileFloat(std::string section, std::string key, float try { m_propertyTree.put(section + "." + key, value); + m_profileNeedSave = true; } catch (std::exception & e) { diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt index a1a7a50..7936862 100644 --- a/src/common/test/CMakeLists.txt +++ b/src/common/test/CMakeLists.txt @@ -1,14 +1,20 @@ cmake_minimum_required(VERSION 2.8) set(CMAKE_BUILD_TYPE debug) -set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0 -std=c++11") +set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wold-style-cast -std=gnu++0x") + +include_directories( +. +../.. +../../.. +${GTEST_DIR}/include +) -include_directories("../../") -include_directories("../../../") add_executable(image_test ../image.cpp image_test.cpp) -target_link_libraries(image_test -lpng -lSDL -lSDL_image) +target_link_libraries(image_test ${SDL_LIBRARY} ${SDLIMAGE_LIBRARY} ${PNG_LIBRARIES}) -add_executable(profile_test ../profile.cpp profile_test.cpp) +add_executable(profile_test ../profile.cpp ../logger.cpp profile_test.cpp) +target_link_libraries(profile_test gtest ${Boost_LIBRARIES}) add_test(profile_test ./profile_test) diff --git a/src/common/test/colobot.ini b/src/common/test/colobot.ini index f6a5f96..2ca37ee 100644 --- a/src/common/test/colobot.ini +++ b/src/common/test/colobot.ini @@ -8,8 +8,8 @@ string_value=Hello world int_value=42 [test_multi] -entry=1 -entry=2 -entry=3 -entry=4 -entry=5 +entry1=1 +entry2=2 +entry3=3 +entry4=4 +entry5=5 diff --git a/src/common/test/profile_test.cpp b/src/common/test/profile_test.cpp index 65e20c5..6236083 100644 --- a/src/common/test/profile_test.cpp +++ b/src/common/test/profile_test.cpp @@ -1,43 +1,44 @@ #include "../profile.h" +#include "../logger.h" #include #include #include +#include -using namespace std; -int main() +class CProfileTest : public testing::Test { - CProfile profile; - profile.InitCurrentDirectory(); // load colobot.ini file +protected: + CLogger m_logger; + CProfile m_profile; - string result; - profile.GetLocalProfileString("test_string", "string_value", result); - if (result != "Hello world") { - cout << "GetLocalProfileString failed!" << endl; - return 1; - } +}; + +TEST_F(CProfileTest, ReadTest) +{ + ASSERT_TRUE(m_profile.InitCurrentDirectory()); // load colobot.ini file + + std::string result; + ASSERT_TRUE(m_profile.GetLocalProfileString("test_string", "string_value", result)); + ASSERT_STREQ("Hello world", result.c_str()); int int_value; - profile.GetLocalProfileInt("test_int", "int_value", int_value); - if (int_value != 42) { - cout << "GetLocalProfileInt failed!" << endl; - return 1; - } + ASSERT_TRUE(m_profile.GetLocalProfileInt("test_int", "int_value", int_value)); + ASSERT_EQ(42, int_value); float float_value; - profile.GetLocalProfileFloat("test_float", "float_value", float_value); - if (float_value != 1.5) { - cout << "GetLocalProfileFloat failed!" << endl; - return 1; - } - - vector list; - list = profile.GetLocalProfileSection("test_multi", "entry"); - if (list.size() != 5) { - cout << "GetLocalProfileSection failed!" << endl; - return 1; - } - - return 0; + ASSERT_TRUE(m_profile.GetLocalProfileFloat("test_float", "float_value", float_value)); + ASSERT_FLOAT_EQ(1.5, float_value); + + std::vector list; + list = m_profile.GetLocalProfileSection("test_multi", "entry"); + ASSERT_EQ(5u, list.size()); } + +int main(int argc, char *argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + -- cgit v1.2.3-1-g7c22