summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2016-12-28 20:41:38 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2016-12-28 20:41:38 -0500
commit4af7e55733098ca42f75a4ffaca1b0f6bab4dd36 (patch)
tree9ca8b51a4c374e8615652def59fa05ff3c7871e2
parent1f898f3bd66c29672275c2c884b17ba662ced626 (diff)
downloadverbly-4af7e55733098ca42f75a4ffaca1b0f6bab4dd36.tar.gz
verbly-4af7e55733098ca42f75a4ffaca1b0f6bab4dd36.tar.bz2
verbly-4af7e55733098ca42f75a4ffaca1b0f6bab4dd36.zip
Updated to nlohmann/json 2.0.9
-rw-r--r--vendor/json/json.hpp1989
1 files changed, 1698 insertions, 291 deletions
diff --git a/vendor/json/json.hpp b/vendor/json/json.hpp index 4447412..23058be 100644 --- a/vendor/json/json.hpp +++ b/vendor/json/json.hpp
@@ -1,7 +1,7 @@
1/* 1/*
2 __ _____ _____ _____ 2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++ 3 __| | __| | | | JSON for Modern C++
4| | |__ | | | | | | version 2.0.7 4| | |__ | | | | | | version 2.0.9
5|_____|_____|_____|_|___| https://github.com/nlohmann/json 5|_____|_____|_____|_|___| https://github.com/nlohmann/json
6 6
7Licensed under the MIT License <http://opensource.org/licenses/MIT>. 7Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -29,32 +29,32 @@ SOFTWARE.
29#ifndef NLOHMANN_JSON_HPP 29#ifndef NLOHMANN_JSON_HPP
30#define NLOHMANN_JSON_HPP 30#define NLOHMANN_JSON_HPP
31 31
32#include <algorithm> 32#include <algorithm> // all_of, for_each, transform
33#include <array> 33#include <array> // array
34#include <cassert> 34#include <cassert> // assert
35#include <cctype> 35#include <cctype> // isdigit
36#include <ciso646> 36#include <ciso646> // and, not, or
37#include <cmath> 37#include <cmath> // isfinite, ldexp, signbit
38#include <cstddef> 38#include <cstddef> // nullptr_t, ptrdiff_t, size_t
39#include <cstdint> 39#include <cstdint> // int64_t, uint64_t
40#include <cstdlib> 40#include <cstdlib> // strtod, strtof, strtold, strtoul
41#include <cstring> 41#include <cstring> // strlen
42#include <functional> 42#include <functional> // function, hash, less
43#include <initializer_list> 43#include <initializer_list> // initializer_list
44#include <iomanip> 44#include <iomanip> // setw
45#include <iostream> 45#include <iostream> // istream, ostream
46#include <iterator> 46#include <iterator> // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
47#include <limits> 47#include <limits> // numeric_limits
48#include <locale> 48#include <locale> // locale
49#include <map> 49#include <map> // map
50#include <memory> 50#include <memory> // addressof, allocator, allocator_traits, unique_ptr
51#include <numeric> 51#include <numeric> // accumulate
52#include <sstream> 52#include <sstream> // stringstream
53#include <stdexcept> 53#include <stdexcept> // domain_error, invalid_argument, out_of_range
54#include <string> 54#include <string> // getline, stoi, string, to_string
55#include <type_traits> 55#include <type_traits> // add_pointer, enable_if, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_floating_point, is_integral, is_nothrow_move_assignable, std::is_nothrow_move_constructible, std::is_pointer, std::is_reference, std::is_same, remove_const, remove_pointer, remove_reference
56#include <utility> 56#include <utility> // declval, forward, make_pair, move, pair, swap
57#include <vector> 57#include <vector> // vector
58 58
59// exclude unsupported compilers 59// exclude unsupported compilers
60#if defined(__clang__) 60#if defined(__clang__)
@@ -75,6 +75,12 @@ SOFTWARE.
75 #pragma GCC diagnostic ignored "-Wfloat-equal" 75 #pragma GCC diagnostic ignored "-Wfloat-equal"
76#endif 76#endif
77 77
78// disable documentation warnings on clang
79#if defined(__clang__)
80 #pragma GCC diagnostic push
81 #pragma GCC diagnostic ignored "-Wdocumentation"
82#endif
83
78// allow for portable deprecation warnings 84// allow for portable deprecation warnings
79#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 85#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
80 #define JSON_DEPRECATED __attribute__((deprecated)) 86 #define JSON_DEPRECATED __attribute__((deprecated))
@@ -122,26 +128,6 @@ struct has_mapped_type
122 std::is_integral<decltype(detect(std::declval<T>()))>::value; 128 std::is_integral<decltype(detect(std::declval<T>()))>::value;
123}; 129};
124 130
125/*!
126@brief helper class to create locales with decimal point
127
128This struct is used a default locale during the JSON serialization. JSON
129requires the decimal point to be `.`, so this function overloads the
130`do_decimal_point()` function to return `.`. This function is called by
131float-to-string conversions to retrieve the decimal separator between integer
132and fractional parts.
133
134@sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315
135@since version 2.0.0
136*/
137struct DecimalSeparator : std::numpunct<char>
138{
139 char do_decimal_point() const
140 {
141 return '.';
142 }
143};
144
145} 131}
146 132
147/*! 133/*!
@@ -242,6 +228,7 @@ class basic_json
242 228
243 public: 229 public:
244 // forward declarations 230 // forward declarations
231 template<typename U> class iter_impl;
245 template<typename Base> class json_reverse_iterator; 232 template<typename Base> class json_reverse_iterator;
246 class json_pointer; 233 class json_pointer;
247 234
@@ -276,9 +263,9 @@ class basic_json
276 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; 263 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
277 264
278 /// an iterator for a basic_json container 265 /// an iterator for a basic_json container
279 class iterator; 266 using iterator = iter_impl<basic_json>;
280 /// a const iterator for a basic_json container 267 /// a const iterator for a basic_json container
281 class const_iterator; 268 using const_iterator = iter_impl<const basic_json>;
282 /// a reverse iterator for a basic_json container 269 /// a reverse iterator for a basic_json container
283 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; 270 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
284 /// a const reverse iterator for a basic_json container 271 /// a const reverse iterator for a basic_json container
@@ -964,7 +951,7 @@ class basic_json
964 951
965 With a parser callback function, the result of parsing a JSON text can be 952 With a parser callback function, the result of parsing a JSON text can be
966 influenced. When passed to @ref parse(std::istream&, const 953 influenced. When passed to @ref parse(std::istream&, const
967 parser_callback_t) or @ref parse(const char*, const parser_callback_t), 954 parser_callback_t) or @ref parse(const CharT, const parser_callback_t),
968 it is called on certain events (passed as @ref parse_event_t via parameter 955 it is called on certain events (passed as @ref parse_event_t via parameter
969 @a event) with a set recursion depth @a depth and context JSON value 956 @a event) with a set recursion depth @a depth and context JSON value
970 @a parsed. The return value of the callback function is a boolean 957 @a parsed. The return value of the callback function is a boolean
@@ -1007,7 +994,7 @@ class basic_json
1007 skipped completely or replaced by an empty discarded object. 994 skipped completely or replaced by an empty discarded object.
1008 995
1009 @sa @ref parse(std::istream&, parser_callback_t) or 996 @sa @ref parse(std::istream&, parser_callback_t) or
1010 @ref parse(const char*, parser_callback_t) for examples 997 @ref parse(const CharT, const parser_callback_t) for examples
1011 998
1012 @since version 1.0.0 999 @since version 1.0.0
1013 */ 1000 */
@@ -2201,8 +2188,7 @@ class basic_json
2201 { 2188 {
2202 std::stringstream ss; 2189 std::stringstream ss;
2203 // fix locale problems 2190 // fix locale problems
2204 const static std::locale loc(std::locale(), new DecimalSeparator); 2191 ss.imbue(std::locale::classic());
2205 ss.imbue(loc);
2206 2192
2207 // 6, 15 or 16 digits of precision allows round-trip IEEE 754 2193 // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2208 // string->float->string, string->double->string or string->long 2194 // string->float->string, string->double->string or string->long
@@ -5054,6 +5040,102 @@ class basic_json
5054 } 5040 }
5055 5041
5056 /*! 5042 /*!
5043 @brief add an object to an array
5044
5045 Creates a JSON value from the passed parameters @a args to the end of the
5046 JSON value. If the function is called on a JSON null value, an empty array
5047 is created before appending the value created from @a args.
5048
5049 @param[in] args arguments to forward to a constructor of @ref basic_json
5050 @tparam Args compatible types to create a @ref basic_json object
5051
5052 @throw std::domain_error when called on a type other than JSON array or
5053 null; example: `"cannot use emplace_back() with number"`
5054
5055 @complexity Amortized constant.
5056
5057 @liveexample{The example shows how `push_back()` can be used to add
5058 elements to a JSON array. Note how the `null` value was silently converted
5059 to a JSON array.,emplace_back}
5060
5061 @since version 2.0.8
5062 */
5063 template<class... Args>
5064 void emplace_back(Args&& ... args)
5065 {
5066 // emplace_back only works for null objects or arrays
5067 if (not(is_null() or is_array()))
5068 {
5069 throw std::domain_error("cannot use emplace_back() with " + type_name());
5070 }
5071
5072 // transform null object into an array
5073 if (is_null())
5074 {
5075 m_type = value_t::array;
5076 m_value = value_t::array;
5077 assert_invariant();
5078 }
5079
5080 // add element to array (perfect forwarding)
5081 m_value.array->emplace_back(std::forward<Args>(args)...);
5082 }
5083
5084 /*!
5085 @brief add an object to an object if key does not exist
5086
5087 Inserts a new element into a JSON object constructed in-place with the given
5088 @a args if there is no element with the key in the container. If the
5089 function is called on a JSON null value, an empty object is created before
5090 appending the value created from @a args.
5091
5092 @param[in] args arguments to forward to a constructor of @ref basic_json
5093 @tparam Args compatible types to create a @ref basic_json object
5094
5095 @return a pair consisting of an iterator to the inserted element, or the
5096 already-existing element if no insertion happened, and a bool
5097 denoting whether the insertion took place.
5098
5099 @throw std::domain_error when called on a type other than JSON object or
5100 null; example: `"cannot use emplace() with number"`
5101
5102 @complexity Logarithmic in the size of the container, O(log(`size()`)).
5103
5104 @liveexample{The example shows how `emplace()` can be used to add elements
5105 to a JSON object. Note how the `null` value was silently converted to a
5106 JSON object. Further note how no value is added if there was already one
5107 value stored with the same key.,emplace}
5108
5109 @since version 2.0.8
5110 */
5111 template<class... Args>
5112 std::pair<iterator, bool> emplace(Args&& ... args)
5113 {
5114 // emplace only works for null objects or arrays
5115 if (not(is_null() or is_object()))
5116 {
5117 throw std::domain_error("cannot use emplace() with " + type_name());
5118 }
5119
5120 // transform null object into an object
5121 if (is_null())
5122 {
5123 m_type = value_t::object;
5124 m_value = value_t::object;
5125 assert_invariant();
5126 }
5127
5128 // add element to array (perfect forwarding)
5129 auto res = m_value.object->emplace(std::forward<Args>(args)...);
5130 // create result iterator and set iterator to the result of emplace
5131 auto it = begin();
5132 it.m_it.object_iterator = res.first;
5133
5134 // return pair of iterator and boolean
5135 return {it, res.second};
5136 }
5137
5138 /*!
5057 @brief inserts element 5139 @brief inserts element
5058 5140
5059 Inserts element @a val before iterator @a pos. 5141 Inserts element @a val before iterator @a pos.
@@ -5829,7 +5911,7 @@ class basic_json
5829 o.width(0); 5911 o.width(0);
5830 5912
5831 // fix locale problems 5913 // fix locale problems
5832 const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator)); 5914 const auto old_locale = o.imbue(std::locale::classic());
5833 // set precision 5915 // set precision
5834 5916
5835 // 6, 15 or 16 digits of precision allows round-trip IEEE 754 5917 // 6, 15 or 16 digits of precision allows round-trip IEEE 754
@@ -5928,11 +6010,11 @@ class basic_json
5928 6010
5929 @since version 1.0.0 (originally for @ref string_t) 6011 @since version 1.0.0 (originally for @ref string_t)
5930 */ 6012 */
5931 template<typename CharPT, typename std::enable_if< 6013 template<typename CharT, typename std::enable_if<
5932 std::is_pointer<CharPT>::value and 6014 std::is_pointer<CharT>::value and
5933 std::is_integral<typename std::remove_pointer<CharPT>::type>::value and 6015 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
5934 sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0> 6016 sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
5935 static basic_json parse(const CharPT s, 6017 static basic_json parse(const CharT s,
5936 const parser_callback_t cb = nullptr) 6018 const parser_callback_t cb = nullptr)
5937 { 6019 {
5938 return parser(reinterpret_cast<const char*>(s), cb).parse(); 6020 return parser(reinterpret_cast<const char*>(s), cb).parse();
@@ -5957,7 +6039,7 @@ class basic_json
5957 @liveexample{The example below demonstrates the `parse()` function with 6039 @liveexample{The example below demonstrates the `parse()` function with
5958 and without callback function.,parse__istream__parser_callback_t} 6040 and without callback function.,parse__istream__parser_callback_t}
5959 6041
5960 @sa @ref parse(const char*, const parser_callback_t) for a version 6042 @sa @ref parse(const CharT, const parser_callback_t) for a version
5961 that reads from a string 6043 that reads from a string
5962 6044
5963 @since version 1.0.0 6045 @since version 1.0.0
@@ -6142,6 +6224,1435 @@ class basic_json
6142 6224
6143 /// @} 6225 /// @}
6144 6226
6227 //////////////////////////////////////////
6228 // binary serialization/deserialization //
6229 //////////////////////////////////////////
6230
6231 /// @name binary serialization/deserialization support
6232 /// @{
6233
6234 private:
6235 template<typename T>
6236 static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
6237 {
6238 assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6239
6240 switch (bytes)
6241 {
6242 case 8:
6243 {
6244 vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
6245 vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
6246 vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
6247 vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
6248 // intentional fall-through
6249 }
6250
6251 case 4:
6252 {
6253 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6254 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6255 // intentional fall-through
6256 }
6257
6258 case 2:
6259 {
6260 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6261 // intentional fall-through
6262 }
6263
6264 case 1:
6265 {
6266 vec.push_back(static_cast<uint8_t>(number & 0xff));
6267 break;
6268 }
6269 }
6270 }
6271
6272 /*!
6273 @brief take sufficient bytes from a vector to fill an integer variable
6274
6275 In the context of binary serialization formats, we need to read several
6276 bytes from a byte vector and combine them to multi-byte integral data
6277 types.
6278
6279 @param[in] vec byte vector to read from
6280 @param[in] current_index the position in the vector after which to read
6281
6282 @return the next sizeof(T) bytes from @a vec, in reverse order as T
6283
6284 @tparam T the integral return type
6285
6286 @throw std::out_of_range if there are less than sizeof(T)+1 bytes in the
6287 vector @a vec to read
6288
6289 In the for loop, the bytes from the vector are copied in reverse order into
6290 the return value. In the figures below, let sizeof(T)=4 and `i` be the loop
6291 variable.
6292
6293 Precondition:
6294
6295 vec: | | | a | b | c | d | T: | | | | |
6296 ^ ^ ^ ^
6297 current_index i ptr sizeof(T)
6298
6299 Postcondition:
6300
6301 vec: | | | a | b | c | d | T: | d | c | b | a |
6302 ^ ^ ^
6303 | i ptr
6304 current_index
6305
6306 @sa Code adapted from <http://stackoverflow.com/a/41031865/266378>.
6307 */
6308 template<typename T>
6309 static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
6310 {
6311 if (current_index + sizeof(T) + 1 > vec.size())
6312 {
6313 throw std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector");
6314 }
6315
6316 T result;
6317 uint8_t* ptr = reinterpret_cast<uint8_t*>(&result);
6318 for (size_t i = 0; i < sizeof(T); ++i)
6319 {
6320 *ptr++ = vec[current_index + sizeof(T) - i];
6321 }
6322 return result;
6323 }
6324
6325 /*!
6326 @brief create a MessagePack serialization of a given JSON value
6327
6328 This is a straightforward implementation of the MessagePack specification.
6329
6330 @param[in] j JSON value to serialize
6331 @param[in,out] v byte vector to write the serialization to
6332
6333 @sa https://github.com/msgpack/msgpack/blob/master/spec.md
6334 */
6335 static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
6336 {
6337 switch (j.type())
6338 {
6339 case value_t::null:
6340 {
6341 // nil
6342 v.push_back(0xc0);
6343 break;
6344 }
6345
6346 case value_t::boolean:
6347 {
6348 // true and false
6349 v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6350 break;
6351 }
6352
6353 case value_t::number_integer:
6354 {
6355 if (j.m_value.number_integer >= 0)
6356 {
6357 // MessagePack does not differentiate between positive
6358 // signed integers and unsigned integers. Therefore, we used
6359 // the code from the value_t::number_unsigned case here.
6360 if (j.m_value.number_unsigned < 128)
6361 {
6362 // positive fixnum
6363 add_to_vector(v, 1, j.m_value.number_unsigned);
6364 }
6365 else if (j.m_value.number_unsigned <= UINT8_MAX)
6366 {
6367 // uint 8
6368 v.push_back(0xcc);
6369 add_to_vector(v, 1, j.m_value.number_unsigned);
6370 }
6371 else if (j.m_value.number_unsigned <= UINT16_MAX)
6372 {
6373 // uint 16
6374 v.push_back(0xcd);
6375 add_to_vector(v, 2, j.m_value.number_unsigned);
6376 }
6377 else if (j.m_value.number_unsigned <= UINT32_MAX)
6378 {
6379 // uint 32
6380 v.push_back(0xce);
6381 add_to_vector(v, 4, j.m_value.number_unsigned);
6382 }
6383 else if (j.m_value.number_unsigned <= UINT64_MAX)
6384 {
6385 // uint 64
6386 v.push_back(0xcf);
6387 add_to_vector(v, 8, j.m_value.number_unsigned);
6388 }
6389 }
6390 else
6391 {
6392 if (j.m_value.number_integer >= -32)
6393 {
6394 // negative fixnum
6395 add_to_vector(v, 1, j.m_value.number_integer);
6396 }
6397 else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
6398 {
6399 // int 8
6400 v.push_back(0xd0);
6401 add_to_vector(v, 1, j.m_value.number_integer);
6402 }
6403 else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
6404 {
6405 // int 16
6406 v.push_back(0xd1);
6407 add_to_vector(v, 2, j.m_value.number_integer);
6408 }
6409 else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
6410 {
6411 // int 32
6412 v.push_back(0xd2);
6413 add_to_vector(v, 4, j.m_value.number_integer);
6414 }
6415 else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
6416 {
6417 // int 64
6418 v.push_back(0xd3);
6419 add_to_vector(v, 8, j.m_value.number_integer);
6420 }
6421 }
6422 break;
6423 }
6424
6425 case value_t::number_unsigned:
6426 {
6427 if (j.m_value.number_unsigned < 128)
6428 {
6429 // positive fixnum
6430 add_to_vector(v, 1, j.m_value.number_unsigned);
6431 }
6432 else if (j.m_value.number_unsigned <= UINT8_MAX)
6433 {
6434 // uint 8
6435 v.push_back(0xcc);
6436 add_to_vector(v, 1, j.m_value.number_unsigned);
6437 }
6438 else if (j.m_value.number_unsigned <= UINT16_MAX)
6439 {
6440 // uint 16
6441 v.push_back(0xcd);
6442 add_to_vector(v, 2, j.m_value.number_unsigned);
6443 }
6444 else if (j.m_value.number_unsigned <= UINT32_MAX)
6445 {
6446 // uint 32
6447 v.push_back(0xce);
6448 add_to_vector(v, 4, j.m_value.number_unsigned);
6449 }
6450 else if (j.m_value.number_unsigned <= UINT64_MAX)
6451 {
6452 // uint 64
6453 v.push_back(0xcf);
6454 add_to_vector(v, 8, j.m_value.number_unsigned);
6455 }
6456 break;
6457 }
6458
6459 case value_t::number_float:
6460 {
6461 // float 64
6462 v.push_back(0xcb);
6463 const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6464 for (size_t i = 0; i < 8; ++i)
6465 {
6466 v.push_back(helper[7 - i]);
6467 }
6468 break;
6469 }
6470
6471 case value_t::string:
6472 {
6473 const auto N = j.m_value.string->size();
6474 if (N <= 31)
6475 {
6476 // fixstr
6477 v.push_back(static_cast<uint8_t>(0xa0 | N));
6478 }
6479 else if (N <= 255)
6480 {
6481 // str 8
6482 v.push_back(0xd9);
6483 add_to_vector(v, 1, N);
6484 }
6485 else if (N <= 65535)
6486 {
6487 // str 16
6488 v.push_back(0xda);
6489 add_to_vector(v, 2, N);
6490 }
6491 else if (N <= 4294967295)
6492 {
6493 // str 32
6494 v.push_back(0xdb);
6495 add_to_vector(v, 4, N);
6496 }
6497
6498 // append string
6499 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6500 std::back_inserter(v));
6501 break;
6502 }
6503
6504 case value_t::array:
6505 {
6506 const auto N = j.m_value.array->size();
6507 if (N <= 15)
6508 {
6509 // fixarray
6510 v.push_back(static_cast<uint8_t>(0x90 | N));
6511 }
6512 else if (N <= 0xffff)
6513 {
6514 // array 16
6515 v.push_back(0xdc);
6516 add_to_vector(v, 2, N);
6517 }
6518 else if (N <= 0xffffffff)
6519 {
6520 // array 32
6521 v.push_back(0xdd);
6522 add_to_vector(v, 4, N);
6523 }
6524
6525 // append each element
6526 for (const auto& el : *j.m_value.array)
6527 {
6528 to_msgpack_internal(el, v);
6529 }
6530 break;
6531 }
6532
6533 case value_t::object:
6534 {
6535 const auto N = j.m_value.object->size();
6536 if (N <= 15)
6537 {
6538 // fixmap
6539 v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6540 }
6541 else if (N <= 65535)
6542 {
6543 // map 16
6544 v.push_back(0xde);
6545 add_to_vector(v, 2, N);
6546 }
6547 else if (N <= 4294967295)
6548 {
6549 // map 32
6550 v.push_back(0xdf);
6551 add_to_vector(v, 4, N);
6552 }
6553
6554 // append each element
6555 for (const auto& el : *j.m_value.object)
6556 {
6557 to_msgpack_internal(el.first, v);
6558 to_msgpack_internal(el.second, v);
6559 }
6560 break;
6561 }
6562
6563 default:
6564 {
6565 break;
6566 }
6567 }
6568 }
6569
6570 /*!
6571 @brief create a CBOR serialization of a given JSON value
6572
6573 This is a straightforward implementation of the CBOR specification.
6574
6575 @param[in] j JSON value to serialize
6576 @param[in,out] v byte vector to write the serialization to
6577
6578 @sa https://tools.ietf.org/html/rfc7049
6579 */
6580 static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
6581 {
6582 switch (j.type())
6583 {
6584 case value_t::null:
6585 {
6586 v.push_back(0xf6);
6587 break;
6588 }
6589
6590 case value_t::boolean:
6591 {
6592 v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6593 break;
6594 }
6595
6596 case value_t::number_integer:
6597 {
6598 if (j.m_value.number_integer >= 0)
6599 {
6600 // CBOR does not differentiate between positive signed
6601 // integers and unsigned integers. Therefore, we used the
6602 // code from the value_t::number_unsigned case here.
6603 if (j.m_value.number_integer <= 0x17)
6604 {
6605 add_to_vector(v, 1, j.m_value.number_integer);
6606 }
6607 else if (j.m_value.number_integer <= UINT8_MAX)
6608 {
6609 v.push_back(0x18);
6610 // one-byte uint8_t
6611 add_to_vector(v, 1, j.m_value.number_integer);
6612 }
6613 else if (j.m_value.number_integer <= UINT16_MAX)
6614 {
6615 v.push_back(0x19);
6616 // two-byte uint16_t
6617 add_to_vector(v, 2, j.m_value.number_integer);
6618 }
6619 else if (j.m_value.number_integer <= UINT32_MAX)
6620 {
6621 v.push_back(0x1a);
6622 // four-byte uint32_t
6623 add_to_vector(v, 4, j.m_value.number_integer);
6624 }
6625 else
6626 {
6627 v.push_back(0x1b);
6628 // eight-byte uint64_t
6629 add_to_vector(v, 8, j.m_value.number_integer);
6630 }
6631 }
6632 else
6633 {
6634 // The conversions below encode the sign in the first byte,
6635 // and the value is converted to a positive number.
6636 const auto positive_number = -1 - j.m_value.number_integer;
6637 if (j.m_value.number_integer >= -24)
6638 {
6639 v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6640 }
6641 else if (positive_number <= UINT8_MAX)
6642 {
6643 // int 8
6644 v.push_back(0x38);
6645 add_to_vector(v, 1, positive_number);
6646 }
6647 else if (positive_number <= UINT16_MAX)
6648 {
6649 // int 16
6650 v.push_back(0x39);
6651 add_to_vector(v, 2, positive_number);
6652 }
6653 else if (positive_number <= UINT32_MAX)
6654 {
6655 // int 32
6656 v.push_back(0x3a);
6657 add_to_vector(v, 4, positive_number);
6658 }
6659 else
6660 {
6661 // int 64
6662 v.push_back(0x3b);
6663 add_to_vector(v, 8, positive_number);
6664 }
6665 }
6666 break;
6667 }
6668
6669 case value_t::number_unsigned:
6670 {
6671 if (j.m_value.number_unsigned <= 0x17)
6672 {
6673 v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
6674 }
6675 else if (j.m_value.number_unsigned <= 0xff)
6676 {
6677 v.push_back(0x18);
6678 // one-byte uint8_t
6679 add_to_vector(v, 1, j.m_value.number_unsigned);
6680 }
6681 else if (j.m_value.number_unsigned <= 0xffff)
6682 {
6683 v.push_back(0x19);
6684 // two-byte uint16_t
6685 add_to_vector(v, 2, j.m_value.number_unsigned);
6686 }
6687 else if (j.m_value.number_unsigned <= 0xffffffff)
6688 {
6689 v.push_back(0x1a);
6690 // four-byte uint32_t
6691 add_to_vector(v, 4, j.m_value.number_unsigned);
6692 }
6693 else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
6694 {
6695 v.push_back(0x1b);
6696 // eight-byte uint64_t
6697 add_to_vector(v, 8, j.m_value.number_unsigned);
6698 }
6699 break;
6700 }
6701
6702 case value_t::number_float:
6703 {
6704 // Double-Precision Float
6705 v.push_back(0xfb);
6706 const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6707 for (size_t i = 0; i < 8; ++i)
6708 {
6709 v.push_back(helper[7 - i]);
6710 }
6711 break;
6712 }
6713
6714 case value_t::string:
6715 {
6716 const auto N = j.m_value.string->size();
6717 if (N <= 0x17)
6718 {
6719 v.push_back(0x60 + N); // 1 byte for string + size
6720 }
6721 else if (N <= 0xff)
6722 {
6723 v.push_back(0x78); // one-byte uint8_t for N
6724 add_to_vector(v, 1, N);
6725 }
6726 else if (N <= 0xffff)
6727 {
6728 v.push_back(0x79); // two-byte uint16_t for N
6729 add_to_vector(v, 2, N);
6730 }
6731 else if (N <= 0xffffffff)
6732 {
6733 v.push_back(0x7a); // four-byte uint32_t for N
6734 add_to_vector(v, 4, N);
6735 }
6736 // LCOV_EXCL_START
6737 else if (N <= 0xffffffffffffffff)
6738 {
6739 v.push_back(0x7b); // eight-byte uint64_t for N
6740 add_to_vector(v, 8, N);
6741 }
6742 // LCOV_EXCL_STOP
6743
6744 // append string
6745 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6746 std::back_inserter(v));
6747 break;
6748 }
6749
6750 case value_t::array:
6751 {
6752 const auto N = j.m_value.array->size();
6753 if (N <= 0x17)
6754 {
6755 v.push_back(0x80 + N); // 1 byte for array + size
6756 }
6757 else if (N <= 0xff)
6758 {
6759 v.push_back(0x98); // one-byte uint8_t for N
6760 add_to_vector(v, 1, N);
6761 }
6762 else if (N <= 0xffff)
6763 {
6764 v.push_back(0x99); // two-byte uint16_t for N
6765 add_to_vector(v, 2, N);
6766 }
6767 else if (N <= 0xffffffff)
6768 {
6769 v.push_back(0x9a); // four-byte uint32_t for N
6770 add_to_vector(v, 4, N);
6771 }
6772 // LCOV_EXCL_START
6773 else if (N <= 0xffffffffffffffff)
6774 {
6775 v.push_back(0x9b); // eight-byte uint64_t for N
6776 add_to_vector(v, 8, N);
6777 }
6778 // LCOV_EXCL_STOP
6779
6780 // append each element
6781 for (const auto& el : *j.m_value.array)
6782 {
6783 to_cbor_internal(el, v);
6784 }
6785 break;
6786 }
6787
6788 case value_t::object:
6789 {
6790 const auto N = j.m_value.object->size();
6791 if (N <= 0x17)
6792 {
6793 v.push_back(0xa0 + N); // 1 byte for object + size
6794 }
6795 else if (N <= 0xff)
6796 {
6797 v.push_back(0xb8);
6798 add_to_vector(v, 1, N); // one-byte uint8_t for N
6799 }
6800 else if (N <= 0xffff)
6801 {
6802 v.push_back(0xb9);
6803 add_to_vector(v, 2, N); // two-byte uint16_t for N
6804 }
6805 else if (N <= 0xffffffff)
6806 {
6807 v.push_back(0xba);
6808 add_to_vector(v, 4, N); // four-byte uint32_t for N
6809 }
6810 // LCOV_EXCL_START
6811 else if (N <= 0xffffffffffffffff)
6812 {
6813 v.push_back(0xbb);
6814 add_to_vector(v, 8, N); // eight-byte uint64_t for N
6815 }
6816 // LCOV_EXCL_STOP
6817
6818 // append each element
6819 for (const auto& el : *j.m_value.object)
6820 {
6821 to_cbor_internal(el.first, v);
6822 to_cbor_internal(el.second, v);
6823 }
6824 break;
6825 }
6826
6827 default:
6828 {
6829 break;
6830 }
6831 }
6832 }
6833
6834 /*!
6835 @brief create a JSON value from a given MessagePack vector
6836
6837 @param[in] v MessagePack serialization
6838 @param[in] idx byte index to start reading from @a v
6839
6840 @return deserialized JSON value
6841
6842 @throw std::invalid_argument if unsupported features from MessagePack were
6843 used in the given vector @a v or if the input is not valid MessagePack
6844 @throw std::out_of_range if the given vector ends prematurely
6845
6846 @sa https://github.com/msgpack/msgpack/blob/master/spec.md
6847 */
6848 static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
6849 {
6850 // store and increment index
6851 const size_t current_idx = idx++;
6852
6853 if (v[current_idx] <= 0xbf)
6854 {
6855 if (v[current_idx] <= 0x7f) // positive fixint
6856 {
6857 return v[current_idx];
6858 }
6859 else if (v[current_idx] <= 0x8f) // fixmap
6860 {
6861 basic_json result = value_t::object;
6862 const size_t len = v[current_idx] & 0x0f;
6863 for (size_t i = 0; i < len; ++i)
6864 {
6865 std::string key = from_msgpack_internal(v, idx);
6866 result[key] = from_msgpack_internal(v, idx);
6867 }
6868 return result;
6869 }
6870 else if (v[current_idx] <= 0x9f) // fixarray
6871 {
6872 basic_json result = value_t::array;
6873 const size_t len = v[current_idx] & 0x0f;
6874 for (size_t i = 0; i < len; ++i)
6875 {
6876 result.push_back(from_msgpack_internal(v, idx));
6877 }
6878 return result;
6879 }
6880 else // fixstr
6881 {
6882 const size_t len = v[current_idx] & 0x1f;
6883 const size_t offset = current_idx + 1;
6884 idx += len; // skip content bytes
6885 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6886 }
6887 }
6888 else if (v[current_idx] >= 0xe0) // negative fixint
6889 {
6890 return static_cast<int8_t>(v[current_idx]);
6891 }
6892 else
6893 {
6894 switch (v[current_idx])
6895 {
6896 case 0xc0: // nil
6897 {
6898 return value_t::null;
6899 }
6900
6901 case 0xc2: // false
6902 {
6903 return false;
6904 }
6905
6906 case 0xc3: // true
6907 {
6908 return true;
6909 }
6910
6911 case 0xca: // float 32
6912 {
6913 // copy bytes in reverse order into the double variable
6914 float res;
6915 for (size_t byte = 0; byte < sizeof(float); ++byte)
6916 {
6917 reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
6918 }
6919 idx += sizeof(float); // skip content bytes
6920 return res;
6921 }
6922
6923 case 0xcb: // float 64
6924 {
6925 // copy bytes in reverse order into the double variable
6926 double res;
6927 for (size_t byte = 0; byte < sizeof(double); ++byte)
6928 {
6929 reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
6930 }
6931 idx += sizeof(double); // skip content bytes
6932 return res;
6933 }
6934
6935 case 0xcc: // uint 8
6936 {
6937 idx += 1; // skip content byte
6938 return get_from_vector<uint8_t>(v, current_idx);
6939 }
6940
6941 case 0xcd: // uint 16
6942 {
6943 idx += 2; // skip 2 content bytes
6944 return get_from_vector<uint16_t>(v, current_idx);
6945 }
6946
6947 case 0xce: // uint 32
6948 {
6949 idx += 4; // skip 4 content bytes
6950 return get_from_vector<uint32_t>(v, current_idx);
6951 }
6952
6953 case 0xcf: // uint 64
6954 {
6955 idx += 8; // skip 8 content bytes
6956 return get_from_vector<uint64_t>(v, current_idx);
6957 }
6958
6959 case 0xd0: // int 8
6960 {
6961 idx += 1; // skip content byte
6962 return get_from_vector<int8_t>(v, current_idx);
6963 }
6964
6965 case 0xd1: // int 16
6966 {
6967 idx += 2; // skip 2 content bytes
6968 return get_from_vector<int16_t>(v, current_idx);
6969 }
6970
6971 case 0xd2: // int 32
6972 {
6973 idx += 4; // skip 4 content bytes
6974 return get_from_vector<int32_t>(v, current_idx);
6975 }
6976
6977 case 0xd3: // int 64
6978 {
6979 idx += 8; // skip 8 content bytes
6980 return get_from_vector<int64_t>(v, current_idx);
6981 }
6982
6983 case 0xd9: // str 8
6984 {
6985 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
6986 const size_t offset = current_idx + 2;
6987 idx += len + 1; // skip size byte + content bytes
6988 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6989 }
6990
6991 case 0xda: // str 16
6992 {
6993 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
6994 const size_t offset = current_idx + 3;
6995 idx += len + 2; // skip 2 size bytes + content bytes
6996 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6997 }
6998
6999 case 0xdb: // str 32
7000 {
7001 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7002 const size_t offset = current_idx + 5;
7003 idx += len + 4; // skip 4 size bytes + content bytes
7004 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7005 }
7006
7007 case 0xdc: // array 16
7008 {
7009 basic_json result = value_t::array;
7010 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7011 idx += 2; // skip 2 size bytes
7012 for (size_t i = 0; i < len; ++i)
7013 {
7014 result.push_back(from_msgpack_internal(v, idx));
7015 }
7016 return result;
7017 }
7018
7019 case 0xdd: // array 32
7020 {
7021 basic_json result = value_t::array;
7022 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7023 idx += 4; // skip 4 size bytes
7024 for (size_t i = 0; i < len; ++i)
7025 {
7026 result.push_back(from_msgpack_internal(v, idx));
7027 }
7028 return result;
7029 }
7030
7031 case 0xde: // map 16
7032 {
7033 basic_json result = value_t::object;
7034 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7035 idx += 2; // skip 2 size bytes
7036 for (size_t i = 0; i < len; ++i)
7037 {
7038 std::string key = from_msgpack_internal(v, idx);
7039 result[key] = from_msgpack_internal(v, idx);
7040 }
7041 return result;
7042 }
7043
7044 case 0xdf: // map 32
7045 {
7046 basic_json result = value_t::object;
7047 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7048 idx += 4; // skip 4 size bytes
7049 for (size_t i = 0; i < len; ++i)
7050 {
7051 std::string key = from_msgpack_internal(v, idx);
7052 result[key] = from_msgpack_internal(v, idx);
7053 }
7054 return result;
7055 }
7056
7057 default:
7058 {
7059 throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
7060 }
7061 }
7062 }
7063 }
7064
7065 /*!
7066 @brief create a JSON value from a given CBOR vector
7067
7068 @param[in] v CBOR serialization
7069 @param[in] idx byte index to start reading from @a v
7070
7071 @return deserialized JSON value
7072
7073 @throw std::invalid_argument if unsupported features from CBOR were used in
7074 the given vector @a v or if the input is not valid CBOR
7075 @throw std::out_of_range if the given vector ends prematurely
7076
7077 @sa https://tools.ietf.org/html/rfc7049
7078 */
7079 static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
7080 {
7081 // store and increment index
7082 const size_t current_idx = idx++;
7083
7084 switch (v[current_idx])
7085 {
7086 // Integer 0x00..0x17 (0..23)
7087 case 0x00:
7088 case 0x01:
7089 case 0x02:
7090 case 0x03:
7091 case 0x04:
7092 case 0x05:
7093 case 0x06:
7094 case 0x07:
7095 case 0x08:
7096 case 0x09:
7097 case 0x0a:
7098 case 0x0b:
7099 case 0x0c:
7100 case 0x0d:
7101 case 0x0e:
7102 case 0x0f:
7103 case 0x10:
7104 case 0x11:
7105 case 0x12:
7106 case 0x13:
7107 case 0x14:
7108 case 0x15:
7109 case 0x16:
7110 case 0x17:
7111 {
7112 return v[current_idx];
7113 }
7114
7115 case 0x18: // Unsigned integer (one-byte uint8_t follows)
7116 {
7117 idx += 1; // skip content byte
7118 return get_from_vector<uint8_t>(v, current_idx);
7119 }
7120
7121 case 0x19: // Unsigned integer (two-byte uint16_t follows)
7122 {
7123 idx += 2; // skip 2 content bytes
7124 return get_from_vector<uint16_t>(v, current_idx);
7125 }
7126
7127 case 0x1a: // Unsigned integer (four-byte uint32_t follows)
7128 {
7129 idx += 4; // skip 4 content bytes
7130 return get_from_vector<uint32_t>(v, current_idx);
7131 }
7132
7133 case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
7134 {
7135 idx += 8; // skip 8 content bytes
7136 return get_from_vector<uint64_t>(v, current_idx);
7137 }
7138
7139 // Negative integer -1-0x00..-1-0x17 (-1..-24)
7140 case 0x20:
7141 case 0x21:
7142 case 0x22:
7143 case 0x23:
7144 case 0x24:
7145 case 0x25:
7146 case 0x26:
7147 case 0x27:
7148 case 0x28:
7149 case 0x29:
7150 case 0x2a:
7151 case 0x2b:
7152 case 0x2c:
7153 case 0x2d:
7154 case 0x2e:
7155 case 0x2f:
7156 case 0x30:
7157 case 0x31:
7158 case 0x32:
7159 case 0x33:
7160 case 0x34:
7161 case 0x35:
7162 case 0x36:
7163 case 0x37:
7164 {
7165 return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
7166 }
7167
7168 case 0x38: // Negative integer (one-byte uint8_t follows)
7169 {
7170 idx += 1; // skip content byte
7171 // must be uint8_t !
7172 return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7173 }
7174
7175 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
7176 {
7177 idx += 2; // skip 2 content bytes
7178 return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7179 }
7180
7181 case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
7182 {
7183 idx += 4; // skip 4 content bytes
7184 return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7185 }
7186
7187 case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
7188 {
7189 idx += 8; // skip 8 content bytes
7190 return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7191 }
7192
7193 // UTF-8 string (0x00..0x17 bytes follow)
7194 case 0x60:
7195 case 0x61:
7196 case 0x62:
7197 case 0x63:
7198 case 0x64:
7199 case 0x65:
7200 case 0x66:
7201 case 0x67:
7202 case 0x68:
7203 case 0x69:
7204 case 0x6a:
7205 case 0x6b:
7206 case 0x6c:
7207 case 0x6d:
7208 case 0x6e:
7209 case 0x6f:
7210 case 0x70:
7211 case 0x71:
7212 case 0x72:
7213 case 0x73:
7214 case 0x74:
7215 case 0x75:
7216 case 0x76:
7217 case 0x77:
7218 {
7219 const auto len = static_cast<size_t>(v[current_idx] - 0x60);
7220 const size_t offset = current_idx + 1;
7221 idx += len; // skip content bytes
7222 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7223 }
7224
7225 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
7226 {
7227 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7228 const size_t offset = current_idx + 2;
7229 idx += len + 1; // skip size byte + content bytes
7230 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7231 }
7232
7233 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
7234 {
7235 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7236 const size_t offset = current_idx + 3;
7237 idx += len + 2; // skip 2 size bytes + content bytes
7238 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7239 }
7240
7241 case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
7242 {
7243 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7244 const size_t offset = current_idx + 5;
7245 idx += len + 4; // skip 4 size bytes + content bytes
7246 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7247 }
7248
7249 case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
7250 {
7251 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7252 const size_t offset = current_idx + 9;
7253 idx += len + 8; // skip 8 size bytes + content bytes
7254 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7255 }
7256
7257 case 0x7f: // UTF-8 string (indefinite length)
7258 {
7259 std::string result;
7260 while (v[idx] != 0xff)
7261 {
7262 string_t s = from_cbor_internal(v, idx);
7263 result += s;
7264 }
7265 // skip break byte (0xFF)
7266 idx += 1;
7267 return result;
7268 }
7269
7270 // array (0x00..0x17 data items follow)
7271 case 0x80:
7272 case 0x81:
7273 case 0x82:
7274 case 0x83:
7275 case 0x84:
7276 case 0x85:
7277 case 0x86:
7278 case 0x87:
7279 case 0x88:
7280 case 0x89:
7281 case 0x8a:
7282 case 0x8b:
7283 case 0x8c:
7284 case 0x8d:
7285 case 0x8e:
7286 case 0x8f:
7287 case 0x90:
7288 case 0x91:
7289 case 0x92:
7290 case 0x93:
7291 case 0x94:
7292 case 0x95:
7293 case 0x96:
7294 case 0x97:
7295 {
7296 basic_json result = value_t::array;
7297 const auto len = static_cast<size_t>(v[current_idx] - 0x80);
7298 for (size_t i = 0; i < len; ++i)
7299 {
7300 result.push_back(from_cbor_internal(v, idx));
7301 }
7302 return result;
7303 }
7304
7305 case 0x98: // array (one-byte uint8_t for n follows)
7306 {
7307 basic_json result = value_t::array;
7308 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7309 idx += 1; // skip 1 size byte
7310 for (size_t i = 0; i < len; ++i)
7311 {
7312 result.push_back(from_cbor_internal(v, idx));
7313 }
7314 return result;
7315 }
7316
7317 case 0x99: // array (two-byte uint16_t for n follow)
7318 {
7319 basic_json result = value_t::array;
7320 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7321 idx += 2; // skip 4 size bytes
7322 for (size_t i = 0; i < len; ++i)
7323 {
7324 result.push_back(from_cbor_internal(v, idx));
7325 }
7326 return result;
7327 }
7328
7329 case 0x9a: // array (four-byte uint32_t for n follow)
7330 {
7331 basic_json result = value_t::array;
7332 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7333 idx += 4; // skip 4 size bytes
7334 for (size_t i = 0; i < len; ++i)
7335 {
7336 result.push_back(from_cbor_internal(v, idx));
7337 }
7338 return result;
7339 }
7340
7341 case 0x9b: // array (eight-byte uint64_t for n follow)
7342 {
7343 basic_json result = value_t::array;
7344 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7345 idx += 8; // skip 8 size bytes
7346 for (size_t i = 0; i < len; ++i)
7347 {
7348 result.push_back(from_cbor_internal(v, idx));
7349 }
7350 return result;
7351 }
7352
7353 case 0x9f: // array (indefinite length)
7354 {
7355 basic_json result = value_t::array;
7356 while (v[idx] != 0xff)
7357 {
7358 result.push_back(from_cbor_internal(v, idx));
7359 }
7360 // skip break byte (0xFF)
7361 idx += 1;
7362 return result;
7363 }
7364
7365 // map (0x00..0x17 pairs of data items follow)
7366 case 0xa0:
7367 case 0xa1:
7368 case 0xa2:
7369 case 0xa3:
7370 case 0xa4:
7371 case 0xa5:
7372 case 0xa6:
7373 case 0xa7:
7374 case 0xa8:
7375 case 0xa9:
7376 case 0xaa:
7377 case 0xab:
7378 case 0xac:
7379 case 0xad:
7380 case 0xae:
7381 case 0xaf:
7382 case 0xb0:
7383 case 0xb1:
7384 case 0xb2:
7385 case 0xb3:
7386 case 0xb4:
7387 case 0xb5:
7388 case 0xb6:
7389 case 0xb7:
7390 {
7391 basic_json result = value_t::object;
7392 const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
7393 for (size_t i = 0; i < len; ++i)
7394 {
7395 std::string key = from_cbor_internal(v, idx);
7396 result[key] = from_cbor_internal(v, idx);
7397 }
7398 return result;
7399 }
7400
7401 case 0xb8: // map (one-byte uint8_t for n follows)
7402 {
7403 basic_json result = value_t::object;
7404 const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7405 idx += 1; // skip 1 size byte
7406 for (size_t i = 0; i < len; ++i)
7407 {
7408 std::string key = from_cbor_internal(v, idx);
7409 result[key] = from_cbor_internal(v, idx);
7410 }
7411 return result;
7412 }
7413
7414 case 0xb9: // map (two-byte uint16_t for n follow)
7415 {
7416 basic_json result = value_t::object;
7417 const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7418 idx += 2; // skip 2 size bytes
7419 for (size_t i = 0; i < len; ++i)
7420 {
7421 std::string key = from_cbor_internal(v, idx);
7422 result[key] = from_cbor_internal(v, idx);
7423 }
7424 return result;
7425 }
7426
7427 case 0xba: // map (four-byte uint32_t for n follow)
7428 {
7429 basic_json result = value_t::object;
7430 const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7431 idx += 4; // skip 4 size bytes
7432 for (size_t i = 0; i < len; ++i)
7433 {
7434 std::string key = from_cbor_internal(v, idx);
7435 result[key] = from_cbor_internal(v, idx);
7436 }
7437 return result;
7438 }
7439
7440 case 0xbb: // map (eight-byte uint64_t for n follow)
7441 {
7442 basic_json result = value_t::object;
7443 const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7444 idx += 8; // skip 8 size bytes
7445 for (size_t i = 0; i < len; ++i)
7446 {
7447 std::string key = from_cbor_internal(v, idx);
7448 result[key] = from_cbor_internal(v, idx);
7449 }
7450 return result;
7451 }
7452
7453 case 0xbf: // map (indefinite length)
7454 {
7455 basic_json result = value_t::object;
7456 while (v[idx] != 0xff)
7457 {
7458 std::string key = from_cbor_internal(v, idx);
7459 result[key] = from_cbor_internal(v, idx);
7460 }
7461 // skip break byte (0xFF)
7462 idx += 1;
7463 return result;
7464 }
7465
7466 case 0xf4: // false
7467 {
7468 return false;
7469 }
7470
7471 case 0xf5: // true
7472 {
7473 return true;
7474 }
7475
7476 case 0xf6: // null
7477 {
7478 return value_t::null;
7479 }
7480
7481 case 0xf9: // Half-Precision Float (two-byte IEEE 754)
7482 {
7483 idx += 2; // skip two content bytes
7484
7485 // code from RFC 7049, Appendix D, Figure 3:
7486 // As half-precision floating-point numbers were only added to
7487 // IEEE 754 in 2008, today's programming platforms often still
7488 // only have limited support for them. It is very easy to
7489 // include at least decoding support for them even without such
7490 // support. An example of a small decoder for half-precision
7491 // floating-point numbers in the C language is shown in Fig. 3.
7492 const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
7493 const int exp = (half >> 10) & 0x1f;
7494 const int mant = half & 0x3ff;
7495 double val;
7496 if (exp == 0)
7497 {
7498 val = std::ldexp(mant, -24);
7499 }
7500 else if (exp != 31)
7501 {
7502 val = std::ldexp(mant + 1024, exp - 25);
7503 }
7504 else
7505 {
7506 val = mant == 0 ? INFINITY : NAN;
7507 }
7508 return half & 0x8000 ? -val : val;
7509 }
7510
7511 case 0xfa: // Single-Precision Float (four-byte IEEE 754)
7512 {
7513 // copy bytes in reverse order into the float variable
7514 float res;
7515 for (size_t byte = 0; byte < sizeof(float); ++byte)
7516 {
7517 reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
7518 }
7519 idx += sizeof(float); // skip content bytes
7520 return res;
7521 }
7522
7523 case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
7524 {
7525 // copy bytes in reverse order into the double variable
7526 double res;
7527 for (size_t byte = 0; byte < sizeof(double); ++byte)
7528 {
7529 reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
7530 }
7531 idx += sizeof(double); // skip content bytes
7532 return res;
7533 }
7534
7535 default: // anything else (0xFF is handled inside the other types)
7536 {
7537 throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
7538 }
7539 }
7540 }
7541
7542 public:
7543 /*!
7544 @brief create a MessagePack serialization of a given JSON value
7545
7546 Serializes a given JSON value @a j to a byte vector using the MessagePack
7547 serialization format. MessagePack is a binary serialization format which
7548 aims to be more compact than JSON itself, yet more efficient to parse.
7549
7550 @param[in] j JSON value to serialize
7551 @return MessagePack serialization as byte vector
7552
7553 @complexity Linear in the size of the JSON value @a j.
7554
7555 @liveexample{The example shows the serialization of a JSON value to a byte
7556 vector in MessagePack format.,to_msgpack}
7557
7558 @sa http://msgpack.org
7559 @sa @ref from_msgpack(const std::vector<uint8_t>&) for the analogous
7560 deserialization
7561 @sa @ref to_cbor(const basic_json& for the related CBOR format
7562 */
7563 static std::vector<uint8_t> to_msgpack(const basic_json& j)
7564 {
7565 std::vector<uint8_t> result;
7566 to_msgpack_internal(j, result);
7567 return result;
7568 }
7569
7570 /*!
7571 @brief create a JSON value from a byte vector in MessagePack format
7572
7573 Deserializes a given byte vector @a v to a JSON value using the MessagePack
7574 serialization format.
7575
7576 @param[in] v a byte vector in MessagePack format
7577 @return deserialized JSON value
7578
7579 @throw std::invalid_argument if unsupported features from MessagePack were
7580 used in the given vector @a v or if the input is not valid MessagePack
7581 @throw std::out_of_range if the given vector ends prematurely
7582
7583 @complexity Linear in the size of the byte vector @a v.
7584
7585 @liveexample{The example shows the deserialization of a byte vector in
7586 MessagePack format to a JSON value.,from_msgpack}
7587
7588 @sa http://msgpack.org
7589 @sa @ref to_msgpack(const basic_json&) for the analogous serialization
7590 @sa @ref from_cbor(const std::vector<uint8_t>&) for the related CBOR format
7591 */
7592 static basic_json from_msgpack(const std::vector<uint8_t>& v)
7593 {
7594 size_t i = 0;
7595 return from_msgpack_internal(v, i);
7596 }
7597
7598 /*!
7599 @brief create a MessagePack serialization of a given JSON value
7600
7601 Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
7602 Binary Object Representation) serialization format. CBOR is a binary
7603 serialization format which aims to be more compact than JSON itself, yet
7604 more efficient to parse.
7605
7606 @param[in] j JSON value to serialize
7607 @return MessagePack serialization as byte vector
7608
7609 @complexity Linear in the size of the JSON value @a j.
7610
7611 @liveexample{The example shows the serialization of a JSON value to a byte
7612 vector in CBOR format.,to_cbor}
7613
7614 @sa http://cbor.io
7615 @sa @ref from_cbor(const std::vector<uint8_t>&) for the analogous
7616 deserialization
7617 @sa @ref to_msgpack(const basic_json& for the related MessagePack format
7618 */
7619 static std::vector<uint8_t> to_cbor(const basic_json& j)
7620 {
7621 std::vector<uint8_t> result;
7622 to_cbor_internal(j, result);
7623 return result;
7624 }
7625
7626 /*!
7627 @brief create a JSON value from a byte vector in CBOR format
7628
7629 Deserializes a given byte vector @a v to a JSON value using the CBOR
7630 (Concise Binary Object Representation) serialization format.
7631
7632 @param[in] v a byte vector in CBOR format
7633 @return deserialized JSON value
7634
7635 @throw std::invalid_argument if unsupported features from CBOR were used in
7636 the given vector @a v or if the input is not valid MessagePack
7637 @throw std::out_of_range if the given vector ends prematurely
7638
7639 @complexity Linear in the size of the byte vector @a v.
7640
7641 @liveexample{The example shows the deserialization of a byte vector in CBOR
7642 format to a JSON value.,from_cbor}
7643
7644 @sa http://cbor.io
7645 @sa @ref to_cbor(const basic_json&) for the analogous serialization
7646 @sa @ref from_msgpack(const std::vector<uint8_t>&) for the related
7647 MessagePack format
7648 */
7649 static basic_json from_cbor(const std::vector<uint8_t>& v)
7650 {
7651 size_t i = 0;
7652 return from_cbor_internal(v, i);
7653 }
7654
7655 /// @}
6145 7656
6146 private: 7657 private:
6147 /////////////////////////// 7658 ///////////////////////////
@@ -6694,10 +8205,10 @@ class basic_json
6694 8205
6695 public: 8206 public:
6696 /*! 8207 /*!
6697 @brief a const random access iterator for the @ref basic_json class 8208 @brief a template for a random access iterator for the @ref basic_json class
6698 8209
6699 This class implements a const iterator for the @ref basic_json class. From 8210 This class implements a both iterators (iterator and const_iterator) for the
6700 this class, the @ref iterator class is derived. 8211 @ref basic_json class.
6701 8212
6702 @note An iterator is called *initialized* when a pointer to a JSON value 8213 @note An iterator is called *initialized* when a pointer to a JSON value
6703 has been set (e.g., by a constructor or a copy assignment). If the 8214 has been set (e.g., by a constructor or a copy assignment). If the
@@ -6710,27 +8221,37 @@ class basic_json
6710 The iterator that can be moved to point (forward and backward) to any 8221 The iterator that can be moved to point (forward and backward) to any
6711 element in constant time. 8222 element in constant time.
6712 8223
6713 @since version 1.0.0 8224 @since version 1.0.0, simplified in version 2.0.9
6714 */ 8225 */
6715 class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json> 8226 template<typename U>
8227 class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
6716 { 8228 {
6717 /// allow basic_json to access private members 8229 /// allow basic_json to access private members
6718 friend class basic_json; 8230 friend class basic_json;
6719 8231
8232 // make sure U is basic_json or const basic_json
8233 static_assert(std::is_same<U, basic_json>::value
8234 or std::is_same<U, const basic_json>::value,
8235 "iter_impl only accepts (const) basic_json");
8236
6720 public: 8237 public:
6721 /// the type of the values when the iterator is dereferenced 8238 /// the type of the values when the iterator is dereferenced
6722 using value_type = typename basic_json::value_type; 8239 using value_type = typename basic_json::value_type;
6723 /// a type to represent differences between iterators 8240 /// a type to represent differences between iterators
6724 using difference_type = typename basic_json::difference_type; 8241 using difference_type = typename basic_json::difference_type;
6725 /// defines a pointer to the type iterated over (value_type) 8242 /// defines a pointer to the type iterated over (value_type)
6726 using pointer = typename basic_json::const_pointer; 8243 using pointer = typename std::conditional<std::is_const<U>::value,
8244 typename basic_json::const_pointer,
8245 typename basic_json::pointer>::type;
6727 /// defines a reference to the type iterated over (value_type) 8246 /// defines a reference to the type iterated over (value_type)
6728 using reference = typename basic_json::const_reference; 8247 using reference = typename std::conditional<std::is_const<U>::value,
8248 typename basic_json::const_reference,
8249 typename basic_json::reference>::type;
6729 /// the category of the iterator 8250 /// the category of the iterator
6730 using iterator_category = std::bidirectional_iterator_tag; 8251 using iterator_category = std::bidirectional_iterator_tag;
6731 8252
6732 /// default constructor 8253 /// default constructor
6733 const_iterator() = default; 8254 iter_impl() = default;
6734 8255
6735 /*! 8256 /*!
6736 @brief constructor for a given JSON instance 8257 @brief constructor for a given JSON instance
@@ -6738,7 +8259,7 @@ class basic_json
6738 @pre object != nullptr 8259 @pre object != nullptr
6739 @post The iterator is initialized; i.e. `m_object != nullptr`. 8260 @post The iterator is initialized; i.e. `m_object != nullptr`.
6740 */ 8261 */
6741 explicit const_iterator(pointer object) noexcept 8262 explicit iter_impl(pointer object) noexcept
6742 : m_object(object) 8263 : m_object(object)
6743 { 8264 {
6744 assert(m_object != nullptr); 8265 assert(m_object != nullptr);
@@ -6765,37 +8286,25 @@ class basic_json
6765 } 8286 }
6766 } 8287 }
6767 8288
6768 /*! 8289 /*
6769 @brief copy constructor given a non-const iterator 8290 Use operator `const_iterator` instead of `const_iterator(const iterator&
6770 @param[in] other iterator to copy from 8291 other) noexcept` to avoid two class definitions for @ref iterator and
6771 @note It is not checked whether @a other is initialized. 8292 @ref const_iterator.
8293
8294 This function is only called if this class is an @ref iterator. If this
8295 class is a @ref const_iterator this function is not called.
6772 */ 8296 */
6773 explicit const_iterator(const iterator& other) noexcept 8297 operator const_iterator() const
6774 : m_object(other.m_object)
6775 { 8298 {
6776 if (m_object != nullptr) 8299 const_iterator ret;
6777 {
6778 switch (m_object->m_type)
6779 {
6780 case basic_json::value_t::object:
6781 {
6782 m_it.object_iterator = other.m_it.object_iterator;
6783 break;
6784 }
6785 8300
6786 case basic_json::value_t::array: 8301 if (m_object)
6787 { 8302 {
6788 m_it.array_iterator = other.m_it.array_iterator; 8303 ret.m_object = m_object;
6789 break; 8304 ret.m_it = m_it;
6790 }
6791
6792 default:
6793 {
6794 m_it.primitive_iterator = other.m_it.primitive_iterator;
6795 break;
6796 }
6797 }
6798 } 8305 }
8306
8307 return ret;
6799 } 8308 }
6800 8309
6801 /*! 8310 /*!
@@ -6803,7 +8312,7 @@ class basic_json
6803 @param[in] other iterator to copy from 8312 @param[in] other iterator to copy from
6804 @note It is not checked whether @a other is initialized. 8313 @note It is not checked whether @a other is initialized.
6805 */ 8314 */
6806 const_iterator(const const_iterator& other) noexcept 8315 iter_impl(const iter_impl& other) noexcept
6807 : m_object(other.m_object), m_it(other.m_it) 8316 : m_object(other.m_object), m_it(other.m_it)
6808 {} 8317 {}
6809 8318
@@ -6812,7 +8321,7 @@ class basic_json
6812 @param[in,out] other iterator to copy from 8321 @param[in,out] other iterator to copy from
6813 @note It is not checked whether @a other is initialized. 8322 @note It is not checked whether @a other is initialized.
6814 */ 8323 */
6815 const_iterator& operator=(const_iterator other) noexcept( 8324 iter_impl& operator=(iter_impl other) noexcept(
6816 std::is_nothrow_move_constructible<pointer>::value and 8325 std::is_nothrow_move_constructible<pointer>::value and
6817 std::is_nothrow_move_assignable<pointer>::value and 8326 std::is_nothrow_move_assignable<pointer>::value and
6818 std::is_nothrow_move_constructible<internal_iterator>::value and 8327 std::is_nothrow_move_constructible<internal_iterator>::value and
@@ -6974,7 +8483,7 @@ class basic_json
6974 @brief post-increment (it++) 8483 @brief post-increment (it++)
6975 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8484 @pre The iterator is initialized; i.e. `m_object != nullptr`.
6976 */ 8485 */
6977 const_iterator operator++(int) 8486 iter_impl operator++(int)
6978 { 8487 {
6979 auto result = *this; 8488 auto result = *this;
6980 ++(*this); 8489 ++(*this);
@@ -6985,7 +8494,7 @@ class basic_json
6985 @brief pre-increment (++it) 8494 @brief pre-increment (++it)
6986 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8495 @pre The iterator is initialized; i.e. `m_object != nullptr`.
6987 */ 8496 */
6988 const_iterator& operator++() 8497 iter_impl& operator++()
6989 { 8498 {
6990 assert(m_object != nullptr); 8499 assert(m_object != nullptr);
6991 8500
@@ -7017,7 +8526,7 @@ class basic_json
7017 @brief post-decrement (it--) 8526 @brief post-decrement (it--)
7018 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8527 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7019 */ 8528 */
7020 const_iterator operator--(int) 8529 iter_impl operator--(int)
7021 { 8530 {
7022 auto result = *this; 8531 auto result = *this;
7023 --(*this); 8532 --(*this);
@@ -7028,7 +8537,7 @@ class basic_json
7028 @brief pre-decrement (--it) 8537 @brief pre-decrement (--it)
7029 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8538 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7030 */ 8539 */
7031 const_iterator& operator--() 8540 iter_impl& operator--()
7032 { 8541 {
7033 assert(m_object != nullptr); 8542 assert(m_object != nullptr);
7034 8543
@@ -7060,7 +8569,7 @@ class basic_json
7060 @brief comparison: equal 8569 @brief comparison: equal
7061 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8570 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7062 */ 8571 */
7063 bool operator==(const const_iterator& other) const 8572 bool operator==(const iter_impl& other) const
7064 { 8573 {
7065 // if objects are not the same, the comparison is undefined 8574 // if objects are not the same, the comparison is undefined
7066 if (m_object != other.m_object) 8575 if (m_object != other.m_object)
@@ -7093,7 +8602,7 @@ class basic_json
7093 @brief comparison: not equal 8602 @brief comparison: not equal
7094 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8603 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7095 */ 8604 */
7096 bool operator!=(const const_iterator& other) const 8605 bool operator!=(const iter_impl& other) const
7097 { 8606 {
7098 return not operator==(other); 8607 return not operator==(other);
7099 } 8608 }
@@ -7102,7 +8611,7 @@ class basic_json
7102 @brief comparison: smaller 8611 @brief comparison: smaller
7103 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8612 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7104 */ 8613 */
7105 bool operator<(const const_iterator& other) const 8614 bool operator<(const iter_impl& other) const
7106 { 8615 {
7107 // if objects are not the same, the comparison is undefined 8616 // if objects are not the same, the comparison is undefined
7108 if (m_object != other.m_object) 8617 if (m_object != other.m_object)
@@ -7135,7 +8644,7 @@ class basic_json
7135 @brief comparison: less than or equal 8644 @brief comparison: less than or equal
7136 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8645 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7137 */ 8646 */
7138 bool operator<=(const const_iterator& other) const 8647 bool operator<=(const iter_impl& other) const
7139 { 8648 {
7140 return not other.operator < (*this); 8649 return not other.operator < (*this);
7141 } 8650 }
@@ -7144,7 +8653,7 @@ class basic_json
7144 @brief comparison: greater than 8653 @brief comparison: greater than
7145 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8654 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7146 */ 8655 */
7147 bool operator>(const const_iterator& other) const 8656 bool operator>(const iter_impl& other) const
7148 { 8657 {
7149 return not operator<=(other); 8658 return not operator<=(other);
7150 } 8659 }
@@ -7153,7 +8662,7 @@ class basic_json
7153 @brief comparison: greater than or equal 8662 @brief comparison: greater than or equal
7154 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8663 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7155 */ 8664 */
7156 bool operator>=(const const_iterator& other) const 8665 bool operator>=(const iter_impl& other) const
7157 { 8666 {
7158 return not operator<(other); 8667 return not operator<(other);
7159 } 8668 }
@@ -7162,7 +8671,7 @@ class basic_json
7162 @brief add to iterator 8671 @brief add to iterator
7163 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8672 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7164 */ 8673 */
7165 const_iterator& operator+=(difference_type i) 8674 iter_impl& operator+=(difference_type i)
7166 { 8675 {
7167 assert(m_object != nullptr); 8676 assert(m_object != nullptr);
7168 8677
@@ -7193,7 +8702,7 @@ class basic_json
7193 @brief subtract from iterator 8702 @brief subtract from iterator
7194 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8703 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7195 */ 8704 */
7196 const_iterator& operator-=(difference_type i) 8705 iter_impl& operator-=(difference_type i)
7197 { 8706 {
7198 return operator+=(-i); 8707 return operator+=(-i);
7199 } 8708 }
@@ -7202,7 +8711,7 @@ class basic_json
7202 @brief add to iterator 8711 @brief add to iterator
7203 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8712 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7204 */ 8713 */
7205 const_iterator operator+(difference_type i) 8714 iter_impl operator+(difference_type i)
7206 { 8715 {
7207 auto result = *this; 8716 auto result = *this;
7208 result += i; 8717 result += i;
@@ -7213,7 +8722,7 @@ class basic_json
7213 @brief subtract from iterator 8722 @brief subtract from iterator
7214 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8723 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7215 */ 8724 */
7216 const_iterator operator-(difference_type i) 8725 iter_impl operator-(difference_type i)
7217 { 8726 {
7218 auto result = *this; 8727 auto result = *this;
7219 result -= i; 8728 result -= i;
@@ -7224,7 +8733,7 @@ class basic_json
7224 @brief return difference 8733 @brief return difference
7225 @pre The iterator is initialized; i.e. `m_object != nullptr`. 8734 @pre The iterator is initialized; i.e. `m_object != nullptr`.
7226 */ 8735 */
7227 difference_type operator-(const const_iterator& other) const 8736 difference_type operator-(const iter_impl& other) const
7228 { 8737 {
7229 assert(m_object != nullptr); 8738 assert(m_object != nullptr);
7230 8739
@@ -7321,141 +8830,6 @@ class basic_json
7321 }; 8830 };
7322 8831
7323 /*! 8832 /*!
7324 @brief a mutable random access iterator for the @ref basic_json class
7325
7326 @requirement The class satisfies the following concept requirements:
7327 - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
7328 The iterator that can be moved to point (forward and backward) to any
7329 element in constant time.
7330 - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
7331 It is possible to write to the pointed-to element.
7332
7333 @since version 1.0.0
7334 */
7335 class iterator : public const_iterator
7336 {
7337 public:
7338 using base_iterator = const_iterator;
7339 using pointer = typename basic_json::pointer;
7340 using reference = typename basic_json::reference;
7341
7342 /// default constructor
7343 iterator() = default;
7344
7345 /// constructor for a given JSON instance
7346 explicit iterator(pointer object) noexcept
7347 : base_iterator(object)
7348 {}
7349
7350 /// copy constructor
7351 iterator(const iterator& other) noexcept
7352 : base_iterator(other)
7353 {}
7354
7355 /// copy assignment
7356 iterator& operator=(iterator other) noexcept(
7357 std::is_nothrow_move_constructible<pointer>::value and
7358 std::is_nothrow_move_assignable<pointer>::value and
7359 std::is_nothrow_move_constructible<internal_iterator>::value and
7360 std::is_nothrow_move_assignable<internal_iterator>::value
7361 )
7362 {
7363 base_iterator::operator=(other);
7364 return *this;
7365 }
7366
7367 /// return a reference to the value pointed to by the iterator
7368 reference operator*() const
7369 {
7370 return const_cast<reference>(base_iterator::operator*());
7371 }
7372
7373 /// dereference the iterator
7374 pointer operator->() const
7375 {
7376 return const_cast<pointer>(base_iterator::operator->());
7377 }
7378
7379 /// post-increment (it++)
7380 iterator operator++(int)
7381 {
7382 iterator result = *this;
7383 base_iterator::operator++();
7384 return result;
7385 }
7386
7387 /// pre-increment (++it)
7388 iterator& operator++()
7389 {
7390 base_iterator::operator++();
7391 return *this;
7392 }
7393
7394 /// post-decrement (it--)
7395 iterator operator--(int)
7396 {
7397 iterator result = *this;
7398 base_iterator::operator--();
7399 return result;
7400 }
7401
7402 /// pre-decrement (--it)
7403 iterator& operator--()
7404 {
7405 base_iterator::operator--();
7406 return *this;
7407 }
7408
7409 /// add to iterator
7410 iterator& operator+=(difference_type i)
7411 {
7412 base_iterator::operator+=(i);
7413 return *this;
7414 }
7415
7416 /// subtract from iterator
7417 iterator& operator-=(difference_type i)
7418 {
7419 base_iterator::operator-=(i);
7420 return *this;
7421 }
7422
7423 /// add to iterator
7424 iterator operator+(difference_type i)
7425 {
7426 auto result = *this;
7427 result += i;
7428 return result;
7429 }
7430
7431 /// subtract from iterator
7432 iterator operator-(difference_type i)
7433 {
7434 auto result = *this;
7435 result -= i;
7436 return result;
7437 }
7438
7439 /// return difference
7440 difference_type operator-(const iterator& other) const
7441 {
7442 return base_iterator::operator-(other);
7443 }
7444
7445 /// access to successor
7446 reference operator[](difference_type n) const
7447 {
7448 return const_cast<reference>(base_iterator::operator[](n));
7449 }
7450
7451 /// return the value of an iterator
7452 reference value() const
7453 {
7454 return const_cast<reference>(base_iterator::value());
7455 }
7456 };
7457
7458 /*!
7459 @brief a template for a reverse iterator class 8833 @brief a template for a reverse iterator class
7460 8834
7461 @tparam Base the base iterator type to reverse. Valid types are @ref 8835 @tparam Base the base iterator type to reverse. Valid types are @ref
@@ -7618,6 +8992,12 @@ class basic_json
7618 explicit lexer(std::istream& s) 8992 explicit lexer(std::istream& s)
7619 : m_stream(&s), m_line_buffer() 8993 : m_stream(&s), m_line_buffer()
7620 { 8994 {
8995 // immediately abort if stream is erroneous
8996 if (s.fail())
8997 {
8998 throw std::invalid_argument("stream error: " + std::string(strerror(errno)));
8999 }
9000
7621 // fill buffer 9001 // fill buffer
7622 fill_line_buffer(); 9002 fill_line_buffer();
7623 9003
@@ -8740,8 +10120,22 @@ basic_json_parser_66:
8740 */ 10120 */
8741 void fill_line_buffer(size_t n = 0) 10121 void fill_line_buffer(size_t n = 0)
8742 { 10122 {
10123 // if line buffer is used, m_content points to its data
10124 assert(m_line_buffer.empty()
10125 or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));
10126
10127 // if line buffer is used, m_limit is set past the end of its data
10128 assert(m_line_buffer.empty()
10129 or m_limit == m_content + m_line_buffer.size());
10130
10131 // pointer relationships
10132 assert(m_content <= m_start);
10133 assert(m_start <= m_cursor);
10134 assert(m_cursor <= m_limit);
10135 assert(m_marker == nullptr or m_marker <= m_limit);
10136
8743 // number of processed characters (p) 10137 // number of processed characters (p)
8744 const auto offset_start = m_start - m_content; 10138 const size_t num_processed_chars = static_cast<size_t>(m_start - m_content);
8745 // offset for m_marker wrt. to m_start 10139 // offset for m_marker wrt. to m_start
8746 const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start; 10140 const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
8747 // number of unprocessed characters (u) 10141 // number of unprocessed characters (u)
@@ -8750,35 +10144,34 @@ basic_json_parser_66:
8750 // no stream is used or end of file is reached 10144 // no stream is used or end of file is reached
8751 if (m_stream == nullptr or m_stream->eof()) 10145 if (m_stream == nullptr or m_stream->eof())
8752 { 10146 {
8753 // skip this part if we are already using the line buffer 10147 // m_start may or may not be pointing into m_line_buffer at
8754 if (m_start != reinterpret_cast<const lexer_char_t*>(m_line_buffer.data())) 10148 // this point. We trust the standand library to do the right
8755 { 10149 // thing. See http://stackoverflow.com/q/28142011/266378
8756 // copy unprocessed characters to line buffer 10150 m_line_buffer.assign(m_start, m_limit);
8757 m_line_buffer.clear();
8758 for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
8759 {
8760 m_line_buffer.append(1, static_cast<const char>(*m_cursor));
8761 }
8762 }
8763 10151
8764 // append n characters to make sure that there is sufficient 10152 // append n characters to make sure that there is sufficient
8765 // space between m_cursor and m_limit 10153 // space between m_cursor and m_limit
8766 m_line_buffer.append(1, '\x00'); 10154 m_line_buffer.append(1, '\x00');
8767 m_line_buffer.append(n - 1, '\x01'); 10155 if (n > 0)
10156 {
10157 m_line_buffer.append(n - 1, '\x01');
10158 }
8768 } 10159 }
8769 else 10160 else
8770 { 10161 {
8771 // delete processed characters from line buffer 10162 // delete processed characters from line buffer
8772 m_line_buffer.erase(0, static_cast<size_t>(offset_start)); 10163 m_line_buffer.erase(0, num_processed_chars);
8773 // read next line from input stream 10164 // read next line from input stream
8774 std::string line; 10165 m_line_buffer_tmp.clear();
8775 std::getline(*m_stream, line, '\n'); 10166 std::getline(*m_stream, m_line_buffer_tmp, '\n');
10167
8776 // add line with newline symbol to the line buffer 10168 // add line with newline symbol to the line buffer
8777 m_line_buffer += line + "\n"; 10169 m_line_buffer += m_line_buffer_tmp;
10170 m_line_buffer.push_back('\n');
8778 } 10171 }
8779 10172
8780 // set pointers 10173 // set pointers
8781 m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.c_str()); 10174 m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());
8782 assert(m_content != nullptr); 10175 assert(m_content != nullptr);
8783 m_start = m_content; 10176 m_start = m_content;
8784 m_marker = m_start + offset_marker; 10177 m_marker = m_start + offset_marker;
@@ -8861,9 +10254,20 @@ basic_json_parser_66:
8861 // iterate the result between the quotes 10254 // iterate the result between the quotes
8862 for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i) 10255 for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8863 { 10256 {
8864 // process escaped characters 10257 // find next escape character
8865 if (*i == '\\') 10258 auto e = std::find(i, m_cursor - 1, '\\');
10259 if (e != i)
10260 {
10261 // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705
10262 for (auto k = i; k < e; k++)
10263 {
10264 result.push_back(static_cast<typename string_t::value_type>(*k));
10265 }
10266 i = e - 1; // -1 because of ++i
10267 }
10268 else
8866 { 10269 {
10270 // processing escaped character
8867 // read next character 10271 // read next character
8868 ++i; 10272 ++i;
8869 10273
@@ -8950,12 +10354,6 @@ basic_json_parser_66:
8950 } 10354 }
8951 } 10355 }
8952 } 10356 }
8953 else
8954 {
8955 // all other characters are just copied to the end of the
8956 // string
8957 result.append(1, static_cast<typename string_t::value_type>(*i));
8958 }
8959 } 10357 }
8960 10358
8961 return result; 10359 return result;
@@ -8969,8 +10367,6 @@ basic_json_parser_66:
8969 supplied via the first parameter. Set this to @a 10367 supplied via the first parameter. Set this to @a
8970 static_cast<number_float_t*>(nullptr). 10368 static_cast<number_float_t*>(nullptr).
8971 10369
8972 @param[in] type the @ref number_float_t in use
8973
8974 @param[in,out] endptr recieves a pointer to the first character after 10370 @param[in,out] endptr recieves a pointer to the first character after
8975 the number 10371 the number
8976 10372
@@ -8989,8 +10385,6 @@ basic_json_parser_66:
8989 supplied via the first parameter. Set this to @a 10385 supplied via the first parameter. Set this to @a
8990 static_cast<number_float_t*>(nullptr). 10386 static_cast<number_float_t*>(nullptr).
8991 10387
8992 @param[in] type the @ref number_float_t in use
8993
8994 @param[in,out] endptr recieves a pointer to the first character after 10388 @param[in,out] endptr recieves a pointer to the first character after
8995 the number 10389 the number
8996 10390
@@ -9009,8 +10403,6 @@ basic_json_parser_66:
9009 supplied via the first parameter. Set this to @a 10403 supplied via the first parameter. Set this to @a
9010 static_cast<number_float_t*>(nullptr). 10404 static_cast<number_float_t*>(nullptr).
9011 10405
9012 @param[in] type the @ref number_float_t in use
9013
9014 @param[in,out] endptr recieves a pointer to the first character after 10406 @param[in,out] endptr recieves a pointer to the first character after
9015 the number 10407 the number
9016 10408
@@ -9091,19 +10483,19 @@ basic_json_parser_66:
9091 // skip if definitely not an integer 10483 // skip if definitely not an integer
9092 if (type != value_t::number_float) 10484 if (type != value_t::number_float)
9093 { 10485 {
9094 // multiply last value by ten and add the new digit 10486 auto digit = static_cast<number_unsigned_t>(*curptr - '0');
9095 auto temp = value * 10 + *curptr - '0';
9096 10487
9097 // test for overflow 10488 // overflow if value * 10 + digit > max, move terms around
9098 if (temp < value || temp > max) 10489 // to avoid overflow in intermediate values
10490 if (value > (max - digit) / 10)
9099 { 10491 {
9100 // overflow 10492 // overflow
9101 type = value_t::number_float; 10493 type = value_t::number_float;
9102 } 10494 }
9103 else 10495 else
9104 { 10496 {
9105 // no overflow - save it 10497 // no overflow
9106 value = temp; 10498 value = value * 10 + digit;
9107 } 10499 }
9108 } 10500 }
9109 } 10501 }
@@ -9115,7 +10507,22 @@ basic_json_parser_66:
9115 } 10507 }
9116 else if (type == value_t::number_integer) 10508 else if (type == value_t::number_integer)
9117 { 10509 {
9118 result.m_value.number_integer = -static_cast<number_integer_t>(value); 10510 // invariant: if we parsed a '-', the absolute value is between
10511 // 0 (we allow -0) and max == -INT64_MIN
10512 assert(value >= 0);
10513 assert(value <= max);
10514
10515 if (value == max)
10516 {
10517 // we cannot simply negate value (== max == -INT64_MIN),
10518 // see https://github.com/nlohmann/json/issues/389
10519 result.m_value.number_integer = static_cast<number_integer_t>(INT64_MIN);
10520 }
10521 else
10522 {
10523 // all other values can be negated safely
10524 result.m_value.number_integer = -static_cast<number_integer_t>(value);
10525 }
9119 } 10526 }
9120 else 10527 else
9121 { 10528 {
@@ -9139,6 +10546,8 @@ basic_json_parser_66:
9139 std::istream* m_stream = nullptr; 10546 std::istream* m_stream = nullptr;
9140 /// line buffer buffer for m_stream 10547 /// line buffer buffer for m_stream
9141 string_t m_line_buffer {}; 10548 string_t m_line_buffer {};
10549 /// used for filling m_line_buffer
10550 string_t m_line_buffer_tmp {};
9142 /// the buffer pointer 10551 /// the buffer pointer
9143 const lexer_char_t* m_content = nullptr; 10552 const lexer_char_t* m_content = nullptr;
9144 /// pointer to the beginning of the current symbol 10553 /// pointer to the beginning of the current symbol
@@ -9164,7 +10573,7 @@ basic_json_parser_66:
9164 /// a parser reading from a string literal 10573 /// a parser reading from a string literal
9165 parser(const char* buff, const parser_callback_t cb = nullptr) 10574 parser(const char* buff, const parser_callback_t cb = nullptr)
9166 : callback(cb), 10575 : callback(cb),
9167 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff)) 10576 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
9168 {} 10577 {}
9169 10578
9170 /// a parser reading from an input stream 10579 /// a parser reading from an input stream
@@ -9896,13 +11305,11 @@ basic_json_parser_66:
9896 /*! 11305 /*!
9897 @brief replace all occurrences of a substring by another string 11306 @brief replace all occurrences of a substring by another string
9898 11307
9899 @param[in,out] s the string to manipulate 11308 @param[in,out] s the string to manipulate; changed so that all
11309 occurrences of @a f are replaced with @a t
9900 @param[in] f the substring to replace with @a t 11310 @param[in] f the substring to replace with @a t
9901 @param[in] t the string to replace @a f 11311 @param[in] t the string to replace @a f
9902 11312
9903 @return The string @a s where all occurrences of @a f are replaced
9904 with @a t.
9905
9906 @pre The search string @a f must not be empty. 11313 @pre The search string @a f must not be empty.
9907 11314
9908 @since version 2.0.0 11315 @since version 2.0.0