1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/json
7  
// Official repository: https://github.com/boostorg/json
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_JSON_STREAM_PARSER_HPP
10  
#ifndef BOOST_JSON_STREAM_PARSER_HPP
11  
#define BOOST_JSON_STREAM_PARSER_HPP
11  
#define BOOST_JSON_STREAM_PARSER_HPP
12  

12  

13  
#include <boost/json/detail/config.hpp>
13  
#include <boost/json/detail/config.hpp>
14  
#include <boost/json/basic_parser.hpp>
14  
#include <boost/json/basic_parser.hpp>
15  
#include <boost/json/parse_options.hpp>
15  
#include <boost/json/parse_options.hpp>
16  
#include <boost/json/storage_ptr.hpp>
16  
#include <boost/json/storage_ptr.hpp>
17  
#include <boost/json/value.hpp>
17  
#include <boost/json/value.hpp>
18  
#include <boost/json/detail/handler.hpp>
18  
#include <boost/json/detail/handler.hpp>
19  
#include <type_traits>
19  
#include <type_traits>
20  
#include <cstddef>
20  
#include <cstddef>
21  

21  

22  
namespace boost {
22  
namespace boost {
23  
namespace json {
23  
namespace json {
24  

24  

25  
//----------------------------------------------------------
25  
//----------------------------------------------------------
26  

26  

27  
/** A DOM parser for JSON text contained in multiple buffers.
27  
/** A DOM parser for JSON text contained in multiple buffers.
28  

28  

29  
    This class is used to parse a JSON text contained in a series of one or
29  
    This class is used to parse a JSON text contained in a series of one or
30  
    more character buffers, into a @ref value container. It implements a
30  
    more character buffers, into a @ref value container. It implements a
31  
    [_streaming algorithm_](https://en.wikipedia.org/wiki/Streaming_algorithm),
31  
    [_streaming algorithm_](https://en.wikipedia.org/wiki/Streaming_algorithm),
32  
    allowing these parsing strategies:
32  
    allowing these parsing strategies:
33  

33  

34  
    @li parse a JSON file a piece at a time;
34  
    @li parse a JSON file a piece at a time;
35  
    @li parse incoming JSON text as it arrives, one buffer at a time;
35  
    @li parse incoming JSON text as it arrives, one buffer at a time;
36  
    @li parse with bounded resource consumption per cycle.
36  
    @li parse with bounded resource consumption per cycle.
37  

37  

38  
    @par Usage
38  
    @par Usage
39  
    To use the parser first construct it, then optionally call @ref reset to
39  
    To use the parser first construct it, then optionally call @ref reset to
40  
    specify a @ref storage_ptr to use for the resulting @ref value. Then call
40  
    specify a @ref storage_ptr to use for the resulting @ref value. Then call
41  
    @ref write one or more times to parse a single, complete JSON text. Call
41  
    @ref write one or more times to parse a single, complete JSON text. Call
42  
    @ref done to determine if the parse has completed. To indicate there are no
42  
    @ref done to determine if the parse has completed. To indicate there are no
43  
    more buffers, call @ref finish. If the parse is successful, call @ref
43  
    more buffers, call @ref finish. If the parse is successful, call @ref
44  
    release to take ownership of the value:
44  
    release to take ownership of the value:
45  

45  

46  
    @code
46  
    @code
47  
    stream_parser p;                                // construct a parser
47  
    stream_parser p;                                // construct a parser
48  
    p.write( "[1,2" );                              // parse some of a JSON text
48  
    p.write( "[1,2" );                              // parse some of a JSON text
49  
    p.write( ",3,4]" );                             // parse the rest of the JSON text
49  
    p.write( ",3,4]" );                             // parse the rest of the JSON text
50  
    assert( p.done() );                             // we have a complete JSON text
50  
    assert( p.done() );                             // we have a complete JSON text
51  
    value jv = p.release();                         // take ownership of the value
51  
    value jv = p.release();                         // take ownership of the value
52  
    @endcode
52  
    @endcode
53  

53  

54  
    @par Extra Data
54  
    @par Extra Data
55  
    When the character buffer provided as input contains additional data that
55  
    When the character buffer provided as input contains additional data that
56  
    is not part of the complete JSON text, an error is returned. The @ref
56  
    is not part of the complete JSON text, an error is returned. The @ref
57  
    write_some function is an alternative which allows the parse to finish
57  
    write_some function is an alternative which allows the parse to finish
58  
    early, without consuming all the characters in the buffer. This allows
58  
    early, without consuming all the characters in the buffer. This allows
59  
    parsing of a buffer containing multiple individual JSON texts or containing
59  
    parsing of a buffer containing multiple individual JSON texts or containing
60  
    different protocol data:
60  
    different protocol data:
61  

61  

62  
    @code
62  
    @code
63  
    stream_parser p;                                // construct a parser
63  
    stream_parser p;                                // construct a parser
64  
    std::size_t n;                                  // number of characters used
64  
    std::size_t n;                                  // number of characters used
65  
    n = p.write_some( "[1,2" );                     // parse some of a JSON text
65  
    n = p.write_some( "[1,2" );                     // parse some of a JSON text
66  
    assert( n == 4 );                               // all characters consumed
66  
    assert( n == 4 );                               // all characters consumed
67  
    n = p.write_some( ",3,4] null" );               // parse the remainder of the JSON text
67  
    n = p.write_some( ",3,4] null" );               // parse the remainder of the JSON text
68  
    assert( n == 6 );                               // only some characters consumed
68  
    assert( n == 6 );                               // only some characters consumed
69  
    assert( p.done() );                             // we have a complete JSON text
69  
    assert( p.done() );                             // we have a complete JSON text
70  
    value jv = p.release();                         // take ownership of the value
70  
    value jv = p.release();                         // take ownership of the value
71  
    @endcode
71  
    @endcode
72  

72  

73  
    @par Temporary Storage
73  
    @par Temporary Storage
74  
    The parser may dynamically allocate temporary storage as needed to
74  
    The parser may dynamically allocate temporary storage as needed to
75  
    accommodate the nesting level of the JSON text being parsed. Temporary
75  
    accommodate the nesting level of the JSON text being parsed. Temporary
76  
    storage is first obtained from an optional, caller-owned buffer specified
76  
    storage is first obtained from an optional, caller-owned buffer specified
77  
    upon construction. When that is exhausted, the next allocation uses the
77  
    upon construction. When that is exhausted, the next allocation uses the
78  
    @ref boost::container::pmr::memory_resource passed to the constructor; if
78  
    @ref boost::container::pmr::memory_resource passed to the constructor; if
79  
    no such argument is specified, the default memory resource is used.
79  
    no such argument is specified, the default memory resource is used.
80  
    Temporary storage is freed only when the parser is destroyed; The
80  
    Temporary storage is freed only when the parser is destroyed; The
81  
    performance of parsing multiple JSON texts may be improved by reusing the
81  
    performance of parsing multiple JSON texts may be improved by reusing the
82  
    same parser instance.
82  
    same parser instance.
83  

83  

84  
    It is important to note that the @ref
84  
    It is important to note that the @ref
85  
    boost::container::pmr::memory_resource supplied upon construction is used
85  
    boost::container::pmr::memory_resource supplied upon construction is used
86  
    for temporary storage only, and not for allocating the elements which make
86  
    for temporary storage only, and not for allocating the elements which make
87  
    up the parsed value. That other memory resource is optionally supplied in
87  
    up the parsed value. That other memory resource is optionally supplied in
88  
    each call to @ref reset.
88  
    each call to @ref reset.
89  

89  

90  
    @par Duplicate Keys
90  
    @par Duplicate Keys
91  
    If there are object elements with duplicate keys; that is, if multiple
91  
    If there are object elements with duplicate keys; that is, if multiple
92  
    elements in an object have keys that compare equal, only the last
92  
    elements in an object have keys that compare equal, only the last
93  
    equivalent element will be inserted.
93  
    equivalent element will be inserted.
94  

94  

95  
    @par Non-Standard JSON
95  
    @par Non-Standard JSON
96  
    The @ref parse_options structure optionally provided upon construction is
96  
    The @ref parse_options structure optionally provided upon construction is
97  
    used to customize some parameters of the parser, including which
97  
    used to customize some parameters of the parser, including which
98  
    non-standard JSON extensions should be allowed. A default-constructed parse
98  
    non-standard JSON extensions should be allowed. A default-constructed parse
99  
    options allows only standard JSON.
99  
    options allows only standard JSON.
100  

100  

101  
    @par Thread Safety
101  
    @par Thread Safety
102  
    Distinct instances may be accessed concurrently. Non-const member functions
102  
    Distinct instances may be accessed concurrently. Non-const member functions
103  
    of a shared instance may not be called concurrently with any other member
103  
    of a shared instance may not be called concurrently with any other member
104  
    functions of that instance.
104  
    functions of that instance.
105  

105  

106  
    @see @ref parse, @ref parser, @ref parse_options.
106  
    @see @ref parse, @ref parser, @ref parse_options.
107  
*/
107  
*/
108  
class stream_parser
108  
class stream_parser
109  
{
109  
{
110  
    basic_parser<detail::handler> p_;
110  
    basic_parser<detail::handler> p_;
111  

111  

112  
public:
112  
public:
113  
    /** Destructor.
113  
    /** Destructor.
114  

114  

115  
        All dynamically allocated memory, including
115  
        All dynamically allocated memory, including
116  
        any incomplete parsing results, is freed.
116  
        any incomplete parsing results, is freed.
117  

117  

118  
        @par Complexity
118  
        @par Complexity
119  
        Linear in the size of partial results
119  
        Linear in the size of partial results
120  

120  

121  
        @par Exception Safety
121  
        @par Exception Safety
122  
        No-throw guarantee.
122  
        No-throw guarantee.
123  
    */
123  
    */
124  
    ~stream_parser() = default;
124  
    ~stream_parser() = default;
125  

125  

126  
    /** Constructors.
126  
    /** Constructors.
127  

127  

128  
        Construct a new parser.
128  
        Construct a new parser.
129  

129  

130  
        The parser will only support standard JSON if overloads **(1)**
130  
        The parser will only support standard JSON if overloads **(1)**
131  
        or **(2)** are used. Otherwise the parser will support extensions
131  
        or **(2)** are used. Otherwise the parser will support extensions
132  
        specified by the parameter `opt`.
132  
        specified by the parameter `opt`.
133  

133  

134  
        The parsed value will use the \<\<default_memory_resource,default
134  
        The parsed value will use the \<\<default_memory_resource,default
135  
        memory resource\>\> for storage. To use a different resource, call @ref
135  
        memory resource\>\> for storage. To use a different resource, call @ref
136  
        reset after construction.
136  
        reset after construction.
137  

137  

138  
        The main difference between the overloads is in what the constructed
138  
        The main difference between the overloads is in what the constructed
139  
        parser will use for temporary storage:
139  
        parser will use for temporary storage:
140  

140  

141  
        @li **(1)** the constructed parser uses the default memory resource for
141  
        @li **(1)** the constructed parser uses the default memory resource for
142  
        temporary storage.
142  
        temporary storage.
143  

143  

144  
        @li **(2)**, **(3)** the constructed parser uses the memory resource of
144  
        @li **(2)**, **(3)** the constructed parser uses the memory resource of
145  
        `sp` for temporary storage.
145  
        `sp` for temporary storage.
146  

146  

147  
        @li **(4)**, **(6)** the constructed parser first uses the caller-owned
147  
        @li **(4)**, **(6)** the constructed parser first uses the caller-owned
148  
        storage `[buffer, buffer + size)` for temporary storage, falling back
148  
        storage `[buffer, buffer + size)` for temporary storage, falling back
149  
        to the memory resource of `sp` if needed.
149  
        to the memory resource of `sp` if needed.
150  

150  

151  
        @li **(5)**, **(7)** the constructed parser first uses the caller-owned
151  
        @li **(5)**, **(7)** the constructed parser first uses the caller-owned
152  
        storage `[buffer, buffer + N)` for temporary storage, falling back to
152  
        storage `[buffer, buffer + N)` for temporary storage, falling back to
153  
        the memory resource of `sp` if needed.
153  
        the memory resource of `sp` if needed.
154  

154  

155  
        @note Ownership of `buffer` is not transferred. The caller is
155  
        @note Ownership of `buffer` is not transferred. The caller is
156  
        responsible for ensuring the lifetime of the storage pointed to by
156  
        responsible for ensuring the lifetime of the storage pointed to by
157  
        `buffer` extends until the parser is destroyed.
157  
        `buffer` extends until the parser is destroyed.
158  

158  

159  
        Overload **(8)** is the copy constructor. The type is neither copyable
159  
        Overload **(8)** is the copy constructor. The type is neither copyable
160  
        nor movable, so the overload is deleted.
160  
        nor movable, so the overload is deleted.
161  

161  

162  
        @par Complexity
162  
        @par Complexity
163  
        Constant.
163  
        Constant.
164  

164  

165  
        @par Exception Safety
165  
        @par Exception Safety
166  
        No-throw guarantee.
166  
        No-throw guarantee.
167  

167  

168  
        @{
168  
        @{
169  
    */
169  
    */
170  
    stream_parser() noexcept
170  
    stream_parser() noexcept
171  
        : stream_parser({}, {})
171  
        : stream_parser({}, {})
172  
    {
172  
    {
173  
    }
173  
    }
174  

174  

175  

175  

176  
    /** Overload
176  
    /** Overload
177  

177  

178  
        @param sp The memory resource to use for temporary storage.
178  
        @param sp The memory resource to use for temporary storage.
179  
    */
179  
    */
180  
    explicit
180  
    explicit
181  
    stream_parser(storage_ptr sp) noexcept
181  
    stream_parser(storage_ptr sp) noexcept
182  
        : stream_parser(std::move(sp), {})
182  
        : stream_parser(std::move(sp), {})
183  
    {
183  
    {
184  
    }
184  
    }
185  

185  

186  
    /** Overload
186  
    /** Overload
187  

187  

188  
        @param opt The parsing options to use.
188  
        @param opt The parsing options to use.
189  
        @param sp
189  
        @param sp
190  
    */
190  
    */
191  
    BOOST_JSON_DECL
191  
    BOOST_JSON_DECL
192  
    stream_parser(
192  
    stream_parser(
193  
        storage_ptr sp,
193  
        storage_ptr sp,
194  
        parse_options const& opt) noexcept;
194  
        parse_options const& opt) noexcept;
195  

195  

196  
    /** Overload
196  
    /** Overload
197  
        @param buffer A pointer to valid storage.
197  
        @param buffer A pointer to valid storage.
198  
        @param size The number of valid bytes in `buffer`.
198  
        @param size The number of valid bytes in `buffer`.
199  
        @param sp
199  
        @param sp
200  
        @param opt
200  
        @param opt
201  
    */
201  
    */
202  
    BOOST_JSON_DECL
202  
    BOOST_JSON_DECL
203  
    stream_parser(
203  
    stream_parser(
204  
        storage_ptr sp,
204  
        storage_ptr sp,
205  
        parse_options const& opt,
205  
        parse_options const& opt,
206  
        unsigned char* buffer,
206  
        unsigned char* buffer,
207  
        std::size_t size) noexcept;
207  
        std::size_t size) noexcept;
208  

208  

209  
    /** Overload
209  
    /** Overload
210  

210  

211  
        @tparam N The number of valid bytes in `buffer`.
211  
        @tparam N The number of valid bytes in `buffer`.
212  
        @param sp
212  
        @param sp
213  
        @param opt
213  
        @param opt
214  
        @param buffer
214  
        @param buffer
215  
    */
215  
    */
216  
    template<std::size_t N>
216  
    template<std::size_t N>
217  
    stream_parser(
217  
    stream_parser(
218  
        storage_ptr sp,
218  
        storage_ptr sp,
219  
        parse_options const& opt,
219  
        parse_options const& opt,
220  
        unsigned char(&buffer)[N]) noexcept
220  
        unsigned char(&buffer)[N]) noexcept
221  
        : stream_parser(std::move(sp),
221  
        : stream_parser(std::move(sp),
222  
            opt, &buffer[0], N)
222  
            opt, &buffer[0], N)
223  
    {
223  
    {
224  
    }
224  
    }
225  

225  

226  
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
226  
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
227  
    /** Overload
227  
    /** Overload
228  

228  

229  
        @param sp
229  
        @param sp
230  
        @param opt
230  
        @param opt
231  
        @param buffer
231  
        @param buffer
232  
        @param size
232  
        @param size
233  
    */
233  
    */
234  
    stream_parser(
234  
    stream_parser(
235  
        storage_ptr sp,
235  
        storage_ptr sp,
236  
        parse_options const& opt,
236  
        parse_options const& opt,
237  
        std::byte* buffer,
237  
        std::byte* buffer,
238  
        std::size_t size) noexcept
238  
        std::size_t size) noexcept
239  
        : stream_parser(sp, opt, reinterpret_cast<
239  
        : stream_parser(sp, opt, reinterpret_cast<
240  
            unsigned char*>(buffer), size)
240  
            unsigned char*>(buffer), size)
241  
    {
241  
    {
242  
    }
242  
    }
243  

243  

244  
    /** Overload
244  
    /** Overload
245  

245  

246  
        @tparam N
246  
        @tparam N
247  
        @param sp
247  
        @param sp
248  
        @param opt
248  
        @param opt
249  
        @param buffer
249  
        @param buffer
250  
    */
250  
    */
251  
    template<std::size_t N>
251  
    template<std::size_t N>
252  
    stream_parser(
252  
    stream_parser(
253  
        storage_ptr sp,
253  
        storage_ptr sp,
254  
        parse_options const& opt,
254  
        parse_options const& opt,
255  
        std::byte(&buffer)[N]) noexcept
255  
        std::byte(&buffer)[N]) noexcept
256  
        : stream_parser(std::move(sp),
256  
        : stream_parser(std::move(sp),
257  
            opt, &buffer[0], N)
257  
            opt, &buffer[0], N)
258  
    {
258  
    {
259  
    }
259  
    }
260  
#endif
260  
#endif
261  

261  

262  
#ifndef BOOST_JSON_DOCS
262  
#ifndef BOOST_JSON_DOCS
263  
    // Safety net for accidental buffer overflows
263  
    // Safety net for accidental buffer overflows
264  
    template<std::size_t N>
264  
    template<std::size_t N>
265  
    stream_parser(
265  
    stream_parser(
266  
        storage_ptr sp,
266  
        storage_ptr sp,
267  
        parse_options const& opt,
267  
        parse_options const& opt,
268  
        unsigned char(&buffer)[N],
268  
        unsigned char(&buffer)[N],
269  
        std::size_t n) noexcept
269  
        std::size_t n) noexcept
270  
        : stream_parser(std::move(sp),
270  
        : stream_parser(std::move(sp),
271  
            opt, &buffer[0], n)
271  
            opt, &buffer[0], n)
272  
    {
272  
    {
273  
        // If this goes off, check your parameters
273  
        // If this goes off, check your parameters
274  
        // closely, chances are you passed an array
274  
        // closely, chances are you passed an array
275  
        // thinking it was a pointer.
275  
        // thinking it was a pointer.
276  
        BOOST_ASSERT(n <= N);
276  
        BOOST_ASSERT(n <= N);
277  
    }
277  
    }
278  

278  

279  
#ifdef __cpp_lib_byte
279  
#ifdef __cpp_lib_byte
280  
    // Safety net for accidental buffer overflows
280  
    // Safety net for accidental buffer overflows
281  
    template<std::size_t N>
281  
    template<std::size_t N>
282  
    stream_parser(
282  
    stream_parser(
283  
        storage_ptr sp,
283  
        storage_ptr sp,
284  
        parse_options const& opt,
284  
        parse_options const& opt,
285  
        std::byte(&buffer)[N], std::size_t n) noexcept
285  
        std::byte(&buffer)[N], std::size_t n) noexcept
286  
        : stream_parser(std::move(sp),
286  
        : stream_parser(std::move(sp),
287  
            opt, &buffer[0], n)
287  
            opt, &buffer[0], n)
288  
    {
288  
    {
289  
        // If this goes off, check your parameters
289  
        // If this goes off, check your parameters
290  
        // closely, chances are you passed an array
290  
        // closely, chances are you passed an array
291  
        // thinking it was a pointer.
291  
        // thinking it was a pointer.
292  
        BOOST_ASSERT(n <= N);
292  
        BOOST_ASSERT(n <= N);
293  
    }
293  
    }
294  
#endif
294  
#endif
295  
#endif
295  
#endif
296  

296  

297  
    /// Overload
297  
    /// Overload
298  
    stream_parser(
298  
    stream_parser(
299  
        stream_parser const&) = delete;
299  
        stream_parser const&) = delete;
300  
    /// @}
300  
    /// @}
301  

301  

302  
    /** Assignment operator.
302  
    /** Assignment operator.
303  

303  

304  
       This type is neither copyable nor movable, so copy assignment operator
304  
       This type is neither copyable nor movable, so copy assignment operator
305  
       is deleted.
305  
       is deleted.
306  
   */
306  
   */
307  
    stream_parser& operator=(
307  
    stream_parser& operator=(
308  
        stream_parser const&) = delete;
308  
        stream_parser const&) = delete;
309  

309  

310  
    /** Reset the parser for a new JSON text.
310  
    /** Reset the parser for a new JSON text.
311  

311  

312  
        This function is used to reset the parser to prepare it for parsing
312  
        This function is used to reset the parser to prepare it for parsing
313  
        a new complete JSON text. Any previous partial results are destroyed.
313  
        a new complete JSON text. Any previous partial results are destroyed.
314  
        The new value will use the memory resource of `sp`.
314  
        The new value will use the memory resource of `sp`.
315  

315  

316  
        @par Complexity
316  
        @par Complexity
317  
        Constant or linear in the size of any previous partial parsing results.
317  
        Constant or linear in the size of any previous partial parsing results.
318  

318  

319  
        @par Exception Safety
319  
        @par Exception Safety
320  
        No-throw guarantee.
320  
        No-throw guarantee.
321  

321  

322  
        @param sp A pointer to the @ref boost::container::pmr::memory_resource.
322  
        @param sp A pointer to the @ref boost::container::pmr::memory_resource.
323  
    */
323  
    */
324  
    BOOST_JSON_DECL
324  
    BOOST_JSON_DECL
325  
    void
325  
    void
326  
    reset(storage_ptr sp = {}) noexcept;
326  
    reset(storage_ptr sp = {}) noexcept;
327  

327  

328  
    /** Check if a complete JSON text has been parsed.
328  
    /** Check if a complete JSON text has been parsed.
329  

329  

330  
        This function returns `true` when all of these conditions are met:
330  
        This function returns `true` when all of these conditions are met:
331  

331  

332  
        @li A complete serialized JSON text has been presented to the parser,
332  
        @li A complete serialized JSON text has been presented to the parser,
333  
        and
333  
        and
334  

334  

335  
        @li No error has occurred since the parser was constructed, or since
335  
        @li No error has occurred since the parser was constructed, or since
336  
        the last call to @ref reset,
336  
        the last call to @ref reset,
337  

337  

338  
        @par Complexity
338  
        @par Complexity
339  
        Constant.
339  
        Constant.
340  

340  

341  
        @par Exception Safety
341  
        @par Exception Safety
342  
        No-throw guarantee.
342  
        No-throw guarantee.
343  
    */
343  
    */
344  
    bool
344  
    bool
345  
    done() const noexcept
345  
    done() const noexcept
346  
    {
346  
    {
347  
        return p_.done();
347  
        return p_.done();
348  
    }
348  
    }
349  

349  

350  
    /** Parse a buffer containing all or part of a complete JSON text.
350  
    /** Parse a buffer containing all or part of a complete JSON text.
351  

351  

352  
        This function parses JSON text contained in the specified character
352  
        This function parses JSON text contained in the specified character
353  
        buffer. If parsing completes, any additional characters past the end of
353  
        buffer. If parsing completes, any additional characters past the end of
354  
        the complete JSON text are ignored. The function returns the actual
354  
        the complete JSON text are ignored. The function returns the actual
355  
        number of characters parsed, which may be less than the size of the
355  
        number of characters parsed, which may be less than the size of the
356  
        input. This allows parsing of a buffer containing multiple individual
356  
        input. This allows parsing of a buffer containing multiple individual
357  
        JSON texts or containing different protocol data.
357  
        JSON texts or containing different protocol data.
358  

358  

359  
        Overloads **(1)**, **(2)**, **(4)**, and **(5)** report errors by
359  
        Overloads **(1)**, **(2)**, **(4)**, and **(5)** report errors by
360  
        setting `ec`. Overloads **(3)** and **(6)** report errors by throwing
360  
        setting `ec`. Overloads **(3)** and **(6)** report errors by throwing
361  
        exceptions. Upon error or exception, subsequent calls will fail until
361  
        exceptions. Upon error or exception, subsequent calls will fail until
362  
        @ref reset is called to parse a new JSON text.
362  
        @ref reset is called to parse a new JSON text.
363  

363  

364  
        @note To indicate there are no more character buffers, such as when
364  
        @note To indicate there are no more character buffers, such as when
365  
        @ref done returns `false` after writing, call @ref finish.
365  
        @ref done returns `false` after writing, call @ref finish.
366  

366  

367  
        @par Example
367  
        @par Example
368  
        @code
368  
        @code
369  
        stream_parser p;                                // construct a parser
369  
        stream_parser p;                                // construct a parser
370  
        std::size_t n;                                  // number of characters used
370  
        std::size_t n;                                  // number of characters used
371  
        n = p.write_some( "[1,2" );                     // parse the first part of the JSON text
371  
        n = p.write_some( "[1,2" );                     // parse the first part of the JSON text
372  
        assert( n == 4 );                               // all characters consumed
372  
        assert( n == 4 );                               // all characters consumed
373  
        n = p.write_some( "3,4] null" );                // parse the rest of the JSON text
373  
        n = p.write_some( "3,4] null" );                // parse the rest of the JSON text
374  
        assert( n == 5 );                               // only some characters consumed
374  
        assert( n == 5 );                               // only some characters consumed
375  
        value jv = p.release();                         // take ownership of the value
375  
        value jv = p.release();                         // take ownership of the value
376  
        @endcode
376  
        @endcode
377  

377  

378  
        @par Complexity
378  
        @par Complexity
379  
        @li **(1)**--**(3)** linear in `size`.
379  
        @li **(1)**--**(3)** linear in `size`.
380  
        @li **(4)**--**(6)** linear in `s.size()`.
380  
        @li **(4)**--**(6)** linear in `s.size()`.
381  

381  

382  
        @par Exception Safety
382  
        @par Exception Safety
383  
        Basic guarantee. Calls to `memory_resource::allocate` may throw.
383  
        Basic guarantee. Calls to `memory_resource::allocate` may throw.
384  

384  

385  
        @return The number of characters consumed from the buffer.
385  
        @return The number of characters consumed from the buffer.
386  

386  

387  
        @param data A pointer to a buffer of `size` characters to parse.
387  
        @param data A pointer to a buffer of `size` characters to parse.
388  
        @param size The number of characters pointed to by `data`.
388  
        @param size The number of characters pointed to by `data`.
389  
        @param ec Set to the error, if any occurred.
389  
        @param ec Set to the error, if any occurred.
390  

390  

391  
        @{
391  
        @{
392  
    */
392  
    */
393  
    BOOST_JSON_DECL
393  
    BOOST_JSON_DECL
394  
    std::size_t
394  
    std::size_t
395  
    write_some(
395  
    write_some(
396  
        char const* data,
396  
        char const* data,
397  
        std::size_t size,
397  
        std::size_t size,
398  
        system::error_code& ec);
398  
        system::error_code& ec);
399  

399  

400  
    BOOST_JSON_DECL
400  
    BOOST_JSON_DECL
401  
    std::size_t
401  
    std::size_t
402  
    write_some(
402  
    write_some(
403  
        char const* data,
403  
        char const* data,
404  
        std::size_t size,
404  
        std::size_t size,
405  
        std::error_code& ec);
405  
        std::error_code& ec);
406  

406  

407  
    /** Overload
407  
    /** Overload
408  

408  

409  
        @param data
409  
        @param data
410  
        @param size
410  
        @param size
411  

411  

412  
        @throw boost::system::system_error Thrown on error.
412  
        @throw boost::system::system_error Thrown on error.
413  
    */
413  
    */
414  
    BOOST_JSON_DECL
414  
    BOOST_JSON_DECL
415  
    std::size_t
415  
    std::size_t
416  
    write_some(
416  
    write_some(
417  
        char const* data,
417  
        char const* data,
418  
        std::size_t size);
418  
        std::size_t size);
419  

419  

420  
    /** Overload
420  
    /** Overload
421  
        @param s The character string to parse.
421  
        @param s The character string to parse.
422  
        @param ec
422  
        @param ec
423  
    */
423  
    */
424  
    std::size_t
424  
    std::size_t
425  
    write_some(
425  
    write_some(
426  
        string_view s,
426  
        string_view s,
427  
        system::error_code& ec)
427  
        system::error_code& ec)
428  
    {
428  
    {
429  
        return write_some(
429  
        return write_some(
430  
            s.data(), s.size(), ec);
430  
            s.data(), s.size(), ec);
431  
    }
431  
    }
432  

432  

433  
    /** Overload
433  
    /** Overload
434  
        @param s
434  
        @param s
435  
        @param ec
435  
        @param ec
436  
    */
436  
    */
437  
    std::size_t
437  
    std::size_t
438  
    write_some(
438  
    write_some(
439  
        string_view s,
439  
        string_view s,
440  
        std::error_code& ec)
440  
        std::error_code& ec)
441  
    {
441  
    {
442  
        return write_some(
442  
        return write_some(
443  
            s.data(), s.size(), ec);
443  
            s.data(), s.size(), ec);
444  
    }
444  
    }
445  

445  

446  
    /** Overload
446  
    /** Overload
447  
        @param s
447  
        @param s
448  
    */
448  
    */
449  
    std::size_t
449  
    std::size_t
450  
    write_some(
450  
    write_some(
451  
        string_view s)
451  
        string_view s)
452  
    {
452  
    {
453  
        return write_some(
453  
        return write_some(
454  
            s.data(), s.size());
454  
            s.data(), s.size());
455  
    }
455  
    }
456  
    /// @}
456  
    /// @}
457  

457  

458  
    /** Parse a buffer containing all or part of a complete JSON text.
458  
    /** Parse a buffer containing all or part of a complete JSON text.
459  

459  

460  
        This function parses all or part of a JSON text contained in the
460  
        This function parses all or part of a JSON text contained in the
461  
        specified character buffer. The entire buffer must be consumed; if
461  
        specified character buffer. The entire buffer must be consumed; if
462  
        there are additional characters past the end of the complete JSON text,
462  
        there are additional characters past the end of the complete JSON text,
463  
        the parse fails and an error is returned.
463  
        the parse fails and an error is returned.
464  

464  

465  
        Overloads **(1)**, **(2)**, **(4)**, and **(5)** report errors by
465  
        Overloads **(1)**, **(2)**, **(4)**, and **(5)** report errors by
466  
        setting `ec`. Overloads **(3)** and **(6)** report errors by throwing
466  
        setting `ec`. Overloads **(3)** and **(6)** report errors by throwing
467  
        exceptions. Upon error or exception, subsequent calls will fail until
467  
        exceptions. Upon error or exception, subsequent calls will fail until
468  
        @ref reset is called to parse a new JSON text.
468  
        @ref reset is called to parse a new JSON text.
469  

469  

470  
        @note To indicate there are no more character buffers, such as when
470  
        @note To indicate there are no more character buffers, such as when
471  
        @ref done returns `false` after writing, call @ref finish.
471  
        @ref done returns `false` after writing, call @ref finish.
472  

472  

473  
        @par Example
473  
        @par Example
474  
        @code
474  
        @code
475  
        stream_parser p;                                // construct a parser
475  
        stream_parser p;                                // construct a parser
476  
        std::size_t n;                                  // number of characters used
476  
        std::size_t n;                                  // number of characters used
477  
        n = p.write( "[1,2" );                          // parse some of the JSON text
477  
        n = p.write( "[1,2" );                          // parse some of the JSON text
478  
        assert( n == 4 );                               // all characters consumed
478  
        assert( n == 4 );                               // all characters consumed
479  
        n = p.write( "3,4]" );                          // parse the rest of the JSON text
479  
        n = p.write( "3,4]" );                          // parse the rest of the JSON text
480  
        assert( n == 4 );                               // all characters consumed
480  
        assert( n == 4 );                               // all characters consumed
481  
        value jv = p.release();                         // take ownership of the value
481  
        value jv = p.release();                         // take ownership of the value
482  
        @endcode
482  
        @endcode
483  

483  

484  
        @par Complexity
484  
        @par Complexity
485  
        @li **(1)**--**(3)** linear in `size`.
485  
        @li **(1)**--**(3)** linear in `size`.
486  
        @li **(4)**--**(6)** linear in `s.size()`.
486  
        @li **(4)**--**(6)** linear in `s.size()`.
487  

487  

488  
        @par Exception Safety
488  
        @par Exception Safety
489  
        Basic guarantee. Calls to `memory_resource::allocate` may throw.
489  
        Basic guarantee. Calls to `memory_resource::allocate` may throw.
490  
        @return The number of characters consumed from the buffer.
490  
        @return The number of characters consumed from the buffer.
491  

491  

492  
        @param data A pointer to a buffer of `size` characters to parse.
492  
        @param data A pointer to a buffer of `size` characters to parse.
493  

493  

494  
        @param size The number of characters pointed to by `data`.
494  
        @param size The number of characters pointed to by `data`.
495  

495  

496  
        @param ec Set to the error, if any occurred.
496  
        @param ec Set to the error, if any occurred.
497  

497  

498  
        @{
498  
        @{
499  
    */
499  
    */
500  
    BOOST_JSON_DECL
500  
    BOOST_JSON_DECL
501  
    std::size_t
501  
    std::size_t
502  
    write(
502  
    write(
503  
        char const* data,
503  
        char const* data,
504  
        std::size_t size,
504  
        std::size_t size,
505  
        system::error_code& ec);
505  
        system::error_code& ec);
506  

506  

507  
    BOOST_JSON_DECL
507  
    BOOST_JSON_DECL
508  
    std::size_t
508  
    std::size_t
509  
    write(
509  
    write(
510  
        char const* data,
510  
        char const* data,
511  
        std::size_t size,
511  
        std::size_t size,
512  
        std::error_code& ec);
512  
        std::error_code& ec);
513  

513  

514  
    /** Overload
514  
    /** Overload
515  

515  

516  
        @param data
516  
        @param data
517  
        @param size
517  
        @param size
518  

518  

519  
        @throw boost::system::system_error Thrown on error.
519  
        @throw boost::system::system_error Thrown on error.
520  
    */
520  
    */
521  
    BOOST_JSON_DECL
521  
    BOOST_JSON_DECL
522  
    std::size_t
522  
    std::size_t
523  
    write(
523  
    write(
524  
        char const* data,
524  
        char const* data,
525  
        std::size_t size);
525  
        std::size_t size);
526  

526  

527  
    /** Overload
527  
    /** Overload
528  

528  

529  
        @param s The character string to parse.
529  
        @param s The character string to parse.
530  
        @param ec
530  
        @param ec
531  
    */
531  
    */
532  
    std::size_t
532  
    std::size_t
533  
    write(
533  
    write(
534  
        string_view s,
534  
        string_view s,
535  
        system::error_code& ec)
535  
        system::error_code& ec)
536  
    {
536  
    {
537  
        return write(
537  
        return write(
538  
            s.data(), s.size(), ec);
538  
            s.data(), s.size(), ec);
539  
    }
539  
    }
540  

540  

541  
    /** Overload
541  
    /** Overload
542  

542  

543  
        @param s
543  
        @param s
544  
        @param ec
544  
        @param ec
545  
    */
545  
    */
546  
    std::size_t
546  
    std::size_t
547  
    write(
547  
    write(
548  
        string_view s,
548  
        string_view s,
549  
        std::error_code& ec)
549  
        std::error_code& ec)
550  
    {
550  
    {
551  
        return write(
551  
        return write(
552  
            s.data(), s.size(), ec);
552  
            s.data(), s.size(), ec);
553  
    }
553  
    }
554  

554  

555  
    /** Overload
555  
    /** Overload
556  
        @param s
556  
        @param s
557  
    */
557  
    */
558  
    std::size_t
558  
    std::size_t
559  
    write(
559  
    write(
560  
        string_view s)
560  
        string_view s)
561  
    {
561  
    {
562  
        return write(
562  
        return write(
563  
            s.data(), s.size());
563  
            s.data(), s.size());
564  
    }
564  
    }
565  
    /// @}
565  
    /// @}
566  

566  

567  
    /** Indicate the end of JSON input.
567  
    /** Indicate the end of JSON input.
568  

568  

569  
        This function is used to indicate that there are no more character
569  
        This function is used to indicate that there are no more character
570  
        buffers in the current JSON text being parsed. If the resulting JSON
570  
        buffers in the current JSON text being parsed. If the resulting JSON
571  
        text is incomplete, **(1)** and **(2)** assign the relevant
571  
        text is incomplete, **(1)** and **(2)** assign the relevant
572  
        `error_code` to `ec`, while **(3)** throws an exception.
572  
        `error_code` to `ec`, while **(3)** throws an exception.
573  

573  

574  
        Upon error or exception, subsequent calls will fail until @ref reset is
574  
        Upon error or exception, subsequent calls will fail until @ref reset is
575  
        called to parse a new JSON text.
575  
        called to parse a new JSON text.
576  

576  

577  
        @par Example
577  
        @par Example
578  
        In the code below, @ref finish is called to
578  
        In the code below, @ref finish is called to
579  
        indicate there are no more digits in the
579  
        indicate there are no more digits in the
580  
        resulting number:
580  
        resulting number:
581  
        @code
581  
        @code
582  
        stream_parser p;                                // construct a parser
582  
        stream_parser p;                                // construct a parser
583  
        p.write( "3." );                                // write the first part of the number
583  
        p.write( "3." );                                // write the first part of the number
584  
        p.write( "14" );                                // write the second part of the number
584  
        p.write( "14" );                                // write the second part of the number
585  
        assert( ! p.done() );                           // there could be more digits
585  
        assert( ! p.done() );                           // there could be more digits
586  
        p.finish();                                     // indicate the end of the JSON input
586  
        p.finish();                                     // indicate the end of the JSON input
587  
        assert( p.done() );                             // now we are finished
587  
        assert( p.done() );                             // now we are finished
588  
        value jv = p.release();                         // take ownership of the value
588  
        value jv = p.release();                         // take ownership of the value
589  
        @endcode
589  
        @endcode
590  

590  

591  
        @par Complexity
591  
        @par Complexity
592  
        Constant.
592  
        Constant.
593  

593  

594  
        @par Exception Safety
594  
        @par Exception Safety
595  
        Basic guarantee. Calls to `memory_resource::allocate` may throw.
595  
        Basic guarantee. Calls to `memory_resource::allocate` may throw.
596  

596  

597  
        @param ec Set to the error, if any occurred.
597  
        @param ec Set to the error, if any occurred.
598  

598  

599  
        @{
599  
        @{
600  
    */
600  
    */
601  
    BOOST_JSON_DECL
601  
    BOOST_JSON_DECL
602  
    void
602  
    void
603  
    finish(system::error_code& ec);
603  
    finish(system::error_code& ec);
604  

604  

605  
    BOOST_JSON_DECL
605  
    BOOST_JSON_DECL
606  
    void
606  
    void
607  
    finish(std::error_code& ec);
607  
    finish(std::error_code& ec);
608  

608  

609  
    /** Overload
609  
    /** Overload
610  

610  

611  
        @throw boost::system::system_error Parsing error.
611  
        @throw boost::system::system_error Parsing error.
612  
    */
612  
    */
613  
    BOOST_JSON_DECL
613  
    BOOST_JSON_DECL
614  
    void
614  
    void
615  
    finish();
615  
    finish();
616  
    /// @}
616  
    /// @}
617  

617  

618  
    /** Return the parsed JSON as a @ref value.
618  
    /** Return the parsed JSON as a @ref value.
619  

619  

620  
        This returns the parsed value, or throws an exception if the parsing is
620  
        This returns the parsed value, or throws an exception if the parsing is
621  
        incomplete or failed. If `! this->done()`, calls @ref finish() first.
621  
        incomplete or failed. If `! this->done()`, calls @ref finish() first.
622  
        It is necessary to call @ref reset after calling this function in order
622  
        It is necessary to call @ref reset after calling this function in order
623  
        to parse another JSON text.
623  
        to parse another JSON text.
624  

624  

625  
        @par Complexity
625  
        @par Complexity
626  
        Constant.
626  
        Constant.
627  

627  

628  
        @return The parsed value. Ownership of this value is transferred to the
628  
        @return The parsed value. Ownership of this value is transferred to the
629  
        caller.
629  
        caller.
630  

630  

631  
        @throw boost::system::system_error A complete JSON text hasn't been
631  
        @throw boost::system::system_error A complete JSON text hasn't been
632  
               parsed, or parsing failed.
632  
               parsed, or parsing failed.
633  
    */
633  
    */
634  
    BOOST_JSON_DECL
634  
    BOOST_JSON_DECL
635  
    value
635  
    value
636  
    release();
636  
    release();
637  
};
637  
};
638  

638  

639  
} // namespace json
639  
} // namespace json
640  
} // namespace boost
640  
} // namespace boost
641  

641  

642  
#endif
642  
#endif