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_SERIALIZER_HPP
10  
#ifndef BOOST_JSON_SERIALIZER_HPP
11  
#define BOOST_JSON_SERIALIZER_HPP
11  
#define BOOST_JSON_SERIALIZER_HPP
12  

12  

13  
#include <boost/json/detail/config.hpp>
13  
#include <boost/json/detail/config.hpp>
14  
#include <boost/json/detail/format.hpp>
14  
#include <boost/json/detail/format.hpp>
15  
#include <boost/json/detail/stream.hpp>
15  
#include <boost/json/detail/stream.hpp>
16  
#include <boost/json/detail/writer.hpp>
16  
#include <boost/json/detail/writer.hpp>
17  
#include <boost/json/serialize_options.hpp>
17  
#include <boost/json/serialize_options.hpp>
18  
#include <boost/json/value.hpp>
18  
#include <boost/json/value.hpp>
19  

19  

20  
namespace boost {
20  
namespace boost {
21  
namespace json {
21  
namespace json {
22  

22  

23  
/** A serializer for JSON.
23  
/** A serializer for JSON.
24  

24  

25 -
    This class traverses an instance of a library type and emits serialized
25 +
    This class traverses an instance of a library
26 -
    JSON text by filling in one or more caller-provided buffers. To use,
26 +
    type and emits serialized JSON text by filling
27 -
    declare a variable and call @ref reset with a pointer to the variable you
27 +
    in one or more caller-provided buffers. To use,
28 -
    want to serialize. Then call @ref read over and over until @ref done
28 +
    declare a variable and call @ref reset with
29 -
    returns `true`.
29 +
    a pointer to the variable you want to serialize.
 
30 +
    Then call @ref read over and over until
 
31 +
    @ref done returns `true`.
30  

32  

31  
    @par Example
33  
    @par Example
32 -
    This demonstrates how the serializer may be used to print a JSON value to
34 +

33 -
    an output stream.
35 +
    This demonstrates how the serializer may
 
36 +
    be used to print a JSON value to an output
 
37 +
    stream.
34  

38  

35  
    @code
39  
    @code
 
40 +

36  
    void print( std::ostream& os, value const& jv)
41  
    void print( std::ostream& os, value const& jv)
37  
    {
42  
    {
38  
        serializer sr;
43  
        serializer sr;
39  
        sr.reset( &jv );
44  
        sr.reset( &jv );
40  
        while( ! sr.done() )
45  
        while( ! sr.done() )
41  
        {
46  
        {
42  
            char buf[ 4000 ];
47  
            char buf[ 4000 ];
43  
            os << sr.read( buf );
48  
            os << sr.read( buf );
44  
        }
49  
        }
45  
    }
50  
    }
 
51 +

46  
    @endcode
52  
    @endcode
47  

53  

48 -
    The same instance may not be accessed concurrently.
 
49  
    @par Thread Safety
54  
    @par Thread Safety
50  

55  

51 -
    @par Non-Standard JSON
56 +
    The same instance may not be accessed concurrently.
52 -
    The @ref serialize_options structure optionally provided upon construction
 
53 -
    is used to enable non-standard JSON extensions. A default-constructed
 
54 -
    `serialize_options` doesn't enable any extensions.
 
55 -

 
56 -
    @see @ref serialize.
 
57  
*/
57  
*/
58  
class serializer
58  
class serializer
59  
    : detail::writer
59  
    : detail::writer
60  
{
60  
{
61  
    using fn_t = bool (*)(writer&, detail::stream&);
61  
    using fn_t = bool (*)(writer&, detail::stream&);
62  

62  

63  
    fn_t fn0_ = nullptr;
63  
    fn_t fn0_ = nullptr;
64  
    fn_t fn1_ = nullptr;
64  
    fn_t fn1_ = nullptr;
65  
    bool done_ = false;
65  
    bool done_ = false;
66  

66  

67  
public:
67  
public:
 
68 +
    /// Move constructor (deleted)
 
69 +
    serializer(serializer&&) = delete;
 
70 +

68  
    /** Destructor
71  
    /** Destructor
69  

72  

70  
        All temporary storage is deallocated.
73  
        All temporary storage is deallocated.
71  

74  

72  
        @par Complexity
75  
        @par Complexity
73  
        Constant
76  
        Constant
74  

77  

75  
        @par Exception Safety
78  
        @par Exception Safety
76  
        No-throw guarantee.
79  
        No-throw guarantee.
77  
    */
80  
    */
78  
#ifdef BOOST_JSON_DOCS
81  
#ifdef BOOST_JSON_DOCS
79  
    BOOST_JSON_DECL
82  
    BOOST_JSON_DECL
80  
    ~serializer() noexcept;
83  
    ~serializer() noexcept;
81  
#endif // BOOST_JSON_DOCS
84  
#endif // BOOST_JSON_DOCS
82  

85  

83 -
    /** Constructors.
86 +
    /** Constructor
84 -

 
85 -
        The serializer is constructed with no value to serialize The value may
 
86 -
        be set later by calling @ref reset. If serialization is attempted with
 
87 -
        no value, the output is as if a null value is serialized.
 
88  

87  

89 -
        Overload **(3)** is a move constructor. The type is neither copyable
88 +
        This constructs a serializer with no value.
90 -
        nor movable, so this constructor is deleted.
89 +
        The value may be set later by calling @ref reset.
 
90 +
        If serialization is attempted with no value,
 
91 +
        the output is as if a null value is serialized.
91  

92  

92  
        @par Complexity
93  
        @par Complexity
93  
        Constant.
94  
        Constant.
94  

95  

95  
        @par Exception Safety
96  
        @par Exception Safety
96  
        No-throw guarantee.
97  
        No-throw guarantee.
97  

98  

98 -
        @param opts The options for the serializer. If this parameter is
99 +
        @param opts The options for the serializer. If this parameter
99 -
        omitted, the serializer will output only standard JSON.
100 +
        is omitted, the serializer will output only standard JSON.
100 -

 
101 -
        @{
 
102  
    */
101  
    */
103  
    BOOST_JSON_DECL
102  
    BOOST_JSON_DECL
104  
    serializer( serialize_options const& opts = {} ) noexcept;
103  
    serializer( serialize_options const& opts = {} ) noexcept;
105  

104  

106 -
    /** Overload
105 +
    /** Constructor
107  

106  

108 -
        @param sp A pointer to the @ref boost::container::pmr::memory_resource
107 +
        This constructs a serializer with no value.
109 -
        to use when producing partial output. Shared ownership of the memory
108 +
        The value may be set later by calling @ref reset.
 
109 +
        If serialization is attempted with no value,
 
110 +
        the output is as if a null value is serialized.
 
111 +

 
112 +
        @par Complexity
 
113 +
        Constant.
 
114 +

 
115 +
        @par Exception Safety
 
116 +
        No-throw guarantee.
 
117 +

 
118 +
        @param sp A pointer to the `boost::container::pmr::memory_resource` to
 
119 +
        use when producing partial output. Shared ownership of the memory
110  
        resource is retained until the serializer is destroyed.
120  
        resource is retained until the serializer is destroyed.
111  

121  

112 -
        @param buf An optional static buffer to use for temporary storage when
122 +
        @param buf An optional static buffer to
113 -
        producing partial output.
123 +
        use for temporary storage when producing
 
124 +
        partial output.
114  

125  

115 -
        @param size The number of bytes of valid memory pointed to by
126 +
        @param buf_size The number of bytes of
116 -
        `buf`.
127 +
        valid memory pointed to by `buf`.
117  

128  

118 -
        @param opts
129 +
        @param opts The options for the serializer. If this parameter
 
130 +
        is omitted, the serializer will output only standard JSON.
119  
    */
131  
    */
120  
    BOOST_JSON_DECL
132  
    BOOST_JSON_DECL
121  
    serializer(
133  
    serializer(
122  
        storage_ptr sp,
134  
        storage_ptr sp,
123  
        unsigned char* buf = nullptr,
135  
        unsigned char* buf = nullptr,
124 -
        std::size_t size = 0,
136 +
        std::size_t buf_size = 0,
125  
        serialize_options const& opts = {}) noexcept;
137  
        serialize_options const& opts = {}) noexcept;
126  

138  

127 -
    /// Overload
139 +
    /** Returns `true` if the serialization is complete
128 -
    serializer(serializer&&) = delete;
 
129 -
    /// @}
 
130 -

 
131 -
    /** Check if the serialization is complete.
 
132  

140  

133 -
        This function returns `true` when all of the characters in the
141 +
        This function returns `true` when all of the
134 -
        serialized representation of the value have been read.
142 +
        characters in the serialized representation of
 
143 +
        the value have been read.
135  

144  

136  
        @par Complexity
145  
        @par Complexity
137  
        Constant.
146  
        Constant.
138  

147  

139  
        @par Exception Safety
148  
        @par Exception Safety
140  
        No-throw guarantee.
149  
        No-throw guarantee.
141  
    */
150  
    */
142  
    bool
151  
    bool
143  
    done() const noexcept
152  
    done() const noexcept
144  
    {
153  
    {
145  
        return done_;
154  
        return done_;
146  
    }
155  
    }
147  

156  

148 -
    /** Reset the serializer for a new element.
157 +
    /** Reset the serializer for a new element
149 -

 
150 -
        This function prepares the serializer to emit a new serialized JSON
 
151 -
        representing its argument: `*p` **(1)**--**(5)**, `sv` **(6)**, or
 
152 -
        `np` **(7)**. Ownership is not transferred. The caller is responsible
 
153 -
        for ensuring that the lifetime of the object pointed to by the argument
 
154 -
        extends until it is no longer needed.
 
155 -

 
156 -
        Any memory internally allocated for previous uses of this `serializer`
 
157 -
        object is preserved and re-used for the new output.
 
158  

158  

159 -
        Overload **(5)** uses \<\<direct_conversion,direct serialization\>\>.
159 +
        This function prepares the serializer to emit
 
160 +
        a new serialized JSON representing `*p`.
 
161 +
        Any internally allocated memory is
 
162 +
        preserved and re-used for the new output.
160  

163  

161  
        @param p A pointer to the element to serialize.
164  
        @param p A pointer to the element to serialize.
162 -

165 +
        Ownership is not transferred; The caller is
163 -
        @{
166 +
        responsible for ensuring that the lifetime of
 
167 +
        `*p` extends until it is no longer needed.
164  
    */
168  
    */
 
169 +
    /** @{ */
165  
    BOOST_JSON_DECL
170  
    BOOST_JSON_DECL
166  
    void
171  
    void
167  
    reset(value const* p) noexcept;
172  
    reset(value const* p) noexcept;
168  

173  

169  
    BOOST_JSON_DECL
174  
    BOOST_JSON_DECL
170  
    void
175  
    void
171  
    reset(array const* p) noexcept;
176  
    reset(array const* p) noexcept;
172  

177  

173  
    BOOST_JSON_DECL
178  
    BOOST_JSON_DECL
174  
    void
179  
    void
175  
    reset(object const* p) noexcept;
180  
    reset(object const* p) noexcept;
176  

181  

177  
    BOOST_JSON_DECL
182  
    BOOST_JSON_DECL
178  
    void
183  
    void
179  
    reset(string const* p) noexcept;
184  
    reset(string const* p) noexcept;
180  

185  

181  
    template<class T>
186  
    template<class T>
182  
    void
187  
    void
183  
    reset(T const* p) noexcept;
188  
    reset(T const* p) noexcept;
 
189 +
    /** @} */
184  

190  

185 -
    /** Overload
191 +
    /** Reset the serializer for a new string
186  

192  

187 -
        @param sv The characters representing a string.
193 +
        This function prepares the serializer to emit
 
194 +
        a new serialized JSON representing the string.
 
195 +
        Any internally allocated memory is
 
196 +
        preserved and re-used for the new output.
 
197 +

 
198 +
        @param sv The characters representing the string.
 
199 +
        Ownership is not transferred; The caller is
 
200 +
        responsible for ensuring that the lifetime of
 
201 +
        the characters reference by `sv` extends
 
202 +
        until it is no longer needed.
188  
    */
203  
    */
189  
    BOOST_JSON_DECL
204  
    BOOST_JSON_DECL
190  
    void
205  
    void
191  
    reset(string_view sv) noexcept;
206  
    reset(string_view sv) noexcept;
192  

207  

193 -
    /** Overload
208 +
    /** Reset the serializer for std::nullptr_t
194  

209  

195 -
        @param np Represents a null value.
210 +
        This function prepares the serializer to emit
 
211 +
        a new serialized JSON representing null.
 
212 +
        Any internally allocated memory is
 
213 +
        preserved and re-used for the new output.
196  
    */
214  
    */
197  
    BOOST_JSON_DECL
215  
    BOOST_JSON_DECL
198  
    void
216  
    void
199 -
    reset(std::nullptr_t np) noexcept;
217 +
    reset(std::nullptr_t) noexcept;
200 -
    /// @}
 
201  

218  

202 -
    /** Read the next buffer of serialized JSON.
219 +
    /** Read the next buffer of serialized JSON
203  

220  

204 -
        This function attempts to fill the caller provided buffer starting at
221 +
        This function attempts to fill the caller
205 -
        `dest` with up to `size` characters of the serialized JSON that
222 +
        provided buffer starting at `dest` with
206 -
        represents the value. If the buffer is not large enough, multiple calls
223 +
        up to `size` characters of the serialized
 
224 +
        JSON that represents the value. If the
 
225 +
        buffer is not large enough, multiple calls
207  
        may be required.
226  
        may be required.
 
227 +
\n
 
228 +
        If serialization completes during this call;
 
229 +
        that is, that all of the characters belonging
 
230 +
        to the serialized value have been written to
 
231 +
        caller-provided buffers, the function
 
232 +
        @ref done will return `true`.
208  

233  

209 -
        If serialization completes during this call; that is, that all of the
234 +
        @par Preconditions
210 -
        characters belonging to the serialized value have been written to
 
211 -
        caller-provided buffers, the function @ref done will return `true`.
 
212 -

 
213 -
        @pre
 
214  
        @code
235  
        @code
215 -
        done() == false
236 +
        this->done() == false
216  
        @endcode
237  
        @endcode
217  

238  

218  
        @par Complexity
239  
        @par Complexity
219 -
        @li **(1)** linear in `size`.
240 +
        Linear in `size`.
220 -
        @li **(2)** linear in `N`.
 
221  

241  

222  
        @par Exception Safety
242  
        @par Exception Safety
223 -
        Basic guarantee. Calls to `memory_resource::allocate` may throw.
243 +
        Basic guarantee.
224 -

244 +
        Calls to `memory_resource::allocate` may throw.
225 -
        @return A @ref string_view containing the characters written, which may
 
226 -
        be less than `size` or `N`.
 
227  

245  

228 -
        @param dest A pointer to storage to write into.
246 +
        @return A @ref string_view containing the
 
247 +
        characters written, which may be less than
 
248 +
        `size`.
229  

249  

230 -
        @param size The maximum number of characters to write to the memory
250 +
        @param dest A pointer to valid memory of at
231 -
        pointed to by `dest`.
251 +
        least `size` bytes.
232  

252  

233 -
        @{
253 +
        @param size The maximum number of characters
 
254 +
        to write to the memory pointed to by `dest`.
234  
    */
255  
    */
235  
    BOOST_JSON_DECL
256  
    BOOST_JSON_DECL
236  
    string_view
257  
    string_view
237  
    read(char* dest, std::size_t size);
258  
    read(char* dest, std::size_t size);
238  

259  

239 -
    /** Overload
260 +
    /** Read the next buffer of serialized JSON
240  

261  

241 -
        @tparam N The size of the array `dest`.
262 +
        This function allows reading into a
242 -
        @param dest
263 +
        character array, with a deduced maximum size.
 
264 +

 
265 +
        @par Preconditions
 
266 +
        @code
 
267 +
        this->done() == false
 
268 +
        @endcode
 
269 +

 
270 +
        @par Effects
 
271 +
        @code
 
272 +
        return this->read( dest, N );
 
273 +
        @endcode
 
274 +

 
275 +
        @par Complexity
 
276 +
        Linear in `N`.
 
277 +

 
278 +
        @par Exception Safety
 
279 +
        Basic guarantee.
 
280 +
        Calls to `memory_resource::allocate` may throw.
 
281 +

 
282 +
        @return A @ref string_view containing the
 
283 +
        characters written, which may be less than
 
284 +
        `size`.
 
285 +

 
286 +
        @param dest The character array to write to.
243  
    */
287  
    */
244  
    template<std::size_t N>
288  
    template<std::size_t N>
245  
    string_view
289  
    string_view
246  
    read(char(&dest)[N])
290  
    read(char(&dest)[N])
247  
    {
291  
    {
248  
        return read(dest, N);
292  
        return read(dest, N);
249 -
    /// @}
 
250  
    }
293  
    }
251  

294  

252  
#ifndef BOOST_JSON_DOCS
295  
#ifndef BOOST_JSON_DOCS
253  
    // Safety net for accidental buffer overflows
296  
    // Safety net for accidental buffer overflows
254  
    template<std::size_t N>
297  
    template<std::size_t N>
255  
    string_view
298  
    string_view
256  
    read(char(&dest)[N], std::size_t n)
299  
    read(char(&dest)[N], std::size_t n)
257  
    {
300  
    {
258  
        // If this goes off, check your parameters
301  
        // If this goes off, check your parameters
259  
        // closely, chances are you passed an array
302  
        // closely, chances are you passed an array
260  
        // thinking it was a pointer.
303  
        // thinking it was a pointer.
261  
        BOOST_ASSERT(n <= N);
304  
        BOOST_ASSERT(n <= N);
262  
        return read(dest, n);
305  
        return read(dest, n);
263  
    }
306  
    }
264  
#endif
307  
#endif
265  
};
308  
};
266  

309  

267  
} // namespace json
310  
} // namespace json
268  
} // namespace boost
311  
} // namespace boost
269  

312  

270  
#include <boost/json/impl/serializer.hpp>
313  
#include <boost/json/impl/serializer.hpp>
271  

314  

272  
#endif
315  
#endif