15 #include "fcitx-utils/macros.h" 16 #include "fcitx-utils/misc_p.h" 23 :
QPtrHolder(q), name_(std::move(_name)), lineNumber_(0),
26 :
QPtrHolder(q), value_(other.value_), comment_(other.comment_),
27 lineNumber_(other.lineNumber_), implicit_(other.implicit_) {}
36 auto value = other.value_;
37 auto comment = other.comment_;
38 auto lineNumber = other.lineNumber_;
39 auto implicit = other.implicit_;
40 OrderedMap<std::string, std::shared_ptr<RawConfig>> newSubItems;
41 for (
const auto &item : other.subItems_) {
42 auto result = newSubItems[item.first] =
43 q_func()->createSub(item.second->name());
44 *result = *item.second;
46 value_ = std::move(value);
47 comment_ = std::move(comment);
48 lineNumber_ = lineNumber;
51 subItems_ = std::move(newSubItems);
55 std::shared_ptr<RawConfig> getNonexistentRawConfig(
RawConfig *q,
56 const std::string &key) {
57 auto result = subItems_[key] = q->createSub(key);
61 static std::shared_ptr<const RawConfig>
62 getNonexistentRawConfig(
const RawConfig * ,
63 const std::string & ) {
67 template <
typename T,
typename U>
68 static std::shared_ptr<T>
69 getRawConfigHelper(T &that,
const std::string &path, U callback) {
71 std::shared_ptr<T> result;
72 for (std::string::size_type pos = 0, new_pos = path.find(
'/', pos);
73 pos != std::string::npos && cur;
74 pos = ((std::string::npos == new_pos) ? new_pos : (new_pos + 1)),
75 new_pos = path.find(
'/', pos)) {
76 auto key = path.substr(pos, (std::string::npos == new_pos)
79 auto iter = cur->d_func()->subItems_.find(key);
80 if (iter == cur->d_func()->subItems_.end()) {
81 result = cur->d_func()->getNonexistentRawConfig(cur, key);
83 result = iter->second;
88 callback(*cur, path.substr(0, new_pos));
97 std::function<
bool(T &,
const std::string &path)> callback,
98 bool recursive,
const std::string &pathPrefix) {
99 auto d = that.d_func();
100 for (
const auto &pair : d->subItems_) {
101 std::shared_ptr<T> item = pair.second;
102 auto newPathPrefix = pathPrefix.empty()
104 : pathPrefix +
"/" + item->name();
105 if (!callback(*item, newPathPrefix)) {
109 if (!visitHelper(*item, callback, recursive, newPathPrefix)) {
117 void detachSubItems() {
118 for (
const auto &pair : subItems_) {
119 pair.second->d_func()->parent_ =
nullptr;
124 const std::string name_;
126 std::string comment_;
127 OrderedMap<std::string, std::shared_ptr<RawConfig>> subItems_;
128 unsigned int lineNumber_;
135 : d_ptr(std::make_unique<RawConfigPrivate>(
this, std::move(name))) {}
137 RawConfig::~RawConfig() {
143 : d_ptr(std::make_unique<RawConfigPrivate>(
this, *other.d_ptr)) {
144 for (
const auto &item : other.d_func()->subItems_) {
145 *
get(item.first,
true) = *item.second;
149 *d_ptr = *other.d_ptr;
155 auto dummy = [](
const RawConfig &,
const std::string &) {};
157 return RawConfigPrivate::getRawConfigHelper(*
this, path, dummy);
159 return std::const_pointer_cast<
RawConfig>(
160 RawConfigPrivate::getRawConfigHelper<const RawConfig>(*
this, path,
165 auto dummy = [](
const RawConfig &,
const std::string &) {};
166 return RawConfigPrivate::getRawConfigHelper(*
this, path, dummy);
170 auto pos = path.rfind(
'/');
172 if (pos == 0 || pos + 1 == path.size()) {
176 if (pos != std::string::npos) {
177 root =
get(path.substr(0, pos)).
get();
179 return root->d_func()->subItems_.erase(path.substr(pos + 1)) > 0;
184 d->subItems_.clear();
189 d->value_ = std::move(value);
194 d->comment_ = std::move(comment);
204 d->implicit_ = implicit;
224 return d->lineNumber_;
245 return !d->subItems_.empty();
250 return d->subItems_.size();
255 std::vector<std::string> result;
256 result.reserve(d->subItems_.size());
257 for (
const auto &pair : d->subItems_) {
258 result.push_back(pair.first);
273 auto ref = d->parent_->get(d->name_);
274 d->parent_->d_func()->subItems_.erase(d->name_);
275 d->parent_ =
nullptr;
280 std::function<
bool(
RawConfig &,
const std::string &path)> callback,
281 const std::string &path,
bool recursive,
const std::string &pathPrefix) {
283 std::shared_ptr<RawConfig> subItem;
286 root = subItem.get();
293 return RawConfigPrivate::visitHelper(*root, std::move(callback), recursive,
298 std::function<
bool(
const RawConfig &,
const std::string &path)> callback,
299 const std::string &path,
bool recursive,
300 const std::string &pathPrefix)
const {
301 const auto *root =
this;
302 std::shared_ptr<const RawConfig> subItem;
305 root = subItem.get();
312 return RawConfigPrivate::visitHelper(*root, std::move(callback), recursive,
317 std::function<
void(
RawConfig &,
const std::string &path)> callback,
318 const std::string &path) {
319 RawConfigPrivate::getRawConfigHelper(*
this, path, std::move(callback));
322 std::function<
void(
const RawConfig &,
const std::string &path)> callback,
323 const std::string &path)
const {
324 RawConfigPrivate::getRawConfigHelper(*
this, path, std::move(callback));
327 std::shared_ptr<RawConfig> RawConfig::createSub(std::string name) {
335 return std::make_shared<RawSubConfig>(
this, std::move(name));
339 log <<
"RawConfig(=" << config.
value();
341 [&log](
const RawConfig &subConfig,
const std::string &path) {
342 log <<
", " << path <<
"=" << subConfig.
value();
RawConfig & operator=(std::string value)
Assign a string value to this node.
RawConfig()
Construct a RawConfig with an empty name.
void setLineNumber(unsigned int lineNumber)
Set the line number where this node was parsed from.
const std::string & name() const
Get the name of this node.
const std::string & comment() const
Get the comment for this node.
bool hasSubItems() const
Check if this node has any sub-items.
void setComment(std::string comment)
Set the comment for this node.
A raw configuration tree that stores key-value pairs in a hierarchical structure. ...
unsigned int lineNumber() const
Get the line number where this node was parsed from.
std::shared_ptr< RawConfig > get(const std::string &path, bool create=false)
Get a sub-item by path.
bool isImplicit() const
Check if this node or any of its ancestors is marked as implicit.
void removeAll()
Remove all sub-items.
std::vector< std::string > subItems() const
Get a list of sub-item names.
void visitItemsOnPath(std::function< void(RawConfig &, const std::string &path)> callback, const std::string &path)
Visit all items on a path.
bool isImplicitSelf() const
Check if this node itself is marked as implicit.
void setImplicit(bool implicit)
Mark this config node as implicit (default value that won't be written to INI).
bool visitSubItems(std::function< bool(RawConfig &, const std::string &path)> callback, const std::string &path="", bool recursive=false, const std::string &pathPrefix="")
Visit all sub-items.
size_t subItemsSize() const
Get the number of sub-items.
RawConfig * parent() const
Get the parent node.
void setValue(std::string value)
Set the value of this node.
const std::string & value() const
Get the value of this node.
bool remove(const std::string &path)
Remove a sub-item by path.
std::shared_ptr< RawConfig > detach()
Detach this node from its parent.