GCC Middle and Back End API Reference
json.h
Go to the documentation of this file.
1/* JSON trees
2 Copyright (C) 2017-2025 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#ifndef GCC_JSON_H
22#define GCC_JSON_H
23
24#include "label-text.h"
25
26/* Implementation of JSON, a lightweight data-interchange format.
27
28 See http://www.json.org/
29 and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
30 and https://tools.ietf.org/html/rfc7159
31
32 Supports parsing text into a DOM-like tree of json::value *, directly
33 creating such trees, and dumping json::value * to text. */
34
35/* TODO: `libcpp/mkdeps.cc` wants JSON writing support for p1689r5 output;
36 extract this code and move to libiberty. */
37
38namespace json
39{
40
41/* Forward decls of json::value and its subclasses (using indentation
42 to denote inheritance. */
43
44class value;
45 class object;
46 class array;
47 class float_number;
48 class integer_number;
49 class string;
50 class literal;
51
52/* An enum for discriminating the subclasses of json::value. */
53
54enum kind
55{
56 /* class json::object. */
58
59 /* class json::array. */
61
62 /* class json::integer_number. */
64
65 /* class json::float_number. */
67
68 /* class json::string. */
70
71 /* class json::literal uses these three values to identify the
72 particular literal. */
76};
77
78namespace pointer { // json::pointer
79
80/* Implementation of JSON pointer (RFC 6901). */
81
82/* A token within a JSON pointer, expressing the parent of a particular
83 JSON value, and how it is descended from that parent.
84
85 A JSON pointer can be built as a list of these tokens. */
86
87struct token
88{
95
96 token ();
97 token (json::object &parent, const char *member);
98 token (json::array &parent, size_t index);
99 token (const token &other) = delete;
100 token (token &&other) = delete;
101
102 ~token ();
103
104 token &
105 operator= (const token &other) = delete;
106
107 token &
108 operator= (token &&other);
109
111 union u
112 {
113 char *u_member;
114 size_t u_index;
117};
118
119} // namespace json::pointer
120
121/* Typesafe way to work with properties in JSON objects. */
122
123template <typename Traits>
125{
126 explicit property (const char *key)
127 : m_key (label_text::borrow (key))
128 {}
129
130 explicit property (const char *key_prefix, const char *key)
131 : m_key (label_text::take (concat (key_prefix, key, nullptr)))
132 {}
133
134 label_text m_key;
135};
136
142
143template <typename EnumType>
145{
146 typedef EnumType enum_t;
147
149 static bool maybe_get_value_from_string (const char *, enum_t &out);
150 static const char *get_string_for_value (enum_t value);
151};
152
153template <typename EnumType>
155
156/* Base class of JSON value. */
157
158class value
159{
160 public:
161 virtual ~value () {}
162 virtual enum kind get_kind () const = 0;
163 virtual void print (pretty_printer *pp, bool formatted) const = 0;
164 virtual std::unique_ptr<value> clone () const = 0;
165
166 void dump (FILE *, bool formatted) const;
167 void DEBUG_FUNCTION dump () const;
168
169 virtual object *dyn_cast_object () { return nullptr; }
170 virtual array *dyn_cast_array () { return nullptr; }
171 virtual integer_number *dyn_cast_integer_number () { return nullptr; }
172 virtual string *dyn_cast_string () { return nullptr; }
173
174 static int compare (const json::value &val_a, const json::value &val_b);
175
177
179};
180
181/* Subclass of value for objects: a collection of key/value pairs
182 preserving the ordering in which keys were inserted.
183
184 Preserving the order eliminates non-determinism in the output,
185 making it easier for the user to compare repeated invocations. */
186
187class object : public value
188{
189 public:
190 ~object ();
191
192 typedef hash_map <char *, value *,
194
195 enum kind get_kind () const final override { return JSON_OBJECT; }
196 void print (pretty_printer *pp, bool formatted) const final override;
197 std::unique_ptr<value> clone () const final override;
198
199 object *dyn_cast_object () final override { return this; }
200
201 bool is_empty () const { return m_map.is_empty (); }
202
203 void set (const char *key, value *v);
204
205 /* Set the property KEY of this object, requiring V
206 to be of a specific json::value subclass.
207
208 This can be used to enforce type-checking, making it easier
209 to comply with a schema, e.g.
210 obj->set<some_subclass> ("property_name", value)
211 leading to a compile-time error if VALUE is not of the
212 appropriate subclass. */
213 template <typename JsonType>
214 void set (const char *key, std::unique_ptr<JsonType> v)
215 {
216 set (key, v.release ());
217 }
218
219 value *get (const char *key) const;
220 const map_t &get_map () const { return m_map; }
221
222 void set_string (const char *key, const char *utf8_value);
223 void set_integer (const char *key, long v);
224 void set_float (const char *key, double v);
225
226 /* Set to literal true/false. */
227 void set_bool (const char *key, bool v);
228
229 /* Typesafe access to properties by name (such as from a schema). */
230 void set_string (const string_property &property, const char *utf8_value);
231 void set_integer (const integer_property &property, long value);
232 void set_bool (const bool_property &property, bool value);
234 std::unique_ptr<json::array> value);
235 template <typename EnumType>
237 EnumType &out) const;
238 template <typename EnumType>
240 EnumType value);
241
242 static int compare (const json::object &obj_a, const json::object &obj_b);
243
244 size_t get_num_keys () const { return m_keys.length (); }
245 const char *get_key (size_t i) const { return m_keys[i]; }
246
247 std::unique_ptr<object> clone_as_object () const;
248
249 private:
251
252 /* Keep track of order in which keys were inserted. */
253 auto_vec <const char *> m_keys;
254};
255
256/* Subclass of value for arrays. */
257
258class array : public value
259{
260 public:
261 ~array ();
262
263 enum kind get_kind () const final override { return JSON_ARRAY; }
264 void print (pretty_printer *pp, bool formatted) const final override;
265 std::unique_ptr<value> clone () const final override;
266
267 array *dyn_cast_array () final override { return this; }
268
269 void append (value *v);
270 void append_string (const char *utf8_value);
271
272 /* Append V to this array, requiring V
273 to be a specific json::value subclass.
274
275 This can be used to enforce type-checking, making it easier
276 to comply with a schema, e.g.
277 arr->append<some_subclass> (value)
278 leading to a compile-time error if VALUE is not of the
279 appropriate subclass. */
280 template <typename JsonType>
281 void append (std::unique_ptr<JsonType> v)
282 {
283 append (v.release ());
284 }
285
286 size_t size () const { return m_elements.length (); }
287 value *operator[] (size_t i) const { return m_elements[i]; }
288
289 value **begin () { return m_elements.begin (); }
290 value **end () { return m_elements.end (); }
291 const value * const *begin () const { return m_elements.begin (); }
292 const value * const *end () const { return m_elements.end (); }
293 size_t length () const { return m_elements.length (); }
294 value *get (size_t idx) const { return m_elements[idx]; }
295
296 private:
298};
299
300/* Subclass of value for floating-point numbers. */
301
302class float_number : public value
303{
304 public:
306
307 enum kind get_kind () const final override { return JSON_FLOAT; }
308 void print (pretty_printer *pp, bool formatted) const final override;
309 std::unique_ptr<value> clone () const final override;
310
311 double get () const { return m_value; }
312
313 private:
314 double m_value;
315};
316
317/* Subclass of value for integer-valued numbers. */
318
319class integer_number : public value
320{
321 public:
323
324 enum kind get_kind () const final override { return JSON_INTEGER; }
325 void print (pretty_printer *pp, bool formatted) const final override;
326 std::unique_ptr<value> clone () const final override;
327
328 integer_number *dyn_cast_integer_number () final override { return this; }
329
330 long get () const { return m_value; }
331
332 private:
334};
335
336
337/* Subclass of value for strings. */
338
339class string : public value
340{
341 public:
342 explicit string (const char *utf8);
343 string (const char *utf8, size_t len);
345
346 enum kind get_kind () const final override { return JSON_STRING; }
347 void print (pretty_printer *pp, bool formatted) const final override;
348 std::unique_ptr<value> clone () const final override;
349 string *dyn_cast_string () final override { return this; }
350
351 const char *get_string () const { return m_utf8; }
352 size_t get_length () const { return m_len; }
353
354 private:
355 char *m_utf8;
356 size_t m_len;
357};
358
359/* Subclass of value for the three JSON literals "true", "false",
360 and "null". */
361
362class literal : public value
363{
364 public:
366
367 /* Construct literal for a boolean value. */
369
370 enum kind get_kind () const final override { return m_kind; }
371 void print (pretty_printer *pp, bool formatted) const final override;
372 std::unique_ptr<value> clone () const final override;
373
374 private:
376};
377
378
379template <typename EnumType>
380inline bool
381object::maybe_get_enum (const enum_property<EnumType> &property,
382 EnumType &out) const
383{
384 if (value *jv = get (property.m_key.get ()))
385 if (string *jstr = jv->dyn_cast_string ())
386 {
387 if (enum_traits<EnumType>::maybe_get_value_from_string
388 (jstr->get_string (), out))
389 return true;
390 }
391 return false;
392}
393
394template <typename EnumType>
395inline void
397 EnumType value)
398{
399 const char *str
401 set_string (property.m_key.get (), str);
402}
403
404} // namespace json
405
406template <>
407template <>
408inline bool
410{
411 return true;
412}
413
414template <>
415template <>
416inline bool
418{
419 return true;
420}
421
422template <>
423template <>
424inline bool
426{
427 return jv->get_kind () == json::JSON_OBJECT;
428}
429
430template <>
431template <>
432inline bool
434{
435 return jv->get_kind () == json::JSON_OBJECT;
436}
437
438template <>
439template <>
440inline bool
442{
443 return jv->get_kind () == json::JSON_ARRAY;
444}
445
446template <>
447template <>
448inline bool
450{
451 return jv->get_kind () == json::JSON_ARRAY;
452}
453
454template <>
455template <>
456inline bool
458{
459 return jv->get_kind () == json::JSON_FLOAT;
460}
461
462template <>
463template <>
464inline bool
466{
467 return jv->get_kind () == json::JSON_FLOAT;
468}
469
470template <>
471template <>
472inline bool
474{
475 return jv->get_kind () == json::JSON_INTEGER;
476}
477
478template <>
479template <>
480inline bool
482{
483 return jv->get_kind () == json::JSON_INTEGER;
484}
485
486template <>
487template <>
488inline bool
490{
491 return jv->get_kind () == json::JSON_STRING;
492}
493
494template <>
495template <>
496inline bool
498{
499 return jv->get_kind () == json::JSON_STRING;
500}
501
502template <>
503template <>
504inline bool
506{
507 return (jv->get_kind () == json::JSON_TRUE
508 || jv->get_kind () == json::JSON_FALSE
509 || jv->get_kind () == json::JSON_NULL);
510}
511
512template <>
513template <>
514inline bool
516{
517 return (jv->get_kind () == json::JSON_TRUE
518 || jv->get_kind () == json::JSON_FALSE
519 || jv->get_kind () == json::JSON_NULL);
520}
521
522#if CHECKING_P
523
524namespace selftest {
525
526class location;
527
528extern void assert_print_eq (const location &loc,
529 const json::value &jv,
530 bool formatted,
531 const char *expected_json);
532
533} // namespace selftest
534
535#endif /* #if CHECKING_P */
536
537#endif /* GCC_JSON_H */
Definition vec.h:1667
Definition hash-map.h:40
Definition json.h:259
value ** end()
Definition json.h:290
enum kind get_kind() const final override
Definition json.h:263
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:468
auto_vec< value * > m_elements
Definition json.h:297
void append_string(const char *utf8_value)
Definition json.cc:517
array * dyn_cast_array() final override
Definition json.h:267
const value *const * end() const
Definition json.h:292
~array()
Definition json.cc:457
size_t size() const
Definition json.h:286
value ** begin()
Definition json.h:289
value * operator[](size_t i) const
Definition json.h:287
size_t length() const
Definition json.h:293
std::unique_ptr< value > clone() const final override
Definition json.cc:496
value * get(size_t idx) const
Definition json.h:294
const value *const * begin() const
Definition json.h:291
void append(value *v)
Definition json.cc:509
void append(std::unique_ptr< JsonType > v)
Definition json.h:281
Definition json.h:303
enum kind get_kind() const final override
Definition json.h:307
float_number(double value)
Definition json.h:305
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:528
std::unique_ptr< value > clone() const final override
Definition json.cc:537
double get() const
Definition json.h:311
double m_value
Definition json.h:314
Definition json.h:320
long m_value
Definition json.h:333
enum kind get_kind() const final override
Definition json.h:324
integer_number(long value)
Definition json.h:322
long get() const
Definition json.h:330
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:547
std::unique_ptr< value > clone() const final override
Definition json.cc:556
integer_number * dyn_cast_integer_number() final override
Definition json.h:328
Definition json.h:363
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:601
literal(bool value)
Definition json.h:368
enum kind m_kind
Definition json.h:375
literal(enum kind kind)
Definition json.h:365
std::unique_ptr< value > clone() const final override
Definition json.cc:621
enum kind get_kind() const final override
Definition json.h:370
Definition json.h:188
hash_map< char *, value *, simple_hashmap_traits< nofree_string_hash, value * > > map_t
Definition json.h:193
bool maybe_get_enum(const enum_property< EnumType > &property, EnumType &out) const
Definition json.h:381
void set(const char *key, value *v)
Definition json.cc:320
const map_t & get_map() const
Definition json.h:220
void set_array_of_string(const array_of_string_property &property, std::unique_ptr< json::array > value)
Definition json.cc:416
void set_string(const char *key, const char *utf8_value)
Definition json.cc:365
size_t get_num_keys() const
Definition json.h:244
void set_float(const char *key, double v)
Definition json.cc:383
enum kind get_kind() const final override
Definition json.h:195
auto_vec< const char * > m_keys
Definition json.h:253
void set_bool(const char *key, bool v)
Definition json.cc:392
map_t m_map
Definition json.h:250
object * dyn_cast_object() final override
Definition json.h:199
void set_integer(const char *key, long v)
Definition json.cc:374
value * get(const char *key) const
Definition json.cc:350
const char * get_key(size_t i) const
Definition json.h:245
void set_enum(const enum_property< EnumType > &property, EnumType value)
Definition json.h:396
void set(const char *key, std::unique_ptr< JsonType > v)
Definition json.h:214
static int compare(const json::object &obj_a, const json::object &obj_b)
Definition json.cc:425
bool is_empty() const
Definition json.h:201
std::unique_ptr< value > clone() const final override
Definition json.cc:293
~object()
Definition json.cc:242
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:254
std::unique_ptr< object > clone_as_object() const
Definition json.cc:299
Definition json.h:340
string(const char *utf8)
Definition json.cc:565
enum kind get_kind() const final override
Definition json.h:346
~string()
Definition json.h:344
const char * get_string() const
Definition json.h:351
size_t m_len
Definition json.h:356
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:584
char * m_utf8
Definition json.h:355
std::unique_ptr< value > clone() const final override
Definition json.cc:591
size_t get_length() const
Definition json.h:352
string * dyn_cast_string() final override
Definition json.h:349
Definition json.h:159
virtual string * dyn_cast_string()
Definition json.h:172
virtual enum kind get_kind() const =0
virtual std::unique_ptr< value > clone() const =0
virtual object * dyn_cast_object()
Definition json.h:169
static int compare(const json::value &val_a, const json::value &val_b)
Definition json.cc:163
virtual void print(pretty_printer *pp, bool formatted) const =0
virtual integer_number * dyn_cast_integer_number()
Definition json.h:171
void DEBUG_FUNCTION dump() const
Definition json.cc:143
const pointer::token & get_pointer_token() const
Definition json.h:176
pointer::token m_pointer_token
Definition json.h:178
virtual array * dyn_cast_array()
Definition json.h:170
virtual ~value()
Definition json.h:161
Definition pretty-print.h:241
void final(rtx_insn *first, FILE *file, int optimize_p)
Definition final.cc:2009
free(str)
Definition json.h:78
Definition json-parsing.h:27
property< literal > bool_property
Definition json.h:139
property< value > json_property
Definition json.h:140
property< integer_number > integer_property
Definition json.h:138
kind
Definition json.h:55
@ JSON_ARRAY
Definition json.h:60
@ JSON_FALSE
Definition json.h:74
@ JSON_INTEGER
Definition json.h:63
@ JSON_NULL
Definition json.h:75
@ JSON_OBJECT
Definition json.h:57
@ JSON_TRUE
Definition json.h:73
@ JSON_FLOAT
Definition json.h:66
@ JSON_STRING
Definition json.h:69
property< array > array_of_string_property
Definition json.h:141
property< string > string_property
Definition json.h:137
property< enum_traits< EnumType > > enum_property
Definition json.h:154
Definition dump-context.h:31
if(N >=2) for(unsigned int i
i
Definition poly-int.h:776
static bool test(U *p)
Definition json.h:145
EnumType enum_t
Definition json.h:146
static enum_t get_unknown_value()
static bool maybe_get_value_from_string(const char *, enum_t &out)
static const char * get_string_for_value(enum_t value)
Definition json.h:88
union json::pointer::token::u m_data
json::value * m_parent
Definition json.h:110
token()
Definition json.cc:79
~token()
Definition json.cc:100
enum kind m_kind
Definition json.h:116
kind
Definition json.h:90
@ object_member
Definition json.h:92
@ array_index
Definition json.h:93
@ root_value
Definition json.h:91
token(token &&other)=delete
token & operator=(const token &other)=delete
token(const token &other)=delete
Definition json.h:125
property(const char *key_prefix, const char *key)
Definition json.h:130
label_text m_key
Definition json.h:134
property(const char *key)
Definition json.h:126
Definition hash-map-traits.h:33
#define DEBUG_FUNCTION
Definition system.h:1236
Definition json.h:112
char * u_member
Definition json.h:113
size_t u_index
Definition json.h:114