LCOV - code coverage report
Current view: top level - json - parser.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 29 29
Test Date: 2025-12-23 16:57:37 Functions: 100.0 % 11 11

            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      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.1