smartmontools SVN Rev 5617
Utility to control and monitor storage systems with "S.M.A.R.T."
json.h
Go to the documentation of this file.
1/*
2 * json.h
3 *
4 * Home page of code is: https://www.smartmontools.org
5 *
6 * Copyright (C) 2017-22 Christian Franke
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11#ifndef JSON_H_CVSID
12#define JSON_H_CVSID "$Id: json.h 5292 2022-01-06 17:13:25Z chrfranke $"
13
14#include <stdint.h>
15#include <stdio.h>
16#include <initializer_list>
17#include <map>
18#include <memory>
19#include <string>
20#include <vector>
21
22/// Create and print JSON output.
23class json
24{
25public:
26 /// Return true if value is a safe JSON integer.
27 /// Same as Number.isSafeInteger(value) in JavaScript.
28 static bool is_safe_uint(unsigned long long value)
29 { return (value < (1ULL << 53)); }
30
31 /// Replace space and non-alphanumerics with '_', upper to lower case.
32 static std::string str2key(const char * str);
33
34 /// Replace space and non-alphanumerics with '_', upper to lower case
35 /// (std::string variant).
36 static std::string str2key(const std::string & str)
37 { return str2key(str.c_str()); }
38
39 enum node_type {
42 };
43
44 // initializer_list<> elements.
46 // cppcheck-suppress noExplicitConstructor
48 // cppcheck-suppress noExplicitConstructor
49 initlist_value(bool v) : type(nt_bool), intval(v ? 1 : 0) {}
50 // cppcheck-suppress noExplicitConstructor
51 initlist_value(int v) : initlist_value((long long)v) {}
52 // cppcheck-suppress noExplicitConstructor
53 initlist_value(unsigned v) : initlist_value((unsigned long long)v) {}
54 // cppcheck-suppress noExplicitConstructor
55 initlist_value(long v) : initlist_value((long long)v) {}
56 // cppcheck-suppress noExplicitConstructor
57 initlist_value(unsigned long v) : initlist_value((unsigned long long)v) {}
58 // cppcheck-suppress noExplicitConstructor
59 initlist_value(long long v) : type(nt_int), intval((uint64_t)(int64_t)v) {}
60 // cppcheck-suppress noExplicitConstructor
61 initlist_value(unsigned long long v) : type(nt_uint), intval((uint64_t)v) {}
62 // cppcheck-suppress noExplicitConstructor
63 initlist_value(const char * v) : type(nt_string), strval(v) {}
64 // cppcheck-suppress noExplicitConstructor
65 initlist_value(const std::string & v) : type(nt_string), strval(v.c_str()) {}
67 uint64_t intval = 0;
68 const char * strval = nullptr;
69 };
70
72 initlist_key_value_pair(const char * k, const initlist_value & v) : keystr(k), value(v) {}
73 initlist_key_value_pair(const std::string & k, const initlist_value & v)
74 : keystr(k.c_str()), value(v) {}
75 initlist_key_value_pair(const char * k, const std::initializer_list<initlist_key_value_pair> & ilist)
76 : keystr(k), value(nt_object), object(ilist) {}
77 initlist_key_value_pair(const std::string & k, const std::initializer_list<initlist_key_value_pair> & ilist)
78 : keystr(k.c_str()), value(nt_object), object(ilist) {}
79 initlist_key_value_pair(const char * k, const std::initializer_list<initlist_value> & ilist)
80 : keystr(k), value(nt_array), array(ilist) {}
81 initlist_key_value_pair(const std::string & k, const std::initializer_list<initlist_value> & ilist)
82 : keystr(k.c_str()), value(nt_array), array(ilist) {}
83 const char * keystr;
85 std::initializer_list<initlist_key_value_pair> object;
86 std::initializer_list<initlist_value> array;
87 };
88
89private:
90 struct node_info
91 {
92 std::string key;
93 int index = 0;
94
95 node_info() = default;
96 explicit node_info(const char * keystr) : key(str2key(keystr)) { }
97 explicit node_info(int index_) : index(index_) { }
98 };
99
100 typedef std::vector<node_info> node_path;
101
102public:
103 /// Reference to a JSON element.
104 class ref
105 {
106 public:
107 ~ref();
108
109 /// Return reference to object element.
110 ref operator[](const char * keystr) const
111 { return ref(*this, keystr); }
112
113 /// Return reference to object element (std::string variant).
114 ref operator[](const std::string & keystr) const
115 { return ref(*this, keystr.c_str()); }
116
117 /// Return reference to array element.
118 ref operator[](int index) const
119 { return ref(*this, index); }
120
121 // Assignment operators create or change element.
122 void operator=(bool value);
123
124 void operator=(int value);
125 void operator=(unsigned value);
126 void operator=(long value);
127 void operator=(unsigned long value);
128 void operator=(long long value);
129 void operator=(unsigned long long value);
130
131 void operator=(const char * value);
132 void operator=(const std::string & value);
133
134 /// Return reference to element with KEY_SUFFIX appended to last key.
135 ref with_suffix(const char * key_suffix) const
136 { return ref(*this, "", key_suffix); }
137
138 void set_uint128(uint64_t value_hi, uint64_t value_lo);
139
140 // Output only if safe integer.
141 bool set_if_safe_uint64(uint64_t value);
142 bool set_if_safe_uint128(uint64_t value_hi, uint64_t value_lo);
143 bool set_if_safe_le128(const void * pvalue);
144
145 // If unsafe integer, output also as string with key "NUMBER_s".
146 void set_unsafe_uint64(uint64_t value);
147 void set_unsafe_uint128(uint64_t value_hi, uint64_t value_lo);
148 void set_unsafe_le128(const void * pvalue);
149
150 /// Braced-init-list support for nested objects.
151 void operator+=(std::initializer_list<initlist_key_value_pair> ilist);
152 /// Braced-init-list support for simple arrays.
153 void operator+=(std::initializer_list<initlist_value> ilist);
154
155 private:
156 friend class json;
157 explicit ref(json & js);
158 ref(json & js, const char * keystr);
159 ref(const ref & base, const char * keystr);
160 ref(const ref & base, int index);
161 ref(const ref & base, const char * /*dummy*/, const char * key_suffix);
162
163 void operator=(const initlist_value & value)
164 { m_js.set_initlist_value(m_path, value); }
165
168 };
169
170 /// Return reference to element of top level object.
171 ref operator[](const char * keystr)
172 { return ref(*this, keystr); }
173
174 /// Return reference to element of top level object (std::string variant).
175 ref operator[](const std::string & keystr)
176 { return ref(*this, keystr.c_str()); }
177
178 /// Braced-init-list support for top level object.
179 void operator+=(std::initializer_list<initlist_key_value_pair> ilist)
180 { ref(*this) += ilist; }
181
182 /// Enable/disable JSON output.
183 void enable(bool yes = true)
184 { m_enabled = yes; }
185
186 /// Return true if enabled.
187 bool is_enabled() const
188 { return m_enabled; }
189
190 /// Enable/disable extra string output for safe integers also.
191 void set_verbose(bool yes = true)
192 { m_verbose = yes; }
193
194 /// Return true if any 128-bit value has been output.
196 { return m_uint128_output; }
197
198 /// Options for print().
200 bool pretty = false; //< Pretty-print output.
201 bool sorted = false; //< Sort object keys.
202 char format = 0; //< 'y': YAML, 'g': flat(grep, gron), other: JSON
203 };
204
205 /// Print JSON tree to a file.
206 void print(FILE * f, const print_options & options) const;
207
208private:
209 struct node
210 {
211 node();
212 node(const node &) = delete;
213 explicit node(const std::string & key_);
214 ~node();
215 void operator=(const node &) = delete;
216
218
219 uint64_t intval = 0, intval_hi = 0;
220 std::string strval;
221
222 std::string key;
223 std::vector< std::unique_ptr<node> > childs;
224 typedef std::map<std::string, unsigned> keymap;
226
228 {
229 public:
230 const_iterator(const node * node_p, bool sorted);
231 bool at_end() const;
232 unsigned array_index() const;
233 void operator++();
234 const node * operator*() const;
235
236 private:
237 const node * m_node_p;
239 unsigned m_child_idx = 0;
240 keymap::const_iterator m_key_iter;
241 };
242 };
243
244 bool m_enabled = false;
245 bool m_verbose = false;
246 bool m_uint128_output = false;
247
249
250 node * find_or_create_node(const node_path & path, node_type type);
251
252 void set_bool(const node_path & path, bool value);
253 void set_int64(const node_path & path, int64_t value);
254 void set_uint64(const node_path & path, uint64_t value);
255 void set_uint128(const node_path & path, uint64_t value_hi, uint64_t value_lo);
256 void set_cstring(const node_path & path, const char * value);
257 void set_string(const node_path & path, const std::string & value);
258 void set_initlist_value(const node_path & path, const initlist_value & value);
259
260 static void print_json(FILE * f, bool pretty, bool sorted, const node * p, int level);
261 static void print_yaml(FILE * f, bool pretty, bool sorted, const node * p, int level_o,
262 int level_a, bool cont);
263 static void print_flat(FILE * f, const char * assign, bool sorted, const node * p,
264 std::string & path);
265};
266
267#endif // JSON_H_CVSID
bool at_end() const
Definition: json.cpp:277
const node * m_node_p
Definition: json.h:237
unsigned array_index() const
Definition: json.cpp:285
const node * operator*() const
Definition: json.cpp:299
keymap::const_iterator m_key_iter
Definition: json.h:240
Reference to a JSON element.
Definition: json.h:105
ref with_suffix(const char *key_suffix) const
Return reference to element with KEY_SUFFIX appended to last key.
Definition: json.h:135
void set_uint128(uint64_t value_hi, uint64_t value_lo)
Definition: json.cpp:164
ref operator[](const char *keystr) const
Return reference to object element.
Definition: json.h:110
void set_unsafe_uint128(uint64_t value_hi, uint64_t value_lo)
Definition: json.cpp:205
void operator=(const initlist_value &value)
Definition: json.h:163
void operator+=(std::initializer_list< initlist_key_value_pair > ilist)
Braced-init-list support for nested objects.
Definition: json.cpp:237
node_path m_path
Definition: json.h:167
void set_unsafe_le128(const void *pvalue)
Definition: json.cpp:231
void operator=(bool value)
Definition: json.cpp:119
bool set_if_safe_le128(const void *pvalue)
Definition: json.cpp:187
void set_unsafe_uint64(uint64_t value)
Definition: json.cpp:193
json & m_js
Definition: json.h:166
bool set_if_safe_uint64(uint64_t value)
Definition: json.cpp:172
~ref()
Definition: json.cpp:115
bool set_if_safe_uint128(uint64_t value_hi, uint64_t value_lo)
Definition: json.cpp:180
ref operator[](const std::string &keystr) const
Return reference to object element (std::string variant).
Definition: json.h:114
ref operator[](int index) const
Return reference to array element.
Definition: json.h:118
Create and print JSON output.
Definition: json.h:24
bool has_uint128_output() const
Return true if any 128-bit value has been output.
Definition: json.h:195
static void print_flat(FILE *f, const char *assign, bool sorted, const node *p, std::string &path)
Definition: json.cpp:647
std::vector< node_info > node_path
Definition: json.h:100
node m_root_node
Definition: json.h:248
void set_uint64(const node_path &path, uint64_t value)
Definition: json.cpp:381
void set_int64(const node_path &path, int64_t value)
Definition: json.cpp:374
bool m_verbose
Definition: json.h:245
bool is_enabled() const
Return true if enabled.
Definition: json.h:187
void set_string(const node_path &path, const std::string &value)
Definition: json.cpp:405
void set_initlist_value(const node_path &path, const initlist_value &value)
Definition: json.cpp:412
static std::string str2key(const char *str)
Replace space and non-alphanumerics with '_', upper to lower case.
Definition: json.cpp:41
bool m_enabled
Definition: json.h:244
void set_bool(const node_path &path, bool value)
Definition: json.cpp:367
void set_cstring(const node_path &path, const char *value)
Definition: json.cpp:397
static void print_json(FILE *f, bool pretty, bool sorted, const node *p, int level)
Definition: json.cpp:514
static bool is_safe_uint(unsigned long long value)
Return true if value is a safe JSON integer.
Definition: json.h:28
ref operator[](const std::string &keystr)
Return reference to element of top level object (std::string variant).
Definition: json.h:175
static std::string str2key(const std::string &str)
Replace space and non-alphanumerics with '_', upper to lower case (std::string variant).
Definition: json.h:36
void set_verbose(bool yes=true)
Enable/disable extra string output for safe integers also.
Definition: json.h:191
bool m_uint128_output
Definition: json.h:246
static void print_yaml(FILE *f, bool pretty, bool sorted, const node *p, int level_o, int level_a, bool cont)
Definition: json.cpp:576
node * find_or_create_node(const node_path &path, node_type type)
Definition: json.cpp:307
ref operator[](const char *keystr)
Return reference to element of top level object.
Definition: json.h:171
void operator+=(std::initializer_list< initlist_key_value_pair > ilist)
Braced-init-list support for top level object.
Definition: json.h:179
void set_uint128(const node_path &path, uint64_t value_hi, uint64_t value_lo)
Definition: json.cpp:388
void enable(bool yes=true)
Enable/disable JSON output.
Definition: json.h:183
void print(FILE *f, const print_options &options) const
Print JSON tree to a file.
Definition: json.cpp:710
node_type
Definition: json.h:39
@ nt_unset
Definition: json.h:40
@ nt_uint128
Definition: json.h:41
@ nt_string
Definition: json.h:41
@ nt_bool
Definition: json.h:41
@ nt_int
Definition: json.h:41
@ nt_object
Definition: json.h:40
@ nt_array
Definition: json.h:40
@ nt_uint
Definition: json.h:41
std::initializer_list< initlist_key_value_pair > object
Definition: json.h:85
initlist_key_value_pair(const char *k, const initlist_value &v)
Definition: json.h:72
initlist_value value
Definition: json.h:84
initlist_key_value_pair(const char *k, const std::initializer_list< initlist_key_value_pair > &ilist)
Definition: json.h:75
initlist_key_value_pair(const std::string &k, const std::initializer_list< initlist_key_value_pair > &ilist)
Definition: json.h:77
initlist_key_value_pair(const char *k, const std::initializer_list< initlist_value > &ilist)
Definition: json.h:79
initlist_key_value_pair(const std::string &k, const std::initializer_list< initlist_value > &ilist)
Definition: json.h:81
initlist_key_value_pair(const std::string &k, const initlist_value &v)
Definition: json.h:73
std::initializer_list< initlist_value > array
Definition: json.h:86
const char * keystr
Definition: json.h:83
initlist_value(int v)
Definition: json.h:51
initlist_value(bool v)
Definition: json.h:49
initlist_value(unsigned v)
Definition: json.h:53
uint64_t intval
Definition: json.h:67
initlist_value(const char *v)
Definition: json.h:63
initlist_value(unsigned long v)
Definition: json.h:57
initlist_value(long v)
Definition: json.h:55
initlist_value(unsigned long long v)
Definition: json.h:61
node_type type
Definition: json.h:66
initlist_value(const std::string &v)
Definition: json.h:65
const char * strval
Definition: json.h:68
initlist_value(long long v)
Definition: json.h:59
initlist_value(node_type t)
Definition: json.h:47
node_info(int index_)
Definition: json.h:97
int index
Definition: json.h:93
std::string key
Definition: json.h:92
node_info(const char *keystr)
Definition: json.h:96
node_info()=default
std::string key
Definition: json.h:222
uint64_t intval_hi
Definition: json.h:219
uint64_t intval
Definition: json.h:219
node(const node &)=delete
std::vector< std::unique_ptr< node > > childs
Definition: json.h:223
std::string strval
Definition: json.h:220
void operator=(const node &)=delete
node_type type
Definition: json.h:217
std::map< std::string, unsigned > keymap
Definition: json.h:224
keymap key2index
Definition: json.h:225
Options for print().
Definition: json.h:199