aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclyne <clyne@bitgloo.com>2021-01-10 09:35:35 -0500
committerGitHub <noreply@github.com>2021-01-10 09:35:35 -0500
commit8fc7548c0330bfbf3860d4c0e8c17e20c37a3439 (patch)
treee7096bfb21eaa358829d87e4379667fd017ee052
parent6a5265be03640928f42e62c936cfb66fd3f0ea3a (diff)
Validate section tags; add cbegin, cend, and contains
-rw-r--r--ini_config.hpp60
1 files changed, 43 insertions, 17 deletions
diff --git a/ini_config.hpp b/ini_config.hpp
index b6af299..db30f0f 100644
--- a/ini_config.hpp
+++ b/ini_config.hpp
@@ -73,6 +73,8 @@ class ini_config
return in + 1;
}
+ // Validates INI syntax, returning the count of chars
+ // needed to store all section names, keys, and values
consteval static unsigned int verify_and_size() {
unsigned int sizechars = 0;
@@ -89,7 +91,10 @@ class ini_config
if (*p == '[') {
do {
++sizechars;
- } while (*++p != ']');
+ ++p;
+ } while (!iseol(*p) && *p != ']');
+ if (iseol(*p))
+ throw "Bad section tag!";
++sizechars; // Null terminator
continue;
}
@@ -130,6 +135,7 @@ class ini_config
return sizechars;
}
+ // Counts how many key-value pairs are in the text
consteval static unsigned int kvpcount() noexcept {
unsigned int count = 0;
@@ -148,6 +154,7 @@ class ini_config
return count;
}
+ // A compact buffer for section names, keys, and values
char_type kvp_buffer[verify_and_size() + 1] = {};
consteval void fill_kvp_buffer() noexcept {
@@ -209,8 +216,7 @@ public:
constexpr const auto& get_next() noexcept {
if (*m_pos == '\0') {
// At the end
- if (m_current.first != nullptr)
- m_current.first = nullptr;
+ m_current.first = nullptr;
} else {
// Enter new section(s) if necessary
while (*m_pos == '[') {
@@ -264,6 +270,10 @@ public:
}
};
+ /**
+ * Constructs the ini_config object, populating the section/key/value
+ * buffer.
+ */
consteval ini_config() noexcept
#ifdef TCSULLIVAN_INI_CONFIG_CHECK_FORWARD_ITERATOR
requires(std::forward_iterator<iterator>)
@@ -278,33 +288,42 @@ public:
consteval auto size() const noexcept {
return kvpcount();
}
+
constexpr auto begin() const noexcept {
return iterator(kvp_buffer);
}
+ constexpr auto cbegin() const noexcept {
+ return begin();
+ }
+ constexpr auto end() const noexcept {
+ return iterator(kvp_buffer + sizeof(kvp_buffer) / sizeof(char_type) - 1);
+ }
+ constexpr auto cend() const noexcept {
+ return end();
+ }
+
/**
* Returns beginning iterator for the given section.
*/
constexpr auto begin(const char_type *section) const noexcept {
- for (auto it = begin(); it != end(); ++it) {
+ auto it = begin();
+ do {
if (it->section != nullptr && stringmatch(it->section, section))
- return it;
- }
- return end();
- }
- constexpr auto end() const noexcept {
- return iterator(kvp_buffer + sizeof(kvp_buffer) / sizeof(char_type) - 1);
+ break;
+ } while (++it != end());
+ return it;
}
- /**
+
+ /**
* Returns end iterator for the given section.
*/
constexpr auto end(const char_type *section) const noexcept {
- for (auto it = begin(); it != end(); ++it) {
- if (it->section != nullptr && stringmatch(it->section, section)) {
- for (++it; it != end() && stringmatch(it->section, section); ++it);
- return it;
- }
+ auto it = begin(section);
+ while (++it != end()) {
+ if (!stringmatch(it->section, section))
+ break;
}
- return end();
+ return it;
}
class section_view {
@@ -357,6 +376,13 @@ public:
constexpr auto operator[](const char_type *key) const noexcept {
return get(key);
}
+
+ constexpr bool contains(const char_type *key) const noexcept {
+ return *get(key) != '\0';
+ }
+ constexpr bool contains(const char_type *sec, const char_type *key) const noexcept {
+ return *get(sec, key) != '\0';
+ }
};
} // namespace ini_config