Coverage Report

Created: 2023-03-26 06:57

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