src/Config/README.md
A cross-platform library that provides a simple API to read and write INI-style configuration files. It supports data files in ASCII, MBCS and Unicode. It is designed explicitly to be portable to any platform and has been tested on Windows, WinCE and Linux. Released as open-source and free using the MIT licence.
Full documentation of the interface is available in doxygen format. See latest documentation here.
SimpleIni is a header-only library. No building is required to use it in your project.
Simply include SimpleIni.h in your source files:
#include "SimpleIni.h"
That's it! The library is ready to use.
While the library itself doesn't require building, you can build and run the test suite using CMake.
# Configure the project
cmake -S . -B build
# Build the tests (optional)
cmake --build build
# To build without tests
cmake -S . -B build -DBUILD_TESTING=OFF
cmake --build build
# Run all tests
cd build
ctest --verbose
To use SimpleIni in your CMake project:
# Add SimpleIni as a subdirectory
add_subdirectory(simpleini)
# Link against your target
target_link_libraries(your_target PRIVATE SimpleIni::SimpleIni)
Or install it system-wide:
cmake -S . -B build
cmake --build build
sudo cmake --install build
Then in your CMake project:
find_package(SimpleIni REQUIRED)
target_link_libraries(your_target PRIVATE SimpleIni::SimpleIni)
Note that the ConvertUTF.* files are required ONLY if you use SI_CONVERT_GENERIC. This is not the default. If you do use this mode, you will need to manually copy or include the files from the SimpleIni source directory.
These snippets are included with the distribution in the automatic tests as ts-snippets.cpp.
// simple demonstration
CSimpleIniA ini;
ini.SetUnicode();
SI_Error rc = ini.LoadFile("example.ini");
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_OK);
const char* pv;
pv = ini.GetValue("section", "key", "default");
ASSERT_STREQ(pv, "value");
ini.SetValue("section", "key", "newvalue");
pv = ini.GetValue("section", "key", "default");
ASSERT_STREQ(pv, "newvalue");
// load from a data file
CSimpleIniA ini;
SI_Error rc = ini.LoadFile("example.ini");
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_OK);
// load from a string
const std::string example = "[section]\nkey = value\n";
CSimpleIniA ini;
SI_Error rc = ini.LoadData(example);
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_OK);
// get all sections
CSimpleIniA::TNamesDepend sections;
ini.GetAllSections(sections);
// get all keys in a section
CSimpleIniA::TNamesDepend keys;
ini.GetAllKeys("section1", keys);
// get the value of a key that doesn't exist
const char* pv;
pv = ini.GetValue("section1", "key99");
ASSERT_EQ(pv, nullptr);
// get the value of a key that does exist
pv = ini.GetValue("section1", "key1");
ASSERT_STREQ(pv, "value1");
// get the value of a key which may have multiple
// values. If hasMultiple is true, then there are
// multiple values and just one value has been returned
bool hasMulti;
pv = ini.GetValue("section1", "key1", nullptr, &hasMulti);
ASSERT_STREQ(pv, "value1");
ASSERT_EQ(hasMulti, false);
pv = ini.GetValue("section1", "key2", nullptr, &hasMulti);
ASSERT_STREQ(pv, "value2.1");
ASSERT_EQ(hasMulti, true);
// get all values of a key with multiple values
CSimpleIniA::TNamesDepend values;
ini.GetAllValues("section1", "key2", values);
// sort the values into a known order, in this case we want
// the original load order
values.sort(CSimpleIniA::Entry::LoadOrder());
// output all of the items
CSimpleIniA::TNamesDepend::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) {
printf("value = '%s'\n", it->pItem);
}
// add a new section
rc = ini.SetValue("section1", nullptr, nullptr);
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_INSERTED);
// not an error to add one that already exists
rc = ini.SetValue("section1", nullptr, nullptr);
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_UPDATED);
// get the value of a key that doesn't exist
const char* pv;
pv = ini.GetValue("section2", "key1", "default-value");
ASSERT_STREQ(pv, "default-value");
// adding a key (the section will be added if needed)
rc = ini.SetValue("section2", "key1", "value1");
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_INSERTED);
// ensure it is set to expected value
pv = ini.GetValue("section2", "key1", nullptr);
ASSERT_STREQ(pv, "value1");
// change the value of a key
rc = ini.SetValue("section2", "key1", "value2");
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_UPDATED);
// ensure it is set to expected value
pv = ini.GetValue("section2", "key1", nullptr);
ASSERT_STREQ(pv, "value2");
// deleting a key from a section. Optionally the entire
// section may be deleted if it is now empty.
bool done, deleteSectionIfEmpty = true;
done = ini.Delete("section1", "key1", deleteSectionIfEmpty);
ASSERT_EQ(done, true);
done = ini.Delete("section1", "key1");
ASSERT_EQ(done, false);
// deleting an entire section and all keys in it
done = ini.Delete("section2", nullptr);
ASSERT_EQ(done, true);
done = ini.Delete("section2", nullptr);
ASSERT_EQ(done, false);
// save the data to a string
std::string data;
rc = ini.Save(data);
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_OK);
// save the data back to the file
rc = ini.SaveFile("example2.ini");
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_OK);