/src/boost/boost/json/impl/serializer.ipp
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_IMPL_SERIALIZER_IPP |
11 | | #define BOOST_JSON_IMPL_SERIALIZER_IPP |
12 | | |
13 | | #include <boost/core/detail/static_assert.hpp> |
14 | | #include <boost/json/serializer.hpp> |
15 | | #include <boost/json/detail/format.hpp> |
16 | | #include <boost/json/detail/sse2.hpp> |
17 | | |
18 | | #ifdef _MSC_VER |
19 | | #pragma warning(push) |
20 | | #pragma warning(disable: 4127) // conditional expression is constant |
21 | | #endif |
22 | | |
23 | | namespace boost { |
24 | | namespace json { |
25 | | namespace detail { |
26 | | |
27 | | struct int64_formatter |
28 | | { |
29 | | std::int64_t i; |
30 | | |
31 | | std::size_t |
32 | | operator()(char* dst) const noexcept |
33 | 3.68M | { |
34 | 3.68M | return format_int64(dst, i); |
35 | 3.68M | } |
36 | | }; |
37 | | |
38 | | struct uint64_formatter |
39 | | { |
40 | | std::uint64_t u; |
41 | | |
42 | | std::size_t |
43 | | operator()(char* dst) const noexcept |
44 | 24.5k | { |
45 | 24.5k | return format_uint64(dst, u); |
46 | 24.5k | } |
47 | | }; |
48 | | |
49 | | struct double_formatter |
50 | | { |
51 | | double d; |
52 | | bool allow_infinity_and_nan; |
53 | | |
54 | | std::size_t |
55 | | operator()(char* dst) const noexcept |
56 | 6.42M | { |
57 | 6.42M | return format_double(dst, d, allow_infinity_and_nan); |
58 | 6.42M | } |
59 | | }; |
60 | | |
61 | | writer:: |
62 | | writer( |
63 | | storage_ptr sp, |
64 | | unsigned char* buf, |
65 | | std::size_t buf_size, |
66 | | serialize_options const& opts) noexcept |
67 | 7.07k | : st_( |
68 | 7.07k | std::move(sp), |
69 | 7.07k | buf, |
70 | 7.07k | buf_size) |
71 | 7.07k | , opts_(opts) |
72 | 7.07k | { |
73 | | // ensure room for \uXXXX escape plus one |
74 | 7.07k | BOOST_CORE_STATIC_ASSERT( sizeof(buf_) >= 7 ); |
75 | 7.07k | } |
76 | | |
77 | | bool |
78 | | BOOST_FORCEINLINE |
79 | | write_buffer(writer& w, stream& ss0) |
80 | 5.62k | { |
81 | 5.62k | local_stream ss(ss0); |
82 | 5.62k | auto const n = ss.remain(); |
83 | 5.62k | if( n < w.cs0_.remain() ) |
84 | 1.16k | { |
85 | 1.16k | ss.append(w.cs0_.data(), n); |
86 | 1.16k | w.cs0_.skip(n); |
87 | 1.16k | return w.suspend(writer::state::lit); |
88 | 1.16k | } |
89 | 4.45k | ss.append( w.cs0_.data(), w.cs0_.remain() ); |
90 | 4.45k | return true; |
91 | 5.62k | } |
92 | | |
93 | | template< class F > |
94 | | bool |
95 | | write_buffer(writer& w, stream& ss0, F f) |
96 | 10.1M | { |
97 | 10.1M | BOOST_ASSERT( w.st_.empty() ); |
98 | | |
99 | 10.1M | local_stream ss(ss0); |
100 | 10.1M | if(BOOST_JSON_LIKELY( ss.remain() >= detail::max_number_chars )) |
101 | 10.1M | { |
102 | 10.1M | ss.advance( f(ss.data()) ); |
103 | 10.1M | return true; |
104 | 10.1M | } |
105 | | |
106 | 4.37k | w.cs0_ = { w.buf_, f(w.buf_) }; |
107 | 4.37k | return write_buffer(w, ss); |
108 | 10.1M | } bool boost::json::detail::write_buffer<boost::json::detail::int64_formatter>(boost::json::detail::writer&, boost::json::detail::stream&, boost::json::detail::int64_formatter) Line | Count | Source | 96 | 3.68M | { | 97 | 3.68M | BOOST_ASSERT( w.st_.empty() ); | 98 | | | 99 | 3.68M | local_stream ss(ss0); | 100 | 3.68M | if(BOOST_JSON_LIKELY( ss.remain() >= detail::max_number_chars )) | 101 | 3.67M | { | 102 | 3.67M | ss.advance( f(ss.data()) ); | 103 | 3.67M | return true; | 104 | 3.67M | } | 105 | | | 106 | 2.45k | w.cs0_ = { w.buf_, f(w.buf_) }; | 107 | 2.45k | return write_buffer(w, ss); | 108 | 3.68M | } |
bool boost::json::detail::write_buffer<boost::json::detail::uint64_formatter>(boost::json::detail::writer&, boost::json::detail::stream&, boost::json::detail::uint64_formatter) Line | Count | Source | 96 | 24.5k | { | 97 | 24.5k | BOOST_ASSERT( w.st_.empty() ); | 98 | | | 99 | 24.5k | local_stream ss(ss0); | 100 | 24.5k | if(BOOST_JSON_LIKELY( ss.remain() >= detail::max_number_chars )) | 101 | 24.4k | { | 102 | 24.4k | ss.advance( f(ss.data()) ); | 103 | 24.4k | return true; | 104 | 24.4k | } | 105 | | | 106 | 167 | w.cs0_ = { w.buf_, f(w.buf_) }; | 107 | 167 | return write_buffer(w, ss); | 108 | 24.5k | } |
bool boost::json::detail::write_buffer<boost::json::detail::double_formatter>(boost::json::detail::writer&, boost::json::detail::stream&, boost::json::detail::double_formatter) Line | Count | Source | 96 | 6.42M | { | 97 | 6.42M | BOOST_ASSERT( w.st_.empty() ); | 98 | | | 99 | 6.42M | local_stream ss(ss0); | 100 | 6.42M | if(BOOST_JSON_LIKELY( ss.remain() >= detail::max_number_chars )) | 101 | 6.42M | { | 102 | 6.42M | ss.advance( f(ss.data()) ); | 103 | 6.42M | return true; | 104 | 6.42M | } | 105 | | | 106 | 1.75k | w.cs0_ = { w.buf_, f(w.buf_) }; | 107 | 1.75k | return write_buffer(w, ss); | 108 | 6.42M | } |
|
109 | | |
110 | | template<literals Lit> |
111 | | bool |
112 | | write_literal(writer& w, stream& ss) |
113 | 30.2k | { |
114 | 30.2k | constexpr std::size_t index = literal_index(Lit); |
115 | 30.2k | constexpr char const* literal = literal_strings[index]; |
116 | 30.2k | constexpr std::size_t sz = literal_sizes[index]; |
117 | | |
118 | 30.2k | std::size_t const n = ss.remain(); |
119 | 30.2k | if(BOOST_JSON_LIKELY( n >= sz )) |
120 | 30.2k | { |
121 | 30.2k | ss.append( literal, sz ); |
122 | 30.2k | return true; |
123 | 30.2k | } |
124 | | |
125 | 83 | ss.append(literal, n); |
126 | | |
127 | 83 | w.cs0_ = {literal + n, sz - n}; |
128 | 83 | return w.suspend(writer::state::lit); |
129 | 30.2k | } bool boost::json::detail::write_literal<(boost::json::detail::literals)1>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 113 | 15.9k | { | 114 | 15.9k | constexpr std::size_t index = literal_index(Lit); | 115 | 15.9k | constexpr char const* literal = literal_strings[index]; | 116 | 15.9k | constexpr std::size_t sz = literal_sizes[index]; | 117 | | | 118 | 15.9k | std::size_t const n = ss.remain(); | 119 | 15.9k | if(BOOST_JSON_LIKELY( n >= sz )) | 120 | 15.8k | { | 121 | 15.8k | ss.append( literal, sz ); | 122 | 15.8k | return true; | 123 | 15.8k | } | 124 | | | 125 | 26 | ss.append(literal, n); | 126 | | | 127 | 26 | w.cs0_ = {literal + n, sz - n}; | 128 | 26 | return w.suspend(writer::state::lit); | 129 | 15.9k | } |
bool boost::json::detail::write_literal<(boost::json::detail::literals)2>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 113 | 6.87k | { | 114 | 6.87k | constexpr std::size_t index = literal_index(Lit); | 115 | 6.87k | constexpr char const* literal = literal_strings[index]; | 116 | 6.87k | constexpr std::size_t sz = literal_sizes[index]; | 117 | | | 118 | 6.87k | std::size_t const n = ss.remain(); | 119 | 6.87k | if(BOOST_JSON_LIKELY( n >= sz )) | 120 | 6.85k | { | 121 | 6.85k | ss.append( literal, sz ); | 122 | 6.85k | return true; | 123 | 6.85k | } | 124 | | | 125 | 26 | ss.append(literal, n); | 126 | | | 127 | 26 | w.cs0_ = {literal + n, sz - n}; | 128 | 26 | return w.suspend(writer::state::lit); | 129 | 6.87k | } |
bool boost::json::detail::write_literal<(boost::json::detail::literals)0>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 113 | 7.49k | { | 114 | 7.49k | constexpr std::size_t index = literal_index(Lit); | 115 | 7.49k | constexpr char const* literal = literal_strings[index]; | 116 | 7.49k | constexpr std::size_t sz = literal_sizes[index]; | 117 | | | 118 | 7.49k | std::size_t const n = ss.remain(); | 119 | 7.49k | if(BOOST_JSON_LIKELY( n >= sz )) | 120 | 7.46k | { | 121 | 7.46k | ss.append( literal, sz ); | 122 | 7.46k | return true; | 123 | 7.46k | } | 124 | | | 125 | 31 | ss.append(literal, n); | 126 | | | 127 | 31 | w.cs0_ = {literal + n, sz - n}; | 128 | 31 | return w.suspend(writer::state::lit); | 129 | 7.49k | } |
|
130 | | |
131 | | bool |
132 | | write_true(writer& w, stream& ss) |
133 | 15.9k | { |
134 | 15.9k | return write_literal<literals::true_>(w, ss); |
135 | 15.9k | } |
136 | | |
137 | | bool |
138 | | write_false(writer& w, stream& ss) |
139 | 6.87k | { |
140 | 6.87k | return write_literal<literals::false_>(w, ss); |
141 | 6.87k | } |
142 | | |
143 | | bool |
144 | | write_null(writer& w, stream& ss) |
145 | 7.49k | { |
146 | 7.49k | return write_literal<literals::null>(w, ss); |
147 | 7.49k | } |
148 | | |
149 | | bool |
150 | | write_int64(writer& w, stream& ss0, std::int64_t i) |
151 | 3.68M | { |
152 | 3.68M | return write_buffer( w, ss0, int64_formatter{i} ); |
153 | 3.68M | } |
154 | | |
155 | | bool |
156 | | write_uint64(writer& w, stream& ss0, std::uint64_t u) |
157 | 24.5k | { |
158 | 24.5k | return write_buffer( w, ss0, uint64_formatter{u} ); |
159 | 24.5k | } |
160 | | |
161 | | bool |
162 | | write_double(writer& w, stream& ss0, double d) |
163 | 6.42M | { |
164 | 6.42M | return write_buffer( |
165 | 6.42M | w, ss0, double_formatter{d, w.opts_.allow_infinity_and_nan} ); |
166 | 6.42M | } |
167 | | |
168 | | bool |
169 | | resume_buffer(writer& w, stream& ss0) |
170 | 1.24k | { |
171 | 1.24k | BOOST_ASSERT( !w.st_.empty() ); |
172 | 1.24k | writer::state st; |
173 | 1.24k | w.st_.pop(st); |
174 | 1.24k | BOOST_ASSERT(st == writer::state::lit); |
175 | | |
176 | 1.24k | return write_buffer(w, ss0); |
177 | 1.24k | } |
178 | | |
179 | | template<bool StackEmpty> |
180 | | bool |
181 | | do_write_string(writer& w, stream& ss0) |
182 | 31.4k | { |
183 | 31.4k | local_stream ss(ss0); |
184 | 31.4k | local_const_stream cs(w.cs0_); |
185 | 31.4k | if(! StackEmpty && ! w.st_.empty()) |
186 | 1.10k | { |
187 | 1.10k | writer::state st; |
188 | 1.10k | w.st_.pop(st); |
189 | 1.10k | switch(st) |
190 | 1.10k | { |
191 | 0 | default: |
192 | 84 | case writer::state::str1: goto do_str1; |
193 | 142 | case writer::state::str2: goto do_str2; |
194 | 673 | case writer::state::str3: goto do_str3; |
195 | 44 | case writer::state::esc1: goto do_esc1; |
196 | 31 | case writer::state::utf1: goto do_utf1; |
197 | 35 | case writer::state::utf2: goto do_utf2; |
198 | 28 | case writer::state::utf3: goto do_utf3; |
199 | 35 | case writer::state::utf4: goto do_utf4; |
200 | 37 | case writer::state::utf5: goto do_utf5; |
201 | 1.10k | } |
202 | 1.10k | } |
203 | 30.3k | static constexpr char hex[] = "0123456789abcdef"; |
204 | 30.3k | static constexpr char esc[] = |
205 | 30.3k | "uuuuuuuubtnufruuuuuuuuuuuuuuuuuu" |
206 | 30.3k | "\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
207 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0" |
208 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
209 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
210 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
211 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" |
212 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; |
213 | | |
214 | | // opening quote |
215 | 30.4k | do_str1: |
216 | 30.4k | if(BOOST_JSON_LIKELY(ss)) |
217 | 30.3k | ss.append('\x22'); // '"' |
218 | 84 | else |
219 | 84 | return w.suspend(writer::state::str1); |
220 | | |
221 | | // fast loop, |
222 | | // copy unescaped |
223 | 30.5k | do_str2: |
224 | 30.5k | if(BOOST_JSON_LIKELY(ss)) |
225 | 30.4k | { |
226 | 30.4k | std::size_t n = cs.remain(); |
227 | 30.4k | if(BOOST_JSON_LIKELY(n > 0)) |
228 | 19.8k | { |
229 | 19.8k | if(ss.remain() > n) |
230 | 19.3k | n = detail::count_unescaped( |
231 | 19.3k | cs.data(), n); |
232 | 493 | else |
233 | 493 | n = detail::count_unescaped( |
234 | 493 | cs.data(), ss.remain()); |
235 | 19.8k | if(n > 0) |
236 | 9.60k | { |
237 | 9.60k | ss.append(cs.data(), n); |
238 | 9.60k | cs.skip(n); |
239 | 9.60k | if(! ss) |
240 | 110 | return w.suspend(writer::state::str2); |
241 | 9.60k | } |
242 | 19.8k | } |
243 | 10.5k | else |
244 | 10.5k | { |
245 | 10.5k | ss.append('\x22'); // '"' |
246 | 10.5k | return true; |
247 | 10.5k | } |
248 | 30.4k | } |
249 | 32 | else |
250 | 32 | { |
251 | 32 | return w.suspend(writer::state::str2); |
252 | 32 | } |
253 | | |
254 | | // slow loop, |
255 | | // handle escapes |
256 | 20.6k | do_str3: |
257 | 20.6k | while(BOOST_JSON_LIKELY(ss)) |
258 | 29.5M | { |
259 | 29.5M | if(BOOST_JSON_LIKELY(cs)) |
260 | 29.4M | { |
261 | 29.4M | auto const ch = *cs; |
262 | 29.4M | auto const c = esc[static_cast< |
263 | 29.4M | unsigned char>(ch)]; |
264 | 29.4M | ++cs; |
265 | 29.4M | if(! c) |
266 | 28.9M | { |
267 | 28.9M | ss.append(ch); |
268 | 28.9M | } |
269 | 503k | else if(c != 'u') |
270 | 376k | { |
271 | 376k | ss.append('\\'); |
272 | 376k | if(BOOST_JSON_LIKELY(ss)) |
273 | 376k | { |
274 | 376k | ss.append(c); |
275 | 376k | } |
276 | 44 | else |
277 | 44 | { |
278 | 44 | w.buf_[0] = c; |
279 | 44 | return w.suspend( |
280 | 44 | writer::state::esc1); |
281 | 44 | } |
282 | 376k | } |
283 | 126k | else |
284 | 126k | { |
285 | 126k | if(BOOST_JSON_LIKELY( |
286 | 126k | ss.remain() >= 6)) |
287 | 126k | { |
288 | 126k | ss.append("\\u00", 4); |
289 | 126k | ss.append(hex[static_cast< |
290 | 126k | unsigned char>(ch) >> 4]); |
291 | 126k | ss.append(hex[static_cast< |
292 | 126k | unsigned char>(ch) & 15]); |
293 | 126k | } |
294 | 166 | else |
295 | 166 | { |
296 | 166 | ss.append('\\'); |
297 | 166 | w.buf_[0] = hex[static_cast< |
298 | 166 | unsigned char>(ch) >> 4]; |
299 | 166 | w.buf_[1] = hex[static_cast< |
300 | 166 | unsigned char>(ch) & 15]; |
301 | 166 | goto do_utf1; |
302 | 166 | } |
303 | 126k | } |
304 | 29.4M | } |
305 | 19.7k | else |
306 | 19.7k | { |
307 | 19.7k | ss.append('\x22'); // '"' |
308 | 19.7k | return true; |
309 | 19.7k | } |
310 | 29.5M | } |
311 | 673 | return w.suspend(writer::state::str3); |
312 | | |
313 | 44 | do_esc1: |
314 | 44 | BOOST_ASSERT(ss); |
315 | 44 | ss.append(w.buf_[0]); |
316 | 44 | goto do_str3; |
317 | | |
318 | 197 | do_utf1: |
319 | 197 | if(BOOST_JSON_LIKELY(ss)) |
320 | 166 | ss.append('u'); |
321 | 31 | else |
322 | 31 | return w.suspend(writer::state::utf1); |
323 | 201 | do_utf2: |
324 | 201 | if(BOOST_JSON_LIKELY(ss)) |
325 | 166 | ss.append('0'); |
326 | 35 | else |
327 | 35 | return w.suspend(writer::state::utf2); |
328 | 194 | do_utf3: |
329 | 194 | if(BOOST_JSON_LIKELY(ss)) |
330 | 166 | ss.append('0'); |
331 | 28 | else |
332 | 28 | return w.suspend(writer::state::utf3); |
333 | 201 | do_utf4: |
334 | 201 | if(BOOST_JSON_LIKELY(ss)) |
335 | 166 | ss.append(w.buf_[0]); |
336 | 35 | else |
337 | 35 | return w.suspend(writer::state::utf4); |
338 | 203 | do_utf5: |
339 | 203 | if(BOOST_JSON_LIKELY(ss)) |
340 | 166 | ss.append(w.buf_[1]); |
341 | 37 | else |
342 | 37 | return w.suspend(writer::state::utf5); |
343 | 166 | goto do_str3; |
344 | 203 | } bool boost::json::detail::do_write_string<true>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 182 | 30.3k | { | 183 | 30.3k | local_stream ss(ss0); | 184 | 30.3k | local_const_stream cs(w.cs0_); | 185 | 30.3k | if(! StackEmpty && ! w.st_.empty()) | 186 | 0 | { | 187 | 0 | writer::state st; | 188 | 0 | w.st_.pop(st); | 189 | 0 | switch(st) | 190 | 0 | { | 191 | 0 | default: | 192 | 0 | case writer::state::str1: goto do_str1; | 193 | 0 | case writer::state::str2: goto do_str2; | 194 | 0 | case writer::state::str3: goto do_str3; | 195 | 0 | case writer::state::esc1: goto do_esc1; | 196 | 0 | case writer::state::utf1: goto do_utf1; | 197 | 0 | case writer::state::utf2: goto do_utf2; | 198 | 0 | case writer::state::utf3: goto do_utf3; | 199 | 0 | case writer::state::utf4: goto do_utf4; | 200 | 0 | case writer::state::utf5: goto do_utf5; | 201 | 0 | } | 202 | 0 | } | 203 | 30.3k | static constexpr char hex[] = "0123456789abcdef"; | 204 | 30.3k | static constexpr char esc[] = | 205 | 30.3k | "uuuuuuuubtnufruuuuuuuuuuuuuuuuuu" | 206 | 30.3k | "\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 207 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0" | 208 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 209 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 210 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 211 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 212 | 30.3k | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; | 213 | | | 214 | | // opening quote | 215 | 30.3k | do_str1: | 216 | 30.3k | if(BOOST_JSON_LIKELY(ss)) | 217 | 30.2k | ss.append('\x22'); // '"' | 218 | 84 | else | 219 | 84 | return w.suspend(writer::state::str1); | 220 | | | 221 | | // fast loop, | 222 | | // copy unescaped | 223 | 30.2k | do_str2: | 224 | 30.2k | if(BOOST_JSON_LIKELY(ss)) | 225 | 30.2k | { | 226 | 30.2k | std::size_t n = cs.remain(); | 227 | 30.2k | if(BOOST_JSON_LIKELY(n > 0)) | 228 | 19.6k | { | 229 | 19.6k | if(ss.remain() > n) | 230 | 19.2k | n = detail::count_unescaped( | 231 | 19.2k | cs.data(), n); | 232 | 420 | else | 233 | 420 | n = detail::count_unescaped( | 234 | 420 | cs.data(), ss.remain()); | 235 | 19.6k | if(n > 0) | 236 | 9.44k | { | 237 | 9.44k | ss.append(cs.data(), n); | 238 | 9.44k | cs.skip(n); | 239 | 9.44k | if(! ss) | 240 | 99 | return w.suspend(writer::state::str2); | 241 | 9.44k | } | 242 | 19.6k | } | 243 | 10.5k | else | 244 | 10.5k | { | 245 | 10.5k | ss.append('\x22'); // '"' | 246 | 10.5k | return true; | 247 | 10.5k | } | 248 | 30.2k | } | 249 | 32 | else | 250 | 32 | { | 251 | 32 | return w.suspend(writer::state::str2); | 252 | 32 | } | 253 | | | 254 | | // slow loop, | 255 | | // handle escapes | 256 | 19.5k | do_str3: | 257 | 19.5k | while(BOOST_JSON_LIKELY(ss)) | 258 | 1.90M | { | 259 | 1.90M | if(BOOST_JSON_LIKELY(cs)) | 260 | 1.88M | { | 261 | 1.88M | auto const ch = *cs; | 262 | 1.88M | auto const c = esc[static_cast< | 263 | 1.88M | unsigned char>(ch)]; | 264 | 1.88M | ++cs; | 265 | 1.88M | if(! c) | 266 | 1.54M | { | 267 | 1.54M | ss.append(ch); | 268 | 1.54M | } | 269 | 342k | else if(c != 'u') | 270 | 273k | { | 271 | 273k | ss.append('\\'); | 272 | 273k | if(BOOST_JSON_LIKELY(ss)) | 273 | 273k | { | 274 | 273k | ss.append(c); | 275 | 273k | } | 276 | 29 | else | 277 | 29 | { | 278 | 29 | w.buf_[0] = c; | 279 | 29 | return w.suspend( | 280 | 29 | writer::state::esc1); | 281 | 29 | } | 282 | 273k | } | 283 | 68.9k | else | 284 | 68.9k | { | 285 | 68.9k | if(BOOST_JSON_LIKELY( | 286 | 68.9k | ss.remain() >= 6)) | 287 | 68.8k | { | 288 | 68.8k | ss.append("\\u00", 4); | 289 | 68.8k | ss.append(hex[static_cast< | 290 | 68.8k | unsigned char>(ch) >> 4]); | 291 | 68.8k | ss.append(hex[static_cast< | 292 | 68.8k | unsigned char>(ch) & 15]); | 293 | 68.8k | } | 294 | 90 | else | 295 | 90 | { | 296 | 90 | ss.append('\\'); | 297 | 90 | w.buf_[0] = hex[static_cast< | 298 | 90 | unsigned char>(ch) >> 4]; | 299 | 90 | w.buf_[1] = hex[static_cast< | 300 | 90 | unsigned char>(ch) & 15]; | 301 | 90 | goto do_utf1; | 302 | 90 | } | 303 | 68.9k | } | 304 | 1.88M | } | 305 | 19.2k | else | 306 | 19.2k | { | 307 | 19.2k | ss.append('\x22'); // '"' | 308 | 19.2k | return true; | 309 | 19.2k | } | 310 | 1.90M | } | 311 | 239 | return w.suspend(writer::state::str3); | 312 | | | 313 | 0 | do_esc1: | 314 | 0 | BOOST_ASSERT(ss); | 315 | 0 | ss.append(w.buf_[0]); | 316 | 0 | goto do_str3; | 317 | | | 318 | 90 | do_utf1: | 319 | 90 | if(BOOST_JSON_LIKELY(ss)) | 320 | 73 | ss.append('u'); | 321 | 17 | else | 322 | 17 | return w.suspend(writer::state::utf1); | 323 | 73 | do_utf2: | 324 | 73 | if(BOOST_JSON_LIKELY(ss)) | 325 | 55 | ss.append('0'); | 326 | 18 | else | 327 | 18 | return w.suspend(writer::state::utf2); | 328 | 55 | do_utf3: | 329 | 55 | if(BOOST_JSON_LIKELY(ss)) | 330 | 39 | ss.append('0'); | 331 | 16 | else | 332 | 16 | return w.suspend(writer::state::utf3); | 333 | 39 | do_utf4: | 334 | 39 | if(BOOST_JSON_LIKELY(ss)) | 335 | 19 | ss.append(w.buf_[0]); | 336 | 20 | else | 337 | 20 | return w.suspend(writer::state::utf4); | 338 | 19 | do_utf5: | 339 | 19 | if(BOOST_JSON_LIKELY(ss)) | 340 | 0 | ss.append(w.buf_[1]); | 341 | 19 | else | 342 | 19 | return w.suspend(writer::state::utf5); | 343 | 0 | goto do_str3; | 344 | 19 | } |
bool boost::json::detail::do_write_string<false>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 182 | 1.10k | { | 183 | 1.10k | local_stream ss(ss0); | 184 | 1.10k | local_const_stream cs(w.cs0_); | 185 | 1.10k | if(! StackEmpty && ! w.st_.empty()) | 186 | 1.10k | { | 187 | 1.10k | writer::state st; | 188 | 1.10k | w.st_.pop(st); | 189 | 1.10k | switch(st) | 190 | 1.10k | { | 191 | 0 | default: | 192 | 84 | case writer::state::str1: goto do_str1; | 193 | 142 | case writer::state::str2: goto do_str2; | 194 | 673 | case writer::state::str3: goto do_str3; | 195 | 44 | case writer::state::esc1: goto do_esc1; | 196 | 31 | case writer::state::utf1: goto do_utf1; | 197 | 35 | case writer::state::utf2: goto do_utf2; | 198 | 28 | case writer::state::utf3: goto do_utf3; | 199 | 35 | case writer::state::utf4: goto do_utf4; | 200 | 37 | case writer::state::utf5: goto do_utf5; | 201 | 1.10k | } | 202 | 1.10k | } | 203 | 0 | static constexpr char hex[] = "0123456789abcdef"; | 204 | 0 | static constexpr char esc[] = | 205 | 0 | "uuuuuuuubtnufruuuuuuuuuuuuuuuuuu" | 206 | 0 | "\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 207 | 0 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0" | 208 | 0 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 209 | 0 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 210 | 0 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 211 | 0 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | 212 | 0 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; | 213 | | | 214 | | // opening quote | 215 | 84 | do_str1: | 216 | 84 | if(BOOST_JSON_LIKELY(ss)) | 217 | 84 | ss.append('\x22'); // '"' | 218 | 0 | else | 219 | 0 | return w.suspend(writer::state::str1); | 220 | | | 221 | | // fast loop, | 222 | | // copy unescaped | 223 | 226 | do_str2: | 224 | 226 | if(BOOST_JSON_LIKELY(ss)) | 225 | 226 | { | 226 | 226 | std::size_t n = cs.remain(); | 227 | 226 | if(BOOST_JSON_LIKELY(n > 0)) | 228 | 200 | { | 229 | 200 | if(ss.remain() > n) | 230 | 127 | n = detail::count_unescaped( | 231 | 127 | cs.data(), n); | 232 | 73 | else | 233 | 73 | n = detail::count_unescaped( | 234 | 73 | cs.data(), ss.remain()); | 235 | 200 | if(n > 0) | 236 | 163 | { | 237 | 163 | ss.append(cs.data(), n); | 238 | 163 | cs.skip(n); | 239 | 163 | if(! ss) | 240 | 11 | return w.suspend(writer::state::str2); | 241 | 163 | } | 242 | 200 | } | 243 | 26 | else | 244 | 26 | { | 245 | 26 | ss.append('\x22'); // '"' | 246 | 26 | return true; | 247 | 26 | } | 248 | 226 | } | 249 | 0 | else | 250 | 0 | { | 251 | 0 | return w.suspend(writer::state::str2); | 252 | 0 | } | 253 | | | 254 | | // slow loop, | 255 | | // handle escapes | 256 | 1.07k | do_str3: | 257 | 1.07k | while(BOOST_JSON_LIKELY(ss)) | 258 | 27.6M | { | 259 | 27.6M | if(BOOST_JSON_LIKELY(cs)) | 260 | 27.6M | { | 261 | 27.6M | auto const ch = *cs; | 262 | 27.6M | auto const c = esc[static_cast< | 263 | 27.6M | unsigned char>(ch)]; | 264 | 27.6M | ++cs; | 265 | 27.6M | if(! c) | 266 | 27.4M | { | 267 | 27.4M | ss.append(ch); | 268 | 27.4M | } | 269 | 161k | else if(c != 'u') | 270 | 103k | { | 271 | 103k | ss.append('\\'); | 272 | 103k | if(BOOST_JSON_LIKELY(ss)) | 273 | 103k | { | 274 | 103k | ss.append(c); | 275 | 103k | } | 276 | 15 | else | 277 | 15 | { | 278 | 15 | w.buf_[0] = c; | 279 | 15 | return w.suspend( | 280 | 15 | writer::state::esc1); | 281 | 15 | } | 282 | 103k | } | 283 | 57.9k | else | 284 | 57.9k | { | 285 | 57.9k | if(BOOST_JSON_LIKELY( | 286 | 57.9k | ss.remain() >= 6)) | 287 | 57.8k | { | 288 | 57.8k | ss.append("\\u00", 4); | 289 | 57.8k | ss.append(hex[static_cast< | 290 | 57.8k | unsigned char>(ch) >> 4]); | 291 | 57.8k | ss.append(hex[static_cast< | 292 | 57.8k | unsigned char>(ch) & 15]); | 293 | 57.8k | } | 294 | 76 | else | 295 | 76 | { | 296 | 76 | ss.append('\\'); | 297 | 76 | w.buf_[0] = hex[static_cast< | 298 | 76 | unsigned char>(ch) >> 4]; | 299 | 76 | w.buf_[1] = hex[static_cast< | 300 | 76 | unsigned char>(ch) & 15]; | 301 | 76 | goto do_utf1; | 302 | 76 | } | 303 | 57.9k | } | 304 | 27.6M | } | 305 | 547 | else | 306 | 547 | { | 307 | 547 | ss.append('\x22'); // '"' | 308 | 547 | return true; | 309 | 547 | } | 310 | 27.6M | } | 311 | 434 | return w.suspend(writer::state::str3); | 312 | | | 313 | 44 | do_esc1: | 314 | 44 | BOOST_ASSERT(ss); | 315 | 44 | ss.append(w.buf_[0]); | 316 | 44 | goto do_str3; | 317 | | | 318 | 107 | do_utf1: | 319 | 107 | if(BOOST_JSON_LIKELY(ss)) | 320 | 93 | ss.append('u'); | 321 | 14 | else | 322 | 14 | return w.suspend(writer::state::utf1); | 323 | 128 | do_utf2: | 324 | 128 | if(BOOST_JSON_LIKELY(ss)) | 325 | 111 | ss.append('0'); | 326 | 17 | else | 327 | 17 | return w.suspend(writer::state::utf2); | 328 | 139 | do_utf3: | 329 | 139 | if(BOOST_JSON_LIKELY(ss)) | 330 | 127 | ss.append('0'); | 331 | 12 | else | 332 | 12 | return w.suspend(writer::state::utf3); | 333 | 162 | do_utf4: | 334 | 162 | if(BOOST_JSON_LIKELY(ss)) | 335 | 147 | ss.append(w.buf_[0]); | 336 | 15 | else | 337 | 15 | return w.suspend(writer::state::utf4); | 338 | 184 | do_utf5: | 339 | 184 | if(BOOST_JSON_LIKELY(ss)) | 340 | 166 | ss.append(w.buf_[1]); | 341 | 18 | else | 342 | 18 | return w.suspend(writer::state::utf5); | 343 | 166 | goto do_str3; | 344 | 184 | } |
|
345 | | |
346 | | bool |
347 | | write_string(writer& w, stream& ss0) |
348 | 13.4k | { |
349 | 13.4k | return do_write_string<true>(w, ss0); |
350 | 13.4k | } |
351 | | |
352 | | bool |
353 | | resume_string(writer& w, stream& ss0) |
354 | 365 | { |
355 | 365 | return do_write_string<false>(w, ss0); |
356 | 365 | } |
357 | | |
358 | | template<bool StackEmpty> |
359 | | bool |
360 | | write_value(writer& w, stream& ss); |
361 | | |
362 | | template< class T, bool StackEmpty > |
363 | | BOOST_FORCEINLINE |
364 | | bool |
365 | | write_impl(no_conversion_tag, writer& w, stream& ss) |
366 | 10.2M | { |
367 | 10.2M | return write_value<StackEmpty>(w, ss); |
368 | 10.2M | } bool boost::json::detail::write_impl<boost::json::value, true>(boost::json::detail::no_conversion_tag, boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 366 | 1.03M | { | 367 | 1.03M | return write_value<StackEmpty>(w, ss); | 368 | 1.03M | } |
bool boost::json::detail::write_impl<boost::json::value, false>(boost::json::detail::no_conversion_tag, boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 366 | 9.14M | { | 367 | 9.14M | return write_value<StackEmpty>(w, ss); | 368 | 9.14M | } |
bool boost::json::detail::write_impl<boost::json::value&, true>(boost::json::detail::no_conversion_tag, boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 366 | 11.0k | { | 367 | 11.0k | return write_value<StackEmpty>(w, ss); | 368 | 11.0k | } |
bool boost::json::detail::write_impl<boost::json::value&, false>(boost::json::detail::no_conversion_tag, boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 366 | 3.59k | { | 367 | 3.59k | return write_value<StackEmpty>(w, ss); | 368 | 3.59k | } |
|
369 | | |
370 | | template<bool StackEmpty> |
371 | | bool |
372 | | write_array(writer& w, stream& ss) |
373 | 21.2k | { |
374 | 21.2k | return write_impl<array, StackEmpty>(sequence_conversion_tag(), w, ss); |
375 | 21.2k | } bool boost::json::detail::write_array<true>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 373 | 14.7k | { | 374 | 14.7k | return write_impl<array, StackEmpty>(sequence_conversion_tag(), w, ss); | 375 | 14.7k | } |
bool boost::json::detail::write_array<false>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 373 | 6.46k | { | 374 | 6.46k | return write_impl<array, StackEmpty>(sequence_conversion_tag(), w, ss); | 375 | 6.46k | } |
|
376 | | |
377 | | template<bool StackEmpty> |
378 | | bool |
379 | | write_object(writer& w, stream& ss) |
380 | 7.63k | { |
381 | 7.63k | return write_impl<object, StackEmpty>(map_like_conversion_tag(), w, ss); |
382 | 7.63k | } bool boost::json::detail::write_object<true>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 380 | 5.92k | { | 381 | 5.92k | return write_impl<object, StackEmpty>(map_like_conversion_tag(), w, ss); | 382 | 5.92k | } |
bool boost::json::detail::write_object<false>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 380 | 1.70k | { | 381 | 1.70k | return write_impl<object, StackEmpty>(map_like_conversion_tag(), w, ss); | 382 | 1.70k | } |
|
383 | | |
384 | | template<bool StackEmpty> |
385 | | bool |
386 | | write_value(writer& w, stream& ss) |
387 | 10.2M | { |
388 | 10.2M | if(StackEmpty || w.st_.empty()) |
389 | 10.2M | { |
390 | 10.2M | BOOST_ASSERT( w.p_ ); |
391 | 10.2M | auto const pv = reinterpret_cast<value const*>(w.p_); |
392 | 10.2M | switch(pv->kind()) |
393 | 10.2M | { |
394 | 0 | default: |
395 | 5.92k | case kind::object: |
396 | 5.92k | w.p_ = &pv->get_object(); |
397 | 5.92k | return write_object<true>(w, ss); |
398 | | |
399 | 14.7k | case kind::array: |
400 | 14.7k | w.p_ = &pv->get_array(); |
401 | 14.7k | return write_array<true>(w, ss); |
402 | | |
403 | 16.9k | case kind::string: |
404 | 16.9k | { |
405 | 16.9k | auto const& js = pv->get_string(); |
406 | 16.9k | w.cs0_ = { js.data(), js.size() }; |
407 | 16.9k | return do_write_string<true>(w, ss); |
408 | 0 | } |
409 | | |
410 | 3.68M | case kind::int64: |
411 | 3.68M | return write_int64( w, ss, pv->get_int64() ); |
412 | 24.5k | case kind::uint64: |
413 | 24.5k | return write_uint64( w, ss, pv->get_uint64() ); |
414 | 6.42M | case kind::double_: |
415 | 6.42M | return write_double( w, ss, pv->get_double() ); |
416 | | |
417 | 22.7k | case kind::bool_: |
418 | 22.7k | if( pv->get_bool() ) |
419 | 15.9k | return write_true(w, ss); |
420 | 6.87k | else |
421 | 6.87k | return write_false(w, ss); |
422 | | |
423 | 7.49k | case kind::null: |
424 | 7.49k | return write_null(w, ss); |
425 | 10.2M | } |
426 | 10.2M | } |
427 | 10.1k | else |
428 | 10.1k | { |
429 | 10.1k | writer::state st; |
430 | 10.1k | w.st_.peek(st); |
431 | 10.1k | switch(st) |
432 | 10.1k | { |
433 | 0 | default: |
434 | 1.24k | case writer::state::lit: |
435 | 1.24k | return resume_buffer(w, ss); |
436 | | |
437 | 139 | case writer::state::str1: case writer::state::str2: |
438 | 588 | case writer::state::str3: case writer::state::esc1: |
439 | 652 | case writer::state::utf1: case writer::state::utf2: |
440 | 712 | case writer::state::utf3: case writer::state::utf4: |
441 | 744 | case writer::state::utf5: |
442 | 744 | return do_write_string<false>(w, ss); |
443 | | |
444 | 6.24k | case writer::state::arr1: case writer::state::arr2: |
445 | 6.46k | case writer::state::arr3: case writer::state::arr4: |
446 | 6.46k | return write_array<StackEmpty>(w, ss); |
447 | | |
448 | 382 | case writer::state::obj1: case writer::state::obj2: |
449 | 1.65k | case writer::state::obj3: case writer::state::obj4: |
450 | 1.70k | case writer::state::obj5: case writer::state::obj6: |
451 | 1.70k | return write_object<StackEmpty>(w, ss); |
452 | 10.1k | } |
453 | 10.1k | } |
454 | 10.2M | } bool boost::json::detail::write_value<true>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 387 | 1.05M | { | 388 | 1.05M | if(StackEmpty || w.st_.empty()) | 389 | 1.05M | { | 390 | 1.05M | BOOST_ASSERT( w.p_ ); | 391 | 1.05M | auto const pv = reinterpret_cast<value const*>(w.p_); | 392 | 1.05M | switch(pv->kind()) | 393 | 1.05M | { | 394 | 0 | default: | 395 | 4.27k | case kind::object: | 396 | 4.27k | w.p_ = &pv->get_object(); | 397 | 4.27k | return write_object<true>(w, ss); | 398 | | | 399 | 11.0k | case kind::array: | 400 | 11.0k | w.p_ = &pv->get_array(); | 401 | 11.0k | return write_array<true>(w, ss); | 402 | | | 403 | 3.92k | case kind::string: | 404 | 3.92k | { | 405 | 3.92k | auto const& js = pv->get_string(); | 406 | 3.92k | w.cs0_ = { js.data(), js.size() }; | 407 | 3.92k | return do_write_string<true>(w, ss); | 408 | 0 | } | 409 | | | 410 | 187k | case kind::int64: | 411 | 187k | return write_int64( w, ss, pv->get_int64() ); | 412 | 19.6k | case kind::uint64: | 413 | 19.6k | return write_uint64( w, ss, pv->get_uint64() ); | 414 | 810k | case kind::double_: | 415 | 810k | return write_double( w, ss, pv->get_double() ); | 416 | | | 417 | 14.6k | case kind::bool_: | 418 | 14.6k | if( pv->get_bool() ) | 419 | 12.0k | return write_true(w, ss); | 420 | 2.62k | else | 421 | 2.62k | return write_false(w, ss); | 422 | | | 423 | 3.74k | case kind::null: | 424 | 3.74k | return write_null(w, ss); | 425 | 1.05M | } | 426 | 1.05M | } | 427 | 0 | else | 428 | 0 | { | 429 | 0 | writer::state st; | 430 | 0 | w.st_.peek(st); | 431 | 0 | switch(st) | 432 | 0 | { | 433 | 0 | default: | 434 | 0 | case writer::state::lit: | 435 | 0 | return resume_buffer(w, ss); | 436 | | | 437 | 0 | case writer::state::str1: case writer::state::str2: | 438 | 0 | case writer::state::str3: case writer::state::esc1: | 439 | 0 | case writer::state::utf1: case writer::state::utf2: | 440 | 0 | case writer::state::utf3: case writer::state::utf4: | 441 | 0 | case writer::state::utf5: | 442 | 0 | return do_write_string<false>(w, ss); | 443 | | | 444 | 0 | case writer::state::arr1: case writer::state::arr2: | 445 | 0 | case writer::state::arr3: case writer::state::arr4: | 446 | 0 | return write_array<StackEmpty>(w, ss); | 447 | | | 448 | 0 | case writer::state::obj1: case writer::state::obj2: | 449 | 0 | case writer::state::obj3: case writer::state::obj4: | 450 | 0 | case writer::state::obj5: case writer::state::obj6: | 451 | 0 | return write_object<StackEmpty>(w, ss); | 452 | 0 | } | 453 | 0 | } | 454 | 1.05M | } |
bool boost::json::detail::write_value<false>(boost::json::detail::writer&, boost::json::detail::stream&) Line | Count | Source | 387 | 9.15M | { | 388 | 9.15M | if(StackEmpty || w.st_.empty()) | 389 | 9.14M | { | 390 | 9.14M | BOOST_ASSERT( w.p_ ); | 391 | 9.14M | auto const pv = reinterpret_cast<value const*>(w.p_); | 392 | 9.14M | switch(pv->kind()) | 393 | 9.14M | { | 394 | 0 | default: | 395 | 1.64k | case kind::object: | 396 | 1.64k | w.p_ = &pv->get_object(); | 397 | 1.64k | return write_object<true>(w, ss); | 398 | | | 399 | 3.75k | case kind::array: | 400 | 3.75k | w.p_ = &pv->get_array(); | 401 | 3.75k | return write_array<true>(w, ss); | 402 | | | 403 | 13.0k | case kind::string: | 404 | 13.0k | { | 405 | 13.0k | auto const& js = pv->get_string(); | 406 | 13.0k | w.cs0_ = { js.data(), js.size() }; | 407 | 13.0k | return do_write_string<true>(w, ss); | 408 | 0 | } | 409 | | | 410 | 3.49M | case kind::int64: | 411 | 3.49M | return write_int64( w, ss, pv->get_int64() ); | 412 | 4.98k | case kind::uint64: | 413 | 4.98k | return write_uint64( w, ss, pv->get_uint64() ); | 414 | 5.61M | case kind::double_: | 415 | 5.61M | return write_double( w, ss, pv->get_double() ); | 416 | | | 417 | 8.10k | case kind::bool_: | 418 | 8.10k | if( pv->get_bool() ) | 419 | 3.85k | return write_true(w, ss); | 420 | 4.24k | else | 421 | 4.24k | return write_false(w, ss); | 422 | | | 423 | 3.74k | case kind::null: | 424 | 3.74k | return write_null(w, ss); | 425 | 9.14M | } | 426 | 9.14M | } | 427 | 10.1k | else | 428 | 10.1k | { | 429 | 10.1k | writer::state st; | 430 | 10.1k | w.st_.peek(st); | 431 | 10.1k | switch(st) | 432 | 10.1k | { | 433 | 0 | default: | 434 | 1.24k | case writer::state::lit: | 435 | 1.24k | return resume_buffer(w, ss); | 436 | | | 437 | 139 | case writer::state::str1: case writer::state::str2: | 438 | 588 | case writer::state::str3: case writer::state::esc1: | 439 | 652 | case writer::state::utf1: case writer::state::utf2: | 440 | 712 | case writer::state::utf3: case writer::state::utf4: | 441 | 744 | case writer::state::utf5: | 442 | 744 | return do_write_string<false>(w, ss); | 443 | | | 444 | 6.24k | case writer::state::arr1: case writer::state::arr2: | 445 | 6.46k | case writer::state::arr3: case writer::state::arr4: | 446 | 6.46k | return write_array<StackEmpty>(w, ss); | 447 | | | 448 | 382 | case writer::state::obj1: case writer::state::obj2: | 449 | 1.65k | case writer::state::obj3: case writer::state::obj4: | 450 | 1.70k | case writer::state::obj5: case writer::state::obj6: | 451 | 1.70k | return write_object<StackEmpty>(w, ss); | 452 | 10.1k | } | 453 | 10.1k | } | 454 | 9.15M | } |
|
455 | | |
456 | | } // namespace detail |
457 | | |
458 | | serializer:: |
459 | | serializer(serialize_options const& opts) noexcept |
460 | 0 | : serializer({}, nullptr, 0, opts) |
461 | 0 | {} |
462 | | |
463 | | serializer:: |
464 | | serializer( |
465 | | storage_ptr sp, |
466 | | unsigned char* buf, |
467 | | std::size_t buf_size, |
468 | | serialize_options const& opts) noexcept |
469 | 7.07k | : detail::writer(std::move(sp), buf, buf_size, opts) |
470 | 7.07k | {} |
471 | | |
472 | | void |
473 | | serializer:: |
474 | | reset(value const* p) noexcept |
475 | 7.07k | { |
476 | 7.07k | p_ = p; |
477 | 7.07k | fn0_ = &detail::write_value<true>; |
478 | 7.07k | fn1_ = &detail::write_value<false>; |
479 | 7.07k | st_.clear(); |
480 | 7.07k | done_ = false; |
481 | 7.07k | } |
482 | | |
483 | | void |
484 | | serializer:: |
485 | | reset(array const* p) noexcept |
486 | 0 | { |
487 | 0 | p_ = p; |
488 | 0 | fn0_ = &detail::write_array<true>; |
489 | 0 | fn1_ = &detail::write_array<false>; |
490 | 0 | st_.clear(); |
491 | 0 | done_ = false; |
492 | 0 | } |
493 | | |
494 | | void |
495 | | serializer:: |
496 | | reset(object const* p) noexcept |
497 | 0 | { |
498 | 0 | p_ = p; |
499 | 0 | fn0_ = &detail::write_object<true>; |
500 | 0 | fn1_ = &detail::write_object<false>; |
501 | 0 | st_.clear(); |
502 | 0 | done_ = false; |
503 | 0 | } |
504 | | |
505 | | void |
506 | | serializer:: |
507 | | reset(string const* p) noexcept |
508 | 0 | { |
509 | 0 | cs0_ = { p->data(), p->size() }; |
510 | 0 | fn0_ = &detail::do_write_string<true>; |
511 | 0 | fn1_ = &detail::do_write_string<false>; |
512 | 0 | st_.clear(); |
513 | 0 | done_ = false; |
514 | 0 | } |
515 | | |
516 | | void |
517 | | serializer:: |
518 | | reset(string_view sv) noexcept |
519 | 0 | { |
520 | 0 | cs0_ = { sv.data(), sv.size() }; |
521 | 0 | fn0_ = &detail::do_write_string<true>; |
522 | 0 | fn1_ = &detail::do_write_string<false>; |
523 | 0 | st_.clear(); |
524 | 0 | done_ = false; |
525 | 0 | } |
526 | | |
527 | | void |
528 | | serializer::reset(std::nullptr_t) noexcept |
529 | 0 | { |
530 | 0 | p_ = nullptr; |
531 | 0 | fn0_ = &detail::write_impl<std::nullptr_t, true>; |
532 | 0 | fn1_ = &detail::write_impl<std::nullptr_t, false>; |
533 | 0 | st_.clear(); |
534 | 0 | done_ = false; |
535 | 0 | } |
536 | | |
537 | | string_view |
538 | | serializer:: |
539 | | read(char* dest, std::size_t size) |
540 | 9.75k | { |
541 | 9.75k | if( !fn0_ ) |
542 | 0 | reset(nullptr); |
543 | | |
544 | 9.75k | if(BOOST_JSON_UNLIKELY(size == 0)) |
545 | 0 | return {dest, 0}; |
546 | | |
547 | 9.75k | detail::stream ss(dest, size); |
548 | 9.75k | if(st_.empty()) |
549 | 7.07k | fn0_(*this, ss); |
550 | 2.67k | else |
551 | 2.67k | fn1_(*this, ss); |
552 | 9.75k | if(st_.empty()) |
553 | 7.07k | { |
554 | 7.07k | done_ = true; |
555 | 7.07k | fn0_ = nullptr; |
556 | 7.07k | p_ = nullptr; |
557 | 7.07k | } |
558 | 9.75k | return string_view( |
559 | 9.75k | dest, ss.used(dest)); |
560 | 9.75k | } |
561 | | |
562 | | } // namespace json |
563 | | } // namespace boost |
564 | | |
565 | | #ifdef _MSC_VER |
566 | | #pragma warning(pop) |
567 | | #endif |
568 | | |
569 | | #endif |