8 #include "configuration.h" 14 #include <unordered_map> 20 std::list<std::string> optionsOrder_;
21 std::unordered_map<std::string, OptionBase *> options_;
24 Configuration::Configuration()
25 : d_ptr(std::make_unique<ConfigurationPrivate>()) {}
27 Configuration::~Configuration() =
default;
29 void Configuration::dumpDescription(
RawConfig &config)
const {
30 return dumpDescriptionImpl(config, {});
33 void Configuration::dumpDescriptionImpl(
34 RawConfig &config,
const std::vector<std::string> &parentPaths)
const {
36 auto fullpaths = parentPaths;
37 fullpaths.push_back(typeName());
39 std::shared_ptr<RawConfig> subRoot = config.get(pathString,
true);
41 std::tuple<std::vector<std::string>, std::unique_ptr<Configuration>>>
43 for (
const auto &path : d->optionsOrder_) {
44 auto optionIter = d->options_.find(path);
45 assert(optionIter != d->options_.end());
46 auto *option = optionIter->second;
47 if (option->skipDescription()) {
50 auto descConfigPtr = subRoot->get(option->path(),
true);
51 option->dumpDescription(*descConfigPtr);
53 auto subConfig = option->subConfigSkeleton();
55 auto subConfigPath = parentPaths;
56 subConfigPath.push_back(option->path());
57 std::string subTypeName = subConfig->typeName();
58 const auto *oldTypeName = descConfigPtr->valueByPath(
"Type");
63 auto newTypeName = oldTypeName->substr(
64 0, oldTypeName->size() - subTypeName.size());
66 newTypeName.append(
"$");
67 newTypeName.append(subTypeName);
68 descConfigPtr->setValueByPath(
"Type", std::move(newTypeName));
70 subConfigs.emplace_back(subConfigPath, std::move(subConfig));
75 for (
const auto &[subConfigPath, subConfigPtr] : subConfigs) {
76 subConfigPtr->dumpDescriptionImpl(config, subConfigPath);
80 bool Configuration::compareHelper(
const Configuration &other)
const {
83 d->optionsOrder_.begin(), d->optionsOrder_.end(),
84 [d, &other](
const auto &path) {
85 auto optionIter = d->options_.find(path);
86 assert(optionIter != d->options_.end());
87 auto otherOptionIter = other.d_func()->options_.find(path);
88 assert(otherOptionIter != other.d_func()->options_.end());
89 return *optionIter->second == *otherOptionIter->second;
96 for (
const auto &path : d->optionsOrder_) {
97 auto optionIter = d->options_.find(path);
98 assert(optionIter != d->options_.end());
99 auto otherOptionIter = other.d_func()->options_.find(path);
100 assert(otherOptionIter != other.d_func()->options_.end());
101 optionIter->second->copyFrom(*otherOptionIter->second);
107 for (
const auto &path : d->optionsOrder_) {
108 auto subConfigPtr = config.get(path);
109 auto *option = d->options_[path];
116 if (!option->unmarshall(*subConfigPtr, partial)) {
122 void Configuration::save(
RawConfig &config)
const {
124 for (
const auto &path : d->optionsOrder_) {
125 auto iter = d->options_.find(path);
126 assert(iter != d->options_.end());
127 if (iter->second->skipSave()) {
130 auto subConfigPtr = config.get(path,
true);
131 iter->second->marshall(*subConfigPtr);
132 subConfigPtr->setComment(iter->second->description());
136 void Configuration::addOption(
OptionBase *option) {
138 if (d->options_.count(option->path())) {
139 throw std::logic_error(
"Duplicate option path");
142 d->optionsOrder_.push_back(option->path());
143 d->options_[option->path()] = option;
148 for (
const auto &path : d->optionsOrder_) {
149 auto iter = d->options_.find(path);
150 assert(iter != d->options_.end());
154 if (
auto *optionV3 = dynamic_cast<OptionBaseV3 *>(iter->second)) {
155 optionV3->syncDefaultValueToCurrent();
156 }
else if (
auto *optionV2 =
157 dynamic_cast<OptionBaseV2 *>(iter->second)) {
158 optionV2->syncDefaultValueToCurrent();
bool endsWith(std::string_view str, std::string_view suffix)
Check if a string ends with a suffix.
void load(const RawConfig &config, bool partial=false)
Load configuration from RawConfig.
void syncDefaultValueToCurrent()
Set default value to current value.
std::string join(Iter start, Iter end, T &&delim)
Join a range of string with delim.