From eb682c5700e7a9176d0104d470b83ff9aa3589e8 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Sun, 28 Apr 2019 19:08:26 -0400 Subject: util: Add ReadSettings and WriteSettings functions Currently unused, but includes tests. --- src/util/settings.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util/settings.h | 12 +++++++++++ 2 files changed, 69 insertions(+) (limited to 'src/util') diff --git a/src/util/settings.cpp b/src/util/settings.cpp index e4979df755..34894e994e 100644 --- a/src/util/settings.cpp +++ b/src/util/settings.cpp @@ -4,6 +4,7 @@ #include +#include #include namespace util { @@ -49,6 +50,62 @@ static void MergeSettings(const Settings& settings, const std::string& section, } } // namespace +bool ReadSettings(const fs::path& path, std::map& values, std::vector& errors) +{ + values.clear(); + errors.clear(); + + fsbridge::ifstream file; + file.open(path); + if (!file.is_open()) return true; // Ok for file not to exist. + + SettingsValue in; + if (!in.read(std::string{std::istreambuf_iterator(file), std::istreambuf_iterator()})) { + errors.emplace_back(strprintf("Unable to parse settings file %s", path.string())); + return false; + } + + if (file.fail()) { + errors.emplace_back(strprintf("Failed reading settings file %s", path.string())); + return false; + } + file.close(); // Done with file descriptor. Release while copying data. + + if (!in.isObject()) { + errors.emplace_back(strprintf("Found non-object value %s in settings file %s", in.write(), path.string())); + return false; + } + + const std::vector& in_keys = in.getKeys(); + const std::vector& in_values = in.getValues(); + for (size_t i = 0; i < in_keys.size(); ++i) { + auto inserted = values.emplace(in_keys[i], in_values[i]); + if (!inserted.second) { + errors.emplace_back(strprintf("Found duplicate key %s in settings file %s", in_keys[i], path.string())); + } + } + return errors.empty(); +} + +bool WriteSettings(const fs::path& path, + const std::map& values, + std::vector& errors) +{ + SettingsValue out(SettingsValue::VOBJ); + for (const auto& value : values) { + out.__pushKV(value.first, value.second); + } + fsbridge::ofstream file; + file.open(path); + if (file.fail()) { + errors.emplace_back(strprintf("Error: Unable to open settings file %s for writing", path.string())); + return false; + } + file << out.write(/* prettyIndent= */ 1, /* indentLevel= */ 4) << std::endl; + file.close(); + return true; +} + SettingsValue GetSetting(const Settings& settings, const std::string& section, const std::string& name, diff --git a/src/util/settings.h b/src/util/settings.h index 1d03639fa2..ee160e1ac8 100644 --- a/src/util/settings.h +++ b/src/util/settings.h @@ -5,6 +5,8 @@ #ifndef BITCOIN_UTIL_SETTINGS_H #define BITCOIN_UTIL_SETTINGS_H +#include + #include #include #include @@ -35,6 +37,16 @@ struct Settings { std::map>> ro_config; }; +//! Read settings file. +bool ReadSettings(const fs::path& path, + std::map& values, + std::vector& errors); + +//! Write settings file. +bool WriteSettings(const fs::path& path, + const std::map& values, + std::vector& errors); + //! Get settings value from combined sources: forced settings, command line //! arguments and the read-only config file. //! -- cgit v1.2.3