diff --git a/doc/qbk/02_08_parsing.qbk b/doc/qbk/02_08_parsing.qbk index d4a0eee4..ec621327 100644 --- a/doc/qbk/02_08_parsing.qbk +++ b/doc/qbk/02_08_parsing.qbk @@ -38,6 +38,14 @@ functions and types to assist with parsing: A structure used to select which extensions are enabled during parsing. ] +][ + [__parser__] + [ + A stateful DOM parser object which may be used + to efficiently parse a series of JSONs each + contained in a single contiguous character buffer, + returning each result as a __value__. + ] ][ [__stream_parser__] [ @@ -89,8 +97,10 @@ structure and passing it by value. By default all extensions are disabled: [doc_parsing_5] -Using a compiler with support for C++20 features, [@https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers designated initializers] can be used to construct -__parse_options__ with a less verbose but equally expressive syntax: +Using a compiler with support for C++20 features, +[@https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers designated initializers] +can be used to construct __parse_options__ with a less verbose but equally +expressive syntax: [doc_parsing_6] @@ -98,8 +108,8 @@ __parse_options__ with a less verbose but equally expressive syntax: [heading Parser Instance] -Instances of __stream_parser__ offer functionality beyond what is -available when using the __parse__ free functions: +Instances of __parser__ and __stream_parser__ offer functionality beyond +what is available when using the __parse__ free functions: * More control over memory * Streaming API, parse input JSON incrementally @@ -114,12 +124,12 @@ parsing more than one JSON, reducing the total number of dynamic memory allocations. To use the __stream_parser__, declare an instance. Then call -[link json.ref.boost__json__parser.write `write`] +[link json.ref.boost__json__stream_parser.write `write`] zero or more times with successive buffers representing the input JSON. When there are no more buffers, call -[link json.ref.boost__json__parser.finish `finish`]. +[link json.ref.boost__json__stream_parser.finish `finish`]. The function -[link json.ref.boost__json__parser.done `done`]. +[link json.ref.boost__json__stream_parser.done `done`]. returns `true` after a successful call to `write` or `finish` if parsing is complete. This example persists the parser instance in a class member to reuse across calls: @@ -141,7 +151,7 @@ JSON in fixed-size amounts, providing these benefits: In the following example a JSON is parsed from standard input a line at a time. Error codes are used instead. The function -[link json.ref.boost__json__parser.finish `finish`] +[link json.ref.boost__json__stream_parser.finish `finish`] is used to indicate the end of the input: [doc_parsing_8] @@ -165,7 +175,7 @@ allow some non-standard JSON extensions to be recognized: [heading Controlling Memory] After default construction, or after -[link json.ref.boost__json__parser.reset `reset`] +[link json.ref.boost__json__stream_parser.reset `reset`] is called with no arguments, the __value__ produced after a successful parse operation uses the default memory resource. To use a different memory resource, call `reset` with the resource to use. Here we use diff --git a/doc/qbk/main.qbk b/doc/qbk/main.qbk index baa034d3..8aef243c 100644 --- a/doc/qbk/main.qbk +++ b/doc/qbk/main.qbk @@ -64,6 +64,7 @@ [def __number_cast__ [link json.ref.boost__json__number_cast `number_cast`]] [def __object__ [link json.ref.boost__json__object `object`]] [def __parse__ [link json.ref.boost__json__parse `parse`]] +[def __parser__ [link json.ref.boost__json__parser `parser`]] [def __parse_options__ [link json.ref.boost__json__parse_options `parse_options`]] [def __polymorphic_allocator__ [link json.ref.boost__json__polymorphic_allocator `polymorphic_allocator`]] [def __serialize__ [link json.ref.boost__json__serialize `serialize`]] diff --git a/doc/qbk/quickref.xml b/doc/qbk/quickref.xml index b2a0b23f..4fc5a64e 100644 --- a/doc/qbk/quickref.xml +++ b/doc/qbk/quickref.xml @@ -25,6 +25,7 @@ key_value_pair monotonic_resource object + parser parse_options serializer static_resource diff --git a/include/boost/json.hpp b/include/boost/json.hpp index 313425ba..06be6a15 100644 --- a/include/boost/json.hpp +++ b/include/boost/json.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/json/impl/parse.ipp b/include/boost/json/impl/parse.ipp index 793c1c04..bf97555e 100644 --- a/include/boost/json/impl/parse.ipp +++ b/include/boost/json/impl/parse.ipp @@ -12,7 +12,7 @@ #define BOOST_JSON_IMPL_PARSE_IPP #include -#include +#include #include BOOST_JSON_NS_BEGIN @@ -25,17 +25,12 @@ parse( const parse_options& opt) { unsigned char temp[BOOST_JSON_STACK_BUFFER_SIZE]; - stream_parser p( + parser p( storage_ptr(), opt, temp, sizeof(temp)); p.reset(std::move(sp)); - p.write( - s.data(), - s.size(), - ec); - if(! ec) - p.finish(ec); + p.write(s, ec); if(ec) return nullptr; return p.release(); diff --git a/include/boost/json/impl/parser.ipp b/include/boost/json/impl/parser.ipp new file mode 100644 index 00000000..5f8d309d --- /dev/null +++ b/include/boost/json/impl/parser.ipp @@ -0,0 +1,151 @@ +// +// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/json +// + +#ifndef BOOST_JSON_IMPL_PARSER_IPP +#define BOOST_JSON_IMPL_PARSER_IPP + +#include +#include +#include +#include +#include +#include + +BOOST_JSON_NS_BEGIN + +parser:: +parser( + storage_ptr sp, + parse_options const& opt, + unsigned char* buffer, + std::size_t size) noexcept + : p_( + opt, + std::move(sp), + buffer, + size) +{ + reset(); +} + +parser:: +parser( + storage_ptr sp, + parse_options const& opt) noexcept + : p_( + opt, + std::move(sp), + nullptr, + 0) +{ + reset(); +} + +void +parser:: +reset(storage_ptr sp) noexcept +{ + p_.reset(); + p_.handler().st.reset(sp); +} + +std::size_t +parser:: +write_some( + char const* data, + std::size_t size, + error_code& ec) +{ + auto const n = p_.write_some( + false, data, size, ec); + if(! ec) + { + if(! p_.done()) + { + ec = error::incomplete; + p_.fail(ec); + } + } + return n; +} + +std::size_t +parser:: +write_some( + char const* data, + std::size_t size) +{ + error_code ec; + auto const n = p_.write_some( + true, data, size, ec); + if(ec) + detail::throw_system_error(ec, + BOOST_CURRENT_LOCATION); + return n; +} + +std::size_t +parser:: +write( + char const* data, + std::size_t size, + error_code& ec) +{ + auto const n = write_some( + data, size, ec); + if(! ec) + { + if(! p_.done()) + { + ec = error::incomplete; + p_.fail(ec); + } + else if(n < size) + { + ec = error::extra_data; + p_.fail(ec); + } + } + return n; +} + +std::size_t +parser:: +write( + char const* data, + std::size_t size) +{ + error_code ec; + auto const n = write( + data, size, ec); + if(ec) + detail::throw_system_error(ec, + BOOST_CURRENT_LOCATION); + return n; +} + +value +parser:: +release() +{ + if( ! p_.done()) + { + // prevent undefined behavior + if(! p_.last_error()) + p_.fail(error::incomplete); + detail::throw_system_error( + p_.last_error(), + BOOST_CURRENT_LOCATION); + } + return p_.handler().st.release(); +} + +BOOST_JSON_NS_END + +#endif diff --git a/include/boost/json/parser.hpp b/include/boost/json/parser.hpp new file mode 100644 index 00000000..07c20087 --- /dev/null +++ b/include/boost/json/parser.hpp @@ -0,0 +1,868 @@ +// +// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/json +// + +#ifndef BOOST_JSON_PARSER_HPP +#define BOOST_JSON_PARSER_HPP + +#include +#include +#include +#include +#include +#include +#include + +BOOST_JSON_NS_BEGIN + +//---------------------------------------------------------- + +/** A DOM parser for serialized JSON. + + This class is used to incrementally parse JSON + from character buffers into a @ref value container. + + @par Usage + + Parsing for a new JSON may begin after the parser is + constructed, or after calling @ref reset, optionally + passing the storage pointer to be used by the + @ref value container into which the parsed results + are stored. After the parse is started, call + @ref write_some or @ref write to provide buffers + of characters of the JSON. When there are no more + buffers, call @ref finish. The parse is complete + when the function @ref done returns `true`, or + when a non-successful error code is returned. + To retrieve the result on success, call @ref release. + + @par Incremental Parsing + + The parser allows the input to be presented in + multiple character buffers. This is useful when + not all of the serialized JSON is present at once + and it is desirable to process the data as it becomes + available, such as when reading from a network socket + or other device. The incremental interface may also + be used to bound the amount of work performed in each + parsing cycle. + + @par Temporary Storage + + The parser may dynamically allocate temporary + storage as needed to accommodate the nesting level + of the JSON being parsed. Temporary storage is + first obtained from an optional, caller-owned + buffer specified upon construction. When that + is exhausted, the next allocation uses the + @ref memory_resource passed to the constructor; if + no such argument is specified, the default memory + resource is used instead. Temporary storage is + freed only when the parser is destroyed, improving + performance when the parser is reused to parse + multiple JSONs. +\n + It is important to note that the @ref memory_resource + supplied upon construction is used for temporary + storage only, and not for allocating the elements + which make up the parsed value. That other memory + resource is optionally supplied in each call + to @ref reset. + + @par Duplicate Keys + + If there are object elements with duplicate keys; + that is, if multiple elements in an object have + keys that compare equal, only the last equivalent + element will be inserted. + + @par Non-Standard JSON + + The @ref parse_options structure optionally + provided upon construction is used to customize + some parameters of the parser, including which + non-standard JSON extensions should be allowed. + A default-constructed parse options allows only + standard JSON. + + @par Thread Safety + + Distinct instances may be accessed concurrently. + Non-const member functions of a shared instance + may not be called concurrently with any other + member functions of that instance. + + @see + @ref parse, + @ref parse_options. +*/ +class parser +{ + basic_parser p_; + +public: + /// Copy constructor (deleted) + parser( + parser const&) = delete; + + /// Copy assignment (deleted) + parser& operator=( + parser const&) = delete; + + /** Destructor. + + All dynamically allocated memory, including + any incomplete parsing results, is freed. + + @par Complexity + Linear in the size of partial results + + @par Exception Safety + No-throw guarantee. + */ + ~parser() = default; + + /** Constructor. + + This constructs a new parser which first uses the + caller-owned storage pointed to by `temp_buffer` + for temporary storage, falling back to the memory + resource `sp` if needed. The parser will use the + specified parsing options. + \n + The parsed value will use the default memory resource + for storage. To use a different resource, call + @ref reset after construction. + + @par Complexity + Constant. + + @par Exception Safety + No-throw guarantee. + + @param sp The memory resource to use for temporary storage + when `buffer` is exhausted. + + @param opt The parsing options to use. + + @param buffer A pointer to valid memory of at least + `size` bytes for the parser to use for temporary storage. + Ownership is not transferred, the caller is responsible + for ensuring the lifetime of the memory pointed to by + `buffer` extends until the parser is destroyed. + + @param size The number of valid bytes in `buffer`. + */ + BOOST_JSON_DECL + parser( + storage_ptr sp, + parse_options const& opt, + unsigned char* buffer, + std::size_t size) noexcept; + + /** Constructor. + + This constructs a new parser which uses the default + memory resource for temporary storage, and accepts + only strict JSON. + \n + The parsed value will use the default memory resource + for storage. To use a different resource, call + @ref reset after construction. + + @par Complexity + Constant. + + @par Exception Safety + No-throw guarantee. + */ + parser() noexcept + : parser({}, {}) + { + } + + /** Constructor. + + This constructs a new parser which uses the specified + memory resource for temporary storage, and is + configured to use the specified parsing options. + \n + The parsed value will use the default memory resource + for storage. To use a different resource, call + @ref reset after construction. + + @par Complexity + Constant. + + @par Exception Safety + No-throw guarantee. + + @param sp The memory resource to use for temporary storage. + + @param opt The parsing options to use. + */ + BOOST_JSON_DECL + parser( + storage_ptr sp, + parse_options const& opt) noexcept; + + /** Constructor. + + This constructs a new parser which uses the specified + memory resource for temporary storage, and accepts + only strict JSON. + \n + The parsed value will use the default memory resource + for storage. To use a different resource, call + @ref reset after construction. + + @par Complexity + Constant. + + @par Exception Safety + No-throw guarantee. + + @param sp The memory resource to use for temporary storage. + */ + explicit + parser(storage_ptr sp) noexcept + : parser(std::move(sp), {}) + { + } + + /** Constructor. + + This constructs a new parser which first uses the + caller-owned storage `buffer` for temporary storage, + falling back to the memory resource `sp` if needed. + The parser will use the specified parsing options. + \n + The parsed value will use the default memory resource + for storage. To use a different resource, call + @ref reset after construction. + + @par Complexity + Constant. + + @par Exception Safety + No-throw guarantee. + + @param sp The memory resource to use for temporary storage + when `buffer` is exhausted. + + @param opt The parsing options to use. + + @param buffer A buffer for the parser to use for temporary + storage. Ownership is not transferred, the caller is + responsible for ensuring the lifetime of `buffer` extends + until the parser is destroyed. + */ + template + parser( + storage_ptr sp, + parse_options const& opt, + unsigned char(&buffer)[N]) noexcept + : parser(std::move(sp), + opt, &buffer[0], N) + { + } + +#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS) + /** Constructor (delegating) + + @par Effects + @code + parser( std::move(sp), opt, + reinterpret_cast( temp_buffer ), N ) + @endcode + */ + parser( + storage_ptr sp, + parse_options const& opt, + std::byte* temp_buffer, + std::size_t temp_size) noexcept + : parser(sp, opt, + reinterpret_cast( + temp_buffer), temp_size) + { + } + + /** Constructor (delegating) + + @par Effects + @code + parser( std::move(sp), opt, &buffer[0], N ) + @endcode + */ + template + parser( + storage_ptr sp, + parse_options const& opt, + std::byte(&buffer)[N]) noexcept + : parser(std::move(sp), + opt, &buffer[0], N) + { + } +#endif + +#ifndef BOOST_JSON_DOCS + // Safety net for accidental buffer overflows + template + parser( + storage_ptr sp, + parse_options const& opt, + unsigned char(&buffer)[N], + std::size_t n) noexcept + : parser(std::move(sp), + opt, &buffer[0], n) + { + // If this goes off, check your parameters + // closely, chances are you passed an array + // thinking it was a pointer. + BOOST_ASSERT(n <= N); + } + +#ifdef __cpp_lib_byte + // Safety net for accidental buffer overflows + template + parser( + storage_ptr sp, + parse_options const& opt, + std::byte(&buffer)[N], std::size_t n) noexcept + : parser(std::move(sp), + opt, &buffer[0], n) + { + // If this goes off, check your parameters + // closely, chances are you passed an array + // thinking it was a pointer. + BOOST_ASSERT(n <= N); + } +#endif +#endif + + /** Returns the current depth of the JSON being parsed. + + The parsing depth is the total current nesting + level of arrays and objects. + + @par Complexity + + Constant. + + @par Exception Safety + + No-throw guarantee. + */ + std::size_t + depth() const noexcept + { + return p_.depth(); + } + + /** Start parsing JSON incrementally. + + This function is used to reset the parser to + prepare it for parsing a new JSON. Any previous + partial results are destroyed. + + @par Complexity + Constant or linear in the size of any previous + partial parsing results. + + @par Exception Safety + No-throw guarantee. + + @param sp A pointer to the @ref memory_resource + to use for the resulting @ref value. The parser + will acquire shared ownership. + */ + BOOST_JSON_DECL + void + reset(storage_ptr sp = {}) noexcept; + + /** Parse some of an input string as JSON, incrementally. + + This function parses the JSON in the specified + buffer. The parse proceeds from the current + state, which is at the beginning of a new JSON + or in the middle of the current JSON if any + characters were already parsed. + \n + The characters in the buffer are processed + starting from the beginning, until one of the + following conditions is met: + + @li All of the characters in the buffer have + been parsed, or + + @li A complete JSON is parsed, including any + optional trailing whitespace in the buffer, or + + @li A parsing error occurs. + + If a complete JSON is parsed, the function will + return the number of characters actually used + which may be less than the size of the input. + \n + The supplied buffer does not need to contain the + entire JSON. Subsequent calls can provide more + serialized data, allowing JSON to be processed + incrementally. The end of the serialized JSON + is be indicated by calling @ref finish. + + @par Complexity + Linear in `size`. + + @par Exception Safety + Basic guarantee. + Calls to `memory_resource::allocate` may throw. + Upon error, the only valid operations are + @ref reset and destruction. + + @return The number of characters consumed from + the buffer. + + @param data A pointer to a buffer of `size` + characters to parse. + + @param size The number of characters pointed to + by `data`. + + @param ec Set to the error, if any occurred. + */ + BOOST_JSON_DECL + std::size_t + write_some( + char const* data, + std::size_t size, + error_code& ec); + + /** Parse some of an input string as JSON, incrementally. + + This function parses the JSON in the specified + buffer. The parse proceeds from the current + state, which is at the beginning of a new JSON + or in the middle of the current JSON if any + characters were already parsed. + \n + The characters in the buffer are processed + starting from the beginning, until one of the + following conditions is met: + + @li All of the characters in the buffer have + been parsed, or + + @li A complete JSON is parsed, including any + optional trailing whitespace in the buffer, or + + @li A parsing error occurs. + + If a complete JSON is parsed, the function will + return the number of characters actually used + which may be less than the size of the input. + \n + The supplied buffer does not need to contain the + entire JSON. Subsequent calls can provide more + serialized data, allowing JSON to be processed + incrementally. The end of the serialized JSON + is be indicated by calling @ref finish. + + @par Complexity + Linear in `size`. + + @par Exception Safety + Basic guarantee. + Calls to `memory_resource::allocate` may throw. + Upon error, the only valid operations are + @ref reset and destruction. + + @return The number of characters consumed from + the buffer. + + @param data A pointer to a buffer of `size` + characters to parse. + + @param size The number of characters pointed to + by `data`. + + @throw system_error Thrown on error. + */ + BOOST_JSON_DECL + std::size_t + write_some( + char const* data, + std::size_t size); + + /** Parse some of an input string as JSON, incrementally. + + This function parses the JSON in the specified + buffer. The parse proceeds from the current + state, which is at the beginning of a new JSON + or in the middle of the current JSON if any + characters were already parsed. + \n + The characters in the buffer are processed + starting from the beginning, until one of the + following conditions is met: + + @li All of the characters in the buffer have + been parsed, or + + @li A complete JSON is parsed, including any + optional trailing whitespace in the buffer, or + + @li A parsing error occurs. + + If a complete JSON is parsed, the function will + return the number of characters actually used + which may be less than the size of the input. + \n + The supplied buffer does not need to contain the + entire JSON. Subsequent calls can provide more + serialized data, allowing JSON to be processed + incrementally. The end of the serialized JSON + is be indicated by calling @ref finish. + + @par Complexity + Linear in `size`. + + @par Exception Safety + Basic guarantee. + Calls to `memory_resource::allocate` may throw. + Upon error, the only valid operations are + @ref reset and destruction. + + @return The number of characters consumed from + the buffer. + + @param s The character string to parse. + + @param ec Set to the error, if any occurred. + */ + std::size_t + write_some( + string_view s, + error_code& ec) + { + return write_some( + s.data(), s.size(), ec); + } + + /** Parse some of an input string as JSON, incrementally. + + This function parses the JSON in the specified + buffer. The parse proceeds from the current + state, which is at the beginning of a new JSON + or in the middle of the current JSON if any + characters were already parsed. + \n + The characters in the buffer are processed + starting from the beginning, until one of the + following conditions is met: + + @li All of the characters in the buffer have + been parsed, or + + @li A complete JSON is parsed, including any + optional trailing whitespace in the buffer, or + + @li A parsing error occurs. + + If a complete JSON is parsed, the function will + return the number of characters actually used + which may be less than the size of the input. + \n + The supplied buffer does not need to contain the + entire JSON. Subsequent calls can provide more + serialized data, allowing JSON to be processed + incrementally. The end of the serialized JSON + is be indicated by calling @ref finish. + + @par Complexity + Linear in `size`. + + @par Exception Safety + Basic guarantee. + Calls to `memory_resource::allocate` may throw. + Upon error, the only valid operations are + @ref reset and destruction. + + @return The number of characters consumed from + the buffer. + + @param s The character string to parse. + + @throw system_error Thrown on error. + */ + std::size_t + write_some( + string_view s) + { + return write_some( + s.data(), s.size()); + } + + /** Parse all of an input string as JSON, incrementally. + + This function parses the JSON in the specified + buffer. The parse proceeds from the current + state, which is at the beginning of a new JSON + or in the middle of the current JSON if any + characters were already parsed. + \n + The characters in the buffer are processed + starting from the beginning, until one of the + following conditions is met: + + @li All of the characters in the buffer have + been parsed, or + + @li A complete JSON is parsed, including any + optional trailing whitespace in the buffer, or + + @li A parsing error occurs. + + If a complete JSON is parsed, but not all + characters in the buffer were consumed, an + error occurs. + \n + The supplied buffer does not need to contain the + entire JSON. Subsequent calls can provide more + serialized data, allowing JSON to be processed + incrementally. The end of the serialized JSON + is be indicated by calling @ref finish. + + @par Complexity + Linear in `size`. + + @par Exception Safety + Basic guarantee. + Calls to `memory_resource::allocate` may throw. + Upon error, the only valid operations are + @ref reset and destruction. + + @return The number of characters consumed from + the buffer. + + @param data A pointer to a buffer of `size` + characters to parse. + + @param size The number of characters pointed to + by `data`. + + @param ec Set to the error, if any occurred. + */ + BOOST_JSON_DECL + std::size_t + write( + char const* data, + std::size_t size, + error_code& ec); + + /** Parse all of an input string as JSON, incrementally. + + This function parses the JSON in the specified + buffer. The parse proceeds from the current + state, which is at the beginning of a new JSON + or in the middle of the current JSON if any + characters were already parsed. + \n + The characters in the buffer are processed + starting from the beginning, until one of the + following conditions is met: + + @li All of the characters in the buffer have + been parsed, or + + @li A complete JSON is parsed, including any + optional trailing whitespace in the buffer, or + + @li A parsing error occurs. + + If a complete JSON is parsed, but not all + characters in the buffer were consumed, an + error occurs. + \n + The supplied buffer does not need to contain the + entire JSON. Subsequent calls can provide more + serialized data, allowing JSON to be processed + incrementally. The end of the serialized JSON + is be indicated by calling @ref finish. + + @par Complexity + Linear in `size`. + + @par Exception Safety + Basic guarantee. + Calls to `memory_resource::allocate` may throw. + Upon error, the only valid operations are + @ref reset and destruction. + + @return The number of characters consumed from + the buffer. + + @param data A pointer to a buffer of `size` + characters to parse. + + @param size The number of characters pointed to + by `data`. + + @throw system_error Thrown on error. + */ + BOOST_JSON_DECL + std::size_t + write( + char const* data, + std::size_t size); + + /** Parse all of an input string as JSON, incrementally. + + This function parses the JSON in the specified + buffer. The parse proceeds from the current + state, which is at the beginning of a new JSON + or in the middle of the current JSON if any + characters were already parsed. + \n + The characters in the buffer are processed + starting from the beginning, until one of the + following conditions is met: + + @li All of the characters in the buffer have + been parsed, or + + @li A complete JSON is parsed, including any + optional trailing whitespace in the buffer, or + + @li A parsing error occurs. + + If a complete JSON is parsed, but not all + characters in the buffer were consumed, an + error occurs. + \n + The supplied buffer does not need to contain the + entire JSON. Subsequent calls can provide more + serialized data, allowing JSON to be processed + incrementally. The end of the serialized JSON + is be indicated by calling @ref finish. + + @par Complexity + Linear in `size`. + + @par Exception Safety + Basic guarantee. + Calls to `memory_resource::allocate` may throw. + Upon error, the only valid operations are + @ref reset and destruction. + + @return The number of characters consumed from + the buffer. + + @param s The character string to parse. + + @param ec Set to the error, if any occurred. + */ + std::size_t + write( + string_view s, + error_code& ec) + { + return write( + s.data(), s.size(), ec); + } + + /** Parse all of an input string as JSON, incrementally. + + This function parses the JSON in the specified + buffer. The parse proceeds from the current + state, which is at the beginning of a new JSON + or in the middle of the current JSON if any + characters were already parsed. + \n + The characters in the buffer are processed + starting from the beginning, until one of the + following conditions is met: + + @li All of the characters in the buffer have + been parsed, or + + @li A complete JSON is parsed, including any + optional trailing whitespace in the buffer, or + + @li A parsing error occurs. + + If a complete JSON is parsed, but not all + characters in the buffer were consumed, an + error occurs. + \n + The supplied buffer does not need to contain the + entire JSON. Subsequent calls can provide more + serialized data, allowing JSON to be processed + incrementally. The end of the serialized JSON + is be indicated by calling @ref finish. + + @par Complexity + Linear in `size`. + + @par Exception Safety + Basic guarantee. + Calls to `memory_resource::allocate` may throw. + Upon error, the only valid operations are + @ref reset and destruction. + + @return The number of characters consumed from + the buffer. + + @param s The character string to parse. + + @throw system_error Thrown on error. + */ + std::size_t + write( + string_view s) + { + return write( + s.data(), s.size()); + } + + /** Return the parsed JSON as a @ref value. + + This returns the parsed value, or throws + an exception if the parsing is incomplete or + failed. It is necessary to call @ref reset + after calling this function in order to parse + another JSON. + + @par Effects + @code + if( ! this->done() ) + this->finish(); + @endcode + @note + + @par Complexity + Constant. + + @par Exception Safety + Basic guarantee. + Calls to `memory_resource::allocate` may throw. + Upon error, the only valid operations are + @ref reset and destruction. + + @return The parsed value. Ownership of this + value is transferred to the caller. + + @throw system_error Thrown on failure. + */ + BOOST_JSON_DECL + value + release(); +}; + +BOOST_JSON_NS_END + +#endif diff --git a/include/boost/json/src.hpp b/include/boost/json/src.hpp index 3abc2502..a6153160 100644 --- a/include/boost/json/src.hpp +++ b/include/boost/json/src.hpp @@ -35,6 +35,7 @@ in a translation unit of the program. #include #include #include +#include #include #include #include diff --git a/test/parser.cpp b/test/parser.cpp new file mode 100644 index 00000000..25c86031 --- /dev/null +++ b/test/parser.cpp @@ -0,0 +1,28 @@ +// +// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/cppalliance/json +// + +// Test that header file is self-contained. +#include + +#include "test_suite.hpp" + +BOOST_JSON_NS_BEGIN + +class parser_test +{ +public: + void + run() + { + } +}; + +TEST_SUITE(parser_test, "boost.json.parser"); + +BOOST_JSON_NS_END