Branch data Line data Source code
1 : : /* JSON trees
2 : : Copyright (C) 2017-2025 Free Software Foundation, Inc.
3 : : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it under
8 : : the terms of the GNU General Public License as published by the Free
9 : : Software Foundation; either version 3, or (at your option) any later
10 : : version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : : for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along 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 : : /* Implementation of JSON, a lightweight data-interchange format.
25 : :
26 : : See http://www.json.org/
27 : : and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
28 : : and https://tools.ietf.org/html/rfc7159
29 : :
30 : : Supports parsing text into a DOM-like tree of json::value *, directly
31 : : creating such trees, and dumping json::value * to text. */
32 : :
33 : : /* TODO: `libcpp/mkdeps.cc` wants JSON writing support for p1689r5 output;
34 : : extract this code and move to libiberty. */
35 : :
36 : : namespace json
37 : : {
38 : :
39 : : /* Forward decls of json::value and its subclasses (using indentation
40 : : to denote inheritance. */
41 : :
42 : : class value;
43 : : class object;
44 : : class array;
45 : : class float_number;
46 : : class integer_number;
47 : : class string;
48 : : class literal;
49 : :
50 : : /* An enum for discriminating the subclasses of json::value. */
51 : :
52 : : enum kind
53 : : {
54 : : /* class json::object. */
55 : : JSON_OBJECT,
56 : :
57 : : /* class json::array. */
58 : : JSON_ARRAY,
59 : :
60 : : /* class json::integer_number. */
61 : : JSON_INTEGER,
62 : :
63 : : /* class json::float_number. */
64 : : JSON_FLOAT,
65 : :
66 : : /* class json::string. */
67 : : JSON_STRING,
68 : :
69 : : /* class json::literal uses these three values to identify the
70 : : particular literal. */
71 : : JSON_TRUE,
72 : : JSON_FALSE,
73 : : JSON_NULL
74 : : };
75 : :
76 : : namespace pointer { // json::pointer
77 : :
78 : : /* Implementation of JSON pointer (RFC 6901). */
79 : :
80 : : /* A token within a JSON pointer, expressing the parent of a particular
81 : : JSON value, and how it is descended from that parent.
82 : :
83 : : A JSON pointer can be built as a list of these tokens. */
84 : :
85 : : struct token
86 : : {
87 : : enum class kind
88 : : {
89 : : root_value,
90 : : object_member,
91 : : array_index
92 : : };
93 : :
94 : : token ();
95 : : token (json::object &parent, const char *member);
96 : : token (json::array &parent, size_t index);
97 : : token (const token &other) = delete;
98 : : token (token &&other) = delete;
99 : :
100 : : ~token ();
101 : :
102 : : token &
103 : : operator= (const token &other) = delete;
104 : :
105 : : token &
106 : : operator= (token &&other);
107 : :
108 : : json::value *m_parent;
109 : : union u
110 : : {
111 : : char *u_member;
112 : : size_t u_index;
113 : : } m_data;
114 : : enum kind m_kind;
115 : : };
116 : :
117 : : } // namespace json::pointer
118 : :
119 : : /* Base class of JSON value. */
120 : :
121 : 2695141 : class value
122 : : {
123 : : public:
124 : 3444701 : virtual ~value () {}
125 : : virtual enum kind get_kind () const = 0;
126 : : virtual void print (pretty_printer *pp, bool formatted) const = 0;
127 : : virtual std::unique_ptr<value> clone () const = 0;
128 : :
129 : : void dump (FILE *, bool formatted) const;
130 : : void DEBUG_FUNCTION dump () const;
131 : :
132 : 0 : virtual object *dyn_cast_object () { return nullptr; }
133 : 0 : virtual string *dyn_cast_string () { return nullptr; }
134 : :
135 : : static int compare (const json::value &val_a, const json::value &val_b);
136 : :
137 : : const pointer::token &get_pointer_token () const { return m_pointer_token; }
138 : :
139 : : pointer::token m_pointer_token;
140 : : };
141 : :
142 : : /* Subclass of value for objects: a collection of key/value pairs
143 : : preserving the ordering in which keys were inserted.
144 : :
145 : : Preserving the order eliminates non-determinism in the output,
146 : : making it easier for the user to compare repeated invocations. */
147 : :
148 : : class object : public value
149 : : {
150 : : public:
151 : : ~object ();
152 : :
153 : 17795 : enum kind get_kind () const final override { return JSON_OBJECT; }
154 : : void print (pretty_printer *pp, bool formatted) const final override;
155 : : std::unique_ptr<value> clone () const final override;
156 : :
157 : 275 : object *dyn_cast_object () final override { return this; }
158 : :
159 : 465 : bool is_empty () const { return m_map.is_empty (); }
160 : :
161 : : void set (const char *key, value *v);
162 : :
163 : : /* Set the property KEY of this object, requiring V
164 : : to be of a specific json::value subclass.
165 : :
166 : : This can be used to enforce type-checking, making it easier
167 : : to comply with a schema, e.g.
168 : : obj->set<some_subclass> ("property_name", value)
169 : : leading to a compile-time error if VALUE is not of the
170 : : appropriate subclass. */
171 : : template <typename JsonType>
172 : 15009 : void set (const char *key, std::unique_ptr<JsonType> v)
173 : : {
174 : 15059 : set (key, v.release ());
175 : : }
176 : :
177 : : value *get (const char *key) const;
178 : :
179 : : void set_string (const char *key, const char *utf8_value);
180 : : void set_integer (const char *key, long v);
181 : : void set_float (const char *key, double v);
182 : :
183 : : /* Set to literal true/false. */
184 : : void set_bool (const char *key, bool v);
185 : :
186 : : static int compare (const json::object &obj_a, const json::object &obj_b);
187 : :
188 : 2187 : size_t get_num_keys () const { return m_keys.length (); }
189 : 1616 : const char *get_key (size_t i) const { return m_keys[i]; }
190 : :
191 : : std::unique_ptr<object> clone_as_object () const;
192 : :
193 : : private:
194 : : typedef hash_map <char *, value *,
195 : : simple_hashmap_traits<nofree_string_hash, value *> > map_t;
196 : : map_t m_map;
197 : :
198 : : /* Keep track of order in which keys were inserted. */
199 : : auto_vec <const char *> m_keys;
200 : : };
201 : :
202 : : /* Subclass of value for arrays. */
203 : :
204 : 615651 : class array : public value
205 : : {
206 : : public:
207 : : ~array ();
208 : :
209 : 776 : enum kind get_kind () const final override { return JSON_ARRAY; }
210 : : void print (pretty_printer *pp, bool formatted) const final override;
211 : : std::unique_ptr<value> clone () const final override;
212 : :
213 : : void append (value *v);
214 : : void append_string (const char *utf8_value);
215 : :
216 : : /* Append V to this array, requiring V
217 : : to be a specific json::value subclass.
218 : :
219 : : This can be used to enforce type-checking, making it easier
220 : : to comply with a schema, e.g.
221 : : arr->append<some_subclass> (value)
222 : : leading to a compile-time error if VALUE is not of the
223 : : appropriate subclass. */
224 : : template <typename JsonType>
225 : 4086 : void append (std::unique_ptr<JsonType> v)
226 : : {
227 : 4086 : append (v.release ());
228 : : }
229 : :
230 : 1861 : size_t size () const { return m_elements.length (); }
231 : 916 : value *operator[] (size_t i) const { return m_elements[i]; }
232 : :
233 : : value **begin () { return m_elements.begin (); }
234 : : value **end () { return m_elements.end (); }
235 : : const value * const *begin () const { return m_elements.begin (); }
236 : : const value * const *end () const { return m_elements.end (); }
237 : 376 : size_t length () const { return m_elements.length (); }
238 : 323 : value *get (size_t idx) const { return m_elements[idx]; }
239 : :
240 : : private:
241 : : auto_vec<value *> m_elements;
242 : : };
243 : :
244 : : /* Subclass of value for floating-point numbers. */
245 : :
246 : 24 : class float_number : public value
247 : : {
248 : : public:
249 : 56 : float_number (double value) : m_value (value) {}
250 : :
251 : 84 : enum kind get_kind () const final override { return JSON_FLOAT; }
252 : : void print (pretty_printer *pp, bool formatted) const final override;
253 : : std::unique_ptr<value> clone () const final override;
254 : :
255 : 44 : double get () const { return m_value; }
256 : :
257 : : private:
258 : : double m_value;
259 : : };
260 : :
261 : : /* Subclass of value for integer-valued numbers. */
262 : :
263 : 28 : class integer_number : public value
264 : : {
265 : : public:
266 : 666643 : integer_number (long value) : m_value (value) {}
267 : :
268 : 2442 : enum kind get_kind () const final override { return JSON_INTEGER; }
269 : : void print (pretty_printer *pp, bool formatted) const final override;
270 : : std::unique_ptr<value> clone () const final override;
271 : :
272 : 2321 : long get () const { return m_value; }
273 : :
274 : : private:
275 : : long m_value;
276 : : };
277 : :
278 : :
279 : : /* Subclass of value for strings. */
280 : :
281 : : class string : public value
282 : : {
283 : : public:
284 : : explicit string (const char *utf8);
285 : : string (const char *utf8, size_t len);
286 : 4157526 : ~string () { free (m_utf8); }
287 : :
288 : 21684 : enum kind get_kind () const final override { return JSON_STRING; }
289 : : void print (pretty_printer *pp, bool formatted) const final override;
290 : : std::unique_ptr<value> clone () const final override;
291 : 41 : string *dyn_cast_string () final override { return this; }
292 : :
293 : 11503 : const char *get_string () const { return m_utf8; }
294 : : size_t get_length () const { return m_len; }
295 : :
296 : : private:
297 : : char *m_utf8;
298 : : size_t m_len;
299 : : };
300 : :
301 : : /* Subclass of value for the three JSON literals "true", "false",
302 : : and "null". */
303 : :
304 : 28 : class literal : public value
305 : : {
306 : : public:
307 : 44 : literal (enum kind kind) : m_kind (kind) {}
308 : :
309 : : /* Construct literal for a boolean value. */
310 : 726 : literal (bool value): m_kind (value ? JSON_TRUE : JSON_FALSE) {}
311 : :
312 : 144 : enum kind get_kind () const final override { return m_kind; }
313 : : void print (pretty_printer *pp, bool formatted) const final override;
314 : : std::unique_ptr<value> clone () const final override;
315 : :
316 : : private:
317 : : enum kind m_kind;
318 : : };
319 : :
320 : : } // namespace json
321 : :
322 : : template <>
323 : : template <>
324 : : inline bool
325 : : is_a_helper <json::value *>::test (json::value *)
326 : : {
327 : : return true;
328 : : }
329 : :
330 : : template <>
331 : : template <>
332 : : inline bool
333 : : is_a_helper <const json::value *>::test (const json::value *)
334 : : {
335 : : return true;
336 : : }
337 : :
338 : : template <>
339 : : template <>
340 : : inline bool
341 : : is_a_helper <json::object *>::test (json::value *jv)
342 : : {
343 : : return jv->get_kind () == json::JSON_OBJECT;
344 : : }
345 : :
346 : : template <>
347 : : template <>
348 : : inline bool
349 : : is_a_helper <const json::object *>::test (const json::value *jv)
350 : : {
351 : : return jv->get_kind () == json::JSON_OBJECT;
352 : : }
353 : :
354 : : template <>
355 : : template <>
356 : : inline bool
357 : 4 : is_a_helper <json::array *>::test (json::value *jv)
358 : : {
359 : 4 : return jv->get_kind () == json::JSON_ARRAY;
360 : : }
361 : :
362 : : template <>
363 : : template <>
364 : : inline bool
365 : 4 : is_a_helper <const json::array *>::test (const json::value *jv)
366 : : {
367 : 4 : return jv->get_kind () == json::JSON_ARRAY;
368 : : }
369 : :
370 : : template <>
371 : : template <>
372 : : inline bool
373 : : is_a_helper <json::float_number *>::test (json::value *jv)
374 : : {
375 : : return jv->get_kind () == json::JSON_FLOAT;
376 : : }
377 : :
378 : : template <>
379 : : template <>
380 : : inline bool
381 : 8 : is_a_helper <const json::float_number *>::test (const json::value *jv)
382 : : {
383 : 8 : return jv->get_kind () == json::JSON_FLOAT;
384 : : }
385 : :
386 : : template <>
387 : : template <>
388 : : inline bool
389 : 44 : is_a_helper <json::integer_number *>::test (json::value *jv)
390 : : {
391 : 44 : return jv->get_kind () == json::JSON_INTEGER;
392 : : }
393 : :
394 : : template <>
395 : : template <>
396 : : inline bool
397 : 12 : is_a_helper <const json::integer_number *>::test (const json::value *jv)
398 : : {
399 : 12 : return jv->get_kind () == json::JSON_INTEGER;
400 : : }
401 : :
402 : : template <>
403 : : template <>
404 : : inline bool
405 : 4 : is_a_helper <json::string *>::test (json::value *jv)
406 : : {
407 : 4 : return jv->get_kind () == json::JSON_STRING;
408 : : }
409 : :
410 : : template <>
411 : : template <>
412 : : inline bool
413 : 16 : is_a_helper <const json::string *>::test (const json::value *jv)
414 : : {
415 : 16 : return jv->get_kind () == json::JSON_STRING;
416 : : }
417 : :
418 : : #if CHECKING_P
419 : :
420 : : namespace selftest {
421 : :
422 : : class location;
423 : :
424 : : extern void assert_print_eq (const location &loc,
425 : : const json::value &jv,
426 : : bool formatted,
427 : : const char *expected_json);
428 : :
429 : : } // namespace selftest
430 : :
431 : : #endif /* #if CHECKING_P */
432 : :
433 : : #endif /* GCC_JSON_H */
|