]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/json.cc
libphobos: core.atomic should have fallback when there's no libatomic.
[thirdparty/gcc.git] / gcc / json.cc
CommitLineData
9dcf2a11 1/* JSON trees
fbd26352 2 Copyright (C) 2017-2019 Free Software Foundation, Inc.
9dcf2a11 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
e4aaf333 79/* Set the json::value * for KEY, taking ownership of V
9dcf2a11 80 (and taking a copy of KEY if necessary). */
81
82void
83object::set (const char *key, value *v)
84{
e4aaf333 85 gcc_assert (key);
86 gcc_assert (v);
87
9dcf2a11 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
102/* class json::array, a subclass of json::value, representing
103 an ordered collection of values. */
104
105/* json::array's dtor. */
106
107array::~array ()
108{
109 unsigned i;
110 value *v;
111 FOR_EACH_VEC_ELT (m_elements, i, v)
112 delete v;
113}
114
115/* Implementation of json::value::print for json::array. */
116
117void
118array::print (pretty_printer *pp) const
119{
120 pp_character (pp, '[');
121 unsigned i;
122 value *v;
123 FOR_EACH_VEC_ELT (m_elements, i, v)
124 {
125 if (i)
126 pp_string (pp, ", ");
127 v->print (pp);
128 }
129 pp_character (pp, ']');
130}
131
e4aaf333 132/* Append non-NULL value V to a json::array, taking ownership of V. */
133
134void
135array::append (value *v)
136{
137 gcc_assert (v);
138 m_elements.safe_push (v);
139}
140
9dcf2a11 141/* class json::number, a subclass of json::value, wrapping a double. */
142
143/* Implementation of json::value::print for json::number. */
144
145void
146number::print (pretty_printer *pp) const
147{
148 char tmp[1024];
149 snprintf (tmp, sizeof (tmp), "%g", m_value);
150 pp_string (pp, tmp);
151}
152
153/* class json::string, a subclass of json::value. */
154
e4aaf333 155/* json::string's ctor. */
156
157string::string (const char *utf8)
158{
159 gcc_assert (utf8);
160 m_utf8 = xstrdup (utf8);
161}
162
163/* Implementation of json::value::print for json::string. */
164
9dcf2a11 165void
166string::print (pretty_printer *pp) const
167{
168 pp_character (pp, '"');
169 for (const char *ptr = m_utf8; *ptr; ptr++)
170 {
171 char ch = *ptr;
172 switch (ch)
173 {
174 case '"':
175 pp_string (pp, "\\\"");
176 break;
177 case '\\':
178 pp_string (pp, "\\n");
179 break;
180 case '\b':
181 pp_string (pp, "\\b");
182 break;
183 case '\f':
184 pp_string (pp, "\\f");
185 break;
186 case '\n':
187 pp_string (pp, "\\n");
188 break;
189 case '\r':
190 pp_string (pp, "\\r");
191 break;
192 case '\t':
193 pp_string (pp, "\\t");
194 break;
195
196 default:
197 pp_character (pp, ch);
198 }
199 }
200 pp_character (pp, '"');
201}
202
203/* class json::literal, a subclass of json::value. */
204
205/* Implementation of json::value::print for json::literal. */
206
207void
208literal::print (pretty_printer *pp) const
209{
210 switch (m_kind)
211 {
212 case JSON_TRUE:
213 pp_string (pp, "true");
214 break;
215 case JSON_FALSE:
216 pp_string (pp, "false");
217 break;
218 case JSON_NULL:
219 pp_string (pp, "null");
220 break;
221 default:
222 gcc_unreachable ();
223 }
224}
225
226\f
227#if CHECKING_P
228
229namespace selftest {
230
231/* Selftests. */
232
233/* Verify that JV->print () prints EXPECTED_JSON. */
234
235static void
236assert_print_eq (const json::value &jv, const char *expected_json)
237{
238 pretty_printer pp;
239 jv.print (&pp);
240 ASSERT_STREQ (expected_json, pp_formatted_text (&pp));
241}
242
243/* Verify that JSON objects are written correctly. We can't test more than
244 one key/value pair, as we don't impose a guaranteed ordering. */
245
246static void
247test_writing_objects ()
248{
249 object obj;
250 obj.set ("foo", new json::string ("bar"));
251 assert_print_eq (obj, "{\"foo\": \"bar\"}");
252}
253
254/* Verify that JSON arrays are written correctly. */
255
256static void
257test_writing_arrays ()
258{
259 array arr;
260 assert_print_eq (arr, "[]");
261
262 arr.append (new json::string ("foo"));
263 assert_print_eq (arr, "[\"foo\"]");
264
265 arr.append (new json::string ("bar"));
266 assert_print_eq (arr, "[\"foo\", \"bar\"]");
267}
268
269/* Verify that JSON numbers are written correctly. */
270
271static void
272test_writing_numbers ()
273{
274 assert_print_eq (number (0), "0");
275 assert_print_eq (number (42), "42");
276 assert_print_eq (number (-100), "-100");
277}
278
279/* Verify that JSON strings are written correctly. */
280
281static void
282test_writing_strings ()
283{
284 string foo ("foo");
285 assert_print_eq (foo, "\"foo\"");
286
287 string contains_quotes ("before \"quoted\" after");
288 assert_print_eq (contains_quotes, "\"before \\\"quoted\\\" after\"");
289}
290
4cd96a00 291/* Verify that JSON literals are written correctly. */
9dcf2a11 292
293static void
294test_writing_literals ()
295{
296 assert_print_eq (literal (JSON_TRUE), "true");
297 assert_print_eq (literal (JSON_FALSE), "false");
298 assert_print_eq (literal (JSON_NULL), "null");
8d11df62 299
300 assert_print_eq (literal (true), "true");
301 assert_print_eq (literal (false), "false");
9dcf2a11 302}
303
304/* Run all of the selftests within this file. */
305
306void
307json_cc_tests ()
308{
309 test_writing_objects ();
310 test_writing_arrays ();
311 test_writing_numbers ();
312 test_writing_strings ();
313 test_writing_literals ();
314}
315
316} // namespace selftest
317
318#endif /* #if CHECKING_P */