98.50% Lines (459/466) 100.00% Functions (63/63)
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_VALUE_IPP 10   #ifndef BOOST_JSON_IMPL_VALUE_IPP
11   #define BOOST_JSON_IMPL_VALUE_IPP 11   #define BOOST_JSON_IMPL_VALUE_IPP
12   12  
13   #include <boost/container_hash/hash.hpp> 13   #include <boost/container_hash/hash.hpp>
14   #include <boost/json/value.hpp> 14   #include <boost/json/value.hpp>
15   #include <boost/json/parser.hpp> 15   #include <boost/json/parser.hpp>
16   #include <cstring> 16   #include <cstring>
17   #include <istream> 17   #include <istream>
18   #include <limits> 18   #include <limits>
19   #include <new> 19   #include <new>
20   #include <utility> 20   #include <utility>
21   21  
22   namespace boost { 22   namespace boost {
23   namespace json { 23   namespace json {
24   24  
25   namespace 25   namespace
26   { 26   {
27   27  
28   int parse_depth_xalloc = std::ios::xalloc(); 28   int parse_depth_xalloc = std::ios::xalloc();
29   int parse_flags_xalloc = std::ios::xalloc(); 29   int parse_flags_xalloc = std::ios::xalloc();
30   30  
31   struct value_hasher 31   struct value_hasher
32   { 32   {
33   std::size_t& seed; 33   std::size_t& seed;
34   34  
35   template< class T > 35   template< class T >
HITCBC 36   248 void operator()( T&& t ) const noexcept 36   248 void operator()( T&& t ) const noexcept
37   { 37   {
HITCBC 38   248 boost::hash_combine( seed, t ); 38   248 boost::hash_combine( seed, t );
HITCBC 39   248 } 39   248 }
40   }; 40   };
41   41  
42   enum class stream_parse_flags 42   enum class stream_parse_flags
43   { 43   {
44   allow_comments = 1 << 0, 44   allow_comments = 1 << 0,
45   allow_trailing_commas = 1 << 1, 45   allow_trailing_commas = 1 << 1,
46   allow_invalid_utf8 = 1 << 2, 46   allow_invalid_utf8 = 1 << 2,
47   }; 47   };
48   48  
49   long 49   long
HITCBC 50   3 to_bitmask( parse_options const& opts ) 50   3 to_bitmask( parse_options const& opts )
51   { 51   {
52   using E = stream_parse_flags; 52   using E = stream_parse_flags;
53   return 53   return
HITCBC 54   3 (opts.allow_comments ? 54   3 (opts.allow_comments ?
HITCBC 55   3 static_cast<long>(E::allow_comments) : 0) | 55   3 static_cast<long>(E::allow_comments) : 0) |
HITCBC 56   3 (opts.allow_trailing_commas ? 56   3 (opts.allow_trailing_commas ?
57   static_cast<long>(E::allow_trailing_commas) : 0) | 57   static_cast<long>(E::allow_trailing_commas) : 0) |
HITCBC 58   3 (opts.allow_invalid_utf8 ? 58   3 (opts.allow_invalid_utf8 ?
HITCBC 59   3 static_cast<long>(E::allow_invalid_utf8) : 0); 59   3 static_cast<long>(E::allow_invalid_utf8) : 0);
60   } 60   }
61   61  
62   parse_options 62   parse_options
HITCBC 63   9 get_parse_options( std::istream& is ) 63   9 get_parse_options( std::istream& is )
64   { 64   {
HITCBC 65   9 long const flags = is.iword(parse_flags_xalloc); 65   9 long const flags = is.iword(parse_flags_xalloc);
66   66  
67   using E = stream_parse_flags; 67   using E = stream_parse_flags;
HITCBC 68   9 parse_options opts; 68   9 parse_options opts;
HITCBC 69   9 opts.allow_comments = 69   9 opts.allow_comments =
HITCBC 70   9 flags & static_cast<long>(E::allow_comments) ? true : false; 70   9 flags & static_cast<long>(E::allow_comments) ? true : false;
HITCBC 71   9 opts.allow_trailing_commas = 71   9 opts.allow_trailing_commas =
HITCBC 72   9 flags & static_cast<long>(E::allow_trailing_commas) ? true : false; 72   9 flags & static_cast<long>(E::allow_trailing_commas) ? true : false;
HITCBC 73   9 opts.allow_invalid_utf8 = 73   9 opts.allow_invalid_utf8 =
HITCBC 74   9 flags & static_cast<long>(E::allow_invalid_utf8) ? true : false; 74   9 flags & static_cast<long>(E::allow_invalid_utf8) ? true : false;
HITCBC 75   9 return opts; 75   9 return opts;
76   } 76   }
77   77  
78   } // namespace 78   } // namespace
79   79  
HITCBC 80   2178821 value:: 80   2178821 value::
81   ~value() noexcept 81   ~value() noexcept
82   { 82   {
HITCBC 83   2178821 switch(kind()) 83   2178821 switch(kind())
84   { 84   {
HITCBC 85   2113114 case json::kind::null: 85   2113114 case json::kind::null:
86   case json::kind::bool_: 86   case json::kind::bool_:
87   case json::kind::int64: 87   case json::kind::int64:
88   case json::kind::uint64: 88   case json::kind::uint64:
89   case json::kind::double_: 89   case json::kind::double_:
HITCBC 90   2113114 sca_.~scalar(); 90   2113114 sca_.~scalar();
HITCBC 91   2113114 break; 91   2113114 break;
92   92  
HITCBC 93   27395 case json::kind::string: 93   27395 case json::kind::string:
HITCBC 94   27395 str_.~string(); 94   27395 str_.~string();
HITCBC 95   27395 break; 95   27395 break;
96   96  
HITCBC 97   3107 case json::kind::array: 97   3107 case json::kind::array:
HITCBC 98   3107 arr_.~array(); 98   3107 arr_.~array();
HITCBC 99   3107 break; 99   3107 break;
100   100  
HITCBC 101   35205 case json::kind::object: 101   35205 case json::kind::object:
HITCBC 102   35205 obj_.~object(); 102   35205 obj_.~object();
HITCBC 103   35205 break; 103   35205 break;
104   } 104   }
HITCBC 105   2178821 } 105   2178821 }
106   106  
HITCBC 107   9587 value:: 107   9587 value::
108   value( 108   value(
109   value const& other, 109   value const& other,
HITCBC 110   9587 storage_ptr sp) 110   9587 storage_ptr sp)
111   { 111   {
HITCBC 112   9587 switch(other.kind()) 112   9587 switch(other.kind())
113   { 113   {
HITCBC 114   2037 case json::kind::null: 114   2037 case json::kind::null:
HITCBC 115   6111 ::new(&sca_) scalar( 115   6111 ::new(&sca_) scalar(
HITCBC 116   2037 std::move(sp)); 116   2037 std::move(sp));
HITCBC 117   2037 break; 117   2037 break;
118   118  
HITCBC 119   136 case json::kind::bool_: 119   136 case json::kind::bool_:
HITCBC 120   408 ::new(&sca_) scalar( 120   408 ::new(&sca_) scalar(
HITCBC 121   136 other.sca_.b, 121   136 other.sca_.b,
HITCBC 122   136 std::move(sp)); 122   136 std::move(sp));
HITCBC 123   136 break; 123   136 break;
124   124  
HITCBC 125   7052 case json::kind::int64: 125   7052 case json::kind::int64:
HITCBC 126   21156 ::new(&sca_) scalar( 126   21156 ::new(&sca_) scalar(
HITCBC 127   7052 other.sca_.i, 127   7052 other.sca_.i,
HITCBC 128   7052 std::move(sp)); 128   7052 std::move(sp));
HITCBC 129   7052 break; 129   7052 break;
130   130  
HITCBC 131   35 case json::kind::uint64: 131   35 case json::kind::uint64:
HITCBC 132   105 ::new(&sca_) scalar( 132   105 ::new(&sca_) scalar(
HITCBC 133   35 other.sca_.u, 133   35 other.sca_.u,
HITCBC 134   35 std::move(sp)); 134   35 std::move(sp));
HITCBC 135   35 break; 135   35 break;
136   136  
HITCBC 137   12 case json::kind::double_: 137   12 case json::kind::double_:
HITCBC 138   36 ::new(&sca_) scalar( 138   36 ::new(&sca_) scalar(
HITCBC 139   12 other.sca_.d, 139   12 other.sca_.d,
HITCBC 140   12 std::move(sp)); 140   12 std::move(sp));
HITCBC 141   12 break; 141   12 break;
142   142  
HITCBC 143   143 case json::kind::string: 143   143 case json::kind::string:
HITCBC 144   18 ::new(&str_) string( 144   18 ::new(&str_) string(
HITCBC 145   143 other.str_, 145   143 other.str_,
HITCBC 146   179 std::move(sp)); 146   179 std::move(sp));
HITCBC 147   125 break; 147   125 break;
148   148  
HITCBC 149   142 case json::kind::array: 149   142 case json::kind::array:
HITCBC 150   29 ::new(&arr_) array( 150   29 ::new(&arr_) array(
HITCBC 151   142 other.arr_, 151   142 other.arr_,
HITCBC 152   200 std::move(sp)); 152   200 std::move(sp));
HITCBC 153   113 break; 153   113 break;
154   154  
HITCBC 155   30 case json::kind::object: 155   30 case json::kind::object:
HITCBC 156   10 ::new(&obj_) object( 156   10 ::new(&obj_) object(
HITCBC 157   30 other.obj_, 157   30 other.obj_,
HITCBC 158   50 std::move(sp)); 158   50 std::move(sp));
HITCBC 159   20 break; 159   20 break;
160   } 160   }
HITCBC 161   9530 } 161   9530 }
162   162  
HITCBC 163   3784 value:: 163   3784 value::
HITCBC 164   3784 value(value&& other) noexcept 164   3784 value(value&& other) noexcept
165   { 165   {
HITCBC 166   3784 relocate(this, other); 166   3784 relocate(this, other);
HITCBC 167   3784 ::new(&other.sca_) scalar(sp_); 167   3784 ::new(&other.sca_) scalar(sp_);
HITCBC 168   3784 } 168   3784 }
169   169  
HITCBC 170   11501 value:: 170   11501 value::
171   value( 171   value(
172   value&& other, 172   value&& other,
HITCBC 173   11501 storage_ptr sp) 173   11501 storage_ptr sp)
174   { 174   {
HITCBC 175   11501 switch(other.kind()) 175   11501 switch(other.kind())
176   { 176   {
HITCBC 177   77 case json::kind::null: 177   77 case json::kind::null:
HITCBC 178   229 ::new(&sca_) scalar( 178   229 ::new(&sca_) scalar(
HITCBC 179   77 std::move(sp)); 179   77 std::move(sp));
HITCBC 180   77 break; 180   77 break;
181   181  
HITCBC 182   193 case json::kind::bool_: 182   193 case json::kind::bool_:
HITCBC 183   579 ::new(&sca_) scalar( 183   579 ::new(&sca_) scalar(
HITCBC 184   193 other.sca_.b, std::move(sp)); 184   193 other.sca_.b, std::move(sp));
HITCBC 185   193 break; 185   193 break;
186   186  
HITCBC 187   10494 case json::kind::int64: 187   10494 case json::kind::int64:
HITCBC 188   31482 ::new(&sca_) scalar( 188   31482 ::new(&sca_) scalar(
HITCBC 189   10494 other.sca_.i, std::move(sp)); 189   10494 other.sca_.i, std::move(sp));
HITCBC 190   10494 break; 190   10494 break;
191   191  
HITCBC 192   75 case json::kind::uint64: 192   75 case json::kind::uint64:
HITCBC 193   225 ::new(&sca_) scalar( 193   225 ::new(&sca_) scalar(
HITCBC 194   75 other.sca_.u, std::move(sp)); 194   75 other.sca_.u, std::move(sp));
HITCBC 195   75 break; 195   75 break;
196   196  
HITCBC 197   34 case json::kind::double_: 197   34 case json::kind::double_:
HITCBC 198   102 ::new(&sca_) scalar( 198   102 ::new(&sca_) scalar(
HITCBC 199   34 other.sca_.d, std::move(sp)); 199   34 other.sca_.d, std::move(sp));
HITCBC 200   34 break; 200   34 break;
201   201  
HITCBC 202   340 case json::kind::string: 202   340 case json::kind::string:
HITCBC 203   6 ::new(&str_) string( 203   6 ::new(&str_) string(
HITCBC 204   340 std::move(other.str_), 204   340 std::move(other.str_),
HITCBC 205   692 std::move(sp)); 205   692 std::move(sp));
HITCBC 206   334 break; 206   334 break;
207   207  
HITCBC 208   224 case json::kind::array: 208   224 case json::kind::array:
HITCBC 209   5 ::new(&arr_) array( 209   5 ::new(&arr_) array(
HITCBC 210   224 std::move(other.arr_), 210   224 std::move(other.arr_),
HITCBC 211   458 std::move(sp)); 211   458 std::move(sp));
HITCBC 212   219 break; 212   219 break;
213   213  
HITCBC 214   64 case json::kind::object: 214   64 case json::kind::object:
HITCBC 215   13 ::new(&obj_) object( 215   13 ::new(&obj_) object(
HITCBC 216   64 std::move(other.obj_), 216   64 std::move(other.obj_),
HITCBC 217   154 std::move(sp)); 217   154 std::move(sp));
HITCBC 218   51 break; 218   51 break;
219   } 219   }
HITCBC 220   11477 } 220   11477 }
221   221  
222   //---------------------------------------------------------- 222   //----------------------------------------------------------
223   // 223   //
224   // Conversion 224   // Conversion
225   // 225   //
226   //---------------------------------------------------------- 226   //----------------------------------------------------------
227   227  
HITCBC 228   338 value:: 228   338 value::
229   value( 229   value(
230   std::initializer_list<value_ref> init, 230   std::initializer_list<value_ref> init,
HITCBC 231   338 storage_ptr sp) 231   338 storage_ptr sp)
232   { 232   {
HITCBC 233   338 if(value_ref::maybe_object(init)) 233   338 if(value_ref::maybe_object(init))
234   { 234   {
MISUBC 235   ::new(&obj_) object( 235   ::new(&obj_) object(
236   value_ref::make_object( 236   value_ref::make_object(
HITCBC 237   103 init, std::move(sp))); 237   103 init, std::move(sp)));
238   } 238   }
239   else 239   else
240   { 240   {
HITCBC 241   235 if( init.size() == 1 ) 241   235 if( init.size() == 1 )
242   { 242   {
MISUBC 243   ::new(this) value( 243   ::new(this) value(
HITCBC 244   14 init.begin()->make_value( std::move(sp) )); 244   14 init.begin()->make_value( std::move(sp) ));
245   } 245   }
246   else 246   else
247   { 247   {
MISUBC 248   ::new(&arr_) array( 248   ::new(&arr_) array(
249   value_ref::make_array( 249   value_ref::make_array(
HITCBC 250   221 init, std::move(sp))); 250   221 init, std::move(sp)));
251   } 251   }
252   } 252   }
HITCBC 253   338 } 253   338 }
254   254  
255   //---------------------------------------------------------- 255   //----------------------------------------------------------
256   // 256   //
257   // Assignment 257   // Assignment
258   // 258   //
259   //---------------------------------------------------------- 259   //----------------------------------------------------------
260   260  
261   value& 261   value&
HITCBC 262   38 value:: 262   38 value::
263   operator=(value const& other) 263   operator=(value const& other)
264   { 264   {
HITCBC 265   76 value(other, 265   76 value(other,
HITCBC 266   32 storage()).swap(*this); 266   32 storage()).swap(*this);
HITCBC 267   32 return *this; 267   32 return *this;
268   } 268   }
269   269  
270   value& 270   value&
HITCBC 271   82 value:: 271   82 value::
272   operator=(value&& other) 272   operator=(value&& other)
273   { 273   {
HITCBC 274   164 value(std::move(other), 274   164 value(std::move(other),
HITCBC 275   63 storage()).swap(*this); 275   63 storage()).swap(*this);
HITCBC 276   63 return *this; 276   63 return *this;
277   } 277   }
278   278  
279   value& 279   value&
HITCBC 280   13 value:: 280   13 value::
281   operator=( 281   operator=(
282   std::initializer_list<value_ref> init) 282   std::initializer_list<value_ref> init)
283   { 283   {
HITCBC 284   26 value(init, 284   26 value(init,
HITCBC 285   13 storage()).swap(*this); 285   13 storage()).swap(*this);
HITCBC 286   13 return *this; 286   13 return *this;
287   } 287   }
288   288  
289   value& 289   value&
HITCBC 290   2 value:: 290   2 value::
291   operator=(string_view s) 291   operator=(string_view s)
292   { 292   {
HITCBC 293   2 value(s, storage()).swap(*this); 293   2 value(s, storage()).swap(*this);
HITCBC 294   2 return *this; 294   2 return *this;
295   } 295   }
296   296  
297   value& 297   value&
HITCBC 298   28 value:: 298   28 value::
299   operator=(char const* s) 299   operator=(char const* s)
300   { 300   {
HITCBC 301   28 value(s, storage()).swap(*this); 301   28 value(s, storage()).swap(*this);
HITCBC 302   28 return *this; 302   28 return *this;
303   } 303   }
304   304  
305   value& 305   value&
HITCBC 306   12 value:: 306   12 value::
307   operator=(string const& str) 307   operator=(string const& str)
308   { 308   {
HITCBC 309   12 value(str, storage()).swap(*this); 309   12 value(str, storage()).swap(*this);
HITCBC 310   12 return *this; 310   12 return *this;
311   } 311   }
312   312  
313   value& 313   value&
HITCBC 314   7 value:: 314   7 value::
315   operator=(string&& str) 315   operator=(string&& str)
316   { 316   {
HITCBC 317   14 value(std::move(str), 317   14 value(std::move(str),
HITCBC 318   7 storage()).swap(*this); 318   7 storage()).swap(*this);
HITCBC 319   7 return *this; 319   7 return *this;
320   } 320   }
321   321  
322   value& 322   value&
HITCBC 323   4 value:: 323   4 value::
324   operator=(array const& arr) 324   operator=(array const& arr)
325   { 325   {
HITCBC 326   4 value(arr, storage()).swap(*this); 326   4 value(arr, storage()).swap(*this);
HITCBC 327   4 return *this; 327   4 return *this;
328   } 328   }
329   329  
330   value& 330   value&
HITCBC 331   21 value:: 331   21 value::
332   operator=(array&& arr) 332   operator=(array&& arr)
333   { 333   {
HITCBC 334   42 value(std::move(arr), 334   42 value(std::move(arr),
HITCBC 335   21 storage()).swap(*this); 335   21 storage()).swap(*this);
HITCBC 336   21 return *this; 336   21 return *this;
337   } 337   }
338   338  
339   value& 339   value&
HITCBC 340   4 value:: 340   4 value::
341   operator=(object const& obj) 341   operator=(object const& obj)
342   { 342   {
HITCBC 343   4 value(obj, storage()).swap(*this); 343   4 value(obj, storage()).swap(*this);
HITCBC 344   4 return *this; 344   4 return *this;
345   } 345   }
346   346  
347   value& 347   value&
HITCBC 348   54 value:: 348   54 value::
349   operator=(object&& obj) 349   operator=(object&& obj)
350   { 350   {
HITCBC 351   108 value(std::move(obj), 351   108 value(std::move(obj),
HITCBC 352   54 storage()).swap(*this); 352   54 storage()).swap(*this);
HITCBC 353   54 return *this; 353   54 return *this;
354   } 354   }
355   355  
356   //---------------------------------------------------------- 356   //----------------------------------------------------------
357   // 357   //
358   // Accessors 358   // Accessors
359   // 359   //
360   //---------------------------------------------------------- 360   //----------------------------------------------------------
361   361  
362   system::result<array&> 362   system::result<array&>
HITCBC 363   16 value::try_as_array() noexcept 363   16 value::try_as_array() noexcept
364   { 364   {
HITCBC 365   16 if( is_array() ) 365   16 if( is_array() )
HITCBC 366   9 return arr_; 366   9 return arr_;
367   367  
HITCBC 368   7 system::error_code ec; 368   7 system::error_code ec;
HITCBC 369   7 BOOST_JSON_FAIL(ec, error::not_array); 369   7 BOOST_JSON_FAIL(ec, error::not_array);
HITCBC 370   7 return ec; 370   7 return ec;
371   } 371   }
372   372  
373   system::result<array const&> 373   system::result<array const&>
HITCBC 374   186 value::try_as_array() const noexcept 374   186 value::try_as_array() const noexcept
375   { 375   {
HITCBC 376   186 if( is_array() ) 376   186 if( is_array() )
HITCBC 377   158 return arr_; 377   158 return arr_;
378   378  
HITCBC 379   28 system::error_code ec; 379   28 system::error_code ec;
HITCBC 380   28 BOOST_JSON_FAIL(ec, error::not_array); 380   28 BOOST_JSON_FAIL(ec, error::not_array);
HITCBC 381   28 return ec; 381   28 return ec;
382   } 382   }
383   383  
384   system::result<object&> 384   system::result<object&>
HITCBC 385   9 value::try_as_object() noexcept 385   9 value::try_as_object() noexcept
386   { 386   {
HITCBC 387   9 if( is_object() ) 387   9 if( is_object() )
HITCBC 388   2 return obj_; 388   2 return obj_;
389   389  
HITCBC 390   7 system::error_code ec; 390   7 system::error_code ec;
HITCBC 391   7 BOOST_JSON_FAIL(ec, error::not_object); 391   7 BOOST_JSON_FAIL(ec, error::not_object);
HITCBC 392   7 return ec; 392   7 return ec;
393   } 393   }
394   394  
395   system::result<object const&> 395   system::result<object const&>
HITCBC 396   208 value::try_as_object() const noexcept 396   208 value::try_as_object() const noexcept
397   { 397   {
HITCBC 398   208 if( is_object() ) 398   208 if( is_object() )
HITCBC 399   180 return obj_; 399   180 return obj_;
400   400  
HITCBC 401   28 system::error_code ec; 401   28 system::error_code ec;
HITCBC 402   28 BOOST_JSON_FAIL(ec, error::not_object); 402   28 BOOST_JSON_FAIL(ec, error::not_object);
HITCBC 403   28 return ec; 403   28 return ec;
404   } 404   }
405   405  
406   system::result<string&> 406   system::result<string&>
HITCBC 407   9 value::try_as_string() noexcept 407   9 value::try_as_string() noexcept
408   { 408   {
HITCBC 409   9 if( is_string() ) 409   9 if( is_string() )
HITCBC 410   2 return str_; 410   2 return str_;
411   411  
HITCBC 412   7 system::error_code ec; 412   7 system::error_code ec;
HITCBC 413   7 BOOST_JSON_FAIL(ec, error::not_string); 413   7 BOOST_JSON_FAIL(ec, error::not_string);
HITCBC 414   7 return ec; 414   7 return ec;
415   } 415   }
416   416  
417   system::result<string const&> 417   system::result<string const&>
HITCBC 418   123 value::try_as_string() const noexcept 418   123 value::try_as_string() const noexcept
419   { 419   {
HITCBC 420   123 if( is_string() ) 420   123 if( is_string() )
HITCBC 421   94 return str_; 421   94 return str_;
422   422  
HITCBC 423   29 system::error_code ec; 423   29 system::error_code ec;
HITCBC 424   29 BOOST_JSON_FAIL(ec, error::not_string); 424   29 BOOST_JSON_FAIL(ec, error::not_string);
HITCBC 425   29 return ec; 425   29 return ec;
426   } 426   }
427   427  
428   system::result<std::int64_t&> 428   system::result<std::int64_t&>
HITCBC 429   69 value::try_as_int64() noexcept 429   69 value::try_as_int64() noexcept
430   { 430   {
HITCBC 431   69 if( is_int64() ) 431   69 if( is_int64() )
HITCBC 432   55 return sca_.i; 432   55 return sca_.i;
433   433  
HITCBC 434   14 system::error_code ec; 434   14 system::error_code ec;
HITCBC 435   14 BOOST_JSON_FAIL(ec, error::not_int64); 435   14 BOOST_JSON_FAIL(ec, error::not_int64);
HITCBC 436   14 return ec; 436   14 return ec;
437   } 437   }
438   438  
439   system::result<std::int64_t> 439   system::result<std::int64_t>
HITCBC 440   33 value::try_as_int64() const noexcept 440   33 value::try_as_int64() const noexcept
441   { 441   {
HITCBC 442   33 if( is_int64() ) 442   33 if( is_int64() )
HITCBC 443   19 return sca_.i; 443   19 return sca_.i;
444   444  
HITCBC 445   14 system::error_code ec; 445   14 system::error_code ec;
HITCBC 446   14 BOOST_JSON_FAIL(ec, error::not_int64); 446   14 BOOST_JSON_FAIL(ec, error::not_int64);
HITCBC 447   14 return ec; 447   14 return ec;
448   } 448   }
449   449  
450   system::result<std::uint64_t&> 450   system::result<std::uint64_t&>
HITCBC 451   16 value::try_as_uint64() noexcept 451   16 value::try_as_uint64() noexcept
452   { 452   {
HITCBC 453   16 if( is_uint64() ) 453   16 if( is_uint64() )
HITCBC 454   2 return sca_.u; 454   2 return sca_.u;
455   455  
HITCBC 456   14 system::error_code ec; 456   14 system::error_code ec;
HITCBC 457   14 BOOST_JSON_FAIL(ec, error::not_uint64); 457   14 BOOST_JSON_FAIL(ec, error::not_uint64);
HITCBC 458   14 return ec; 458   14 return ec;
459   } 459   }
460   460  
461   system::result<std::uint64_t> 461   system::result<std::uint64_t>
HITCBC 462   16 value::try_as_uint64() const noexcept 462   16 value::try_as_uint64() const noexcept
463   { 463   {
HITCBC 464   16 if( is_uint64() ) 464   16 if( is_uint64() )
HITCBC 465   2 return sca_.u; 465   2 return sca_.u;
466   466  
HITCBC 467   14 system::error_code ec; 467   14 system::error_code ec;
HITCBC 468   14 BOOST_JSON_FAIL(ec, error::not_uint64); 468   14 BOOST_JSON_FAIL(ec, error::not_uint64);
HITCBC 469   14 return ec; 469   14 return ec;
470   } 470   }
471   471  
472   system::result<double&> 472   system::result<double&>
HITCBC 473   2000657 value::try_as_double() noexcept 473   2000657 value::try_as_double() noexcept
474   { 474   {
HITCBC 475   2000657 if( is_double() ) 475   2000657 if( is_double() )
HITCBC 476   2000643 return sca_.d; 476   2000643 return sca_.d;
477   477  
HITCBC 478   14 system::error_code ec; 478   14 system::error_code ec;
HITCBC 479   14 BOOST_JSON_FAIL(ec, error::not_double); 479   14 BOOST_JSON_FAIL(ec, error::not_double);
HITCBC 480   14 return ec; 480   14 return ec;
481   } 481   }
482   482  
483   system::result<double> 483   system::result<double>
HITCBC 484   580 value::try_as_double() const noexcept 484   580 value::try_as_double() const noexcept
485   { 485   {
HITCBC 486   580 if( is_double() ) 486   580 if( is_double() )
HITCBC 487   566 return sca_.d; 487   566 return sca_.d;
488   488  
HITCBC 489   14 system::error_code ec; 489   14 system::error_code ec;
HITCBC 490   14 BOOST_JSON_FAIL(ec, error::not_double); 490   14 BOOST_JSON_FAIL(ec, error::not_double);
HITCBC 491   14 return ec; 491   14 return ec;
492   } 492   }
493   493  
494   system::result<bool&> 494   system::result<bool&>
HITCBC 495   19 value::try_as_bool() noexcept 495   19 value::try_as_bool() noexcept
496   { 496   {
HITCBC 497   19 if( is_bool() ) 497   19 if( is_bool() )
HITCBC 498   4 return sca_.b; 498   4 return sca_.b;
499   499  
HITCBC 500   15 system::error_code ec; 500   15 system::error_code ec;
HITCBC 501   15 BOOST_JSON_FAIL(ec, error::not_bool); 501   15 BOOST_JSON_FAIL(ec, error::not_bool);
HITCBC 502   15 return ec; 502   15 return ec;
503   } 503   }
504   504  
505   system::result<bool> 505   system::result<bool>
HITCBC 506   30 value::try_as_bool() const noexcept 506   30 value::try_as_bool() const noexcept
507   { 507   {
HITCBC 508   30 if( is_bool() ) 508   30 if( is_bool() )
HITCBC 509   16 return sca_.b; 509   16 return sca_.b;
510   510  
HITCBC 511   14 system::error_code ec; 511   14 system::error_code ec;
HITCBC 512   14 BOOST_JSON_FAIL(ec, error::not_bool); 512   14 BOOST_JSON_FAIL(ec, error::not_bool);
HITCBC 513   14 return ec; 513   14 return ec;
514   } 514   }
515   515  
516   system::result<std::nullptr_t> 516   system::result<std::nullptr_t>
HITCBC 517   2 value::try_as_null() const noexcept 517   2 value::try_as_null() const noexcept
518   { 518   {
HITCBC 519   2 if( is_null() ) 519   2 if( is_null() )
HITCBC 520   1 return nullptr; 520   1 return nullptr;
521   521  
HITCBC 522   1 system::error_code ec; 522   1 system::error_code ec;
HITCBC 523   1 BOOST_JSON_FAIL(ec, error::not_null); 523   1 BOOST_JSON_FAIL(ec, error::not_null);
HITCBC 524   1 return ec; 524   1 return ec;
525   } 525   }
526   526  
527   boost::system::result<value&> 527   boost::system::result<value&>
HITCBC 528   1 value::try_at(string_view key) noexcept 528   1 value::try_at(string_view key) noexcept
529   { 529   {
HITCBC 530   1 auto r = try_as_object(); 530   1 auto r = try_as_object();
HITCBC 531   1 if( !r ) 531   1 if( !r )
MISUBC 532   return r.error(); 532   return r.error();
HITCBC 533   1 return r.unsafe_value().try_at(key); 533   1 return r.unsafe_value().try_at(key);
534   } 534   }
535   535  
536   boost::system::result<value const&> 536   boost::system::result<value const&>
HITCBC 537   3 value::try_at(string_view key) const noexcept 537   3 value::try_at(string_view key) const noexcept
538   { 538   {
HITCBC 539   3 auto r = try_as_object(); 539   3 auto r = try_as_object();
HITCBC 540   3 if( !r ) 540   3 if( !r )
MISUBC 541   return r.error(); 541   return r.error();
HITCBC 542   3 return r.unsafe_value().try_at(key); 542   3 return r.unsafe_value().try_at(key);
543   } 543   }
544   544  
545   boost::system::result<value&> 545   boost::system::result<value&>
HITCBC 546   8 value::try_at(std::size_t pos) noexcept 546   8 value::try_at(std::size_t pos) noexcept
547   { 547   {
HITCBC 548   8 auto r = try_as_array(); 548   8 auto r = try_as_array();
HITCBC 549   8 if( !r ) 549   8 if( !r )
MISUBC 550   return r.error(); 550   return r.error();
HITCBC 551   8 return r.unsafe_value().try_at(pos); 551   8 return r.unsafe_value().try_at(pos);
552   } 552   }
553   553  
554   boost::system::result<value const&> 554   boost::system::result<value const&>
HITCBC 555   2 value::try_at(std::size_t pos) const noexcept 555   2 value::try_at(std::size_t pos) const noexcept
556   { 556   {
HITCBC 557   2 auto r = try_as_array(); 557   2 auto r = try_as_array();
HITCBC 558   2 if( !r ) 558   2 if( !r )
MISUBC 559   return r.error(); 559   return r.error();
HITCBC 560   2 return r.unsafe_value().try_at(pos); 560   2 return r.unsafe_value().try_at(pos);
561   } 561   }
562   562  
563   object const& 563   object const&
HITCBC 564   197 value::as_object(source_location const& loc) const& 564   197 value::as_object(source_location const& loc) const&
565   { 565   {
HITCBC 566   197 return try_as_object().value(loc); 566   197 return try_as_object().value(loc);
567   } 567   }
568   568  
569   array const& 569   array const&
HITCBC 570   176 value::as_array(source_location const& loc) const& 570   176 value::as_array(source_location const& loc) const&
571   { 571   {
HITCBC 572   176 return try_as_array().value(loc); 572   176 return try_as_array().value(loc);
573   } 573   }
574   574  
575   string const& 575   string const&
HITCBC 576   115 value::as_string(source_location const& loc) const& 576   115 value::as_string(source_location const& loc) const&
577   { 577   {
HITCBC 578   115 return try_as_string().value(loc); 578   115 return try_as_string().value(loc);
579   } 579   }
580   580  
581   std::int64_t& 581   std::int64_t&
HITCBC 582   61 value::as_int64(source_location const& loc) 582   61 value::as_int64(source_location const& loc)
583   { 583   {
HITCBC 584   61 return try_as_int64().value(loc); 584   61 return try_as_int64().value(loc);
585   } 585   }
586   586  
587   std::int64_t 587   std::int64_t
HITCBC 588   26 value::as_int64(source_location const& loc) const 588   26 value::as_int64(source_location const& loc) const
589   { 589   {
HITCBC 590   26 return try_as_int64().value(loc); 590   26 return try_as_int64().value(loc);
591   } 591   }
592   592  
593   std::uint64_t& 593   std::uint64_t&
HITCBC 594   8 value::as_uint64(source_location const& loc) 594   8 value::as_uint64(source_location const& loc)
595   { 595   {
HITCBC 596   8 return try_as_uint64().value(loc); 596   8 return try_as_uint64().value(loc);
597   } 597   }
598   598  
599   std::uint64_t 599   std::uint64_t
HITCBC 600   8 value::as_uint64(source_location const& loc) const 600   8 value::as_uint64(source_location const& loc) const
601   { 601   {
HITCBC 602   8 return try_as_uint64().value(loc); 602   8 return try_as_uint64().value(loc);
603   } 603   }
604   604  
605   double& 605   double&
HITCBC 606   2000649 value::as_double(source_location const& loc) 606   2000649 value::as_double(source_location const& loc)
607   { 607   {
HITCBC 608   2000649 return try_as_double().value(loc); 608   2000649 return try_as_double().value(loc);
609   } 609   }
610   610  
611   double 611   double
HITCBC 612   572 value::as_double(source_location const& loc) const 612   572 value::as_double(source_location const& loc) const
613   { 613   {
HITCBC 614   572 return try_as_double().value(loc); 614   572 return try_as_double().value(loc);
615   } 615   }
616   616  
617   bool& 617   bool&
HITCBC 618   10 value::as_bool(source_location const& loc) 618   10 value::as_bool(source_location const& loc)
619   { 619   {
HITCBC 620   10 return try_as_bool().value(loc); 620   10 return try_as_bool().value(loc);
621   } 621   }
622   622  
623   bool 623   bool
HITCBC 624   22 value::as_bool(source_location const& loc) const 624   22 value::as_bool(source_location const& loc) const
625   { 625   {
HITCBC 626   22 return try_as_bool().value(loc); 626   22 return try_as_bool().value(loc);
627   } 627   }
628   628  
629   //---------------------------------------------------------- 629   //----------------------------------------------------------
630   // 630   //
631   // Modifiers 631   // Modifiers
632   // 632   //
633   //---------------------------------------------------------- 633   //----------------------------------------------------------
634   634  
635   string& 635   string&
HITCBC 636   99 value:: 636   99 value::
637   emplace_string() noexcept 637   emplace_string() noexcept
638   { 638   {
HITCBC 639   99 storage_ptr sp = destroy(); 639   99 storage_ptr sp = destroy();
HITCBC 640   99 return *::new(&str_) string(sp); 640   99 return *::new(&str_) string(sp);
HITCBC 641   99 } 641   99 }
642   642  
643   array& 643   array&
HITCBC 644   250 value:: 644   250 value::
645   emplace_array() noexcept 645   emplace_array() noexcept
646   { 646   {
HITCBC 647   250 storage_ptr sp = destroy(); 647   250 storage_ptr sp = destroy();
HITCBC 648   250 return *::new(&arr_) array(sp); 648   250 return *::new(&arr_) array(sp);
HITCBC 649   250 } 649   250 }
650   650  
651   object& 651   object&
HITCBC 652   56 value:: 652   56 value::
653   emplace_object() noexcept 653   emplace_object() noexcept
654   { 654   {
HITCBC 655   56 storage_ptr sp = destroy(); 655   56 storage_ptr sp = destroy();
HITCBC 656   56 return *::new(&obj_) object(sp); 656   56 return *::new(&obj_) object(sp);
HITCBC 657   56 } 657   56 }
658   658  
659   void 659   void
HITCBC 660   246 value:: 660   246 value::
661   swap(value& other) 661   swap(value& other)
662   { 662   {
HITCBC 663   246 if(*storage() == *other.storage()) 663   246 if(*storage() == *other.storage())
664   { 664   {
665   // fast path 665   // fast path
666   union U 666   union U
667   { 667   {
668   value tmp; 668   value tmp;
HITCBC 669   245 U(){} 669   245 U(){}
HITCBC 670   245 ~U(){} 670   245 ~U(){}
671   }; 671   };
HITCBC 672   245 U u; 672   245 U u;
HITCBC 673   245 relocate(&u.tmp, *this); 673   245 relocate(&u.tmp, *this);
HITCBC 674   245 relocate(this, other); 674   245 relocate(this, other);
HITCBC 675   245 relocate(&other, u.tmp); 675   245 relocate(&other, u.tmp);
HITCBC 676   245 return; 676   245 return;
HITCBC 677   245 } 677   245 }
678   678  
679   // copy 679   // copy
680   value temp1( 680   value temp1(
HITCBC 681   1 std::move(*this), 681   1 std::move(*this),
HITCBC 682   2 other.storage()); 682   2 other.storage());
683   value temp2( 683   value temp2(
HITCBC 684   1 std::move(other), 684   1 std::move(other),
HITCBC 685   2 this->storage()); 685   2 this->storage());
HITCBC 686   1 other.~value(); 686   1 other.~value();
HITCBC 687   1 ::new(&other) value(pilfer(temp1)); 687   1 ::new(&other) value(pilfer(temp1));
HITCBC 688   1 this->~value(); 688   1 this->~value();
HITCBC 689   1 ::new(this) value(pilfer(temp2)); 689   1 ::new(this) value(pilfer(temp2));
HITCBC 690   1 } 690   1 }
691   691  
692   std::istream& 692   std::istream&
HITCBC 693   10 operator>>( 693   10 operator>>(
694   std::istream& is, 694   std::istream& is,
695   value& jv) 695   value& jv)
696   { 696   {
697   using Traits = std::istream::traits_type; 697   using Traits = std::istream::traits_type;
698   698  
699   // sentry prepares the stream for reading and finalizes it in destructor 699   // sentry prepares the stream for reading and finalizes it in destructor
HITCBC 700   10 std::istream::sentry sentry(is); 700   10 std::istream::sentry sentry(is);
HITCBC 701   10 if( !sentry ) 701   10 if( !sentry )
HITCBC 702   1 return is; 702   1 return is;
703   703  
HITCBC 704   9 parse_options opts = get_parse_options( is ); 704   9 parse_options opts = get_parse_options( is );
HITCBC 705   9 if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) ) 705   9 if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
HITCBC 706   3 opts.max_depth = depth; 706   3 opts.max_depth = depth;
707   707  
708   unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2]; 708   unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
HITCBC 709   9 stream_parser p( {}, opts, parser_buf ); 709   9 stream_parser p( {}, opts, parser_buf );
HITCBC 710   9 p.reset( jv.storage() ); 710   9 p.reset( jv.storage() );
711   711  
712   char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2]; 712   char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
HITCBC 713   9 std::streambuf& buf = *is.rdbuf(); 713   9 std::streambuf& buf = *is.rdbuf();
HITCBC 714   9 std::ios::iostate err = std::ios::goodbit; 714   9 std::ios::iostate err = std::ios::goodbit;
715   #ifndef BOOST_NO_EXCEPTIONS 715   #ifndef BOOST_NO_EXCEPTIONS
716   try 716   try
717   #endif 717   #endif
718   { 718   {
719   while( true ) 719   while( true )
720   { 720   {
HITCBC 721   15 system::error_code ec; 721   15 system::error_code ec;
722   722  
723   // we peek the buffer; this either makes sure that there's no 723   // we peek the buffer; this either makes sure that there's no
724   // more input, or makes sure there's something in the internal 724   // more input, or makes sure there's something in the internal
725   // buffer (so in_avail will return a positive number) 725   // buffer (so in_avail will return a positive number)
HITCBC 726   15 std::istream::int_type c = is.rdbuf()->sgetc(); 726   15 std::istream::int_type c = is.rdbuf()->sgetc();
727   // if we indeed reached EOF, we check if we parsed a full JSON 727   // if we indeed reached EOF, we check if we parsed a full JSON
728   // document; if not, we error out 728   // document; if not, we error out
HITCBC 729   13 if( Traits::eq_int_type(c, Traits::eof()) ) 729   13 if( Traits::eq_int_type(c, Traits::eof()) )
730   { 730   {
HITCBC 731   3 err |= std::ios::eofbit; 731   3 err |= std::ios::eofbit;
HITCBC 732   3 p.finish(ec); 732   3 p.finish(ec);
HITCBC 733   3 if( ec.failed() ) 733   3 if( ec.failed() )
HITCBC 734   4 break; 734   4 break;
735   } 735   }
736   736  
737   // regardless of reaching EOF, we might have parsed a full JSON 737   // regardless of reaching EOF, we might have parsed a full JSON
738   // document; if so, we successfully finish 738   // document; if so, we successfully finish
HITCBC 739   12 if( p.done() ) 739   12 if( p.done() )
740   { 740   {
HITCBC 741   3 jv = p.release(); 741   3 jv = p.release();
HITCBC 742   3 return is; 742   3 return is;
743   } 743   }
744   744  
745   // at this point we definitely have more input, specifically in 745   // at this point we definitely have more input, specifically in
746   // buf's internal buffer; we also definitely haven't parsed a whole 746   // buf's internal buffer; we also definitely haven't parsed a whole
747   // document 747   // document
HITCBC 748   9 std::streamsize available = buf.in_avail(); 748   9 std::streamsize available = buf.in_avail();
749   // if this assert fails, the streambuf is buggy 749   // if this assert fails, the streambuf is buggy
HITCBC 750   9 BOOST_ASSERT( available > 0 ); 750   9 BOOST_ASSERT( available > 0 );
751   751  
HITCBC 752   18 available = ( std::min )( 752   18 available = ( std::min )(
HITCBC 753   9 static_cast<std::size_t>(available), sizeof(read_buf) ); 753   9 static_cast<std::size_t>(available), sizeof(read_buf) );
754   // we read from the internal buffer of buf into our buffer 754   // we read from the internal buffer of buf into our buffer
HITCBC 755   9 available = buf.sgetn( read_buf, available ); 755   9 available = buf.sgetn( read_buf, available );
756   756  
HITCBC 757   9 std::size_t consumed = p.write_some( 757   9 std::size_t consumed = p.write_some(
758   read_buf, static_cast<std::size_t>(available), ec ); 758   read_buf, static_cast<std::size_t>(available), ec );
759   // if the parser hasn't consumed the entire input we've took from 759   // if the parser hasn't consumed the entire input we've took from
760   // buf, we put the remaining data back; this should succeed, 760   // buf, we put the remaining data back; this should succeed,
761   // because we only read data from buf's internal buffer 761   // because we only read data from buf's internal buffer
HITCBC 762   21 while( consumed++ < static_cast<std::size_t>(available) ) 762   21 while( consumed++ < static_cast<std::size_t>(available) )
763   { 763   {
HITCBC 764   12 std::istream::int_type const status = buf.sungetc(); 764   12 std::istream::int_type const status = buf.sungetc();
HITCBC 765   12 BOOST_ASSERT( status != Traits::eof() ); 765   12 BOOST_ASSERT( status != Traits::eof() );
766   (void)status; 766   (void)status;
767   } 767   }
768   768  
HITCBC 769   9 if( ec.failed() ) 769   9 if( ec.failed() )
HITCBC 770   3 break; 770   3 break;
HITCBC 771   6 } 771   6 }
772   } 772   }
773   #ifndef BOOST_NO_EXCEPTIONS 773   #ifndef BOOST_NO_EXCEPTIONS
HITCBC 774   2 catch(...) 774   2 catch(...)
775   { 775   {
776   try 776   try
777   { 777   {
HITCBC 778   2 is.setstate(std::ios::badbit); 778   2 is.setstate(std::ios::badbit);
779   } 779   }
780   // we ignore the exception, because we need to throw the original 780   // we ignore the exception, because we need to throw the original
781   // exception instead 781   // exception instead
HITCBC 782   1 catch( std::ios::failure const& ) { } 782   1 catch( std::ios::failure const& ) { }
783   783  
HITCBC 784   2 if( is.exceptions() & std::ios::badbit ) 784   2 if( is.exceptions() & std::ios::badbit )
HITCBC 785   1 throw; 785   1 throw;
HITCBC 786   2 } 786   2 }
787   #endif 787   #endif
788   788  
HITCBC 789   5 is.setstate(err | std::ios::failbit); 789   5 is.setstate(err | std::ios::failbit);
HITCBC 790   5 return is; 790   5 return is;
HITCBC 791   9 } 791   9 }
792   792  
793   std::istream& 793   std::istream&
HITCBC 794   3 operator>>( 794   3 operator>>(
795   std::istream& is, 795   std::istream& is,
796   parse_options const& opts) 796   parse_options const& opts)
797   { 797   {
HITCBC 798   3 is.iword(parse_flags_xalloc) = to_bitmask(opts); 798   3 is.iword(parse_flags_xalloc) = to_bitmask(opts);
HITCBC 799   3 is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth); 799   3 is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
HITCBC 800   3 return is; 800   3 return is;
801   } 801   }
802   802  
803   //---------------------------------------------------------- 803   //----------------------------------------------------------
804   // 804   //
805   // private 805   // private
806   // 806   //
807   //---------------------------------------------------------- 807   //----------------------------------------------------------
808   808  
809   storage_ptr 809   storage_ptr
HITCBC 810   423 value:: 810   423 value::
811   destroy() noexcept 811   destroy() noexcept
812   { 812   {
HITCBC 813   423 switch(kind()) 813   423 switch(kind())
814   { 814   {
HITCBC 815   404 case json::kind::null: 815   404 case json::kind::null:
816   case json::kind::bool_: 816   case json::kind::bool_:
817   case json::kind::int64: 817   case json::kind::int64:
818   case json::kind::uint64: 818   case json::kind::uint64:
819   case json::kind::double_: 819   case json::kind::double_:
HITCBC 820   404 break; 820   404 break;
821   821  
HITCBC 822   14 case json::kind::string: 822   14 case json::kind::string:
823   { 823   {
HITCBC 824   14 auto sp = str_.storage(); 824   14 auto sp = str_.storage();
HITCBC 825   14 str_.~string(); 825   14 str_.~string();
HITCBC 826   14 return sp; 826   14 return sp;
HITCBC 827   14 } 827   14 }
828   828  
HITCBC 829   2 case json::kind::array: 829   2 case json::kind::array:
830   { 830   {
HITCBC 831   2 auto sp = arr_.storage(); 831   2 auto sp = arr_.storage();
HITCBC 832   2 arr_.~array(); 832   2 arr_.~array();
HITCBC 833   2 return sp; 833   2 return sp;
HITCBC 834   2 } 834   2 }
835   835  
HITCBC 836   3 case json::kind::object: 836   3 case json::kind::object:
837   { 837   {
HITCBC 838   3 auto sp = obj_.storage(); 838   3 auto sp = obj_.storage();
HITCBC 839   3 obj_.~object(); 839   3 obj_.~object();
HITCBC 840   3 return sp; 840   3 return sp;
HITCBC 841   3 } 841   3 }
842   842  
843   } 843   }
HITCBC 844   404 return std::move(sp_); 844   404 return std::move(sp_);
845   } 845   }
846   846  
847   bool 847   bool
HITCBC 848   4172 value:: 848   4172 value::
849   equal(value const& other) const noexcept 849   equal(value const& other) const noexcept
850   { 850   {
HITCBC 851   4172 switch(kind()) 851   4172 switch(kind())
852   { 852   {
HITCBC 853   21 default: // unreachable()? 853   21 default: // unreachable()?
854   case json::kind::null: 854   case json::kind::null:
HITCBC 855   21 return other.kind() == json::kind::null; 855   21 return other.kind() == json::kind::null;
856   856  
HITCBC 857   17 case json::kind::bool_: 857   17 case json::kind::bool_:
858   return 858   return
HITCBC 859   27 other.kind() == json::kind::bool_ && 859   27 other.kind() == json::kind::bool_ &&
HITCBC 860   27 get_bool() == other.get_bool(); 860   27 get_bool() == other.get_bool();
861   861  
HITCBC 862   3943 case json::kind::int64: 862   3943 case json::kind::int64:
HITCBC 863   3943 switch(other.kind()) 863   3943 switch(other.kind())
864   { 864   {
HITCBC 865   3916 case json::kind::int64: 865   3916 case json::kind::int64:
HITCBC 866   3916 return get_int64() == other.get_int64(); 866   3916 return get_int64() == other.get_int64();
HITCBC 867   26 case json::kind::uint64: 867   26 case json::kind::uint64:
HITCBC 868   26 if(get_int64() < 0) 868   26 if(get_int64() < 0)
HITCBC 869   1 return false; 869   1 return false;
HITCBC 870   25 return static_cast<std::uint64_t>( 870   25 return static_cast<std::uint64_t>(
HITCBC 871   25 get_int64()) == other.get_uint64(); 871   25 get_int64()) == other.get_uint64();
HITCBC 872   1 default: 872   1 default:
HITCBC 873   1 return false; 873   1 return false;
874   } 874   }
875   875  
HITCBC 876   7 case json::kind::uint64: 876   7 case json::kind::uint64:
HITCBC 877   7 switch(other.kind()) 877   7 switch(other.kind())
878   { 878   {
HITCBC 879   2 case json::kind::uint64: 879   2 case json::kind::uint64:
HITCBC 880   2 return get_uint64() == other.get_uint64(); 880   2 return get_uint64() == other.get_uint64();
HITCBC 881   3 case json::kind::int64: 881   3 case json::kind::int64:
HITCBC 882   3 if(other.get_int64() < 0) 882   3 if(other.get_int64() < 0)
HITCBC 883   2 return false; 883   2 return false;
HITCBC 884   1 return static_cast<std::uint64_t>( 884   1 return static_cast<std::uint64_t>(
HITCBC 885   1 other.get_int64()) == get_uint64(); 885   1 other.get_int64()) == get_uint64();
HITCBC 886   2 default: 886   2 default:
HITCBC 887   2 return false; 887   2 return false;
888   } 888   }
889   889  
HITCBC 890   55 case json::kind::double_: 890   55 case json::kind::double_:
891   return 891   return
HITCBC 892   108 other.kind() == json::kind::double_ && 892   108 other.kind() == json::kind::double_ &&
HITCBC 893   108 get_double() == other.get_double(); 893   108 get_double() == other.get_double();
894   894  
HITCBC 895   47 case json::kind::string: 895   47 case json::kind::string:
896   return 896   return
HITCBC 897   91 other.kind() == json::kind::string && 897   91 other.kind() == json::kind::string &&
HITCBC 898   91 get_string() == other.get_string(); 898   91 get_string() == other.get_string();
899   899  
HITCBC 900   62 case json::kind::array: 900   62 case json::kind::array:
901   return 901   return
HITCBC 902   122 other.kind() == json::kind::array && 902   122 other.kind() == json::kind::array &&
HITCBC 903   122 get_array() == other.get_array(); 903   122 get_array() == other.get_array();
904   904  
HITCBC 905   20 case json::kind::object: 905   20 case json::kind::object:
906   return 906   return
HITCBC 907   37 other.kind() == json::kind::object && 907   37 other.kind() == json::kind::object &&
HITCBC 908   37 get_object() == other.get_object(); 908   37 get_object() == other.get_object();
909   } 909   }
910   } 910   }
911   911  
912   //---------------------------------------------------------- 912   //----------------------------------------------------------
913   // 913   //
914   // key_value_pair 914   // key_value_pair
915   // 915   //
916   //---------------------------------------------------------- 916   //----------------------------------------------------------
917   917  
918   // empty keys point here 918   // empty keys point here
919   BOOST_JSON_REQUIRE_CONST_INIT 919   BOOST_JSON_REQUIRE_CONST_INIT
920   char const 920   char const
921   key_value_pair::empty_[1] = { 0 }; 921   key_value_pair::empty_[1] = { 0 };
922   922  
HITCBC 923   38150 key_value_pair:: 923   38150 key_value_pair::
924   key_value_pair( 924   key_value_pair(
925   pilfered<json::value> key, 925   pilfered<json::value> key,
HITCBC 926   38150 pilfered<json::value> value) noexcept 926   38150 pilfered<json::value> value) noexcept
HITCBC 927   38150 : value_(value) 927   38150 : value_(value)
928   { 928   {
929   std::size_t len; 929   std::size_t len;
HITCBC 930   38150 key_ = access::release_key(key.get(), len); 930   38150 key_ = access::release_key(key.get(), len);
HITCBC 931   38150 len_ = static_cast<std::uint32_t>(len); 931   38150 len_ = static_cast<std::uint32_t>(len);
HITCBC 932   38150 } 932   38150 }
933   933  
HITCBC 934   6858 key_value_pair:: 934   6858 key_value_pair::
935   key_value_pair( 935   key_value_pair(
936   key_value_pair const& other, 936   key_value_pair const& other,
HITCBC 937   6858 storage_ptr sp) 937   6858 storage_ptr sp)
HITCBC 938   6862 : value_(other.value_, std::move(sp)) 938   6862 : value_(other.value_, std::move(sp))
939   { 939   {
940   auto p = reinterpret_cast< 940   auto p = reinterpret_cast<
HITCBC 941   6854 char*>(value_.storage()-> 941   6854 char*>(value_.storage()->
HITCBC 942   6854 allocate(other.len_ + 1, 942   6854 allocate(other.len_ + 1,
943   alignof(char))); 943   alignof(char)));
HITCBC 944   6596 std::memcpy( 944   6596 std::memcpy(
HITCBC 945   6596 p, other.key_, other.len_); 945   6596 p, other.key_, other.len_);
HITCBC 946   6596 len_ = other.len_; 946   6596 len_ = other.len_;
HITCBC 947   6596 p[len_] = 0; 947   6596 p[len_] = 0;
HITCBC 948   6596 key_ = p; 948   6596 key_ = p;
HITCBC 949   6854 } 949   6854 }
950   950  
951   //---------------------------------------------------------- 951   //----------------------------------------------------------
952   952  
953   namespace detail 953   namespace detail
954   { 954   {
955   955  
956   std::size_t 956   std::size_t
HITCBC 957   248 hash_value_impl( value const& jv ) noexcept 957   248 hash_value_impl( value const& jv ) noexcept
958   { 958   {
HITCBC 959   248 std::size_t seed = 0; 959   248 std::size_t seed = 0;
960   960  
HITCBC 961   248 kind const k = jv.kind(); 961   248 kind const k = jv.kind();
HITCBC 962   248 boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 ); 962   248 boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
963   963  
HITCBC 964   248 visit( value_hasher{seed}, jv ); 964   248 visit( value_hasher{seed}, jv );
HITCBC 965   248 return seed; 965   248 return seed;
966   } 966   }
967   967  
968   } // namespace detail 968   } // namespace detail
969   } // namespace json 969   } // namespace json
970   } // namespace boost 970   } // namespace boost
971   971  
972   //---------------------------------------------------------- 972   //----------------------------------------------------------
973   // 973   //
974   // std::hash specialization 974   // std::hash specialization
975   // 975   //
976   //---------------------------------------------------------- 976   //----------------------------------------------------------
977   977  
978   std::size_t 978   std::size_t
HITCBC 979   62 std::hash<::boost::json::value>::operator()( 979   62 std::hash<::boost::json::value>::operator()(
980   ::boost::json::value const& jv) const noexcept 980   ::boost::json::value const& jv) const noexcept
981   { 981   {
HITCBC 982   62 return ::boost::hash< ::boost::json::value >()( jv ); 982   62 return ::boost::hash< ::boost::json::value >()( jv );
983   } 983   }
984   984  
985   //---------------------------------------------------------- 985   //----------------------------------------------------------
986   986  
987   #endif 987   #endif