17#ifndef TOOLBOX_UTIL_CONFIG_HPP
18#define TOOLBOX_UTIL_CONFIG_HPP
22#pragma GCC diagnostic push
23#pragma GCC diagnostic ignored "-Wstrict-aliasing"
24#include <boost/container/flat_map.hpp>
25#pragma GCC diagnostic pop
30inline namespace util {
32template <
typename FnT>
36 while (std::getline(
is,
line)) {
42 if (
line.empty() ||
line[0] ==
'#') {
46 if (
line.front() ==
'[' &&
line.back() ==
']') {
48 name->assign(
line, 1,
line.size() - 2);
81 const
std::
string& get(const
std::
string& key) const;
82 const
char* get(const
std::
string& key, const
char* dfl) const noexcept;
83 const
char* get(const
std::
string& key,
std::nullptr_t) const noexcept
85 return get(key,
static_cast<const char*
>(
nullptr));
88 template <
typename ValueT>
89 ValueT
get(
const std::string& key)
const
91 const auto it{map_.find(key)};
92 if (it != map_.end()) {
93 if constexpr (std::is_same_v<ValueT, std::string_view>) {
96 return std::string_view{it->second};
97 }
else if constexpr (std::is_enum_v<ValueT>) {
98 return ValueT{from_string<std::underlying_type_t<ValueT>>(it->second)};
100 return from_string<ValueT>(it->second);
104 throw std::runtime_error{std::string{
"missing config key: "} + key};
106 return parent_->get<ValueT>(key);
108 template <
typename ValueT>
109 ValueT
get(
const std::string& key, ValueT dfl)
const noexcept
111 const auto it{map_.find(key)};
112 if (it != map_.end()) {
113 if constexpr (std::is_same_v<ValueT, std::string_view>) {
116 return std::string_view{it->second};
117 }
else if constexpr (std::is_enum_v<ValueT>) {
118 return ValueT{from_string<std::underlying_type_t<ValueT>>(it->second)};
120 return from_string<ValueT>(it->second);
123 return parent_ ? parent_->get<ValueT>(key, dfl) : dfl;
125 std::size_t
size() const noexcept {
return map_.size(); }
126 void clear() noexcept { map_.clear(); }
131 return read_section(is, &next);
135 return read_section(is, next);
137 void set(std::string key, std::string val)
139 map_.insert_or_assign(std::move(key), std::move(val));
144 std::istream& read_section(std::istream& is, std::string* next);
145 std::map<std::string, std::string> map_;
162 void clear() noexcept;
163 void read(
std::istream& is);
169 auto it = map_.find(name);
170 return it != map_.end() ? it->second : root_;
174 return section(std::string{name});
180 std::map<std::string, Config> map_;