Ocean
JSONConfig.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_IO_JSON_CONFIG_H
9 #define META_OCEAN_IO_JSON_CONFIG_H
10 
11 #include "ocean/io/IO.h"
12 #include "ocean/io/Scanner.h"
13 
14 #include "ocean/base/Config.h"
15 
16 namespace Ocean
17 {
18 
19 namespace IO
20 {
21 
22 /**
23  * This class implements a configuration toolkit based on JSON.
24  * @ingroup io
25  */
26 class OCEAN_IO_EXPORT JSONConfig final : public Config
27 {
28  public:
29 
30  // Forward declaration
31  class JSONValue;
32 
33  /**
34  * Definition of a map mapping value names to value objects.
35  */
36  typedef std::unordered_map<std::string, std::vector<JSONValue>> JSONValues;
37 
38  /**
39  * Definition of a JSON value object.
40  */
41  class OCEAN_IO_EXPORT JSONValue final : public Value
42  {
43  friend class JSONConfig;
44 
45  public:
46 
47  /**
48  * Creates a new value object.
49  */
51 
52  /**
53  * Default copy constructor.
54  * @param value The value to copy
55  */
56  JSONValue(const JSONValue& value) = default;
57 
58  /**
59  * Creates a new value object by a single value as string and the real value type.
60  * @param value String value
61  * @param type Value type
62  */
63  JSONValue(const std::string& value, const ValueType type);
64 
65  /**
66  * Creates a new value object holding sub values.
67  * @param values Sub values
68  */
69  explicit JSONValue(const JSONValues& values);
70 
71  /**
72  * Destructs a value object.
73  */
74  ~JSONValue() override;
75 
76  /**
77  * Returns the number of sub values.
78  * @see Config::Value::values().
79  */
80  unsigned int values() const override;
81 
82  /**
83  * Returns the number of sub values with a given name.
84  * @param name The name of the JSON node
85  * @see Config::Value::values().
86  */
87  unsigned int values(const std::string& name) const override;
88 
89  /**
90  * Returns whether this value holds at least one specified sub value.
91  * @param name The name of the JSON node
92  * @see Config::Value::exist().
93  */
94  bool exist(const std::string& name) const override;
95 
96  /**
97  * Returns a sub value specified by it's name and it's index if more than one value exists with the same name.
98  * @param name The name of the JSON node
99  * @param index The index of the specific node in case multiple nodes with the same name exist, range: [0, infinity)
100  * @return A reference to the node with the specified name, will be an empty node if the name doesn't exist
101  * @see Config::Value::value().
102  */
103  JSONValue& value(const std::string& name, const unsigned int index) override;
104 
105  /**
106  * Returns a sub value specified by it's name and it's index if more than one value exists with the same name.
107  * @param name The name of the JSON node, must be valid
108  * @param index The index of the specific node in case multiple nodes with the same name exist, range: [0, infinity)
109  * @param value Pointer to the memory where the value of the selected node will be copied to
110  * @return True if the node with the specified name exists, otherwise false
111  * @see Config::Value::value().
112  */
113  bool value(const std::string& name, const unsigned int index, Value** value) override;
114 
115  /**
116  * Returns a sub value specified by it's index.
117  * @param index The index of the specific node , range: [0, N), where N = number of nodes
118  * @param name The name of the JSON node at index @c index, will be unchanged if that node doesn't exist
119  * @return A reference to the node with the specified name, will be an empty node if the name doesn't exist
120  * @see Config::Value::value().
121  */
122  JSONValue& value(const unsigned int index, std::string& name) override;
123 
124  /**
125  * Returns a sub value specified by it's index.
126  * @param index The index of the specific node , range: [0, N), where N = number of nodes
127  * @param name The name of the JSON node, must be valid
128  * @param value Pointer to the memory where the value of the selected node will be copied to
129  * @return True if the node with the specified name exists, otherwise false
130  * @see Config::Value::value().
131  */
132  bool value(const unsigned int index, std::string& name, Value** value) override;
133 
134  /**
135  * Adds a new sub value specified by it's name.
136  * @param name The name of the sub value to create
137  * @return New sub value
138  */
139  JSONValue& add(const std::string& name) override;
140 
141  /**
142  * Returns this value as boolean.
143  * @param value The value that is returned in case the type of the internal value doesn't match (or cannot be cast into) the type of this parameter/return type of this function
144  * @return The internal value of this node
145  * @see Config::Value::operator().
146  */
147  bool operator()(const bool value) const override;
148 
149  /**
150  * Returns this value as integer.
151  * @param value The value that is returned in case the type of the internal value doesn't match (or cannot be cast into) the type of this parameter/return type of this function
152  * @return The internal value of this node
153  * @see Config::Value::operator().
154  */
155  int operator()(const int value) const override;
156 
157  /**
158  * Returns this value as number.
159  * @param value The value that is returned in case the type of the internal value doesn't match (or cannot be cast into) the type of this parameter/return type of this function
160  * @return The internal value of this node
161  * @see Config::Value::operator().
162  */
163  double operator()(const double value) const override;
164 
165  /**
166  * Returns this value as string.
167  * @param value The value that is returned in case the type of the internal value doesn't match (or cannot be cast into) the type of this parameter/return type of this function
168  * @return The internal value of this node
169  * @see Config::Value::operator().
170  */
171  std::string operator()(const std::string& value) const override;
172 
173  /**
174  * Returns this value as multi boolean.
175  * @param value The value that is returned in case the type of the internal value doesn't match (or cannot be cast into) the type of this parameter/return type of this function
176  * @return The internal value of this node
177  * @see Config::Value::operator().
178  */
179  std::vector<bool> operator()(const std::vector<bool>& value) const override;
180 
181  /**
182  * Returns this value as multi integer.
183  * @param value The value that is returned in case the type of the internal value doesn't match (or cannot be cast into) the type of this parameter/return type of this function
184  * @return The internal value of this node
185  * @see Config::Value::operator().
186  */
187  std::vector<int> operator()(const std::vector<int>& value) const override;
188 
189  /**
190  * Returns this value as multi number.
191  * @param value The value that is returned in case the type of the internal value doesn't match (or cannot be cast into) the type of this parameter/return type of this function
192  * @return The internal value of this node
193  * @see Config::Value::operator().
194  */
195  std::vector<double> operator()(const std::vector<double>& value) const override;
196 
197  /**
198  * Returns this value as multi string.
199  * @param value The value that is returned in case the type of the internal value doesn't match (or cannot be cast into) the type of this parameter/return type of this function
200  * @return The internal value of this node
201  * @see Config::Value::operator().
202  */
203  std::vector<std::string> operator()(const std::vector<std::string>& value) const override;
204 
205  /**
206  * Sets this value as boolean.
207  * @param value Will set the internal value and value type of this node, node must be valid and not a group
208  * @return True if the value could be set, otherwise false
209  * @see Config::Value::operator=().
210  */
211  bool operator=(const bool value) override;
212 
213  /**
214  * Sets this value as integer.
215  * @param value Will set the internal value and value type of this node, node must be valid and not a group
216  * @return True if the value could be set, otherwise false
217  * @see Config::Value::operator=().
218  */
219  bool operator=(const int value) override;
220 
221  /**
222  * Sets this value as number.
223  * @param value Will set the internal value and value type of this node, node must be valid and not a group. Up to 10 decimals of the value will be stored.
224  * @return True if the value could be set, otherwise false
225  * @see Config::Value::operator=().
226  */
227  bool operator=(const double value) override;
228 
229  /**
230  * Sets this value as string.
231  * @param value Will set the internal value and value type of this node, node must be valid and not a group
232  * @return True if the value could be set, otherwise false
233  * @see Config::Value::operator=().
234  */
235  bool operator=(const std::string& value) override;
236 
237  /**
238  * Sets this value as multi boolean.
239  * @param values Will set the internal value and value type of this node, node must be valid and not a group
240  * @return True if the value could be set, otherwise false
241  * @see Config::Value::operator=().
242  */
243  bool operator=(const std::vector<bool>& values) override;
244 
245  /**
246  * Sets this value as multi integer.
247  * @param values Will set the internal value and value type of this node, node must be valid and not a group
248  * @return True if the value could be set, otherwise false
249  * @see Config::Value::operator=().
250  */
251  bool operator=(const std::vector<int>& values) override;
252 
253  /**
254  * Sets this value as multi number.
255  * @param values Will set the internal value and value type of this node, node must be valid and not a group
256  * @return True if the value could be set, otherwise false
257  * @see Config::Value::operator=().
258  */
259  bool operator=(const std::vector<double>& values) override;
260 
261  /**
262  * Sets this value as multi string.
263  * @param values Will set the internal value and value type of this node, node must be valid and not a group
264  * @return True if the value could be set, otherwise false
265  * @see Config::Value::operator=().
266  */
267  bool operator=(const std::vector<std::string>& values) override;
268 
269  /**
270  * Returns a sub value specified by it's name
271  * @param name The name of the JSON node to retrieve
272  * @return A reference to the node with the specified name; will be an empty node if the name doesn't exist
273  * @see Config::Value::operator[]().
274  */
275  JSONValue& operator[](const std::string& name) override;
276 
277  /**
278  * Returns a sub value specified by it's name
279  * @param name The name of the JSON node to retrieve
280  * @return A constant reference to the node with the specified name; will be an empty node if the name doesn't exist
281  * @see Config::Value::operator[]().
282  */
283  const JSONValue& operator[](const std::string& name) const;
284 
285  private:
286 
287  /**
288  * Returns the boolean value of this object.
289  * @return Parsed boolean value
290  */
291  bool boolValue() const;
292 
293  /**
294  * Returns the integer value of this object.
295  * @return Parsed integer value
296  */
297  int integerValue() const;
298 
299  /**
300  * Returns the number value of this object.
301  * @return Parsed number value
302  */
303  double numberValue() const;
304 
305  /**
306  * Returns the boolean value of this object.
307  * @return Parsed boolean value
308  */
309  std::vector<bool> boolValues() const;
310 
311  /**
312  * Returns the integer values of this object.
313  * @return Parsed integer value
314  */
315  std::vector<int> integerValues() const;
316 
317  /**
318  * Returns the number values of this object.
319  * @return Parsed number value
320  */
321  std::vector<double> numberValues() const;
322 
323  /**
324  * Returns the string values of this object.
325  * @return Parsed number value
326  */
327  std::vector<std::string> stringValues() const;
328 
329  private:
330 
331  /// Value as string.
332  std::string valueString_;
333 
334  /// Sub values if this value is a group.
336  };
337 
338  protected:
339 
340  /**
341  * This class implements a scanner for JSON files.
342  */
343  class JSONScanner : public Scanner
344  {
345  public:
346 
347  /**
348  * Definition of individual JSON symbols.
349  */
351  {
352  /// Node begin symbol: '{'.
354  /// Node end symbol: '}'.
356  /// Array begin symbol: '['.
358  /// Node end symbol: ']'.
360  /// Colon symbol: '.'
362  /// Comma symbol: ','
363  JS_COMMA
364  };
365 
366  /**
367  * Definition of individual JSON keywords.
368  */
370  {
371  /// Keyword true.
373  /// Keyword false.
375  /// Keyword null.
376  JK_NULL
377  };
378 
379  public:
380 
381  /**
382  * Creates a new scanner by a given filename.
383  * @param stream The input stream from which the JSON data is read, must be valid
384  * @param progress Optional scanner progress value
385  * @param cancel Optional scanner cancel state
386  * @see Scanner::Scanner().
387  */
388  explicit JSONScanner(const std::shared_ptr<std::istream>& stream, float* progress = nullptr, bool* cancel = nullptr);
389  };
390 
391  public:
392 
393  /**
394  * Creates a new config object.
395  */
397 
398  /**
399  * Creates a new config object with a specified configuration file.
400  * @param filename The name of the file associated with the new config object
401  * @param read True, to load the data from the file directly
402  * @see read().
403  */
404  explicit JSONConfig(const std::string& filename, const bool read = true);
405 
406  /**
407  * Creates a new config object with a specified input stream.
408  * @param stream The input stream from which the JSON data is read immediately, must be valid
409  */
410  explicit JSONConfig(const std::shared_ptr<std::istream>& stream);
411 
412  /**
413  * Returns the config file.
414  * @return Config file
415  */
416  inline const std::string& filename() const;
417 
418  /**
419  * Sets the filename of the new config objects.
420  * All old config objects will be released before.
421  * @param filename to set
422  * @param read True, to load the file directly
423  * @return True, if the file could be loaded
424  */
425  bool setFilename(const std::string& filename, const bool read = true);
426 
427  /**
428  * Reads / loads all values of this configuration.
429  * @see Config::read().
430  */
431  bool read() override;
432 
433  /**
434  * Writes / saves all values of this configuration.
435  * @see Config::write().
436  */
437  bool write() override;
438 
439  /**
440  * Returns the number of sub values.
441  * @see Config::values().
442  */
443  unsigned int values() const override;
444 
445  /**
446  * Returns the number of sub values with a given name.
447  * @see Config::values().
448  */
449  unsigned int values(const std::string& name) const override;
450 
451  /**
452  * Returns whether this value holds at least one specified sub value.
453  * @see Config::exist().
454  */
455  bool exist(const std::string& name) const override;
456 
457  /**
458  * Returns a sub value specified by it's index.
459  * @see Config::value().
460  */
461  JSONValue& value(const unsigned int index, std::string& name) override;
462 
463  /**
464  * Returns a sub value specified by it's index.
465  * @see Config::value().
466  */
467  bool value(const unsigned int index, std::string& name, Value** value) override;
468 
469  /**
470  * Returns a sub value specified by it's name and it's index if more than one value exists with the same name.
471  * @see Config::value().
472  */
473  JSONValue& value(const std::string& name, const unsigned int index) override;
474 
475  /**
476  * Returns a sub value specified by it's name and it's index if more than one value exists with the same name.
477  * @see Config::value().
478  */
479  bool value(const std::string& name, const unsigned int index, Value** value) override;
480 
481  /**
482  * Adds a new sub value specified by it's name.
483  * @param name The name of the sub value to create
484  * @return New sub value
485  */
486  JSONValue& add(const std::string& name) override;
487 
488  /**
489  * Returns a sub value specified by it's name
490  * @see Config::operator[]().
491  */
492  JSONValue& operator[](const std::string& name) override;
493 
494  protected:
495 
496  /**
497  * Parses a JSON node.
498  * @param node The node receiving the parse data
499  * @param scanner The scanner from which the information is parsed, while the node begin symbol has been popped already
500  * @return True, if succeeded
501  */
502  bool parseNode(JSONValue& node, JSONScanner& scanner);
503 
504  /**
505  * Parses a JSON array.
506  * @param node The node receiving the parse data
507  * @param fieldName The name of the array
508  * @param scanner The scanner from which the information is parsed, while the array begin symbol has been popped already
509  * @return True, if succeeded
510  */
511  bool parseArray(JSONValue& node, const std::string& fieldName, JSONScanner& scanner);
512 
513  /**
514  * Writes a JSON node.
515  * @param node The node to be written
516  * @param stream The output stream receiving the node's information
517  * @param indentation The indentation of the node (the number of empty space characters in front of the node), with range [0, infinity)
518  * @return True, if succeeded
519  */
520  static bool writeNode(JSONValue& node, std::ostream& stream, const unsigned int indentation);
521 
522  /**
523  * Writes a line (with indentation) to an output stream.
524  * @param string The string to be written
525  * @param stream The output stream in which the string will be written
526  * @param indentation The number of empty space characters to be written in front of the string, with range [0, infinity)
527  * @return True, if succeeded
528  */
529  static bool writeLine(const std::string& string, std::ostream& stream, const unsigned int indentation);
530 
531  /**
532  * Returns the default value holding no data.
533  * @return The default value holding no data.
534  */
535  static JSONValue& nullValue();
536 
537  protected:
538 
539  /// Filename of this config object.
540  std::string filename_;
541 
542  /// The root value.
544 };
545 
546 inline const std::string& JSONConfig::filename() const
547 {
548  return filename_;
549 }
550 
551 } // namespace IO
552 
553 } // namespace Ocean
554 
555 #endif // META_OCEAN_IO_JSON_CONFIG_H
This class implements a configuration value.
Definition: Config.h:77
This class implements an application or module configuration toolkit.
Definition: Config.h:38
ValueType
Definition of different value types.
Definition: Config.h:45
This class implements a scanner for JSON files.
Definition: JSONConfig.h:344
JSONScanner(const std::shared_ptr< std::istream > &stream, float *progress=nullptr, bool *cancel=nullptr)
Creates a new scanner by a given filename.
JSONKeyword
Definition of individual JSON keywords.
Definition: JSONConfig.h:370
@ JK_FALSE
Keyword false.
Definition: JSONConfig.h:374
@ JK_TRUE
Keyword true.
Definition: JSONConfig.h:372
JSONSymbol
Definition of individual JSON symbols.
Definition: JSONConfig.h:351
@ JS_NODE_BEGIN
Node begin symbol: '{'.
Definition: JSONConfig.h:353
@ JS_ARRAY_END
Node end symbol: ']'.
Definition: JSONConfig.h:359
@ JS_COLON
Colon symbol: '.'.
Definition: JSONConfig.h:361
@ JS_NODE_END
Node end symbol: '}'.
Definition: JSONConfig.h:355
@ JS_ARRAY_BEGIN
Array begin symbol: '['.
Definition: JSONConfig.h:357
Definition of a JSON value object.
Definition: JSONConfig.h:42
JSONValues subValues_
Sub values if this value is a group.
Definition: JSONConfig.h:335
bool value(const std::string &name, const unsigned int index, Value **value) override
Returns a sub value specified by it's name and it's index if more than one value exists with the same...
std::string operator()(const std::string &value) const override
Returns this value as string.
std::vector< std::string > stringValues() const
Returns the string values of this object.
const JSONValue & operator[](const std::string &name) const
Returns a sub value specified by it's name.
double operator()(const double value) const override
Returns this value as number.
std::vector< std::string > operator()(const std::vector< std::string > &value) const override
Returns this value as multi string.
std::vector< double > operator()(const std::vector< double > &value) const override
Returns this value as multi number.
std::vector< int > operator()(const std::vector< int > &value) const override
Returns this value as multi integer.
JSONValue & add(const std::string &name) override
Adds a new sub value specified by it's name.
int operator()(const int value) const override
Returns this value as integer.
bool operator=(const std::vector< bool > &values) override
Sets this value as multi boolean.
bool boolValue() const
Returns the boolean value of this object.
JSONValue()
Creates a new value object.
bool exist(const std::string &name) const override
Returns whether this value holds at least one specified sub value.
int integerValue() const
Returns the integer value of this object.
bool operator=(const double value) override
Sets this value as number.
std::vector< bool > boolValues() const
Returns the boolean value of this object.
JSONValue(const JSONValues &values)
Creates a new value object holding sub values.
JSONValue(const JSONValue &value)=default
Default copy constructor.
unsigned int values() const override
Returns the number of sub values.
bool value(const unsigned int index, std::string &name, Value **value) override
Returns a sub value specified by it's index.
bool operator=(const std::vector< int > &values) override
Sets this value as multi integer.
~JSONValue() override
Destructs a value object.
std::string valueString_
Value as string.
Definition: JSONConfig.h:332
bool operator=(const std::vector< std::string > &values) override
Sets this value as multi string.
JSONValue & value(const unsigned int index, std::string &name) override
Returns a sub value specified by it's index.
bool operator()(const bool value) const override
Returns this value as boolean.
bool operator=(const bool value) override
Sets this value as boolean.
std::vector< bool > operator()(const std::vector< bool > &value) const override
Returns this value as multi boolean.
JSONValue & operator[](const std::string &name) override
Returns a sub value specified by it's name.
bool operator=(const std::string &value) override
Sets this value as string.
std::vector< double > numberValues() const
Returns the number values of this object.
JSONValue(const std::string &value, const ValueType type)
Creates a new value object by a single value as string and the real value type.
JSONValue & value(const std::string &name, const unsigned int index) override
Returns a sub value specified by it's name and it's index if more than one value exists with the same...
bool operator=(const int value) override
Sets this value as integer.
double numberValue() const
Returns the number value of this object.
unsigned int values(const std::string &name) const override
Returns the number of sub values with a given name.
std::vector< int > integerValues() const
Returns the integer values of this object.
bool operator=(const std::vector< double > &values) override
Sets this value as multi number.
This class implements a configuration toolkit based on JSON.
Definition: JSONConfig.h:27
JSONValue root_
The root value.
Definition: JSONConfig.h:543
static bool writeNode(JSONValue &node, std::ostream &stream, const unsigned int indentation)
Writes a JSON node.
bool value(const unsigned int index, std::string &name, Value **value) override
Returns a sub value specified by it's index.
JSONConfig(const std::string &filename, const bool read=true)
Creates a new config object with a specified configuration file.
const std::string & filename() const
Returns the config file.
Definition: JSONConfig.h:546
std::string filename_
Filename of this config object.
Definition: JSONConfig.h:540
JSONConfig()
Creates a new config object.
bool read() override
Reads / loads all values of this configuration.
static JSONValue & nullValue()
Returns the default value holding no data.
bool parseArray(JSONValue &node, const std::string &fieldName, JSONScanner &scanner)
Parses a JSON array.
JSONValue & value(const unsigned int index, std::string &name) override
Returns a sub value specified by it's index.
bool parseNode(JSONValue &node, JSONScanner &scanner)
Parses a JSON node.
unsigned int values() const override
Returns the number of sub values.
bool setFilename(const std::string &filename, const bool read=true)
Sets the filename of the new config objects.
bool write() override
Writes / saves all values of this configuration.
bool value(const std::string &name, const unsigned int index, Value **value) override
Returns a sub value specified by it's name and it's index if more than one value exists with the same...
JSONValue & operator[](const std::string &name) override
Returns a sub value specified by it's name.
JSONConfig(const std::shared_ptr< std::istream > &stream)
Creates a new config object with a specified input stream.
JSONValue & value(const std::string &name, const unsigned int index) override
Returns a sub value specified by it's name and it's index if more than one value exists with the same...
unsigned int values(const std::string &name) const override
Returns the number of sub values with a given name.
bool exist(const std::string &name) const override
Returns whether this value holds at least one specified sub value.
static bool writeLine(const std::string &string, std::ostream &stream, const unsigned int indentation)
Writes a line (with indentation) to an output stream.
std::unordered_map< std::string, std::vector< JSONValue > > JSONValues
Definition of a map mapping value names to value objects.
Definition: JSONConfig.h:31
JSONValue & add(const std::string &name) override
Adds a new sub value specified by it's name.
This class implements a simple scanner.
Definition: Scanner.h:31
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15