| 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 |