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