Table of Contents
ini
is a simple and easy to use ini file
parser for C++.
-
Does not depend on any type and does not assume the type of data passed in by the user.
-
Supports writing the read data back to the file without losing the original comments of the file.
-
Supports writing data back to the file in the order it was read. (Newly added data is not guaranteed.)
The front-end implementation of the parser is based on the lexy implementation.
struct string_hasher
{
using is_transparent = int;
template<typename String>
[[nodiscard]] constexpr auto operator()(const String& string) const noexcept -> std::size_t
{
if constexpr (std::is_array_v<String>)
{
return std::hash<std::basic_string_view<typename std::pointer_traits<std::decay_t<String>>::element_type>>{}(string);
}
else if constexpr (std::is_pointer_v<String>)
{
return std::hash<std::basic_string_view<typename std::pointer_traits<String>::element_type>>{}(string);
}
else if constexpr (requires { std::hash<String>{}; })
{
return std::hash<String>{}(string);
}
else
{
[]<bool always_false = false> { static_assert(always_false, "Unsupported hash type!"); }
();
}
}
};
using group_type = std::unordered_map<std::string, std::string, string_hasher, std::equal_to<>>;
using context_type = std::unordered_map<std::string, group_type, string_hasher, std::equal_to<>>;
auto [extract_result, data] = ini::extract_from_file<context_type>("config.ini");
assert(extract_result == ini::ExtractResult::SUCCESS);
assert(not data["properties"].empty());
using group_type = std::unordered_map<std::string, std::string, string_hasher, std::equal_to<>>;
using context_type = std::unordered_map<std::string, group_type, string_hasher, std::equal_to<>>;
std::ifstream file{"config.ini", std::ios::in};
expect((file.is_open()) >> fatal);
std::string buffer{};
file.seekg(0, std::ios::end);
buffer.reserve(file.tellg());
file.seekg(0, std::ios::beg);
buffer.assign(
std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>());
auto [extract_result, data] = ini::extract_from_buffer<context_type>(buffer);
assert(extract_result == ini::ExtractResult::SUCCESS);
assert(not data["properties"].empty());
using group_type = std::unordered_map<std::string, std::string, string_hasher, std::equal_to<>>;
using context_type = std::unordered_map<std::string, group_type, string_hasher, std::equal_to<>>;
context_type data{};
// read data...
using key_type = context_type::key_type;
using char_type = typename ini::string_view_t<key_type>::value_type;
class MyOut final : public ini::UserOut<char_type>
{
public:
using out_type = key_type;
private:
out_type& out_;
public:
explicit MyOut(out_type& out) : out_{out} {}
/* constexpr */ auto operator<<(const char_type d) -> UserOut& override
{
out_.push_back(d);
return *this;
}
/* constexpr */ auto operator<<(const std::basic_string_view<char_type> d) -> UserOut& override
{
out_.append(d);
return *this;
}
};
key_type buffer{};
MyOut out{buffer};
// The file path is optional, if the file exists, write `out` in the order of the content in the file, otherwise the writing order is not guaranteed.(depends on the order of `context_type)
ini::flush_to_user("config.ini", data, out);
assert(not buffer.empty());
See LICENSE.