impl/serializer.ipp
100.0% Lines (285/0/285)
100.0% List of functions (37/0/37)
Functions (37)
Function
Calls
Lines
Blocks
(anonymous namespace)::format_special(char*, double, bool)
:28
15x
100.0%
94.0%
boost::json::detail::int64_formatter::operator()(char*) const
:86
3188x
100.0%
100.0%
boost::json::detail::uint64_formatter::operator()(char*) const
:97
425x
100.0%
100.0%
boost::json::detail::double_formatter::operator()(char*) const
:109
534x
100.0%
89.0%
boost::json::detail::writer::writer(boost::json::storage_ptr, unsigned char*, unsigned long, boost::json::serialize_options const&)
:126
21302x
100.0%
100.0%
bool boost::json::detail::write_buffer<boost::json::detail::double_formatter>(boost::json::detail::writer&, boost::json::detail::stream&, boost::json::detail::double_formatter)
:160
534x
100.0%
84.0%
bool boost::json::detail::write_buffer<boost::json::detail::int64_formatter>(boost::json::detail::writer&, boost::json::detail::stream&, boost::json::detail::int64_formatter)
:160
3188x
100.0%
84.0%
bool boost::json::detail::write_buffer<boost::json::detail::uint64_formatter>(boost::json::detail::writer&, boost::json::detail::stream&, boost::json::detail::uint64_formatter)
:160
425x
100.0%
84.0%
bool boost::json::detail::write_literal<(boost::json::detail::literals)0>(boost::json::detail::writer&, boost::json::detail::stream&)
:177
4352x
100.0%
100.0%
bool boost::json::detail::write_literal<(boost::json::detail::literals)1>(boost::json::detail::writer&, boost::json::detail::stream&)
:177
197x
100.0%
100.0%
bool boost::json::detail::write_literal<(boost::json::detail::literals)2>(boost::json::detail::writer&, boost::json::detail::stream&)
:177
176x
100.0%
100.0%
boost::json::detail::write_true(boost::json::detail::writer&, boost::json::detail::stream&)
:197
197x
100.0%
100.0%
boost::json::detail::write_false(boost::json::detail::writer&, boost::json::detail::stream&)
:203
176x
100.0%
100.0%
boost::json::detail::write_null(boost::json::detail::writer&, boost::json::detail::stream&)
:209
4352x
100.0%
100.0%
boost::json::detail::write_int64(boost::json::detail::writer&, boost::json::detail::stream&, long)
:215
3188x
100.0%
100.0%
boost::json::detail::write_uint64(boost::json::detail::writer&, boost::json::detail::stream&, unsigned long)
:221
425x
100.0%
100.0%
boost::json::detail::write_double(boost::json::detail::writer&, boost::json::detail::stream&, double)
:227
534x
100.0%
100.0%
boost::json::detail::resume_buffer(boost::json::detail::writer&, boost::json::detail::stream&)
:234
1558x
100.0%
82.0%
bool boost::json::detail::do_write_string<false>(boost::json::detail::writer&, boost::json::detail::stream&)
:246
9812x
96.7%
90.0%
bool boost::json::detail::do_write_string<true>(boost::json::detail::writer&, boost::json::detail::stream&)
:246
34473x
97.3%
94.0%
boost::json::detail::write_string(boost::json::detail::writer&, boost::json::detail::stream&)
:412
19827x
100.0%
100.0%
boost::json::detail::resume_string(boost::json::detail::writer&, boost::json::detail::stream&)
:418
408x
100.0%
100.0%
bool boost::json::detail::write_array<false>(boost::json::detail::writer&, boost::json::detail::stream&)
:437
2662x
100.0%
77.0%
bool boost::json::detail::write_array<true>(boost::json::detail::writer&, boost::json::detail::stream&)
:437
3418x
100.0%
98.0%
bool boost::json::detail::write_object<false>(boost::json::detail::writer&, boost::json::detail::stream&)
:444
9060x
100.0%
83.0%
bool boost::json::detail::write_object<true>(boost::json::detail::writer&, boost::json::detail::stream&)
:444
18134x
100.0%
93.0%
bool boost::json::detail::write_value<false>(boost::json::detail::writer&, boost::json::detail::stream&)
:451
23041x
86.5%
81.0%
bool boost::json::detail::write_value<true>(boost::json::detail::writer&, boost::json::detail::stream&)
:451
44090x
100.0%
97.0%
boost::json::serializer::serializer(boost::json::serialize_options const&)
:523
2405x
100.0%
100.0%
boost::json::serializer::serializer(boost::json::storage_ptr, unsigned char*, unsigned long, boost::json::serialize_options const&)
:528
21302x
100.0%
100.0%
boost::json::serializer::reset(boost::json::value const*)
:538
21016x
100.0%
100.0%
boost::json::serializer::reset(boost::json::array const*)
:549
5x
100.0%
100.0%
boost::json::serializer::reset(boost::json::object const*)
:560
51x
100.0%
100.0%
boost::json::serializer::reset(boost::json::string const*)
:571
2x
100.0%
100.0%
boost::json::serializer::reset(boost::core::basic_string_view<char>)
:582
1x
100.0%
100.0%
boost::json::serializer::reset(decltype(nullptr))
:593
6x
100.0%
100.0%
boost::json::serializer::read(char*, unsigned long)
:603
33154x
100.0%
100.0%
| Line | TLA | Hits | Source Code |
|---|---|---|---|
| 1 | // | ||
| 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | ||
| 3 | // | ||
| 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
| 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| 6 | // | ||
| 7 | // Official repository: https://github.com/boostorg/json | ||
| 8 | // | ||
| 9 | |||
| 10 | #ifndef BOOST_JSON_IMPL_SERIALIZER_IPP | ||
| 11 | #define BOOST_JSON_IMPL_SERIALIZER_IPP | ||
| 12 | |||
| 13 | #include <boost/charconv/to_chars.hpp> | ||
| 14 | #include <boost/core/detail/static_assert.hpp> | ||
| 15 | #include <boost/json/serializer.hpp> | ||
| 16 | #include <boost/json/detail/format.hpp> | ||
| 17 | #include <boost/json/detail/sse2.hpp> | ||
| 18 | |||
| 19 | #ifdef _MSC_VER | ||
| 20 | #pragma warning(push) | ||
| 21 | #pragma warning(disable: 4127) // conditional expression is constant | ||
| 22 | #endif | ||
| 23 | |||
| 24 | namespace { | ||
| 25 | |||
| 26 | std::size_t | ||
| 27 | BOOST_NOINLINE | ||
| 28 | 15x | format_special(char* dest, double d, bool allow_infinity_and_nan) noexcept | |
| 29 | { | ||
| 30 | 15x | if( std::isinf(d) ) | |
| 31 | { | ||
| 32 | 10x | if( std::signbit(d) ) | |
| 33 | { | ||
| 34 | 5x | if( allow_infinity_and_nan ) | |
| 35 | { | ||
| 36 | 2x | std::memcpy(dest, "-Infinity", 9); | |
| 37 | 2x | return 9; | |
| 38 | } | ||
| 39 | else | ||
| 40 | { | ||
| 41 | 3x | std::memcpy(dest, "-1e99999", 8); | |
| 42 | 3x | return 8; | |
| 43 | } | ||
| 44 | } | ||
| 45 | else | ||
| 46 | { | ||
| 47 | 5x | if( allow_infinity_and_nan ) | |
| 48 | { | ||
| 49 | 2x | std::memcpy(dest, "Infinity", 8); | |
| 50 | 2x | return 8; | |
| 51 | } | ||
| 52 | else | ||
| 53 | { | ||
| 54 | 3x | std::memcpy(dest, "1e99999", 7); | |
| 55 | 3x | return 7; | |
| 56 | } | ||
| 57 | } | ||
| 58 | } | ||
| 59 | else | ||
| 60 | { | ||
| 61 | 5x | BOOST_ASSERT( std::isnan(d) ); | |
| 62 | 5x | if( allow_infinity_and_nan ) | |
| 63 | { | ||
| 64 | 2x | std::memcpy(dest, "NaN", 3); | |
| 65 | 2x | return 3; | |
| 66 | } | ||
| 67 | else | ||
| 68 | { | ||
| 69 | 3x | std::memcpy(dest, "null", 4); | |
| 70 | 3x | return 4; | |
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | } // namespace | ||
| 76 | |||
| 77 | namespace boost { | ||
| 78 | namespace json { | ||
| 79 | namespace detail { | ||
| 80 | |||
| 81 | struct int64_formatter | ||
| 82 | { | ||
| 83 | std::int64_t i; | ||
| 84 | |||
| 85 | std::size_t | ||
| 86 | 3188x | operator()(char* dst) const noexcept | |
| 87 | { | ||
| 88 | 3188x | return format_int64(dst, i); | |
| 89 | } | ||
| 90 | }; | ||
| 91 | |||
| 92 | struct uint64_formatter | ||
| 93 | { | ||
| 94 | std::uint64_t u; | ||
| 95 | |||
| 96 | std::size_t | ||
| 97 | 425x | operator()(char* dst) const noexcept | |
| 98 | { | ||
| 99 | 425x | return format_uint64(dst, u); | |
| 100 | } | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct double_formatter | ||
| 104 | { | ||
| 105 | double d; | ||
| 106 | bool allow_infinity_and_nan; | ||
| 107 | |||
| 108 | std::size_t | ||
| 109 | 534x | operator()(char* dst) const noexcept | |
| 110 | { | ||
| 111 | 534x | if(BOOST_JSON_UNLIKELY( !std::isfinite(d)) ) | |
| 112 | { | ||
| 113 | 15x | return format_special(dst, d, allow_infinity_and_nan); | |
| 114 | } | ||
| 115 | |||
| 116 | 519x | auto const result = boost::charconv::to_chars( | |
| 117 | dst, | ||
| 118 | dst + detail::max_number_chars, | ||
| 119 | 519x | d, | |
| 120 | boost::charconv::chars_format::scientific); | ||
| 121 | 519x | BOOST_ASSERT( result.ec == std::errc() ); | |
| 122 | 519x | return result.ptr - dst; | |
| 123 | } | ||
| 124 | }; | ||
| 125 | |||
| 126 | 21302x | writer:: | |
| 127 | writer( | ||
| 128 | storage_ptr sp, | ||
| 129 | unsigned char* buf, | ||
| 130 | std::size_t buf_size, | ||
| 131 | 21302x | serialize_options const& opts) noexcept | |
| 132 | 21302x | : st_( | |
| 133 | 21302x | std::move(sp), | |
| 134 | buf, | ||
| 135 | buf_size) | ||
| 136 | 21302x | , opts_(opts) | |
| 137 | { | ||
| 138 | // ensure room for \uXXXX escape plus one | ||
| 139 | BOOST_CORE_STATIC_ASSERT( sizeof(buf_) >= 7 ); | ||
| 140 | 21302x | } | |
| 141 | |||
| 142 | bool | ||
| 143 | BOOST_FORCEINLINE | ||
| 144 | write_buffer(writer& w, stream& ss0) | ||
| 145 | { | ||
| 146 | 1558x | local_stream ss(ss0); | |
| 147 | 2744x | auto const n = ss.remain(); | |
| 148 | 2744x | if( n < w.cs0_.remain() ) | |
| 149 | { | ||
| 150 | 1448x | ss.append(w.cs0_.data(), n); | |
| 151 | 1448x | w.cs0_.skip(n); | |
| 152 | 1448x | return w.suspend(writer::state::lit); | |
| 153 | } | ||
| 154 | 1296x | ss.append( w.cs0_.data(), w.cs0_.remain() ); | |
| 155 | 1296x | return true; | |
| 156 | 2744x | } | |
| 157 | |||
| 158 | template< class F > | ||
| 159 | bool | ||
| 160 | 4147x | write_buffer(writer& w, stream& ss0, F f) | |
| 161 | { | ||
| 162 | 4147x | BOOST_ASSERT( w.st_.empty() ); | |
| 163 | |||
| 164 | 4147x | local_stream ss(ss0); | |
| 165 | 4147x | if(BOOST_JSON_LIKELY( ss.remain() >= detail::max_number_chars )) | |
| 166 | { | ||
| 167 | 2961x | ss.advance( f(ss.data()) ); | |
| 168 | 2961x | return true; | |
| 169 | } | ||
| 170 | |||
| 171 | 1186x | w.cs0_ = { w.buf_, f(w.buf_) }; | |
| 172 | 1186x | return write_buffer(w, ss); | |
| 173 | 4147x | } | |
| 174 | |||
| 175 | template<literals Lit> | ||
| 176 | bool | ||
| 177 | 4725x | write_literal(writer& w, stream& ss) | |
| 178 | { | ||
| 179 | 4725x | constexpr std::size_t index = literal_index(Lit); | |
| 180 | 4725x | constexpr char const* literal = literal_strings[index]; | |
| 181 | 4725x | constexpr std::size_t sz = literal_sizes[index]; | |
| 182 | |||
| 183 | 4725x | std::size_t const n = ss.remain(); | |
| 184 | 4725x | if(BOOST_JSON_LIKELY( n >= sz )) | |
| 185 | { | ||
| 186 | 4613x | ss.append( literal, sz ); | |
| 187 | 4613x | return true; | |
| 188 | } | ||
| 189 | |||
| 190 | 112x | ss.append(literal, n); | |
| 191 | |||
| 192 | 112x | w.cs0_ = {literal + n, sz - n}; | |
| 193 | 112x | return w.suspend(writer::state::lit); | |
| 194 | } | ||
| 195 | |||
| 196 | bool | ||
| 197 | 197x | write_true(writer& w, stream& ss) | |
| 198 | { | ||
| 199 | 197x | return write_literal<literals::true_>(w, ss); | |
| 200 | } | ||
| 201 | |||
| 202 | bool | ||
| 203 | 176x | write_false(writer& w, stream& ss) | |
| 204 | { | ||
| 205 | 176x | return write_literal<literals::false_>(w, ss); | |
| 206 | } | ||
| 207 | |||
| 208 | bool | ||
| 209 | 4352x | write_null(writer& w, stream& ss) | |
| 210 | { | ||
| 211 | 4352x | return write_literal<literals::null>(w, ss); | |
| 212 | } | ||
| 213 | |||
| 214 | bool | ||
| 215 | 3188x | write_int64(writer& w, stream& ss0, std::int64_t i) | |
| 216 | { | ||
| 217 | 3188x | return write_buffer( w, ss0, int64_formatter{i} ); | |
| 218 | } | ||
| 219 | |||
| 220 | bool | ||
| 221 | 425x | write_uint64(writer& w, stream& ss0, std::uint64_t u) | |
| 222 | { | ||
| 223 | 425x | return write_buffer( w, ss0, uint64_formatter{u} ); | |
| 224 | } | ||
| 225 | |||
| 226 | bool | ||
| 227 | 534x | write_double(writer& w, stream& ss0, double d) | |
| 228 | { | ||
| 229 | 1068x | return write_buffer( | |
| 230 | 534x | w, ss0, double_formatter{d, w.opts_.allow_infinity_and_nan} ); | |
| 231 | } | ||
| 232 | |||
| 233 | bool | ||
| 234 | 1558x | resume_buffer(writer& w, stream& ss0) | |
| 235 | { | ||
| 236 | 1558x | BOOST_ASSERT( !w.st_.empty() ); | |
| 237 | writer::state st; | ||
| 238 | 1558x | w.st_.pop(st); | |
| 239 | 1558x | BOOST_ASSERT(st == writer::state::lit); | |
| 240 | |||
| 241 | 3116x | return write_buffer(w, ss0); | |
| 242 | } | ||
| 243 | |||
| 244 | template<bool StackEmpty> | ||
| 245 | bool | ||
| 246 | 44285x | do_write_string(writer& w, stream& ss0) | |
| 247 | { | ||
| 248 | 44285x | local_stream ss(ss0); | |
| 249 | 44285x | local_const_stream cs(w.cs0_); | |
| 250 | 9812x | if(! StackEmpty && ! w.st_.empty()) | |
| 251 | { | ||
| 252 | writer::state st; | ||
| 253 | 9812x | w.st_.pop(st); | |
| 254 | 9812x | switch(st) | |
| 255 | { | ||
| 256 | 170x | default: | |
| 257 | 170x | case writer::state::str1: goto do_str1; | |
| 258 | 268x | case writer::state::str2: goto do_str2; | |
| 259 | 9082x | case writer::state::str3: goto do_str3; | |
| 260 | 52x | case writer::state::esc1: goto do_esc1; | |
| 261 | 48x | case writer::state::utf1: goto do_utf1; | |
| 262 | 48x | case writer::state::utf2: goto do_utf2; | |
| 263 | 48x | case writer::state::utf3: goto do_utf3; | |
| 264 | 48x | case writer::state::utf4: goto do_utf4; | |
| 265 | 48x | case writer::state::utf5: goto do_utf5; | |
| 266 | } | ||
| 267 | } | ||
| 268 | static constexpr char hex[] = "0123456789abcdef"; | ||
| 269 | static constexpr char esc[] = | ||
| 270 | "uuuuuuuubtnufruuuuuuuuuuuuuuuuuu" | ||
| 271 | "\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | ||
| 272 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0" | ||
| 273 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | ||
| 274 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | ||
| 275 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | ||
| 276 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" | ||
| 277 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; | ||
| 278 | |||
| 279 | // opening quote | ||
| 280 | 34473x | do_str1: | |
| 281 | 34643x | if(BOOST_JSON_LIKELY(ss)) | |
| 282 | 34473x | ss.append('\x22'); // '"' | |
| 283 | else | ||
| 284 | 170x | return w.suspend(writer::state::str1); | |
| 285 | |||
| 286 | // fast loop, | ||
| 287 | // copy unescaped | ||
| 288 | 34741x | do_str2: | |
| 289 | 34741x | if(BOOST_JSON_LIKELY(ss)) | |
| 290 | { | ||
| 291 | 34485x | std::size_t n = cs.remain(); | |
| 292 | 34485x | if(BOOST_JSON_LIKELY(n > 0)) | |
| 293 | { | ||
| 294 | 34441x | if(ss.remain() > n) | |
| 295 | 25766x | n = detail::count_unescaped( | |
| 296 | cs.data(), n); | ||
| 297 | else | ||
| 298 | 8675x | n = detail::count_unescaped( | |
| 299 | cs.data(), ss.remain()); | ||
| 300 | 34441x | if(n > 0) | |
| 301 | { | ||
| 302 | 25225x | ss.append(cs.data(), n); | |
| 303 | 25225x | cs.skip(n); | |
| 304 | 25225x | if(! ss) | |
| 305 | 12x | return w.suspend(writer::state::str2); | |
| 306 | } | ||
| 307 | } | ||
| 308 | else | ||
| 309 | { | ||
| 310 | 44x | ss.append('\x22'); // '"' | |
| 311 | 44x | return true; | |
| 312 | } | ||
| 313 | } | ||
| 314 | else | ||
| 315 | { | ||
| 316 | 256x | return w.suspend(writer::state::str2); | |
| 317 | } | ||
| 318 | |||
| 319 | // slow loop, | ||
| 320 | // handle escapes | ||
| 321 | 43707x | do_str3: | |
| 322 | 31461016x | while(BOOST_JSON_LIKELY(ss)) | |
| 323 | { | ||
| 324 | 31451934x | if(BOOST_JSON_LIKELY(cs)) | |
| 325 | { | ||
| 326 | 31417505x | auto const ch = *cs; | |
| 327 | 31417505x | auto const c = esc[static_cast< | |
| 328 | unsigned char>(ch)]; | ||
| 329 | 31417505x | ++cs; | |
| 330 | 31417505x | if(! c) | |
| 331 | { | ||
| 332 | 31416777x | ss.append(ch); | |
| 333 | } | ||
| 334 | 728x | else if(c != 'u') | |
| 335 | { | ||
| 336 | 376x | ss.append('\\'); | |
| 337 | 376x | if(BOOST_JSON_LIKELY(ss)) | |
| 338 | { | ||
| 339 | 324x | ss.append(c); | |
| 340 | } | ||
| 341 | else | ||
| 342 | { | ||
| 343 | 52x | w.buf_[0] = c; | |
| 344 | 52x | return w.suspend( | |
| 345 | 52x | writer::state::esc1); | |
| 346 | } | ||
| 347 | } | ||
| 348 | else | ||
| 349 | { | ||
| 350 | 352x | if(BOOST_JSON_LIKELY( | |
| 351 | ss.remain() >= 6)) | ||
| 352 | { | ||
| 353 | 208x | ss.append("\\u00", 4); | |
| 354 | 208x | ss.append(hex[static_cast< | |
| 355 | 208x | unsigned char>(ch) >> 4]); | |
| 356 | 208x | ss.append(hex[static_cast< | |
| 357 | 208x | unsigned char>(ch) & 15]); | |
| 358 | } | ||
| 359 | else | ||
| 360 | { | ||
| 361 | 144x | ss.append('\\'); | |
| 362 | 144x | w.buf_[0] = hex[static_cast< | |
| 363 | 144x | unsigned char>(ch) >> 4]; | |
| 364 | 144x | w.buf_[1] = hex[static_cast< | |
| 365 | 144x | unsigned char>(ch) & 15]; | |
| 366 | 144x | goto do_utf1; | |
| 367 | } | ||
| 368 | } | ||
| 369 | } | ||
| 370 | else | ||
| 371 | { | ||
| 372 | 34429x | ss.append('\x22'); // '"' | |
| 373 | 34429x | return true; | |
| 374 | } | ||
| 375 | } | ||
| 376 | 9082x | return w.suspend(writer::state::str3); | |
| 377 | |||
| 378 | 52x | do_esc1: | |
| 379 | 52x | BOOST_ASSERT(ss); | |
| 380 | 52x | ss.append(w.buf_[0]); | |
| 381 | 52x | goto do_str3; | |
| 382 | |||
| 383 | 192x | do_utf1: | |
| 384 | 192x | if(BOOST_JSON_LIKELY(ss)) | |
| 385 | 144x | ss.append('u'); | |
| 386 | else | ||
| 387 | 48x | return w.suspend(writer::state::utf1); | |
| 388 | 192x | do_utf2: | |
| 389 | 192x | if(BOOST_JSON_LIKELY(ss)) | |
| 390 | 144x | ss.append('0'); | |
| 391 | else | ||
| 392 | 48x | return w.suspend(writer::state::utf2); | |
| 393 | 192x | do_utf3: | |
| 394 | 192x | if(BOOST_JSON_LIKELY(ss)) | |
| 395 | 144x | ss.append('0'); | |
| 396 | else | ||
| 397 | 48x | return w.suspend(writer::state::utf3); | |
| 398 | 192x | do_utf4: | |
| 399 | 192x | if(BOOST_JSON_LIKELY(ss)) | |
| 400 | 144x | ss.append(w.buf_[0]); | |
| 401 | else | ||
| 402 | 48x | return w.suspend(writer::state::utf4); | |
| 403 | 192x | do_utf5: | |
| 404 | 192x | if(BOOST_JSON_LIKELY(ss)) | |
| 405 | 144x | ss.append(w.buf_[1]); | |
| 406 | else | ||
| 407 | 48x | return w.suspend(writer::state::utf5); | |
| 408 | 144x | goto do_str3; | |
| 409 | 44285x | } | |
| 410 | |||
| 411 | bool | ||
| 412 | 19827x | write_string(writer& w, stream& ss0) | |
| 413 | { | ||
| 414 | 19827x | return do_write_string<true>(w, ss0); | |
| 415 | } | ||
| 416 | |||
| 417 | bool | ||
| 418 | 408x | resume_string(writer& w, stream& ss0) | |
| 419 | { | ||
| 420 | 408x | return do_write_string<false>(w, ss0); | |
| 421 | } | ||
| 422 | |||
| 423 | template<bool StackEmpty> | ||
| 424 | bool | ||
| 425 | write_value(writer& w, stream& ss); | ||
| 426 | |||
| 427 | template< class T, bool StackEmpty > | ||
| 428 | BOOST_FORCEINLINE | ||
| 429 | bool | ||
| 430 | write_impl(no_conversion_tag, writer& w, stream& ss) | ||
| 431 | { | ||
| 432 | 34575x | return write_value<StackEmpty>(w, ss); | |
| 433 | } | ||
| 434 | |||
| 435 | template<bool StackEmpty> | ||
| 436 | bool | ||
| 437 | 6080x | write_array(writer& w, stream& ss) | |
| 438 | { | ||
| 439 | 6079x | return write_impl<array, StackEmpty>(sequence_conversion_tag(), w, ss); | |
| 440 | } | ||
| 441 | |||
| 442 | template<bool StackEmpty> | ||
| 443 | bool | ||
| 444 | 27194x | write_object(writer& w, stream& ss) | |
| 445 | { | ||
| 446 | 27194x | return write_impl<object, StackEmpty>(map_like_conversion_tag(), w, ss); | |
| 447 | } | ||
| 448 | |||
| 449 | template<bool StackEmpty> | ||
| 450 | bool | ||
| 451 | 67131x | write_value(writer& w, stream& ss) | |
| 452 | { | ||
| 453 | 23041x | if(StackEmpty || w.st_.empty()) | |
| 454 | { | ||
| 455 | 44571x | BOOST_ASSERT( w.p_ ); | |
| 456 | 44571x | auto const pv = reinterpret_cast<value const*>(w.p_); | |
| 457 | 44571x | switch(pv->kind()) | |
| 458 | { | ||
| 459 | 18083x | default: | |
| 460 | case kind::object: | ||
| 461 | 18083x | w.p_ = &pv->get_object(); | |
| 462 | 18083x | return write_object<true>(w, ss); | |
| 463 | |||
| 464 | 3413x | case kind::array: | |
| 465 | 3413x | w.p_ = &pv->get_array(); | |
| 466 | 3413x | return write_array<true>(w, ss); | |
| 467 | |||
| 468 | 14643x | case kind::string: | |
| 469 | { | ||
| 470 | 14643x | auto const& js = pv->get_string(); | |
| 471 | 14643x | w.cs0_ = { js.data(), js.size() }; | |
| 472 | 14643x | return do_write_string<true>(w, ss); | |
| 473 | } | ||
| 474 | |||
| 475 | 3182x | case kind::int64: | |
| 476 | 3182x | return write_int64( w, ss, pv->get_int64() ); | |
| 477 | 91x | case kind::uint64: | |
| 478 | 91x | return write_uint64( w, ss, pv->get_uint64() ); | |
| 479 | 522x | case kind::double_: | |
| 480 | 522x | return write_double( w, ss, pv->get_double() ); | |
| 481 | |||
| 482 | 306x | case kind::bool_: | |
| 483 | 306x | if( pv->get_bool() ) | |
| 484 | 139x | return write_true(w, ss); | |
| 485 | else | ||
| 486 | 167x | return write_false(w, ss); | |
| 487 | |||
| 488 | 4331x | case kind::null: | |
| 489 | 4331x | return write_null(w, ss); | |
| 490 | } | ||
| 491 | } | ||
| 492 | else | ||
| 493 | { | ||
| 494 | writer::state st; | ||
| 495 | 22560x | w.st_.peek(st); | |
| 496 | 22560x | switch(st) | |
| 497 | { | ||
| 498 | 1434x | default: | |
| 499 | case writer::state::lit: | ||
| 500 | 1434x | return resume_buffer(w, ss); | |
| 501 | |||
| 502 | 9404x | case writer::state::str1: case writer::state::str2: | |
| 503 | case writer::state::str3: case writer::state::esc1: | ||
| 504 | case writer::state::utf1: case writer::state::utf2: | ||
| 505 | case writer::state::utf3: case writer::state::utf4: | ||
| 506 | case writer::state::utf5: | ||
| 507 | 9404x | return do_write_string<false>(w, ss); | |
| 508 | |||
| 509 | 2662x | case writer::state::arr1: case writer::state::arr2: | |
| 510 | case writer::state::arr3: case writer::state::arr4: | ||
| 511 | 2662x | return write_array<StackEmpty>(w, ss); | |
| 512 | |||
| 513 | 9060x | case writer::state::obj1: case writer::state::obj2: | |
| 514 | case writer::state::obj3: case writer::state::obj4: | ||
| 515 | case writer::state::obj5: case writer::state::obj6: | ||
| 516 | 9060x | return write_object<StackEmpty>(w, ss); | |
| 517 | } | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | } // namespace detail | ||
| 522 | |||
| 523 | 2405x | serializer:: | |
| 524 | 2405x | serializer(serialize_options const& opts) noexcept | |
| 525 | 2405x | : serializer({}, nullptr, 0, opts) | |
| 526 | 2405x | {} | |
| 527 | |||
| 528 | 21302x | serializer:: | |
| 529 | serializer( | ||
| 530 | storage_ptr sp, | ||
| 531 | unsigned char* buf, | ||
| 532 | std::size_t buf_size, | ||
| 533 | 21302x | serialize_options const& opts) noexcept | |
| 534 | 21302x | : detail::writer(std::move(sp), buf, buf_size, opts) | |
| 535 | 21302x | {} | |
| 536 | |||
| 537 | void | ||
| 538 | 21016x | serializer:: | |
| 539 | reset(value const* p) noexcept | ||
| 540 | { | ||
| 541 | 21016x | p_ = p; | |
| 542 | 21016x | fn0_ = &detail::write_value<true>; | |
| 543 | 21016x | fn1_ = &detail::write_value<false>; | |
| 544 | 21016x | st_.clear(); | |
| 545 | 21016x | done_ = false; | |
| 546 | 21016x | } | |
| 547 | |||
| 548 | void | ||
| 549 | 5x | serializer:: | |
| 550 | reset(array const* p) noexcept | ||
| 551 | { | ||
| 552 | 5x | p_ = p; | |
| 553 | 5x | fn0_ = &detail::write_array<true>; | |
| 554 | 5x | fn1_ = &detail::write_array<false>; | |
| 555 | 5x | st_.clear(); | |
| 556 | 5x | done_ = false; | |
| 557 | 5x | } | |
| 558 | |||
| 559 | void | ||
| 560 | 51x | serializer:: | |
| 561 | reset(object const* p) noexcept | ||
| 562 | { | ||
| 563 | 51x | p_ = p; | |
| 564 | 51x | fn0_ = &detail::write_object<true>; | |
| 565 | 51x | fn1_ = &detail::write_object<false>; | |
| 566 | 51x | st_.clear(); | |
| 567 | 51x | done_ = false; | |
| 568 | 51x | } | |
| 569 | |||
| 570 | void | ||
| 571 | 2x | serializer:: | |
| 572 | reset(string const* p) noexcept | ||
| 573 | { | ||
| 574 | 2x | cs0_ = { p->data(), p->size() }; | |
| 575 | 2x | fn0_ = &detail::do_write_string<true>; | |
| 576 | 2x | fn1_ = &detail::do_write_string<false>; | |
| 577 | 2x | st_.clear(); | |
| 578 | 2x | done_ = false; | |
| 579 | 2x | } | |
| 580 | |||
| 581 | void | ||
| 582 | 1x | serializer:: | |
| 583 | reset(string_view sv) noexcept | ||
| 584 | { | ||
| 585 | 1x | cs0_ = { sv.data(), sv.size() }; | |
| 586 | 1x | fn0_ = &detail::do_write_string<true>; | |
| 587 | 1x | fn1_ = &detail::do_write_string<false>; | |
| 588 | 1x | st_.clear(); | |
| 589 | 1x | done_ = false; | |
| 590 | 1x | } | |
| 591 | |||
| 592 | void | ||
| 593 | 6x | serializer::reset(std::nullptr_t) noexcept | |
| 594 | { | ||
| 595 | 6x | p_ = nullptr; | |
| 596 | 6x | fn0_ = &detail::write_impl<std::nullptr_t, true>; | |
| 597 | 6x | fn1_ = &detail::write_impl<std::nullptr_t, false>; | |
| 598 | 6x | st_.clear(); | |
| 599 | 6x | done_ = false; | |
| 600 | 6x | } | |
| 601 | |||
| 602 | string_view | ||
| 603 | 33154x | serializer:: | |
| 604 | read(char* dest, std::size_t size) | ||
| 605 | { | ||
| 606 | 33154x | if( !fn0_ ) | |
| 607 | 6x | reset(nullptr); | |
| 608 | |||
| 609 | 33154x | if(BOOST_JSON_UNLIKELY(size == 0)) | |
| 610 | 1x | return {dest, 0}; | |
| 611 | |||
| 612 | 33153x | detail::stream ss(dest, size); | |
| 613 | 33153x | if(st_.empty()) | |
| 614 | 21301x | fn0_(*this, ss); | |
| 615 | else | ||
| 616 | 11852x | fn1_(*this, ss); | |
| 617 | 33151x | if(st_.empty()) | |
| 618 | { | ||
| 619 | 21299x | done_ = true; | |
| 620 | 21299x | fn0_ = nullptr; | |
| 621 | 21299x | p_ = nullptr; | |
| 622 | } | ||
| 623 | 33151x | return string_view( | |
| 624 | 33151x | dest, ss.used(dest)); | |
| 625 | } | ||
| 626 | |||
| 627 | } // namespace json | ||
| 628 | } // namespace boost | ||
| 629 | |||
| 630 | #ifdef _MSC_VER | ||
| 631 | #pragma warning(pop) | ||
| 632 | #endif | ||
| 633 | |||
| 634 | #endif | ||
| 635 |