]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/json.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / json.cc
CommitLineData
4a4412b9 1/* JSON trees
99dee823 2 Copyright (C) 2017-2021 Free Software Foundation, Inc.
4a4412b9
DM
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#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "json.h"
25#include "pretty-print.h"
26#include "math.h"
27#include "selftest.h"
28
29using namespace json;
30
31/* class json::value. */
32
33/* Dump this json::value tree to OUTF.
34 No formatting is done. There are no guarantees about the order
35 in which the key/value pairs of json::objects are printed. */
36
37void
38value::dump (FILE *outf) const
39{
40 pretty_printer pp;
41 pp_buffer (&pp)->stream = outf;
42 print (&pp);
43 pp_flush (&pp);
44}
45
46/* class json::object, a subclass of json::value, representing
47 an unordered collection of key/value pairs. */
48
49/* json:object's dtor. */
50
51object::~object ()
52{
53 for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it)
54 {
55 free (const_cast <char *>((*it).first));
56 delete ((*it).second);
57 }
58}
59
60/* Implementation of json::value::print for json::object. */
61
62void
63object::print (pretty_printer *pp) const
64{
65 /* Note that the order is not guaranteed. */
66 pp_character (pp, '{');
67 for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it)
68 {
69 if (it != m_map.begin ())
70 pp_string (pp, ", ");
71 const char *key = const_cast <char *>((*it).first);
72 value *value = (*it).second;
ca23341b
MS
73 pp_doublequote (pp);
74 pp_string (pp, key); // FIXME: escaping?
75 pp_doublequote (pp);
76 pp_string (pp, ": ");
4a4412b9
DM
77 value->print (pp);
78 }
79 pp_character (pp, '}');
80}
81
dad2580c 82/* Set the json::value * for KEY, taking ownership of V
4a4412b9
DM
83 (and taking a copy of KEY if necessary). */
84
85void
86object::set (const char *key, value *v)
87{
dad2580c
DM
88 gcc_assert (key);
89 gcc_assert (v);
90
4a4412b9
DM
91 value **ptr = m_map.get (key);
92 if (ptr)
93 {
94 /* If the key is already present, delete the existing value
95 and overwrite it. */
96 delete *ptr;
97 *ptr = v;
98 }
99 else
100 /* If the key wasn't already present, take a copy of the key,
101 and store the value. */
102 m_map.put (xstrdup (key), v);
103}
104
30d3ba51
DM
105/* Get the json::value * for KEY.
106
107 The object retains ownership of the value. */
108
109value *
110object::get (const char *key) const
111{
112 gcc_assert (key);
113
114 value **ptr = const_cast <map_t &> (m_map).get (key);
115 if (ptr)
116 return *ptr;
117 else
118 return NULL;
119}
120
4a4412b9
DM
121/* class json::array, a subclass of json::value, representing
122 an ordered collection of values. */
123
124/* json::array's dtor. */
125
126array::~array ()
127{
128 unsigned i;
129 value *v;
130 FOR_EACH_VEC_ELT (m_elements, i, v)
131 delete v;
132}
133
134/* Implementation of json::value::print for json::array. */
135
136void
137array::print (pretty_printer *pp) const
138{
139 pp_character (pp, '[');
140 unsigned i;
141 value *v;
142 FOR_EACH_VEC_ELT (m_elements, i, v)
143 {
144 if (i)
145 pp_string (pp, ", ");
146 v->print (pp);
147 }
148 pp_character (pp, ']');
149}
150
dad2580c
DM
151/* Append non-NULL value V to a json::array, taking ownership of V. */
152
153void
154array::append (value *v)
155{
156 gcc_assert (v);
157 m_elements.safe_push (v);
158}
159
07622278 160/* class json::float_number, a subclass of json::value, wrapping a double. */
4a4412b9 161
07622278 162/* Implementation of json::value::print for json::float_number. */
4a4412b9
DM
163
164void
07622278 165float_number::print (pretty_printer *pp) const
4a4412b9
DM
166{
167 char tmp[1024];
168 snprintf (tmp, sizeof (tmp), "%g", m_value);
169 pp_string (pp, tmp);
170}
171
07622278
ML
172/* class json::integer_number, a subclass of json::value, wrapping a long. */
173
174/* Implementation of json::value::print for json::integer_number. */
175
176void
177integer_number::print (pretty_printer *pp) const
178{
179 char tmp[1024];
180 snprintf (tmp, sizeof (tmp), "%ld", m_value);
181 pp_string (pp, tmp);
182}
183
184
4a4412b9
DM
185/* class json::string, a subclass of json::value. */
186
dad2580c
DM
187/* json::string's ctor. */
188
189string::string (const char *utf8)
190{
191 gcc_assert (utf8);
192 m_utf8 = xstrdup (utf8);
193}
194
195/* Implementation of json::value::print for json::string. */
196
4a4412b9
DM
197void
198string::print (pretty_printer *pp) const
199{
200 pp_character (pp, '"');
201 for (const char *ptr = m_utf8; *ptr; ptr++)
202 {
203 char ch = *ptr;
204 switch (ch)
205 {
206 case '"':
207 pp_string (pp, "\\\"");
208 break;
209 case '\\':
210 pp_string (pp, "\\n");
211 break;
212 case '\b':
213 pp_string (pp, "\\b");
214 break;
215 case '\f':
216 pp_string (pp, "\\f");
217 break;
218 case '\n':
219 pp_string (pp, "\\n");
220 break;
221 case '\r':
222 pp_string (pp, "\\r");
223 break;
224 case '\t':
225 pp_string (pp, "\\t");
226 break;
227
228 default:
229 pp_character (pp, ch);
230 }
231 }
232 pp_character (pp, '"');
233}
234
235/* class json::literal, a subclass of json::value. */
236
237/* Implementation of json::value::print for json::literal. */
238
239void
240literal::print (pretty_printer *pp) const
241{
242 switch (m_kind)
243 {
244 case JSON_TRUE:
245 pp_string (pp, "true");
246 break;
247 case JSON_FALSE:
248 pp_string (pp, "false");
249 break;
250 case JSON_NULL:
251 pp_string (pp, "null");
252 break;
253 default:
254 gcc_unreachable ();
255 }
256}
257
258\f
259#if CHECKING_P
260
261namespace selftest {
262
263/* Selftests. */
264
265/* Verify that JV->print () prints EXPECTED_JSON. */
266
267static void
268assert_print_eq (const json::value &jv, const char *expected_json)
269{
270 pretty_printer pp;
271 jv.print (&pp);
272 ASSERT_STREQ (expected_json, pp_formatted_text (&pp));
273}
274
30d3ba51
DM
275/* Verify that object::get works as expected. */
276
277static void
278test_object_get ()
279{
280 object obj;
281 value *val = new json::string ("value");
282 obj.set ("foo", val);
283 ASSERT_EQ (obj.get ("foo"), val);
284 ASSERT_EQ (obj.get ("not-present"), NULL);
285}
286
4a4412b9
DM
287/* Verify that JSON objects are written correctly. We can't test more than
288 one key/value pair, as we don't impose a guaranteed ordering. */
289
290static void
291test_writing_objects ()
292{
293 object obj;
294 obj.set ("foo", new json::string ("bar"));
295 assert_print_eq (obj, "{\"foo\": \"bar\"}");
296}
297
298/* Verify that JSON arrays are written correctly. */
299
300static void
301test_writing_arrays ()
302{
303 array arr;
304 assert_print_eq (arr, "[]");
305
306 arr.append (new json::string ("foo"));
307 assert_print_eq (arr, "[\"foo\"]");
308
309 arr.append (new json::string ("bar"));
310 assert_print_eq (arr, "[\"foo\", \"bar\"]");
311}
312
313/* Verify that JSON numbers are written correctly. */
314
315static void
07622278
ML
316test_writing_float_numbers ()
317{
318 assert_print_eq (float_number (0), "0");
319 assert_print_eq (float_number (42), "42");
320 assert_print_eq (float_number (-100), "-100");
321 assert_print_eq (float_number (123456789), "1.23457e+08");
322}
323
324static void
325test_writing_integer_numbers ()
4a4412b9 326{
07622278
ML
327 assert_print_eq (integer_number (0), "0");
328 assert_print_eq (integer_number (42), "42");
329 assert_print_eq (integer_number (-100), "-100");
330 assert_print_eq (integer_number (123456789), "123456789");
331 assert_print_eq (integer_number (-123456789), "-123456789");
4a4412b9
DM
332}
333
334/* Verify that JSON strings are written correctly. */
335
336static void
337test_writing_strings ()
338{
339 string foo ("foo");
340 assert_print_eq (foo, "\"foo\"");
341
342 string contains_quotes ("before \"quoted\" after");
343 assert_print_eq (contains_quotes, "\"before \\\"quoted\\\" after\"");
344}
345
9ed31860 346/* Verify that JSON literals are written correctly. */
4a4412b9
DM
347
348static void
349test_writing_literals ()
350{
351 assert_print_eq (literal (JSON_TRUE), "true");
352 assert_print_eq (literal (JSON_FALSE), "false");
353 assert_print_eq (literal (JSON_NULL), "null");
c8fda30f
ML
354
355 assert_print_eq (literal (true), "true");
356 assert_print_eq (literal (false), "false");
4a4412b9
DM
357}
358
359/* Run all of the selftests within this file. */
360
361void
362json_cc_tests ()
363{
30d3ba51 364 test_object_get ();
4a4412b9
DM
365 test_writing_objects ();
366 test_writing_arrays ();
07622278
ML
367 test_writing_float_numbers ();
368 test_writing_integer_numbers ();
4a4412b9
DM
369 test_writing_strings ();
370 test_writing_literals ();
371}
372
373} // namespace selftest
374
375#endif /* #if CHECKING_P */