1 | // SPDX-License-Identifier: GPL-3.0-or-later |
---|---|
2 | |
3 | #include "libconfig/libconfig.h" |
4 | |
5 | #include <fstream> |
6 | #include <iostream> |
7 | |
8 | std::optional<Config> Config::from_file(const std::string &filepath) |
9 | { |
10 | std::fstream f(filepath, f.in); |
11 | if (!f) |
12 | return std::nullopt; |
13 | |
14 | Config config; |
15 | |
16 | Config::SectionType current_section = std::make_pair(x: "global", y: Config::SectionContentType{}); |
17 | for (std::string line; std::getline(is&: f, str&: line);) |
18 | { |
19 | if (line.empty()) |
20 | continue; |
21 | |
22 | if (line.starts_with(x: '#')) |
23 | continue; |
24 | |
25 | if (line.starts_with(x: '[') && line.ends_with(x: ']')) |
26 | { |
27 | // a new section |
28 | config.sections.push_back(x: current_section); |
29 | current_section = std::make_pair(x: line.substr(pos: 1, n: line.size() - 2), y: Config::SectionContentType{}); // remove the brackets |
30 | } |
31 | else |
32 | { |
33 | // a key-value pair |
34 | size_t pos = line.find(c: '='); |
35 | if (pos == std::string::npos) |
36 | { |
37 | std::cerr << "Invalid line: "<< line << std::endl; |
38 | continue; |
39 | } |
40 | |
41 | std::string key = line.substr(pos: 0, n: pos); |
42 | std::string value = line.substr(pos: pos + 1); |
43 | |
44 | const auto remove_leading_trailing_spaces = [](std::string &str) |
45 | { |
46 | while (!str.empty() && str.front() == ' ') |
47 | str.erase(pos: 0, n: 1); |
48 | while (!str.empty() && str.back() == ' ') |
49 | str.pop_back(); |
50 | }; |
51 | |
52 | remove_leading_trailing_spaces(key); |
53 | remove_leading_trailing_spaces(value); |
54 | |
55 | current_section.second.push_back(x: { key, value }); |
56 | } |
57 | } |
58 | |
59 | config.sections.push_back(x: current_section); |
60 | |
61 | return config; |
62 | } |
63 | |
64 | std::optional<Config::SectionType> Config::get_section(const std::string §ion_name) const |
65 | { |
66 | for (const auto §ion : sections) |
67 | if (section.first == section_name) |
68 | return section; |
69 | |
70 | return std::nullopt; |
71 | } |
72 | |
73 | std::vector<Config::EntryType> Config::get_entry(const std::string §ion_name, const std::string &key) const |
74 | { |
75 | auto entries = get_section(section_name); |
76 | if (!entries) |
77 | return {}; |
78 | return entries->second | std::ranges::views::filter([&key](const auto &entry) { return entry.first == key; }) | std::ranges::to<std::vector<EntryType>>(); |
79 | } |
80 | |
81 | std::vector<Config::EntryType> Config::get_entries(const std::string §ion_name) const |
82 | { |
83 | auto entries = get_section(section_name); |
84 | if (!entries) |
85 | return {}; |
86 | return entries->second; |
87 | } |
88 |