Skip to content

Instantly share code, notes, and snippets.

@dtoma
Created March 24, 2017 08:43
Show Gist options
  • Save dtoma/53cff994a7f2b2dfab9242c490876377 to your computer and use it in GitHub Desktop.
Save dtoma/53cff994a7f2b2dfab9242c490876377 to your computer and use it in GitHub Desktop.
ini configuration reader
#include <algorithm>
#include <optional>
#include <type_traits>
#include <unordered_map>
#include <vector>
#include <cstdio>
// http://tristanbrindle.com/posts/a-quicker-study-on-tokenising/
template <typename Iterator, typename Lambda>
void for_each_token(Iterator&& first, Iterator&& last, char separator, Lambda&& lambda) {
while (first != last) {
const auto pos = std::find(first, last, separator);
lambda(first, pos);
if (pos == last) {
break;
}
first = std::next(pos);
}
}
template<class T> struct always_false : std::false_type {};
struct Config {
std::unordered_map<std::string, std::string> config_values = {
{"foo", "bar"},
{"bar", "4242"},
{"array", "one,two,three,four"}
};
template <typename T>
std::optional<T> get(std::string const& key, std::optional<T> default_value = {}) {
if (this->config_values.find(key) != std::end(this->config_values)) {
if constexpr(std::is_same_v<T, int>) {
return std::stoi(this->config_values.at(key));
} else if constexpr(std::is_same_v<T, std::string>) {
return this->config_values.at(key);
} else if constexpr(std::is_same_v<T, std::vector<std::string>>) {
auto v = this->config_values.at(key);
std::vector<std::string> ret;
for_each_token(std::begin(v), std::end(v), ',', [&ret](auto begin, auto end) {
ret.emplace_back(begin, end);
});
return ret;
} else {
static_assert(always_false<T>::value, "supported types are int, std::string, std::vector<std::string>");
}
} else {
return default_value;
}
}
};
int main() {
Config c;
auto v = c.get<std::string>("foo");
printf("foo:%15s\n", v.value_or("No value found for this key").c_str());
auto v2 = c.get<int>("bar");
printf("bar:%15i\n", v2.value_or(0));
auto v3 = c.get<std::string>("doesnotexist", "defaultvalue");
printf("doesnotexist:%15s\n", v3.value_or("No value found for this key").c_str());
auto v4 = c.get<std::vector<std::string>>("array");
for (auto e : v4.value_or(std::vector<std::string>{})) {
printf("%s ", e.c_str());
} printf("\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment