LCOV - code coverage report
Current view: top level - gcc - json.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.0 % 67 63
Test Date: 2026-02-28 14:20:25 Functions: 80.0 % 20 16
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* JSON trees
       2              :    Copyright (C) 2017-2026 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              : #ifndef GCC_JSON_H
      22              : #define GCC_JSON_H
      23              : 
      24              : #include "label-text.h"
      25              : 
      26              : /* Implementation of JSON, a lightweight data-interchange format.
      27              : 
      28              :    See http://www.json.org/
      29              :    and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
      30              :    and https://tools.ietf.org/html/rfc7159
      31              : 
      32              :    Supports parsing text into a DOM-like tree of json::value *, directly
      33              :    creating such trees, and dumping json::value * to text.  */
      34              : 
      35              : /* TODO: `libcpp/mkdeps.cc` wants JSON writing support for p1689r5 output;
      36              :    extract this code and move to libiberty.  */
      37              : 
      38              : namespace json
      39              : {
      40              : 
      41              : /* Forward decls of json::value and its subclasses (using indentation
      42              :    to denote inheritance.  */
      43              : 
      44              : class value;
      45              :   class object;
      46              :   class array;
      47              :   class float_number;
      48              :   class integer_number;
      49              :   class string;
      50              :   class literal;
      51              : 
      52              : /* An enum for discriminating the subclasses of json::value.  */
      53              : 
      54              : enum kind
      55              : {
      56              :   /* class json::object.  */
      57              :   JSON_OBJECT,
      58              : 
      59              :   /* class json::array.  */
      60              :   JSON_ARRAY,
      61              : 
      62              :   /* class json::integer_number.  */
      63              :   JSON_INTEGER,
      64              : 
      65              :   /* class json::float_number.  */
      66              :   JSON_FLOAT,
      67              : 
      68              :   /* class json::string.  */
      69              :   JSON_STRING,
      70              : 
      71              :   /* class json::literal uses these three values to identify the
      72              :      particular literal.  */
      73              :   JSON_TRUE,
      74              :   JSON_FALSE,
      75              :   JSON_NULL
      76              : };
      77              : 
      78              : namespace pointer { // json::pointer
      79              : 
      80              : /* Implementation of JSON pointer (RFC 6901).  */
      81              : 
      82              : /* A token within a JSON pointer, expressing the parent of a particular
      83              :    JSON value, and how it is descended from that parent.
      84              : 
      85              :    A JSON pointer can be built as a list of these tokens.  */
      86              : 
      87              : struct token
      88              : {
      89              :   enum class kind
      90              :   {
      91              :     root_value,
      92              :     object_member,
      93              :     array_index
      94              :   };
      95              : 
      96              :   token ();
      97              :   token (json::object &parent, const char *member);
      98              :   token (json::array &parent, size_t index);
      99              :   token (const token &other) = delete;
     100              :   token (token &&other) = delete;
     101              : 
     102              :   ~token ();
     103              : 
     104              :   token &
     105              :   operator= (const token &other) = delete;
     106              : 
     107              :   token &
     108              :   operator= (token &&other);
     109              : 
     110              :   void print (pretty_printer *pp) const;
     111              : 
     112              :   json::value *m_parent;
     113              :   union u
     114              :   {
     115              :     char *u_member;
     116              :     size_t u_index;
     117              :   } m_data;
     118              :   enum kind m_kind;
     119              : };
     120              : 
     121              : } // namespace json::pointer
     122              : 
     123              : /* Typesafe way to work with properties in JSON objects.  */
     124              : 
     125              : template <typename Traits>
     126           78 : struct property
     127              : {
     128              :   explicit property (const char *key)
     129              :   : m_key (label_text::borrow (key))
     130              :   {}
     131              : 
     132           39 :   explicit property (const char *key_prefix, const char *key)
     133           39 :   : m_key (label_text::take (concat (key_prefix, key, nullptr)))
     134              :   {}
     135              : 
     136              :   label_text m_key;
     137              : };
     138              : 
     139              : using string_property = property<string>;
     140              : using integer_property = property<integer_number>;
     141              : using bool_property = property<literal>;
     142              : using json_property = property<value>;
     143              : using array_of_string_property = property<array>;
     144              : 
     145              : template <typename EnumType>
     146              : struct enum_traits
     147              : {
     148              :   typedef EnumType enum_t;
     149              : 
     150              :   static enum_t get_unknown_value ();
     151              :   static bool maybe_get_value_from_string (const char *, enum_t &out);
     152              :   static const char *get_string_for_value (enum_t value);
     153              : };
     154              : 
     155              : template <typename EnumType>
     156              : using enum_property = property<enum_traits<EnumType>>;
     157              : 
     158              : /* Base class of JSON value.  */
     159              : 
     160      2683738 : class value
     161              : {
     162              :  public:
     163      3430464 :   virtual ~value () {}
     164              :   virtual enum kind get_kind () const = 0;
     165              :   virtual void print (pretty_printer *pp, bool formatted) const = 0;
     166              :   virtual std::unique_ptr<value> clone () const = 0;
     167              : 
     168              :   void dump (FILE *, bool formatted) const;
     169              :   void DEBUG_FUNCTION dump () const;
     170              : 
     171            0 :   virtual object *dyn_cast_object () { return nullptr; }
     172            0 :   virtual array *dyn_cast_array () { return nullptr; }
     173            0 :   virtual integer_number *dyn_cast_integer_number () { return nullptr; }
     174            0 :   virtual string *dyn_cast_string () { return nullptr; }
     175              : 
     176              :   static int compare (const json::value &val_a, const json::value &val_b);
     177              : 
     178              :   const pointer::token &get_pointer_token () const { return m_pointer_token; }
     179              :   void print_pointer (pretty_printer *pp) const;
     180              : 
     181              :   pointer::token m_pointer_token;
     182              : };
     183              : 
     184              : /* Subclass of value for objects: a collection of key/value pairs
     185              :    preserving the ordering in which keys were inserted.
     186              : 
     187              :    Preserving the order eliminates non-determinism in the output,
     188              :    making it easier for the user to compare repeated invocations.  */
     189              : 
     190              : class object : public value
     191              : {
     192              :  public:
     193              :   ~object ();
     194              : 
     195              :   typedef hash_map <char *, value *,
     196              :     simple_hashmap_traits<nofree_string_hash, value *> > map_t;
     197              : 
     198        18589 :   enum kind get_kind () const final override { return JSON_OBJECT; }
     199              :   void print (pretty_printer *pp, bool formatted) const final override;
     200              :   std::unique_ptr<value> clone () const final override;
     201              : 
     202          305 :   object *dyn_cast_object () final override { return this; }
     203              : 
     204          485 :   bool is_empty () const { return m_map.is_empty (); }
     205              : 
     206              :   void set (const char *key, value *v);
     207              : 
     208              :   /* Set the property KEY of this object, requiring V
     209              :      to be of a specific json::value subclass.
     210              : 
     211              :      This can be used to enforce type-checking, making it easier
     212              :      to comply with a schema, e.g.
     213              :        obj->set<some_subclass> ("property_name", value)
     214              :      leading to a compile-time error if VALUE is not of the
     215              :      appropriate subclass.  */
     216              :   template <typename JsonType>
     217        18145 :   void set (const char *key, std::unique_ptr<JsonType> v)
     218              :   {
     219        18210 :     set (key, v.release ());
     220              :   }
     221              : 
     222              :   value *get (const char *key) const;
     223              :   const map_t &get_map () const { return m_map; }
     224              : 
     225              :   void set_string (const char *key, const char *utf8_value);
     226              :   void set_integer (const char *key, long v);
     227              :   void set_float (const char *key, double v);
     228              : 
     229              :   /* Set to literal true/false.  */
     230              :   void set_bool (const char *key, bool v);
     231              : 
     232              :   /* Typesafe access to properties by name (such as from a schema).  */
     233              :   void set_string (const string_property &property, const char *utf8_value);
     234              :   void set_integer (const integer_property &property, long value);
     235              :   void set_bool (const bool_property &property, bool value);
     236              :   void set_array_of_string (const array_of_string_property &property,
     237              :                             std::unique_ptr<json::array> value);
     238              :   template <typename EnumType>
     239              :   bool maybe_get_enum (const enum_property<EnumType> &property,
     240              :                        EnumType &out) const;
     241              :   template <typename EnumType>
     242              :   void set_enum (const enum_property<EnumType> &property,
     243              :                  EnumType value);
     244              : 
     245              :   static int compare (const json::object &obj_a, const json::object &obj_b);
     246              : 
     247         4251 :   size_t get_num_keys () const { return m_keys.length (); }
     248         3089 :   const char *get_key (size_t i) const { return m_keys[i]; }
     249              : 
     250              :   std::unique_ptr<object> clone_as_object () const;
     251              : 
     252              :  private:
     253              :   map_t m_map;
     254              : 
     255              :   /* Keep track of order in which keys were inserted.  */
     256              :   auto_vec <const char *> m_keys;
     257              : };
     258              : 
     259              : /* Subclass of value for arrays.  */
     260              : 
     261       619550 : class array : public value
     262              : {
     263              :  public:
     264              :   ~array ();
     265              : 
     266          777 :   enum kind get_kind () const final override { return JSON_ARRAY; }
     267              :   void print (pretty_printer *pp, bool formatted) const final override;
     268              :   std::unique_ptr<value> clone () const final override;
     269              : 
     270         2100 :   array *dyn_cast_array () final override { return this; }
     271              : 
     272              :   void append (value *v);
     273              :   void append_string (const char *utf8_value);
     274              : 
     275              :   /* Append V to this array, requiring V
     276              :      to be a specific json::value subclass.
     277              : 
     278              :      This can be used to enforce type-checking, making it easier
     279              :      to comply with a schema, e.g.
     280              :        arr->append<some_subclass> (value)
     281              :      leading to a compile-time error if VALUE is not of the
     282              :      appropriate subclass.  */
     283              :   template <typename JsonType>
     284         5966 :   void append (std::unique_ptr<JsonType> v)
     285              :   {
     286         5966 :     append (v.release ());
     287              :   }
     288              : 
     289         2097 :   size_t size () const { return m_elements.length (); }
     290          916 :   value *operator[] (size_t i) const { return m_elements[i]; }
     291              : 
     292         3497 :   value **begin () { return m_elements.begin (); }
     293         3497 :   value **end () { return m_elements.end (); }
     294              :   const value * const *begin () const { return m_elements.begin (); }
     295              :   const value * const *end () const { return m_elements.end (); }
     296          420 :   size_t length () const { return m_elements.length (); }
     297          353 :   value *get (size_t idx) const { return m_elements[idx]; }
     298              : 
     299              :  private:
     300              :   auto_vec<value *> m_elements;
     301              : };
     302              : 
     303              : /* Subclass of value for floating-point numbers.  */
     304              : 
     305           24 : class float_number : public value
     306              : {
     307              :  public:
     308           56 :   float_number (double value) : m_value (value) {}
     309              : 
     310           84 :   enum kind get_kind () const final override { return JSON_FLOAT; }
     311              :   void print (pretty_printer *pp, bool formatted) const final override;
     312              :   std::unique_ptr<value> clone () const final override;
     313              : 
     314           44 :   double get () const { return m_value; }
     315              : 
     316              :  private:
     317              :   double m_value;
     318              : };
     319              : 
     320              : /* Subclass of value for integer-valued numbers.  */
     321              : 
     322           28 : class integer_number : public value
     323              : {
     324              :  public:
     325       668345 :   integer_number (long value) : m_value (value) {}
     326              : 
     327         2467 :   enum kind get_kind () const final override { return JSON_INTEGER; }
     328              :   void print (pretty_printer *pp, bool formatted) const final override;
     329              :   std::unique_ptr<value> clone () const final override;
     330              : 
     331          128 :   integer_number *dyn_cast_integer_number () final override { return this; }
     332              : 
     333         2462 :   long get () const { return m_value; }
     334              : 
     335              :  private:
     336              :   long m_value;
     337              : };
     338              : 
     339              : 
     340              : /* Subclass of value for strings.  */
     341              : 
     342              : class string : public value
     343              : {
     344              :  public:
     345              :   explicit string (const char *utf8);
     346              :   string (const char *utf8, size_t len);
     347      4128218 :   ~string () { free (m_utf8); }
     348              : 
     349        23630 :   enum kind get_kind () const final override { return JSON_STRING; }
     350              :   void print (pretty_printer *pp, bool formatted) const final override;
     351              :   std::unique_ptr<value> clone () const final override;
     352         2740 :   string *dyn_cast_string () final override { return this; }
     353              : 
     354        15167 :   const char *get_string () const { return m_utf8; }
     355              :   size_t get_length () const { return m_len; }
     356              : 
     357              :  private:
     358              :   char *m_utf8;
     359              :   size_t m_len;
     360              : };
     361              : 
     362              : /* Subclass of value for the three JSON literals "true", "false",
     363              :    and "null".  */
     364              : 
     365           28 : class literal : public value
     366              : {
     367              :  public:
     368           44 :   literal (enum kind kind) : m_kind (kind) {}
     369              : 
     370              :   /* Construct literal for a boolean value.  */
     371          745 :   literal (bool value): m_kind (value ? JSON_TRUE : JSON_FALSE) {}
     372              : 
     373          144 :   enum kind get_kind () const final override { return m_kind; }
     374              :   void print (pretty_printer *pp, bool formatted) const final override;
     375              :   std::unique_ptr<value> clone () const final override;
     376              : 
     377              :  private:
     378              :   enum kind m_kind;
     379              : };
     380              : 
     381              : 
     382              : template <typename EnumType>
     383              : inline bool
     384           24 : object::maybe_get_enum (const enum_property<EnumType> &property,
     385              :                         EnumType &out) const
     386              : {
     387           24 :   if (value *jv = get (property.m_key.get ()))
     388           20 :     if (string *jstr = jv->dyn_cast_string ())
     389              :       {
     390           20 :         if (enum_traits<EnumType>::maybe_get_value_from_string
     391           20 :             (jstr->get_string (), out))
     392              :           return true;
     393              :       }
     394              :   return false;
     395              : }
     396              : 
     397              : template <typename EnumType>
     398              : inline void
     399          555 : object::set_enum (const enum_property<EnumType> &property,
     400              :                   EnumType value)
     401              : {
     402              :   const char *str
     403          555 :     = json::enum_traits<EnumType>::get_string_for_value (value);
     404          555 :   set_string (property.m_key.get (), str);
     405          555 : }
     406              : 
     407              : } // namespace json
     408              : 
     409              : template <>
     410              : template <>
     411              : inline bool
     412              : is_a_helper <json::value *>::test (json::value *)
     413              : {
     414              :   return true;
     415              : }
     416              : 
     417              : template <>
     418              : template <>
     419              : inline bool
     420              : is_a_helper <const json::value *>::test (const json::value *)
     421              : {
     422              :   return true;
     423              : }
     424              : 
     425              : template <>
     426              : template <>
     427              : inline bool
     428              : is_a_helper <json::object *>::test (json::value *jv)
     429              : {
     430              :   return jv->get_kind () == json::JSON_OBJECT;
     431              : }
     432              : 
     433              : template <>
     434              : template <>
     435              : inline bool
     436              : is_a_helper <const json::object *>::test (const json::value *jv)
     437              : {
     438              :   return jv->get_kind () == json::JSON_OBJECT;
     439              : }
     440              : 
     441              : template <>
     442              : template <>
     443              : inline bool
     444            4 : is_a_helper <json::array *>::test (json::value *jv)
     445              : {
     446            4 :   return jv->get_kind () == json::JSON_ARRAY;
     447              : }
     448              : 
     449              : template <>
     450              : template <>
     451              : inline bool
     452            4 : is_a_helper <const json::array *>::test (const json::value *jv)
     453              : {
     454            4 :   return jv->get_kind () == json::JSON_ARRAY;
     455              : }
     456              : 
     457              : template <>
     458              : template <>
     459              : inline bool
     460              : is_a_helper <json::float_number *>::test (json::value *jv)
     461              : {
     462              :   return jv->get_kind () == json::JSON_FLOAT;
     463              : }
     464              : 
     465              : template <>
     466              : template <>
     467              : inline bool
     468            8 : is_a_helper <const json::float_number *>::test (const json::value *jv)
     469              : {
     470            8 :   return jv->get_kind () == json::JSON_FLOAT;
     471              : }
     472              : 
     473              : template <>
     474              : template <>
     475              : inline bool
     476           44 : is_a_helper <json::integer_number *>::test (json::value *jv)
     477              : {
     478           44 :   return jv->get_kind () == json::JSON_INTEGER;
     479              : }
     480              : 
     481              : template <>
     482              : template <>
     483              : inline bool
     484           12 : is_a_helper <const json::integer_number *>::test (const json::value *jv)
     485              : {
     486           12 :   return jv->get_kind () == json::JSON_INTEGER;
     487              : }
     488              : 
     489              : template <>
     490              : template <>
     491              : inline bool
     492            4 : is_a_helper <json::string *>::test (json::value *jv)
     493              : {
     494            4 :   return jv->get_kind () == json::JSON_STRING;
     495              : }
     496              : 
     497              : template <>
     498              : template <>
     499              : inline bool
     500           16 : is_a_helper <const json::string *>::test (const  json::value *jv)
     501              : {
     502           16 :   return jv->get_kind () == json::JSON_STRING;
     503              : }
     504              : 
     505              : template <>
     506              : template <>
     507              : inline bool
     508              : is_a_helper<json::literal *>::test (json::value *jv)
     509              : {
     510              :   return (jv->get_kind () == json::JSON_TRUE
     511              :           || jv->get_kind () == json::JSON_FALSE
     512              :           || jv->get_kind () == json::JSON_NULL);
     513              : }
     514              : 
     515              : template <>
     516              : template <>
     517              : inline bool
     518              : is_a_helper<const json::literal *>::test (const json::value *jv)
     519              : {
     520              :   return (jv->get_kind () == json::JSON_TRUE
     521              :           || jv->get_kind () == json::JSON_FALSE
     522              :           || jv->get_kind () == json::JSON_NULL);
     523              : }
     524              : 
     525              : #if CHECKING_P
     526              : 
     527              : namespace selftest {
     528              : 
     529              : class location;
     530              : 
     531              : extern void assert_print_eq (const location &loc,
     532              :                              const json::value &jv,
     533              :                              bool formatted,
     534              :                              const char *expected_json);
     535              : 
     536              : } // namespace selftest
     537              : 
     538              : #endif /* #if CHECKING_P */
     539              : 
     540              : #endif  /* GCC_JSON_H  */
        

Generated by: LCOV version 2.4-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.