liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/json
//
 
#ifndef BOOST_JSON_SERIALIZER_HPP
#define BOOST_JSON_SERIALIZER_HPP
 
#include <boost/json/detail/config.hpp>
#include <boost/json/value.hpp>
#include <boost/json/detail/format.hpp>
#include <boost/json/detail/stack.hpp>
#include <boost/json/detail/stream.hpp>
 
BOOST_JSON_NS_BEGIN
 
/** A serializer for JSON.
 
    This class traverses an instance of a library
    type and emits serialized JSON text by filling
    in one or more caller-provided buffers. To use,
    declare a variable and call @ref reset with
    a pointer to the variable you want to serialize.
    Then call @ref read over and over until
    @ref done returns `true`.
 
    @par Example
 
    This demonstrates how the serializer may
    be used to print a JSON value to an output
    stream.
 
    @code
 
    void print( std::ostream& os, value const& jv)
    {
        serializer sr;
        sr.reset( &jv );
        while( ! sr.done() )
        {
            char buf[ 4000 ];
            os << sr.read( buf );
        }
    }
 
    @endcode
 
    @par Thread Safety
 
    The same instance may not be accessed concurrently.
*/
class serializer
{
    enum class state : char;
    // VFALCO Too many streams
    using stream = detail::stream;
    using const_stream = detail::const_stream;
    using local_stream = detail::local_stream;
    using local_const_stream =
        detail::local_const_stream;
 
    using fn_t = bool (serializer::*)(stream&);
 
#ifndef BOOST_JSON_DOCS
    union
    {
        value const* pv_;
        array const* pa_;
        object const* po_;
    };
#endif
    fn_t fn0_ = &serializer::write_null<true>;
    fn_t fn1_ = &serializer::write_null<false>;
    value const* jv_ = nullptr;
    detail::stack st_;
    const_stream cs0_;
    char buf_[detail::max_number_chars + 1];
    bool done_ = false;
 
    inline bool suspend(state st);
    inline bool suspend(
        state st, array::const_iterator it, array const* pa);
    inline bool suspend(
        state st, object::const_iterator it, object const* po);
    template<bool StackEmpty> bool write_null   (stream& ss);
    template<bool StackEmpty> bool write_true   (stream& ss);
    template<bool StackEmpty> bool write_false  (stream& ss);
    template<bool StackEmpty> bool write_string (stream& ss);
    template<bool StackEmpty> bool write_number (stream& ss);
    template<bool StackEmpty> bool write_array  (stream& ss);
    template<bool StackEmpty> bool write_object (stream& ss);
    template<bool StackEmpty> bool write_value  (stream& ss);
    inline string_view read_some(char* dest, std::size_t size);
 
public:
    /// Move constructor (deleted)
    serializer(serializer&&) = delete;
 
    /** Destructor
 
        All temporary storage is deallocated.
 
        @par Complexity
        Constant
 
        @par Exception Safety
        No-throw guarantee.
    */
    BOOST_JSON_DECL
    ~serializer() noexcept;
 
    /** Default constructor
 
        This constructs a serializer with no value.
        The value may be set later by calling @ref reset.
        If serialization is attempted with no value,
        the output is as if a null value is serialized.
 
        @par Complexity
        Constant.
 
        @par Exception Safety
        No-throw guarantee.
    */
    BOOST_JSON_DECL
    serializer() noexcept;
 
    /** Returns `true` if the serialization is complete
 
        This function returns `true` when all of the
        characters in the serialized representation of
        the value have been read.
 
        @par Complexity
        Constant.
 
        @par Exception Safety
        No-throw guarantee.
    */
    bool
    done() const noexcept
    {
        return done_;
    }
 
    /** Reset the serializer for a new element
 
        This function prepares the serializer to emit
        a new serialized JSON representing `*p`.
        Any internally allocated memory is
        preserved and re-used for the new output.
 
        @param p A pointer to the element to serialize.
        Ownership is not transferred; The caller is
        responsible for ensuring that the lifetime of
        `*p` extends until it is no longer needed.
    */
    /** @{ */
    BOOST_JSON_DECL
    void
    reset(value const* p) noexcept;
 
    BOOST_JSON_DECL
    void
    reset(array const* p) noexcept;
 
    BOOST_JSON_DECL
    void
    reset(object const* p) noexcept;
 
    BOOST_JSON_DECL
    void
    reset(string const* p) noexcept;
    /** @} */
 
    /** Reset the serializer for a new string
 
        This function prepares the serializer to emit
        a new serialized JSON representing the string.
        Any internally allocated memory is
        preserved and re-used for the new output.
 
        @param sv The characters representing the string.
        Ownership is not transferred; The caller is
        responsible for ensuring that the lifetime of
        the characters reference by `sv` extends
        until it is no longer needed.
    */
    BOOST_JSON_DECL
    void
    reset(string_view sv) noexcept;
 
    /** Read the next buffer of serialized JSON
 
        This function attempts to fill the caller
        provided buffer starting at `dest` with
        up to `size` characters of the serialized
        JSON that represents the value. If the
        buffer is not large enough, multiple calls
        may be required.
\n
        If serialization completes during this call;
        that is, that all of the characters belonging
        to the serialized value have been written to
        caller-provided buffers, the function
        @ref done will return `true`.
 
        @par Preconditions
        `this->done() == true`
 
        @par Complexity
        Linear in `size`.
 
        @par Exception Safety
        Basic guarantee.
        Calls to `memory_resource::allocate` may throw.
 
        @return A @ref string_view containing the
        characters written, which may be less than
        `size`.
 
        @param dest A pointer to valid memory of at
        least `size` bytes.
 
        @param size The maximum number of characters
        to write to the memory pointed to by `dest`.
    */
    BOOST_JSON_DECL
    string_view
    read(char* dest, std::size_t size);
 
    /** Read the next buffer of serialized JSON
 
        This function allows reading into a
        character array, with a deduced maximum size.
 
        @par Preconditions
        `this->done() == true`
 
        @par Effects
        @code
        return this->read( dest, N );
        @endcode
 
        @par Complexity
        Linear in `N`.
 
        @par Exception Safety
        Basic guarantee.
        Calls to `memory_resource::allocate` may throw.
 
        @return A @ref string_view containing the
        characters written, which may be less than
        `size`.
 
        @param dest The character array to write to.
    */
    template<std::size_t N>
    string_view
    read(char(&dest)[N])
    {
        return read(dest, N);
    }
 
#ifndef BOOST_JSON_DOCS
    // Safety net for accidental buffer overflows
    template<std::size_t N>
    string_view
    read(char(&dest)[N], std::size_t n)
    {
        // If this goes off, check your parameters
        // closely, chances are you passed an array
        // thinking it was a pointer.
        BOOST_ASSERT(n <= N);
        return read(dest, n);
    }
#endif
};
 
BOOST_JSON_NS_END
 
#endif