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