Fcitx
rawconfig.h
1 /*
2  * SPDX-FileCopyrightText: 2015-2015 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 #ifndef _FCITX_CONFIG_RAWCONFIG_H_
8 #define _FCITX_CONFIG_RAWCONFIG_H_
9 
10 #include <cstddef>
11 #include <functional>
12 #include <memory>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 #include <fcitx-config/fcitxconfig_export.h>
17 #include <fcitx-utils/log.h>
18 #include <fcitx-utils/macros.h>
19 
20 namespace fcitx {
21 
22 class RawConfig;
23 
24 /** Shared pointer type for RawConfig. */
25 using RawConfigPtr = std::shared_ptr<RawConfig>;
26 
27 class RawConfigPrivate;
28 /**
29  * A raw configuration tree that stores key-value pairs in a hierarchical
30  * structure.
31  *
32  * RawConfig represents a configuration as a tree of nodes, where each node
33  * can have a value and sub-items. For example, It supports reading from and
34  * writing to INI format, and can represent configuration with implicit
35  * (default) values.
36  */
37 class FCITXCONFIG_EXPORT RawConfig {
38 public:
39  /** Construct a RawConfig with an empty name. */
40  RawConfig();
41  FCITX_DECLARE_VIRTUAL_DTOR_COPY(RawConfig)
42 
43  /**
44  * Get a sub-item by path.
45  *
46  * @param path path to the sub-item, using '/' as separator
47  * @param create if true, create intermediate nodes if they don't exist
48  * @return shared pointer to the sub-item, or nullptr if not found and
49  * create is false
50  */
51  std::shared_ptr<RawConfig> get(const std::string &path,
52  bool create = false);
53  /** @overload */
54  std::shared_ptr<const RawConfig> get(const std::string &path) const;
55 
56  /**
57  * Remove a sub-item by path.
58  *
59  * @param path path to the item to remove
60  * @return true if the item was removed, false if not found or invalid path
61  */
62  bool remove(const std::string &path);
63 
64  /** Remove all sub-items. */
65  void removeAll();
66 
67  /**
68  * Set the value of this node.
69  *
70  * @param value the value to set
71  */
72  void setValue(std::string value);
73 
74  /**
75  * Set the comment for this node.
76  *
77  * @param comment the comment to set
78  */
79  void setComment(std::string comment);
80 
81  /**
82  * Set the line number where this node was parsed from.
83  *
84  * @param lineNumber the line number
85  */
86  void setLineNumber(unsigned int lineNumber);
87 
88  /**
89  * Mark this config node as implicit (default value that won't be written
90  * to INI).
91  *
92  * @param implicit true to mark as implicit, false otherwise
93  *
94  * @since 5.1.22
95  */
96  void setImplicit(bool implicit);
97 
98  /** Get the name of this node. */
99  const std::string &name() const;
100 
101  /** Get the comment for this node. */
102  const std::string &comment() const;
103 
104  /** Get the value of this node. */
105  const std::string &value() const;
106 
107  /** Get the line number where this node was parsed from. */
108  unsigned int lineNumber() const;
109 
110  /**
111  * Check if this node itself is marked as implicit.
112  *
113  * @return true if this node is marked as implicit
114  *
115  * @since 5.1.22
116  */
117  bool isImplicitSelf() const;
118 
119  /**
120  * Check if this node or any of its ancestors is marked as implicit.
121  *
122  * @return true if this node or any ancestor is marked as implicit
123  *
124  * @since 5.1.22
125  */
126  bool isImplicit() const;
127 
128  /**
129  * Check if this node has any sub-items.
130  *
131  * @return true if this node has sub-items
132  */
133  bool hasSubItems() const;
134 
135  /**
136  * Get the number of sub-items.
137  *
138  * @return number of sub-items
139  */
140  size_t subItemsSize() const;
141 
142  /**
143  * Get a list of sub-item names.
144  *
145  * @return list of sub-item names
146  */
147  std::vector<std::string> subItems() const;
148 
149  /**
150  * Set a value by path, creating intermediate nodes if needed.
151  *
152  * @param path path to the value, using '/' as separator
153  * @param value the value to set
154  */
155  void setValueByPath(const std::string &path, std::string value) {
156  (*this)[path] = std::move(value);
157  }
158 
159  /**
160  * Get a value by path.
161  *
162  * @param path path to the value, using '/' as separator
163  * @return pointer to the value, or nullptr if not found
164  */
165  const std::string *valueByPath(const std::string &path) const {
166  auto config = get(path);
167  return config ? &config->value() : nullptr;
168  }
169 
170  /**
171  * Get or create a sub-item by path.
172  *
173  * @param path path to the sub-item, using '/' as separator
174  * @return reference to the sub-item
175  */
176  RawConfig &operator[](const std::string &path) { return *get(path, true); }
177 
178  /**
179  * Assign a string value to this node.
180  *
181  * @param value the value to assign
182  * @return reference to this node
183  */
184  RawConfig &operator=(std::string value) {
185  setValue(std::move(value));
186  return *this;
187  }
188 
189  /**
190  * Check if two RawConfig trees are equal.
191  *
192  * @param other the other RawConfig to compare with
193  * @return true if the trees are equal
194  */
195  bool operator==(const RawConfig &other) const {
196  if (this == &other) {
197  return true;
198  }
199  if (value() != other.value()) {
200  return false;
201  }
202  if (subItemsSize() != other.subItemsSize()) {
203  return false;
204  }
205  return visitSubItems(
206  [&other](const RawConfig &subConfig, const std::string &path) {
207  auto otherSubConfig = other.get(path);
208  return (otherSubConfig && *otherSubConfig == subConfig);
209  });
210  }
211 
212  /**
213  * Check if two RawConfig trees are not equal.
214  *
215  * @param config the other RawConfig to compare with
216  * @return true if the trees are not equal
217  */
218  bool operator!=(const RawConfig &config) const {
219  return !(*this == config);
220  }
221 
222  /**
223  * Get the parent node.
224  *
225  * @return pointer to the parent node, or nullptr if this is the root
226  */
227  RawConfig *parent() const;
228 
229  /**
230  * Detach this node from its parent.
231  *
232  * @return shared pointer to the detached node, or empty if already root
233  */
234  std::shared_ptr<RawConfig> detach();
235 
236  /**
237  * Visit all sub-items.
238  *
239  * @param callback function to call for each sub-item, return false to stop
240  * @param path path to start visiting from, empty for root
241  * @param recursive if true, visit sub-items recursively
242  * @param pathPrefix prefix to prepend to paths in callback
243  * @return true if all items were visited, false if stopped early
244  */
245  bool visitSubItems(
246  std::function<bool(RawConfig &, const std::string &path)> callback,
247  const std::string &path = "", bool recursive = false,
248  const std::string &pathPrefix = "");
249  /** @overload */
250  bool visitSubItems(
251  std::function<bool(const RawConfig &, const std::string &path)>
252  callback,
253  const std::string &path = "", bool recursive = false,
254  const std::string &pathPrefix = "") const;
255 
256  /**
257  * Visit all items on a path.
258  *
259  * @param callback function to call for each item on the path
260  * @param path the path to visit
261  */
262  void visitItemsOnPath(
263  std::function<void(RawConfig &, const std::string &path)> callback,
264  const std::string &path);
265 
266  /** @overload */
267  void visitItemsOnPath(
268  std::function<void(const RawConfig &, const std::string &path)>
269  callback,
270  const std::string &path) const;
271 
272 private:
273  friend class RawConfigPrivate;
274  RawConfig(std::string name);
275  std::shared_ptr<RawConfig> createSub(std::string name);
276  FCITX_DECLARE_PRIVATE(RawConfig);
277  std::unique_ptr<RawConfigPrivate> d_ptr;
278 };
279 
280 /**
281  * Output a RawConfig to a log message.
282  *
283  * @param log the log message builder
284  * @param config the RawConfig to output
285  * @return reference to the log message builder
286  */
287 FCITXCONFIG_EXPORT LogMessageBuilder &operator<<(LogMessageBuilder &log,
288  const RawConfig &config);
289 } // namespace fcitx
290 
291 #endif // _FCITX_CONFIG_RAWCONFIG_H_
RawConfig & operator=(std::string value)
Assign a string value to this node.
Definition: rawconfig.h:184
void setValueByPath(const std::string &path, std::string value)
Set a value by path, creating intermediate nodes if needed.
Definition: rawconfig.h:155
RawConfig & operator[](const std::string &path)
Get or create a sub-item by path.
Definition: rawconfig.h:176
A raw configuration tree that stores key-value pairs in a hierarchical structure. ...
Definition: rawconfig.h:37
Definition: action.cpp:17
const std::string * valueByPath(const std::string &path) const
Get a value by path.
Definition: rawconfig.h:165
std::shared_ptr< RawConfig > get(const std::string &path, bool create=false)
Get a sub-item by path.
Definition: rawconfig.cpp:153
bool operator!=(const RawConfig &config) const
Check if two RawConfig trees are not equal.
Definition: rawconfig.h:218
size_t subItemsSize() const
Get the number of sub-items.
Definition: rawconfig.cpp:248
bool operator==(const RawConfig &other) const
Check if two RawConfig trees are equal.
Definition: rawconfig.h:195
const std::string & value() const
Get the value of this node.
Definition: rawconfig.cpp:217
Log utilities.