GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: impl/serializer.ipp
Date: 2025-12-23 17:22:01
Exec Total Coverage
Lines: 441 442 99.8%
Functions: 28 28 100.0%
Branches: 222 238 93.3%

Line Branch Exec 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/json/serializer.hpp>
14 #include <boost/json/detail/format.hpp>
15 #include <boost/json/detail/sse2.hpp>
16 #include <ostream>
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
26 enum class serializer::state : char
27 {
28 nul1, nul2, nul3, nul4,
29 tru1, tru2, tru3, tru4,
30 fal1, fal2, fal3, fal4, fal5,
31 str1, str2, str3, esc1, utf1,
32 utf2, utf3, utf4, utf5,
33 num,
34 arr1, arr2, arr3, arr4,
35 obj1, obj2, obj3, obj4, obj5, obj6
36 };
37
38 //----------------------------------------------------------
39
40 18855 serializer::
41 serializer(
42 storage_ptr sp,
43 unsigned char* buf,
44 std::size_t buf_size,
45 18855 serialize_options const& opts) noexcept
46 18855 : st_(
47 18855 std::move(sp),
48 buf,
49 buf_size)
50 18855 , opts_(opts)
51 {
52 18855 }
53
54 bool
55 9505 serializer::
56 suspend(state st)
57 {
58 9505 st_.push(st);
59 9504 return false;
60 }
61
62 bool
63 1319 serializer::
64 suspend(
65 state st,
66 array::const_iterator it,
67 array const* pa)
68 {
69 1319 st_.push(pa);
70 1318 st_.push(it);
71 1318 st_.push(st);
72 1318 return false;
73 }
74
75 bool
76 8534 serializer::
77 suspend(
78 state st,
79 object::const_iterator it,
80 object const* po)
81 {
82 8534 st_.push(po);
83 8534 st_.push(it);
84 8534 st_.push(st);
85 8534 return false;
86 }
87
88 template<bool StackEmpty>
89 bool
90 150 serializer::
91 write_null(stream& ss0)
92 {
93 150 local_stream ss(ss0);
94
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
72 if(! StackEmpty && ! st_.empty())
95 {
96 state st;
97 72 st_.pop(st);
98
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 10 times.
72 switch(st)
99 {
100 14 default:
101 14 case state::nul1: goto do_nul1;
102 20 case state::nul2: goto do_nul2;
103 18 case state::nul3: goto do_nul3;
104 20 case state::nul4: goto do_nul4;
105 }
106 }
107 78 do_nul1:
108
2/2
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 7 times.
92 if(BOOST_JSON_LIKELY(ss))
109 78 ss.append('n');
110 else
111
1/1
✓ Branch 1 taken 7 times.
14 return suspend(state::nul1);
112 98 do_nul2:
113
2/2
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 11 times.
98 if(BOOST_JSON_LIKELY(ss))
114 76 ss.append('u');
115 else
116
1/1
✓ Branch 1 taken 10 times.
22 return suspend(state::nul2);
117 94 do_nul3:
118
2/2
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 9 times.
94 if(BOOST_JSON_LIKELY(ss))
119 76 ss.append('l');
120 else
121
1/1
✓ Branch 1 taken 9 times.
18 return suspend(state::nul3);
122 96 do_nul4:
123
2/2
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 10 times.
96 if(BOOST_JSON_LIKELY(ss))
124 76 ss.append('l');
125 else
126
1/1
✓ Branch 1 taken 10 times.
20 return suspend(state::nul4);
127 76 return true;
128 150 }
129
130 template<bool StackEmpty>
131 bool
132 56 serializer::
133 write_true(stream& ss0)
134 {
135 56 local_stream ss(ss0);
136
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
28 if(! StackEmpty && ! st_.empty())
137 {
138 state st;
139 28 st_.pop(st);
140
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
28 switch(st)
141 {
142 4 default:
143 4 case state::tru1: goto do_tru1;
144 8 case state::tru2: goto do_tru2;
145 8 case state::tru3: goto do_tru3;
146 8 case state::tru4: goto do_tru4;
147 }
148 }
149 28 do_tru1:
150
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 2 times.
32 if(BOOST_JSON_LIKELY(ss))
151 28 ss.append('t');
152 else
153
1/1
✓ Branch 1 taken 2 times.
4 return suspend(state::tru1);
154 36 do_tru2:
155
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 4 times.
36 if(BOOST_JSON_LIKELY(ss))
156 28 ss.append('r');
157 else
158
1/1
✓ Branch 1 taken 4 times.
8 return suspend(state::tru2);
159 36 do_tru3:
160
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 4 times.
36 if(BOOST_JSON_LIKELY(ss))
161 28 ss.append('u');
162 else
163
1/1
✓ Branch 1 taken 4 times.
8 return suspend(state::tru3);
164 36 do_tru4:
165
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 4 times.
36 if(BOOST_JSON_LIKELY(ss))
166 28 ss.append('e');
167 else
168
1/1
✓ Branch 1 taken 4 times.
8 return suspend(state::tru4);
169 28 return true;
170 56 }
171
172 template<bool StackEmpty>
173 bool
174 72 serializer::
175 write_false(stream& ss0)
176 {
177 72 local_stream ss(ss0);
178
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
36 if(! StackEmpty && ! st_.empty())
179 {
180 state st;
181 36 st_.pop(st);
182
5/5
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
36 switch(st)
183 {
184 4 default:
185 4 case state::fal1: goto do_fal1;
186 8 case state::fal2: goto do_fal2;
187 8 case state::fal3: goto do_fal3;
188 8 case state::fal4: goto do_fal4;
189 8 case state::fal5: goto do_fal5;
190 }
191 }
192 36 do_fal1:
193
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 2 times.
40 if(BOOST_JSON_LIKELY(ss))
194 36 ss.append('f');
195 else
196
1/1
✓ Branch 1 taken 2 times.
4 return suspend(state::fal1);
197 44 do_fal2:
198
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 4 times.
44 if(BOOST_JSON_LIKELY(ss))
199 36 ss.append('a');
200 else
201
1/1
✓ Branch 1 taken 4 times.
8 return suspend(state::fal2);
202 44 do_fal3:
203
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 4 times.
44 if(BOOST_JSON_LIKELY(ss))
204 36 ss.append('l');
205 else
206
1/1
✓ Branch 1 taken 4 times.
8 return suspend(state::fal3);
207 44 do_fal4:
208
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 4 times.
44 if(BOOST_JSON_LIKELY(ss))
209 36 ss.append('s');
210 else
211
1/1
✓ Branch 1 taken 4 times.
8 return suspend(state::fal4);
212 44 do_fal5:
213
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 4 times.
44 if(BOOST_JSON_LIKELY(ss))
214 36 ss.append('e');
215 else
216
1/1
✓ Branch 1 taken 4 times.
8 return suspend(state::fal5);
217 36 return true;
218 72 }
219
220 template<bool StackEmpty>
221 bool
222 85846 serializer::
223 write_string(stream& ss0)
224 {
225 85846 local_stream ss(ss0);
226 85846 local_const_stream cs(cs0_);
227
2/2
✓ Branch 1 taken 8839 times.
✓ Branch 2 taken 129 times.
17936 if(! StackEmpty && ! st_.empty())
228 {
229 state st;
230 17678 st_.pop(st);
231
9/9
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 8485 times.
✓ Branch 3 taken 26 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 24 times.
✓ Branch 6 taken 24 times.
✓ Branch 7 taken 24 times.
✓ Branch 8 taken 24 times.
17678 switch(st)
232 {
233 156 default:
234 156 case state::str1: goto do_str1;
235 260 case state::str2: goto do_str2;
236 16970 case state::str3: goto do_str3;
237 52 case state::esc1: goto do_esc1;
238 48 case state::utf1: goto do_utf1;
239 48 case state::utf2: goto do_utf2;
240 48 case state::utf3: goto do_utf3;
241 48 case state::utf4: goto do_utf4;
242 48 case state::utf5: goto do_utf5;
243 }
244 }
245 static constexpr char hex[] = "0123456789abcdef";
246 static constexpr char esc[] =
247 "uuuuuuuubtnufruuuuuuuuuuuuuuuuuu"
248 "\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"
249 "\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"
250 "\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"
251 "\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"
252 "\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"
253 "\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"
254 "\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";
255
256 // opening quote
257 68168 do_str1:
258
2/2
✓ Branch 1 taken 34084 times.
✓ Branch 2 taken 78 times.
68324 if(BOOST_JSON_LIKELY(ss))
259 68168 ss.append('\x22'); // '"'
260 else
261
1/1
✓ Branch 1 taken 78 times.
156 return suspend(state::str1);
262
263 // fast loop,
264 // copy unescaped
265 68428 do_str2:
266
2/2
✓ Branch 1 taken 34094 times.
✓ Branch 2 taken 120 times.
68428 if(BOOST_JSON_LIKELY(ss))
267 {
268 68188 std::size_t n = cs.remain();
269
2/2
✓ Branch 0 taken 34054 times.
✓ Branch 1 taken 40 times.
68188 if(BOOST_JSON_LIKELY(n > 0))
270 {
271
2/2
✓ Branch 1 taken 25559 times.
✓ Branch 2 taken 8495 times.
68108 if(ss.remain() > n)
272 51118 n = detail::count_unescaped(
273 cs.data(), n);
274 else
275 16990 n = detail::count_unescaped(
276 cs.data(), ss.remain());
277
2/2
✓ Branch 0 taken 25199 times.
✓ Branch 1 taken 8855 times.
68108 if(n > 0)
278 {
279 50398 ss.append(cs.data(), n);
280 50398 cs.skip(n);
281
2/2
✓ Branch 1 taken 25171 times.
✓ Branch 2 taken 28 times.
50398 if(! ss)
282
1/1
✓ Branch 1 taken 10 times.
20 return suspend(state::str2);
283 }
284 }
285 else
286 {
287 80 ss.append('\x22'); // '"'
288 80 return true;
289 }
290 }
291 else
292 {
293
1/1
✓ Branch 1 taken 120 times.
240 return suspend(state::str2);
294 }
295
296 // slow loop,
297 // handle escapes
298 85350 do_str3:
299
2/2
✓ Branch 1 taken 31449602 times.
✓ Branch 2 taken 8485 times.
62916174 while(BOOST_JSON_LIKELY(ss))
300 {
301
2/2
✓ Branch 1 taken 31415558 times.
✓ Branch 2 taken 34044 times.
62899204 if(BOOST_JSON_LIKELY(cs))
302 {
303 62831116 auto const ch = *cs;
304 62831116 auto const c = esc[static_cast<
305 unsigned char>(ch)];
306 62831116 ++cs;
307
2/2
✓ Branch 0 taken 31414880 times.
✓ Branch 1 taken 678 times.
62831116 if(! c)
308 {
309 62829760 ss.append(ch);
310 }
311
2/2
✓ Branch 0 taken 350 times.
✓ Branch 1 taken 328 times.
1356 else if(c != 'u')
312 {
313 700 ss.append('\\');
314
2/2
✓ Branch 1 taken 324 times.
✓ Branch 2 taken 26 times.
700 if(BOOST_JSON_LIKELY(ss))
315 {
316 648 ss.append(c);
317 }
318 else
319 {
320 52 buf_[0] = c;
321
1/1
✓ Branch 1 taken 26 times.
52 return suspend(
322 52 state::esc1);
323 }
324 }
325 else
326 {
327
2/2
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 120 times.
656 if(BOOST_JSON_LIKELY(
328 ss.remain() >= 6))
329 {
330 416 ss.append("\\u00", 4);
331 416 ss.append(hex[static_cast<
332 416 unsigned char>(ch) >> 4]);
333 416 ss.append(hex[static_cast<
334 416 unsigned char>(ch) & 15]);
335 }
336 else
337 {
338 240 ss.append('\\');
339 240 buf_[0] = hex[static_cast<
340 240 unsigned char>(ch) >> 4];
341 240 buf_[1] = hex[static_cast<
342 240 unsigned char>(ch) & 15];
343 240 goto do_utf1;
344 }
345 }
346 }
347 else
348 {
349 68088 ss.append('\x22'); // '"'
350 68088 return true;
351 }
352 }
353
1/1
✓ Branch 1 taken 8485 times.
16970 return suspend(state::str3);
354
355 52 do_esc1:
356
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
52 if(BOOST_JSON_LIKELY(ss))
357 52 ss.append(buf_[0]);
358 else
359 return suspend(state::esc1);
360 52 goto do_str3;
361
362 288 do_utf1:
363
2/2
✓ Branch 1 taken 120 times.
✓ Branch 2 taken 24 times.
288 if(BOOST_JSON_LIKELY(ss))
364 240 ss.append('u');
365 else
366
1/1
✓ Branch 1 taken 24 times.
48 return suspend(state::utf1);
367 288 do_utf2:
368
2/2
✓ Branch 1 taken 120 times.
✓ Branch 2 taken 24 times.
288 if(BOOST_JSON_LIKELY(ss))
369 240 ss.append('0');
370 else
371
1/1
✓ Branch 1 taken 24 times.
48 return suspend(state::utf2);
372 288 do_utf3:
373
2/2
✓ Branch 1 taken 120 times.
✓ Branch 2 taken 24 times.
288 if(BOOST_JSON_LIKELY(ss))
374 240 ss.append('0');
375 else
376
1/1
✓ Branch 1 taken 24 times.
48 return suspend(state::utf3);
377 288 do_utf4:
378
2/2
✓ Branch 1 taken 120 times.
✓ Branch 2 taken 24 times.
288 if(BOOST_JSON_LIKELY(ss))
379 240 ss.append(buf_[0]);
380 else
381
1/1
✓ Branch 1 taken 24 times.
48 return suspend(state::utf4);
382 288 do_utf5:
383
2/2
✓ Branch 1 taken 120 times.
✓ Branch 2 taken 24 times.
288 if(BOOST_JSON_LIKELY(ss))
384 240 ss.append(buf_[1]);
385 else
386
1/1
✓ Branch 1 taken 24 times.
48 return suspend(state::utf5);
387 240 goto do_str3;
388 85846 }
389
390 template<bool StackEmpty>
391 bool
392 8444 serializer::
393 write_number(stream& ss0)
394 {
395 8444 local_stream ss(ss0);
396
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 596 times.
1192 if(StackEmpty || st_.empty())
397 {
398
3/3
✓ Branch 1 taken 3111 times.
✓ Branch 2 taken 88 times.
✓ Branch 3 taken 427 times.
7252 switch(jv_->kind())
399 {
400 6222 default:
401 case kind::int64:
402
2/2
✓ Branch 1 taken 2559 times.
✓ Branch 2 taken 552 times.
6222 if(BOOST_JSON_LIKELY(
403 ss.remain() >=
404 detail::max_number_chars))
405 {
406 5118 ss.advance(detail::format_int64(
407 5118 ss.data(), jv_->get_int64()));
408 5118 return true;
409 }
410 1104 cs0_ = { buf_, detail::format_int64(
411 1104 buf_, jv_->get_int64()) };
412 1104 break;
413
414 176 case kind::uint64:
415
2/2
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 55 times.
176 if(BOOST_JSON_LIKELY(
416 ss.remain() >=
417 detail::max_number_chars))
418 {
419 66 ss.advance(detail::format_uint64(
420 66 ss.data(), jv_->get_uint64()));
421 66 return true;
422 }
423 110 cs0_ = { buf_, detail::format_uint64(
424 110 buf_, jv_->get_uint64()) };
425 110 break;
426
427 854 case kind::double_:
428
2/2
✓ Branch 1 taken 286 times.
✓ Branch 2 taken 141 times.
854 if(BOOST_JSON_LIKELY(
429 ss.remain() >=
430 detail::max_number_chars))
431 {
432 572 ss.advance(
433 572 detail::format_double(
434 ss.data(),
435 572 jv_->get_double(),
436 572 opts_.allow_infinity_and_nan));
437 572 return true;
438 }
439 282 cs0_ = { buf_, detail::format_double(
440 282 buf_, jv_->get_double(), opts_.allow_infinity_and_nan) };
441 282 break;
442 }
443 }
444 else
445 {
446 state st;
447 1192 st_.pop(st);
448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 596 times.
1192 BOOST_ASSERT(
449 st == state::num);
450 }
451 2688 auto const n = ss.remain();
452
2/2
✓ Branch 1 taken 597 times.
✓ Branch 2 taken 747 times.
2688 if(n < cs0_.remain())
453 {
454 1194 ss.append(cs0_.data(), n);
455 1194 cs0_.skip(n);
456
1/1
✓ Branch 1 taken 597 times.
1194 return suspend(state::num);
457 }
458 1494 ss.append(
459 cs0_.data(), cs0_.remain());
460 1494 return true;
461 8444 }
462
463 template<bool StackEmpty>
464 bool
465 9212 serializer::
466 write_array(stream& ss0)
467 {
468 array const* pa;
469 9212 local_stream ss(ss0);
470 array::const_iterator it;
471 array::const_iterator end;
472
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1318 times.
2636 if(StackEmpty || st_.empty())
473 {
474 6576 pa = pa_;
475 6576 it = pa->begin();
476 6576 end = pa->end();
477 }
478 else
479 {
480 state st;
481 2636 st_.pop(st);
482 2636 st_.pop(it);
483 2636 st_.pop(pa);
484 2636 end = pa->end();
485
4/4
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 1152 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 115 times.
2636 switch(st)
486 {
487 70 default:
488 70 case state::arr1: goto do_arr1;
489 2304 case state::arr2: goto do_arr2;
490 32 case state::arr3: goto do_arr3;
491 230 case state::arr4: goto do_arr4;
492 break;
493 }
494 }
495 6646 do_arr1:
496
2/2
✓ Branch 1 taken 3288 times.
✓ Branch 2 taken 35 times.
6646 if(BOOST_JSON_LIKELY(ss))
497 6576 ss.append('[');
498 else
499
1/1
✓ Branch 1 taken 35 times.
70 return suspend(
500 70 state::arr1, it, pa);
501
2/2
✓ Branch 0 taken 2774 times.
✓ Branch 1 taken 514 times.
6576 if(it == end)
502 990 goto do_arr4;
503 for(;;)
504 {
505 5586 do_arr2:
506 10014 jv_ = &*it;
507
3/4
✓ Branch 1 taken 5007 times.
✓ Branch 3 taken 1153 times.
✓ Branch 4 taken 3854 times.
✗ Branch 2 not taken.
10014 if(! write_value<StackEmpty>(ss))
508
1/1
✓ Branch 1 taken 1152 times.
2306 return suspend(
509 2304 state::arr2, it, pa);
510
2/2
✓ Branch 0 taken 2792 times.
✓ Branch 1 taken 1062 times.
7708 if(BOOST_JSON_UNLIKELY(
511 ++it == end))
512 5584 break;
513 2124 do_arr3:
514
2/2
✓ Branch 1 taken 1062 times.
✓ Branch 2 taken 16 times.
2156 if(BOOST_JSON_LIKELY(ss))
515 2124 ss.append(',');
516 else
517
1/1
✓ Branch 1 taken 16 times.
32 return suspend(
518 32 state::arr3, it, pa);
519 }
520 6804 do_arr4:
521
2/2
✓ Branch 1 taken 3287 times.
✓ Branch 2 taken 115 times.
6804 if(BOOST_JSON_LIKELY(ss))
522 6574 ss.append(']');
523 else
524
1/1
✓ Branch 1 taken 115 times.
230 return suspend(
525 230 state::arr4, it, pa);
526 6574 return true;
527 9212 }
528
529 template<bool StackEmpty>
530 bool
531 53290 serializer::
532 write_object(stream& ss0)
533 {
534 object const* po;
535 53290 local_stream ss(ss0);
536 object::const_iterator it;
537 object::const_iterator end;
538
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8534 times.
17068 if(StackEmpty || st_.empty())
539 {
540 36222 po = po_;
541 36222 it = po->begin();
542 36222 end = po->end();
543 }
544 else
545 {
546 state st;
547 17068 st_.pop(st);
548 17068 st_.pop(it);
549 17068 st_.pop(po);
550 17068 end = po->end();
551
6/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 133 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 8349 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 22 times.
17068 switch(st)
552 {
553 12 default:
554 12 case state::obj1: goto do_obj1;
555 266 case state::obj2: goto do_obj2;
556 40 case state::obj3: goto do_obj3;
557 16698 case state::obj4: goto do_obj4;
558 8 case state::obj5: goto do_obj5;
559 44 case state::obj6: goto do_obj6;
560 break;
561 }
562 }
563 36234 do_obj1:
564
2/2
✓ Branch 1 taken 18111 times.
✓ Branch 2 taken 6 times.
36234 if(BOOST_JSON_LIKELY(ss))
565 36222 ss.append('{');
566 else
567
1/1
✓ Branch 1 taken 6 times.
12 return suspend(
568 12 state::obj1, it, po);
569
2/2
✓ Branch 0 taken 557 times.
✓ Branch 1 taken 17554 times.
36222 if(BOOST_JSON_UNLIKELY(
570 it == end))
571 1114 goto do_obj6;
572 for(;;)
573 {
574 78152 cs0_ = {
575 39076 it->key().data(),
576 78152 it->key().size() };
577 39342 do_obj2:
578
3/4
✓ Branch 1 taken 19671 times.
✓ Branch 3 taken 133 times.
✓ Branch 4 taken 19538 times.
✗ Branch 2 not taken.
39342 if(BOOST_JSON_UNLIKELY(
579 ! write_string<StackEmpty>(ss)))
580
1/1
✓ Branch 1 taken 133 times.
266 return suspend(
581 266 state::obj2, it, po);
582 39076 do_obj3:
583
2/2
✓ Branch 1 taken 19538 times.
✓ Branch 2 taken 20 times.
39116 if(BOOST_JSON_LIKELY(ss))
584 39076 ss.append(':');
585 else
586
1/1
✓ Branch 1 taken 20 times.
40 return suspend(
587 40 state::obj3, it, po);
588 55774 do_obj4:
589 55774 jv_ = &it->value();
590
3/4
✓ Branch 1 taken 27887 times.
✓ Branch 3 taken 8349 times.
✓ Branch 4 taken 19538 times.
✗ Branch 2 not taken.
55774 if(BOOST_JSON_UNLIKELY(
591 ! write_value<StackEmpty>(ss)))
592
1/1
✓ Branch 1 taken 8349 times.
16698 return suspend(
593 16698 state::obj4, it, po);
594 39076 ++it;
595
2/2
✓ Branch 0 taken 17554 times.
✓ Branch 1 taken 1984 times.
39076 if(BOOST_JSON_UNLIKELY(it == end))
596 35108 break;
597 3968 do_obj5:
598
2/2
✓ Branch 1 taken 1984 times.
✓ Branch 2 taken 4 times.
3976 if(BOOST_JSON_LIKELY(ss))
599 3968 ss.append(',');
600 else
601
1/1
✓ Branch 1 taken 4 times.
8 return suspend(
602 8 state::obj5, it, po);
603 }
604 36266 do_obj6:
605
2/2
✓ Branch 1 taken 18111 times.
✓ Branch 2 taken 22 times.
36266 if(BOOST_JSON_LIKELY(ss))
606 {
607 36222 ss.append('}');
608 36222 return true;
609 }
610
1/1
✓ Branch 1 taken 22 times.
44 return suspend(
611 44 state::obj6, it, po);
612 53290 }
613
614 template<bool StackEmpty>
615 bool
616 126704 serializer::
617 write_value(stream& ss)
618 {
619
2/2
✓ Branch 1 taken 418 times.
✓ Branch 2 taken 19220 times.
39276 if(StackEmpty || st_.empty())
620 {
621 88264 auto const& jv(*jv_);
622
6/6
✓ Branch 1 taken 18060 times.
✓ Branch 2 taken 3283 times.
✓ Branch 3 taken 14543 times.
✓ Branch 4 taken 3626 times.
✓ Branch 5 taken 298 times.
✓ Branch 6 taken 4322 times.
88264 switch(jv.kind())
623 {
624 36120 default:
625 case kind::object:
626 36120 po_ = &jv.get_object();
627 36120 return write_object<true>(ss);
628
629 6566 case kind::array:
630 6566 pa_ = &jv.get_array();
631 6566 return write_array<true>(ss);
632
633 29086 case kind::string:
634 {
635 29086 auto const& js = jv.get_string();
636 29086 cs0_ = { js.data(), js.size() };
637 29086 return write_string<true>(ss);
638 }
639
640 7252 case kind::int64:
641 case kind::uint64:
642 case kind::double_:
643 7252 return write_number<true>(ss);
644
645 596 case kind::bool_:
646
2/2
✓ Branch 1 taken 135 times.
✓ Branch 2 taken 163 times.
596 if(jv.get_bool())
647 {
648
2/2
✓ Branch 1 taken 121 times.
✓ Branch 2 taken 14 times.
270 if(BOOST_JSON_LIKELY(
649 ss.remain() >= 4))
650 {
651 242 ss.append("true", 4);
652 242 return true;
653 }
654 28 return write_true<true>(ss);
655 }
656 else
657 {
658
2/2
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 18 times.
326 if(BOOST_JSON_LIKELY(
659 ss.remain() >= 5))
660 {
661 290 ss.append("false", 5);
662 290 return true;
663 }
664 36 return write_false<true>(ss);
665 }
666
667 8644 case kind::null:
668
2/2
✓ Branch 1 taken 4288 times.
✓ Branch 2 taken 34 times.
8644 if(BOOST_JSON_LIKELY(
669 ss.remain() >= 4))
670 {
671 8576 ss.append("null", 4);
672 8576 return true;
673 }
674 68 return write_null<true>(ss);
675 }
676 }
677 else
678 {
679 state st;
680 38440 st_.peek(st);
681
7/7
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 8706 times.
✓ Branch 4 taken 596 times.
✓ Branch 5 taken 1318 times.
✓ Branch 6 taken 8534 times.
38440 switch(st)
682 {
683 68 default:
684 case state::nul1: case state::nul2:
685 case state::nul3: case state::nul4:
686
1/1
✓ Branch 1 taken 34 times.
68 return write_null<StackEmpty>(ss);
687
688 28 case state::tru1: case state::tru2:
689 case state::tru3: case state::tru4:
690
1/1
✓ Branch 1 taken 14 times.
28 return write_true<StackEmpty>(ss);
691
692 36 case state::fal1: case state::fal2:
693 case state::fal3: case state::fal4:
694 case state::fal5:
695
1/1
✓ Branch 1 taken 18 times.
36 return write_false<StackEmpty>(ss);
696
697 17412 case state::str1: case state::str2:
698 case state::str3: case state::esc1:
699 case state::utf1: case state::utf2:
700 case state::utf3: case state::utf4:
701 case state::utf5:
702
1/1
✓ Branch 1 taken 8706 times.
17412 return write_string<StackEmpty>(ss);
703
704 1192 case state::num:
705
1/1
✓ Branch 1 taken 596 times.
1192 return write_number<StackEmpty>(ss);
706
707 2636 case state::arr1: case state::arr2:
708 case state::arr3: case state::arr4:
709
1/1
✓ Branch 1 taken 1318 times.
2636 return write_array<StackEmpty>(ss);
710
711 17068 case state::obj1: case state::obj2:
712 case state::obj3: case state::obj4:
713 case state::obj5: case state::obj6:
714
1/1
✓ Branch 1 taken 8534 times.
17068 return write_object<StackEmpty>(ss);
715 }
716 }
717 }
718
719 string_view
720 30524 serializer::
721 read_some(
722 char* dest, std::size_t size)
723 {
724 // If this goes off it means you forgot
725 // to call reset() before seriailzing a
726 // new value, or you never checked done()
727 // to see if you should stop.
728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30524 times.
30524 BOOST_ASSERT(! done_);
729
730 30524 stream ss(dest, size);
731
2/2
✓ Branch 1 taken 20803 times.
✓ Branch 2 taken 9721 times.
30524 if(st_.empty())
732
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 20803 times.
✓ Branch 3 taken 20801 times.
20803 (this->*fn0_)(ss);
733 else
734
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 9721 times.
✓ Branch 3 taken 9721 times.
9721 (this->*fn1_)(ss);
735
2/2
✓ Branch 1 taken 20801 times.
✓ Branch 2 taken 9721 times.
30522 if(st_.empty())
736 {
737 20801 done_ = true;
738 20801 jv_ = nullptr;
739 }
740 30522 return string_view(
741 30522 dest, ss.used(dest));
742 }
743
744 //----------------------------------------------------------
745
746 1948 serializer::
747 1948 serializer( serialize_options const& opts ) noexcept
748 1948 : opts_(opts)
749 {
750 // ensure room for \uXXXX escape plus one
751 BOOST_STATIC_ASSERT(
752 sizeof(serializer::buf_) >= 7);
753 1948 }
754
755 void
756 20739 serializer::
757 reset(value const* p) noexcept
758 {
759 20739 pv_ = p;
760 20739 fn0_ = &serializer::write_value<true>;
761 20739 fn1_ = &serializer::write_value<false>;
762
763 20739 jv_ = p;
764 20739 st_.clear();
765 20739 done_ = false;
766 20739 }
767
768 void
769 5 serializer::
770 reset(array const* p) noexcept
771 {
772 5 pa_ = p;
773 5 fn0_ = &serializer::write_array<true>;
774 5 fn1_ = &serializer::write_array<false>;
775 5 st_.clear();
776 5 done_ = false;
777 5 }
778
779 void
780 51 serializer::
781 reset(object const* p) noexcept
782 {
783 51 po_ = p;
784 51 fn0_ = &serializer::write_object<true>;
785 51 fn1_ = &serializer::write_object<false>;
786 51 st_.clear();
787 51 done_ = false;
788 51 }
789
790 void
791 2 serializer::
792 reset(string const* p) noexcept
793 {
794 2 cs0_ = { p->data(), p->size() };
795 2 fn0_ = &serializer::write_string<true>;
796 2 fn1_ = &serializer::write_string<false>;
797 2 st_.clear();
798 2 done_ = false;
799 2 }
800
801 void
802 1 serializer::
803 reset(string_view sv) noexcept
804 {
805 1 cs0_ = { sv.data(), sv.size() };
806 1 fn0_ = &serializer::write_string<true>;
807 1 fn1_ = &serializer::write_string<false>;
808 1 st_.clear();
809 1 done_ = false;
810 1 }
811
812 string_view
813 30524 serializer::
814 read(char* dest, std::size_t size)
815 {
816
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 30460 times.
30524 if(! jv_)
817 {
818
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 60 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
64 static value const null;
819 64 jv_ = &null;
820 }
821 30524 return read_some(dest, size);
822 }
823
824 } // namespace json
825 } // namespace boost
826
827 #ifdef _MSC_VER
828 #pragma warning(pop)
829 #endif
830
831 #endif
832