mirror of
https://github.com/boostorg/json.git
synced 2025-05-11 13:44:06 +00:00
Refactor parser interface
This commit is contained in:
parent
8f1348ed40
commit
19ebd6c943
@ -256,6 +256,8 @@ public:
|
||||
error_code ec;
|
||||
vec_parser p;
|
||||
p.write(s.data(), s.size(), ec);
|
||||
if(! ec)
|
||||
p.finish(ec);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@ PREDEFINED = \
|
||||
BOOST_JSON_DECL \
|
||||
BOOST_JSON_PUBLIC \
|
||||
BOOST_JSON_FORCEINLINE \
|
||||
"BOOST_JSON_NODISCARD=[[nodiscard]]" \
|
||||
"BOOST_JSON_INLINE_VARIABLE(v, t)=constexpr t v;"
|
||||
|
||||
EXPAND_AS_DEFINED =
|
||||
|
@ -18,6 +18,45 @@
|
||||
|
||||
namespace json = boost::json;
|
||||
|
||||
class file
|
||||
{
|
||||
FILE* f_ = nullptr;
|
||||
|
||||
public:
|
||||
~file()
|
||||
{
|
||||
if(f_)
|
||||
std::fclose(f_);
|
||||
}
|
||||
|
||||
file() = default;
|
||||
|
||||
void
|
||||
close()
|
||||
{
|
||||
if(f_)
|
||||
{
|
||||
std::fclose(f_);
|
||||
f_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
open(
|
||||
char const* path,
|
||||
char const* mode,
|
||||
json::error_code& ec)
|
||||
{
|
||||
close();
|
||||
f_ = std::fopen( path, mode );
|
||||
if( ! f_ )
|
||||
{
|
||||
ec.assign( errno, json::generic_category() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
json::value
|
||||
parse_file( char const* filename )
|
||||
{
|
||||
@ -54,7 +93,7 @@ parse_file( char const* filename )
|
||||
while( ! std::feof(f) );
|
||||
|
||||
// Tell the parser there is no more serialized JSON.
|
||||
p.write_eof(ec);
|
||||
p.finish(ec);
|
||||
if( ec )
|
||||
throw json::system_error(ec);
|
||||
|
||||
|
@ -573,7 +573,7 @@ public:
|
||||
|
||||
@param pos A zero-based index.
|
||||
|
||||
@throws std::out_of_range `pos >= size()`
|
||||
@throw std::out_of_range `pos >= size()`
|
||||
*/
|
||||
inline
|
||||
reference
|
||||
@ -592,7 +592,7 @@ public:
|
||||
|
||||
@param pos A zero-based index.
|
||||
|
||||
@throws std::out_of_range `pos >= size()`
|
||||
@throw std::out_of_range `pos >= size()`
|
||||
*/
|
||||
inline
|
||||
const_reference
|
||||
|
@ -21,21 +21,30 @@
|
||||
namespace boost {
|
||||
namespace json {
|
||||
|
||||
/** A SAX parser for serialized JSON.
|
||||
/** An incremental SAX parser for serialized JSON.
|
||||
|
||||
This implements a SAX-style parser. The serialized
|
||||
JSON is presented to the parser by calling to
|
||||
@ref write_some, @ref write, and @ref write_eof.
|
||||
@ref write_some, @ref write, and @ref finish.
|
||||
The parsing events are realized through calls of
|
||||
protected virtual functions, whose implementations
|
||||
are in the derived class.
|
||||
|
||||
<br>
|
||||
|
||||
The parser may dynamically allocate intermediate
|
||||
storage as needed to accommodate the nesting level
|
||||
of the JSON being parsed. This storage is freed
|
||||
when the parser is destroyed, allowing the parser
|
||||
to cheaply re-use this memory when parsing
|
||||
subsequent JSONs, improving performance.
|
||||
|
||||
@note
|
||||
|
||||
The parser is strict: no extensions are supported.
|
||||
Only compliant JSON is recognized.
|
||||
|
||||
@see parser
|
||||
@see parse, parser
|
||||
*/
|
||||
class basic_parser
|
||||
{
|
||||
@ -64,7 +73,7 @@ public:
|
||||
|
||||
/** Destructor.
|
||||
|
||||
All internal memory is freed.
|
||||
All dynamically allocated internal memory is freed.
|
||||
*/
|
||||
virtual
|
||||
~basic_parser()
|
||||
@ -132,8 +141,36 @@ public:
|
||||
|
||||
/** Parse JSON incrementally.
|
||||
|
||||
This function presents the next buffer of serialized
|
||||
JSON as input into the parser.
|
||||
This function parses the JSON in the specified
|
||||
buffer, emitting SAX parsing events by calling
|
||||
the derived class. 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.
|
||||
|
||||
<br>
|
||||
|
||||
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 Some of the characters in the buffer have been
|
||||
parsed and the JSON is complete, or
|
||||
|
||||
@li A parsing error occurs.
|
||||
|
||||
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
|
||||
can be indicated by calling @ref finish().
|
||||
|
||||
@par Complexity
|
||||
|
||||
Linear in `size`.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
@ -144,7 +181,7 @@ public:
|
||||
@param ec Set to the error, if any occurred.
|
||||
|
||||
@return The number of characters successfully
|
||||
parsed.
|
||||
parsed, which may be smaller than `size`.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
@ -153,19 +190,85 @@ public:
|
||||
std::size_t size,
|
||||
error_code& ec);
|
||||
|
||||
/** Parse JSON incrementally.
|
||||
|
||||
This function parses the JSON in the specified
|
||||
buffer, emitting SAX parsing events by calling
|
||||
the derived class. 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.
|
||||
|
||||
<br>
|
||||
|
||||
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 Some of the characters in the buffer have been
|
||||
parsed and the JSON is complete, or
|
||||
|
||||
@li A parsing error occurs.
|
||||
|
||||
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
|
||||
can be indicated by calling @ref finish().
|
||||
|
||||
@par Complexity
|
||||
|
||||
Linear in `size`.
|
||||
|
||||
@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 failure.
|
||||
|
||||
@return The number of characters successfully
|
||||
parsed, which may be smaller than `size`.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size);
|
||||
|
||||
/** Parse the remaining JSON immediately.
|
||||
/** Parse JSON incrementally.
|
||||
|
||||
This function is used to submit the last buffer,
|
||||
or the only buffer, of serialized JSON as input into
|
||||
the parser. An error occurs if all of the characters
|
||||
could not be successfully parsed, even if a complete
|
||||
JSON object is encountered.
|
||||
This function parses the JSON in the specified
|
||||
buffer, emitting SAX parsing events by calling
|
||||
the derived class. 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.
|
||||
|
||||
<br>
|
||||
|
||||
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 parsing error occurs.
|
||||
|
||||
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
|
||||
can be indicated by calling @ref finish().
|
||||
|
||||
@par Complexity
|
||||
|
||||
Linear in `size`.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
@ -182,28 +285,190 @@ public:
|
||||
std::size_t size,
|
||||
error_code& ec);
|
||||
|
||||
/** Parse JSON incrementally.
|
||||
|
||||
This function parses the JSON in the specified
|
||||
buffer, emitting SAX parsing events by calling
|
||||
the derived class. 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.
|
||||
|
||||
<br>
|
||||
|
||||
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 parsing error occurs.
|
||||
|
||||
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
|
||||
can be indicated by calling @ref finish().
|
||||
|
||||
@par Complexity
|
||||
|
||||
Linear in `size`.
|
||||
|
||||
@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 failure.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size);
|
||||
|
||||
/** Indicate that no more serialized JSON remains.
|
||||
/** Parse JSON incrementally.
|
||||
|
||||
This function informs the parser that there is
|
||||
are no more characters left in the serialized
|
||||
JSON being parsed. If no error occurs, the parse
|
||||
is complete and @ref is_done will return `true`.
|
||||
Otherwise, the error is set to the problem
|
||||
encountered.
|
||||
This function parses the JSON in the specified
|
||||
buffer, emitting SAX parsing events by calling
|
||||
the derived class. 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.
|
||||
|
||||
<br>
|
||||
|
||||
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 and form a complete JSON, or
|
||||
|
||||
@li A parsing error occurs.
|
||||
|
||||
The caller uses this function to inform the
|
||||
parser that there is no more serialized JSON
|
||||
available. If the entire buffer is not consumed
|
||||
or if a complete JSON is not available after
|
||||
consuming the entire buffer, the error is
|
||||
set to indicate failure.
|
||||
|
||||
@par Complexity
|
||||
|
||||
Linear in `size`.
|
||||
|
||||
@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
|
||||
void
|
||||
write_eof(error_code& ec);
|
||||
finish(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec);
|
||||
|
||||
/** Parse JSON incrementally.
|
||||
|
||||
This function parses the JSON in the specified
|
||||
buffer, emitting SAX parsing events by calling
|
||||
the derived class. 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.
|
||||
|
||||
<br>
|
||||
|
||||
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 and form a complete JSON, or
|
||||
|
||||
@li A parsing error occurs.
|
||||
|
||||
The caller uses this function to inform the
|
||||
parser that there is no more serialized JSON
|
||||
available. If the entire buffer is not consumed
|
||||
or if a complete JSON is not available after
|
||||
consuming the entire buffer, the error is
|
||||
set to indicate failure.
|
||||
|
||||
@par Complexity
|
||||
|
||||
Linear in `size`.
|
||||
|
||||
@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 failure.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
write_eof();
|
||||
finish(
|
||||
char const* data,
|
||||
std::size_t size);
|
||||
|
||||
/** Parse JSON incrementally.
|
||||
|
||||
This function finishes parsing the current JSON,
|
||||
emitting SAX parsing events by calling the derived
|
||||
class. The parse is finalized according to the
|
||||
current state, which includes all previously
|
||||
parsed data since the last reset.
|
||||
|
||||
<br>
|
||||
|
||||
The caller uses this function to inform the
|
||||
parser that there is no more serialized JSON
|
||||
available. If a complete JSON is not available
|
||||
the error is set to indicate failure.
|
||||
|
||||
@par Complexity
|
||||
|
||||
Constant.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
finish(error_code& ec);
|
||||
|
||||
/** Parse JSON incrementally.
|
||||
|
||||
This function finishes parsing the current JSON,
|
||||
emitting SAX parsing events by calling the derived
|
||||
class. The parse is finalized according to the
|
||||
current state, which includes all previously
|
||||
parsed data since the last reset.
|
||||
|
||||
<br>
|
||||
|
||||
The caller uses this function to inform the
|
||||
parser that there is no more serialized JSON
|
||||
available. If a complete JSON is not available
|
||||
the error is set to indicate failure.
|
||||
|
||||
@par Complexity
|
||||
|
||||
Constant.
|
||||
|
||||
@throw system_error Thrown on failure.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
finish();
|
||||
|
||||
protected:
|
||||
using saved_state = char;
|
||||
@ -244,7 +509,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -260,7 +525,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -274,7 +539,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -289,7 +554,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -303,7 +568,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -318,7 +583,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -339,7 +604,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -360,7 +625,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -382,7 +647,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -403,7 +668,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -420,7 +685,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -437,7 +702,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -454,7 +719,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -471,7 +736,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
@ -483,7 +748,7 @@ protected:
|
||||
|
||||
@param ec The error, if any, which will be
|
||||
returned by the current invocation of
|
||||
@ref write_some, @ref write, or @ref write_eof.
|
||||
@ref write_some, @ref write, or @ref finish.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
|
@ -54,6 +54,19 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// VFALCO Copied from <boost/config.hpp>
|
||||
// This is a derivative work.
|
||||
#ifdef __has_cpp_attribute
|
||||
// clang-6 accepts [[nodiscard]] with -std=c++14, but warns about it -pedantic
|
||||
# if __has_cpp_attribute(nodiscard) && !(defined(__clang__) && (__cplusplus < 201703L))
|
||||
# define BOOST_JSON_NODISCARD [[nodiscard]]
|
||||
# else
|
||||
# define BOOST_JSON_NODISCARD
|
||||
# endif
|
||||
#else
|
||||
# define BOOST_JSON_NODISCARD
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_FORCEINLINE
|
||||
# ifdef _MSC_VER
|
||||
# define BOOST_JSON_FORCEINLINE __forceinline
|
||||
|
@ -98,7 +98,7 @@ public:
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
write_eof(
|
||||
finish(
|
||||
error_code& ec) noexcept;
|
||||
};
|
||||
|
||||
|
@ -260,7 +260,7 @@ loop:
|
||||
st_ = state::exp1;
|
||||
goto loop;
|
||||
}
|
||||
write_eof(ec);
|
||||
finish(ec);
|
||||
goto finish;
|
||||
}
|
||||
while(p < p1);
|
||||
@ -346,7 +346,7 @@ loop:
|
||||
if(static_cast<unsigned char>(
|
||||
*p - '0') > 9)
|
||||
{
|
||||
write_eof(ec);
|
||||
finish(ec);
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
@ -406,7 +406,7 @@ loop:
|
||||
if(*p != 'e' && *p != 'E')
|
||||
{
|
||||
n_.u = m;
|
||||
write_eof(ec);
|
||||
finish(ec);
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
@ -445,7 +445,7 @@ loop:
|
||||
if(*p != 'e' && *p != 'E')
|
||||
{
|
||||
n_.d = m;
|
||||
write_eof(ec);
|
||||
finish(ec);
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
@ -522,7 +522,7 @@ loop:
|
||||
continue;
|
||||
}
|
||||
exp_ = e;
|
||||
write_eof(ec);
|
||||
finish(ec);
|
||||
goto finish;
|
||||
}
|
||||
while(p < p1);
|
||||
@ -532,7 +532,7 @@ loop:
|
||||
}
|
||||
|
||||
case state::end:
|
||||
ec = error::illegal_extra_chars;
|
||||
ec = error::extra_data;
|
||||
break;
|
||||
}
|
||||
finish:
|
||||
@ -557,13 +557,13 @@ write(
|
||||
if(ec)
|
||||
return n;
|
||||
}
|
||||
write_eof(ec);
|
||||
finish(ec);
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
number_parser::
|
||||
write_eof(
|
||||
finish(
|
||||
error_code& ec) noexcept
|
||||
{
|
||||
switch(st_)
|
||||
|
@ -26,6 +26,9 @@ enum class error
|
||||
/// extra data
|
||||
extra_data,
|
||||
|
||||
/// incomplete data
|
||||
incomplete,
|
||||
|
||||
/// mantissa overflow
|
||||
mantissa_overflow,
|
||||
|
||||
@ -47,9 +50,6 @@ enum class error
|
||||
/// illegal extra digits in number
|
||||
illegal_extra_digits,
|
||||
|
||||
/// illegal extra characters
|
||||
illegal_extra_chars,
|
||||
|
||||
/// illegal leading surrogate
|
||||
illegal_leading_surrogate,
|
||||
|
||||
|
@ -169,13 +169,13 @@ loop:
|
||||
goto loop_val;
|
||||
|
||||
case state::end:
|
||||
ec = error::illegal_extra_chars;
|
||||
ec = error::extra_data;
|
||||
goto yield;
|
||||
|
||||
case state::maybe_end:
|
||||
if(! skip_white())
|
||||
goto yield;
|
||||
write_eof(ec);
|
||||
finish(ec);
|
||||
goto yield;
|
||||
|
||||
//------------------------------------------------------
|
||||
@ -799,7 +799,7 @@ loop_num:
|
||||
// is_done inside write_some better
|
||||
if(p < p1)
|
||||
{
|
||||
iep_.write_eof(ec);
|
||||
iep_.finish(ec);
|
||||
if(ec)
|
||||
goto yield;
|
||||
BOOST_JSON_ASSERT(iep_.is_done());
|
||||
@ -884,8 +884,7 @@ write(
|
||||
if(! ec)
|
||||
{
|
||||
if(n < size)
|
||||
write_some(
|
||||
data + n, size - n, ec);
|
||||
ec = error::extra_data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -906,7 +905,34 @@ write(
|
||||
|
||||
void
|
||||
basic_parser::
|
||||
write_eof(error_code& ec)
|
||||
finish(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
write(data, size, ec);
|
||||
if(! ec)
|
||||
finish(ec);
|
||||
}
|
||||
|
||||
void
|
||||
basic_parser::
|
||||
finish(
|
||||
char const* data,
|
||||
std::size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
finish(data, size, ec);
|
||||
if(ec)
|
||||
BOOST_JSON_THROW(
|
||||
system_error(ec));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
basic_parser::
|
||||
finish(error_code& ec)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
@ -931,7 +957,7 @@ write_eof(error_code& ec)
|
||||
|
||||
case state::num:
|
||||
{
|
||||
iep_.write_eof(ec);
|
||||
iep_.finish(ec);
|
||||
if(ec)
|
||||
return;
|
||||
auto const num = iep_.get();
|
||||
@ -976,7 +1002,7 @@ write_eof(error_code& ec)
|
||||
case state::sur2:
|
||||
case state::sur3:
|
||||
case state::sur1:
|
||||
ec = error::syntax;
|
||||
ec = error::incomplete;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -984,10 +1010,10 @@ write_eof(error_code& ec)
|
||||
|
||||
void
|
||||
basic_parser::
|
||||
write_eof()
|
||||
finish()
|
||||
{
|
||||
error_code ec;
|
||||
write_eof(ec);
|
||||
finish(ec);
|
||||
if(ec)
|
||||
BOOST_JSON_THROW(
|
||||
system_error(ec));
|
||||
|
@ -34,6 +34,7 @@ make_error_code(error e)
|
||||
default:
|
||||
case error::syntax: return "syntax error";
|
||||
case error::extra_data: return "extra data";
|
||||
case error::incomplete: return "incomplete";
|
||||
case error::mantissa_overflow: return "mantissa overflow";
|
||||
case error::exponent_overflow: return "exponent overflow";
|
||||
case error::too_deep: return "too deep";
|
||||
@ -41,7 +42,6 @@ make_error_code(error e)
|
||||
case error::illegal_control_char: return "illegal control character";
|
||||
case error::illegal_escape_char: return "illegal character in escape sequence";
|
||||
case error::illegal_extra_digits: return "illegal extra digits in number";
|
||||
case error::illegal_extra_chars: return "illegal extra characters";
|
||||
case error::illegal_leading_surrogate: return "illegal leading surrogate";
|
||||
case error::illegal_trailing_surrogate: return "illegal trailing surrogate";
|
||||
case error::need_start: return "parser needs start";
|
||||
@ -91,7 +91,6 @@ make_error_code(error e)
|
||||
case error::illegal_control_char:
|
||||
case error::illegal_escape_char:
|
||||
case error::illegal_extra_digits:
|
||||
case error::illegal_extra_chars:
|
||||
case error::illegal_leading_surrogate:
|
||||
case error::illegal_trailing_surrogate:
|
||||
|
||||
|
@ -59,7 +59,7 @@ enum class parser::state : char
|
||||
arr, // empty array value
|
||||
obj, // empty object value
|
||||
key, // complete key
|
||||
end // compelte top value
|
||||
end // complete top value
|
||||
};
|
||||
|
||||
void
|
||||
@ -182,62 +182,27 @@ clear() noexcept
|
||||
|
||||
value
|
||||
parser::
|
||||
release() noexcept
|
||||
release()
|
||||
{
|
||||
if(is_done())
|
||||
{
|
||||
BOOST_JSON_ASSERT(lev_.st == state::end);
|
||||
auto ua = pop_array();
|
||||
BOOST_JSON_ASSERT(rs_.empty());
|
||||
union U
|
||||
{
|
||||
value v;
|
||||
U(){}
|
||||
~U(){}
|
||||
};
|
||||
U u;
|
||||
ua.relocate(&u.v);
|
||||
basic_parser::reset();
|
||||
lev_.st = state::need_start;
|
||||
sp_ = {};
|
||||
return pilfer(u.v);
|
||||
}
|
||||
// return null
|
||||
value jv(std::move(sp_));
|
||||
clear();
|
||||
return jv;
|
||||
}
|
||||
|
||||
value
|
||||
parser::
|
||||
parse(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec,
|
||||
storage_ptr sp)
|
||||
{
|
||||
start(std::move(sp));
|
||||
write(data, size, ec);
|
||||
if(! ec)
|
||||
write_eof(ec);
|
||||
return release();
|
||||
}
|
||||
|
||||
value
|
||||
parser::
|
||||
parse(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
storage_ptr sp)
|
||||
{
|
||||
error_code ec;
|
||||
auto jv = parse(
|
||||
data, size, ec,
|
||||
std::move(sp));
|
||||
if(ec)
|
||||
if(! is_done())
|
||||
BOOST_JSON_THROW(
|
||||
system_error(ec));
|
||||
return release();
|
||||
std::logic_error(
|
||||
"no value"));
|
||||
BOOST_JSON_ASSERT(lev_.st == state::end);
|
||||
auto ua = pop_array();
|
||||
BOOST_JSON_ASSERT(rs_.empty());
|
||||
union U
|
||||
{
|
||||
value v;
|
||||
U(){}
|
||||
~U(){}
|
||||
};
|
||||
U u;
|
||||
ua.relocate(&u.v);
|
||||
basic_parser::reset();
|
||||
lev_.st = state::need_start;
|
||||
sp_ = {};
|
||||
return pilfer(u.v);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
@ -291,10 +256,19 @@ emplace(Args&&... args)
|
||||
key, std::forward<Args>(args)...);
|
||||
rs_.add(sizeof(u.v));
|
||||
}
|
||||
else if(lev_.st == state::arr)
|
||||
{
|
||||
// prevent splits from exceptions
|
||||
rs_.prepare(sizeof(value));
|
||||
BOOST_JSON_ASSERT((rs_.top() %
|
||||
alignof(value)) == 0);
|
||||
::new(rs_.behind(sizeof(value))) value(
|
||||
std::forward<Args>(args)...);
|
||||
rs_.add(sizeof(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_JSON_ASSERT(
|
||||
lev_.st == state::arr ||
|
||||
lev_.st == state::top);
|
||||
// prevent splits from exceptions
|
||||
rs_.prepare(sizeof(value));
|
||||
@ -303,6 +277,7 @@ emplace(Args&&... args)
|
||||
::new(rs_.behind(sizeof(value))) value(
|
||||
std::forward<Args>(args)...);
|
||||
rs_.add(sizeof(value));
|
||||
lev_.st = state::end; // VFALCO Maybe pre_end
|
||||
}
|
||||
++lev_.count;
|
||||
}
|
||||
@ -384,7 +359,6 @@ parser::
|
||||
on_document_end(error_code&)
|
||||
{
|
||||
BOOST_JSON_ASSERT(lev_.count == 1);
|
||||
lev_.st = state::end; // VFALCO RECONSIDER
|
||||
}
|
||||
|
||||
void
|
||||
@ -574,12 +548,17 @@ on_null(error_code&)
|
||||
value
|
||||
parse(
|
||||
string_view s,
|
||||
storage_ptr sp,
|
||||
error_code& ec)
|
||||
error_code& ec,
|
||||
storage_ptr sp)
|
||||
{
|
||||
parser p;
|
||||
p.start(std::move(sp));
|
||||
p.write(s.data(), s.size(), ec);
|
||||
p.finish(
|
||||
s.data(),
|
||||
s.size(),
|
||||
ec);
|
||||
if(ec)
|
||||
return nullptr;
|
||||
return p.release();
|
||||
}
|
||||
|
||||
@ -589,7 +568,8 @@ parse(
|
||||
storage_ptr sp)
|
||||
{
|
||||
error_code ec;
|
||||
auto jv = parse(s, std::move(sp), ec);
|
||||
auto jv = parse(
|
||||
s, ec, std::move(sp));
|
||||
if(ec)
|
||||
BOOST_JSON_THROW(
|
||||
system_error(ec));
|
||||
|
@ -33,8 +33,7 @@ struct value::undo
|
||||
undo(value* self_) noexcept
|
||||
: self(self_)
|
||||
{
|
||||
std::memcpy(&saved, self,
|
||||
sizeof(*self));
|
||||
relocate(&saved, *self_);
|
||||
}
|
||||
|
||||
void
|
||||
@ -47,9 +46,7 @@ struct value::undo
|
||||
~undo()
|
||||
{
|
||||
if(self)
|
||||
std::memcpy(
|
||||
self, &saved,
|
||||
sizeof(*self));
|
||||
relocate(self, saved);
|
||||
}
|
||||
};
|
||||
|
||||
@ -164,6 +161,19 @@ operator=(T&& t)
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
value::
|
||||
relocate(
|
||||
value* dest,
|
||||
value const& src) noexcept
|
||||
{
|
||||
std::memcpy(
|
||||
reinterpret_cast<
|
||||
void*>(dest),
|
||||
&src,
|
||||
sizeof(src));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class... Args>
|
||||
|
@ -122,8 +122,7 @@ value::
|
||||
value::
|
||||
value(pilfered<value> p) noexcept
|
||||
{
|
||||
std::memcpy(this,
|
||||
&p.get(), sizeof(*this));
|
||||
relocate(this, p.get());
|
||||
::new(&p.get().nul_) null_k;
|
||||
}
|
||||
|
||||
@ -186,8 +185,7 @@ value(
|
||||
value::
|
||||
value(value&& other) noexcept
|
||||
{
|
||||
std::memcpy(
|
||||
this, &other, sizeof(*this));
|
||||
relocate(this, other);
|
||||
::new(&other.nul_) null_k(sp_);
|
||||
}
|
||||
|
||||
@ -394,12 +392,9 @@ swap(value& other)
|
||||
~U(){}
|
||||
};
|
||||
U u;
|
||||
std::memcpy(&u.tmp,
|
||||
this, sizeof(*this));
|
||||
std::memcpy(this,
|
||||
&other, sizeof(other));
|
||||
std::memcpy(&other,
|
||||
&u.tmp, sizeof(u.tmp));
|
||||
relocate(&u.tmp, *this);
|
||||
relocate(this, other);
|
||||
relocate(&other, u.tmp);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
@ -901,14 +901,14 @@ public:
|
||||
|
||||
@param p The value to insert.
|
||||
|
||||
@returns A pair where `first` is an iterator
|
||||
to the existing or inserted element, and `second`
|
||||
is `true` if the insertion took place or `false` if
|
||||
the assignment took place.
|
||||
|
||||
@throw std::length_error key is too long.
|
||||
|
||||
@throw std::length_error @ref size() >= max_size().
|
||||
|
||||
@return A pair where `first` is an iterator
|
||||
to the existing or inserted element, and `second`
|
||||
is `true` if the insertion took place or `false` if
|
||||
the assignment took place.
|
||||
*/
|
||||
template<class P
|
||||
#ifndef GENERATING_DOCUMENTATION
|
||||
@ -1016,13 +1016,13 @@ public:
|
||||
Strong guarantee.
|
||||
Calls to @ref storage::allocate may throw.
|
||||
|
||||
@throw std::length_error if key is too long
|
||||
|
||||
@param key The key used for lookup and insertion
|
||||
|
||||
@param m The value to insert or assign
|
||||
|
||||
@returns A `std::pair` where `first` is an iterator
|
||||
@throw std::length_error if key is too long
|
||||
|
||||
@return A `std::pair` where `first` is an iterator
|
||||
to the existing or inserted element, and `second`
|
||||
is `true` if the insertion took place or `false` if
|
||||
the assignment took place.
|
||||
@ -1056,15 +1056,15 @@ public:
|
||||
Strong guarantee.
|
||||
Calls to @ref storage::allocate may throw.
|
||||
|
||||
@throw std::length_error if key is too long
|
||||
|
||||
@param key The key used for lookup and insertion
|
||||
|
||||
@param arg The argument used to construct the value.
|
||||
This will be passed as `std::forward<Arg>(arg)` to
|
||||
the @ref value constructor.
|
||||
|
||||
@returns A `std::pair` where `first` is an iterator
|
||||
@throw std::length_error if key is too long
|
||||
|
||||
@return A `std::pair` where `first` is an iterator
|
||||
to the existing or inserted element, and `second`
|
||||
is `true` if the insertion took place or `false` if
|
||||
the assignment took place.
|
||||
@ -1094,7 +1094,7 @@ public:
|
||||
@param pos An iterator pointing to the element to be
|
||||
removed.
|
||||
|
||||
@returns The number of elements removed, which can
|
||||
@return The number of elements removed, which can
|
||||
be either 0 or 1.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
@ -1116,7 +1116,7 @@ public:
|
||||
|
||||
No-throw guarantee.
|
||||
|
||||
@returns The number of elements removed, which can
|
||||
@return The number of elements removed, which can
|
||||
be either 0 or 1.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
@ -1168,9 +1168,9 @@ public:
|
||||
|
||||
Constant on average, worst case linear in @ref size().
|
||||
|
||||
@throw std::out_of_range if no such element exists.
|
||||
|
||||
@param key The key of the element to find
|
||||
|
||||
@throw std::out_of_range if no such element exists.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
value&
|
||||
@ -1185,9 +1185,9 @@ public:
|
||||
|
||||
Constant on average, worst case linear in @ref size().
|
||||
|
||||
@throw std::out_of_range if no such element exists.
|
||||
|
||||
@param key The key of the element to find
|
||||
|
||||
@throw std::out_of_range if no such element exists.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
value const&
|
||||
|
@ -40,7 +40,7 @@ namespace json {
|
||||
pointer to be used by the @ref value container into
|
||||
which the parsed results are stored. After the
|
||||
parse is started, the functions @ref write_some,
|
||||
@ref write, and @ref write_eof may be called to
|
||||
@ref write, and @ref finish may be called to
|
||||
provide successive buffers of characters of the
|
||||
JSON. The caller can check that the parse is
|
||||
complete by calling @ref is_done, or that a
|
||||
@ -57,6 +57,14 @@ namespace json {
|
||||
to bound the amount of work performed in each
|
||||
parsing cycle.
|
||||
|
||||
<br>
|
||||
|
||||
The parser may dynamically allocate intermediate
|
||||
storage as needed to accommodate the nesting level
|
||||
of the JSON being parsed. This storage is freed
|
||||
when the parser is destroyed, allowing the parser
|
||||
to cheaply re-use this memory when parsing
|
||||
subsequent JSONs, improving performance.
|
||||
*/
|
||||
class parser final
|
||||
: public basic_parser
|
||||
@ -83,6 +91,9 @@ class parser final
|
||||
|
||||
public:
|
||||
/** Destructor.
|
||||
|
||||
All dynamically allocated memory, including
|
||||
any partial parsing results, is freed.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
virtual
|
||||
@ -96,11 +107,11 @@ public:
|
||||
BOOST_JSON_DECL
|
||||
parser();
|
||||
|
||||
/** Prepare the parser for new serialized JSON.
|
||||
/** Start parsing JSON incrementally.
|
||||
|
||||
This function must be called once, before
|
||||
any data is presented, to start parsing a
|
||||
new JSON.
|
||||
This function must be called once manually before
|
||||
parsing a new JSON incrementally; that is, when
|
||||
using @ref write_some, @ref write, or @ref finish.
|
||||
|
||||
@param sp The storage to use for all values.
|
||||
*/
|
||||
@ -108,16 +119,17 @@ public:
|
||||
void
|
||||
start(storage_ptr sp = {}) noexcept;
|
||||
|
||||
/** Discard all intermadiate or final parsing results.
|
||||
/** Discard all parsed JSON results.
|
||||
|
||||
This function destroys all intermediate parsing
|
||||
results, while preserving dynamically allocated
|
||||
internal memory which is reused between parses.
|
||||
internal memory which may be reused on a
|
||||
subsequent parse.
|
||||
|
||||
@note
|
||||
|
||||
It is necessary to call @ref start to parse new
|
||||
JSON after calling this function.
|
||||
After this call, it is necessary to call
|
||||
@ref start to parse a new JSON incrementally.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
@ -125,34 +137,19 @@ public:
|
||||
|
||||
/** Return the parsed JSON as a @ref value.
|
||||
|
||||
If the parse failed, the returned value
|
||||
will be null.
|
||||
If @ref is_done() returns `true`, then the
|
||||
parsed value is returned. Otherwise an
|
||||
exception is thrown.
|
||||
|
||||
@par Preconditions
|
||||
@throw std::logic_error `! is_done()`
|
||||
|
||||
`is_done() == true`.
|
||||
|
||||
@returns The parsed value. Ownership of this
|
||||
@return The parsed value. Ownership of this
|
||||
value is transferred to the caller.
|
||||
*/
|
||||
BOOST_JSON_NODISCARD
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
release() noexcept;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
parse(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec,
|
||||
storage_ptr sp = {});
|
||||
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
parse(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
storage_ptr sp = {});
|
||||
release();
|
||||
|
||||
private:
|
||||
template<class T>
|
||||
@ -271,8 +268,12 @@ private:
|
||||
|
||||
/** Parse a string of JSON.
|
||||
|
||||
The string is parsed as JSON into a @ref value,
|
||||
using the specified storage.
|
||||
This function parses an entire single string in
|
||||
one step to produce a complete JSON object, returned
|
||||
as a @ref value. If the buffer does not contain a
|
||||
complete serialized JSON, an error occurs. In this
|
||||
case the returned value will be null, using the
|
||||
default storage.
|
||||
|
||||
@par Complexity
|
||||
|
||||
@ -283,28 +284,33 @@ private:
|
||||
Strong guarantee.
|
||||
Calls to @ref storage::allocate may throw.
|
||||
|
||||
@param s The string containing the JSON to parse.
|
||||
@param s The string to parse.
|
||||
|
||||
@param sp A pointer to the @ref storage
|
||||
to use. The container will acquire shared
|
||||
ownership of the storage object.
|
||||
@param ec Set to the error, if any occurred.
|
||||
|
||||
@param ec Set to the error if any occurred.
|
||||
@param sp The storage that the new value and all of
|
||||
its elements will use. If this parameter is omitted,
|
||||
the default storage is used.
|
||||
|
||||
@return A value representing the parsed JSON,
|
||||
or a null if any error occurred.
|
||||
*/
|
||||
BOOST_JSON_NODISCARD
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
parse(
|
||||
string_view s,
|
||||
storage_ptr sp,
|
||||
error_code& ec);
|
||||
error_code& ec,
|
||||
storage_ptr sp = {});
|
||||
|
||||
/** Parse a string of JSON.
|
||||
|
||||
The string is parsed as JSON into a @ref value
|
||||
using the specified storage.
|
||||
This function parses an entire single string in
|
||||
one step to produce a complete JSON object, returned
|
||||
as a @ref value. If the buffer does not contain a
|
||||
complete serialized JSON, an error occurs. In this
|
||||
case the returned value will be null, using the
|
||||
default storage.
|
||||
|
||||
@par Complexity
|
||||
|
||||
@ -315,80 +321,23 @@ parse(
|
||||
Strong guarantee.
|
||||
Calls to @ref storage::allocate may throw.
|
||||
|
||||
@param s The string containing the JSON to parse.
|
||||
@param s The string to parse.
|
||||
|
||||
@param sp A pointer to the @ref storage
|
||||
to use. The container will acquire shared
|
||||
ownership of the storage object.
|
||||
@param sp The storage that the new value and all of
|
||||
its elements will use. If this parameter is omitted,
|
||||
the default storage is used.
|
||||
|
||||
@return A value representing the parsed JSON.
|
||||
|
||||
@throw system_error any errors.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
parse(
|
||||
string_view s,
|
||||
storage_ptr sp);
|
||||
|
||||
/** Parse a string of JSON.
|
||||
|
||||
The string is parsed as JSON into a @ref value,
|
||||
using the default storage.
|
||||
|
||||
@par Complexity
|
||||
|
||||
Linear in `s.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Strong guarantee.
|
||||
Calls to @ref storage::allocate may throw.
|
||||
|
||||
@param s The string containing the JSON to parse.
|
||||
|
||||
@param ec Set to the error if any occurred.
|
||||
@throw system_error Thrown on failure.
|
||||
|
||||
@return A value representing the parsed JSON,
|
||||
or a null if any error occurred.
|
||||
*/
|
||||
inline
|
||||
BOOST_JSON_NODISCARD
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
parse(
|
||||
string_view s,
|
||||
error_code& ec)
|
||||
{
|
||||
return parse(s,
|
||||
storage_ptr{}, ec);
|
||||
}
|
||||
|
||||
/** Parse a string of JSON.
|
||||
|
||||
The string is parsed as JSON into a @ref value
|
||||
using the default storage.
|
||||
|
||||
@par Complexity
|
||||
|
||||
Linear in `s.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Strong guarantee.
|
||||
Calls to @ref storage::allocate may throw.
|
||||
|
||||
@param s The string containing the JSON to parse.
|
||||
|
||||
@return A value representing the parsed JSON.
|
||||
|
||||
@throw system_error any errors.
|
||||
*/
|
||||
inline
|
||||
value
|
||||
parse(string_view s)
|
||||
{
|
||||
return parse(
|
||||
s, storage_ptr{});
|
||||
}
|
||||
storage_ptr sp = {});
|
||||
|
||||
} // json
|
||||
} // boost
|
||||
|
@ -168,10 +168,10 @@ public:
|
||||
Strong guarantee.
|
||||
Calls to @ref storage::allocate may throw.
|
||||
|
||||
@throw std::logic_error if no value is set.
|
||||
|
||||
@return The number of characters written
|
||||
to `dest`.
|
||||
|
||||
@throw std::logic_error if no value is set.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
|
@ -220,7 +220,7 @@ public:
|
||||
If this parameter is omitted, the default storage
|
||||
is used.
|
||||
|
||||
@throws std::length_error `count > max_size()`.
|
||||
@throw std::length_error `count > max_size()`.
|
||||
*/
|
||||
string(
|
||||
std::size_t count,
|
||||
@ -262,7 +262,7 @@ public:
|
||||
If this parameter is omitted, the default storage
|
||||
is used.
|
||||
|
||||
@throws std::out_of_range `pos >= other.size()`.
|
||||
@throw std::out_of_range `pos >= other.size()`.
|
||||
*/
|
||||
string(
|
||||
string const& other,
|
||||
@ -299,7 +299,7 @@ public:
|
||||
If this parameter is omitted, the default storage
|
||||
is used.
|
||||
|
||||
@throws std::length_error `strlen(s) > max_size()`.
|
||||
@throw std::length_error `strlen(s) > max_size()`.
|
||||
*/
|
||||
string(
|
||||
char const* s,
|
||||
@ -335,7 +335,7 @@ public:
|
||||
If this parameter is omitted, the default storage
|
||||
is used.
|
||||
|
||||
@throws std::length_error `count > max_size()`.
|
||||
@throw std::length_error `count > max_size()`.
|
||||
*/
|
||||
string(
|
||||
char const* s,
|
||||
@ -377,7 +377,7 @@ public:
|
||||
If this parameter is omitted, the default storage
|
||||
is used.
|
||||
|
||||
@throws std::length_error `std::distance(first, last) > max_size()`.
|
||||
@throw std::length_error `std::distance(first, last) > max_size()`.
|
||||
*/
|
||||
template<class InputIt
|
||||
#ifndef GENERATING_DOCUMENTATION
|
||||
@ -533,7 +533,7 @@ public:
|
||||
If this parameter is omitted, the default storage
|
||||
is used.
|
||||
|
||||
@throws std::length_error `init.size() > max_size()`.
|
||||
@throw std::length_error `init.size() > max_size()`.
|
||||
*/
|
||||
string(
|
||||
std::initializer_list<char> init,
|
||||
@ -566,7 +566,7 @@ public:
|
||||
If this parameter is omitted, the default storage
|
||||
is used.
|
||||
|
||||
@throws std::length_error `s.size() > max_size()`.
|
||||
@throw std::length_error `s.size() > max_size()`.
|
||||
*/
|
||||
string(
|
||||
string_view s,
|
||||
@ -607,9 +607,9 @@ public:
|
||||
If this parameter is omitted, the default storage
|
||||
is used.
|
||||
|
||||
@throws std::out_of_range `pos >= s.size()`
|
||||
@throw std::out_of_range `pos >= s.size()`
|
||||
|
||||
@throws std::length_error `count > max_size()`.
|
||||
@throw std::length_error `count > max_size()`.
|
||||
*/
|
||||
string(
|
||||
string_view s,
|
||||
@ -698,7 +698,7 @@ public:
|
||||
@param s A pointer to a character string used to
|
||||
copy from.
|
||||
|
||||
@throws std::length_error `strlen(s) > max_size()`.
|
||||
@throw std::length_error `strlen(s) > max_size()`.
|
||||
*/
|
||||
string&
|
||||
operator=(char const* s)
|
||||
@ -722,7 +722,7 @@ public:
|
||||
|
||||
@param init The initializer list to copy from.
|
||||
|
||||
@throws std::length_error `init.size() > max_size()`.
|
||||
@throw std::length_error `init.size() > max_size()`.
|
||||
*/
|
||||
string&
|
||||
operator=(std::initializer_list<char> init)
|
||||
@ -747,7 +747,7 @@ public:
|
||||
|
||||
@param s The string view to copy from.
|
||||
|
||||
@throws std::length_error `s.size() > max_size()`.
|
||||
@throw std::length_error `s.size() > max_size()`.
|
||||
*/
|
||||
string&
|
||||
operator=(string_view s)
|
||||
@ -776,7 +776,7 @@ public:
|
||||
@param ch THe value to initialize characters
|
||||
of the string with.
|
||||
|
||||
@throws std::length_error `count > max_size()`.
|
||||
@throw std::length_error `count > max_size()`.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
string&
|
||||
@ -830,7 +830,7 @@ public:
|
||||
|
||||
@param count The number of characters to copy.
|
||||
|
||||
@throws std::out_of_range `pos >= other.size()`.
|
||||
@throw std::out_of_range `pos >= other.size()`.
|
||||
*/
|
||||
string&
|
||||
assign(
|
||||
@ -892,7 +892,7 @@ public:
|
||||
@param s A pointer to a character string used to
|
||||
copy from.
|
||||
|
||||
@throws std::length_error `count > max_size()`.
|
||||
@throw std::length_error `count > max_size()`.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
string&
|
||||
@ -919,7 +919,7 @@ public:
|
||||
@param s A pointer to a character string used to
|
||||
copy from.
|
||||
|
||||
@throws std::length_error `strlen(s) > max_size()`.
|
||||
@throw std::length_error `strlen(s) > max_size()`.
|
||||
*/
|
||||
string&
|
||||
assign(
|
||||
@ -954,7 +954,7 @@ public:
|
||||
@param last An input iterator pointing to the end
|
||||
of the range.
|
||||
|
||||
@throws std::length_error `std::distance(first, last) > max_size()`.
|
||||
@throw std::length_error `std::distance(first, last) > max_size()`.
|
||||
*/
|
||||
template<class InputIt
|
||||
#ifndef GENERATING_DOCUMENTATION
|
||||
@ -982,7 +982,7 @@ public:
|
||||
|
||||
@param init The initializer list to copy from.
|
||||
|
||||
@throws std::length_error `init.size() > max_size()`.
|
||||
@throw std::length_error `init.size() > max_size()`.
|
||||
*/
|
||||
string&
|
||||
assign(std::initializer_list<char> init)
|
||||
@ -1007,7 +1007,7 @@ public:
|
||||
|
||||
@param s The string view to copy from.
|
||||
|
||||
@throws std::length_error `s.size() > max_size()`.
|
||||
@throw std::length_error `s.size() > max_size()`.
|
||||
*/
|
||||
string&
|
||||
assign(string_view s)
|
||||
@ -1040,9 +1040,9 @@ public:
|
||||
|
||||
@param count The number of characters to copy.
|
||||
|
||||
@throws std::out_of_range `pos >= s.size()`
|
||||
@throw std::out_of_range `pos >= s.size()`
|
||||
|
||||
@throws std::length_error `count > max_size()`.
|
||||
@throw std::length_error `count > max_size()`.
|
||||
*/
|
||||
string&
|
||||
assign(
|
||||
@ -1089,7 +1089,7 @@ public:
|
||||
|
||||
@param pos A zero-based index
|
||||
|
||||
@throws std::out_of_range `pos >= size()`
|
||||
@throw std::out_of_range `pos >= size()`
|
||||
*/
|
||||
char&
|
||||
at(std::size_t pos)
|
||||
@ -1114,7 +1114,7 @@ public:
|
||||
|
||||
@param pos A zero-based index
|
||||
|
||||
@throws std::out_of_range `pos >= size()`
|
||||
@throw std::out_of_range `pos >= size()`
|
||||
*/
|
||||
char const&
|
||||
at(std::size_t pos) const
|
||||
@ -1612,9 +1612,9 @@ public:
|
||||
Strong guarantee.
|
||||
Calls to @ref storage::allocate may throw.
|
||||
|
||||
@throw std::length_error `new_capacity > max_size()`
|
||||
|
||||
@param new_capacity The new capacity of the array.
|
||||
|
||||
@throw std::length_error `new_capacity > max_size()`
|
||||
*/
|
||||
void
|
||||
reserve(std::size_t new_capacity)
|
||||
|
@ -1407,7 +1407,7 @@ public:
|
||||
|
||||
Strong guarantee.
|
||||
|
||||
@throws system error Thrown upon failure
|
||||
@throw system error Thrown upon failure
|
||||
*/
|
||||
template<class T>
|
||||
void
|
||||
@ -2748,6 +2748,13 @@ public:
|
||||
//------------------------------------------------------
|
||||
|
||||
private:
|
||||
static
|
||||
inline
|
||||
void
|
||||
relocate(
|
||||
value* dest,
|
||||
value const& src) noexcept;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
storage_ptr
|
||||
destroy() noexcept;
|
||||
|
@ -47,6 +47,8 @@ public:
|
||||
p.write(
|
||||
s.data() + n,
|
||||
s.size() - n, ec);
|
||||
if(! ec)
|
||||
p.finish(ec);
|
||||
if(! BEAST_EXPECTS(ec == ex,
|
||||
ec.message()))
|
||||
log << "should be " << ex.message() << std::endl;
|
||||
@ -67,6 +69,8 @@ public:
|
||||
fail_parser p(j);
|
||||
p.write(
|
||||
s.data(), s.size(), ec);
|
||||
if(! ec)
|
||||
p.finish(ec);
|
||||
if(ec == error::test_failure)
|
||||
continue;
|
||||
BEAST_EXPECTS(ec == ex,
|
||||
@ -91,6 +95,8 @@ public:
|
||||
{
|
||||
p.write(
|
||||
s.data(), s.size(), ec);
|
||||
if(! ec)
|
||||
p.finish(ec);
|
||||
BEAST_EXPECTS(ec == ex,
|
||||
ec.message());
|
||||
break;
|
||||
@ -118,6 +124,8 @@ public:
|
||||
s.data(),
|
||||
s.size(),
|
||||
ex);
|
||||
if(! ex)
|
||||
p.finish(ex);
|
||||
if(good)
|
||||
{
|
||||
if(! BEAST_EXPECTS(
|
||||
@ -441,6 +449,8 @@ public:
|
||||
BEAST_EXPECT(ec);
|
||||
p.reset();
|
||||
p.write("{}", 2, ec);
|
||||
if(! ec)
|
||||
p.finish(ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
BEAST_EXPECT(p.is_done());
|
||||
}
|
||||
@ -480,11 +490,67 @@ public:
|
||||
{
|
||||
error_code ec;
|
||||
fail_parser p;
|
||||
p.write_eof(ec);
|
||||
p.finish(ec);
|
||||
BEAST_EXPECT(ec);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testMembers()
|
||||
{
|
||||
// write_some(char const*, size_t, error_code&)
|
||||
{
|
||||
error_code ec;
|
||||
fail_parser p;
|
||||
p.write_some("0", 1, ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
}
|
||||
|
||||
// write_some(char const*, size_t)
|
||||
{
|
||||
fail_parser p;
|
||||
BEAST_THROWS(
|
||||
p.write_some("x", 1),
|
||||
system_error);
|
||||
}
|
||||
|
||||
// write(char const*, size_t, error_code&)
|
||||
{
|
||||
error_code ec;
|
||||
fail_parser p;
|
||||
p.write("0x", 2, ec);
|
||||
BEAST_EXPECTS(
|
||||
ec == error::extra_data,
|
||||
ec.message());
|
||||
}
|
||||
|
||||
// write(char const*, size_t)
|
||||
{
|
||||
fail_parser p;
|
||||
BEAST_THROWS(
|
||||
p.write("0x", 2),
|
||||
system_error);
|
||||
}
|
||||
|
||||
// finish(char const*, size_t, error_code&)
|
||||
{
|
||||
error_code ec;
|
||||
fail_parser p;
|
||||
p.finish("{", 1, ec);
|
||||
BEAST_EXPECTS(
|
||||
ec == error::incomplete,
|
||||
ec.message());
|
||||
}
|
||||
|
||||
// finish(char const*, size_t)
|
||||
{
|
||||
fail_parser p;
|
||||
BEAST_THROWS(
|
||||
p.finish("{", 1),
|
||||
system_error);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testParseVectors()
|
||||
{
|
||||
@ -520,6 +586,7 @@ public:
|
||||
testBoolean();
|
||||
testNull();
|
||||
testParser();
|
||||
testMembers();
|
||||
testParseVectors();
|
||||
}
|
||||
};
|
||||
|
@ -44,7 +44,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void run() override
|
||||
void
|
||||
run() override
|
||||
{
|
||||
check(condition::parse_error, error::syntax);
|
||||
check(condition::parse_error, error::extra_data);
|
||||
@ -56,7 +57,6 @@ public:
|
||||
check(condition::parse_error, error::illegal_control_char);
|
||||
check(condition::parse_error, error::illegal_escape_char);
|
||||
check(condition::parse_error, error::illegal_extra_digits);
|
||||
check(condition::parse_error, error::illegal_extra_chars);
|
||||
check(condition::parse_error, error::illegal_leading_surrogate);
|
||||
check(condition::parse_error, error::illegal_trailing_surrogate);
|
||||
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
if(! BEAST_EXPECT(n == 0))
|
||||
break;
|
||||
f(p.get());
|
||||
p.write_eof(ec);
|
||||
p.finish(ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
break;
|
||||
}
|
||||
@ -311,7 +311,7 @@ public:
|
||||
BEAST_EXPECT(p.maybe_init('-')); p.reset();
|
||||
}
|
||||
|
||||
// write_eof
|
||||
// finish
|
||||
{
|
||||
error_code ec;
|
||||
number_parser p;
|
||||
@ -319,7 +319,7 @@ public:
|
||||
if(BEAST_EXPECTS(! ec,
|
||||
ec.message()))
|
||||
{
|
||||
p.write_eof(ec);
|
||||
p.finish(ec);
|
||||
BEAST_EXPECTS(! ec,
|
||||
ec.message());
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <boost/json/parser.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/json/parser.hpp>
|
||||
#include <boost/json/block_storage.hpp>
|
||||
#include <boost/json/serializer.hpp>
|
||||
#include <sstream>
|
||||
|
||||
@ -36,6 +36,8 @@ public:
|
||||
s.data(),
|
||||
s.size(),
|
||||
ec);
|
||||
if(! ec)
|
||||
p.finish(ec);
|
||||
BEAST_EXPECTS(! ec,
|
||||
ec.message());
|
||||
//log << " " << to_string_test(p.get()) << std::endl;
|
||||
@ -92,6 +94,8 @@ public:
|
||||
error_code ec;
|
||||
p.start(ss);
|
||||
p.write(s.data(), i, ec);
|
||||
if(! ec)
|
||||
p.finish(ec);
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,11 +230,11 @@ R"xx({
|
||||
error_code ec;
|
||||
parser p;
|
||||
p.start();
|
||||
p.write_some(js.data(), N, ec);
|
||||
p.write(js.data(), N, ec);
|
||||
if(BEAST_EXPECTS(! ec,
|
||||
ec.message()))
|
||||
{
|
||||
p.write(js.data() + N,
|
||||
p.finish(js.data() + N,
|
||||
js.size() - N, ec);
|
||||
if(BEAST_EXPECTS(! ec,
|
||||
ec.message()))
|
||||
@ -302,7 +306,42 @@ R"xx({
|
||||
"{\"1\":{},\"2\":[],\"3\":\"x\",\"4\":1,"
|
||||
"\"5\":-1,\"6\":1.0,\"7\":false,\"8\":null}";
|
||||
|
||||
// parse(value)
|
||||
// parse(string_view, error_code)
|
||||
{
|
||||
{
|
||||
error_code ec;
|
||||
auto jv = parse(js, ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
check_round_trip(jv, js);
|
||||
}
|
||||
{
|
||||
error_code ec;
|
||||
auto jv = parse("xxx", ec);
|
||||
BEAST_EXPECT(ec);
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
}
|
||||
}
|
||||
|
||||
// parse(string_view, storage_ptr, error_code)
|
||||
{
|
||||
{
|
||||
error_code ec;
|
||||
scoped_storage<block_storage> sp;
|
||||
auto jv = parse(js, ec, sp);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
check_round_trip(jv, js);
|
||||
}
|
||||
|
||||
{
|
||||
error_code ec;
|
||||
scoped_storage<block_storage> sp;
|
||||
auto jv = parse("xxx", ec, sp);
|
||||
BEAST_EXPECT(ec);
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
}
|
||||
}
|
||||
|
||||
// parse(string_view)
|
||||
{
|
||||
{
|
||||
check_round_trip(
|
||||
@ -317,27 +356,17 @@ R"xx({
|
||||
}
|
||||
}
|
||||
|
||||
// parse(value, storage_ptr)
|
||||
// parse(string_view, storage_ptr)
|
||||
{
|
||||
check_round_trip(
|
||||
parse(js, storage_ptr{}),
|
||||
js);
|
||||
}
|
||||
|
||||
// parse(value, error_code)
|
||||
{
|
||||
error_code ec;
|
||||
auto jv = parse(js, ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
check_round_trip(jv, js);
|
||||
}
|
||||
|
||||
// parse(value, storage_ptr, error_code)
|
||||
{
|
||||
error_code ec;
|
||||
auto jv = parse(js, storage_ptr{}, ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
check_round_trip(jv, js);
|
||||
{
|
||||
scoped_storage<block_storage> sp;
|
||||
check_round_trip(parse(js, sp), js);
|
||||
}
|
||||
{
|
||||
scoped_storage<block_storage> sp;
|
||||
BEAST_THROWS(parse("xxx", sp),
|
||||
system_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user