LCOV - code coverage report
Current view: top level - json - parser.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 29 29
Test Date: 2026-02-25 20:43:10 Functions: 100.0 % 11 11

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : //
       4                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6                 : //
       7                 : // Official repository: https://github.com/boostorg/json
       8                 : //
       9                 : 
      10                 : #ifndef BOOST_JSON_PARSER_HPP
      11                 : #define BOOST_JSON_PARSER_HPP
      12                 : 
      13                 : #include <boost/json/detail/config.hpp>
      14                 : #include <boost/json/basic_parser.hpp>
      15                 : #include <boost/json/storage_ptr.hpp>
      16                 : #include <boost/json/value.hpp>
      17                 : #include <boost/json/detail/handler.hpp>
      18                 : #include <type_traits>
      19                 : #include <cstddef>
      20                 : 
      21                 : namespace boost {
      22                 : namespace json {
      23                 : 
      24                 : //----------------------------------------------------------
      25                 : 
      26                 : /** A DOM parser for JSON contained in a single buffer.
      27                 : 
      28                 :     This class is used to parse a JSON text contained in a single character
      29                 :     buffer, into a @ref value container.
      30                 : 
      31                 :     @par Usage
      32                 :     To use the parser first construct it, then optionally call @ref reset to
      33                 :     specify a @ref storage_ptr to use for the resulting @ref value. Then call
      34                 :     @ref write to parse a character buffer containing a complete JSON text. If
      35                 :     the parse is successful, call @ref release to take ownership of the value:
      36                 :     @code
      37                 :     parser p;                                       // construct a parser
      38                 :     size_t n = p.write( "[1,2,3]" );                // parse a complete JSON text
      39                 :     assert( n == 7 );                               // all characters consumed
      40                 :     value jv = p.release();                         // take ownership of the value
      41                 :     @endcode
      42                 : 
      43                 :     @par Extra Data
      44                 :     When the character buffer provided as input contains additional data that
      45                 :     is not part of the complete JSON text, an error is returned. The @ref
      46                 :     write_some function is an alternative which allows the parse to finish
      47                 :     early, without consuming all the characters in the buffer. This allows
      48                 :     parsing of a buffer containing multiple individual JSON texts or containing
      49                 :     different protocol data:
      50                 :     @code
      51                 :     parser p;                                       // construct a parser
      52                 :     size_t n = p.write_some( "[1,2,3] null" );      // parse a complete JSON text
      53                 :     assert( n == 8 );                               // only some characters consumed
      54                 :     value jv = p.release();                         // take ownership of the value
      55                 :     @endcode
      56                 : 
      57                 :     @par Temporary Storage
      58                 :     The parser may dynamically allocate temporary storage as needed to
      59                 :     accommodate the nesting level of the JSON text being parsed. Temporary
      60                 :     storage is first obtained from an optional, caller-owned buffer specified
      61                 :     upon construction. When that is exhausted, the next allocation uses the
      62                 :     @ref boost::container::pmr::memory_resource passed to the constructor; if
      63                 :     no such argument is specified, the default memory resource is used.
      64                 :     Temporary storage is freed only when the parser is destroyed; The
      65                 :     performance of parsing multiple JSON texts may be improved by reusing the
      66                 :     same parser instance.
      67                 : 
      68                 :     It is important to note that the `boost::container::pmr::memory_resource`
      69                 :     supplied upon construction is used for temporary storage only, and not for
      70                 :     allocating the elements which make up the parsed value. That other memory
      71                 :     resource is optionally supplied in each call to @ref reset.
      72                 : 
      73                 :     @par Duplicate Keys
      74                 :     If there are object elements with duplicate keys; that is, if multiple
      75                 :     elements in an object have keys that compare equal, only the last
      76                 :     equivalent element will be inserted.
      77                 : 
      78                 :     @par Non-Standard JSON
      79                 :     The @ref parse_options structure optionally provided upon construction is
      80                 :     used to customize some parameters of the parser, including which
      81                 :     non-standard JSON extensions should be allowed. A default-constructed parse
      82                 :     options allows only standard JSON.
      83                 : 
      84                 :     @par Thread Safety
      85                 :     Distinct instances may be accessed concurrently. Non-const member functions
      86                 :     of a shared instance may not be called concurrently with any other member
      87                 :     functions of that instance.
      88                 : 
      89                 :     @see @ref parse, @ref stream_parser.
      90                 : */
      91                 : class parser
      92                 : {
      93                 :     basic_parser<detail::handler> p_;
      94                 : 
      95                 : public:
      96                 :     /** Assignment operator.
      97                 : 
      98                 :         This type is neither copyable nor movable. The operator is deleted.
      99                 :     */
     100                 :     parser& operator=(
     101                 :         parser const&) = delete;
     102                 : 
     103                 :     /** Destructor.
     104                 : 
     105                 :         All dynamically allocated memory, including
     106                 :         any incomplete parsing results, is freed.
     107                 : 
     108                 :         @par Complexity
     109                 :         Linear in the size of partial results.
     110                 : 
     111                 :         @par Exception Safety
     112                 :         No-throw guarantee.
     113                 :     */
     114 HIT     2001563 :     ~parser() = default;
     115                 : 
     116                 :     /** Constructors.
     117                 : 
     118                 :         Construct a new parser.
     119                 : 
     120                 :         The parser will only support standard JSON if overloads **(1)**
     121                 :         or **(2)** are used. Otherwise the parser will support extensions
     122                 :         specified by the parameter `opt`.
     123                 : 
     124                 :         The parsed value will use the \<\<default_memory_resource,default
     125                 :         memory resource\>\> for storage. To use a different resource, call @ref
     126                 :         reset after construction.
     127                 : 
     128                 :         The main difference between the overloads is in what the constructed
     129                 :         parser will use for temporary storage:
     130                 : 
     131                 :         @li **(1)** the constructed parser uses the default memory resource for
     132                 :         temporary storage.
     133                 : 
     134                 :         @li **(2)**, **(3)** the constructed parser uses the memory resource of
     135                 :         `sp` for temporary storage.
     136                 : 
     137                 :         @li **(4)**, **(6)** the constructed parser first uses the caller-owned
     138                 :         storage `[buffer, buffer + size)` for temporary storage, falling back
     139                 :         to the memory resource of `sp` if needed.
     140                 : 
     141                 :         @li **(5)**, **(7)** the constructed parser first uses the caller-owned
     142                 :         storage `[buffer, buffer + N)` for temporary storage, falling back to
     143                 :         the memory resource of `sp` if needed.
     144                 : 
     145                 :         @note Ownership of `buffer` is not transferred. The caller is
     146                 :         responsible for ensuring the lifetime of the storage pointed to by
     147                 :         `buffer` extends until the parser is destroyed.
     148                 : 
     149                 :         Overload **(8)** is the copy constructor. The type is neither copyable
     150                 :         nor movable, so the overload is deleted.
     151                 : 
     152                 :         @par Complexity
     153                 :         Constant.
     154                 : 
     155                 :         @par Exception Safety
     156                 :         No-throw guarantee.
     157                 : 
     158                 :         @{
     159                 :     */
     160              53 :     parser() noexcept
     161              53 :         : parser({}, {})
     162                 :     {
     163              53 :     }
     164                 : 
     165                 :     /** Overload
     166                 : 
     167                 :         @param sp The memory resource to use for temporary storage.
     168                 :     */
     169                 :     explicit
     170               1 :     parser(storage_ptr sp) noexcept
     171               1 :         : parser(std::move(sp), {})
     172                 :     {
     173               1 :     }
     174                 : 
     175                 :     /** Overload
     176                 : 
     177                 :         @param opt The parsing options to use.
     178                 :         @param sp
     179                 :     */
     180                 :     BOOST_JSON_DECL
     181                 :     parser(
     182                 :         storage_ptr sp,
     183                 :         parse_options const& opt) noexcept;
     184                 : 
     185                 :     /** Overload
     186                 : 
     187                 :         @param buffer A pointer to valid storage.
     188                 :         @param size The number of valid bytes in `buffer`.
     189                 :         @param sp
     190                 :         @param opt
     191                 :     */
     192                 :     BOOST_JSON_DECL
     193                 :     parser(
     194                 :         storage_ptr sp,
     195                 :         parse_options const& opt,
     196                 :         unsigned char* buffer,
     197                 :         std::size_t size) noexcept;
     198                 : 
     199                 :     /** Overload
     200                 : 
     201                 :         @tparam N The number of valid bytes in `buffer`.
     202                 :         @param sp
     203                 :         @param opt
     204                 :         @param buffer
     205                 :     */
     206                 :     template<std::size_t N>
     207         2001506 :     parser(
     208                 :         storage_ptr sp,
     209                 :         parse_options const& opt,
     210                 :         unsigned char(&buffer)[N]) noexcept
     211         2001506 :         : parser(std::move(sp),
     212         2001506 :             opt, &buffer[0], N)
     213                 :     {
     214         2001506 :     }
     215                 : 
     216                 : #if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
     217                 :     /** Overload
     218                 : 
     219                 :         @param buffer
     220                 :         @param size
     221                 :         @param sp
     222                 :         @param opt
     223                 :     */
     224                 :     parser(
     225                 :         storage_ptr sp,
     226                 :         parse_options const& opt,
     227                 :         std::byte* buffer,
     228                 :         std::size_t size) noexcept
     229                 :         : parser(sp, opt, reinterpret_cast<
     230                 :             unsigned char*>(buffer), size)
     231                 :     {
     232                 :     }
     233                 : 
     234                 :     /** Overload
     235                 : 
     236                 :         @tparam N
     237                 :         @param sp
     238                 :         @param opt
     239                 :         @param buffer
     240                 :     */
     241                 :     template<std::size_t N>
     242                 :     parser(
     243                 :         storage_ptr sp,
     244                 :         parse_options const& opt,
     245                 :         std::byte(&buffer)[N]) noexcept
     246                 :         : parser(std::move(sp),
     247                 :             opt, &buffer[0], N)
     248                 :     {
     249                 :     }
     250                 : #endif
     251                 : 
     252                 : #ifndef BOOST_JSON_DOCS
     253                 :     // Safety net for accidental buffer overflows
     254                 :     template<std::size_t N>
     255                 :     parser(
     256                 :         storage_ptr sp,
     257                 :         parse_options const& opt,
     258                 :         unsigned char(&buffer)[N],
     259                 :         std::size_t n) noexcept
     260                 :         : parser(std::move(sp),
     261                 :             opt, &buffer[0], n)
     262                 :     {
     263                 :         // If this goes off, check your parameters
     264                 :         // closely, chances are you passed an array
     265                 :         // thinking it was a pointer.
     266                 :         BOOST_ASSERT(n <= N);
     267                 :     }
     268                 : 
     269                 : #ifdef __cpp_lib_byte
     270                 :     // Safety net for accidental buffer overflows
     271                 :     template<std::size_t N>
     272                 :     parser(
     273                 :         storage_ptr sp,
     274                 :         parse_options const& opt,
     275                 :         std::byte(&buffer)[N], std::size_t n) noexcept
     276                 :         : parser(std::move(sp),
     277                 :             opt, &buffer[0], n)
     278                 :     {
     279                 :         // If this goes off, check your parameters
     280                 :         // closely, chances are you passed an array
     281                 :         // thinking it was a pointer.
     282                 :         BOOST_ASSERT(n <= N);
     283                 :     }
     284                 : #endif
     285                 : #endif
     286                 : 
     287                 :     /// Overload
     288                 :     parser(
     289                 :         parser const&) = delete;
     290                 :     /// @}
     291                 : 
     292                 : 
     293                 :     /** Reset the parser for a new JSON text.
     294                 : 
     295                 :         This function is used to reset the parser to
     296                 :         prepare it for parsing a new complete JSON text.
     297                 :         Any previous partial results are destroyed.
     298                 : 
     299                 :         @par Complexity
     300                 :         Constant or linear in the size of any previous
     301                 :         partial parsing results.
     302                 : 
     303                 :         @par Exception Safety
     304                 :         No-throw guarantee.
     305                 : 
     306                 :         @param sp A pointer to the @ref boost::container::pmr::memory_resource
     307                 :         to use for the resulting @ref value. The parser will acquire shared
     308                 :         ownership.
     309                 :     */
     310                 :     BOOST_JSON_DECL
     311                 :     void
     312                 :     reset(storage_ptr sp = {}) noexcept;
     313                 : 
     314                 :     /** Parse a buffer containing a complete JSON text.
     315                 : 
     316                 :         This function parses a complete JSON text contained in the specified
     317                 :         character buffer. Additional characters past the end of the complete
     318                 :         JSON text are ignored. The function returns the actual number of
     319                 :         characters parsed, which may be less than the size of the input. This
     320                 :         allows parsing of a buffer containing multiple individual JSON texts or
     321                 :         containing different protocol data:
     322                 : 
     323                 :         @par Example
     324                 :         @code
     325                 :         parser p;                                       // construct a parser
     326                 :         size_t n = p.write_some( "[1,2,3] null" );      // parse a complete JSON text
     327                 :         assert( n == 8 );                               // only some characters consumed
     328                 :         value jv = p.release();                         // take ownership of the value
     329                 :         @endcode
     330                 : 
     331                 :         Overloads **(1)**, **(2)**, **(4)**, and **(5)** report errors by
     332                 :         setting `ec`. Overloads **(3)** and **(6)** report errors by throwing
     333                 :         exceptions.
     334                 : 
     335                 :         @par Complexity
     336                 :         @li **(1)**--**(3)** linear in `size`.
     337                 :         @li **(4)**--**(6)** linear in `s.size()`.
     338                 : 
     339                 :         @par Exception Safety
     340                 :         Basic guarantee. Calls to `memory_resource::allocate` may throw. Upon
     341                 :         error or exception, subsequent calls will fail until @ref reset is
     342                 :         called to parse a new JSON text.
     343                 : 
     344                 :         @return The number of characters consumed from the buffer.
     345                 : 
     346                 :         @param data A pointer to a buffer of `size` characters to parse.
     347                 :         @param size The number of characters pointed to by `data`.
     348                 :         @param ec Set to the error, if any occurred.
     349                 : 
     350                 :         @{
     351                 :     */
     352                 :     BOOST_JSON_DECL
     353                 :     std::size_t
     354                 :     write_some(
     355                 :         char const* data,
     356                 :         std::size_t size,
     357                 :         system::error_code& ec);
     358                 : 
     359                 :     BOOST_JSON_DECL
     360                 :     std::size_t
     361                 :     write_some(
     362                 :         char const* data,
     363                 :         std::size_t size,
     364                 :         std::error_code& ec);
     365                 : 
     366                 :     /** Overload
     367                 : 
     368                 :         @param data
     369                 :         @param size
     370                 :     */
     371                 :     BOOST_JSON_DECL
     372                 :     std::size_t
     373                 :     write_some(
     374                 :         char const* data,
     375                 :         std::size_t size);
     376                 : 
     377                 :     /** Overload
     378                 : 
     379                 :         @param s The character string to parse.
     380                 :         @param ec
     381                 :     */
     382                 :     std::size_t
     383               2 :     write_some(
     384                 :         string_view s,
     385                 :         system::error_code& ec)
     386                 :     {
     387               2 :         return write_some(
     388               2 :             s.data(), s.size(), ec);
     389                 :     }
     390                 : 
     391                 :     /** Overload
     392                 : 
     393                 :         @param s
     394                 :         @param ec
     395                 :     */
     396                 :     std::size_t
     397               2 :     write_some(
     398                 :         string_view s,
     399                 :         std::error_code& ec)
     400                 :     {
     401               2 :         return write_some(
     402               2 :             s.data(), s.size(), ec);
     403                 :     }
     404                 : 
     405                 :     /** Overload
     406                 : 
     407                 :         @param s
     408                 :     */
     409                 :     std::size_t
     410               4 :     write_some(
     411                 :         string_view s)
     412                 :     {
     413               4 :         return write_some(
     414               2 :             s.data(), s.size());
     415                 :     }
     416                 :     /// @}
     417                 : 
     418                 :     /** Parse a buffer containing a complete JSON text.
     419                 : 
     420                 :         This function parses a complete JSON text contained in the specified
     421                 :         character buffer. The entire buffer must be consumed; if there are
     422                 :         additional characters past the end of the complete JSON text, the parse
     423                 :         fails and an error is returned.
     424                 : 
     425                 :         @par Example
     426                 :         @code
     427                 :         parser p;                                       // construct a parser
     428                 :         size_t n = p.write( "[1,2,3]" );                // parse a complete JSON text
     429                 :         assert( n == 7 );                               // all characters consumed
     430                 :         value jv = p.release();                         // take ownership of the value
     431                 :         @endcode
     432                 : 
     433                 :         Overloads **(1)**, **(2)**, **(4)**, and **(5)** report errors by
     434                 :         setting `ec`. Overloads **(3)** and **(6)** report errors by throwing
     435                 :         exceptions.
     436                 : 
     437                 :         @par Complexity
     438                 :         @li **(1)**--**(3)** linear in `size`.
     439                 :         @li **(4)**--**(6)** linear in `s.size()`.
     440                 : 
     441                 :         @par Exception Safety
     442                 :         Basic guarantee. Calls to `memory_resource::allocate` may throw. Upon
     443                 :         error or exception, subsequent calls will fail until @ref reset is
     444                 :         called to parse a new JSON text.
     445                 : 
     446                 :         @return The number of characters consumed from the buffer.
     447                 : 
     448                 :         @param data A pointer to a buffer of `size` characters to parse.
     449                 :         @param size The number of characters pointed to by `data`.
     450                 :         @param ec Set to the error, if any occurred.
     451                 : 
     452                 :         @{
     453                 :     */
     454                 :     BOOST_JSON_DECL
     455                 :     std::size_t
     456                 :     write(
     457                 :         char const* data,
     458                 :         std::size_t size,
     459                 :         system::error_code& ec);
     460                 : 
     461                 :     BOOST_JSON_DECL
     462                 :     std::size_t
     463                 :     write(
     464                 :         char const* data,
     465                 :         std::size_t size,
     466                 :         std::error_code& ec);
     467                 : 
     468                 :     /** Overload
     469                 : 
     470                 :         @throw `boost::system::system_error` Thrown on error.
     471                 :     */
     472                 :     BOOST_JSON_DECL
     473                 :     std::size_t
     474                 :     write(
     475                 :         char const* data,
     476                 :         std::size_t size);
     477                 : 
     478                 :     /** Overload
     479                 : 
     480                 :         @param s The character string to parse.
     481                 :         @param ec
     482                 :     */
     483                 :     std::size_t
     484         2001508 :     write(
     485                 :         string_view s,
     486                 :         system::error_code& ec)
     487                 :     {
     488         2001508 :         return write(
     489         2001507 :             s.data(), s.size(), ec);
     490                 :     }
     491                 : 
     492                 :     /** Overload
     493                 : 
     494                 :         @param s
     495                 :         @param ec
     496                 :     */
     497                 :     std::size_t
     498               3 :     write(
     499                 :         string_view s,
     500                 :         std::error_code& ec)
     501                 :     {
     502               3 :         return write(
     503               3 :             s.data(), s.size(), ec);
     504                 :     }
     505                 : 
     506                 :     /** Overload
     507                 : 
     508                 :         @param s
     509                 :     */
     510                 :     std::size_t
     511               8 :     write(
     512                 :         string_view s)
     513                 :     {
     514               8 :         return write(
     515               4 :             s.data(), s.size());
     516                 :     }
     517                 :     /// @}
     518                 : 
     519                 :     /** Return the parsed JSON text as a @ref value.
     520                 : 
     521                 :         This returns the parsed value, or throws an exception if the parsing is
     522                 :         incomplete or failed. It is necessary to call @ref reset after calling
     523                 :         this function in order to parse another JSON text.
     524                 : 
     525                 :         @par Complexity
     526                 :         Constant.
     527                 : 
     528                 :         @return The parsed value. Ownership of this value is transferred to the
     529                 :         caller.
     530                 : 
     531                 :         @throw boost::system::system_error A complete JSON text hasn't been
     532                 :                parsed, or parsing failed.
     533                 :     */
     534                 :     BOOST_JSON_DECL
     535                 :     value
     536                 :     release();
     537                 : };
     538                 : 
     539                 : } // namespace json
     540                 : } // namespace boost
     541                 : 
     542                 : #endif
        

Generated by: LCOV version 2.3