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