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
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
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/>. */
23 #include "coretypes.h"
25 #include "pretty-print.h"
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. */
41 value::dump (FILE *outf
) const
44 pp_buffer (&pp
)->stream
= outf
;
49 /* class json::object, a subclass of json::value, representing
50 an ordered collection of key/value pairs. */
52 /* json:object's dtor. */
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. */
66 object::print (pretty_printer
*pp
) const
68 pp_character (pp
, '{');
70 /* Iterate in the order that the keys were inserted. */
73 FOR_EACH_VEC_ELT (m_keys
, i
, key
)
77 map_t
&mut_map
= const_cast<map_t
&> (m_map
);
78 value
*value
= *mut_map
.get (key
);
80 pp_string (pp
, key
); // FIXME: escaping?
85 pp_character (pp
, '}');
88 /* Set the json::value * for KEY, taking ownership of V
89 (and taking a copy of KEY if necessary). */
92 object::set (const char *key
, value
*v
)
97 value
**ptr
= m_map
.get (key
);
100 /* If the key is already present, delete the existing value
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. */
120 object::get (const char *key
) const
124 value
**ptr
= const_cast <map_t
&> (m_map
).get (key
);
131 /* class json::array, a subclass of json::value, representing
132 an ordered collection of values. */
134 /* json::array's dtor. */
140 FOR_EACH_VEC_ELT (m_elements
, i
, v
)
144 /* Implementation of json::value::print for json::array. */
147 array::print (pretty_printer
*pp
) const
149 pp_character (pp
, '[');
152 FOR_EACH_VEC_ELT (m_elements
, i
, v
)
155 pp_string (pp
, ", ");
158 pp_character (pp
, ']');
161 /* Append non-NULL value V to a json::array, taking ownership of V. */
164 array::append (value
*v
)
167 m_elements
.safe_push (v
);
170 /* class json::float_number, a subclass of json::value, wrapping a double. */
172 /* Implementation of json::value::print for json::float_number. */
175 float_number::print (pretty_printer
*pp
) const
178 snprintf (tmp
, sizeof (tmp
), "%g", m_value
);
182 /* class json::integer_number, a subclass of json::value, wrapping a long. */
184 /* Implementation of json::value::print for json::integer_number. */
187 integer_number::print (pretty_printer
*pp
) const
190 snprintf (tmp
, sizeof (tmp
), "%ld", m_value
);
195 /* class json::string, a subclass of json::value. */
197 /* json::string's ctor. */
199 string::string (const char *utf8
)
202 m_utf8
= xstrdup (utf8
);
203 m_len
= strlen (utf8
);
206 string::string (const char *utf8
, size_t len
)
209 m_utf8
= XNEWVEC (char, len
);
211 memcpy (m_utf8
, utf8
, len
);
214 /* Implementation of json::value::print for json::string. */
217 string::print (pretty_printer
*pp
) const
219 pp_character (pp
, '"');
220 for (size_t i
= 0; i
!= m_len
; ++i
)
226 pp_string (pp
, "\\\"");
229 pp_string (pp
, "\\\\");
232 pp_string (pp
, "\\b");
235 pp_string (pp
, "\\f");
238 pp_string (pp
, "\\n");
241 pp_string (pp
, "\\r");
244 pp_string (pp
, "\\t");
247 pp_string (pp
, "\\0");
250 pp_character (pp
, ch
);
253 pp_character (pp
, '"');
256 /* class json::literal, a subclass of json::value. */
258 /* Implementation of json::value::print for json::literal. */
261 literal::print (pretty_printer
*pp
) const
266 pp_string (pp
, "true");
269 pp_string (pp
, "false");
272 pp_string (pp
, "null");
286 /* Verify that JV->print () prints EXPECTED_JSON. */
289 assert_print_eq (const json::value
&jv
, const char *expected_json
)
293 ASSERT_STREQ (expected_json
, pp_formatted_text (&pp
));
296 /* Verify that object::get works as expected. */
302 value
*val
= new json::string ("value");
303 obj
.set ("foo", val
);
304 ASSERT_EQ (obj
.get ("foo"), val
);
305 ASSERT_EQ (obj
.get ("not-present"), NULL
);
308 /* Verify that JSON objects are written correctly. */
311 test_writing_objects ()
314 obj
.set ("foo", new json::string ("bar"));
315 obj
.set ("baz", new json::string ("quux"));
316 /* This test relies on json::object writing out key/value pairs
317 in key-insertion order. */
318 assert_print_eq (obj
, "{\"foo\": \"bar\", \"baz\": \"quux\"}");
321 /* Verify that JSON arrays are written correctly. */
324 test_writing_arrays ()
327 assert_print_eq (arr
, "[]");
329 arr
.append (new json::string ("foo"));
330 assert_print_eq (arr
, "[\"foo\"]");
332 arr
.append (new json::string ("bar"));
333 assert_print_eq (arr
, "[\"foo\", \"bar\"]");
336 /* Verify that JSON numbers are written correctly. */
339 test_writing_float_numbers ()
341 assert_print_eq (float_number (0), "0");
342 assert_print_eq (float_number (42), "42");
343 assert_print_eq (float_number (-100), "-100");
344 assert_print_eq (float_number (123456789), "1.23457e+08");
348 test_writing_integer_numbers ()
350 assert_print_eq (integer_number (0), "0");
351 assert_print_eq (integer_number (42), "42");
352 assert_print_eq (integer_number (-100), "-100");
353 assert_print_eq (integer_number (123456789), "123456789");
354 assert_print_eq (integer_number (-123456789), "-123456789");
357 /* Verify that JSON strings are written correctly. */
360 test_writing_strings ()
363 assert_print_eq (foo
, "\"foo\"");
365 string
contains_quotes ("before \"quoted\" after");
366 assert_print_eq (contains_quotes
, "\"before \\\"quoted\\\" after\"");
368 const char data
[] = {'a', 'b', 'c', 'd', '\0', 'e', 'f'};
369 string
not_terminated (data
, 3);
370 assert_print_eq (not_terminated
, "\"abc\"");
371 string
embedded_null (data
, sizeof data
);
372 assert_print_eq (embedded_null
, "\"abcd\\0ef\"");
375 /* Verify that JSON literals are written correctly. */
378 test_writing_literals ()
380 assert_print_eq (literal (JSON_TRUE
), "true");
381 assert_print_eq (literal (JSON_FALSE
), "false");
382 assert_print_eq (literal (JSON_NULL
), "null");
384 assert_print_eq (literal (true), "true");
385 assert_print_eq (literal (false), "false");
388 /* Run all of the selftests within this file. */
394 test_writing_objects ();
395 test_writing_arrays ();
396 test_writing_float_numbers ();
397 test_writing_integer_numbers ();
398 test_writing_strings ();
399 test_writing_literals ();
402 } // namespace selftest
404 #endif /* #if CHECKING_P */