98.70% Lines (456/462) 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   2178636 value:: 80   2178636 value::
81   ~value() noexcept 81   ~value() noexcept
82   { 82   {
HITCBC 83   2178636 switch(kind()) 83   2178636 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   27376 case json::kind::string: 93   27376 case json::kind::string:
HITCBC 94   27376 str_.~string(); 94   27376 str_.~string();
HITCBC 95   27376 break; 95   27376 break;
96   96  
HITCBC 97   3087 case json::kind::array: 97   3087 case json::kind::array:
HITCBC 98   3087 arr_.~array(); 98   3087 arr_.~array();
HITCBC 99   3087 break; 99   3087 break;
100   100  
HITCBC 101   35204 case json::kind::object: 101   35204 case json::kind::object:
HITCBC 102   35204 obj_.~object(); 102   35204 obj_.~object();
HITCBC 103   35204 break; 103   35204 break;
104   } 104   }
HITCBC 105   2178636 } 105   2178636 }
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   186 value::try_as_array() const noexcept
376   { 376   {
HITCBC 377   186 if( is_array() ) 377   186 if( is_array() )
HITCBC 378   158 return arr_; 378   158 return arr_;
379   379  
HITCBC 380   28 system::error_code ec; 380   28 system::error_code ec;
HITCBC 381   28 BOOST_JSON_FAIL(ec, error::not_array); 381   28 BOOST_JSON_FAIL(ec, error::not_array);
HITCBC 382   28 return ec; 382   28 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   208 value::try_as_object() const noexcept
398   { 398   {
HITCBC 399   208 if( is_object() ) 399   208 if( is_object() )
HITCBC 400   180 return obj_; 400   180 return obj_;
401   401  
HITCBC 402   28 system::error_code ec; 402   28 system::error_code ec;
HITCBC 403   28 BOOST_JSON_FAIL(ec, error::not_object); 403   28 BOOST_JSON_FAIL(ec, error::not_object);
HITCBC 404   28 return ec; 404   28 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   1 auto r = try_as_object();
HITCBC 532   1 if( !r ) 532   1 if( !r )
MISUBC 533   return r.error(); 533   return r.error();
HITCBC 534   1 return r->try_at(key); 534   1 return r->try_at(key);
535   } 535   }
536   536  
537   boost::system::result<value const&> 537   boost::system::result<value const&>
HITCBC 538   3 value::try_at(string_view key) const noexcept 538   3 value::try_at(string_view key) const noexcept
539   { 539   {
HITCBC 540   3 auto r = try_as_object(); 540   3 auto r = try_as_object();
HITCBC 541   3 if( !r ) 541   3 if( !r )
MISUBC 542   return r.error(); 542   return r.error();
HITCBC 543   3 return r->try_at(key); 543   3 return r->try_at(key);
544   } 544   }
545   545  
546   boost::system::result<value&> 546   boost::system::result<value&>
HITCBC 547   8 value::try_at(std::size_t pos) noexcept 547   8 value::try_at(std::size_t pos) noexcept
548   { 548   {
HITCBC 549   8 auto r = try_as_array(); 549   8 auto r = try_as_array();
HITCBC 550   8 if( !r ) 550   8 if( !r )
MISUBC 551   return r.error(); 551   return r.error();
HITCBC 552   8 return r->try_at(pos); 552   8 return r->try_at(pos);
553   } 553   }
554   554  
555   boost::system::result<value const&> 555   boost::system::result<value const&>
HITCBC 556   2 value::try_at(std::size_t pos) const noexcept 556   2 value::try_at(std::size_t pos) const noexcept
557   { 557   {
HITCBC 558   2 auto r = try_as_array(); 558   2 auto r = try_as_array();
HITCBC 559   2 if( !r ) 559   2 if( !r )
MISUBC 560   return r.error(); 560   return r.error();
HITCBC 561   2 return r->try_at(pos); 561   2 return r->try_at(pos);
562   } 562   }
563   563  
564   object const& 564   object const&
HITCBC 565   197 value::as_object(source_location const& loc) const& 565   197 value::as_object(source_location const& loc) const&
566   { 566   {
HITCBC 567   197 return try_as_object().value(loc); 567   197 return try_as_object().value(loc);
568   } 568   }
569   569  
570   array const& 570   array const&
HITCBC 571   176 value::as_array(source_location const& loc) const& 571   176 value::as_array(source_location const& loc) const&
572   { 572   {
HITCBC 573   176 return try_as_array().value(loc); 573   176 return try_as_array().value(loc);
574   } 574   }
575   575  
576   string const& 576   string const&
HITCBC 577   113 value::as_string(source_location const& loc) const& 577   113 value::as_string(source_location const& loc) const&
578   { 578   {
HITCBC 579   113 return try_as_string().value(loc); 579   113 return try_as_string().value(loc);
580   } 580   }
581   581  
582   std::int64_t& 582   std::int64_t&
HITCBC 583   44 value::as_int64(source_location const& loc) 583   44 value::as_int64(source_location const& loc)
584   { 584   {
HITCBC 585   44 return try_as_int64().value(loc); 585   44 return try_as_int64().value(loc);
586   } 586   }
587   587  
588   std::int64_t 588   std::int64_t
HITCBC 589   26 value::as_int64(source_location const& loc) const 589   26 value::as_int64(source_location const& loc) const
590   { 590   {
HITCBC 591   26 return try_as_int64().value(loc); 591   26 return try_as_int64().value(loc);
592   } 592   }
593   593  
594   std::uint64_t& 594   std::uint64_t&
HITCBC 595   8 value::as_uint64(source_location const& loc) 595   8 value::as_uint64(source_location const& loc)
596   { 596   {
HITCBC 597   8 return try_as_uint64().value(loc); 597   8 return try_as_uint64().value(loc);
598   } 598   }
599   599  
600   std::uint64_t 600   std::uint64_t
HITCBC 601   8 value::as_uint64(source_location const& loc) const 601   8 value::as_uint64(source_location const& loc) const
602   { 602   {
HITCBC 603   8 return try_as_uint64().value(loc); 603   8 return try_as_uint64().value(loc);
604   } 604   }
605   605  
606   double& 606   double&
HITCBC 607   2000649 value::as_double(source_location const& loc) 607   2000649 value::as_double(source_location const& loc)
608   { 608   {
HITCBC 609   2000649 return try_as_double().value(loc); 609   2000649 return try_as_double().value(loc);
610   } 610   }
611   611  
612   double 612   double
HITCBC 613   572 value::as_double(source_location const& loc) const 613   572 value::as_double(source_location const& loc) const
614   { 614   {
HITCBC 615   572 return try_as_double().value(loc); 615   572 return try_as_double().value(loc);
616   } 616   }
617   617  
618   bool& 618   bool&
HITCBC 619   10 value::as_bool(source_location const& loc) 619   10 value::as_bool(source_location const& loc)
620   { 620   {
HITCBC 621   10 return try_as_bool().value(loc); 621   10 return try_as_bool().value(loc);
622   } 622   }
623   623  
624   bool 624   bool
HITCBC 625   22 value::as_bool(source_location const& loc) const 625   22 value::as_bool(source_location const& loc) const
626   { 626   {
HITCBC 627   22 return try_as_bool().value(loc); 627   22 return try_as_bool().value(loc);
628   } 628   }
629   629  
630   //---------------------------------------------------------- 630   //----------------------------------------------------------
631   // 631   //
632   // Modifiers 632   // Modifiers
633   // 633   //
634   //---------------------------------------------------------- 634   //----------------------------------------------------------
635   635  
636   string& 636   string&
HITCBC 637   98 value:: 637   98 value::
638   emplace_string() noexcept 638   emplace_string() noexcept
639   { 639   {
HITCBC 640   98 return *::new(&str_) string(destroy()); 640   98 return *::new(&str_) string(destroy());
641   } 641   }
642   642  
643   array& 643   array&
HITCBC 644   249 value:: 644   249 value::
645   emplace_array() noexcept 645   emplace_array() noexcept
646   { 646   {
HITCBC 647   249 return *::new(&arr_) array(destroy()); 647   249 return *::new(&arr_) array(destroy());
648   } 648   }
649   649  
650   object& 650   object&
HITCBC 651   55 value:: 651   55 value::
652   emplace_object() noexcept 652   emplace_object() noexcept
653   { 653   {
HITCBC 654   55 return *::new(&obj_) object(destroy()); 654   55 return *::new(&obj_) object(destroy());
655   } 655   }
656   656  
657   void 657   void
HITCBC 658   259 value:: 658   259 value::
659   swap(value& other) 659   swap(value& other)
660   { 660   {
HITCBC 661   259 if(*storage() == *other.storage()) 661   259 if(*storage() == *other.storage())
662   { 662   {
663   // fast path 663   // fast path
664   union U 664   union U
665   { 665   {
666   value tmp; 666   value tmp;
HITCBC 667   258 U(){} 667   258 U(){}
HITCBC 668   258 ~U(){} 668   258 ~U(){}
669   }; 669   };
HITCBC 670   258 U u; 670   258 U u;
HITCBC 671   258 relocate(&u.tmp, *this); 671   258 relocate(&u.tmp, *this);
HITCBC 672   258 relocate(this, other); 672   258 relocate(this, other);
HITCBC 673   258 relocate(&other, u.tmp); 673   258 relocate(&other, u.tmp);
HITCBC 674   258 return; 674   258 return;
HITCBC 675   258 } 675   258 }
676   676  
677   // copy 677   // copy
678   value temp1( 678   value temp1(
HITCBC 679   1 std::move(*this), 679   1 std::move(*this),
HITCBC 680   2 other.storage()); 680   2 other.storage());
681   value temp2( 681   value temp2(
HITCBC 682   1 std::move(other), 682   1 std::move(other),
HITCBC 683   2 this->storage()); 683   2 this->storage());
HITCBC 684   1 other.~value(); 684   1 other.~value();
HITCBC 685   1 ::new(&other) value(pilfer(temp1)); 685   1 ::new(&other) value(pilfer(temp1));
HITCBC 686   1 this->~value(); 686   1 this->~value();
HITCBC 687   1 ::new(this) value(pilfer(temp2)); 687   1 ::new(this) value(pilfer(temp2));
HITCBC 688   1 } 688   1 }
689   689  
690   std::istream& 690   std::istream&
HITCBC 691   10 operator>>( 691   10 operator>>(
692   std::istream& is, 692   std::istream& is,
693   value& jv) 693   value& jv)
694   { 694   {
695   using Traits = std::istream::traits_type; 695   using Traits = std::istream::traits_type;
696   696  
697   // sentry prepares the stream for reading and finalizes it in destructor 697   // sentry prepares the stream for reading and finalizes it in destructor
HITCBC 698   10 std::istream::sentry sentry(is); 698   10 std::istream::sentry sentry(is);
HITCBC 699   10 if( !sentry ) 699   10 if( !sentry )
HITCBC 700   1 return is; 700   1 return is;
701   701  
HITCBC 702   9 parse_options opts = get_parse_options( is ); 702   9 parse_options opts = get_parse_options( is );
HITCBC 703   9 if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) ) 703   9 if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
HITCBC 704   3 opts.max_depth = depth; 704   3 opts.max_depth = depth;
705   705  
706   unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2]; 706   unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
HITCBC 707   9 stream_parser p( {}, opts, parser_buf ); 707   9 stream_parser p( {}, opts, parser_buf );
HITCBC 708   9 p.reset( jv.storage() ); 708   9 p.reset( jv.storage() );
709   709  
710   char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2]; 710   char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
HITCBC 711   9 std::streambuf& buf = *is.rdbuf(); 711   9 std::streambuf& buf = *is.rdbuf();
HITCBC 712   9 std::ios::iostate err = std::ios::goodbit; 712   9 std::ios::iostate err = std::ios::goodbit;
713   #ifndef BOOST_NO_EXCEPTIONS 713   #ifndef BOOST_NO_EXCEPTIONS
714   try 714   try
715   #endif 715   #endif
716   { 716   {
717   while( true ) 717   while( true )
718   { 718   {
HITCBC 719   15 system::error_code ec; 719   15 system::error_code ec;
720   720  
721   // we peek the buffer; this either makes sure that there's no 721   // we peek the buffer; this either makes sure that there's no
722   // more input, or makes sure there's something in the internal 722   // more input, or makes sure there's something in the internal
723   // buffer (so in_avail will return a positive number) 723   // buffer (so in_avail will return a positive number)
HITCBC 724   15 std::istream::int_type c = is.rdbuf()->sgetc(); 724   15 std::istream::int_type c = is.rdbuf()->sgetc();
725   // if we indeed reached EOF, we check if we parsed a full JSON 725   // if we indeed reached EOF, we check if we parsed a full JSON
726   // document; if not, we error out 726   // document; if not, we error out
HITCBC 727   13 if( Traits::eq_int_type(c, Traits::eof()) ) 727   13 if( Traits::eq_int_type(c, Traits::eof()) )
728   { 728   {
HITCBC 729   3 err |= std::ios::eofbit; 729   3 err |= std::ios::eofbit;
HITCBC 730   3 p.finish(ec); 730   3 p.finish(ec);
HITCBC 731   3 if( ec.failed() ) 731   3 if( ec.failed() )
HITCBC 732   4 break; 732   4 break;
733   } 733   }
734   734  
735   // regardless of reaching EOF, we might have parsed a full JSON 735   // regardless of reaching EOF, we might have parsed a full JSON
736   // document; if so, we successfully finish 736   // document; if so, we successfully finish
HITCBC 737   12 if( p.done() ) 737   12 if( p.done() )
738   { 738   {
HITCBC 739   3 jv = p.release(); 739   3 jv = p.release();
HITCBC 740   3 return is; 740   3 return is;
741   } 741   }
742   742  
743   // at this point we definitely have more input, specifically in 743   // at this point we definitely have more input, specifically in
744   // buf's internal buffer; we also definitely haven't parsed a whole 744   // buf's internal buffer; we also definitely haven't parsed a whole
745   // document 745   // document
HITCBC 746   9 std::streamsize available = buf.in_avail(); 746   9 std::streamsize available = buf.in_avail();
747   // if this assert fails, the streambuf is buggy 747   // if this assert fails, the streambuf is buggy
HITCBC 748   9 BOOST_ASSERT( available > 0 ); 748   9 BOOST_ASSERT( available > 0 );
749   749  
HITCBC 750   18 available = ( std::min )( 750   18 available = ( std::min )(
HITCBC 751   9 static_cast<std::size_t>(available), sizeof(read_buf) ); 751   9 static_cast<std::size_t>(available), sizeof(read_buf) );
752   // we read from the internal buffer of buf into our buffer 752   // we read from the internal buffer of buf into our buffer
HITCBC 753   9 available = buf.sgetn( read_buf, available ); 753   9 available = buf.sgetn( read_buf, available );
754   754  
HITCBC 755   9 std::size_t consumed = p.write_some( 755   9 std::size_t consumed = p.write_some(
756   read_buf, static_cast<std::size_t>(available), ec ); 756   read_buf, static_cast<std::size_t>(available), ec );
757   // if the parser hasn't consumed the entire input we've took from 757   // if the parser hasn't consumed the entire input we've took from
758   // buf, we put the remaining data back; this should succeed, 758   // buf, we put the remaining data back; this should succeed,
759   // because we only read data from buf's internal buffer 759   // because we only read data from buf's internal buffer
HITCBC 760   21 while( consumed++ < static_cast<std::size_t>(available) ) 760   21 while( consumed++ < static_cast<std::size_t>(available) )
761   { 761   {
HITCBC 762   12 std::istream::int_type const status = buf.sungetc(); 762   12 std::istream::int_type const status = buf.sungetc();
HITCBC 763   12 BOOST_ASSERT( status != Traits::eof() ); 763   12 BOOST_ASSERT( status != Traits::eof() );
764   (void)status; 764   (void)status;
765   } 765   }
766   766  
HITCBC 767   9 if( ec.failed() ) 767   9 if( ec.failed() )
HITCBC 768   3 break; 768   3 break;
HITCBC 769   6 } 769   6 }
770   } 770   }
771   #ifndef BOOST_NO_EXCEPTIONS 771   #ifndef BOOST_NO_EXCEPTIONS
HITCBC 772   2 catch(...) 772   2 catch(...)
773   { 773   {
774   try 774   try
775   { 775   {
HITCBC 776   2 is.setstate(std::ios::badbit); 776   2 is.setstate(std::ios::badbit);
777   } 777   }
778   // we ignore the exception, because we need to throw the original 778   // we ignore the exception, because we need to throw the original
779   // exception instead 779   // exception instead
HITCBC 780   1 catch( std::ios::failure const& ) { } 780   1 catch( std::ios::failure const& ) { }
781   781  
HITCBC 782   2 if( is.exceptions() & std::ios::badbit ) 782   2 if( is.exceptions() & std::ios::badbit )
HITCBC 783   1 throw; 783   1 throw;
HITCBC 784   2 } 784   2 }
785   #endif 785   #endif
786   786  
HITCBC 787   5 is.setstate(err | std::ios::failbit); 787   5 is.setstate(err | std::ios::failbit);
HITCBC 788   5 return is; 788   5 return is;
HITCBC 789   9 } 789   9 }
790   790  
791   std::istream& 791   std::istream&
HITCBC 792   3 operator>>( 792   3 operator>>(
793   std::istream& is, 793   std::istream& is,
794   parse_options const& opts) 794   parse_options const& opts)
795   { 795   {
HITCBC 796   3 is.iword(parse_flags_xalloc) = to_bitmask(opts); 796   3 is.iword(parse_flags_xalloc) = to_bitmask(opts);
HITCBC 797   3 is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth); 797   3 is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
HITCBC 798   3 return is; 798   3 return is;
799   } 799   }
800   800  
801   //---------------------------------------------------------- 801   //----------------------------------------------------------
802   // 802   //
803   // private 803   // private
804   // 804   //
805   //---------------------------------------------------------- 805   //----------------------------------------------------------
806   806  
807   storage_ptr 807   storage_ptr
HITCBC 808   420 value:: 808   420 value::
809   destroy() noexcept 809   destroy() noexcept
810   { 810   {
HITCBC 811   420 switch(kind()) 811   420 switch(kind())
812   { 812   {
HITCBC 813   401 case json::kind::null: 813   401 case json::kind::null:
814   case json::kind::bool_: 814   case json::kind::bool_:
815   case json::kind::int64: 815   case json::kind::int64:
816   case json::kind::uint64: 816   case json::kind::uint64:
817   case json::kind::double_: 817   case json::kind::double_:
HITCBC 818   401 break; 818   401 break;
819   819  
HITCBC 820   14 case json::kind::string: 820   14 case json::kind::string:
821   { 821   {
HITCBC 822   14 auto sp = str_.storage(); 822   14 auto sp = str_.storage();
HITCBC 823   14 str_.~string(); 823   14 str_.~string();
HITCBC 824   14 return sp; 824   14 return sp;
HITCBC 825   14 } 825   14 }
826   826  
HITCBC 827   2 case json::kind::array: 827   2 case json::kind::array:
828   { 828   {
HITCBC 829   2 auto sp = arr_.storage(); 829   2 auto sp = arr_.storage();
HITCBC 830   2 arr_.~array(); 830   2 arr_.~array();
HITCBC 831   2 return sp; 831   2 return sp;
HITCBC 832   2 } 832   2 }
833   833  
HITCBC 834   3 case json::kind::object: 834   3 case json::kind::object:
835   { 835   {
HITCBC 836   3 auto sp = obj_.storage(); 836   3 auto sp = obj_.storage();
HITCBC 837   3 obj_.~object(); 837   3 obj_.~object();
HITCBC 838   3 return sp; 838   3 return sp;
HITCBC 839   3 } 839   3 }
840   840  
841   } 841   }
HITCBC 842   401 return std::move(sp_); 842   401 return std::move(sp_);
843   } 843   }
844   844  
845   bool 845   bool
HITCBC 846   4172 value:: 846   4172 value::
847   equal(value const& other) const noexcept 847   equal(value const& other) const noexcept
848   { 848   {
HITCBC 849   4172 switch(kind()) 849   4172 switch(kind())
850   { 850   {
HITCBC 851   21 default: // unreachable()? 851   21 default: // unreachable()?
852   case json::kind::null: 852   case json::kind::null:
HITCBC 853   21 return other.kind() == json::kind::null; 853   21 return other.kind() == json::kind::null;
854   854  
HITCBC 855   17 case json::kind::bool_: 855   17 case json::kind::bool_:
856   return 856   return
HITCBC 857   27 other.kind() == json::kind::bool_ && 857   27 other.kind() == json::kind::bool_ &&
HITCBC 858   27 get_bool() == other.get_bool(); 858   27 get_bool() == other.get_bool();
859   859  
HITCBC 860   3943 case json::kind::int64: 860   3943 case json::kind::int64:
HITCBC 861   3943 switch(other.kind()) 861   3943 switch(other.kind())
862   { 862   {
HITCBC 863   3916 case json::kind::int64: 863   3916 case json::kind::int64:
HITCBC 864   3916 return get_int64() == other.get_int64(); 864   3916 return get_int64() == other.get_int64();
HITCBC 865   26 case json::kind::uint64: 865   26 case json::kind::uint64:
HITCBC 866   26 if(get_int64() < 0) 866   26 if(get_int64() < 0)
HITCBC 867   1 return false; 867   1 return false;
HITCBC 868   25 return static_cast<std::uint64_t>( 868   25 return static_cast<std::uint64_t>(
HITCBC 869   25 get_int64()) == other.get_uint64(); 869   25 get_int64()) == other.get_uint64();
HITCBC 870   1 default: 870   1 default:
HITCBC 871   1 return false; 871   1 return false;
872   } 872   }
873   873  
HITCBC 874   7 case json::kind::uint64: 874   7 case json::kind::uint64:
HITCBC 875   7 switch(other.kind()) 875   7 switch(other.kind())
876   { 876   {
HITCBC 877   2 case json::kind::uint64: 877   2 case json::kind::uint64:
HITCBC 878   2 return get_uint64() == other.get_uint64(); 878   2 return get_uint64() == other.get_uint64();
HITCBC 879   3 case json::kind::int64: 879   3 case json::kind::int64:
HITCBC 880   3 if(other.get_int64() < 0) 880   3 if(other.get_int64() < 0)
HITCBC 881   2 return false; 881   2 return false;
HITCBC 882   1 return static_cast<std::uint64_t>( 882   1 return static_cast<std::uint64_t>(
HITCBC 883   1 other.get_int64()) == get_uint64(); 883   1 other.get_int64()) == get_uint64();
HITCBC 884   2 default: 884   2 default:
HITCBC 885   2 return false; 885   2 return false;
886   } 886   }
887   887  
HITCBC 888   55 case json::kind::double_: 888   55 case json::kind::double_:
889   return 889   return
HITCBC 890   108 other.kind() == json::kind::double_ && 890   108 other.kind() == json::kind::double_ &&
HITCBC 891   108 get_double() == other.get_double(); 891   108 get_double() == other.get_double();
892   892  
HITCBC 893   47 case json::kind::string: 893   47 case json::kind::string:
894   return 894   return
HITCBC 895   91 other.kind() == json::kind::string && 895   91 other.kind() == json::kind::string &&
HITCBC 896   91 get_string() == other.get_string(); 896   91 get_string() == other.get_string();
897   897  
HITCBC 898   62 case json::kind::array: 898   62 case json::kind::array:
899   return 899   return
HITCBC 900   122 other.kind() == json::kind::array && 900   122 other.kind() == json::kind::array &&
HITCBC 901   122 get_array() == other.get_array(); 901   122 get_array() == other.get_array();
902   902  
HITCBC 903   20 case json::kind::object: 903   20 case json::kind::object:
904   return 904   return
HITCBC 905   37 other.kind() == json::kind::object && 905   37 other.kind() == json::kind::object &&
HITCBC 906   37 get_object() == other.get_object(); 906   37 get_object() == other.get_object();
907   } 907   }
908   } 908   }
909   909  
910   //---------------------------------------------------------- 910   //----------------------------------------------------------
911   // 911   //
912   // key_value_pair 912   // key_value_pair
913   // 913   //
914   //---------------------------------------------------------- 914   //----------------------------------------------------------
915   915  
916   // empty keys point here 916   // empty keys point here
917   BOOST_JSON_REQUIRE_CONST_INIT 917   BOOST_JSON_REQUIRE_CONST_INIT
918   char const 918   char const
919   key_value_pair::empty_[1] = { 0 }; 919   key_value_pair::empty_[1] = { 0 };
920   920  
HITCBC 921   38150 key_value_pair:: 921   38150 key_value_pair::
922   key_value_pair( 922   key_value_pair(
923   pilfered<json::value> key, 923   pilfered<json::value> key,
HITCBC 924   38150 pilfered<json::value> value) noexcept 924   38150 pilfered<json::value> value) noexcept
HITCBC 925   38150 : value_(value) 925   38150 : value_(value)
926   { 926   {
927   std::size_t len; 927   std::size_t len;
HITCBC 928   38150 key_ = access::release_key(key.get(), len); 928   38150 key_ = access::release_key(key.get(), len);
HITCBC 929   38150 len_ = static_cast<std::uint32_t>(len); 929   38150 len_ = static_cast<std::uint32_t>(len);
HITCBC 930   38150 } 930   38150 }
931   931  
HITCBC 932   6858 key_value_pair:: 932   6858 key_value_pair::
933   key_value_pair( 933   key_value_pair(
934   key_value_pair const& other, 934   key_value_pair const& other,
HITCBC 935   6858 storage_ptr sp) 935   6858 storage_ptr sp)
HITCBC 936   6862 : value_(other.value_, std::move(sp)) 936   6862 : value_(other.value_, std::move(sp))
937   { 937   {
938   auto p = reinterpret_cast< 938   auto p = reinterpret_cast<
HITCBC 939   6854 char*>(value_.storage()-> 939   6854 char*>(value_.storage()->
HITCBC 940   6854 allocate(other.len_ + 1, 940   6854 allocate(other.len_ + 1,
941   alignof(char))); 941   alignof(char)));
HITCBC 942   6596 std::memcpy( 942   6596 std::memcpy(
HITCBC 943   6596 p, other.key_, other.len_); 943   6596 p, other.key_, other.len_);
HITCBC 944   6596 len_ = other.len_; 944   6596 len_ = other.len_;
HITCBC 945   6596 p[len_] = 0; 945   6596 p[len_] = 0;
HITCBC 946   6596 key_ = p; 946   6596 key_ = p;
HITCBC 947   6854 } 947   6854 }
948   948  
949   //---------------------------------------------------------- 949   //----------------------------------------------------------
950   950  
951   namespace detail 951   namespace detail
952   { 952   {
953   953  
954   std::size_t 954   std::size_t
HITCBC 955   248 hash_value_impl( value const& jv ) noexcept 955   248 hash_value_impl( value const& jv ) noexcept
956   { 956   {
HITCBC 957   248 std::size_t seed = 0; 957   248 std::size_t seed = 0;
958   958  
HITCBC 959   248 kind const k = jv.kind(); 959   248 kind const k = jv.kind();
HITCBC 960   248 boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 ); 960   248 boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
961   961  
HITCBC 962   248 visit( value_hasher{seed}, jv ); 962   248 visit( value_hasher{seed}, jv );
HITCBC 963   248 return seed; 963   248 return seed;
964   } 964   }
965   965  
966   } // namespace detail 966   } // namespace detail
967   } // namespace json 967   } // namespace json
968   } // namespace boost 968   } // namespace boost
969   969  
970   //---------------------------------------------------------- 970   //----------------------------------------------------------
971   // 971   //
972   // std::hash specialization 972   // std::hash specialization
973   // 973   //
974   //---------------------------------------------------------- 974   //----------------------------------------------------------
975   975  
976   std::size_t 976   std::size_t
HITCBC 977   62 std::hash<::boost::json::value>::operator()( 977   62 std::hash<::boost::json::value>::operator()(
978   ::boost::json::value const& jv) const noexcept 978   ::boost::json::value const& jv) const noexcept
979   { 979   {
HITCBC 980   62 return ::boost::hash< ::boost::json::value >()( jv ); 980   62 return ::boost::hash< ::boost::json::value >()( jv );
981   } 981   }
982   982  
983   //---------------------------------------------------------- 983   //----------------------------------------------------------
984   984  
985   #endif 985   #endif