From e5809ca41c81750dbf59c2b170328df892a69e26 Mon Sep 17 00:00:00 2001
From: Aqua-sama <aqua@iserlohn-fortress.net>
Date: Sun, 4 Oct 2020 13:40:20 +0300
Subject: Remove outparam section in Configuration parse

---
 lib/configuration/configuration.cpp | 84 ++++++++++++++++++++++++-------------
 lib/configuration/configuration.h   |  4 +-
 2 files changed, 58 insertions(+), 30 deletions(-)

(limited to 'lib')

diff --git a/lib/configuration/configuration.cpp b/lib/configuration/configuration.cpp
index 6e479f4..66617ed 100644
--- a/lib/configuration/configuration.cpp
+++ b/lib/configuration/configuration.cpp
@@ -27,12 +27,12 @@ Configuration::Configuration()
     }
 }
 
-Configuration::Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> l) noexcept
+Configuration::Configuration(const std::initializer_list<std::pair<std::string, conf_value_t>> &list) noexcept
 #ifndef NO_QT_SPEC
     : m_homePath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString())
 #endif
 {
-    for(const auto &i : l) {
+    for(const auto &i : list) {
         insert_or_assign(i.first, i.second);
     }
 }
@@ -53,20 +53,36 @@ inline auto strip(std::string &value)
     return value;
 }
 
-inline auto parse(const std::string &line, std::string &section)
+enum parse_result {
+    None,
+    Pair,
+    Section,
+    Include,
+};
+
+inline auto parse(const std::string &line, const std::string &section)
 {
     struct {
-        bool pair = false;
+        parse_result result = None;
         std::string key;
         std::string value;
     } ret;
 
-    if(line[0] == '#' || line.length() == 0) {
+    if(line.front() == '#' || line.length() == 0) {
+        return ret;
+    }
+
+    if(line.starts_with("@@")) {
+        if(line.starts_with("@@include ")) {
+            ret.result = parse_result::Include;
+            ret.key = line.substr(10);
+        }
         return ret;
     }
 
     if(line.front() == '[' && line.back() == ']') {
-        section = line.substr(1, line.length() - 2) + '/';
+        ret.result = parse_result::Section;
+        ret.key = line.substr(1, line.length() - 2) + '/';
         return ret;
     }
 
@@ -85,7 +101,7 @@ inline auto parse(const std::string &line, std::string &section)
     ret.value = line.substr(pos + 1);
     strip(ret.value);
 
-    ret.pair = true;
+    ret.result = parse_result::Pair;
     return ret;
 }
 
@@ -103,30 +119,40 @@ void Configuration::read(std::basic_istream<char> &input)
     std::string line, section;
 
     while(std::getline(input, line)) {
-        if(line.rfind("@@") == 0) {
-            if(line.rfind("@@include ") == 0) {
-                read_file(line.substr(10));
-            }
-            continue;
+        const auto p = parse(line, section);
+        switch(p.result) {
+        case parse_result::None:
+            break;
+        case parse_result::Section:
+            section = p.key;
+            break;
+        case parse_result::Include:
+            read_file(p.key);
+            break;
+        case parse_result::Pair:
+            setValue(p.key, p.value);
+            break;
         }
+    }
+}
+
+void Configuration::setValue(const std::string &key, const std::string &value)
+{
+    if(use_global) {
+        s_conf->setValue(key, value);
+        return;
+    }
 
-        const auto pair = parse(line, section);
-        if(pair.pair) {
-
-            if(this->count(pair.key) == 0) {
-                // no type has been specified for this key, assuming std::string
-                insert(std::make_pair(pair.key, pair.value));
-                continue;
-            }
-
-            auto v = at(pair.key);
-            if(std::holds_alternative<std::string>(v)) {
-                at(pair.key) = pair.value;
-            } else if(std::holds_alternative<int>(v)) {
-                at(pair.key) = std::stoi(pair.value);
-            } else if(std::holds_alternative<bool>(v)) {
-                at(pair.key) = (pair.value == "true");
-            }
+    if(this->count(key) == 0) {
+        insert(std::make_pair(key, value));
+    } else {
+        auto v = at(key);
+        if(std::holds_alternative<std::string>(v)) {
+            at(key) = value;
+        } else if(std::holds_alternative<int>(v)) {
+            at(key) = std::stoi(value);
+        } else if(std::holds_alternative<bool>(v)) {
+            at(key) = (value == "true");
         }
     }
 }
diff --git a/lib/configuration/configuration.h b/lib/configuration/configuration.h
index c2400b6..af55f62 100644
--- a/lib/configuration/configuration.h
+++ b/lib/configuration/configuration.h
@@ -40,7 +40,7 @@ class consumable(unconsumed) Configuration : private std::unordered_map<std::str
 
 public:
     return_typestate(unconsumed) Configuration();
-    return_typestate(unconsumed) Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> l) noexcept;
+    return_typestate(unconsumed) Configuration(const std::initializer_list<std::pair<std::string, conf_value_t>> &list) noexcept;
 
     Configuration(const Configuration &) = delete;
     Configuration &operator=(const Configuration &) = delete;
@@ -126,6 +126,8 @@ public:
         return T{};
     }
 
+    callable_when(unconsumed) void setValue(const std::string &key, const std::string &value);
+
     bool make_global();
 
 private:
-- 
cgit v1.2.1