LCOV - code coverage report
Current view: top level - gcc - json.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 96.4 % 500 482
Test Date: 2025-07-12 13:27:34 Functions: 96.2 % 53 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                 :     1330372 : print_escaped_json_string (pretty_printer *pp,
      37                 :             :                            const char *utf8_str,
      38                 :             :                            size_t len)
      39                 :             : {
      40                 :     1330372 :   pp_character (pp, '"');
      41                 :    18013799 :   for (size_t i = 0; i != len; ++i)
      42                 :             :     {
      43                 :    16683427 :       char ch = utf8_str[i];
      44                 :    16683427 :       switch (ch)
      45                 :             :         {
      46                 :        2588 :         case '"':
      47                 :        2588 :           pp_string (pp, "\\\"");
      48                 :        2588 :           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                 :       52930 :         case '\n':
      59                 :       52930 :           pp_string (pp, "\\n");
      60                 :       52930 :           break;
      61                 :           8 :         case '\r':
      62                 :           8 :           pp_string (pp, "\\r");
      63                 :           8 :           break;
      64                 :        3580 :         case '\t':
      65                 :        3580 :           pp_string (pp, "\\t");
      66                 :        3580 :           break;
      67                 :           4 :         case '\0':
      68                 :           4 :           pp_string (pp, "\\0");
      69                 :           4 :           break;
      70                 :    16622818 :         default:
      71                 :    16622818 :           pp_character (pp, ch);
      72                 :             :         }
      73                 :             :     }
      74                 :     1330372 :   pp_character (pp, '"');
      75                 :     1330372 : }
      76                 :             : 
      77                 :             : /* class pointer::token.  */
      78                 :             : 
      79                 :     4143751 : pointer::token::token ()
      80                 :             : {
      81                 :     4143751 :   m_parent = nullptr;
      82                 :     4143751 :   m_data.u_member = nullptr;
      83                 :     4143751 :   m_kind = kind::root_value;
      84                 :     4143751 : }
      85                 :             : 
      86                 :     3338479 : pointer::token::token (json::object &parent, const char *member)
      87                 :             : {
      88                 :     3338479 :   m_parent = &parent;
      89                 :     3338479 :   m_data.u_member = xstrdup (member); // ideally we'd share
      90                 :     3338479 :   m_kind = kind::object_member;
      91                 :     3338479 : }
      92                 :             : 
      93                 :      800717 : pointer::token::token (json::array &parent, size_t index)
      94                 :             : {
      95                 :      800717 :   m_parent = &parent;
      96                 :      800717 :   m_data.u_index = index;
      97                 :      800717 :   m_kind = kind::array_index;
      98                 :      800717 : }
      99                 :             : 
     100                 :     8281595 : pointer::token::~token ()
     101                 :             : {
     102                 :     8281595 :   if (m_kind == kind::object_member)
     103                 :             :     {
     104                 :     3337345 :       gcc_assert (m_data.u_member);
     105                 :     3337345 :       free (m_data.u_member);
     106                 :             :     }
     107                 :     8281595 : }
     108                 :             : 
     109                 :             : pointer::token &
     110                 :     4139196 : pointer::token::operator= (pointer::token &&other)
     111                 :             : {
     112                 :     4139196 :   m_parent = other.m_parent;
     113                 :     4139196 :   m_data = other.m_data;
     114                 :     4139196 :   m_kind = other.m_kind;
     115                 :             : 
     116                 :     4139196 :   other.m_parent = nullptr;
     117                 :     4139196 :   other.m_data.u_member = nullptr;
     118                 :     4139196 :   other.m_kind = kind::root_value;
     119                 :             : 
     120                 :     4139196 :   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                 :          98 : value::dump (FILE *outf, bool formatted) const
     132                 :             : {
     133                 :          98 :   pretty_printer pp;
     134                 :          98 :   pp_buffer (&pp)->m_stream = outf;
     135                 :          98 :   print (&pp, formatted);
     136                 :          98 :   pp_flush (&pp);
     137                 :          98 : }
     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                 :       15452 : value::compare (const value &val_a, const value &val_b)
     164                 :             : {
     165                 :       15452 :   enum kind kind_a = val_a.get_kind ();
     166                 :       15452 :   enum kind kind_b = val_b.get_kind ();
     167                 :       15452 :   if (kind_a != kind_b)
     168                 :          32 :     return (int)kind_a - (int)kind_b;
     169                 :             : 
     170                 :       15420 :   switch (kind_a)
     171                 :             :     {
     172                 :           0 :     default:
     173                 :           0 :       gcc_unreachable ();
     174                 :             : 
     175                 :        5041 :     case JSON_OBJECT:
     176                 :        5041 :       {
     177                 :        5041 :         const object &obj_a = (const object &)val_a;
     178                 :        5041 :         const object &obj_b = (const object &)val_b;
     179                 :        5041 :         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                 :       10182 :       break;
     219                 :             : 
     220                 :       10182 :     case JSON_STRING:
     221                 :       10182 :       {
     222                 :       10182 :         const string &str_a = (const string &)val_a;
     223                 :       10182 :         const string &str_b = (const string &)val_b;
     224                 :       10182 :         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                 :     1502122 : object::~object ()
     243                 :             : {
     244                 :     7432229 :   for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it)
     245                 :             :     {
     246                 :     3337254 :       free (const_cast <char *>((*it).first));
     247                 :     3337254 :       delete ((*it).second);
     248                 :             :     }
     249                 :     1502122 : }
     250                 :             : 
     251                 :             : /* Implementation of json::value::print for json::object.  */
     252                 :             : 
     253                 :             : void
     254                 :      251063 : object::print (pretty_printer *pp, bool formatted) const
     255                 :             : {
     256                 :      251063 :   pp_character (pp, '{');
     257                 :      251063 :   if (formatted)
     258                 :        7522 :     pp_indentation (pp) += 1;
     259                 :             : 
     260                 :             :   /* Iterate in the order that the keys were inserted.  */
     261                 :             :   unsigned i;
     262                 :             :   const char *key;
     263                 :     1067217 :   FOR_EACH_VEC_ELT (m_keys, i, key)
     264                 :             :     {
     265                 :      816154 :       if (i > 0)
     266                 :             :         {
     267                 :      565099 :           pp_string (pp, ",");
     268                 :      565099 :           if (formatted)
     269                 :             :             {
     270                 :       10257 :               pp_newline (pp);
     271                 :       10257 :               pp_indent (pp);
     272                 :             :             }
     273                 :             :           else
     274                 :      554842 :             pp_space (pp);
     275                 :             :         }
     276                 :      816154 :       map_t &mut_map = const_cast<map_t &> (m_map);
     277                 :      816154 :       value *value = *mut_map.get (key);
     278                 :      816154 :       print_escaped_json_string (pp, key, strlen (key));
     279                 :      816154 :       pp_string (pp, ": ");
     280                 :      816154 :       const int indent = strlen (key) + 4;
     281                 :      816154 :       if (formatted)
     282                 :       17771 :         pp_indentation (pp) += indent;
     283                 :      816154 :       value->print (pp, formatted);
     284                 :      816154 :       if (formatted)
     285                 :       17771 :         pp_indentation (pp) -= indent;
     286                 :             :     }
     287                 :      251063 :   if (formatted)
     288                 :        7522 :     pp_indentation (pp) -= 1;
     289                 :      251063 :   pp_character (pp, '}');
     290                 :      251063 : }
     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                 :     3338479 : object::set (const char *key, value *v)
     321                 :             : {
     322                 :     3338479 :   gcc_assert (key);
     323                 :     3338479 :   gcc_assert (v);
     324                 :             : 
     325                 :     3338479 :   value **ptr = m_map.get (key);
     326                 :     3338479 :   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                 :     3338388 :       char *owned_key = xstrdup (key);
     338                 :     3338388 :       m_map.put (owned_key, v);
     339                 :     3338388 :       m_keys.safe_push (owned_key);
     340                 :             :     }
     341                 :             : 
     342                 :     3338479 :   v->m_pointer_token = pointer::token (*this, key);
     343                 :     3338479 : }
     344                 :             : 
     345                 :             : /* Get the json::value * for KEY.
     346                 :             : 
     347                 :             :    The object retains ownership of the value.  */
     348                 :             : 
     349                 :             : value *
     350                 :       18733 : object::get (const char *key) const
     351                 :             : {
     352                 :       18733 :   gcc_assert (key);
     353                 :             : 
     354                 :       18733 :   value **ptr = const_cast <map_t &> (m_map).get (key);
     355                 :       18733 :   if (ptr)
     356                 :       17721 :     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                 :     1357466 : object::set_string (const char *key, const char *utf8_value)
     366                 :             : {
     367                 :     1357466 :   set (key, new json::string (utf8_value));
     368                 :     1357466 : }
     369                 :             : 
     370                 :             : /* Set value of KEY within this object to a JSON
     371                 :             :    integer value based on V.  */
     372                 :             : 
     373                 :             : void
     374                 :      672049 : object::set_integer (const char *key, long v)
     375                 :             : {
     376                 :      672049 :   set (key, new json::integer_number (v));
     377                 :      672049 : }
     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                 :         473 : object::set_bool (const char *key, bool v)
     393                 :             : {
     394                 :         946 :   set (key, new json::literal (v));
     395                 :         473 : }
     396                 :             : 
     397                 :             : /* Subroutine of json::compare for comparing a pairs of objects.  */
     398                 :             : 
     399                 :             : int
     400                 :        5041 : object::compare (const json::object &obj_a, const json::object &obj_b)
     401                 :             : {
     402                 :       15047 :   if (int cmp_size = (int)obj_a.m_keys.length () - (int)obj_b.m_keys.length ())
     403                 :             :     return cmp_size;
     404                 :             : 
     405                 :       16038 :   for (auto iter_a : obj_a.m_map)
     406                 :             :     {
     407                 :       10123 :       const char *key = iter_a.first;
     408                 :       10123 :       const value *value_a = iter_a.second;
     409                 :       10123 :       gcc_assert (value_a);
     410                 :             : 
     411                 :       10123 :       const value *value_b = obj_b.get (key);
     412                 :       10123 :       if (!value_b)
     413                 :             :         /* Key is in OBJ_A but not in OBJ_B.  */
     414                 :        4554 :         return 1;
     415                 :             :       /* If key is OBJ_B but not in OBJ_A, then the
     416                 :             :          count of keys will have been different, or
     417                 :             :          OBJ_A would have had a key not in OBJ_B.  */
     418                 :       10123 :       if (int cmp_value = value::compare (*value_a, *value_b))
     419                 :             :         /* Values for key are non-equal.  */
     420                 :             :         return cmp_value;
     421                 :             :     }
     422                 :             : 
     423                 :             :   /* Objects are equal.  */
     424                 :         346 :   return 0;
     425                 :             : }
     426                 :             : 
     427                 :             : /* class json::array, a subclass of json::value, representing
     428                 :             :    an ordered collection of values.  */
     429                 :             : 
     430                 :             : /* json::array's dtor.  */
     431                 :             : 
     432                 :     1236985 : array::~array ()
     433                 :             : {
     434                 :      618919 :   unsigned i;
     435                 :      618919 :   value *v;
     436                 :     1419557 :   FOR_EACH_VEC_ELT (m_elements, i, v)
     437                 :      800638 :     delete v;
     438                 :     1236985 : }
     439                 :             : 
     440                 :             : /* Implementation of json::value::print for json::array.  */
     441                 :             : 
     442                 :             : void
     443                 :       92953 : array::print (pretty_printer *pp, bool formatted) const
     444                 :             : {
     445                 :       92953 :   pp_character (pp, '[');
     446                 :       92953 :   if (formatted)
     447                 :        1856 :     pp_indentation (pp) += 1;
     448                 :             :   unsigned i;
     449                 :             :   value *v;
     450                 :      306913 :   FOR_EACH_VEC_ELT (m_elements, i, v)
     451                 :             :     {
     452                 :      213960 :       if (i)
     453                 :             :         {
     454                 :      135562 :           pp_string (pp, ",");
     455                 :      135562 :           if (formatted)
     456                 :             :             {
     457                 :        4730 :               pp_newline (pp);
     458                 :        4730 :               pp_indent (pp);
     459                 :             :             }
     460                 :             :           else
     461                 :      130832 :             pp_space (pp);
     462                 :             :         }
     463                 :      213960 :       v->print (pp, formatted);
     464                 :             :     }
     465                 :       92953 :   if (formatted)
     466                 :        1856 :     pp_indentation (pp) -= 1;
     467                 :       92953 :   pp_character (pp, ']');
     468                 :       92953 : }
     469                 :             : 
     470                 :             : std::unique_ptr<value>
     471                 :           4 : array::clone () const
     472                 :             : {
     473                 :           4 :   auto result = std::make_unique<array> ();
     474                 :           4 :   unsigned i;
     475                 :           4 :   value *v;
     476                 :          12 :   FOR_EACH_VEC_ELT (m_elements, i, v)
     477                 :           4 :     result->append (v->clone ());
     478                 :           4 :   return result;
     479                 :           4 : }
     480                 :             : 
     481                 :             : /* Append non-NULL value V to a json::array, taking ownership of V.  */
     482                 :             : 
     483                 :             : void
     484                 :      800717 : array::append (value *v)
     485                 :             : {
     486                 :      800717 :   gcc_assert (v);
     487                 :     1406116 :   v->m_pointer_token = pointer::token (*this, m_elements.length ());
     488                 :      800717 :   m_elements.safe_push (v);
     489                 :      800717 : }
     490                 :             : 
     491                 :             : void
     492                 :      181807 : array::append_string (const char *utf8_value)
     493                 :             : {
     494                 :      181807 :   gcc_assert (utf8_value);
     495                 :      181807 :   append (new json::string (utf8_value));
     496                 :      181807 : }
     497                 :             : 
     498                 :             : /* class json::float_number, a subclass of json::value, wrapping a double.  */
     499                 :             : 
     500                 :             : /* Implementation of json::value::print for json::float_number.  */
     501                 :             : 
     502                 :             : void
     503                 :          32 : float_number::print (pretty_printer *pp,
     504                 :             :                      bool formatted ATTRIBUTE_UNUSED) const
     505                 :             : {
     506                 :          32 :   char tmp[1024];
     507                 :          32 :   snprintf (tmp, sizeof (tmp), "%g", m_value);
     508                 :          32 :   pp_string (pp, tmp);
     509                 :          32 : }
     510                 :             : 
     511                 :             : std::unique_ptr<value>
     512                 :           4 : float_number::clone () const
     513                 :             : {
     514                 :           4 :   return std::make_unique<float_number> (m_value);
     515                 :             : }
     516                 :             : 
     517                 :             : /* class json::integer_number, a subclass of json::value, wrapping a long.  */
     518                 :             : 
     519                 :             : /* Implementation of json::value::print for json::integer_number.  */
     520                 :             : 
     521                 :             : void
     522                 :      171952 : integer_number::print (pretty_printer *pp,
     523                 :             :                        bool formatted ATTRIBUTE_UNUSED) const
     524                 :             : {
     525                 :      171952 :   char tmp[1024];
     526                 :      171952 :   snprintf (tmp, sizeof (tmp), "%ld", m_value);
     527                 :      171952 :   pp_string (pp, tmp);
     528                 :      171952 : }
     529                 :             : 
     530                 :             : std::unique_ptr<value>
     531                 :           4 : integer_number::clone () const
     532                 :             : {
     533                 :           4 :   return std::make_unique<integer_number> (m_value);
     534                 :             : }
     535                 :             : 
     536                 :             : /* class json::string, a subclass of json::value.  */
     537                 :             : 
     538                 :             : /* json::string's ctor.  */
     539                 :             : 
     540                 :     2091985 : string::string (const char *utf8)
     541                 :             : {
     542                 :     2091985 :   gcc_assert (utf8);
     543                 :     2091985 :   m_utf8 = xstrdup (utf8);
     544                 :     2091985 :   m_len = strlen (utf8);
     545                 :     2091985 : }
     546                 :             : 
     547                 :        1850 : string::string (const char *utf8, size_t len)
     548                 :             : {
     549                 :        1850 :   gcc_assert (utf8);
     550                 :        1850 :   m_utf8 = XNEWVEC (char, len + 1);
     551                 :        1850 :   m_len = len;
     552                 :        1850 :   memcpy (m_utf8, utf8, len);
     553                 :        1850 :   m_utf8[len] = '\0';
     554                 :        1850 : }
     555                 :             : 
     556                 :             : /* Implementation of json::value::print for json::string.  */
     557                 :             : 
     558                 :             : void
     559                 :      514218 : string::print (pretty_printer *pp,
     560                 :             :                bool formatted ATTRIBUTE_UNUSED) const
     561                 :             : {
     562                 :      514218 :   print_escaped_json_string (pp, m_utf8, m_len);
     563                 :      514218 : }
     564                 :             : 
     565                 :             : std::unique_ptr<value>
     566                 :        1628 : string::clone () const
     567                 :             : {
     568                 :        1628 :   return std::make_unique<string> (m_utf8, m_len);
     569                 :             : }
     570                 :             : 
     571                 :             : /* class json::literal, a subclass of json::value.  */
     572                 :             : 
     573                 :             : /* Implementation of json::value::print for json::literal.  */
     574                 :             : 
     575                 :             : void
     576                 :         209 : literal::print (pretty_printer *pp,
     577                 :             :                 bool formatted ATTRIBUTE_UNUSED) const
     578                 :             : {
     579                 :         209 :   switch (m_kind)
     580                 :             :     {
     581                 :         112 :     case JSON_TRUE:
     582                 :         112 :       pp_string (pp, "true");
     583                 :         112 :       break;
     584                 :          89 :     case JSON_FALSE:
     585                 :          89 :       pp_string (pp, "false");
     586                 :          89 :       break;
     587                 :           8 :     case JSON_NULL:
     588                 :           8 :       pp_string (pp, "null");
     589                 :           8 :       break;
     590                 :           0 :     default:
     591                 :           0 :       gcc_unreachable ();
     592                 :             :     }
     593                 :         209 : }
     594                 :             : 
     595                 :             : std::unique_ptr<value>
     596                 :           4 : literal::clone () const
     597                 :             : {
     598                 :           4 :   return std::make_unique<literal> (m_kind);
     599                 :             : }
     600                 :             : 
     601                 :             : 
     602                 :             : #if CHECKING_P
     603                 :             : 
     604                 :             : namespace selftest {
     605                 :             : 
     606                 :             : /* Selftests.  */
     607                 :             : 
     608                 :             : /* Verify that JV->print () prints EXPECTED_JSON.  */
     609                 :             : 
     610                 :             : void
     611                 :         160 : assert_print_eq (const location &loc,
     612                 :             :                  const json::value &jv,
     613                 :             :                  bool formatted,
     614                 :             :                  const char *expected_json)
     615                 :             : {
     616                 :         160 :   pretty_printer pp;
     617                 :         160 :   jv.print (&pp, formatted);
     618                 :         160 :   ASSERT_STREQ_AT (loc, expected_json, pp_formatted_text (&pp));
     619                 :         160 : }
     620                 :             : 
     621                 :             : #define ASSERT_PRINT_EQ(JV, FORMATTED, EXPECTED_JSON)   \
     622                 :             :   assert_print_eq (SELFTEST_LOCATION, JV, FORMATTED, EXPECTED_JSON)
     623                 :             : 
     624                 :             : /* Verify that object::get works as expected.  */
     625                 :             : 
     626                 :             : static void
     627                 :           4 : test_object_get ()
     628                 :             : {
     629                 :           4 :   object obj;
     630                 :           4 :   value *val = new json::string ("value");
     631                 :           4 :   obj.set ("foo", val);
     632                 :           4 :   ASSERT_EQ (obj.get ("foo"), val);
     633                 :           4 :   ASSERT_EQ (obj.get ("not-present"), NULL);
     634                 :           4 : }
     635                 :             : 
     636                 :             : /* Verify that JSON objects are written correctly.  */
     637                 :             : 
     638                 :             : static void
     639                 :           4 : test_writing_objects ()
     640                 :             : {
     641                 :           4 :   object obj;
     642                 :           4 :   obj.set_string ("foo", "bar");
     643                 :           4 :   obj.set_string ("baz", "quux");
     644                 :           4 :   obj.set_string ("\"\\\b\f\n\r\t", "value for awkward key");
     645                 :             : 
     646                 :             :   /* This test relies on json::object writing out key/value pairs
     647                 :             :      in key-insertion order.  */
     648                 :           4 :   ASSERT_PRINT_EQ (obj, true,
     649                 :             :                    "{\"foo\": \"bar\",\n"
     650                 :             :                    " \"baz\": \"quux\",\n"
     651                 :             :                    " \"\\\"\\\\\\b\\f\\n\\r\\t\": \"value for awkward key\"}");
     652                 :           4 :   ASSERT_PRINT_EQ (obj, false,
     653                 :             :                    "{\"foo\": \"bar\", \"baz\": \"quux\""
     654                 :             :                    ", \"\\\"\\\\\\b\\f\\n\\r\\t\": \"value for awkward key\"}");
     655                 :           4 : }
     656                 :             : 
     657                 :             : /* Verify that JSON arrays are written correctly.  */
     658                 :             : 
     659                 :             : static void
     660                 :           4 : test_writing_arrays ()
     661                 :             : {
     662                 :           4 :   array arr;
     663                 :           4 :   ASSERT_PRINT_EQ (arr, true, "[]");
     664                 :             : 
     665                 :           4 :   arr.append (new json::string ("foo"));
     666                 :           4 :   ASSERT_PRINT_EQ (arr, true, "[\"foo\"]");
     667                 :             : 
     668                 :           4 :   arr.append_string ("bar");
     669                 :           4 :   ASSERT_PRINT_EQ (arr, true,
     670                 :             :                    "[\"foo\",\n"
     671                 :             :                    " \"bar\"]");
     672                 :           4 :   ASSERT_PRINT_EQ (arr, false,
     673                 :             :                    "[\"foo\", \"bar\"]");
     674                 :           4 : }
     675                 :             : 
     676                 :             : /* Verify that JSON numbers are written correctly.  */
     677                 :             : 
     678                 :             : static void
     679                 :           4 : test_writing_float_numbers ()
     680                 :             : {
     681                 :           4 :   ASSERT_PRINT_EQ (float_number (0), true, "0");
     682                 :           4 :   ASSERT_PRINT_EQ (float_number (42), true, "42");
     683                 :           4 :   ASSERT_PRINT_EQ (float_number (-100), true, "-100");
     684                 :           4 :   ASSERT_PRINT_EQ (float_number (123456789), true, "1.23457e+08");
     685                 :           4 : }
     686                 :             : 
     687                 :             : static void
     688                 :           4 : test_writing_integer_numbers ()
     689                 :             : {
     690                 :           4 :   ASSERT_PRINT_EQ (integer_number (0), true, "0");
     691                 :           4 :   ASSERT_PRINT_EQ (integer_number (42), true, "42");
     692                 :           4 :   ASSERT_PRINT_EQ (integer_number (-100), true, "-100");
     693                 :           4 :   ASSERT_PRINT_EQ (integer_number (123456789), true, "123456789");
     694                 :           4 :   ASSERT_PRINT_EQ (integer_number (-123456789), true, "-123456789");
     695                 :           4 : }
     696                 :             : 
     697                 :             : /* Verify that JSON strings are written correctly.  */
     698                 :             : 
     699                 :             : static void
     700                 :           4 : test_writing_strings ()
     701                 :             : {
     702                 :           4 :   string foo ("foo");
     703                 :           4 :   ASSERT_PRINT_EQ (foo, true, "\"foo\"");
     704                 :             : 
     705                 :           4 :   string contains_quotes ("before \"quoted\" after");
     706                 :           4 :   ASSERT_PRINT_EQ (contains_quotes, true, "\"before \\\"quoted\\\" after\"");
     707                 :             : 
     708                 :           4 :   const char data[] = {'a', 'b', 'c', 'd', '\0', 'e', 'f'};
     709                 :           4 :   string not_terminated (data, 3);
     710                 :           4 :   ASSERT_PRINT_EQ (not_terminated, true, "\"abc\"");
     711                 :           4 :   string embedded_null (data, sizeof data);
     712                 :           4 :   ASSERT_PRINT_EQ (embedded_null, true, "\"abcd\\0ef\"");
     713                 :           4 : }
     714                 :             : 
     715                 :             : /* Verify that JSON literals are written correctly.  */
     716                 :             : 
     717                 :             : static void
     718                 :           4 : test_writing_literals ()
     719                 :             : {
     720                 :           4 :   ASSERT_PRINT_EQ (literal (JSON_TRUE), true, "true");
     721                 :           4 :   ASSERT_PRINT_EQ (literal (JSON_FALSE), true, "false");
     722                 :           4 :   ASSERT_PRINT_EQ (literal (JSON_NULL), true, "null");
     723                 :             : 
     724                 :           4 :   ASSERT_PRINT_EQ (literal (true), true, "true");
     725                 :           4 :   ASSERT_PRINT_EQ (literal (false), true, "false");
     726                 :           4 : }
     727                 :             : 
     728                 :             : /* Verify that nested values are formatted correctly when written.
     729                 :             : 
     730                 :             :    Also, make use of array::append(std::unique_ptr<value>) and
     731                 :             :    object::set (const char *key, std::unique_ptr<value> v).*/
     732                 :             : 
     733                 :             : static void
     734                 :           4 : test_formatting ()
     735                 :             : {
     736                 :           4 :   object obj;
     737                 :           4 :   object *child = new object;
     738                 :           4 :   std::unique_ptr<object> grandchild = std::make_unique<object> ();
     739                 :             : 
     740                 :           4 :   obj.set_string ("str", "bar");
     741                 :           4 :   obj.set ("child", child);
     742                 :           4 :   obj.set_integer ("int", 42);
     743                 :             : 
     744                 :           4 :   array *arr = new array;
     745                 :          16 :   for (int i = 0; i < 3; i++)
     746                 :          12 :     arr->append (std::make_unique<integer_number> (i));
     747                 :           4 :   grandchild->set ("arr", arr);
     748                 :           4 :   grandchild->set_integer ("int", 1066);
     749                 :             : 
     750                 :           4 :   child->set ("grandchild", std::move (grandchild));
     751                 :           4 :   child->set_integer ("int", 1776);
     752                 :             : 
     753                 :             :   /* This test relies on json::object writing out key/value pairs
     754                 :             :      in key-insertion order.  */
     755                 :           4 :   ASSERT_PRINT_EQ (obj, true,
     756                 :             :                    ("{\"str\": \"bar\",\n"
     757                 :             :                     " \"child\": {\"grandchild\": {\"arr\": [0,\n"
     758                 :             :                     "                                  1,\n"
     759                 :             :                     "                                  2],\n"
     760                 :             :                     "                          \"int\": 1066},\n"
     761                 :             :                     "           \"int\": 1776},\n"
     762                 :             :                     " \"int\": 42}"));
     763                 :           4 :   ASSERT_PRINT_EQ (obj, false,
     764                 :             :                    ("{\"str\": \"bar\", \"child\": {\"grandchild\":"
     765                 :             :                     " {\"arr\": [0, 1, 2], \"int\": 1066},"
     766                 :             :                     " \"int\": 1776}, \"int\": 42}"));
     767                 :           4 : }
     768                 :             : 
     769                 :             : /* Helper function for reporting failure of JSON comparisons.  */
     770                 :             : 
     771                 :             : static void
     772                 :           0 : fail_comparison (const location &loc,
     773                 :             :                  const char *desc,
     774                 :             :                  const value &val_a, const value &val_b,
     775                 :             :                  const char *desc_expected_value,
     776                 :             :                  int actual_value)
     777                 :             : {
     778                 :           0 :   fprintf (stderr, "val_a: ");
     779                 :           0 :   val_a.dump ();
     780                 :             : 
     781                 :           0 :   fprintf (stderr, "val_b: ");
     782                 :           0 :   val_b.dump ();
     783                 :             : 
     784                 :           0 :   selftest::fail_formatted (loc,
     785                 :             :                             "%s: failed JSON comparison:"
     786                 :             :                             " expected: %s got: %i\n",
     787                 :             :                             desc,
     788                 :             :                             desc_expected_value, actual_value);
     789                 :             : }
     790                 :             : 
     791                 :             : /* Implementation of ASSERT_JSON_EQ.  */
     792                 :             : 
     793                 :             : static void
     794                 :         100 : assert_json_equal (const location &loc,
     795                 :             :                    const char *desc,
     796                 :             :                    const value &val_a, const value &val_b)
     797                 :             : {
     798                 :             :   /* Comparison should return zero, both ways, indicating no differences.  */
     799                 :         100 :   const int a_vs_b = value::compare (val_a, val_b);
     800                 :         100 :   if (a_vs_b != 0)
     801                 :           0 :     fail_comparison (loc, desc, val_a, val_b, "zero", a_vs_b);
     802                 :             : 
     803                 :         100 :   const int b_vs_a = value::compare (val_b, val_a);
     804                 :         100 :   if (b_vs_a != 0)
     805                 :           0 :     fail_comparison (loc, desc, val_b, val_a, "zero", b_vs_a);
     806                 :         100 : }
     807                 :             : 
     808                 :             : /* Verify that json::value::compare returns 0 ("no differences") on
     809                 :             :    VAL1 and VAL2, in both orders.  */
     810                 :             : 
     811                 :             : #define ASSERT_JSON_EQ(VAL1, VAL2) \
     812                 :             :   SELFTEST_BEGIN_STMT                                           \
     813                 :             :     assert_json_equal ((SELFTEST_LOCATION),                     \
     814                 :             :                        "ASSERT_JSON_EQ",                      \
     815                 :             :                        (VAL1), (VAL2));                 \
     816                 :             :   SELFTEST_END_STMT
     817                 :             : 
     818                 :             : /* Implementation of ASSERT_JSON_NE.  */
     819                 :             : 
     820                 :             : static void
     821                 :          48 : assert_json_non_equal (const location &loc,
     822                 :             :                        const char *desc,
     823                 :             :                        const value &val_a, const value &val_b)
     824                 :             : {
     825                 :             :   /* Comparison should be non-zero, indicating differences.  */
     826                 :          48 :   const int a_vs_b = value::compare (val_a, val_b);
     827                 :          48 :   if (a_vs_b == 0)
     828                 :           0 :     fail_comparison (loc, desc, val_a, val_b, "non-zero", a_vs_b);
     829                 :             : 
     830                 :          48 :   const int b_vs_a = value::compare (val_b, val_a);
     831                 :          48 :   ASSERT_NE_AT (loc, b_vs_a, 0);
     832                 :          48 :   if (b_vs_a == 0)
     833                 :             :     fail_comparison (loc, desc, val_b, val_a, "non-zero", b_vs_a);
     834                 :             : 
     835                 :             :   /* Swapping the args should swap the sign of the result
     836                 :             :      (but isn't necessarily the negation).  */
     837                 :          48 :   if ( (a_vs_b > 0) == (b_vs_a > 0) )
     838                 :           0 :     fail_comparison (loc, desc, val_b, val_a, "opposite signs", 1);
     839                 :          48 : }
     840                 :             : 
     841                 :             : /* Verify that json::value::compare returns non-zero ("different") on
     842                 :             :    VAL1 and VAL2, in both orders, and that they have opposite
     843                 :             :    sign.  */
     844                 :             : 
     845                 :             : #define ASSERT_JSON_NE(VAL1, VAL2) \
     846                 :             :   SELFTEST_BEGIN_STMT                                           \
     847                 :             :     assert_json_non_equal ((SELFTEST_LOCATION),         \
     848                 :             :                            "ASSERT_JSON_NE",                  \
     849                 :             :                            (VAL1), (VAL2));                     \
     850                 :             :   SELFTEST_END_STMT
     851                 :             : 
     852                 :             : /* Verify that json::value::compare works as expected.  */
     853                 :             : 
     854                 :             : static void
     855                 :           4 : test_comparisons ()
     856                 :             : {
     857                 :             :   /* Literals.  */
     858                 :             : 
     859                 :           4 :   literal null_lit (JSON_NULL);
     860                 :           4 :   ASSERT_JSON_EQ (null_lit, null_lit);
     861                 :             : 
     862                 :           4 :   literal other_null_lit (JSON_NULL);
     863                 :           4 :   ASSERT_JSON_EQ (null_lit, other_null_lit);
     864                 :             : 
     865                 :           4 :   literal true_lit (JSON_TRUE);
     866                 :           4 :   ASSERT_JSON_EQ (true_lit, true_lit);
     867                 :           4 :   ASSERT_JSON_NE (true_lit, null_lit);
     868                 :             : 
     869                 :           4 :   literal false_lit (JSON_FALSE);
     870                 :           4 :   ASSERT_JSON_EQ (false_lit, false_lit);
     871                 :           4 :   ASSERT_JSON_NE (false_lit, true_lit);
     872                 :           4 :   ASSERT_JSON_NE (false_lit, null_lit);
     873                 :             : 
     874                 :             :   /* Strings.  */
     875                 :           4 :   string str_foo_1 ("foo");
     876                 :           4 :   ASSERT_JSON_EQ (str_foo_1, str_foo_1);
     877                 :             : 
     878                 :           4 :   string str_foo_2 ("foo");
     879                 :           4 :   ASSERT_JSON_EQ (str_foo_1, str_foo_2);
     880                 :             : 
     881                 :           4 :   string str_bar ("bar");
     882                 :           4 :   ASSERT_JSON_NE (str_bar, str_foo_1);
     883                 :             : 
     884                 :             :   /* Numbers.  */
     885                 :           4 :   integer_number i_42 (42);
     886                 :           4 :   ASSERT_JSON_EQ (i_42, i_42);
     887                 :           4 :   integer_number i_42_2 (42);
     888                 :           4 :   ASSERT_JSON_EQ (i_42, i_42_2);
     889                 :           4 :   integer_number i_43 (43);
     890                 :           4 :   ASSERT_JSON_NE (i_42, i_43);
     891                 :             : 
     892                 :           4 :   float_number f_zero (0.0);
     893                 :           4 :   ASSERT_JSON_EQ (f_zero, f_zero);
     894                 :           4 :   float_number f_zero_2 (0.0);
     895                 :           4 :   ASSERT_JSON_EQ (f_zero, f_zero_2);
     896                 :           4 :   float_number f_one (1.0);
     897                 :           4 :   ASSERT_JSON_NE (f_zero, f_one);
     898                 :             :   /* We don't yet test the more awkward cases e.g. NaN.  */
     899                 :             : 
     900                 :             :   /* Objects.  */
     901                 :             : 
     902                 :             :   // Empty object
     903                 :             :   // Self comparison should be 0
     904                 :           4 :   object empty_obj_a;
     905                 :           4 :   ASSERT_JSON_EQ (empty_obj_a, empty_obj_a);
     906                 :             : 
     907                 :             :   // Instances of empty objects should compare equal to each other
     908                 :           4 :   object empty_obj_b;
     909                 :           4 :   ASSERT_JSON_EQ (empty_obj_a, empty_obj_b);
     910                 :             : 
     911                 :             :   // Object with one field:
     912                 :           4 :   object obj_1;
     913                 :           4 :   obj_1.set_string ("foo", "bar");
     914                 :             :   // Self comparison should be 0
     915                 :           4 :   ASSERT_JSON_EQ (obj_1, obj_1);
     916                 :             : 
     917                 :             :   // but should be different to an empty object:
     918                 :           4 :   ASSERT_JSON_NE (obj_1, empty_obj_a);
     919                 :             : 
     920                 :             :   // Another with one field, with same key/value:
     921                 :           4 :   object obj_2;
     922                 :           4 :   obj_2.set_string ("foo", "bar");
     923                 :           4 :   ASSERT_JSON_EQ (obj_1, obj_2);
     924                 :             : 
     925                 :             :   // Same key, different value:
     926                 :           4 :   object obj_3;
     927                 :           4 :   obj_3.set_string ("foo", "baz");
     928                 :           4 :   ASSERT_JSON_NE (obj_1, obj_3);
     929                 :             : 
     930                 :             :   // Adding an extra property:
     931                 :           4 :   obj_2.set_integer ("year", 1066);
     932                 :           4 :   ASSERT_JSON_NE (obj_1, obj_2);
     933                 :             : 
     934                 :             :   /* Different insertion order, but same k-v pairs should be equal,
     935                 :             :      despite having different serialization.  */
     936                 :           4 :   object obj_4;
     937                 :           4 :   obj_4.set_integer ("year", 1066);
     938                 :           4 :   obj_4.set_string ("foo", "bar");
     939                 :           4 :   ASSERT_JSON_EQ (obj_2, obj_4);
     940                 :           4 :   ASSERT_PRINT_EQ (obj_2, false, "{\"foo\": \"bar\", \"year\": 1066}");
     941                 :           4 :   ASSERT_PRINT_EQ (obj_4, false, "{\"year\": 1066, \"foo\": \"bar\"}");
     942                 :             : 
     943                 :             :   /* Arrays.  */
     944                 :             : 
     945                 :             :   // Empty array
     946                 :           4 :   array empty_arr_a;
     947                 :             :   // Self comparison should be 0
     948                 :           4 :   ASSERT_JSON_EQ (empty_arr_a, empty_arr_a);
     949                 :             : 
     950                 :             :   // Objects and arrays are different
     951                 :           4 :   ASSERT_JSON_NE (empty_obj_a, empty_arr_a);
     952                 :             : 
     953                 :             :   // Instances of empty arrays should compare equal to each other
     954                 :           4 :   array empty_arr_b;
     955                 :           4 :   ASSERT_JSON_EQ (empty_arr_a, empty_arr_b);
     956                 :             : 
     957                 :             :   // Array with one element:
     958                 :           4 :   array arr_1;
     959                 :           4 :   arr_1.append (std::make_unique<string> ("foo"));
     960                 :             :   // Self comparison should be 0
     961                 :           4 :   ASSERT_JSON_EQ (arr_1, arr_1);
     962                 :             : 
     963                 :             :   // but should be different to an empty array:
     964                 :           4 :   ASSERT_JSON_NE (arr_1, empty_arr_a);
     965                 :             : 
     966                 :             :   // Another with one element:
     967                 :           4 :   array arr_2;
     968                 :           4 :   arr_2.append (std::make_unique<string> ("foo"));
     969                 :           4 :   ASSERT_JSON_EQ (arr_1, arr_2);
     970                 :             : 
     971                 :             :   // Adding an extra element:
     972                 :           4 :   arr_2.append (std::make_unique<string> ("bar"));
     973                 :           4 :   ASSERT_JSON_NE (arr_1, arr_2);
     974                 :           4 : }
     975                 :             : 
     976                 :             : /* Ensure that json::string's get_string is usable as a C-style string.  */
     977                 :             : 
     978                 :             : static void
     979                 :           4 : test_strcmp ()
     980                 :             : {
     981                 :           4 :   string str ("foobar", 3);
     982                 :           4 :   ASSERT_EQ (strcmp (str.get_string (), "foo"), 0);
     983                 :           4 : }
     984                 :             : 
     985                 :             : static void
     986                 :           4 : test_cloning ()
     987                 :             : {
     988                 :             :   // Objects
     989                 :           4 :   {
     990                 :           4 :     object obj;
     991                 :           4 :     obj.set_string ("foo", "bar");
     992                 :             : 
     993                 :           4 :     auto obj_clone = obj.clone ();
     994                 :           4 :     ASSERT_JSON_EQ (obj, *obj_clone);
     995                 :           4 :   }
     996                 :             : 
     997                 :             :   // Arrays
     998                 :           4 :   {
     999                 :           4 :     array arr;
    1000                 :           4 :     arr.append (std::make_unique<string> ("foo"));
    1001                 :             : 
    1002                 :           4 :     auto arr_clone = arr.clone ();
    1003                 :           4 :     ASSERT_JSON_EQ (arr, *arr_clone);
    1004                 :           4 :   }
    1005                 :             : 
    1006                 :             :   // float_number
    1007                 :           4 :   {
    1008                 :           4 :     float_number f_one (1.0);
    1009                 :           4 :     auto f_clone = f_one.clone ();
    1010                 :           4 :     ASSERT_JSON_EQ (f_one, *f_clone);
    1011                 :           4 :   }
    1012                 :             : 
    1013                 :             :   // integer_number
    1014                 :           4 :   {
    1015                 :           4 :     integer_number num (42);
    1016                 :           4 :     auto num_clone = num.clone ();
    1017                 :           4 :     ASSERT_JSON_EQ (num, *num_clone);
    1018                 :           4 :   }
    1019                 :             : 
    1020                 :             :   // string
    1021                 :           4 :   {
    1022                 :           4 :     string str ("foo");
    1023                 :           4 :     auto str_clone = str.clone ();
    1024                 :           4 :     ASSERT_JSON_EQ (str, *str_clone);
    1025                 :           4 :   }
    1026                 :             : 
    1027                 :             :   // literal
    1028                 :           4 :   {
    1029                 :           4 :     literal lit (JSON_TRUE);
    1030                 :           4 :     auto lit_clone = lit.clone ();
    1031                 :           4 :     ASSERT_JSON_EQ (lit, *lit_clone);
    1032                 :           4 :   }
    1033                 :           4 : }
    1034                 :             : 
    1035                 :             : /* Run all of the selftests within this file.  */
    1036                 :             : 
    1037                 :             : void
    1038                 :           4 : json_cc_tests ()
    1039                 :             : {
    1040                 :           4 :   test_object_get ();
    1041                 :           4 :   test_writing_objects ();
    1042                 :           4 :   test_writing_arrays ();
    1043                 :           4 :   test_writing_float_numbers ();
    1044                 :           4 :   test_writing_integer_numbers ();
    1045                 :           4 :   test_writing_strings ();
    1046                 :           4 :   test_writing_literals ();
    1047                 :           4 :   test_formatting ();
    1048                 :           4 :   test_comparisons ();
    1049                 :           4 :   test_strcmp ();
    1050                 :           4 :   test_cloning ();
    1051                 :           4 : }
    1052                 :             : 
    1053                 :             : } // namespace selftest
    1054                 :             : 
    1055                 :             : #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.