100.00% Lines (261/261) 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   21245 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   21245 serialize_options const& opts) noexcept
HITCBC 67   21245 : st_( 67   21245 : st_(
HITCBC 68   21245 std::move(sp), 68   21245 std::move(sp),
69   buf, 69   buf,
70   buf_size) 70   buf_size)
HITCBC 71   21245 , opts_(opts) 71   21245 , 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   21245 }
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   44285 do_write_string(writer& w, stream& ss0)
182   { 182   {
HITCBC 183   44285 local_stream ss(ss0); 183   44285 local_stream ss(ss0);
HITCBC 184   44285 local_const_stream cs(w.cs0_); 184   44285 local_const_stream cs(w.cs0_);
HITCBC 185   9812 if(! StackEmpty && ! w.st_.empty()) 185   9812 if(! StackEmpty && ! w.st_.empty())
186   { 186   {
187   writer::state st; 187   writer::state st;
HITCBC 188   9812 w.st_.pop(st); 188   9812 w.st_.pop(st);
HITCBC 189   9812 switch(st) 189   9812 switch(st)
190   { 190   {
HITCBC 191   170 default: 191   170 default:
HITCBC 192   170 case writer::state::str1: goto do_str1; 192   170 case writer::state::str1: goto do_str1;
HITCBC 193   268 case writer::state::str2: goto do_str2; 193   268 case writer::state::str2: goto do_str2;
HITCBC 194   9082 case writer::state::str3: goto do_str3; 194   9082 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
HITCBC 215   34473 do_str1: 215   34473 do_str1:
HITCBC 216   34643 if(BOOST_JSON_LIKELY(ss)) 216   34643 if(BOOST_JSON_LIKELY(ss))
HITCBC 217   34473 ss.append('\x22'); // '"' 217   34473 ss.append('\x22'); // '"'
218   else 218   else
HITCBC 219   170 return w.suspend(writer::state::str1); 219   170 return w.suspend(writer::state::str1);
220   220  
221   // fast loop, 221   // fast loop,
222   // copy unescaped 222   // copy unescaped
HITCBC 223   34741 do_str2: 223   34741 do_str2:
HITCBC 224   34741 if(BOOST_JSON_LIKELY(ss)) 224   34741 if(BOOST_JSON_LIKELY(ss))
225   { 225   {
HITCBC 226   34485 std::size_t n = cs.remain(); 226   34485 std::size_t n = cs.remain();
HITCBC 227   34485 if(BOOST_JSON_LIKELY(n > 0)) 227   34485 if(BOOST_JSON_LIKELY(n > 0))
228   { 228   {
HITCBC 229   34441 if(ss.remain() > n) 229   34441 if(ss.remain() > n)
HITCBC 230   25766 n = detail::count_unescaped( 230   25766 n = detail::count_unescaped(
231   cs.data(), n); 231   cs.data(), n);
232   else 232   else
HITCBC 233   8675 n = detail::count_unescaped( 233   8675 n = detail::count_unescaped(
234   cs.data(), ss.remain()); 234   cs.data(), ss.remain());
HITCBC 235   34441 if(n > 0) 235   34441 if(n > 0)
236   { 236   {
HITCBC 237   25225 ss.append(cs.data(), n); 237   25225 ss.append(cs.data(), n);
HITCBC 238   25225 cs.skip(n); 238   25225 cs.skip(n);
HITCBC 239   25225 if(! ss) 239   25225 if(! ss)
HITCBC 240   12 return w.suspend(writer::state::str2); 240   12 return w.suspend(writer::state::str2);
241   } 241   }
242   } 242   }
243   else 243   else
244   { 244   {
HITCBC 245   44 ss.append('\x22'); // '"' 245   44 ss.append('\x22'); // '"'
HITCBC 246   44 return true; 246   44 return true;
247   } 247   }
248   } 248   }
249   else 249   else
250   { 250   {
HITCBC 251   256 return w.suspend(writer::state::str2); 251   256 return w.suspend(writer::state::str2);
252   } 252   }
253   253  
254   // slow loop, 254   // slow loop,
255   // handle escapes 255   // handle escapes
HITCBC 256   43707 do_str3: 256   43707 do_str3:
HITCBC 257   31461016 while(BOOST_JSON_LIKELY(ss)) 257   31461016 while(BOOST_JSON_LIKELY(ss))
258   { 258   {
HITCBC 259   31451934 if(BOOST_JSON_LIKELY(cs)) 259   31451934 if(BOOST_JSON_LIKELY(cs))
260   { 260   {
HITCBC 261   31417505 auto const ch = *cs; 261   31417505 auto const ch = *cs;
HITCBC 262   31417505 auto const c = esc[static_cast< 262   31417505 auto const c = esc[static_cast<
263   unsigned char>(ch)]; 263   unsigned char>(ch)];
HITCBC 264   31417505 ++cs; 264   31417505 ++cs;
HITCBC 265   31417505 if(! c) 265   31417505 if(! c)
266   { 266   {
HITCBC 267   31416777 ss.append(ch); 267   31416777 ss.append(ch);
268   } 268   }
HITCBC 269   728 else if(c != 'u') 269   728 else if(c != 'u')
270   { 270   {
HITCBC 271   376 ss.append('\\'); 271   376 ss.append('\\');
HITCBC 272   376 if(BOOST_JSON_LIKELY(ss)) 272   376 if(BOOST_JSON_LIKELY(ss))
273   { 273   {
HITCBC 274   324 ss.append(c); 274   324 ss.append(c);
275   } 275   }
276   else 276   else
277   { 277   {
HITCBC 278   52 w.buf_[0] = c; 278   52 w.buf_[0] = c;
HITCBC 279   52 return w.suspend( 279   52 return w.suspend(
HITCBC 280   52 writer::state::esc1); 280   52 writer::state::esc1);
281   } 281   }
282   } 282   }
283   else 283   else
284   { 284   {
HITCBC 285   352 if(BOOST_JSON_LIKELY( 285   352 if(BOOST_JSON_LIKELY(
286   ss.remain() >= 6)) 286   ss.remain() >= 6))
287   { 287   {
HITCBC 288   208 ss.append("\\u00", 4); 288   208 ss.append("\\u00", 4);
HITCBC 289   208 ss.append(hex[static_cast< 289   208 ss.append(hex[static_cast<
HITCBC 290   208 unsigned char>(ch) >> 4]); 290   208 unsigned char>(ch) >> 4]);
HITCBC 291   208 ss.append(hex[static_cast< 291   208 ss.append(hex[static_cast<
HITCBC 292   208 unsigned char>(ch) & 15]); 292   208 unsigned char>(ch) & 15]);
293   } 293   }
294   else 294   else
295   { 295   {
HITCBC 296   144 ss.append('\\'); 296   144 ss.append('\\');
HITCBC 297   144 w.buf_[0] = hex[static_cast< 297   144 w.buf_[0] = hex[static_cast<
HITCBC 298   144 unsigned char>(ch) >> 4]; 298   144 unsigned char>(ch) >> 4];
HITCBC 299   144 w.buf_[1] = hex[static_cast< 299   144 w.buf_[1] = hex[static_cast<
HITCBC 300   144 unsigned char>(ch) & 15]; 300   144 unsigned char>(ch) & 15];
HITCBC 301   144 goto do_utf1; 301   144 goto do_utf1;
302   } 302   }
303   } 303   }
304   } 304   }
305   else 305   else
306   { 306   {
HITCBC 307   34429 ss.append('\x22'); // '"' 307   34429 ss.append('\x22'); // '"'
HITCBC 308   34429 return true; 308   34429 return true;
309   } 309   }
310   } 310   }
HITCBC 311   9082 return w.suspend(writer::state::str3); 311   9082 return w.suspend(writer::state::str3);
312   312  
HITCBC 313   52 do_esc1: 313   52 do_esc1:
HITCBC 314   52 BOOST_ASSERT(ss); 314   52 BOOST_ASSERT(ss);
HITCBC 315   52 ss.append(w.buf_[0]); 315   52 ss.append(w.buf_[0]);
HITCBC 316   52 goto do_str3; 316   52 goto do_str3;
317   317  
HITCBC 318   192 do_utf1: 318   192 do_utf1:
HITCBC 319   192 if(BOOST_JSON_LIKELY(ss)) 319   192 if(BOOST_JSON_LIKELY(ss))
HITCBC 320   144 ss.append('u'); 320   144 ss.append('u');
321   else 321   else
HITCBC 322   48 return w.suspend(writer::state::utf1); 322   48 return w.suspend(writer::state::utf1);
HITCBC 323   192 do_utf2: 323   192 do_utf2:
HITCBC 324   192 if(BOOST_JSON_LIKELY(ss)) 324   192 if(BOOST_JSON_LIKELY(ss))
HITCBC 325   144 ss.append('0'); 325   144 ss.append('0');
326   else 326   else
HITCBC 327   48 return w.suspend(writer::state::utf2); 327   48 return w.suspend(writer::state::utf2);
HITCBC 328   192 do_utf3: 328   192 do_utf3:
HITCBC 329   192 if(BOOST_JSON_LIKELY(ss)) 329   192 if(BOOST_JSON_LIKELY(ss))
HITCBC 330   144 ss.append('0'); 330   144 ss.append('0');
331   else 331   else
HITCBC 332   48 return w.suspend(writer::state::utf3); 332   48 return w.suspend(writer::state::utf3);
HITCBC 333   192 do_utf4: 333   192 do_utf4:
HITCBC 334   192 if(BOOST_JSON_LIKELY(ss)) 334   192 if(BOOST_JSON_LIKELY(ss))
HITCBC 335   144 ss.append(w.buf_[0]); 335   144 ss.append(w.buf_[0]);
336   else 336   else
HITCBC 337   48 return w.suspend(writer::state::utf4); 337   48 return w.suspend(writer::state::utf4);
HITCBC 338   192 do_utf5: 338   192 do_utf5:
HITCBC 339   192 if(BOOST_JSON_LIKELY(ss)) 339   192 if(BOOST_JSON_LIKELY(ss))
HITCBC 340   144 ss.append(w.buf_[1]); 340   144 ss.append(w.buf_[1]);
341   else 341   else
HITCBC 342   48 return w.suspend(writer::state::utf5); 342   48 return w.suspend(writer::state::utf5);
HITCBC 343   144 goto do_str3; 343   144 goto do_str3;
HITCBC 344   44285 } 344   44285 }
345   345  
346   bool 346   bool
HITCBC 347   19827 write_string(writer& w, stream& ss0) 347   19827 write_string(writer& w, stream& ss0)
348   { 348   {
HITCBC 349   19827 return do_write_string<true>(w, ss0); 349   19827 return do_write_string<true>(w, ss0);
350   } 350   }
351   351  
352   bool 352   bool
HITCBC 353   408 resume_string(writer& w, stream& ss0) 353   408 resume_string(writer& w, stream& ss0)
354   { 354   {
HITCBC 355   408 return do_write_string<false>(w, ss0); 355   408 return do_write_string<false>(w, ss0);
356   } 356   }
357   357  
358   template<bool StackEmpty> 358   template<bool StackEmpty>
359   bool 359   bool
360   write_value(writer& w, stream& ss); 360   write_value(writer& w, stream& ss);
361   361  
362   template< class T, bool StackEmpty > 362   template< class T, bool StackEmpty >
363   BOOST_FORCEINLINE 363   BOOST_FORCEINLINE
364   bool 364   bool
365 - write_impl(no_conversion_tag, writer& w, stream& ss) 365 + write_impl(unknown_category, writer& w, stream& ss)
366   { 366   {
HITCBC 367   34536 return write_value<StackEmpty>(w, ss); 367   34536 return write_value<StackEmpty>(w, ss);
368   } 368   }
369   369  
370   template<bool StackEmpty> 370   template<bool StackEmpty>
371   bool 371   bool
HITCBC 372   6041 write_array(writer& w, stream& ss) 372   6041 write_array(writer& w, stream& ss)
373   { 373   {
HITCBC 374 - 6040 return write_impl<array, StackEmpty>(sequence_conversion_tag(), w, ss); 374 + 6040 return write_impl<array, StackEmpty>(sequence_category(), w, ss);
375   } 375   }
376   376  
377   template<bool StackEmpty> 377   template<bool StackEmpty>
378   bool 378   bool
HITCBC 379   27194 write_object(writer& w, stream& ss) 379   27194 write_object(writer& w, stream& ss)
380   { 380   {
HITCBC 381 - 27194 return write_impl<object, StackEmpty>(map_like_conversion_tag(), w, ss); 381 + 27194 return write_impl<object, StackEmpty>(map_category(), w, ss);
382   } 382   }
383   383  
384   template<bool StackEmpty> 384   template<bool StackEmpty>
385   bool 385   bool
HITCBC 386   66927 write_value(writer& w, stream& ss) 386   66927 write_value(writer& w, stream& ss)
387   { 387   {
HITCBC 388   22905 if(StackEmpty || w.st_.empty()) 388   22905 if(StackEmpty || w.st_.empty())
389   { 389   {
HITCBC 390   44503 BOOST_ASSERT( w.p_ ); 390   44503 BOOST_ASSERT( w.p_ );
HITCBC 391   44503 auto const pv = reinterpret_cast<value const*>(w.p_); 391   44503 auto const pv = reinterpret_cast<value const*>(w.p_);
HITCBC 392   44503 switch(pv->kind()) 392   44503 switch(pv->kind())
393   { 393   {
HITCBC 394   18083 default: 394   18083 default:
395   case kind::object: 395   case kind::object:
HITCBC 396   18083 w.p_ = &pv->get_object(); 396   18083 w.p_ = &pv->get_object();
HITCBC 397   18083 return write_object<true>(w, ss); 397   18083 return write_object<true>(w, ss);
398   398  
HITCBC 399   3400 case kind::array: 399   3400 case kind::array:
HITCBC 400   3400 w.p_ = &pv->get_array(); 400   3400 w.p_ = &pv->get_array();
HITCBC 401   3400 return write_array<true>(w, ss); 401   3400 return write_array<true>(w, ss);
402   402  
HITCBC 403   14643 case kind::string: 403   14643 case kind::string:
404   { 404   {
HITCBC 405   14643 auto const& js = pv->get_string(); 405   14643 auto const& js = pv->get_string();
HITCBC 406   14643 w.cs0_ = { js.data(), js.size() }; 406   14643 w.cs0_ = { js.data(), js.size() };
HITCBC 407   14643 return do_write_string<true>(w, ss); 407   14643 return do_write_string<true>(w, ss);
408   } 408   }
409   409  
HITCBC 410   3182 case kind::int64: 410   3182 case kind::int64:
HITCBC 411   3182 return write_int64( w, ss, pv->get_int64() ); 411   3182 return write_int64( w, ss, pv->get_int64() );
HITCBC 412   91 case kind::uint64: 412   91 case kind::uint64:
HITCBC 413   91 return write_uint64( w, ss, pv->get_uint64() ); 413   91 return write_uint64( w, ss, pv->get_uint64() );
HITCBC 414   467 case kind::double_: 414   467 case kind::double_:
HITCBC 415   467 return write_double( w, ss, pv->get_double() ); 415   467 return write_double( w, ss, pv->get_double() );
416   416  
HITCBC 417   306 case kind::bool_: 417   306 case kind::bool_:
HITCBC 418   306 if( pv->get_bool() ) 418   306 if( pv->get_bool() )
HITCBC 419   139 return write_true(w, ss); 419   139 return write_true(w, ss);
420   else 420   else
HITCBC 421   167 return write_false(w, ss); 421   167 return write_false(w, ss);
422   422  
HITCBC 423   4331 case kind::null: 423   4331 case kind::null:
HITCBC 424   4331 return write_null(w, ss); 424   4331 return write_null(w, ss);
425   } 425   }
426   } 426   }
427   else 427   else
428   { 428   {
429   writer::state st; 429   writer::state st;
HITCBC 430   22424 w.st_.peek(st); 430   22424 w.st_.peek(st);
HITCBC 431   22424 switch(st) 431   22424 switch(st)
432   { 432   {
HITCBC 433   1324 default: 433   1324 default:
434   case writer::state::lit: 434   case writer::state::lit:
HITCBC 435   1324 return resume_buffer(w, ss); 435   1324 return resume_buffer(w, ss);
436   436  
HITCBC 437   9404 case writer::state::str1: case writer::state::str2: 437   9404 case writer::state::str1: case writer::state::str2:
438   case writer::state::str3: case writer::state::esc1: 438   case writer::state::str3: case writer::state::esc1:
439   case writer::state::utf1: case writer::state::utf2: 439   case writer::state::utf1: case writer::state::utf2:
440   case writer::state::utf3: case writer::state::utf4: 440   case writer::state::utf3: case writer::state::utf4:
441   case writer::state::utf5: 441   case writer::state::utf5:
HITCBC 442   9404 return do_write_string<false>(w, ss); 442   9404 return do_write_string<false>(w, ss);
443   443  
HITCBC 444   2636 case writer::state::arr1: case writer::state::arr2: 444   2636 case writer::state::arr1: case writer::state::arr2:
445   case writer::state::arr3: case writer::state::arr4: 445   case writer::state::arr3: case writer::state::arr4:
HITCBC 446   2636 return write_array<StackEmpty>(w, ss); 446   2636 return write_array<StackEmpty>(w, ss);
447   447  
HITCBC 448   9060 case writer::state::obj1: case writer::state::obj2: 448   9060 case writer::state::obj1: case writer::state::obj2:
449   case writer::state::obj3: case writer::state::obj4: 449   case writer::state::obj3: case writer::state::obj4:
450   case writer::state::obj5: case writer::state::obj6: 450   case writer::state::obj5: case writer::state::obj6:
HITCBC 451   9060 return write_object<StackEmpty>(w, ss); 451   9060 return write_object<StackEmpty>(w, ss);
452   } 452   }
453   } 453   }
454   } 454   }
455   455  
456   } // namespace detail 456   } // namespace detail
457   457  
HITCBC 458   2348 serializer:: 458   2348 serializer::
HITCBC 459   2348 serializer(serialize_options const& opts) noexcept 459   2348 serializer(serialize_options const& opts) noexcept
HITCBC 460   2348 : serializer({}, nullptr, 0, opts) 460   2348 : serializer({}, nullptr, 0, opts)
HITCBC 461   2348 {} 461   2348 {}
462   462  
HITCBC 463   21245 serializer:: 463   21245 serializer::
464   serializer( 464   serializer(
465   storage_ptr sp, 465   storage_ptr sp,
466   unsigned char* buf, 466   unsigned char* buf,
467   std::size_t buf_size, 467   std::size_t buf_size,
HITCBC 468   21245 serialize_options const& opts) noexcept 468   21245 serialize_options const& opts) noexcept
HITCBC 469   21245 : detail::writer(std::move(sp), buf, buf_size, opts) 469   21245 : detail::writer(std::move(sp), buf, buf_size, opts)
HITCBC 470   21245 {} 470   21245 {}
471   471  
472   void 472   void
HITCBC 473   20961 serializer:: 473   20961 serializer::
474   reset(value const* p) noexcept 474   reset(value const* p) noexcept
475   { 475   {
HITCBC 476   20961 p_ = p; 476   20961 p_ = p;
HITCBC 477   20961 fn0_ = &detail::write_value<true>; 477   20961 fn0_ = &detail::write_value<true>;
HITCBC 478   20961 fn1_ = &detail::write_value<false>; 478   20961 fn1_ = &detail::write_value<false>;
HITCBC 479   20961 st_.clear(); 479   20961 st_.clear();
HITCBC 480   20961 done_ = false; 480   20961 done_ = false;
HITCBC 481   20961 } 481   20961 }
482   482  
483   void 483   void
HITCBC 484   5 serializer:: 484   5 serializer::
485   reset(array const* p) noexcept 485   reset(array const* p) noexcept
486   { 486   {
HITCBC 487   5 p_ = p; 487   5 p_ = p;
HITCBC 488   5 fn0_ = &detail::write_array<true>; 488   5 fn0_ = &detail::write_array<true>;
HITCBC 489   5 fn1_ = &detail::write_array<false>; 489   5 fn1_ = &detail::write_array<false>;
HITCBC 490   5 st_.clear(); 490   5 st_.clear();
HITCBC 491   5 done_ = false; 491   5 done_ = false;
HITCBC 492   5 } 492   5 }
493   493  
494   void 494   void
HITCBC 495   51 serializer:: 495   51 serializer::
496   reset(object const* p) noexcept 496   reset(object const* p) noexcept
497   { 497   {
HITCBC 498   51 p_ = p; 498   51 p_ = p;
HITCBC 499   51 fn0_ = &detail::write_object<true>; 499   51 fn0_ = &detail::write_object<true>;
HITCBC 500   51 fn1_ = &detail::write_object<false>; 500   51 fn1_ = &detail::write_object<false>;
HITCBC 501   51 st_.clear(); 501   51 st_.clear();
HITCBC 502   51 done_ = false; 502   51 done_ = false;
HITCBC 503   51 } 503   51 }
504   504  
505   void 505   void
HITCBC 506   2 serializer:: 506   2 serializer::
507   reset(string const* p) noexcept 507   reset(string const* p) noexcept
508   { 508   {
HITCBC 509   2 cs0_ = { p->data(), p->size() }; 509   2 cs0_ = { p->data(), p->size() };
HITCBC 510   2 fn0_ = &detail::do_write_string<true>; 510   2 fn0_ = &detail::do_write_string<true>;
HITCBC 511   2 fn1_ = &detail::do_write_string<false>; 511   2 fn1_ = &detail::do_write_string<false>;
HITCBC 512   2 st_.clear(); 512   2 st_.clear();
HITCBC 513   2 done_ = false; 513   2 done_ = false;
HITCBC 514   2 } 514   2 }
515   515  
516   void 516   void
HITCBC 517   1 serializer:: 517   1 serializer::
518   reset(string_view sv) noexcept 518   reset(string_view sv) noexcept
519   { 519   {
HITCBC 520   1 cs0_ = { sv.data(), sv.size() }; 520   1 cs0_ = { sv.data(), sv.size() };
HITCBC 521   1 fn0_ = &detail::do_write_string<true>; 521   1 fn0_ = &detail::do_write_string<true>;
HITCBC 522   1 fn1_ = &detail::do_write_string<false>; 522   1 fn1_ = &detail::do_write_string<false>;
HITCBC 523   1 st_.clear(); 523   1 st_.clear();
HITCBC 524   1 done_ = false; 524   1 done_ = false;
HITCBC 525   1 } 525   1 }
526   526  
527   void 527   void
HITCBC 528   6 serializer::reset(std::nullptr_t) noexcept 528   6 serializer::reset(std::nullptr_t) noexcept
529   { 529   {
HITCBC 530   6 p_ = nullptr; 530   6 p_ = nullptr;
HITCBC 531   6 fn0_ = &detail::write_impl<std::nullptr_t, true>; 531   6 fn0_ = &detail::write_impl<std::nullptr_t, true>;
HITCBC 532   6 fn1_ = &detail::write_impl<std::nullptr_t, false>; 532   6 fn1_ = &detail::write_impl<std::nullptr_t, false>;
HITCBC 533   6 st_.clear(); 533   6 st_.clear();
HITCBC 534   6 done_ = false; 534   6 done_ = false;
HITCBC 535   6 } 535   6 }
536   536  
537   string_view 537   string_view
HITCBC 538   32983 serializer:: 538   32983 serializer::
539   read(char* dest, std::size_t size) 539   read(char* dest, std::size_t size)
540   { 540   {
HITCBC 541   32983 if( !fn0_ ) 541   32983 if( !fn0_ )
HITCBC 542   6 reset(nullptr); 542   6 reset(nullptr);
543   543  
HITCBC 544   32983 if(BOOST_JSON_UNLIKELY(size == 0)) 544   32983 if(BOOST_JSON_UNLIKELY(size == 0))
HITCBC 545   1 return {dest, 0}; 545   1 return {dest, 0};
546   546  
HITCBC 547   32982 detail::stream ss(dest, size); 547   32982 detail::stream ss(dest, size);
HITCBC 548   32982 if(st_.empty()) 548   32982 if(st_.empty())
HITCBC 549   21244 fn0_(*this, ss); 549   21244 fn0_(*this, ss);
550   else 550   else
HITCBC 551   11738 fn1_(*this, ss); 551   11738 fn1_(*this, ss);
HITCBC 552   32980 if(st_.empty()) 552   32980 if(st_.empty())
553   { 553   {
HITCBC 554   21242 done_ = true; 554   21242 done_ = true;
HITCBC 555   21242 fn0_ = nullptr; 555   21242 fn0_ = nullptr;
HITCBC 556   21242 p_ = nullptr; 556   21242 p_ = nullptr;
557   } 557   }
HITCBC 558   32980 return string_view( 558   32980 return string_view(
HITCBC 559   32980 dest, ss.used(dest)); 559   32980 dest, ss.used(dest));
560   } 560   }
561   561  
562   } // namespace json 562   } // namespace json
563   } // namespace boost 563   } // namespace boost
564   564  
565   #ifdef _MSC_VER 565   #ifdef _MSC_VER
566   #pragma warning(pop) 566   #pragma warning(pop)
567   #endif 567   #endif
568   568  
569   #endif 569   #endif