GCC Middle and Back End API Reference
json.h
Go to the documentation of this file.
1/* JSON trees
2 Copyright (C) 2017-2026 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{
89 enum class kind
90 {
91 root_value,
92 object_member,
93 array_index
94 };
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
110 void print (pretty_printer *pp) const;
111
113 union u
114 {
115 char *u_member;
116 size_t u_index;
119};
120
121} // namespace json::pointer
122
123/* Typesafe way to work with properties in JSON objects. */
124
125template <typename Traits>
127{
128 explicit property (const char *key)
129 : m_key (label_text::borrow (key))
130 {}
131
132 explicit property (const char *key_prefix, const char *key)
133 : m_key (label_text::take (concat (key_prefix, key, nullptr)))
134 {}
135
136 label_text m_key;
137};
138
144
145template <typename EnumType>
147{
148 typedef EnumType enum_t;
149
151 static bool maybe_get_value_from_string (const char *, enum_t &out);
152 static const char *get_string_for_value (enum_t value);
153};
154
155template <typename EnumType>
157
158/* Base class of JSON value. */
159
160class value
161{
162 public:
163 virtual ~value () {}
164 virtual enum kind get_kind () const = 0;
165 virtual void print (pretty_printer *pp, bool formatted) const = 0;
166 virtual std::unique_ptr<value> clone () const = 0;
167
168 void dump (FILE *, bool formatted) const;
169 void DEBUG_FUNCTION dump () const;
170
171 virtual object *dyn_cast_object () { return nullptr; }
172 virtual array *dyn_cast_array () { return nullptr; }
173 virtual integer_number *dyn_cast_integer_number () { return nullptr; }
174 virtual string *dyn_cast_string () { return nullptr; }
175
176 static int compare (const json::value &val_a, const json::value &val_b);
177
179 void print_pointer (pretty_printer *pp) const;
180
182};
183
184/* Subclass of value for objects: a collection of key/value pairs
185 preserving the ordering in which keys were inserted.
186
187 Preserving the order eliminates non-determinism in the output,
188 making it easier for the user to compare repeated invocations. */
189
190class object : public value
191{
192 public:
193 ~object ();
194
195 typedef hash_map <char *, value *,
197
198 enum kind get_kind () const final override { return JSON_OBJECT; }
199 void print (pretty_printer *pp, bool formatted) const final override;
200 std::unique_ptr<value> clone () const final override;
201
202 object *dyn_cast_object () final override { return this; }
203
204 bool is_empty () const { return m_map.is_empty (); }
205
206 void set (const char *key, value *v);
207
208 /* Set the property KEY of this object, requiring V
209 to be of a specific json::value subclass.
210
211 This can be used to enforce type-checking, making it easier
212 to comply with a schema, e.g.
213 obj->set<some_subclass> ("property_name", value)
214 leading to a compile-time error if VALUE is not of the
215 appropriate subclass. */
216 template <typename JsonType>
217 void set (const char *key, std::unique_ptr<JsonType> v)
218 {
219 set (key, v.release ());
220 }
221
222 value *get (const char *key) const;
223 const map_t &get_map () const { return m_map; }
224
225 const json::string *set_string (const char *key, const char *utf8_value);
226 const json::string *set_string (const char *key, std::string utf8_value);
227 const json::integer_number *set_integer (const char *key, long v);
228 void set_float (const char *key, double v);
229
230 /* Set to literal true/false. */
231 void set_bool (const char *key, bool v);
232
233 /* Typesafe access to properties by name (such as from a schema). */
234 void set_string (const string_property &property, const char *utf8_value);
235 void set_integer (const integer_property &property, long value);
236 void set_bool (const bool_property &property, bool value);
238 std::unique_ptr<json::array> value);
239 template <typename EnumType>
241 EnumType &out) const;
242 template <typename EnumType>
244 EnumType value);
245
246 static int compare (const json::object &obj_a, const json::object &obj_b);
247
248 size_t get_num_keys () const { return m_keys.length (); }
249 const char *get_key (size_t i) const { return m_keys[i]; }
250
251 std::unique_ptr<object> clone_as_object () const;
252
253 private:
255
256 /* Keep track of order in which keys were inserted. */
257 auto_vec <const char *> m_keys;
258};
259
260/* Subclass of value for arrays. */
261
262class array : public value
263{
264 public:
265 ~array ();
266
267 enum kind get_kind () const final override { return JSON_ARRAY; }
268 void print (pretty_printer *pp, bool formatted) const final override;
269 std::unique_ptr<value> clone () const final override;
270
271 array *dyn_cast_array () final override { return this; }
272
273 void append (value *v);
274 const json::string *append_string (const char *utf8_value);
275
276 /* Append V to this array, requiring V
277 to be a specific json::value subclass.
278
279 This can be used to enforce type-checking, making it easier
280 to comply with a schema, e.g.
281 arr->append<some_subclass> (value)
282 leading to a compile-time error if VALUE is not of the
283 appropriate subclass. */
284 template <typename JsonType>
285 void append (std::unique_ptr<JsonType> v)
286 {
287 append (v.release ());
288 }
289
290 size_t size () const { return m_elements.length (); }
291 value *operator[] (size_t i) const { return m_elements[i]; }
292
293 value **begin () { return m_elements.begin (); }
294 value **end () { return m_elements.end (); }
295 const value * const *begin () const { return m_elements.begin (); }
296 const value * const *end () const { return m_elements.end (); }
297 size_t length () const { return m_elements.length (); }
298 value *get (size_t idx) const { return m_elements[idx]; }
299
300 private:
302};
303
304/* Subclass of value for floating-point numbers. */
305
306class float_number : public value
307{
308 public:
310
311 enum kind get_kind () const final override { return JSON_FLOAT; }
312 void print (pretty_printer *pp, bool formatted) const final override;
313 std::unique_ptr<value> clone () const final override;
314
315 double get () const { return m_value; }
316
317 private:
318 double m_value;
319};
320
321/* Subclass of value for integer-valued numbers. */
322
323class integer_number : public value
324{
325 public:
327
328 enum kind get_kind () const final override { return JSON_INTEGER; }
329 void print (pretty_printer *pp, bool formatted) const final override;
330 std::unique_ptr<value> clone () const final override;
331
332 integer_number *dyn_cast_integer_number () final override { return this; }
333
334 long get () const { return m_value; }
335
336 private:
338};
339
340
341/* Subclass of value for strings. */
342
343class string : public value
344{
345 public:
346 explicit string (const char *utf8);
347 string (const char *utf8, size_t len);
349
350 enum kind get_kind () const final override { return JSON_STRING; }
351 void print (pretty_printer *pp, bool formatted) const final override;
352 std::unique_ptr<value> clone () const final override;
353 string *dyn_cast_string () final override { return this; }
354
355 const char *get_string () const { return m_utf8; }
356 size_t get_length () const { return m_len; }
357
358 private:
359 char *m_utf8;
360 size_t m_len;
361};
362
363/* Subclass of value for the three JSON literals "true", "false",
364 and "null". */
365
366class literal : public value
367{
368 public:
370
371 /* Construct literal for a boolean value. */
373
374 enum kind get_kind () const final override { return m_kind; }
375 void print (pretty_printer *pp, bool formatted) const final override;
376 std::unique_ptr<value> clone () const final override;
377
378 private:
380};
381
382
383template <typename EnumType>
384inline bool
385object::maybe_get_enum (const enum_property<EnumType> &property,
386 EnumType &out) const
387{
388 if (value *jv = get (property.m_key.get ()))
389 if (string *jstr = jv->dyn_cast_string ())
390 {
391 if (enum_traits<EnumType>::maybe_get_value_from_string
392 (jstr->get_string (), out))
393 return true;
394 }
395 return false;
396}
397
398template <typename EnumType>
399inline void
401 EnumType value)
402{
403 const char *str
405 set_string (property.m_key.get (), str);
406}
407
408} // namespace json
409
410template <>
411template <>
412inline bool
414{
415 return true;
416}
417
418template <>
419template <>
420inline bool
422{
423 return true;
424}
425
426template <>
427template <>
428inline bool
430{
431 return jv->get_kind () == json::JSON_OBJECT;
432}
433
434template <>
435template <>
436inline bool
438{
439 return jv->get_kind () == json::JSON_OBJECT;
440}
441
442template <>
443template <>
444inline bool
446{
447 return jv->get_kind () == json::JSON_ARRAY;
448}
449
450template <>
451template <>
452inline bool
454{
455 return jv->get_kind () == json::JSON_ARRAY;
456}
457
458template <>
459template <>
460inline bool
462{
463 return jv->get_kind () == json::JSON_FLOAT;
464}
465
466template <>
467template <>
468inline bool
470{
471 return jv->get_kind () == json::JSON_FLOAT;
472}
473
474template <>
475template <>
476inline bool
478{
479 return jv->get_kind () == json::JSON_INTEGER;
480}
481
482template <>
483template <>
484inline bool
486{
487 return jv->get_kind () == json::JSON_INTEGER;
488}
489
490template <>
491template <>
492inline bool
494{
495 return jv->get_kind () == json::JSON_STRING;
496}
497
498template <>
499template <>
500inline bool
502{
503 return jv->get_kind () == json::JSON_STRING;
504}
505
506template <>
507template <>
508inline bool
510{
511 return (jv->get_kind () == json::JSON_TRUE
512 || jv->get_kind () == json::JSON_FALSE
513 || jv->get_kind () == json::JSON_NULL);
514}
515
516template <>
517template <>
518inline bool
520{
521 return (jv->get_kind () == json::JSON_TRUE
522 || jv->get_kind () == json::JSON_FALSE
523 || jv->get_kind () == json::JSON_NULL);
524}
525
526#if CHECKING_P
527
528namespace selftest {
529
530class location;
531
532extern void assert_print_eq (const location &loc,
533 const json::value &jv,
534 bool formatted,
535 const char *expected_json);
536
537} // namespace selftest
538
539#endif /* #if CHECKING_P */
540
541#endif /* GCC_JSON_H */
Definition vec.h:1667
Definition hash-map.h:40
bool is_empty() const
Definition hash-map.h:252
Definition json.h:263
value ** end()
Definition json.h:294
enum kind get_kind() const final override
Definition json.h:267
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:544
auto_vec< value * > m_elements
Definition json.h:301
array * dyn_cast_array() final override
Definition json.h:271
const value *const * end() const
Definition json.h:296
size_t size() const
Definition json.h:290
value ** begin()
Definition json.h:293
value * operator[](size_t i) const
Definition json.h:291
size_t length() const
Definition json.h:297
std::unique_ptr< value > clone() const final override
Definition json.cc:572
const json::string * append_string(const char *utf8_value)
Definition json.cc:596
value * get(size_t idx) const
Definition json.h:298
const value *const * begin() const
Definition json.h:295
void append(value *v)
Definition json.cc:585
void append(std::unique_ptr< JsonType > v)
Definition json.h:285
Definition json.h:307
enum kind get_kind() const final override
Definition json.h:311
float_number(double value)
Definition json.h:309
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:609
std::unique_ptr< value > clone() const final override
Definition json.cc:618
double get() const
Definition json.h:315
double m_value
Definition json.h:318
Definition json.h:324
long m_value
Definition json.h:337
enum kind get_kind() const final override
Definition json.h:328
integer_number(long value)
Definition json.h:326
long get() const
Definition json.h:334
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:628
std::unique_ptr< value > clone() const final override
Definition json.cc:637
integer_number * dyn_cast_integer_number() final override
Definition json.h:332
Definition json.h:367
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:682
literal(bool value)
Definition json.h:372
enum kind m_kind
Definition json.h:379
literal(enum kind kind)
Definition json.h:369
std::unique_ptr< value > clone() const final override
Definition json.cc:702
enum kind get_kind() const final override
Definition json.h:374
Definition json.h:191
hash_map< char *, value *, simple_hashmap_traits< nofree_string_hash, value * > > map_t
Definition json.h:196
bool maybe_get_enum(const enum_property< EnumType > &property, EnumType &out) const
Definition json.h:385
void set(const char *key, value *v)
Definition json.cc:380
const map_t & get_map() const
Definition json.h:223
void set_array_of_string(const array_of_string_property &property, std::unique_ptr< json::array > value)
Definition json.cc:492
size_t get_num_keys() const
Definition json.h:248
void set_float(const char *key, double v)
Definition json.cc:459
enum kind get_kind() const final override
Definition json.h:198
auto_vec< const char * > m_keys
Definition json.h:257
const json::string * set_string(const char *key, const char *utf8_value)
Definition json.cc:426
void set_bool(const char *key, bool v)
Definition json.cc:468
map_t m_map
Definition json.h:254
object * dyn_cast_object() final override
Definition json.h:202
const json::integer_number * set_integer(const char *key, long v)
Definition json.cc:448
value * get(const char *key) const
Definition json.cc:410
const char * get_key(size_t i) const
Definition json.h:249
void set_enum(const enum_property< EnumType > &property, EnumType value)
Definition json.h:400
void set(const char *key, std::unique_ptr< JsonType > v)
Definition json.h:217
static int compare(const json::object &obj_a, const json::object &obj_b)
Definition json.cc:501
bool is_empty() const
Definition json.h:204
std::unique_ptr< value > clone() const final override
Definition json.cc:353
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:314
std::unique_ptr< object > clone_as_object() const
Definition json.cc:359
Definition json.h:344
string(const char *utf8)
Definition json.cc:646
enum kind get_kind() const final override
Definition json.h:350
~string()
Definition json.h:348
const char * get_string() const
Definition json.h:355
size_t m_len
Definition json.h:360
void print(pretty_printer *pp, bool formatted) const final override
Definition json.cc:665
char * m_utf8
Definition json.h:359
std::unique_ptr< value > clone() const final override
Definition json.cc:672
size_t get_length() const
Definition json.h:356
string * dyn_cast_string() final override
Definition json.h:353
Definition json.h:161
virtual string * dyn_cast_string()
Definition json.h:174
virtual enum kind get_kind() const =0
virtual std::unique_ptr< value > clone() const =0
virtual object * dyn_cast_object()
Definition json.h:171
void print_pointer(pretty_printer *pp) const
Definition json.cc:277
static int compare(const json::value &val_a, const json::value &val_b)
Definition json.cc:200
virtual void print(pretty_printer *pp, bool formatted) const =0
virtual integer_number * dyn_cast_integer_number()
Definition json.h:173
void dump(FILE *, bool formatted) const
Definition json.cc:168
const pointer::token & get_pointer_token() const
Definition json.h:178
pointer::token m_pointer_token
Definition json.h:181
virtual array * dyn_cast_array()
Definition json.h:172
virtual ~value()
Definition json.h:163
Definition pretty-print.h:241
void final(rtx_insn *first, FILE *file, int optimize_p)
Definition final.cc:2001
free(str)
Definition cfghooks.h:27
property< literal > bool_property
Definition json.h:141
property< value > json_property
Definition json.h:142
property< integer_number > integer_property
Definition json.h:140
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:143
property< string > string_property
Definition json.h:139
property< enum_traits< EnumType > > enum_property
Definition json.h:156
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:147
EnumType enum_t
Definition json.h:148
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
void print(pretty_printer *pp) const
Definition json.cc:127
union json::pointer::token::u m_data
json::value * m_parent
Definition json.h:112
token()
Definition json.cc:80
enum kind m_kind
Definition json.h:118
kind
Definition json.h:90
token(token &&other)=delete
token & operator=(const token &other)=delete
token(const token &other)=delete
Definition json.h:127
property(const char *key_prefix, const char *key)
Definition json.h:132
label_text m_key
Definition json.h:136
property(const char *key)
Definition json.h:128
Definition cse.cc:4184
Definition hash-map-traits.h:33
#define DEBUG_FUNCTION
Definition system.h:1145
Definition json.h:114
char * u_member
Definition json.h:115
size_t u_index
Definition json.h:116