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.
34 No formatting is done. There are no guarantees about the order
35 in which the key/value pairs of json::objects are printed. */
38 value::dump (FILE *outf
) const
41 pp_buffer (&pp
)->stream
= outf
;
46 /* class json::object, a subclass of json::value, representing
47 an unordered collection of key/value pairs. */
49 /* json:object's dtor. */
53 for (map_t::iterator it
= m_map
.begin (); it
!= m_map
.end (); ++it
)
55 free (const_cast <char *>((*it
).first
));
56 delete ((*it
).second
);
60 /* Implementation of json::value::print for json::object. */
63 object::print (pretty_printer
*pp
) const
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
)
69 if (it
!= m_map
.begin ())
71 const char *key
= const_cast <char *>((*it
).first
);
72 value
*value
= (*it
).second
;
74 pp_string (pp
, key
); // FIXME: escaping?
79 pp_character (pp
, '}');
82 /* Set the json::value * for KEY, taking ownership of V
83 (and taking a copy of KEY if necessary). */
86 object::set (const char *key
, value
*v
)
91 value
**ptr
= m_map
.get (key
);
94 /* If the key is already present, delete the existing value
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
);
105 /* Get the json::value * for KEY.
107 The object retains ownership of the value. */
110 object::get (const char *key
) const
114 value
**ptr
= const_cast <map_t
&> (m_map
).get (key
);
121 /* class json::array, a subclass of json::value, representing
122 an ordered collection of values. */
124 /* json::array's dtor. */
130 FOR_EACH_VEC_ELT (m_elements
, i
, v
)
134 /* Implementation of json::value::print for json::array. */
137 array::print (pretty_printer
*pp
) const
139 pp_character (pp
, '[');
142 FOR_EACH_VEC_ELT (m_elements
, i
, v
)
145 pp_string (pp
, ", ");
148 pp_character (pp
, ']');
151 /* Append non-NULL value V to a json::array, taking ownership of V. */
154 array::append (value
*v
)
157 m_elements
.safe_push (v
);
160 /* class json::float_number, a subclass of json::value, wrapping a double. */
162 /* Implementation of json::value::print for json::float_number. */
165 float_number::print (pretty_printer
*pp
) const
168 snprintf (tmp
, sizeof (tmp
), "%g", m_value
);
172 /* class json::integer_number, a subclass of json::value, wrapping a long. */
174 /* Implementation of json::value::print for json::integer_number. */
177 integer_number::print (pretty_printer
*pp
) const
180 snprintf (tmp
, sizeof (tmp
), "%ld", m_value
);
185 /* class json::string, a subclass of json::value. */
187 /* json::string's ctor. */
189 string::string (const char *utf8
)
192 m_utf8
= xstrdup (utf8
);
193 m_len
= strlen (utf8
);
196 string::string (const char *utf8
, size_t len
)
199 m_utf8
= XNEWVEC (char, len
);
201 memcpy (m_utf8
, utf8
, len
);
204 /* Implementation of json::value::print for json::string. */
207 string::print (pretty_printer
*pp
) const
209 pp_character (pp
, '"');
210 for (size_t i
= 0; i
!= m_len
; ++i
)
216 pp_string (pp
, "\\\"");
219 pp_string (pp
, "\\\\");
222 pp_string (pp
, "\\b");
225 pp_string (pp
, "\\f");
228 pp_string (pp
, "\\n");
231 pp_string (pp
, "\\r");
234 pp_string (pp
, "\\t");
237 pp_string (pp
, "\\0");
240 pp_character (pp
, ch
);
243 pp_character (pp
, '"');
246 /* class json::literal, a subclass of json::value. */
248 /* Implementation of json::value::print for json::literal. */
251 literal::print (pretty_printer
*pp
) const
256 pp_string (pp
, "true");
259 pp_string (pp
, "false");
262 pp_string (pp
, "null");
276 /* Verify that JV->print () prints EXPECTED_JSON. */
279 assert_print_eq (const json::value
&jv
, const char *expected_json
)
283 ASSERT_STREQ (expected_json
, pp_formatted_text (&pp
));
286 /* Verify that object::get works as expected. */
292 value
*val
= new json::string ("value");
293 obj
.set ("foo", val
);
294 ASSERT_EQ (obj
.get ("foo"), val
);
295 ASSERT_EQ (obj
.get ("not-present"), NULL
);
298 /* Verify that JSON objects are written correctly. We can't test more than
299 one key/value pair, as we don't impose a guaranteed ordering. */
302 test_writing_objects ()
305 obj
.set ("foo", new json::string ("bar"));
306 assert_print_eq (obj
, "{\"foo\": \"bar\"}");
309 /* Verify that JSON arrays are written correctly. */
312 test_writing_arrays ()
315 assert_print_eq (arr
, "[]");
317 arr
.append (new json::string ("foo"));
318 assert_print_eq (arr
, "[\"foo\"]");
320 arr
.append (new json::string ("bar"));
321 assert_print_eq (arr
, "[\"foo\", \"bar\"]");
324 /* Verify that JSON numbers are written correctly. */
327 test_writing_float_numbers ()
329 assert_print_eq (float_number (0), "0");
330 assert_print_eq (float_number (42), "42");
331 assert_print_eq (float_number (-100), "-100");
332 assert_print_eq (float_number (123456789), "1.23457e+08");
336 test_writing_integer_numbers ()
338 assert_print_eq (integer_number (0), "0");
339 assert_print_eq (integer_number (42), "42");
340 assert_print_eq (integer_number (-100), "-100");
341 assert_print_eq (integer_number (123456789), "123456789");
342 assert_print_eq (integer_number (-123456789), "-123456789");
345 /* Verify that JSON strings are written correctly. */
348 test_writing_strings ()
351 assert_print_eq (foo
, "\"foo\"");
353 string
contains_quotes ("before \"quoted\" after");
354 assert_print_eq (contains_quotes
, "\"before \\\"quoted\\\" after\"");
356 const char data
[] = {'a', 'b', 'c', 'd', '\0', 'e', 'f'};
357 string
not_terminated (data
, 3);
358 assert_print_eq (not_terminated
, "\"abc\"");
359 string
embedded_null (data
, sizeof data
);
360 assert_print_eq (embedded_null
, "\"abcd\\0ef\"");
363 /* Verify that JSON literals are written correctly. */
366 test_writing_literals ()
368 assert_print_eq (literal (JSON_TRUE
), "true");
369 assert_print_eq (literal (JSON_FALSE
), "false");
370 assert_print_eq (literal (JSON_NULL
), "null");
372 assert_print_eq (literal (true), "true");
373 assert_print_eq (literal (false), "false");
376 /* Run all of the selftests within this file. */
382 test_writing_objects ();
383 test_writing_arrays ();
384 test_writing_float_numbers ();
385 test_writing_integer_numbers ();
386 test_writing_strings ();
387 test_writing_literals ();
390 } // namespace selftest
392 #endif /* #if CHECKING_P */