hppa: Revise REG+D address support to allow long displacements before reload
[official-gcc.git] / gcc / json.cc
blobd0f157f0dfe741ed98475d9314b31201ec0b5126
1 /* JSON trees
2 Copyright (C) 2017-2023 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
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.
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.
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/>. */
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"
29 using namespace json;
31 /* class json::value. */
33 /* Dump this json::value tree to OUTF.
35 No formatting is done.
37 The key/value pairs of json::objects are printed in the order
38 in which the keys were originally inserted. */
40 void
41 value::dump (FILE *outf) const
43 pretty_printer pp;
44 pp_buffer (&pp)->stream = outf;
45 print (&pp);
46 pp_flush (&pp);
49 /* class json::object, a subclass of json::value, representing
50 an ordered collection of key/value pairs. */
52 /* json:object's dtor. */
54 object::~object ()
56 for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it)
58 free (const_cast <char *>((*it).first));
59 delete ((*it).second);
63 /* Implementation of json::value::print for json::object. */
65 void
66 object::print (pretty_printer *pp) const
68 pp_character (pp, '{');
70 /* Iterate in the order that the keys were inserted. */
71 unsigned i;
72 const char *key;
73 FOR_EACH_VEC_ELT (m_keys, i, key)
75 if (i > 0)
76 pp_string (pp, ", ");
77 map_t &mut_map = const_cast<map_t &> (m_map);
78 value *value = *mut_map.get (key);
79 pp_doublequote (pp);
80 pp_string (pp, key); // FIXME: escaping?
81 pp_doublequote (pp);
82 pp_string (pp, ": ");
83 value->print (pp);
85 pp_character (pp, '}');
88 /* Set the json::value * for KEY, taking ownership of V
89 (and taking a copy of KEY if necessary). */
91 void
92 object::set (const char *key, value *v)
94 gcc_assert (key);
95 gcc_assert (v);
97 value **ptr = m_map.get (key);
98 if (ptr)
100 /* If the key is already present, delete the existing value
101 and overwrite it. */
102 delete *ptr;
103 *ptr = v;
105 else
107 /* If the key wasn't already present, take a copy of the key,
108 and store the value. */
109 char *owned_key = xstrdup (key);
110 m_map.put (owned_key, v);
111 m_keys.safe_push (owned_key);
115 /* Get the json::value * for KEY.
117 The object retains ownership of the value. */
119 value *
120 object::get (const char *key) const
122 gcc_assert (key);
124 value **ptr = const_cast <map_t &> (m_map).get (key);
125 if (ptr)
126 return *ptr;
127 else
128 return NULL;
131 /* Set value of KEY within this object to a JSON
132 string value based on UTF8_VALUE. */
134 void
135 object::set_string (const char *key, const char *utf8_value)
137 set (key, new json::string (utf8_value));
140 /* Set value of KEY within this object to a JSON
141 integer value based on V. */
143 void
144 object::set_integer (const char *key, long v)
146 set (key, new json::integer_number (v));
149 /* Set value of KEY within this object to a JSON
150 floating point value based on V. */
152 void
153 object::set_float (const char *key, double v)
155 set (key, new json::float_number (v));
158 /* Set value of KEY within this object to the JSON
159 literal true or false, based on V. */
161 void
162 object::set_bool (const char *key, bool v)
164 set (key, new json::literal (v));
167 /* class json::array, a subclass of json::value, representing
168 an ordered collection of values. */
170 /* json::array's dtor. */
172 array::~array ()
174 unsigned i;
175 value *v;
176 FOR_EACH_VEC_ELT (m_elements, i, v)
177 delete v;
180 /* Implementation of json::value::print for json::array. */
182 void
183 array::print (pretty_printer *pp) const
185 pp_character (pp, '[');
186 unsigned i;
187 value *v;
188 FOR_EACH_VEC_ELT (m_elements, i, v)
190 if (i)
191 pp_string (pp, ", ");
192 v->print (pp);
194 pp_character (pp, ']');
197 /* Append non-NULL value V to a json::array, taking ownership of V. */
199 void
200 array::append (value *v)
202 gcc_assert (v);
203 m_elements.safe_push (v);
206 /* class json::float_number, a subclass of json::value, wrapping a double. */
208 /* Implementation of json::value::print for json::float_number. */
210 void
211 float_number::print (pretty_printer *pp) const
213 char tmp[1024];
214 snprintf (tmp, sizeof (tmp), "%g", m_value);
215 pp_string (pp, tmp);
218 /* class json::integer_number, a subclass of json::value, wrapping a long. */
220 /* Implementation of json::value::print for json::integer_number. */
222 void
223 integer_number::print (pretty_printer *pp) const
225 char tmp[1024];
226 snprintf (tmp, sizeof (tmp), "%ld", m_value);
227 pp_string (pp, tmp);
231 /* class json::string, a subclass of json::value. */
233 /* json::string's ctor. */
235 string::string (const char *utf8)
237 gcc_assert (utf8);
238 m_utf8 = xstrdup (utf8);
239 m_len = strlen (utf8);
242 string::string (const char *utf8, size_t len)
244 gcc_assert (utf8);
245 m_utf8 = XNEWVEC (char, len);
246 m_len = len;
247 memcpy (m_utf8, utf8, len);
250 /* Implementation of json::value::print for json::string. */
252 void
253 string::print (pretty_printer *pp) const
255 pp_character (pp, '"');
256 for (size_t i = 0; i != m_len; ++i)
258 char ch = m_utf8[i];
259 switch (ch)
261 case '"':
262 pp_string (pp, "\\\"");
263 break;
264 case '\\':
265 pp_string (pp, "\\\\");
266 break;
267 case '\b':
268 pp_string (pp, "\\b");
269 break;
270 case '\f':
271 pp_string (pp, "\\f");
272 break;
273 case '\n':
274 pp_string (pp, "\\n");
275 break;
276 case '\r':
277 pp_string (pp, "\\r");
278 break;
279 case '\t':
280 pp_string (pp, "\\t");
281 break;
282 case '\0':
283 pp_string (pp, "\\0");
284 break;
285 default:
286 pp_character (pp, ch);
289 pp_character (pp, '"');
292 /* class json::literal, a subclass of json::value. */
294 /* Implementation of json::value::print for json::literal. */
296 void
297 literal::print (pretty_printer *pp) const
299 switch (m_kind)
301 case JSON_TRUE:
302 pp_string (pp, "true");
303 break;
304 case JSON_FALSE:
305 pp_string (pp, "false");
306 break;
307 case JSON_NULL:
308 pp_string (pp, "null");
309 break;
310 default:
311 gcc_unreachable ();
316 #if CHECKING_P
318 namespace selftest {
320 /* Selftests. */
322 /* Verify that JV->print () prints EXPECTED_JSON. */
324 static void
325 assert_print_eq (const location &loc, const json::value &jv, const char *expected_json)
327 pretty_printer pp;
328 jv.print (&pp);
329 ASSERT_STREQ_AT (loc, expected_json, pp_formatted_text (&pp));
332 #define ASSERT_PRINT_EQ(JV, EXPECTED_JSON) \
333 assert_print_eq (SELFTEST_LOCATION, JV, EXPECTED_JSON)
335 /* Verify that object::get works as expected. */
337 static void
338 test_object_get ()
340 object obj;
341 value *val = new json::string ("value");
342 obj.set ("foo", val);
343 ASSERT_EQ (obj.get ("foo"), val);
344 ASSERT_EQ (obj.get ("not-present"), NULL);
347 /* Verify that JSON objects are written correctly. */
349 static void
350 test_writing_objects ()
352 object obj;
353 obj.set_string ("foo", "bar");
354 obj.set_string ("baz", "quux");
355 /* This test relies on json::object writing out key/value pairs
356 in key-insertion order. */
357 ASSERT_PRINT_EQ (obj, "{\"foo\": \"bar\", \"baz\": \"quux\"}");
360 /* Verify that JSON arrays are written correctly. */
362 static void
363 test_writing_arrays ()
365 array arr;
366 ASSERT_PRINT_EQ (arr, "[]");
368 arr.append (new json::string ("foo"));
369 ASSERT_PRINT_EQ (arr, "[\"foo\"]");
371 arr.append (new json::string ("bar"));
372 ASSERT_PRINT_EQ (arr, "[\"foo\", \"bar\"]");
375 /* Verify that JSON numbers are written correctly. */
377 static void
378 test_writing_float_numbers ()
380 ASSERT_PRINT_EQ (float_number (0), "0");
381 ASSERT_PRINT_EQ (float_number (42), "42");
382 ASSERT_PRINT_EQ (float_number (-100), "-100");
383 ASSERT_PRINT_EQ (float_number (123456789), "1.23457e+08");
386 static void
387 test_writing_integer_numbers ()
389 ASSERT_PRINT_EQ (integer_number (0), "0");
390 ASSERT_PRINT_EQ (integer_number (42), "42");
391 ASSERT_PRINT_EQ (integer_number (-100), "-100");
392 ASSERT_PRINT_EQ (integer_number (123456789), "123456789");
393 ASSERT_PRINT_EQ (integer_number (-123456789), "-123456789");
396 /* Verify that JSON strings are written correctly. */
398 static void
399 test_writing_strings ()
401 string foo ("foo");
402 ASSERT_PRINT_EQ (foo, "\"foo\"");
404 string contains_quotes ("before \"quoted\" after");
405 ASSERT_PRINT_EQ (contains_quotes, "\"before \\\"quoted\\\" after\"");
407 const char data[] = {'a', 'b', 'c', 'd', '\0', 'e', 'f'};
408 string not_terminated (data, 3);
409 ASSERT_PRINT_EQ (not_terminated, "\"abc\"");
410 string embedded_null (data, sizeof data);
411 ASSERT_PRINT_EQ (embedded_null, "\"abcd\\0ef\"");
414 /* Verify that JSON literals are written correctly. */
416 static void
417 test_writing_literals ()
419 ASSERT_PRINT_EQ (literal (JSON_TRUE), "true");
420 ASSERT_PRINT_EQ (literal (JSON_FALSE), "false");
421 ASSERT_PRINT_EQ (literal (JSON_NULL), "null");
423 ASSERT_PRINT_EQ (literal (true), "true");
424 ASSERT_PRINT_EQ (literal (false), "false");
427 /* Run all of the selftests within this file. */
429 void
430 json_cc_tests ()
432 test_object_get ();
433 test_writing_objects ();
434 test_writing_arrays ();
435 test_writing_float_numbers ();
436 test_writing_integer_numbers ();
437 test_writing_strings ();
438 test_writing_literals ();
441 } // namespace selftest
443 #endif /* #if CHECKING_P */