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