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