LCOV - code coverage report
Current view: top level - gcc - json.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.1 % 512 482
Test Date: 2025-10-18 14:39:06 Functions: 89.5 % 57 51
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* JSON trees
       2                 :             :    Copyright (C) 2017-2025 Free Software Foundation, Inc.
       3                 :             :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       4                 :             : 
       5                 :             : This file is part of GCC.
       6                 :             : 
       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.
      11                 :             : 
      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.
      16                 :             : 
      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/>.  */
      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                 :             : 
      29                 :             : using namespace json;
      30                 :             : 
      31                 :             : /* Print a JSON string to PP, escaping '"', control characters,
      32                 :             :    and embedded null bytes.
      33                 :             :    The string is required to be UTF-8 encoded.  */
      34                 :             : 
      35                 :             : static void
      36                 :     1290235 : print_escaped_json_string (pretty_printer *pp,
      37                 :             :                            const char *utf8_str,
      38                 :             :                            size_t len)
      39                 :             : {
      40                 :     1290235 :   pp_character (pp, '"');
      41                 :    17443146 :   for (size_t i = 0; i != len; ++i)
      42                 :             :     {
      43                 :    16152911 :       char ch = utf8_str[i];
      44                 :    16152911 :       switch (ch)
      45                 :             :         {
      46                 :        2656 :         case '"':
      47                 :        2656 :           pp_string (pp, "\\\"");
      48                 :        2656 :           break;
      49                 :        1483 :         case '\\':
      50                 :        1483 :           pp_string (pp, "\\\\");
      51                 :        1483 :           break;
      52                 :           8 :         case '\b':
      53                 :           8 :           pp_string (pp, "\\b");
      54                 :           8 :           break;
      55                 :           8 :         case '\f':
      56                 :           8 :           pp_string (pp, "\\f");
      57                 :           8 :           break;
      58                 :       51368 :         case '\n':
      59                 :       51368 :           pp_string (pp, "\\n");
      60                 :       51368 :           break;
      61                 :           8 :         case '\r':
      62                 :           8 :           pp_string (pp, "\\r");
      63                 :           8 :           break;
      64                 :        3848 :         case '\t':
      65                 :        3848 :           pp_string (pp, "\\t");
      66                 :        3848 :           break;
      67                 :           4 :         case '\0':
      68                 :           4 :           pp_string (pp, "\\0");
      69                 :           4 :           break;
      70                 :    16093528 :         default:
      71                 :    16093528 :           pp_character (pp, ch);
      72                 :             :         }
      73                 :             :     }
      74                 :     1290235 :   pp_character (pp, '"');
      75                 :     1290235 : }
      76                 :             : 
      77                 :             : /* class pointer::token.  */
      78                 :             : 
      79                 :     4120432 : pointer::token::token ()
      80                 :             : {
      81                 :     4120432 :   m_parent = nullptr;
      82                 :     4120432 :   m_data.u_member = nullptr;
      83                 :     4120432 :   m_kind = kind::root_value;
      84                 :     4120432 : }
      85                 :             : 
      86                 :     3319268 : pointer::token::token (json::object &parent, const char *member)
      87                 :             : {
      88                 :     3319268 :   m_parent = &parent;
      89                 :     3319268 :   m_data.u_member = xstrdup (member); // ideally we'd share
      90                 :     3319268 :   m_kind = kind::object_member;
      91                 :     3319268 : }
      92                 :             : 
      93                 :      796593 : pointer::token::token (json::array &parent, size_t index)
      94                 :             : {
      95                 :      796593 :   m_parent = &parent;
      96                 :      796593 :   m_data.u_index = index;
      97                 :      796593 :   m_kind = kind::array_index;
      98                 :      796593 : }
      99                 :             : 
     100                 :     8234941 : pointer::token::~token ()
     101                 :             : {
     102                 :     8234941 :   if (m_kind == kind::object_member)
     103                 :             :     {
     104                 :     3318134 :       gcc_assert (m_data.u_member);
     105                 :     3318134 :       free (m_data.u_member);
     106                 :             :     }
     107                 :     8234941 : }
     108                 :             : 
     109                 :             : pointer::token &
     110                 :     4115861 : pointer::token::operator= (pointer::token &&other)
     111                 :             : {
     112                 :     4115861 :   m_parent = other.m_parent;
     113                 :     4115861 :   m_data = other.m_data;
     114                 :     4115861 :   m_kind = other.m_kind;
     115                 :             : 
     116                 :     4115861 :   other.m_parent = nullptr;
     117                 :     4115861 :   other.m_data.u_member = nullptr;
     118                 :     4115861 :   other.m_kind = kind::root_value;
     119                 :             : 
     120                 :     4115861 :   return *this;
     121                 :             : }
     122                 :             : 
     123                 :             : /* class json::value.  */
     124                 :             : 
     125                 :             : /* Dump this json::value tree to OUTF.
     126                 :             : 
     127                 :             :    The key/value pairs of json::objects are printed in the order
     128                 :             :    in which the keys were originally inserted.  */
     129                 :             : 
     130                 :             : void
     131                 :         102 : value::dump (FILE *outf, bool formatted) const
     132                 :             : {
     133                 :         102 :   pretty_printer pp;
     134                 :         102 :   pp_buffer (&pp)->m_stream = outf;
     135                 :         102 :   print (&pp, formatted);
     136                 :         102 :   pp_flush (&pp);
     137                 :         102 : }
     138                 :             : 
     139                 :             : /* A convenience function for debugging.
     140                 :             :    Dump to stderr with formatting, and a trailing newline. */
     141                 :             : 
     142                 :             : void
     143                 :           0 : value::dump () const
     144                 :             : {
     145                 :           0 :   dump (stderr, true);
     146                 :           0 :   fprintf (stderr, "\n");
     147                 :           0 : }
     148                 :             : 
     149                 :             : /* A deterministic total ordering for comparing json values, so that we
     150                 :             :    can e.g. put them in std::map.
     151                 :             : 
     152                 :             :    This is intended to follow the condition for equality described in
     153                 :             :    the JSON Schema standard (§4.3, “Instance equality”), as referenced
     154                 :             :    by SARIF v2.1.0 (§3.7.3 "Array properties with unique values"), but has
     155                 :             :    the following limitations:
     156                 :             :    - numbers are supposed to be checked for "the same mathematical value",
     157                 :             :    but in this implementation int vs float numbers won't compare as equal,
     158                 :             :    and float number comparison is bitwise
     159                 :             :    - strings are supposed to be "the same codepoint-for-codepoint", but
     160                 :             :    this implementation doesn't take into account canonicalization issues.  */
     161                 :             : 
     162                 :             : int
     163                 :       15472 : value::compare (const value &val_a, const value &val_b)
     164                 :             : {
     165                 :       15472 :   enum kind kind_a = val_a.get_kind ();
     166                 :       15472 :   enum kind kind_b = val_b.get_kind ();
     167                 :       15472 :   if (kind_a != kind_b)
     168                 :          32 :     return (int)kind_a - (int)kind_b;
     169                 :             : 
     170                 :       15440 :   switch (kind_a)
     171                 :             :     {
     172                 :           0 :     default:
     173                 :           0 :       gcc_unreachable ();
     174                 :             : 
     175                 :        5045 :     case JSON_OBJECT:
     176                 :        5045 :       {
     177                 :        5045 :         const object &obj_a = (const object &)val_a;
     178                 :        5045 :         const object &obj_b = (const object &)val_b;
     179                 :        5045 :         return object::compare (obj_a, obj_b);
     180                 :             :       }
     181                 :          56 :       break;
     182                 :             : 
     183                 :          56 :     case JSON_ARRAY:
     184                 :          56 :       {
     185                 :          56 :         const array &arr_a = (const array &)val_a;
     186                 :          56 :         const array &arr_b = (const array &)val_b;
     187                 :         128 :         if (int cmp_size = (int)arr_a.size () - (int)arr_b.size ())
     188                 :             :           return cmp_size;
     189                 :          64 :         for (size_t idx = 0; idx < arr_a.size (); ++idx)
     190                 :          24 :           if (int cmp_element = compare (*arr_a[idx], *arr_b[idx]))
     191                 :             :             return cmp_element;
     192                 :             :         return 0;
     193                 :             :       }
     194                 :          69 :       break;
     195                 :             : 
     196                 :          69 :     case JSON_INTEGER:
     197                 :          69 :       {
     198                 :          69 :         const integer_number &int_a = (const integer_number &)val_a;
     199                 :          69 :         const integer_number &int_b = (const integer_number &)val_b;
     200                 :          69 :         return int_a.get () - int_b.get ();
     201                 :             :       }
     202                 :          32 :       break;
     203                 :             : 
     204                 :          32 :     case JSON_FLOAT:
     205                 :          32 :       {
     206                 :          32 :         const float_number &float_a = (const float_number &)val_a;
     207                 :          32 :         const float_number &float_b = (const float_number &)val_b;
     208                 :          32 :         union u
     209                 :             :         {
     210                 :             :           double u_double;
     211                 :             :           char u_buf[sizeof(double)];
     212                 :             :         };
     213                 :          32 :         union u u_a, u_b;
     214                 :          32 :         u_a.u_double = float_a.get ();
     215                 :          32 :         u_b.u_double = float_b.get ();
     216                 :          32 :         return memcmp (&u_a, &u_b, sizeof(double));
     217                 :             :       }
     218                 :       10198 :       break;
     219                 :             : 
     220                 :       10198 :     case JSON_STRING:
     221                 :       10198 :       {
     222                 :       10198 :         const string &str_a = (const string &)val_a;
     223                 :       10198 :         const string &str_b = (const string &)val_b;
     224                 :       10198 :         return strcmp (str_a.get_string (), str_b.get_string ());
     225                 :             :       }
     226                 :             :       break;
     227                 :             : 
     228                 :             :     case JSON_TRUE:
     229                 :             :     case JSON_FALSE:
     230                 :             :     case JSON_NULL:
     231                 :             :       /* All instances of literals compare equal to instances
     232                 :             :          of the same literal.  */
     233                 :             :       return 0;
     234                 :             :     }
     235                 :             : }
     236                 :             : 
     237                 :             : /* class json::object, a subclass of json::value, representing
     238                 :             :    an ordered collection of key/value pairs.  */
     239                 :             : 
     240                 :             : /* json:object's dtor.  */
     241                 :             : 
     242                 :     1487439 : object::~object ()
     243                 :             : {
     244                 :     7386818 :   for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it)
     245                 :             :     {
     246                 :     3318043 :       free (const_cast <char *>((*it).first));
     247                 :     3318043 :       delete ((*it).second);
     248                 :             :     }
     249                 :     1487439 : }
     250                 :             : 
     251                 :             : /* Implementation of json::value::print for json::object.  */
     252                 :             : 
     253                 :             : void
     254                 :      242825 : object::print (pretty_printer *pp, bool formatted) const
     255                 :             : {
     256                 :      242825 :   pp_character (pp, '{');
     257                 :      242825 :   if (formatted)
     258                 :        7641 :     pp_indentation (pp) += 1;
     259                 :             : 
     260                 :             :   /* Iterate in the order that the keys were inserted.  */
     261                 :             :   unsigned i;
     262                 :             :   const char *key;
     263                 :     1033275 :   FOR_EACH_VEC_ELT (m_keys, i, key)
     264                 :             :     {
     265                 :      790450 :       if (i > 0)
     266                 :             :         {
     267                 :      547633 :           pp_string (pp, ",");
     268                 :      547633 :           if (formatted)
     269                 :             :             {
     270                 :       10671 :               pp_newline (pp);
     271                 :       10671 :               pp_indent (pp);
     272                 :             :             }
     273                 :             :           else
     274                 :      536962 :             pp_space (pp);
     275                 :             :         }
     276                 :      790450 :       map_t &mut_map = const_cast<map_t &> (m_map);
     277                 :      790450 :       value *value = *mut_map.get (key);
     278                 :      790450 :       print_escaped_json_string (pp, key, strlen (key));
     279                 :      790450 :       pp_string (pp, ": ");
     280                 :      790450 :       const int indent = strlen (key) + 4;
     281                 :      790450 :       if (formatted)
     282                 :       18304 :         pp_indentation (pp) += indent;
     283                 :      790450 :       value->print (pp, formatted);
     284                 :      790450 :       if (formatted)
     285                 :       18304 :         pp_indentation (pp) -= indent;
     286                 :             :     }
     287                 :      242825 :   if (formatted)
     288                 :        7641 :     pp_indentation (pp) -= 1;
     289                 :      242825 :   pp_character (pp, '}');
     290                 :      242825 : }
     291                 :             : 
     292                 :             : std::unique_ptr<value>
     293                 :           4 : object::clone () const
     294                 :             : {
     295                 :           4 :   return clone_as_object ();
     296                 :             : }
     297                 :             : 
     298                 :             : std::unique_ptr<object>
     299                 :           4 : object::clone_as_object () const
     300                 :             : {
     301                 :           4 :   auto result = std::make_unique<object> ();
     302                 :             : 
     303                 :             :   /* Iterate in the order that the keys were inserted.  */
     304                 :           4 :   unsigned i;
     305                 :           4 :   const char *key;
     306                 :           8 :   FOR_EACH_VEC_ELT (m_keys, i, key)
     307                 :             :     {
     308                 :           4 :       map_t &mut_map = const_cast<map_t &> (m_map);
     309                 :           4 :       value *value = *mut_map.get (key);
     310                 :           4 :       result->set (key, value->clone ());
     311                 :             :     }
     312                 :             : 
     313                 :           4 :   return result;
     314                 :             : }
     315                 :             : 
     316                 :             : /* Set the json::value * for KEY, taking ownership of V
     317                 :             :    (and taking a copy of KEY if necessary).  */
     318                 :             : 
     319                 :             : void
     320                 :     3319268 : object::set (const char *key, value *v)
     321                 :             : {
     322                 :     3319268 :   gcc_assert (key);
     323                 :     3319268 :   gcc_assert (v);
     324                 :             : 
     325                 :     3319268 :   value **ptr = m_map.get (key);
     326                 :     3319268 :   if (ptr)
     327                 :             :     {
     328                 :             :       /* If the key is already present, delete the existing value
     329                 :             :          and overwrite it.  */
     330                 :          91 :       delete *ptr;
     331                 :          91 :       *ptr = v;
     332                 :             :     }
     333                 :             :   else
     334                 :             :     {
     335                 :             :       /* If the key wasn't already present, take a copy of the key,
     336                 :             :          and store the value.  */
     337                 :     3319177 :       char *owned_key = xstrdup (key);
     338                 :     3319177 :       m_map.put (owned_key, v);
     339                 :     3319177 :       m_keys.safe_push (owned_key);
     340                 :             :     }
     341                 :             : 
     342                 :     3319268 :   v->m_pointer_token = pointer::token (*this, key);
     343                 :     3319268 : }
     344                 :             : 
     345                 :             : /* Get the json::value * for KEY.
     346                 :             : 
     347                 :             :    The object retains ownership of the value.  */
     348                 :             : 
     349                 :             : value *
     350                 :       18999 : object::get (const char *key) const
     351                 :             : {
     352                 :       18999 :   gcc_assert (key);
     353                 :             : 
     354                 :       18999 :   value **ptr = const_cast <map_t &> (m_map).get (key);
     355                 :       18999 :   if (ptr)
     356                 :       17985 :     return *ptr;
     357                 :             :   else
     358                 :             :     return NULL;
     359                 :             : }
     360                 :             : 
     361                 :             : /* Set value of KEY within this object to a JSON
     362                 :             :    string value based on UTF8_VALUE.  */
     363                 :             : 
     364                 :             : void
     365                 :     1350239 : object::set_string (const char *key, const char *utf8_value)
     366                 :             : {
     367                 :     1350239 :   set (key, new json::string (utf8_value));
     368                 :     1350239 : }
     369                 :             : 
     370                 :             : /* Set value of KEY within this object to a JSON
     371                 :             :    integer value based on V.  */
     372                 :             : 
     373                 :             : void
     374                 :      667595 : object::set_integer (const char *key, long v)
     375                 :             : {
     376                 :      667595 :   set (key, new json::integer_number (v));
     377                 :      667595 : }
     378                 :             : 
     379                 :             : /* Set value of KEY within this object to a JSON
     380                 :             :    floating point value based on V.  */
     381                 :             : 
     382                 :             : void
     383                 :          16 : object::set_float (const char *key, double v)
     384                 :             : {
     385                 :          16 :   set (key, new json::float_number (v));
     386                 :          16 : }
     387                 :             : 
     388                 :             : /* Set value of KEY within this object to the JSON
     389                 :             :    literal true or false, based on V.  */
     390                 :             : 
     391                 :             : void
     392                 :         477 : object::set_bool (const char *key, bool v)
     393                 :             : {
     394                 :         954 :   set (key, new json::literal (v));
     395                 :         477 : }
     396                 :             : 
     397                 :             : void
     398                 :           0 : object::set_string (const string_property &property, const char *utf8_value)
     399                 :             : {
     400                 :           0 :   set_string (property.m_key.get (), utf8_value);
     401                 :           0 : }
     402                 :             : 
     403                 :             : void
     404                 :           0 : object::set_integer (const integer_property &property, long value)
     405                 :             : {
     406                 :           0 :   set_integer (property.m_key.get (), value);
     407                 :           0 : }
     408                 :             : 
     409                 :             : void
     410                 :           0 : object::set_bool (const bool_property &property, bool value)
     411                 :             : {
     412                 :           0 :   set_bool (property.m_key.get (), value);
     413                 :           0 : }
     414                 :             : 
     415                 :             : void
     416                 :           0 : object::set_array_of_string (const array_of_string_property &property,
     417                 :             :                              std::unique_ptr<json::array> value)
     418                 :             : {
     419                 :           0 :   set<array> (property.m_key.get (), std::move (value));
     420                 :           0 : }
     421                 :             : 
     422                 :             : /* Subroutine of json::compare for comparing a pairs of objects.  */
     423                 :             : 
     424                 :             : int
     425                 :        5045 : object::compare (const json::object &obj_a, const json::object &obj_b)
     426                 :             : {
     427                 :       15059 :   if (int cmp_size = (int)obj_a.m_keys.length () - (int)obj_b.m_keys.length ())
     428                 :             :     return cmp_size;
     429                 :             : 
     430                 :       16074 :   for (auto iter_a : obj_a.m_map)
     431                 :             :     {
     432                 :       10139 :       const char *key = iter_a.first;
     433                 :       10139 :       const value *value_a = iter_a.second;
     434                 :       10139 :       gcc_assert (value_a);
     435                 :             : 
     436                 :       10139 :       const value *value_b = obj_b.get (key);
     437                 :       10139 :       if (!value_b)
     438                 :             :         /* Key is in OBJ_A but not in OBJ_B.  */
     439                 :        4554 :         return 1;
     440                 :             :       /* If key is OBJ_B but not in OBJ_A, then the
     441                 :             :          count of keys will have been different, or
     442                 :             :          OBJ_A would have had a key not in OBJ_B.  */
     443                 :       10139 :       if (int cmp_value = value::compare (*value_a, *value_b))
     444                 :             :         /* Values for key are non-equal.  */
     445                 :             :         return cmp_value;
     446                 :             :     }
     447                 :             : 
     448                 :             :   /* Objects are equal.  */
     449                 :         350 :   return 0;
     450                 :             : }
     451                 :             : 
     452                 :             : /* class json::array, a subclass of json::value, representing
     453                 :             :    an ordered collection of values.  */
     454                 :             : 
     455                 :             : /* json::array's dtor.  */
     456                 :             : 
     457                 :     1234045 : array::~array ()
     458                 :             : {
     459                 :      617455 :   unsigned i;
     460                 :      617455 :   value *v;
     461                 :     1413969 :   FOR_EACH_VEC_ELT (m_elements, i, v)
     462                 :      796514 :     delete v;
     463                 :     1234045 : }
     464                 :             : 
     465                 :             : /* Implementation of json::value::print for json::array.  */
     466                 :             : 
     467                 :             : void
     468                 :       90232 : array::print (pretty_printer *pp, bool formatted) const
     469                 :             : {
     470                 :       90232 :   pp_character (pp, '[');
     471                 :       90232 :   if (formatted)
     472                 :        1907 :     pp_indentation (pp) += 1;
     473                 :             :   unsigned i;
     474                 :             :   value *v;
     475                 :      298803 :   FOR_EACH_VEC_ELT (m_elements, i, v)
     476                 :             :     {
     477                 :      208571 :       if (i)
     478                 :             :         {
     479                 :      132960 :           pp_string (pp, ",");
     480                 :      132960 :           if (formatted)
     481                 :             :             {
     482                 :        4947 :               pp_newline (pp);
     483                 :        4947 :               pp_indent (pp);
     484                 :             :             }
     485                 :             :           else
     486                 :      128013 :             pp_space (pp);
     487                 :             :         }
     488                 :      208571 :       v->print (pp, formatted);
     489                 :             :     }
     490                 :       90232 :   if (formatted)
     491                 :        1907 :     pp_indentation (pp) -= 1;
     492                 :       90232 :   pp_character (pp, ']');
     493                 :       90232 : }
     494                 :             : 
     495                 :             : std::unique_ptr<value>
     496                 :           4 : array::clone () const
     497                 :             : {
     498                 :           4 :   auto result = std::make_unique<array> ();
     499                 :           4 :   unsigned i;
     500                 :           4 :   value *v;
     501                 :          12 :   FOR_EACH_VEC_ELT (m_elements, i, v)
     502                 :           4 :     result->append (v->clone ());
     503                 :           4 :   return result;
     504                 :           4 : }
     505                 :             : 
     506                 :             : /* Append non-NULL value V to a json::array, taking ownership of V.  */
     507                 :             : 
     508                 :             : void
     509                 :      796593 : array::append (value *v)
     510                 :             : {
     511                 :      796593 :   gcc_assert (v);
     512                 :     1400651 :   v->m_pointer_token = pointer::token (*this, m_elements.length ());
     513                 :      796593 :   m_elements.safe_push (v);
     514                 :      796593 : }
     515                 :             : 
     516                 :             : void
     517                 :      180222 : array::append_string (const char *utf8_value)
     518                 :             : {
     519                 :      180222 :   gcc_assert (utf8_value);
     520                 :      180222 :   append (new json::string (utf8_value));
     521                 :      180222 : }
     522                 :             : 
     523                 :             : /* class json::float_number, a subclass of json::value, wrapping a double.  */
     524                 :             : 
     525                 :             : /* Implementation of json::value::print for json::float_number.  */
     526                 :             : 
     527                 :             : void
     528                 :          32 : float_number::print (pretty_printer *pp,
     529                 :             :                      bool formatted ATTRIBUTE_UNUSED) const
     530                 :             : {
     531                 :          32 :   char tmp[1024];
     532                 :          32 :   snprintf (tmp, sizeof (tmp), "%g", m_value);
     533                 :          32 :   pp_string (pp, tmp);
     534                 :          32 : }
     535                 :             : 
     536                 :             : std::unique_ptr<value>
     537                 :           4 : float_number::clone () const
     538                 :             : {
     539                 :           4 :   return std::make_unique<float_number> (m_value);
     540                 :             : }
     541                 :             : 
     542                 :             : /* class json::integer_number, a subclass of json::value, wrapping a long.  */
     543                 :             : 
     544                 :             : /* Implementation of json::value::print for json::integer_number.  */
     545                 :             : 
     546                 :             : void
     547                 :      166251 : integer_number::print (pretty_printer *pp,
     548                 :             :                        bool formatted ATTRIBUTE_UNUSED) const
     549                 :             : {
     550                 :      166251 :   char tmp[1024];
     551                 :      166251 :   snprintf (tmp, sizeof (tmp), "%ld", m_value);
     552                 :      166251 :   pp_string (pp, tmp);
     553                 :      166251 : }
     554                 :             : 
     555                 :             : std::unique_ptr<value>
     556                 :           4 : integer_number::clone () const
     557                 :             : {
     558                 :           4 :   return std::make_unique<integer_number> (m_value);
     559                 :             : }
     560                 :             : 
     561                 :             : /* class json::string, a subclass of json::value.  */
     562                 :             : 
     563                 :             : /* json::string's ctor.  */
     564                 :             : 
     565                 :     2081317 : string::string (const char *utf8)
     566                 :             : {
     567                 :     2081317 :   gcc_assert (utf8);
     568                 :     2081317 :   m_utf8 = xstrdup (utf8);
     569                 :     2081317 :   m_len = strlen (utf8);
     570                 :     2081317 : }
     571                 :             : 
     572                 :        2102 : string::string (const char *utf8, size_t len)
     573                 :             : {
     574                 :        2102 :   gcc_assert (utf8);
     575                 :        2102 :   m_utf8 = XNEWVEC (char, len + 1);
     576                 :        2102 :   m_len = len;
     577                 :        2102 :   memcpy (m_utf8, utf8, len);
     578                 :        2102 :   m_utf8[len] = '\0';
     579                 :        2102 : }
     580                 :             : 
     581                 :             : /* Implementation of json::value::print for json::string.  */
     582                 :             : 
     583                 :             : void
     584                 :      499785 : string::print (pretty_printer *pp,
     585                 :             :                bool formatted ATTRIBUTE_UNUSED) const
     586                 :             : {
     587                 :      499785 :   print_escaped_json_string (pp, m_utf8, m_len);
     588                 :      499785 : }
     589                 :             : 
     590                 :             : std::unique_ptr<value>
     591                 :        1876 : string::clone () const
     592                 :             : {
     593                 :        1876 :   return std::make_unique<string> (m_utf8, m_len);
     594                 :             : }
     595                 :             : 
     596                 :             : /* class json::literal, a subclass of json::value.  */
     597                 :             : 
     598                 :             : /* Implementation of json::value::print for json::literal.  */
     599                 :             : 
     600                 :             : void
     601                 :         213 : literal::print (pretty_printer *pp,
     602                 :             :                 bool formatted ATTRIBUTE_UNUSED) const
     603                 :             : {
     604                 :         213 :   switch (m_kind)
     605                 :             :     {
     606                 :         113 :     case JSON_TRUE:
     607                 :         113 :       pp_string (pp, "true");
     608                 :         113 :       break;
     609                 :          92 :     case JSON_FALSE:
     610                 :          92 :       pp_string (pp, "false");
     611                 :          92 :       break;
     612                 :           8 :     case JSON_NULL:
     613                 :           8 :       pp_string (pp, "null");
     614                 :           8 :       break;
     615                 :           0 :     default:
     616                 :           0 :       gcc_unreachable ();
     617                 :             :     }
     618                 :         213 : }
     619                 :             : 
     620                 :             : std::unique_ptr<value>
     621                 :           4 : literal::clone () const
     622                 :             : {
     623                 :           4 :   return std::make_unique<literal> (m_kind);
     624                 :             : }
     625                 :             : 
     626                 :             : 
     627                 :             : #if CHECKING_P
     628                 :             : 
     629                 :             : namespace selftest {
     630                 :             : 
     631                 :             : /* Selftests.  */
     632                 :             : 
     633                 :             : /* Verify that JV->print () prints EXPECTED_JSON.  */
     634                 :             : 
     635                 :             : void
     636                 :         160 : assert_print_eq (const location &loc,
     637                 :             :                  const json::value &jv,
     638                 :             :                  bool formatted,
     639                 :             :                  const char *expected_json)
     640                 :             : {
     641                 :         160 :   pretty_printer pp;
     642                 :         160 :   jv.print (&pp, formatted);
     643                 :         160 :   ASSERT_STREQ_AT (loc, expected_json, pp_formatted_text (&pp));
     644                 :         160 : }
     645                 :             : 
     646                 :             : #define ASSERT_PRINT_EQ(JV, FORMATTED, EXPECTED_JSON)   \
     647                 :             :   assert_print_eq (SELFTEST_LOCATION, JV, FORMATTED, EXPECTED_JSON)
     648                 :             : 
     649                 :             : /* Verify that object::get works as expected.  */
     650                 :             : 
     651                 :             : static void
     652                 :           4 : test_object_get ()
     653                 :             : {
     654                 :           4 :   object obj;
     655                 :           4 :   value *val = new json::string ("value");
     656                 :           4 :   obj.set ("foo", val);
     657                 :           4 :   ASSERT_EQ (obj.get ("foo"), val);
     658                 :           4 :   ASSERT_EQ (obj.get ("not-present"), NULL);
     659                 :           4 : }
     660                 :             : 
     661                 :             : /* Verify that JSON objects are written correctly.  */
     662                 :             : 
     663                 :             : static void
     664                 :           4 : test_writing_objects ()
     665                 :             : {
     666                 :           4 :   object obj;
     667                 :           4 :   obj.set_string ("foo", "bar");
     668                 :           4 :   obj.set_string ("baz", "quux");
     669                 :           4 :   obj.set_string ("\"\\\b\f\n\r\t", "value for awkward key");
     670                 :             : 
     671                 :             :   /* This test relies on json::object writing out key/value pairs
     672                 :             :      in key-insertion order.  */
     673                 :           4 :   ASSERT_PRINT_EQ (obj, true,
     674                 :             :                    "{\"foo\": \"bar\",\n"
     675                 :             :                    " \"baz\": \"quux\",\n"
     676                 :             :                    " \"\\\"\\\\\\b\\f\\n\\r\\t\": \"value for awkward key\"}");
     677                 :           4 :   ASSERT_PRINT_EQ (obj, false,
     678                 :             :                    "{\"foo\": \"bar\", \"baz\": \"quux\""
     679                 :             :                    ", \"\\\"\\\\\\b\\f\\n\\r\\t\": \"value for awkward key\"}");
     680                 :           4 : }
     681                 :             : 
     682                 :             : /* Verify that JSON arrays are written correctly.  */
     683                 :             : 
     684                 :             : static void
     685                 :           4 : test_writing_arrays ()
     686                 :             : {
     687                 :           4 :   array arr;
     688                 :           4 :   ASSERT_PRINT_EQ (arr, true, "[]");
     689                 :             : 
     690                 :           4 :   arr.append (new json::string ("foo"));
     691                 :           4 :   ASSERT_PRINT_EQ (arr, true, "[\"foo\"]");
     692                 :             : 
     693                 :           4 :   arr.append_string ("bar");
     694                 :           4 :   ASSERT_PRINT_EQ (arr, true,
     695                 :             :                    "[\"foo\",\n"
     696                 :             :                    " \"bar\"]");
     697                 :           4 :   ASSERT_PRINT_EQ (arr, false,
     698                 :             :                    "[\"foo\", \"bar\"]");
     699                 :           4 : }
     700                 :             : 
     701                 :             : /* Verify that JSON numbers are written correctly.  */
     702                 :             : 
     703                 :             : static void
     704                 :           4 : test_writing_float_numbers ()
     705                 :             : {
     706                 :           4 :   ASSERT_PRINT_EQ (float_number (0), true, "0");
     707                 :           4 :   ASSERT_PRINT_EQ (float_number (42), true, "42");
     708                 :           4 :   ASSERT_PRINT_EQ (float_number (-100), true, "-100");
     709                 :           4 :   ASSERT_PRINT_EQ (float_number (123456789), true, "1.23457e+08");
     710                 :           4 : }
     711                 :             : 
     712                 :             : static void
     713                 :           4 : test_writing_integer_numbers ()
     714                 :             : {
     715                 :           4 :   ASSERT_PRINT_EQ (integer_number (0), true, "0");
     716                 :           4 :   ASSERT_PRINT_EQ (integer_number (42), true, "42");
     717                 :           4 :   ASSERT_PRINT_EQ (integer_number (-100), true, "-100");
     718                 :           4 :   ASSERT_PRINT_EQ (integer_number (123456789), true, "123456789");
     719                 :           4 :   ASSERT_PRINT_EQ (integer_number (-123456789), true, "-123456789");
     720                 :           4 : }
     721                 :             : 
     722                 :             : /* Verify that JSON strings are written correctly.  */
     723                 :             : 
     724                 :             : static void
     725                 :           4 : test_writing_strings ()
     726                 :             : {
     727                 :           4 :   string foo ("foo");
     728                 :           4 :   ASSERT_PRINT_EQ (foo, true, "\"foo\"");
     729                 :             : 
     730                 :           4 :   string contains_quotes ("before \"quoted\" after");
     731                 :           4 :   ASSERT_PRINT_EQ (contains_quotes, true, "\"before \\\"quoted\\\" after\"");
     732                 :             : 
     733                 :           4 :   const char data[] = {'a', 'b', 'c', 'd', '\0', 'e', 'f'};
     734                 :           4 :   string not_terminated (data, 3);
     735                 :           4 :   ASSERT_PRINT_EQ (not_terminated, true, "\"abc\"");
     736                 :           4 :   string embedded_null (data, sizeof data);
     737                 :           4 :   ASSERT_PRINT_EQ (embedded_null, true, "\"abcd\\0ef\"");
     738                 :           4 : }
     739                 :             : 
     740                 :             : /* Verify that JSON literals are written correctly.  */
     741                 :             : 
     742                 :             : static void
     743                 :           4 : test_writing_literals ()
     744                 :             : {
     745                 :           4 :   ASSERT_PRINT_EQ (literal (JSON_TRUE), true, "true");
     746                 :           4 :   ASSERT_PRINT_EQ (literal (JSON_FALSE), true, "false");
     747                 :           4 :   ASSERT_PRINT_EQ (literal (JSON_NULL), true, "null");
     748                 :             : 
     749                 :           4 :   ASSERT_PRINT_EQ (literal (true), true, "true");
     750                 :           4 :   ASSERT_PRINT_EQ (literal (false), true, "false");
     751                 :           4 : }
     752                 :             : 
     753                 :             : /* Verify that nested values are formatted correctly when written.
     754                 :             : 
     755                 :             :    Also, make use of array::append(std::unique_ptr<value>) and
     756                 :             :    object::set (const char *key, std::unique_ptr<value> v).*/
     757                 :             : 
     758                 :             : static void
     759                 :           4 : test_formatting ()
     760                 :             : {
     761                 :           4 :   object obj;
     762                 :           4 :   object *child = new object;
     763                 :           4 :   std::unique_ptr<object> grandchild = std::make_unique<object> ();
     764                 :             : 
     765                 :           4 :   obj.set_string ("str", "bar");
     766                 :           4 :   obj.set ("child", child);
     767                 :           4 :   obj.set_integer ("int", 42);
     768                 :             : 
     769                 :           4 :   array *arr = new array;
     770                 :          16 :   for (int i = 0; i < 3; i++)
     771                 :          12 :     arr->append (std::make_unique<integer_number> (i));
     772                 :           4 :   grandchild->set ("arr", arr);
     773                 :           4 :   grandchild->set_integer ("int", 1066);
     774                 :             : 
     775                 :           4 :   child->set ("grandchild", std::move (grandchild));
     776                 :           4 :   child->set_integer ("int", 1776);
     777                 :             : 
     778                 :             :   /* This test relies on json::object writing out key/value pairs
     779                 :             :      in key-insertion order.  */
     780                 :           4 :   ASSERT_PRINT_EQ (obj, true,
     781                 :             :                    ("{\"str\": \"bar\",\n"
     782                 :             :                     " \"child\": {\"grandchild\": {\"arr\": [0,\n"
     783                 :             :                     "                                  1,\n"
     784                 :             :                     "                                  2],\n"
     785                 :             :                     "                          \"int\": 1066},\n"
     786                 :             :                     "           \"int\": 1776},\n"
     787                 :             :                     " \"int\": 42}"));
     788                 :           4 :   ASSERT_PRINT_EQ (obj, false,
     789                 :             :                    ("{\"str\": \"bar\", \"child\": {\"grandchild\":"
     790                 :             :                     " {\"arr\": [0, 1, 2], \"int\": 1066},"
     791                 :             :                     " \"int\": 1776}, \"int\": 42}"));
     792                 :           4 : }
     793                 :             : 
     794                 :             : /* Helper function for reporting failure of JSON comparisons.  */
     795                 :             : 
     796                 :             : static void
     797                 :           0 : fail_comparison (const location &loc,
     798                 :             :                  const char *desc,
     799                 :             :                  const value &val_a, const value &val_b,
     800                 :             :                  const char *desc_expected_value,
     801                 :             :                  int actual_value)
     802                 :             : {
     803                 :           0 :   fprintf (stderr, "val_a: ");
     804                 :           0 :   val_a.dump ();
     805                 :             : 
     806                 :           0 :   fprintf (stderr, "val_b: ");
     807                 :           0 :   val_b.dump ();
     808                 :             : 
     809                 :           0 :   selftest::fail_formatted (loc,
     810                 :             :                             "%s: failed JSON comparison:"
     811                 :             :                             " expected: %s got: %i\n",
     812                 :             :                             desc,
     813                 :             :                             desc_expected_value, actual_value);
     814                 :             : }
     815                 :             : 
     816                 :             : /* Implementation of ASSERT_JSON_EQ.  */
     817                 :             : 
     818                 :             : static void
     819                 :         100 : assert_json_equal (const location &loc,
     820                 :             :                    const char *desc,
     821                 :             :                    const value &val_a, const value &val_b)
     822                 :             : {
     823                 :             :   /* Comparison should return zero, both ways, indicating no differences.  */
     824                 :         100 :   const int a_vs_b = value::compare (val_a, val_b);
     825                 :         100 :   if (a_vs_b != 0)
     826                 :           0 :     fail_comparison (loc, desc, val_a, val_b, "zero", a_vs_b);
     827                 :             : 
     828                 :         100 :   const int b_vs_a = value::compare (val_b, val_a);
     829                 :         100 :   if (b_vs_a != 0)
     830                 :           0 :     fail_comparison (loc, desc, val_b, val_a, "zero", b_vs_a);
     831                 :         100 : }
     832                 :             : 
     833                 :             : /* Verify that json::value::compare returns 0 ("no differences") on
     834                 :             :    VAL1 and VAL2, in both orders.  */
     835                 :             : 
     836                 :             : #define ASSERT_JSON_EQ(VAL1, VAL2) \
     837                 :             :   SELFTEST_BEGIN_STMT                                           \
     838                 :             :     assert_json_equal ((SELFTEST_LOCATION),                     \
     839                 :             :                        "ASSERT_JSON_EQ",                      \
     840                 :             :                        (VAL1), (VAL2));                 \
     841                 :             :   SELFTEST_END_STMT
     842                 :             : 
     843                 :             : /* Implementation of ASSERT_JSON_NE.  */
     844                 :             : 
     845                 :             : static void
     846                 :          48 : assert_json_non_equal (const location &loc,
     847                 :             :                        const char *desc,
     848                 :             :                        const value &val_a, const value &val_b)
     849                 :             : {
     850                 :             :   /* Comparison should be non-zero, indicating differences.  */
     851                 :          48 :   const int a_vs_b = value::compare (val_a, val_b);
     852                 :          48 :   if (a_vs_b == 0)
     853                 :           0 :     fail_comparison (loc, desc, val_a, val_b, "non-zero", a_vs_b);
     854                 :             : 
     855                 :          48 :   const int b_vs_a = value::compare (val_b, val_a);
     856                 :          48 :   ASSERT_NE_AT (loc, b_vs_a, 0);
     857                 :          48 :   if (b_vs_a == 0)
     858                 :             :     fail_comparison (loc, desc, val_b, val_a, "non-zero", b_vs_a);
     859                 :             : 
     860                 :             :   /* Swapping the args should swap the sign of the result
     861                 :             :      (but isn't necessarily the negation).  */
     862                 :          48 :   if ( (a_vs_b > 0) == (b_vs_a > 0) )
     863                 :           0 :     fail_comparison (loc, desc, val_b, val_a, "opposite signs", 1);
     864                 :          48 : }
     865                 :             : 
     866                 :             : /* Verify that json::value::compare returns non-zero ("different") on
     867                 :             :    VAL1 and VAL2, in both orders, and that they have opposite
     868                 :             :    sign.  */
     869                 :             : 
     870                 :             : #define ASSERT_JSON_NE(VAL1, VAL2) \
     871                 :             :   SELFTEST_BEGIN_STMT                                           \
     872                 :             :     assert_json_non_equal ((SELFTEST_LOCATION),         \
     873                 :             :                            "ASSERT_JSON_NE",                  \
     874                 :             :                            (VAL1), (VAL2));                     \
     875                 :             :   SELFTEST_END_STMT
     876                 :             : 
     877                 :             : /* Verify that json::value::compare works as expected.  */
     878                 :             : 
     879                 :             : static void
     880                 :           4 : test_comparisons ()
     881                 :             : {
     882                 :             :   /* Literals.  */
     883                 :             : 
     884                 :           4 :   literal null_lit (JSON_NULL);
     885                 :           4 :   ASSERT_JSON_EQ (null_lit, null_lit);
     886                 :             : 
     887                 :           4 :   literal other_null_lit (JSON_NULL);
     888                 :           4 :   ASSERT_JSON_EQ (null_lit, other_null_lit);
     889                 :             : 
     890                 :           4 :   literal true_lit (JSON_TRUE);
     891                 :           4 :   ASSERT_JSON_EQ (true_lit, true_lit);
     892                 :           4 :   ASSERT_JSON_NE (true_lit, null_lit);
     893                 :             : 
     894                 :           4 :   literal false_lit (JSON_FALSE);
     895                 :           4 :   ASSERT_JSON_EQ (false_lit, false_lit);
     896                 :           4 :   ASSERT_JSON_NE (false_lit, true_lit);
     897                 :           4 :   ASSERT_JSON_NE (false_lit, null_lit);
     898                 :             : 
     899                 :             :   /* Strings.  */
     900                 :           4 :   string str_foo_1 ("foo");
     901                 :           4 :   ASSERT_JSON_EQ (str_foo_1, str_foo_1);
     902                 :             : 
     903                 :           4 :   string str_foo_2 ("foo");
     904                 :           4 :   ASSERT_JSON_EQ (str_foo_1, str_foo_2);
     905                 :             : 
     906                 :           4 :   string str_bar ("bar");
     907                 :           4 :   ASSERT_JSON_NE (str_bar, str_foo_1);
     908                 :             : 
     909                 :             :   /* Numbers.  */
     910                 :           4 :   integer_number i_42 (42);
     911                 :           4 :   ASSERT_JSON_EQ (i_42, i_42);
     912                 :           4 :   integer_number i_42_2 (42);
     913                 :           4 :   ASSERT_JSON_EQ (i_42, i_42_2);
     914                 :           4 :   integer_number i_43 (43);
     915                 :           4 :   ASSERT_JSON_NE (i_42, i_43);
     916                 :             : 
     917                 :           4 :   float_number f_zero (0.0);
     918                 :           4 :   ASSERT_JSON_EQ (f_zero, f_zero);
     919                 :           4 :   float_number f_zero_2 (0.0);
     920                 :           4 :   ASSERT_JSON_EQ (f_zero, f_zero_2);
     921                 :           4 :   float_number f_one (1.0);
     922                 :           4 :   ASSERT_JSON_NE (f_zero, f_one);
     923                 :             :   /* We don't yet test the more awkward cases e.g. NaN.  */
     924                 :             : 
     925                 :             :   /* Objects.  */
     926                 :             : 
     927                 :             :   // Empty object
     928                 :             :   // Self comparison should be 0
     929                 :           4 :   object empty_obj_a;
     930                 :           4 :   ASSERT_JSON_EQ (empty_obj_a, empty_obj_a);
     931                 :             : 
     932                 :             :   // Instances of empty objects should compare equal to each other
     933                 :           4 :   object empty_obj_b;
     934                 :           4 :   ASSERT_JSON_EQ (empty_obj_a, empty_obj_b);
     935                 :             : 
     936                 :             :   // Object with one field:
     937                 :           4 :   object obj_1;
     938                 :           4 :   obj_1.set_string ("foo", "bar");
     939                 :             :   // Self comparison should be 0
     940                 :           4 :   ASSERT_JSON_EQ (obj_1, obj_1);
     941                 :             : 
     942                 :             :   // but should be different to an empty object:
     943                 :           4 :   ASSERT_JSON_NE (obj_1, empty_obj_a);
     944                 :             : 
     945                 :             :   // Another with one field, with same key/value:
     946                 :           4 :   object obj_2;
     947                 :           4 :   obj_2.set_string ("foo", "bar");
     948                 :           4 :   ASSERT_JSON_EQ (obj_1, obj_2);
     949                 :             : 
     950                 :             :   // Same key, different value:
     951                 :           4 :   object obj_3;
     952                 :           4 :   obj_3.set_string ("foo", "baz");
     953                 :           4 :   ASSERT_JSON_NE (obj_1, obj_3);
     954                 :             : 
     955                 :             :   // Adding an extra property:
     956                 :           4 :   obj_2.set_integer ("year", 1066);
     957                 :           4 :   ASSERT_JSON_NE (obj_1, obj_2);
     958                 :             : 
     959                 :             :   /* Different insertion order, but same k-v pairs should be equal,
     960                 :             :      despite having different serialization.  */
     961                 :           4 :   object obj_4;
     962                 :           4 :   obj_4.set_integer ("year", 1066);
     963                 :           4 :   obj_4.set_string ("foo", "bar");
     964                 :           4 :   ASSERT_JSON_EQ (obj_2, obj_4);
     965                 :           4 :   ASSERT_PRINT_EQ (obj_2, false, "{\"foo\": \"bar\", \"year\": 1066}");
     966                 :           4 :   ASSERT_PRINT_EQ (obj_4, false, "{\"year\": 1066, \"foo\": \"bar\"}");
     967                 :             : 
     968                 :             :   /* Arrays.  */
     969                 :             : 
     970                 :             :   // Empty array
     971                 :           4 :   array empty_arr_a;
     972                 :             :   // Self comparison should be 0
     973                 :           4 :   ASSERT_JSON_EQ (empty_arr_a, empty_arr_a);
     974                 :             : 
     975                 :             :   // Objects and arrays are different
     976                 :           4 :   ASSERT_JSON_NE (empty_obj_a, empty_arr_a);
     977                 :             : 
     978                 :             :   // Instances of empty arrays should compare equal to each other
     979                 :           4 :   array empty_arr_b;
     980                 :           4 :   ASSERT_JSON_EQ (empty_arr_a, empty_arr_b);
     981                 :             : 
     982                 :             :   // Array with one element:
     983                 :           4 :   array arr_1;
     984                 :           4 :   arr_1.append (std::make_unique<string> ("foo"));
     985                 :             :   // Self comparison should be 0
     986                 :           4 :   ASSERT_JSON_EQ (arr_1, arr_1);
     987                 :             : 
     988                 :             :   // but should be different to an empty array:
     989                 :           4 :   ASSERT_JSON_NE (arr_1, empty_arr_a);
     990                 :             : 
     991                 :             :   // Another with one element:
     992                 :           4 :   array arr_2;
     993                 :           4 :   arr_2.append (std::make_unique<string> ("foo"));
     994                 :           4 :   ASSERT_JSON_EQ (arr_1, arr_2);
     995                 :             : 
     996                 :             :   // Adding an extra element:
     997                 :           4 :   arr_2.append (std::make_unique<string> ("bar"));
     998                 :           4 :   ASSERT_JSON_NE (arr_1, arr_2);
     999                 :           4 : }
    1000                 :             : 
    1001                 :             : /* Ensure that json::string's get_string is usable as a C-style string.  */
    1002                 :             : 
    1003                 :             : static void
    1004                 :           4 : test_strcmp ()
    1005                 :             : {
    1006                 :           4 :   string str ("foobar", 3);
    1007                 :           4 :   ASSERT_EQ (strcmp (str.get_string (), "foo"), 0);
    1008                 :           4 : }
    1009                 :             : 
    1010                 :             : static void
    1011                 :           4 : test_cloning ()
    1012                 :             : {
    1013                 :             :   // Objects
    1014                 :           4 :   {
    1015                 :           4 :     object obj;
    1016                 :           4 :     obj.set_string ("foo", "bar");
    1017                 :             : 
    1018                 :           4 :     auto obj_clone = obj.clone ();
    1019                 :           4 :     ASSERT_JSON_EQ (obj, *obj_clone);
    1020                 :           4 :   }
    1021                 :             : 
    1022                 :             :   // Arrays
    1023                 :           4 :   {
    1024                 :           4 :     array arr;
    1025                 :           4 :     arr.append (std::make_unique<string> ("foo"));
    1026                 :             : 
    1027                 :           4 :     auto arr_clone = arr.clone ();
    1028                 :           4 :     ASSERT_JSON_EQ (arr, *arr_clone);
    1029                 :           4 :   }
    1030                 :             : 
    1031                 :             :   // float_number
    1032                 :           4 :   {
    1033                 :           4 :     float_number f_one (1.0);
    1034                 :           4 :     auto f_clone = f_one.clone ();
    1035                 :           4 :     ASSERT_JSON_EQ (f_one, *f_clone);
    1036                 :           4 :   }
    1037                 :             : 
    1038                 :             :   // integer_number
    1039                 :           4 :   {
    1040                 :           4 :     integer_number num (42);
    1041                 :           4 :     auto num_clone = num.clone ();
    1042                 :           4 :     ASSERT_JSON_EQ (num, *num_clone);
    1043                 :           4 :   }
    1044                 :             : 
    1045                 :             :   // string
    1046                 :           4 :   {
    1047                 :           4 :     string str ("foo");
    1048                 :           4 :     auto str_clone = str.clone ();
    1049                 :           4 :     ASSERT_JSON_EQ (str, *str_clone);
    1050                 :           4 :   }
    1051                 :             : 
    1052                 :             :   // literal
    1053                 :           4 :   {
    1054                 :           4 :     literal lit (JSON_TRUE);
    1055                 :           4 :     auto lit_clone = lit.clone ();
    1056                 :           4 :     ASSERT_JSON_EQ (lit, *lit_clone);
    1057                 :           4 :   }
    1058                 :           4 : }
    1059                 :             : 
    1060                 :             : /* Run all of the selftests within this file.  */
    1061                 :             : 
    1062                 :             : void
    1063                 :           4 : json_cc_tests ()
    1064                 :             : {
    1065                 :           4 :   test_object_get ();
    1066                 :           4 :   test_writing_objects ();
    1067                 :           4 :   test_writing_arrays ();
    1068                 :           4 :   test_writing_float_numbers ();
    1069                 :           4 :   test_writing_integer_numbers ();
    1070                 :           4 :   test_writing_strings ();
    1071                 :           4 :   test_writing_literals ();
    1072                 :           4 :   test_formatting ();
    1073                 :           4 :   test_comparisons ();
    1074                 :           4 :   test_strcmp ();
    1075                 :           4 :   test_cloning ();
    1076                 :           4 : }
    1077                 :             : 
    1078                 :             : } // namespace selftest
    1079                 :             : 
    1080                 :             : #endif /* #if CHECKING_P */
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.