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