mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 16:57:49 +03:00
80b1296a05
Summary: cpptoml has traversal functionality for table reads, but not for writes. Add a helper function for reading a config value and updating the TOML table if it's unset. Reviewed By: fanzeyi Differential Revision: D19671264 fbshipit-source-id: e2b78d338af35d51fddaa258b7f45f8966d00a26
99 lines
2.6 KiB
C++
99 lines
2.6 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This software may be used and distributed according to the terms of the
|
|
* GNU General Public License version 2.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cpptoml.h> // @manual=fbsource//third-party/cpptoml:cpptoml
|
|
#include <folly/Range.h>
|
|
#include <folly/String.h>
|
|
#include <glog/logging.h>
|
|
|
|
namespace facebook {
|
|
namespace eden {
|
|
|
|
class TomlPath {
|
|
public:
|
|
/*implicit*/ constexpr TomlPath(
|
|
std::initializer_list<folly::StringPiece> list)
|
|
: begin_{list.begin()}, end_{list.end()} {}
|
|
|
|
constexpr TomlPath(
|
|
const folly::StringPiece* begin,
|
|
const folly::StringPiece* end)
|
|
: begin_{begin}, end_{end} {}
|
|
|
|
constexpr const folly::StringPiece* begin() const {
|
|
return begin_;
|
|
}
|
|
|
|
constexpr const folly::StringPiece* end() const {
|
|
return end_;
|
|
}
|
|
|
|
constexpr size_t size() const {
|
|
return end_ - begin_;
|
|
}
|
|
|
|
private:
|
|
const folly::StringPiece* begin_;
|
|
const folly::StringPiece* end_;
|
|
};
|
|
|
|
/**
|
|
* Given a root toml table, walks the table path given by key, and sets it to
|
|
* defaultValue if not set.
|
|
*
|
|
* Returns a pair of the value at the given key (whether or not it was set) and
|
|
* a boolean indicating whether the table was modified.
|
|
*
|
|
* Throws std::domain_error if the path through `root` specified by `key`
|
|
* contains non-table values.
|
|
*/
|
|
template <typename T>
|
|
std::pair<T, bool>
|
|
setDefault(cpptoml::table& root, TomlPath key, const T& defaultValue) {
|
|
// TODO: Much of this function could be moved into the .cpp file.
|
|
DCHECK_GE(key.size(), 1);
|
|
|
|
auto begin = key.begin();
|
|
const auto end = key.end();
|
|
|
|
cpptoml::table* table = &root;
|
|
for (; begin + 1 < end; ++begin) {
|
|
auto keystr = begin->str();
|
|
if (table->contains(keystr)) {
|
|
auto entry = table->get(keystr);
|
|
if (entry->is_table()) {
|
|
table = static_cast<cpptoml::table*>(entry.get());
|
|
} else {
|
|
throw std::runtime_error(
|
|
folly::join(".", key.begin(), begin + 1) + " is not a table");
|
|
}
|
|
} else {
|
|
auto entry = cpptoml::make_table();
|
|
auto newtable = entry.get();
|
|
table->insert(keystr, std::move(entry));
|
|
table = newtable;
|
|
}
|
|
}
|
|
|
|
auto keystr = begin->str();
|
|
if (table->contains(keystr)) {
|
|
if (auto value = table->get(keystr)->as<T>()) {
|
|
return std::make_pair(value->get(), false);
|
|
} else {
|
|
throw std::runtime_error(
|
|
folly::join(".", key.begin(), key.end()) + " has mismatched type");
|
|
}
|
|
}
|
|
table->insert(begin->str(), defaultValue);
|
|
return std::make_pair(defaultValue, true);
|
|
}
|
|
|
|
} // namespace eden
|
|
} // namespace facebook
|