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