json.hpp
Go to the documentation of this file.
00001 /*
00002     __ _____ _____ _____
00003  __|  |   __|     |   | |  JSON for Modern C++
00004 |  |  |__   |  |  | | | |  version 2.0.0
00005 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
00006 
00007 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
00008 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
00009 
00010 Permission is hereby  granted, free of charge, to any  person obtaining a copy
00011 of this software and associated  documentation files (the "Software"), to deal
00012 in the Software  without restriction, including without  limitation the rights
00013 to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
00014 copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
00015 furnished to do so, subject to the following conditions:
00016 
00017 The above copyright notice and this permission notice shall be included in all
00018 copies or substantial portions of the Software.
00019 
00020 THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
00021 IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
00022 FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
00023 AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
00024 LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00025 OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
00026 SOFTWARE.
00027 */
00028 
00029 #ifndef NLOHMANN_JSON_HPP
00030 #define NLOHMANN_JSON_HPP
00031 
00032 #include <algorithm>
00033 #include <array>
00034 #include <cassert>
00035 #include <cerrno>
00036 #include <ciso646>
00037 #include <cmath>
00038 #include <cstddef>
00039 #include <cstdio>
00040 #include <cstdlib>
00041 #include <functional>
00042 #include <initializer_list>
00043 #include <iomanip>
00044 #include <iostream>
00045 #include <iterator>
00046 #include <limits>
00047 #include <map>
00048 #include <memory>
00049 #include <sstream>
00050 #include <stdexcept>
00051 #include <string>
00052 #include <type_traits>
00053 #include <utility>
00054 #include <vector>
00055 
00056 // disable float-equal warnings on GCC/clang
00057 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
00058     #pragma GCC diagnostic push
00059     #pragma GCC diagnostic ignored "-Wfloat-equal"
00060 #endif
00061 
00067 namespace nlohmann
00068 {
00069 
00070 
00075 namespace
00076 {
00081 template<typename T>
00082 struct has_mapped_type
00083 {
00084   private:
00085     template<typename C> static char test(typename C::mapped_type*);
00086     template<typename C> static char (&test(...))[2];
00087   public:
00088     static constexpr bool value = sizeof(test<T>(0)) == 1;
00089 };
00090 
00095 class DecimalSeparator : public std::numpunct<char>
00096 {
00097   protected:
00098     char do_decimal_point() const
00099     {
00100         return '.';
00101     }
00102 };
00103 
00104 }
00105 
00177 template <
00178     template<typename U, typename V, typename... Args> class ObjectType = std::map,
00179     template<typename U, typename... Args> class ArrayType = std::vector,
00180     class StringType = std::string,
00181     class BooleanType = bool,
00182     class NumberIntegerType = std::int64_t,
00183     class NumberUnsignedType = std::uint64_t,
00184     class NumberFloatType = double,
00185     template<typename U> class AllocatorType = std::allocator
00186     >
00187 class basic_json
00188 {
00189   private:
00191     using basic_json_t = basic_json<ObjectType,
00192           ArrayType,
00193           StringType,
00194           BooleanType,
00195           NumberIntegerType,
00196           NumberUnsignedType,
00197           NumberFloatType,
00198           AllocatorType>;
00199 
00200   public:
00201     // forward declarations
00202     template<typename Base> class json_reverse_iterator;
00203     class json_pointer;
00204 
00206     // container types //
00208 
00211 
00213     using value_type = basic_json;
00214 
00216     using reference = value_type&;
00218     using const_reference = const value_type&;
00219 
00221     using difference_type = std::ptrdiff_t;
00223     using size_type = std::size_t;
00224 
00226     using allocator_type = AllocatorType<basic_json>;
00227 
00229     using pointer = typename std::allocator_traits<allocator_type>::pointer;
00231     using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
00232 
00234     class iterator;
00236     class const_iterator;
00238     using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
00240     using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
00241 
00243 
00244 
00248     static allocator_type get_allocator()
00249     {
00250         return allocator_type();
00251     }
00252 
00253 
00255     // JSON value data types //
00257 
00260 
00344     using object_t = ObjectType<StringType,
00345           basic_json,
00346           std::less<StringType>,
00347           AllocatorType<std::pair<const StringType,
00348           basic_json>>>;
00349 
00394     using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
00395 
00441     using string_t = StringType;
00442 
00467     using boolean_t = BooleanType;
00468 
00539     using number_integer_t = NumberIntegerType;
00540 
00611     using number_unsigned_t = NumberUnsignedType;
00612 
00679     using number_float_t = NumberFloatType;
00680 
00682 
00683 
00685     // JSON type enumeration //
00687 
00698     enum class value_t : uint8_t
00699     {
00700         null,            
00701         object,          
00702         array,           
00703         string,          
00704         boolean,         
00705         number_integer,  
00706         number_unsigned, 
00707         number_float,    
00708         discarded        
00709     };
00710 
00711 
00712   private:
00713 
00715     template<typename T, typename... Args>
00716     static T* create(Args&& ... args)
00717     {
00718         AllocatorType<T> alloc;
00719         auto deleter = [&](T * object)
00720         {
00721             alloc.deallocate(object, 1);
00722         };
00723         std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
00724         alloc.construct(object.get(), std::forward<Args>(args)...);
00725         return object.release();
00726     }
00727 
00729     // JSON value storage //
00731 
00739     union json_value
00740     {
00742         object_t* object;
00744         array_t* array;
00746         string_t* string;
00748         boolean_t boolean;
00750         number_integer_t number_integer;
00752         number_unsigned_t number_unsigned;
00754         number_float_t number_float;
00755 
00757         json_value() = default;
00759         json_value(boolean_t v) noexcept : boolean(v) {}
00761         json_value(number_integer_t v) noexcept : number_integer(v) {}
00763         json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
00765         json_value(number_float_t v) noexcept : number_float(v) {}
00767         json_value(value_t t)
00768         {
00769             switch (t)
00770             {
00771                 case value_t::object:
00772                 {
00773                     object = create<object_t>();
00774                     break;
00775                 }
00776 
00777                 case value_t::array:
00778                 {
00779                     array = create<array_t>();
00780                     break;
00781                 }
00782 
00783                 case value_t::string:
00784                 {
00785                     string = create<string_t>("");
00786                     break;
00787                 }
00788 
00789                 case value_t::boolean:
00790                 {
00791                     boolean = boolean_t(false);
00792                     break;
00793                 }
00794 
00795                 case value_t::number_integer:
00796                 {
00797                     number_integer = number_integer_t(0);
00798                     break;
00799                 }
00800 
00801                 case value_t::number_unsigned:
00802                 {
00803                     number_unsigned = number_unsigned_t(0);
00804                     break;
00805                 }
00806 
00807                 case value_t::number_float:
00808                 {
00809                     number_float = number_float_t(0.0);
00810                     break;
00811                 }
00812 
00813                 default:
00814                 {
00815                     break;
00816                 }
00817             }
00818         }
00819 
00821         json_value(const string_t& value)
00822         {
00823             string = create<string_t>(value);
00824         }
00825 
00827         json_value(const object_t& value)
00828         {
00829             object = create<object_t>(value);
00830         }
00831 
00833         json_value(const array_t& value)
00834         {
00835             array = create<array_t>(value);
00836         }
00837     };
00838 
00839 
00840   public:
00842     // JSON parser callback //
00844 
00853     enum class parse_event_t : uint8_t
00854     {
00856         object_start,
00858         object_end,
00860         array_start,
00862         array_end,
00864         key,
00866         value
00867     };
00868 
00918     using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
00919 
00920 
00922     // constructors //
00924 
00927 
00967     basic_json(const value_t value_type)
00968         : m_type(value_type), m_value(value_type)
00969     {}
00970 
00995     basic_json() = default;
00996 
01019     basic_json(std::nullptr_t) noexcept
01020         : basic_json(value_t::null)
01021     {}
01022 
01042     basic_json(const object_t& val)
01043         : m_type(value_t::object), m_value(val)
01044     {}
01045 
01072     template <class CompatibleObjectType, typename
01073               std::enable_if<
01074                   std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
01075                   std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
01076               = 0>
01077     basic_json(const CompatibleObjectType& val)
01078         : m_type(value_t::object)
01079     {
01080         using std::begin;
01081         using std::end;
01082         m_value.object = create<object_t>(begin(val), end(val));
01083     }
01084 
01104     basic_json(const array_t& val)
01105         : m_type(value_t::array), m_value(val)
01106     {}
01107 
01134     template <class CompatibleArrayType, typename
01135               std::enable_if<
01136                   not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
01137                   not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
01138                   not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
01139                   not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
01140                   not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
01141                   not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
01142                   std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
01143               = 0>
01144     basic_json(const CompatibleArrayType& val)
01145         : m_type(value_t::array)
01146     {
01147         using std::begin;
01148         using std::end;
01149         m_value.array = create<array_t>(begin(val), end(val));
01150     }
01151 
01173     basic_json(const string_t& val)
01174         : m_type(value_t::string), m_value(val)
01175     {}
01176 
01197     basic_json(const typename string_t::value_type* val)
01198         : basic_json(string_t(val))
01199     {}
01200 
01224     template <class CompatibleStringType, typename
01225               std::enable_if<
01226                   std::is_constructible<string_t, CompatibleStringType>::value, int>::type
01227               = 0>
01228     basic_json(const CompatibleStringType& val)
01229         : basic_json(string_t(val))
01230     {}
01231 
01246     basic_json(boolean_t val) noexcept
01247         : m_type(value_t::boolean), m_value(val)
01248     {}
01249 
01273     template<typename T,
01274              typename std::enable_if<
01275                  not (std::is_same<T, int>::value)
01276                  and std::is_same<T, number_integer_t>::value
01277                  , int>::type
01278              = 0>
01279     basic_json(const number_integer_t val) noexcept
01280         : m_type(value_t::number_integer), m_value(val)
01281     {}
01282 
01308     basic_json(const int val) noexcept
01309         : m_type(value_t::number_integer),
01310           m_value(static_cast<number_integer_t>(val))
01311     {}
01312 
01338     template<typename CompatibleNumberIntegerType, typename
01339              std::enable_if<
01340                  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
01341                  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
01342                  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
01343                  CompatibleNumberIntegerType>::type
01344              = 0>
01345     basic_json(const CompatibleNumberIntegerType val) noexcept
01346         : m_type(value_t::number_integer),
01347           m_value(static_cast<number_integer_t>(val))
01348     {}
01349 
01367     template<typename T,
01368              typename std::enable_if<
01369                  not (std::is_same<T, int>::value)
01370                  and std::is_same<T, number_unsigned_t>::value
01371                  , int>::type
01372              = 0>
01373     basic_json(const number_unsigned_t val) noexcept
01374         : m_type(value_t::number_unsigned), m_value(val)
01375     {}
01376 
01397     template <typename CompatibleNumberUnsignedType, typename
01398               std::enable_if <
01399                   std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
01400                   std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
01401                   not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
01402                   CompatibleNumberUnsignedType>::type
01403               = 0>
01404     basic_json(const CompatibleNumberUnsignedType val) noexcept
01405         : m_type(value_t::number_unsigned),
01406           m_value(static_cast<number_unsigned_t>(val))
01407     {}
01408 
01433     basic_json(const number_float_t val) noexcept
01434         : m_type(value_t::number_float), m_value(val)
01435     {
01436         // replace infinity and NAN by null
01437         if (not std::isfinite(val))
01438         {
01439             m_type = value_t::null;
01440             m_value = json_value();
01441         }
01442     }
01443 
01475     template<typename CompatibleNumberFloatType, typename = typename
01476              std::enable_if<
01477                  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
01478                  std::is_floating_point<CompatibleNumberFloatType>::value>::type
01479              >
01480     basic_json(const CompatibleNumberFloatType val) noexcept
01481         : basic_json(number_float_t(val))
01482     {}
01483 
01553     basic_json(std::initializer_list<basic_json> init,
01554                bool type_deduction = true,
01555                value_t manual_type = value_t::array)
01556     {
01557         // the initializer list could describe an object
01558         bool is_an_object = true;
01559 
01560         // check if each element is an array with two elements whose first
01561         // element is a string
01562         for (const auto& element : init)
01563         {
01564             if (not element.is_array() or element.size() != 2
01565                     or not element[0].is_string())
01566             {
01567                 // we found an element that makes it impossible to use the
01568                 // initializer list as object
01569                 is_an_object = false;
01570                 break;
01571             }
01572         }
01573 
01574         // adjust type if type deduction is not wanted
01575         if (not type_deduction)
01576         {
01577             // if array is wanted, do not create an object though possible
01578             if (manual_type == value_t::array)
01579             {
01580                 is_an_object = false;
01581             }
01582 
01583             // if object is wanted but impossible, throw an exception
01584             if (manual_type == value_t::object and not is_an_object)
01585             {
01586                 throw std::domain_error("cannot create object from initializer list");
01587             }
01588         }
01589 
01590         if (is_an_object)
01591         {
01592             // the initializer list is a list of pairs -> create object
01593             m_type = value_t::object;
01594             m_value = value_t::object;
01595 
01596             assert(m_value.object != nullptr);
01597 
01598             for (auto& element : init)
01599             {
01600                 m_value.object->emplace(*(element[0].m_value.string), element[1]);
01601             }
01602         }
01603         else
01604         {
01605             // the initializer list describes an array -> create array
01606             m_type = value_t::array;
01607             m_value.array = create<array_t>(init);
01608         }
01609     }
01610 
01645     static basic_json array(std::initializer_list<basic_json> init =
01646                                 std::initializer_list<basic_json>())
01647     {
01648         return basic_json(init, false, value_t::array);
01649     }
01650 
01685     static basic_json object(std::initializer_list<basic_json> init =
01686                                  std::initializer_list<basic_json>())
01687     {
01688         return basic_json(init, false, value_t::object);
01689     }
01690 
01709     basic_json(size_type cnt, const basic_json& val)
01710         : m_type(value_t::array)
01711     {
01712         m_value.array = create<array_t>(cnt, val);
01713     }
01714 
01749     template <class InputIT, typename
01750               std::enable_if<
01751                   std::is_same<InputIT, typename basic_json_t::iterator>::value or
01752                   std::is_same<InputIT, typename basic_json_t::const_iterator>::value
01753                   , int>::type
01754               = 0>
01755     basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
01756     {
01757         // make sure iterator fits the current value
01758         if (first.m_object != last.m_object)
01759         {
01760             throw std::domain_error("iterators are not compatible");
01761         }
01762 
01763         // check if iterator range is complete for primitive values
01764         switch (m_type)
01765         {
01766             case value_t::boolean:
01767             case value_t::number_float:
01768             case value_t::number_integer:
01769             case value_t::number_unsigned:
01770             case value_t::string:
01771             {
01772                 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
01773                 {
01774                     throw std::out_of_range("iterators out of range");
01775                 }
01776                 break;
01777             }
01778 
01779             default:
01780             {
01781                 break;
01782             }
01783         }
01784 
01785         switch (m_type)
01786         {
01787             case value_t::number_integer:
01788             {
01789                 assert(first.m_object != nullptr);
01790                 m_value.number_integer = first.m_object->m_value.number_integer;
01791                 break;
01792             }
01793 
01794             case value_t::number_unsigned:
01795             {
01796                 assert(first.m_object != nullptr);
01797                 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
01798                 break;
01799             }
01800 
01801             case value_t::number_float:
01802             {
01803                 assert(first.m_object != nullptr);
01804                 m_value.number_float = first.m_object->m_value.number_float;
01805                 break;
01806             }
01807 
01808             case value_t::boolean:
01809             {
01810                 assert(first.m_object != nullptr);
01811                 m_value.boolean = first.m_object->m_value.boolean;
01812                 break;
01813             }
01814 
01815             case value_t::string:
01816             {
01817                 assert(first.m_object != nullptr);
01818                 m_value = *first.m_object->m_value.string;
01819                 break;
01820             }
01821 
01822             case value_t::object:
01823             {
01824                 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
01825                 break;
01826             }
01827 
01828             case value_t::array:
01829             {
01830                 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
01831                 break;
01832             }
01833 
01834             default:
01835             {
01836                 assert(first.m_object != nullptr);
01837                 throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
01838             }
01839         }
01840     }
01841 
01862     explicit basic_json(std::istream& i, parser_callback_t cb = nullptr)
01863     {
01864         *this = parser(i, cb).parse();
01865     }
01866 
01868     // other constructors and destructor //
01870 
01893     basic_json(const basic_json& other)
01894         : m_type(other.m_type)
01895     {
01896         switch (m_type)
01897         {
01898             case value_t::object:
01899             {
01900                 assert(other.m_value.object != nullptr);
01901                 m_value = *other.m_value.object;
01902                 break;
01903             }
01904 
01905             case value_t::array:
01906             {
01907                 assert(other.m_value.array != nullptr);
01908                 m_value = *other.m_value.array;
01909                 break;
01910             }
01911 
01912             case value_t::string:
01913             {
01914                 assert(other.m_value.string != nullptr);
01915                 m_value = *other.m_value.string;
01916                 break;
01917             }
01918 
01919             case value_t::boolean:
01920             {
01921                 m_value = other.m_value.boolean;
01922                 break;
01923             }
01924 
01925             case value_t::number_integer:
01926             {
01927                 m_value = other.m_value.number_integer;
01928                 break;
01929             }
01930 
01931             case value_t::number_unsigned:
01932             {
01933                 m_value = other.m_value.number_unsigned;
01934                 break;
01935             }
01936 
01937             case value_t::number_float:
01938             {
01939                 m_value = other.m_value.number_float;
01940                 break;
01941             }
01942 
01943             default:
01944             {
01945                 break;
01946             }
01947         }
01948     }
01949 
01968     basic_json(basic_json&& other) noexcept
01969         : m_type(std::move(other.m_type)),
01970           m_value(std::move(other.m_value))
01971     {
01972         // invalidate payload
01973         other.m_type = value_t::null;
01974         other.m_value = {};
01975     }
01976 
02000     reference& operator=(basic_json other) noexcept (
02001         std::is_nothrow_move_constructible<value_t>::value and
02002         std::is_nothrow_move_assignable<value_t>::value and
02003         std::is_nothrow_move_constructible<json_value>::value and
02004         std::is_nothrow_move_assignable<json_value>::value
02005     )
02006     {
02007         using std::swap;
02008         swap(m_type, other.m_type);
02009         swap(m_value, other.m_value);
02010         return *this;
02011     }
02012 
02028     ~basic_json()
02029     {
02030         switch (m_type)
02031         {
02032             case value_t::object:
02033             {
02034                 AllocatorType<object_t> alloc;
02035                 alloc.destroy(m_value.object);
02036                 alloc.deallocate(m_value.object, 1);
02037                 break;
02038             }
02039 
02040             case value_t::array:
02041             {
02042                 AllocatorType<array_t> alloc;
02043                 alloc.destroy(m_value.array);
02044                 alloc.deallocate(m_value.array, 1);
02045                 break;
02046             }
02047 
02048             case value_t::string:
02049             {
02050                 AllocatorType<string_t> alloc;
02051                 alloc.destroy(m_value.string);
02052                 alloc.deallocate(m_value.string, 1);
02053                 break;
02054             }
02055 
02056             default:
02057             {
02058                 // all other types need no specific destructor
02059                 break;
02060             }
02061         }
02062     }
02063 
02065 
02066   public:
02068     // object inspection //
02070 
02073 
02097     string_t dump(const int indent = -1) const
02098     {
02099         std::stringstream ss;
02100 
02101         if (indent >= 0)
02102         {
02103             dump(ss, true, static_cast<unsigned int>(indent));
02104         }
02105         else
02106         {
02107             dump(ss, false, 0);
02108         }
02109 
02110         return ss.str();
02111     }
02112 
02131     constexpr value_t type() const noexcept
02132     {
02133         return m_type;
02134     }
02135 
02161     constexpr bool is_primitive() const noexcept
02162     {
02163         return is_null() or is_string() or is_boolean() or is_number();
02164     }
02165 
02188     constexpr bool is_structured() const noexcept
02189     {
02190         return is_array() or is_object();
02191     }
02192 
02210     constexpr bool is_null() const noexcept
02211     {
02212         return m_type == value_t::null;
02213     }
02214 
02232     constexpr bool is_boolean() const noexcept
02233     {
02234         return m_type == value_t::boolean;
02235     }
02236 
02262     constexpr bool is_number() const noexcept
02263     {
02264         return is_number_integer() or is_number_float();
02265     }
02266 
02291     constexpr bool is_number_integer() const noexcept
02292     {
02293         return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
02294     }
02295 
02319     constexpr bool is_number_unsigned() const noexcept
02320     {
02321         return m_type == value_t::number_unsigned;
02322     }
02323 
02347     constexpr bool is_number_float() const noexcept
02348     {
02349         return m_type == value_t::number_float;
02350     }
02351 
02369     constexpr bool is_object() const noexcept
02370     {
02371         return m_type == value_t::object;
02372     }
02373 
02391     constexpr bool is_array() const noexcept
02392     {
02393         return m_type == value_t::array;
02394     }
02395 
02413     constexpr bool is_string() const noexcept
02414     {
02415         return m_type == value_t::string;
02416     }
02417 
02440     constexpr bool is_discarded() const noexcept
02441     {
02442         return m_type == value_t::discarded;
02443     }
02444 
02463     constexpr operator value_t() const noexcept
02464     {
02465         return m_type;
02466     }
02467 
02469 
02470   private:
02472     // value access //
02474 
02476     template <class T, typename
02477               std::enable_if<
02478                   std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
02479                   std::is_convertible<basic_json_t, typename T::mapped_type>::value
02480                   , int>::type = 0>
02481     T get_impl(T*) const
02482     {
02483         if (is_object())
02484         {
02485             assert(m_value.object != nullptr);
02486             return T(m_value.object->begin(), m_value.object->end());
02487         }
02488         else
02489         {
02490             throw std::domain_error("type must be object, but is " + type_name());
02491         }
02492     }
02493 
02495     object_t get_impl(object_t*) const
02496     {
02497         if (is_object())
02498         {
02499             assert(m_value.object != nullptr);
02500             return *(m_value.object);
02501         }
02502         else
02503         {
02504             throw std::domain_error("type must be object, but is " + type_name());
02505         }
02506     }
02507 
02509     template <class T, typename
02510               std::enable_if<
02511                   std::is_convertible<basic_json_t, typename T::value_type>::value and
02512                   not std::is_same<basic_json_t, typename T::value_type>::value and
02513                   not std::is_arithmetic<T>::value and
02514                   not std::is_convertible<std::string, T>::value and
02515                   not has_mapped_type<T>::value
02516                   , int>::type = 0>
02517     T get_impl(T*) const
02518     {
02519         if (is_array())
02520         {
02521             T to_vector;
02522             assert(m_value.array != nullptr);
02523             std::transform(m_value.array->begin(), m_value.array->end(),
02524                            std::inserter(to_vector, to_vector.end()), [](basic_json i)
02525             {
02526                 return i.get<typename T::value_type>();
02527             });
02528             return to_vector;
02529         }
02530         else
02531         {
02532             throw std::domain_error("type must be array, but is " + type_name());
02533         }
02534     }
02535 
02537     template <class T, typename
02538               std::enable_if<
02539                   std::is_convertible<basic_json_t, T>::value and
02540                   not std::is_same<basic_json_t, T>::value
02541                   , int>::type = 0>
02542     std::vector<T> get_impl(std::vector<T>*) const
02543     {
02544         if (is_array())
02545         {
02546             std::vector<T> to_vector;
02547             assert(m_value.array != nullptr);
02548             to_vector.reserve(m_value.array->size());
02549             std::transform(m_value.array->begin(), m_value.array->end(),
02550                            std::inserter(to_vector, to_vector.end()), [](basic_json i)
02551             {
02552                 return i.get<T>();
02553             });
02554             return to_vector;
02555         }
02556         else
02557         {
02558             throw std::domain_error("type must be array, but is " + type_name());
02559         }
02560     }
02561 
02563     template <class T, typename
02564               std::enable_if<
02565                   std::is_same<basic_json, typename T::value_type>::value and
02566                   not has_mapped_type<T>::value
02567                   , int>::type = 0>
02568     T get_impl(T*) const
02569     {
02570         if (is_array())
02571         {
02572             assert(m_value.array != nullptr);
02573             return T(m_value.array->begin(), m_value.array->end());
02574         }
02575         else
02576         {
02577             throw std::domain_error("type must be array, but is " + type_name());
02578         }
02579     }
02580 
02582     array_t get_impl(array_t*) const
02583     {
02584         if (is_array())
02585         {
02586             assert(m_value.array != nullptr);
02587             return *(m_value.array);
02588         }
02589         else
02590         {
02591             throw std::domain_error("type must be array, but is " + type_name());
02592         }
02593     }
02594 
02596     template <typename T, typename
02597               std::enable_if<
02598                   std::is_convertible<string_t, T>::value
02599                   , int>::type = 0>
02600     T get_impl(T*) const
02601     {
02602         if (is_string())
02603         {
02604             assert(m_value.string != nullptr);
02605             return *m_value.string;
02606         }
02607         else
02608         {
02609             throw std::domain_error("type must be string, but is " + type_name());
02610         }
02611     }
02612 
02614     template<typename T, typename
02615              std::enable_if<
02616                  std::is_arithmetic<T>::value
02617                  , int>::type = 0>
02618     T get_impl(T*) const
02619     {
02620         switch (m_type)
02621         {
02622             case value_t::number_integer:
02623             {
02624                 return static_cast<T>(m_value.number_integer);
02625             }
02626 
02627             case value_t::number_unsigned:
02628             {
02629                 return static_cast<T>(m_value.number_unsigned);
02630             }
02631 
02632             case value_t::number_float:
02633             {
02634                 return static_cast<T>(m_value.number_float);
02635             }
02636 
02637             default:
02638             {
02639                 throw std::domain_error("type must be number, but is " + type_name());
02640             }
02641         }
02642     }
02643 
02645     constexpr boolean_t get_impl(boolean_t*) const
02646     {
02647         return is_boolean()
02648                ? m_value.boolean
02649                : throw std::domain_error("type must be boolean, but is " + type_name());
02650     }
02651 
02653     object_t* get_impl_ptr(object_t*) noexcept
02654     {
02655         return is_object() ? m_value.object : nullptr;
02656     }
02657 
02659     constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
02660     {
02661         return is_object() ? m_value.object : nullptr;
02662     }
02663 
02665     array_t* get_impl_ptr(array_t*) noexcept
02666     {
02667         return is_array() ? m_value.array : nullptr;
02668     }
02669 
02671     constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
02672     {
02673         return is_array() ? m_value.array : nullptr;
02674     }
02675 
02677     string_t* get_impl_ptr(string_t*) noexcept
02678     {
02679         return is_string() ? m_value.string : nullptr;
02680     }
02681 
02683     constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
02684     {
02685         return is_string() ? m_value.string : nullptr;
02686     }
02687 
02689     boolean_t* get_impl_ptr(boolean_t*) noexcept
02690     {
02691         return is_boolean() ? &m_value.boolean : nullptr;
02692     }
02693 
02695     constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
02696     {
02697         return is_boolean() ? &m_value.boolean : nullptr;
02698     }
02699 
02701     number_integer_t* get_impl_ptr(number_integer_t*) noexcept
02702     {
02703         return is_number_integer() ? &m_value.number_integer : nullptr;
02704     }
02705 
02707     constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
02708     {
02709         return is_number_integer() ? &m_value.number_integer : nullptr;
02710     }
02711 
02713     number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
02714     {
02715         return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
02716     }
02717 
02719     constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
02720     {
02721         return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
02722     }
02723 
02725     number_float_t* get_impl_ptr(number_float_t*) noexcept
02726     {
02727         return is_number_float() ? &m_value.number_float : nullptr;
02728     }
02729 
02731     constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
02732     {
02733         return is_number_float() ? &m_value.number_float : nullptr;
02734     }
02735 
02747     template<typename ReferenceType, typename ThisType>
02748     static ReferenceType get_ref_impl(ThisType& obj)
02749     {
02750         // delegate the call to get_ptr<>()
02751         using PointerType = typename std::add_pointer<ReferenceType>::type;
02752         auto ptr = obj.template get_ptr<PointerType>();
02753 
02754         if (ptr != nullptr)
02755         {
02756             return *ptr;
02757         }
02758         else
02759         {
02760             throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
02761                                     obj.type_name());
02762         }
02763     }
02764 
02765   public:
02766 
02769 
02803     template<typename ValueType, typename
02804              std::enable_if<
02805                  not std::is_pointer<ValueType>::value
02806                  , int>::type = 0>
02807     ValueType get() const
02808     {
02809         return get_impl(static_cast<ValueType*>(nullptr));
02810     }
02811 
02838     template<typename PointerType, typename
02839              std::enable_if<
02840                  std::is_pointer<PointerType>::value
02841                  , int>::type = 0>
02842     PointerType get() noexcept
02843     {
02844         // delegate the call to get_ptr
02845         return get_ptr<PointerType>();
02846     }
02847 
02852     template<typename PointerType, typename
02853              std::enable_if<
02854                  std::is_pointer<PointerType>::value
02855                  , int>::type = 0>
02856     constexpr const PointerType get() const noexcept
02857     {
02858         // delegate the call to get_ptr
02859         return get_ptr<PointerType>();
02860     }
02861 
02887     template<typename PointerType, typename
02888              std::enable_if<
02889                  std::is_pointer<PointerType>::value
02890                  , int>::type = 0>
02891     PointerType get_ptr() noexcept
02892     {
02893         // delegate the call to get_impl_ptr<>()
02894         return get_impl_ptr(static_cast<PointerType>(nullptr));
02895     }
02896 
02901     template<typename PointerType, typename
02902              std::enable_if<
02903                  std::is_pointer<PointerType>::value
02904                  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
02905                  , int>::type = 0>
02906     constexpr const PointerType get_ptr() const noexcept
02907     {
02908         // delegate the call to get_impl_ptr<>() const
02909         return get_impl_ptr(static_cast<const PointerType>(nullptr));
02910     }
02911 
02938     template<typename ReferenceType, typename
02939              std::enable_if<
02940                  std::is_reference<ReferenceType>::value
02941                  , int>::type = 0>
02942     ReferenceType get_ref()
02943     {
02944         // delegate call to get_ref_impl
02945         return get_ref_impl<ReferenceType>(*this);
02946     }
02947 
02952     template<typename ReferenceType, typename
02953              std::enable_if<
02954                  std::is_reference<ReferenceType>::value
02955                  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
02956                  , int>::type = 0>
02957     ReferenceType get_ref() const
02958     {
02959         // delegate call to get_ref_impl
02960         return get_ref_impl<ReferenceType>(*this);
02961     }
02962 
02991     template < typename ValueType, typename
02992                std::enable_if <
02993                    not std::is_pointer<ValueType>::value
02994                    and not std::is_same<ValueType, typename string_t::value_type>::value
02995 #ifndef _MSC_VER  // Fix for issue #167 operator<< abiguity under VS2015
02996                    and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
02997 #endif
02998                    , int >::type = 0 >
02999     operator ValueType() const
03000     {
03001         // delegate the call to get<>() const
03002         return get<ValueType>();
03003     }
03004 
03006 
03007 
03009     // element access //
03011 
03014 
03037     reference at(size_type idx)
03038     {
03039         // at only works for arrays
03040         if (is_array())
03041         {
03042             try
03043             {
03044                 assert(m_value.array != nullptr);
03045                 return m_value.array->at(idx);
03046             }
03047             catch (std::out_of_range&)
03048             {
03049                 // create better exception explanation
03050                 throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
03051             }
03052         }
03053         else
03054         {
03055             throw std::domain_error("cannot use at() with " + type_name());
03056         }
03057     }
03058 
03081     const_reference at(size_type idx) const
03082     {
03083         // at only works for arrays
03084         if (is_array())
03085         {
03086             try
03087             {
03088                 assert(m_value.array != nullptr);
03089                 return m_value.array->at(idx);
03090             }
03091             catch (std::out_of_range&)
03092             {
03093                 // create better exception explanation
03094                 throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
03095             }
03096         }
03097         else
03098         {
03099             throw std::domain_error("cannot use at() with " + type_name());
03100         }
03101     }
03102 
03129     reference at(const typename object_t::key_type& key)
03130     {
03131         // at only works for objects
03132         if (is_object())
03133         {
03134             try
03135             {
03136                 assert(m_value.object != nullptr);
03137                 return m_value.object->at(key);
03138             }
03139             catch (std::out_of_range&)
03140             {
03141                 // create better exception explanation
03142                 throw std::out_of_range("key '" + key + "' not found");
03143             }
03144         }
03145         else
03146         {
03147             throw std::domain_error("cannot use at() with " + type_name());
03148         }
03149     }
03150 
03177     const_reference at(const typename object_t::key_type& key) const
03178     {
03179         // at only works for objects
03180         if (is_object())
03181         {
03182             try
03183             {
03184                 assert(m_value.object != nullptr);
03185                 return m_value.object->at(key);
03186             }
03187             catch (std::out_of_range&)
03188             {
03189                 // create better exception explanation
03190                 throw std::out_of_range("key '" + key + "' not found");
03191             }
03192         }
03193         else
03194         {
03195             throw std::domain_error("cannot use at() with " + type_name());
03196         }
03197     }
03198 
03224     reference operator[](size_type idx)
03225     {
03226         // implicitly convert null value to an empty array
03227         if (is_null())
03228         {
03229             m_type = value_t::array;
03230             m_value.array = create<array_t>();
03231         }
03232 
03233         // operator[] only works for arrays
03234         if (is_array())
03235         {
03236             // fill up array with null values until given idx is reached
03237             assert(m_value.array != nullptr);
03238             for (size_t i = m_value.array->size(); i <= idx; ++i)
03239             {
03240                 m_value.array->push_back(basic_json());
03241             }
03242 
03243             return m_value.array->operator[](idx);
03244         }
03245         else
03246         {
03247             throw std::domain_error("cannot use operator[] with " + type_name());
03248         }
03249     }
03250 
03270     const_reference operator[](size_type idx) const
03271     {
03272         // const operator[] only works for arrays
03273         if (is_array())
03274         {
03275             assert(m_value.array != nullptr);
03276             return m_value.array->operator[](idx);
03277         }
03278         else
03279         {
03280             throw std::domain_error("cannot use operator[] with " + type_name());
03281         }
03282     }
03283 
03311     reference operator[](const typename object_t::key_type& key)
03312     {
03313         // implicitly convert null value to an empty object
03314         if (is_null())
03315         {
03316             m_type = value_t::object;
03317             m_value.object = create<object_t>();
03318         }
03319 
03320         // operator[] only works for objects
03321         if (is_object())
03322         {
03323             assert(m_value.object != nullptr);
03324             return m_value.object->operator[](key);
03325         }
03326         else
03327         {
03328             throw std::domain_error("cannot use operator[] with " + type_name());
03329         }
03330     }
03331 
03359     const_reference operator[](const typename object_t::key_type& key) const
03360     {
03361         // const operator[] only works for objects
03362         if (is_object())
03363         {
03364             assert(m_value.object != nullptr);
03365             assert(m_value.object->find(key) != m_value.object->end());
03366             return m_value.object->find(key)->second;
03367         }
03368         else
03369         {
03370             throw std::domain_error("cannot use operator[] with " + type_name());
03371         }
03372     }
03373 
03401     template<typename T, std::size_t n>
03402     reference operator[](T * (&key)[n])
03403     {
03404         return operator[](static_cast<const T>(key));
03405     }
03406 
03436     template<typename T, std::size_t n>
03437     const_reference operator[](T * (&key)[n]) const
03438     {
03439         return operator[](static_cast<const T>(key));
03440     }
03441 
03469     template<typename T>
03470     reference operator[](T* key)
03471     {
03472         // implicitly convert null to object
03473         if (is_null())
03474         {
03475             m_type = value_t::object;
03476             m_value = value_t::object;
03477         }
03478 
03479         // at only works for objects
03480         if (is_object())
03481         {
03482             assert(m_value.object != nullptr);
03483             return m_value.object->operator[](key);
03484         }
03485         else
03486         {
03487             throw std::domain_error("cannot use operator[] with " + type_name());
03488         }
03489     }
03490 
03518     template<typename T>
03519     const_reference operator[](T* key) const
03520     {
03521         // at only works for objects
03522         if (is_object())
03523         {
03524             assert(m_value.object != nullptr);
03525             assert(m_value.object->find(key) != m_value.object->end());
03526             return m_value.object->find(key)->second;
03527         }
03528         else
03529         {
03530             throw std::domain_error("cannot use operator[] with " + type_name());
03531         }
03532     }
03533 
03582     template <class ValueType, typename
03583               std::enable_if<
03584                   std::is_convertible<basic_json_t, ValueType>::value
03585                   , int>::type = 0>
03586     ValueType value(const typename object_t::key_type& key, ValueType default_value) const
03587     {
03588         // at only works for objects
03589         if (is_object())
03590         {
03591             // if key is found, return value and given default value otherwise
03592             const auto it = find(key);
03593             if (it != end())
03594             {
03595                 return *it;
03596             }
03597             else
03598             {
03599                 return default_value;
03600             }
03601         }
03602         else
03603         {
03604             throw std::domain_error("cannot use value() with " + type_name());
03605         }
03606     }
03607 
03612     string_t value(const typename object_t::key_type& key, const char* default_value) const
03613     {
03614         return value(key, string_t(default_value));
03615     }
03616 
03641     reference front()
03642     {
03643         return *begin();
03644     }
03645 
03649     const_reference front() const
03650     {
03651         return *cbegin();
03652     }
03653 
03683     reference back()
03684     {
03685         auto tmp = end();
03686         --tmp;
03687         return *tmp;
03688     }
03689 
03693     const_reference back() const
03694     {
03695         auto tmp = cend();
03696         --tmp;
03697         return *tmp;
03698     }
03699 
03745     template <class InteratorType, typename
03746               std::enable_if<
03747                   std::is_same<InteratorType, typename basic_json_t::iterator>::value or
03748                   std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
03749                   , int>::type
03750               = 0>
03751     InteratorType erase(InteratorType pos)
03752     {
03753         // make sure iterator fits the current value
03754         if (this != pos.m_object)
03755         {
03756             throw std::domain_error("iterator does not fit current value");
03757         }
03758 
03759         InteratorType result = end();
03760 
03761         switch (m_type)
03762         {
03763             case value_t::boolean:
03764             case value_t::number_float:
03765             case value_t::number_integer:
03766             case value_t::number_unsigned:
03767             case value_t::string:
03768             {
03769                 if (not pos.m_it.primitive_iterator.is_begin())
03770                 {
03771                     throw std::out_of_range("iterator out of range");
03772                 }
03773 
03774                 if (is_string())
03775                 {
03776                     delete m_value.string;
03777                     m_value.string = nullptr;
03778                 }
03779 
03780                 m_type = value_t::null;
03781                 break;
03782             }
03783 
03784             case value_t::object:
03785             {
03786                 assert(m_value.object != nullptr);
03787                 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
03788                 break;
03789             }
03790 
03791             case value_t::array:
03792             {
03793                 assert(m_value.array != nullptr);
03794                 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
03795                 break;
03796             }
03797 
03798             default:
03799             {
03800                 throw std::domain_error("cannot use erase() with " + type_name());
03801             }
03802         }
03803 
03804         return result;
03805     }
03806 
03853     template <class InteratorType, typename
03854               std::enable_if<
03855                   std::is_same<InteratorType, typename basic_json_t::iterator>::value or
03856                   std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
03857                   , int>::type
03858               = 0>
03859     InteratorType erase(InteratorType first, InteratorType last)
03860     {
03861         // make sure iterator fits the current value
03862         if (this != first.m_object or this != last.m_object)
03863         {
03864             throw std::domain_error("iterators do not fit current value");
03865         }
03866 
03867         InteratorType result = end();
03868 
03869         switch (m_type)
03870         {
03871             case value_t::boolean:
03872             case value_t::number_float:
03873             case value_t::number_integer:
03874             case value_t::number_unsigned:
03875             case value_t::string:
03876             {
03877                 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
03878                 {
03879                     throw std::out_of_range("iterators out of range");
03880                 }
03881 
03882                 if (is_string())
03883                 {
03884                     delete m_value.string;
03885                     m_value.string = nullptr;
03886                 }
03887 
03888                 m_type = value_t::null;
03889                 break;
03890             }
03891 
03892             case value_t::object:
03893             {
03894                 assert(m_value.object != nullptr);
03895                 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
03896                                               last.m_it.object_iterator);
03897                 break;
03898             }
03899 
03900             case value_t::array:
03901             {
03902                 assert(m_value.array != nullptr);
03903                 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
03904                                              last.m_it.array_iterator);
03905                 break;
03906             }
03907 
03908             default:
03909             {
03910                 throw std::domain_error("cannot use erase() with " + type_name());
03911             }
03912         }
03913 
03914         return result;
03915     }
03916 
03946     size_type erase(const typename object_t::key_type& key)
03947     {
03948         // this erase only works for objects
03949         if (is_object())
03950         {
03951             assert(m_value.object != nullptr);
03952             return m_value.object->erase(key);
03953         }
03954         else
03955         {
03956             throw std::domain_error("cannot use erase() with " + type_name());
03957         }
03958     }
03959 
03984     void erase(const size_type idx)
03985     {
03986         // this erase only works for arrays
03987         if (is_array())
03988         {
03989             if (idx >= size())
03990             {
03991                 throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
03992             }
03993 
03994             assert(m_value.array != nullptr);
03995             m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
03996         }
03997         else
03998         {
03999             throw std::domain_error("cannot use erase() with " + type_name());
04000         }
04001     }
04002 
04004 
04005 
04007     // lookup //
04009 
04012 
04031     iterator find(typename object_t::key_type key)
04032     {
04033         auto result = end();
04034 
04035         if (is_object())
04036         {
04037             assert(m_value.object != nullptr);
04038             result.m_it.object_iterator = m_value.object->find(key);
04039         }
04040 
04041         return result;
04042     }
04043 
04048     const_iterator find(typename object_t::key_type key) const
04049     {
04050         auto result = cend();
04051 
04052         if (is_object())
04053         {
04054             assert(m_value.object != nullptr);
04055             result.m_it.object_iterator = m_value.object->find(key);
04056         }
04057 
04058         return result;
04059     }
04060 
04079     size_type count(typename object_t::key_type key) const
04080     {
04081         // return 0 for all nonobject types
04082         assert(not is_object() or m_value.object != nullptr);
04083         return is_object() ? m_value.object->count(key) : 0;
04084     }
04085 
04087 
04088 
04090     // iterators //
04092 
04095 
04120     iterator begin() noexcept
04121     {
04122         iterator result(this);
04123         result.set_begin();
04124         return result;
04125     }
04126 
04130     const_iterator begin() const noexcept
04131     {
04132         return cbegin();
04133     }
04134 
04160     const_iterator cbegin() const noexcept
04161     {
04162         const_iterator result(this);
04163         result.set_begin();
04164         return result;
04165     }
04166 
04191     iterator end() noexcept
04192     {
04193         iterator result(this);
04194         result.set_end();
04195         return result;
04196     }
04197 
04201     const_iterator end() const noexcept
04202     {
04203         return cend();
04204     }
04205 
04231     const_iterator cend() const noexcept
04232     {
04233         const_iterator result(this);
04234         result.set_end();
04235         return result;
04236     }
04237 
04261     reverse_iterator rbegin() noexcept
04262     {
04263         return reverse_iterator(end());
04264     }
04265 
04269     const_reverse_iterator rbegin() const noexcept
04270     {
04271         return crbegin();
04272     }
04273 
04298     reverse_iterator rend() noexcept
04299     {
04300         return reverse_iterator(begin());
04301     }
04302 
04306     const_reverse_iterator rend() const noexcept
04307     {
04308         return crend();
04309     }
04310 
04335     const_reverse_iterator crbegin() const noexcept
04336     {
04337         return const_reverse_iterator(cend());
04338     }
04339 
04364     const_reverse_iterator crend() const noexcept
04365     {
04366         return const_reverse_iterator(cbegin());
04367     }
04368 
04369   private:
04370     // forward declaration
04371     template<typename IteratorType> class iteration_proxy;
04372 
04373   public:
04385     static iteration_proxy<iterator> iterator_wrapper(reference cont)
04386     {
04387         return iteration_proxy<iterator>(cont);
04388     }
04389 
04393     static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
04394     {
04395         return iteration_proxy<const_iterator>(cont);
04396     }
04397 
04399 
04400 
04402     // capacity //
04404 
04407 
04441     bool empty() const noexcept
04442     {
04443         switch (m_type)
04444         {
04445             case value_t::null:
04446             {
04447                 // null values are empty
04448                 return true;
04449             }
04450 
04451             case value_t::array:
04452             {
04453                 assert(m_value.array != nullptr);
04454                 return m_value.array->empty();
04455             }
04456 
04457             case value_t::object:
04458             {
04459                 assert(m_value.object != nullptr);
04460                 return m_value.object->empty();
04461             }
04462 
04463             default:
04464             {
04465                 // all other types are nonempty
04466                 return false;
04467             }
04468         }
04469     }
04470 
04505     size_type size() const noexcept
04506     {
04507         switch (m_type)
04508         {
04509             case value_t::null:
04510             {
04511                 // null values are empty
04512                 return 0;
04513             }
04514 
04515             case value_t::array:
04516             {
04517                 assert(m_value.array != nullptr);
04518                 return m_value.array->size();
04519             }
04520 
04521             case value_t::object:
04522             {
04523                 assert(m_value.object != nullptr);
04524                 return m_value.object->size();
04525             }
04526 
04527             default:
04528             {
04529                 // all other types have size 1
04530                 return 1;
04531             }
04532         }
04533     }
04534 
04571     size_type max_size() const noexcept
04572     {
04573         switch (m_type)
04574         {
04575             case value_t::array:
04576             {
04577                 assert(m_value.array != nullptr);
04578                 return m_value.array->max_size();
04579             }
04580 
04581             case value_t::object:
04582             {
04583                 assert(m_value.object != nullptr);
04584                 return m_value.object->max_size();
04585             }
04586 
04587             default:
04588             {
04589                 // all other types have max_size() == size()
04590                 return size();
04591             }
04592         }
04593     }
04594 
04596 
04597 
04599     // modifiers //
04601 
04604 
04630     void clear() noexcept
04631     {
04632         switch (m_type)
04633         {
04634             case value_t::number_integer:
04635             {
04636                 m_value.number_integer = 0;
04637                 break;
04638             }
04639 
04640             case value_t::number_unsigned:
04641             {
04642                 m_value.number_unsigned = 0;
04643                 break;
04644             }
04645 
04646             case value_t::number_float:
04647             {
04648                 m_value.number_float = 0.0;
04649                 break;
04650             }
04651 
04652             case value_t::boolean:
04653             {
04654                 m_value.boolean = false;
04655                 break;
04656             }
04657 
04658             case value_t::string:
04659             {
04660                 assert(m_value.string != nullptr);
04661                 m_value.string->clear();
04662                 break;
04663             }
04664 
04665             case value_t::array:
04666             {
04667                 assert(m_value.array != nullptr);
04668                 m_value.array->clear();
04669                 break;
04670             }
04671 
04672             case value_t::object:
04673             {
04674                 assert(m_value.object != nullptr);
04675                 m_value.object->clear();
04676                 break;
04677             }
04678 
04679             default:
04680             {
04681                 break;
04682             }
04683         }
04684     }
04685 
04706     void push_back(basic_json&& val)
04707     {
04708         // push_back only works for null objects or arrays
04709         if (not(is_null() or is_array()))
04710         {
04711             throw std::domain_error("cannot use push_back() with " + type_name());
04712         }
04713 
04714         // transform null object into an array
04715         if (is_null())
04716         {
04717             m_type = value_t::array;
04718             m_value = value_t::array;
04719         }
04720 
04721         // add element to array (move semantics)
04722         assert(m_value.array != nullptr);
04723         m_value.array->push_back(std::move(val));
04724         // invalidate object
04725         val.m_type = value_t::null;
04726     }
04727 
04732     reference operator+=(basic_json&& val)
04733     {
04734         push_back(std::move(val));
04735         return *this;
04736     }
04737 
04742     void push_back(const basic_json& val)
04743     {
04744         // push_back only works for null objects or arrays
04745         if (not(is_null() or is_array()))
04746         {
04747             throw std::domain_error("cannot use push_back() with " + type_name());
04748         }
04749 
04750         // transform null object into an array
04751         if (is_null())
04752         {
04753             m_type = value_t::array;
04754             m_value = value_t::array;
04755         }
04756 
04757         // add element to array
04758         assert(m_value.array != nullptr);
04759         m_value.array->push_back(val);
04760     }
04761 
04766     reference operator+=(const basic_json& val)
04767     {
04768         push_back(val);
04769         return *this;
04770     }
04771 
04792     void push_back(const typename object_t::value_type& val)
04793     {
04794         // push_back only works for null objects or objects
04795         if (not(is_null() or is_object()))
04796         {
04797             throw std::domain_error("cannot use push_back() with " + type_name());
04798         }
04799 
04800         // transform null object into an object
04801         if (is_null())
04802         {
04803             m_type = value_t::object;
04804             m_value = value_t::object;
04805         }
04806 
04807         // add element to array
04808         assert(m_value.object != nullptr);
04809         m_value.object->insert(val);
04810     }
04811 
04816     reference operator+=(const typename object_t::value_type& val)
04817     {
04818         push_back(val);
04819         return *this;
04820     }
04821 
04847     void push_back(std::initializer_list<basic_json> init)
04848     {
04849         if (is_object() and init.size() == 2 and init.begin()->is_string())
04850         {
04851             const string_t key = *init.begin();
04852             push_back(typename object_t::value_type(key, *(init.begin() + 1)));
04853         }
04854         else
04855         {
04856             push_back(basic_json(init));
04857         }
04858     }
04859 
04864     reference operator+=(std::initializer_list<basic_json> init)
04865     {
04866         push_back(init);
04867         return *this;
04868     }
04869 
04892     iterator insert(const_iterator pos, const basic_json& val)
04893     {
04894         // insert only works for arrays
04895         if (is_array())
04896         {
04897             // check if iterator pos fits to this JSON value
04898             if (pos.m_object != this)
04899             {
04900                 throw std::domain_error("iterator does not fit current value");
04901             }
04902 
04903             // insert to array and return iterator
04904             iterator result(this);
04905             assert(m_value.array != nullptr);
04906             result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
04907             return result;
04908         }
04909         else
04910         {
04911             throw std::domain_error("cannot use insert() with " + type_name());
04912         }
04913     }
04914 
04919     iterator insert(const_iterator pos, basic_json&& val)
04920     {
04921         return insert(pos, val);
04922     }
04923 
04948     iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
04949     {
04950         // insert only works for arrays
04951         if (is_array())
04952         {
04953             // check if iterator pos fits to this JSON value
04954             if (pos.m_object != this)
04955             {
04956                 throw std::domain_error("iterator does not fit current value");
04957             }
04958 
04959             // insert to array and return iterator
04960             iterator result(this);
04961             assert(m_value.array != nullptr);
04962             result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
04963             return result;
04964         }
04965         else
04966         {
04967             throw std::domain_error("cannot use insert() with " + type_name());
04968         }
04969     }
04970 
05001     iterator insert(const_iterator pos, const_iterator first, const_iterator last)
05002     {
05003         // insert only works for arrays
05004         if (not is_array())
05005         {
05006             throw std::domain_error("cannot use insert() with " + type_name());
05007         }
05008 
05009         // check if iterator pos fits to this JSON value
05010         if (pos.m_object != this)
05011         {
05012             throw std::domain_error("iterator does not fit current value");
05013         }
05014 
05015         // check if range iterators belong to the same JSON object
05016         if (first.m_object != last.m_object)
05017         {
05018             throw std::domain_error("iterators do not fit");
05019         }
05020 
05021         if (first.m_object == this or last.m_object == this)
05022         {
05023             throw std::domain_error("passed iterators may not belong to container");
05024         }
05025 
05026         // insert to array and return iterator
05027         iterator result(this);
05028         assert(m_value.array != nullptr);
05029         result.m_it.array_iterator = m_value.array->insert(
05030                                          pos.m_it.array_iterator,
05031                                          first.m_it.array_iterator,
05032                                          last.m_it.array_iterator);
05033         return result;
05034     }
05035 
05060     iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
05061     {
05062         // insert only works for arrays
05063         if (not is_array())
05064         {
05065             throw std::domain_error("cannot use insert() with " + type_name());
05066         }
05067 
05068         // check if iterator pos fits to this JSON value
05069         if (pos.m_object != this)
05070         {
05071             throw std::domain_error("iterator does not fit current value");
05072         }
05073 
05074         // insert to array and return iterator
05075         iterator result(this);
05076         assert(m_value.array != nullptr);
05077         result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
05078         return result;
05079     }
05080 
05098     void swap(reference other) noexcept (
05099         std::is_nothrow_move_constructible<value_t>::value and
05100         std::is_nothrow_move_assignable<value_t>::value and
05101         std::is_nothrow_move_constructible<json_value>::value and
05102         std::is_nothrow_move_assignable<json_value>::value
05103     )
05104     {
05105         std::swap(m_type, other.m_type);
05106         std::swap(m_value, other.m_value);
05107     }
05108 
05129     void swap(array_t& other)
05130     {
05131         // swap only works for arrays
05132         if (is_array())
05133         {
05134             assert(m_value.array != nullptr);
05135             std::swap(*(m_value.array), other);
05136         }
05137         else
05138         {
05139             throw std::domain_error("cannot use swap() with " + type_name());
05140         }
05141     }
05142 
05163     void swap(object_t& other)
05164     {
05165         // swap only works for objects
05166         if (is_object())
05167         {
05168             assert(m_value.object != nullptr);
05169             std::swap(*(m_value.object), other);
05170         }
05171         else
05172         {
05173             throw std::domain_error("cannot use swap() with " + type_name());
05174         }
05175     }
05176 
05197     void swap(string_t& other)
05198     {
05199         // swap only works for strings
05200         if (is_string())
05201         {
05202             assert(m_value.string != nullptr);
05203             std::swap(*(m_value.string), other);
05204         }
05205         else
05206         {
05207             throw std::domain_error("cannot use swap() with " + type_name());
05208         }
05209     }
05210 
05212 
05213 
05215     // lexicographical comparison operators //
05217 
05220 
05221   private:
05231     friend bool operator<(const value_t lhs, const value_t rhs) noexcept
05232     {
05233         static constexpr std::array<uint8_t, 8> order = {{
05234                 0, // null
05235                 3, // object
05236                 4, // array
05237                 5, // string
05238                 1, // boolean
05239                 2, // integer
05240                 2, // unsigned
05241                 2, // float
05242             }
05243         };
05244 
05245         // discarded values are not comparable
05246         if (lhs == value_t::discarded or rhs == value_t::discarded)
05247         {
05248             return false;
05249         }
05250 
05251         return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
05252     }
05253 
05254   public:
05278     friend bool operator==(const_reference lhs, const_reference rhs) noexcept
05279     {
05280         const auto lhs_type = lhs.type();
05281         const auto rhs_type = rhs.type();
05282 
05283         if (lhs_type == rhs_type)
05284         {
05285             switch (lhs_type)
05286             {
05287                 case value_t::array:
05288                 {
05289                     assert(lhs.m_value.array != nullptr);
05290                     assert(rhs.m_value.array != nullptr);
05291                     return *lhs.m_value.array == *rhs.m_value.array;
05292                 }
05293                 case value_t::object:
05294                 {
05295                     assert(lhs.m_value.object != nullptr);
05296                     assert(rhs.m_value.object != nullptr);
05297                     return *lhs.m_value.object == *rhs.m_value.object;
05298                 }
05299                 case value_t::null:
05300                 {
05301                     return true;
05302                 }
05303                 case value_t::string:
05304                 {
05305                     assert(lhs.m_value.string != nullptr);
05306                     assert(rhs.m_value.string != nullptr);
05307                     return *lhs.m_value.string == *rhs.m_value.string;
05308                 }
05309                 case value_t::boolean:
05310                 {
05311                     return lhs.m_value.boolean == rhs.m_value.boolean;
05312                 }
05313                 case value_t::number_integer:
05314                 {
05315                     return lhs.m_value.number_integer == rhs.m_value.number_integer;
05316                 }
05317                 case value_t::number_unsigned:
05318                 {
05319                     return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
05320                 }
05321                 case value_t::number_float:
05322                 {
05323                     return lhs.m_value.number_float == rhs.m_value.number_float;
05324                 }
05325                 default:
05326                 {
05327                     return false;
05328                 }
05329             }
05330         }
05331         else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
05332         {
05333             return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
05334         }
05335         else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
05336         {
05337             return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
05338         }
05339         else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
05340         {
05341             return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
05342         }
05343         else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
05344         {
05345             return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
05346         }
05347         else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
05348         {
05349             return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
05350         }
05351         else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
05352         {
05353             return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
05354         }
05355 
05356         return false;
05357     }
05358 
05377     friend bool operator==(const_reference v, std::nullptr_t) noexcept
05378     {
05379         return v.is_null();
05380     }
05381 
05386     friend bool operator==(std::nullptr_t, const_reference v) noexcept
05387     {
05388         return v.is_null();
05389     }
05390 
05407     friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
05408     {
05409         return not (lhs == rhs);
05410     }
05411 
05430     friend bool operator!=(const_reference v, std::nullptr_t) noexcept
05431     {
05432         return not v.is_null();
05433     }
05434 
05439     friend bool operator!=(std::nullptr_t, const_reference v) noexcept
05440     {
05441         return not v.is_null();
05442     }
05443 
05468     friend bool operator<(const_reference lhs, const_reference rhs) noexcept
05469     {
05470         const auto lhs_type = lhs.type();
05471         const auto rhs_type = rhs.type();
05472 
05473         if (lhs_type == rhs_type)
05474         {
05475             switch (lhs_type)
05476             {
05477                 case value_t::array:
05478                 {
05479                     assert(lhs.m_value.array != nullptr);
05480                     assert(rhs.m_value.array != nullptr);
05481                     return *lhs.m_value.array < *rhs.m_value.array;
05482                 }
05483                 case value_t::object:
05484                 {
05485                     assert(lhs.m_value.object != nullptr);
05486                     assert(rhs.m_value.object != nullptr);
05487                     return *lhs.m_value.object < *rhs.m_value.object;
05488                 }
05489                 case value_t::null:
05490                 {
05491                     return false;
05492                 }
05493                 case value_t::string:
05494                 {
05495                     assert(lhs.m_value.string != nullptr);
05496                     assert(rhs.m_value.string != nullptr);
05497                     return *lhs.m_value.string < *rhs.m_value.string;
05498                 }
05499                 case value_t::boolean:
05500                 {
05501                     return lhs.m_value.boolean < rhs.m_value.boolean;
05502                 }
05503                 case value_t::number_integer:
05504                 {
05505                     return lhs.m_value.number_integer < rhs.m_value.number_integer;
05506                 }
05507                 case value_t::number_unsigned:
05508                 {
05509                     return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
05510                 }
05511                 case value_t::number_float:
05512                 {
05513                     return lhs.m_value.number_float < rhs.m_value.number_float;
05514                 }
05515                 default:
05516                 {
05517                     return false;
05518                 }
05519             }
05520         }
05521         else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
05522         {
05523             return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
05524         }
05525         else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
05526         {
05527             return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
05528         }
05529         else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
05530         {
05531             return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
05532         }
05533         else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
05534         {
05535             return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
05536         }
05537         else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
05538         {
05539             return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
05540         }
05541         else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
05542         {
05543             return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
05544         }
05545 
05546         // We only reach this line if we cannot compare values. In that case,
05547         // we compare types. Note we have to call the operator explicitly,
05548         // because MSVC has problems otherwise.
05549         return operator<(lhs_type, rhs_type);
05550     }
05551 
05569     friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
05570     {
05571         return not (rhs < lhs);
05572     }
05573 
05591     friend bool operator>(const_reference lhs, const_reference rhs) noexcept
05592     {
05593         return not (lhs <= rhs);
05594     }
05595 
05613     friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
05614     {
05615         return not (lhs < rhs);
05616     }
05617 
05619 
05620 
05622     // serialization //
05624 
05627 
05650     friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
05651     {
05652         // read width member and use it as indentation parameter if nonzero
05653         const bool pretty_print = (o.width() > 0);
05654         const auto indentation = (pretty_print ? o.width() : 0);
05655 
05656         // reset width to 0 for subsequent calls to this stream
05657         o.width(0);
05658 
05659         // do the actual serialization
05660         j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
05661         return o;
05662     }
05663 
05668     friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
05669     {
05670         return o << j;
05671     }
05672 
05674 
05675 
05677     // deserialization //
05679 
05682 
05707     static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
05708     {
05709         return parser(s, cb).parse();
05710     }
05711 
05736     static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
05737     {
05738         return parser(i, cb).parse();
05739     }
05740 
05744     static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
05745     {
05746         return parser(i, cb).parse();
05747     }
05748 
05772     friend std::istream& operator<<(basic_json& j, std::istream& i)
05773     {
05774         j = parser(i).parse();
05775         return i;
05776     }
05777 
05782     friend std::istream& operator>>(std::istream& i, basic_json& j)
05783     {
05784         j = parser(i).parse();
05785         return i;
05786     }
05787 
05789 
05790 
05791   private:
05793     // convenience functions //
05795 
05797     string_t type_name() const noexcept
05798     {
05799         switch (m_type)
05800         {
05801             case value_t::null:
05802                 return "null";
05803             case value_t::object:
05804                 return "object";
05805             case value_t::array:
05806                 return "array";
05807             case value_t::string:
05808                 return "string";
05809             case value_t::boolean:
05810                 return "boolean";
05811             case value_t::discarded:
05812                 return "discarded";
05813             default:
05814                 return "number";
05815         }
05816     }
05817 
05826     static std::size_t extra_space(const string_t& s) noexcept
05827     {
05828         std::size_t result = 0;
05829 
05830         for (const auto& c : s)
05831         {
05832             switch (c)
05833             {
05834                 case '"':
05835                 case '\\':
05836                 case '\b':
05837                 case '\f':
05838                 case '\n':
05839                 case '\r':
05840                 case '\t':
05841                 {
05842                     // from c (1 byte) to \x (2 bytes)
05843                     result += 1;
05844                     break;
05845                 }
05846 
05847                 default:
05848                 {
05849                     if (c >= 0x00 and c <= 0x1f)
05850                     {
05851                         // from c (1 byte) to \uxxxx (6 bytes)
05852                         result += 5;
05853                     }
05854                     break;
05855                 }
05856             }
05857         }
05858 
05859         return result;
05860     }
05861 
05875     static string_t escape_string(const string_t& s)
05876     {
05877         const auto space = extra_space(s);
05878         if (space == 0)
05879         {
05880             return s;
05881         }
05882 
05883         // create a result string of necessary size
05884         string_t result(s.size() + space, '\\');
05885         std::size_t pos = 0;
05886 
05887         for (const auto& c : s)
05888         {
05889             switch (c)
05890             {
05891                 // quotation mark (0x22)
05892                 case '"':
05893                 {
05894                     result[pos + 1] = '"';
05895                     pos += 2;
05896                     break;
05897                 }
05898 
05899                 // reverse solidus (0x5c)
05900                 case '\\':
05901                 {
05902                     // nothing to change
05903                     pos += 2;
05904                     break;
05905                 }
05906 
05907                 // backspace (0x08)
05908                 case '\b':
05909                 {
05910                     result[pos + 1] = 'b';
05911                     pos += 2;
05912                     break;
05913                 }
05914 
05915                 // formfeed (0x0c)
05916                 case '\f':
05917                 {
05918                     result[pos + 1] = 'f';
05919                     pos += 2;
05920                     break;
05921                 }
05922 
05923                 // newline (0x0a)
05924                 case '\n':
05925                 {
05926                     result[pos + 1] = 'n';
05927                     pos += 2;
05928                     break;
05929                 }
05930 
05931                 // carriage return (0x0d)
05932                 case '\r':
05933                 {
05934                     result[pos + 1] = 'r';
05935                     pos += 2;
05936                     break;
05937                 }
05938 
05939                 // horizontal tab (0x09)
05940                 case '\t':
05941                 {
05942                     result[pos + 1] = 't';
05943                     pos += 2;
05944                     break;
05945                 }
05946 
05947                 default:
05948                 {
05949                     if (c >= 0x00 and c <= 0x1f)
05950                     {
05951                         // convert a number 0..15 to its hex representation
05952                         // (0..f)
05953                         const auto hexify = [](const int v) -> char
05954                         {
05955                             return (v < 10)
05956                             ? ('0' + static_cast<char>(v))
05957                             : ('a' + static_cast<char>((v - 10) & 0x1f));
05958                         };
05959 
05960                         // print character c as \uxxxx
05961                         for (const char m :
05962                     { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
05963                         })
05964                         {
05965                             result[++pos] = m;
05966                         }
05967 
05968                         ++pos;
05969                     }
05970                     else
05971                     {
05972                         // all other characters are added as-is
05973                         result[pos++] = c;
05974                     }
05975                     break;
05976                 }
05977             }
05978         }
05979 
05980         return result;
05981     }
05982 
06000     void dump(std::ostream& o,
06001               const bool pretty_print,
06002               const unsigned int indent_step,
06003               const unsigned int current_indent = 0) const
06004     {
06005         // variable to hold indentation for recursive calls
06006         unsigned int new_indent = current_indent;
06007 
06008         switch (m_type)
06009         {
06010             case value_t::object:
06011             {
06012                 assert(m_value.object != nullptr);
06013 
06014                 if (m_value.object->empty())
06015                 {
06016                     o << "{}";
06017                     return;
06018                 }
06019 
06020                 o << "{";
06021 
06022                 // increase indentation
06023                 if (pretty_print)
06024                 {
06025                     new_indent += indent_step;
06026                     o << "\n";
06027                 }
06028 
06029                 for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
06030                 {
06031                     if (i != m_value.object->cbegin())
06032                     {
06033                         o << (pretty_print ? ",\n" : ",");
06034                     }
06035                     o << string_t(new_indent, ' ') << "\""
06036                       << escape_string(i->first) << "\":"
06037                       << (pretty_print ? " " : "");
06038                     i->second.dump(o, pretty_print, indent_step, new_indent);
06039                 }
06040 
06041                 // decrease indentation
06042                 if (pretty_print)
06043                 {
06044                     new_indent -= indent_step;
06045                     o << "\n";
06046                 }
06047 
06048                 o << string_t(new_indent, ' ') + "}";
06049                 return;
06050             }
06051 
06052             case value_t::array:
06053             {
06054                 assert(m_value.array != nullptr);
06055 
06056                 if (m_value.array->empty())
06057                 {
06058                     o << "[]";
06059                     return;
06060                 }
06061 
06062                 o << "[";
06063 
06064                 // increase indentation
06065                 if (pretty_print)
06066                 {
06067                     new_indent += indent_step;
06068                     o << "\n";
06069                 }
06070 
06071                 for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
06072                 {
06073                     if (i != m_value.array->cbegin())
06074                     {
06075                         o << (pretty_print ? ",\n" : ",");
06076                     }
06077                     o << string_t(new_indent, ' ');
06078                     i->dump(o, pretty_print, indent_step, new_indent);
06079                 }
06080 
06081                 // decrease indentation
06082                 if (pretty_print)
06083                 {
06084                     new_indent -= indent_step;
06085                     o << "\n";
06086                 }
06087 
06088                 o << string_t(new_indent, ' ') << "]";
06089                 return;
06090             }
06091 
06092             case value_t::string:
06093             {
06094                 assert(m_value.string != nullptr);
06095                 o << string_t("\"") << escape_string(*m_value.string) << "\"";
06096                 return;
06097             }
06098 
06099             case value_t::boolean:
06100             {
06101                 o << (m_value.boolean ? "true" : "false");
06102                 return;
06103             }
06104 
06105             case value_t::number_integer:
06106             {
06107                 o << m_value.number_integer;
06108                 return;
06109             }
06110 
06111             case value_t::number_unsigned:
06112             {
06113                 o << m_value.number_unsigned;
06114                 return;
06115             }
06116 
06117             case value_t::number_float:
06118             {
06119                 if (m_value.number_float == 0)
06120                 {
06121                     // special case for zero to get "0.0"/"-0.0"
06122                     o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
06123                 }
06124                 else
06125                 {
06126                     // Otherwise 6, 15 or 16 digits of precision allows
06127                     // round-trip IEEE 754 string->float->string,
06128                     // string->double->string or string->long
06129                     // double->string; to be safe, we read this value from
06130                     // std::numeric_limits<number_float_t>::digits10
06131                     std::stringstream ss;
06132                     ss.imbue(std::locale(std::locale(), new DecimalSeparator));  // fix locale problems
06133                     ss << std::setprecision(std::numeric_limits<double>::digits10)
06134                        << m_value.number_float;
06135                     o << ss.str();
06136                 }
06137                 return;
06138             }
06139 
06140             case value_t::discarded:
06141             {
06142                 o << "<discarded>";
06143                 return;
06144             }
06145 
06146             case value_t::null:
06147             {
06148                 o << "null";
06149                 return;
06150             }
06151         }
06152     }
06153 
06154   private:
06156     // member variables //
06158 
06160     value_t m_type = value_t::null;
06161 
06163     json_value m_value = {};
06164 
06165 
06166   private:
06168     // iterators //
06170 
06180     class primitive_iterator_t
06181     {
06182       public:
06184         void set_begin() noexcept
06185         {
06186             m_it = begin_value;
06187         }
06188 
06190         void set_end() noexcept
06191         {
06192             m_it = end_value;
06193         }
06194 
06196         constexpr bool is_begin() const noexcept
06197         {
06198             return (m_it == begin_value);
06199         }
06200 
06202         constexpr bool is_end() const noexcept
06203         {
06204             return (m_it == end_value);
06205         }
06206 
06208         operator difference_type& () noexcept
06209         {
06210             return m_it;
06211         }
06212 
06214         constexpr operator difference_type () const noexcept
06215         {
06216             return m_it;
06217         }
06218 
06219       private:
06220         static constexpr difference_type begin_value = 0;
06221         static constexpr difference_type end_value = begin_value + 1;
06222 
06224         difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
06225     };
06226 
06234     struct internal_iterator
06235     {
06237         typename object_t::iterator object_iterator;
06239         typename array_t::iterator array_iterator;
06241         primitive_iterator_t primitive_iterator;
06242 
06244         internal_iterator() noexcept
06245             : object_iterator(), array_iterator(), primitive_iterator()
06246         {}
06247     };
06248 
06250     template<typename IteratorType>
06251     class iteration_proxy
06252     {
06253       private:
06255         class iteration_proxy_internal
06256         {
06257           private:
06259             IteratorType anchor;
06261             size_t array_index = 0;
06262 
06263           public:
06264             explicit iteration_proxy_internal(IteratorType it) noexcept
06265                 : anchor(it)
06266             {}
06267 
06269             iteration_proxy_internal& operator*()
06270             {
06271                 return *this;
06272             }
06273 
06275             iteration_proxy_internal& operator++()
06276             {
06277                 ++anchor;
06278                 ++array_index;
06279 
06280                 return *this;
06281             }
06282 
06284             bool operator!= (const iteration_proxy_internal& o) const
06285             {
06286                 return anchor != o.anchor;
06287             }
06288 
06290             typename basic_json::string_t key() const
06291             {
06292                 assert(anchor.m_object != nullptr);
06293 
06294                 switch (anchor.m_object->type())
06295                 {
06296                     // use integer array index as key
06297                     case value_t::array:
06298                     {
06299                         return std::to_string(array_index);
06300                     }
06301 
06302                     // use key from the object
06303                     case value_t::object:
06304                     {
06305                         return anchor.key();
06306                     }
06307 
06308                     // use an empty key for all primitive types
06309                     default:
06310                     {
06311                         return "";
06312                     }
06313                 }
06314             }
06315 
06317             typename IteratorType::reference value() const
06318             {
06319                 return anchor.value();
06320             }
06321         };
06322 
06324         typename IteratorType::reference container;
06325 
06326       public:
06328         explicit iteration_proxy(typename IteratorType::reference cont)
06329             : container(cont)
06330         {}
06331 
06333         iteration_proxy_internal begin() noexcept
06334         {
06335             return iteration_proxy_internal(container.begin());
06336         }
06337 
06339         iteration_proxy_internal end() noexcept
06340         {
06341             return iteration_proxy_internal(container.end());
06342         }
06343     };
06344 
06345   public:
06359     class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
06360     {
06362         friend class basic_json;
06363 
06364       public:
06366         using value_type = typename basic_json::value_type;
06368         using difference_type = typename basic_json::difference_type;
06370         using pointer = typename basic_json::const_pointer;
06372         using reference = typename basic_json::const_reference;
06374         using iterator_category = std::bidirectional_iterator_tag;
06375 
06377         const_iterator() = default;
06378 
06380         explicit const_iterator(pointer object) noexcept
06381             : m_object(object)
06382         {
06383             assert(m_object != nullptr);
06384 
06385             switch (m_object->m_type)
06386             {
06387                 case basic_json::value_t::object:
06388                 {
06389                     m_it.object_iterator = typename object_t::iterator();
06390                     break;
06391                 }
06392 
06393                 case basic_json::value_t::array:
06394                 {
06395                     m_it.array_iterator = typename array_t::iterator();
06396                     break;
06397                 }
06398 
06399                 default:
06400                 {
06401                     m_it.primitive_iterator = primitive_iterator_t();
06402                     break;
06403                 }
06404             }
06405         }
06406 
06408         explicit const_iterator(const iterator& other) noexcept
06409             : m_object(other.m_object)
06410         {
06411             assert(m_object != nullptr);
06412 
06413             switch (m_object->m_type)
06414             {
06415                 case basic_json::value_t::object:
06416                 {
06417                     m_it.object_iterator = other.m_it.object_iterator;
06418                     break;
06419                 }
06420 
06421                 case basic_json::value_t::array:
06422                 {
06423                     m_it.array_iterator = other.m_it.array_iterator;
06424                     break;
06425                 }
06426 
06427                 default:
06428                 {
06429                     m_it.primitive_iterator = other.m_it.primitive_iterator;
06430                     break;
06431                 }
06432             }
06433         }
06434 
06436         const_iterator(const const_iterator& other) noexcept
06437             : m_object(other.m_object), m_it(other.m_it)
06438         {}
06439 
06441         const_iterator& operator=(const_iterator other) noexcept(
06442             std::is_nothrow_move_constructible<pointer>::value and
06443             std::is_nothrow_move_assignable<pointer>::value and
06444             std::is_nothrow_move_constructible<internal_iterator>::value and
06445             std::is_nothrow_move_assignable<internal_iterator>::value
06446         )
06447         {
06448             std::swap(m_object, other.m_object);
06449             std::swap(m_it, other.m_it);
06450             return *this;
06451         }
06452 
06453       private:
06455         void set_begin() noexcept
06456         {
06457             assert(m_object != nullptr);
06458 
06459             switch (m_object->m_type)
06460             {
06461                 case basic_json::value_t::object:
06462                 {
06463                     assert(m_object->m_value.object != nullptr);
06464                     m_it.object_iterator = m_object->m_value.object->begin();
06465                     break;
06466                 }
06467 
06468                 case basic_json::value_t::array:
06469                 {
06470                     assert(m_object->m_value.array != nullptr);
06471                     m_it.array_iterator = m_object->m_value.array->begin();
06472                     break;
06473                 }
06474 
06475                 case basic_json::value_t::null:
06476                 {
06477                     // set to end so begin()==end() is true: null is empty
06478                     m_it.primitive_iterator.set_end();
06479                     break;
06480                 }
06481 
06482                 default:
06483                 {
06484                     m_it.primitive_iterator.set_begin();
06485                     break;
06486                 }
06487             }
06488         }
06489 
06491         void set_end() noexcept
06492         {
06493             assert(m_object != nullptr);
06494 
06495             switch (m_object->m_type)
06496             {
06497                 case basic_json::value_t::object:
06498                 {
06499                     assert(m_object->m_value.object != nullptr);
06500                     m_it.object_iterator = m_object->m_value.object->end();
06501                     break;
06502                 }
06503 
06504                 case basic_json::value_t::array:
06505                 {
06506                     assert(m_object->m_value.array != nullptr);
06507                     m_it.array_iterator = m_object->m_value.array->end();
06508                     break;
06509                 }
06510 
06511                 default:
06512                 {
06513                     m_it.primitive_iterator.set_end();
06514                     break;
06515                 }
06516             }
06517         }
06518 
06519       public:
06521         reference operator*() const
06522         {
06523             assert(m_object != nullptr);
06524 
06525             switch (m_object->m_type)
06526             {
06527                 case basic_json::value_t::object:
06528                 {
06529                     assert(m_object->m_value.object);
06530                     assert(m_it.object_iterator != m_object->m_value.object->end());
06531                     return m_it.object_iterator->second;
06532                 }
06533 
06534                 case basic_json::value_t::array:
06535                 {
06536                     assert(m_object->m_value.array);
06537                     assert(m_it.array_iterator != m_object->m_value.array->end());
06538                     return *m_it.array_iterator;
06539                 }
06540 
06541                 case basic_json::value_t::null:
06542                 {
06543                     throw std::out_of_range("cannot get value");
06544                 }
06545 
06546                 default:
06547                 {
06548                     if (m_it.primitive_iterator.is_begin())
06549                     {
06550                         return *m_object;
06551                     }
06552                     else
06553                     {
06554                         throw std::out_of_range("cannot get value");
06555                     }
06556                 }
06557             }
06558         }
06559 
06561         pointer operator->() const
06562         {
06563             assert(m_object != nullptr);
06564 
06565             switch (m_object->m_type)
06566             {
06567                 case basic_json::value_t::object:
06568                 {
06569                     assert(m_object->m_value.object);
06570                     assert(m_it.object_iterator != m_object->m_value.object->end());
06571                     return &(m_it.object_iterator->second);
06572                 }
06573 
06574                 case basic_json::value_t::array:
06575                 {
06576                     assert(m_object->m_value.array);
06577                     assert(m_it.array_iterator != m_object->m_value.array->end());
06578                     return &*m_it.array_iterator;
06579                 }
06580 
06581                 default:
06582                 {
06583                     if (m_it.primitive_iterator.is_begin())
06584                     {
06585                         return m_object;
06586                     }
06587                     else
06588                     {
06589                         throw std::out_of_range("cannot get value");
06590                     }
06591                 }
06592             }
06593         }
06594 
06596         const_iterator operator++(int)
06597         {
06598             auto result = *this;
06599             ++(*this);
06600             return result;
06601         }
06602 
06604         const_iterator& operator++()
06605         {
06606             assert(m_object != nullptr);
06607 
06608             switch (m_object->m_type)
06609             {
06610                 case basic_json::value_t::object:
06611                 {
06612                     ++m_it.object_iterator;
06613                     break;
06614                 }
06615 
06616                 case basic_json::value_t::array:
06617                 {
06618                     ++m_it.array_iterator;
06619                     break;
06620                 }
06621 
06622                 default:
06623                 {
06624                     ++m_it.primitive_iterator;
06625                     break;
06626                 }
06627             }
06628 
06629             return *this;
06630         }
06631 
06633         const_iterator operator--(int)
06634         {
06635             auto result = *this;
06636             --(*this);
06637             return result;
06638         }
06639 
06641         const_iterator& operator--()
06642         {
06643             assert(m_object != nullptr);
06644 
06645             switch (m_object->m_type)
06646             {
06647                 case basic_json::value_t::object:
06648                 {
06649                     --m_it.object_iterator;
06650                     break;
06651                 }
06652 
06653                 case basic_json::value_t::array:
06654                 {
06655                     --m_it.array_iterator;
06656                     break;
06657                 }
06658 
06659                 default:
06660                 {
06661                     --m_it.primitive_iterator;
06662                     break;
06663                 }
06664             }
06665 
06666             return *this;
06667         }
06668 
06670         bool operator==(const const_iterator& other) const
06671         {
06672             // if objects are not the same, the comparison is undefined
06673             if (m_object != other.m_object)
06674             {
06675                 throw std::domain_error("cannot compare iterators of different containers");
06676             }
06677 
06678             assert(m_object != nullptr);
06679 
06680             switch (m_object->m_type)
06681             {
06682                 case basic_json::value_t::object:
06683                 {
06684                     return (m_it.object_iterator == other.m_it.object_iterator);
06685                 }
06686 
06687                 case basic_json::value_t::array:
06688                 {
06689                     return (m_it.array_iterator == other.m_it.array_iterator);
06690                 }
06691 
06692                 default:
06693                 {
06694                     return (m_it.primitive_iterator == other.m_it.primitive_iterator);
06695                 }
06696             }
06697         }
06698 
06700         bool operator!=(const const_iterator& other) const
06701         {
06702             return not operator==(other);
06703         }
06704 
06706         bool operator<(const const_iterator& other) const
06707         {
06708             // if objects are not the same, the comparison is undefined
06709             if (m_object != other.m_object)
06710             {
06711                 throw std::domain_error("cannot compare iterators of different containers");
06712             }
06713 
06714             assert(m_object != nullptr);
06715 
06716             switch (m_object->m_type)
06717             {
06718                 case basic_json::value_t::object:
06719                 {
06720                     throw std::domain_error("cannot compare order of object iterators");
06721                 }
06722 
06723                 case basic_json::value_t::array:
06724                 {
06725                     return (m_it.array_iterator < other.m_it.array_iterator);
06726                 }
06727 
06728                 default:
06729                 {
06730                     return (m_it.primitive_iterator < other.m_it.primitive_iterator);
06731                 }
06732             }
06733         }
06734 
06736         bool operator<=(const const_iterator& other) const
06737         {
06738             return not other.operator < (*this);
06739         }
06740 
06742         bool operator>(const const_iterator& other) const
06743         {
06744             return not operator<=(other);
06745         }
06746 
06748         bool operator>=(const const_iterator& other) const
06749         {
06750             return not operator<(other);
06751         }
06752 
06754         const_iterator& operator+=(difference_type i)
06755         {
06756             assert(m_object != nullptr);
06757 
06758             switch (m_object->m_type)
06759             {
06760                 case basic_json::value_t::object:
06761                 {
06762                     throw std::domain_error("cannot use offsets with object iterators");
06763                 }
06764 
06765                 case basic_json::value_t::array:
06766                 {
06767                     m_it.array_iterator += i;
06768                     break;
06769                 }
06770 
06771                 default:
06772                 {
06773                     m_it.primitive_iterator += i;
06774                     break;
06775                 }
06776             }
06777 
06778             return *this;
06779         }
06780 
06782         const_iterator& operator-=(difference_type i)
06783         {
06784             return operator+=(-i);
06785         }
06786 
06788         const_iterator operator+(difference_type i)
06789         {
06790             auto result = *this;
06791             result += i;
06792             return result;
06793         }
06794 
06796         const_iterator operator-(difference_type i)
06797         {
06798             auto result = *this;
06799             result -= i;
06800             return result;
06801         }
06802 
06804         difference_type operator-(const const_iterator& other) const
06805         {
06806             assert(m_object != nullptr);
06807 
06808             switch (m_object->m_type)
06809             {
06810                 case basic_json::value_t::object:
06811                 {
06812                     throw std::domain_error("cannot use offsets with object iterators");
06813                 }
06814 
06815                 case basic_json::value_t::array:
06816                 {
06817                     return m_it.array_iterator - other.m_it.array_iterator;
06818                 }
06819 
06820                 default:
06821                 {
06822                     return m_it.primitive_iterator - other.m_it.primitive_iterator;
06823                 }
06824             }
06825         }
06826 
06828         reference operator[](difference_type n) const
06829         {
06830             assert(m_object != nullptr);
06831 
06832             switch (m_object->m_type)
06833             {
06834                 case basic_json::value_t::object:
06835                 {
06836                     throw std::domain_error("cannot use operator[] for object iterators");
06837                 }
06838 
06839                 case basic_json::value_t::array:
06840                 {
06841                     return *(m_it.array_iterator + n);
06842                 }
06843 
06844                 case basic_json::value_t::null:
06845                 {
06846                     throw std::out_of_range("cannot get value");
06847                 }
06848 
06849                 default:
06850                 {
06851                     if (m_it.primitive_iterator == -n)
06852                     {
06853                         return *m_object;
06854                     }
06855                     else
06856                     {
06857                         throw std::out_of_range("cannot get value");
06858                     }
06859                 }
06860             }
06861         }
06862 
06864         typename object_t::key_type key() const
06865         {
06866             assert(m_object != nullptr);
06867 
06868             if (m_object->is_object())
06869             {
06870                 return m_it.object_iterator->first;
06871             }
06872             else
06873             {
06874                 throw std::domain_error("cannot use key() for non-object iterators");
06875             }
06876         }
06877 
06879         reference value() const
06880         {
06881             return operator*();
06882         }
06883 
06884       private:
06886         pointer m_object = nullptr;
06888         internal_iterator m_it = internal_iterator();
06889     };
06890 
06903     class iterator : public const_iterator
06904     {
06905       public:
06906         using base_iterator = const_iterator;
06907         using pointer = typename basic_json::pointer;
06908         using reference = typename basic_json::reference;
06909 
06911         iterator() = default;
06912 
06914         explicit iterator(pointer object) noexcept
06915             : base_iterator(object)
06916         {}
06917 
06919         iterator(const iterator& other) noexcept
06920             : base_iterator(other)
06921         {}
06922 
06924         iterator& operator=(iterator other) noexcept(
06925             std::is_nothrow_move_constructible<pointer>::value and
06926             std::is_nothrow_move_assignable<pointer>::value and
06927             std::is_nothrow_move_constructible<internal_iterator>::value and
06928             std::is_nothrow_move_assignable<internal_iterator>::value
06929         )
06930         {
06931             base_iterator::operator=(other);
06932             return *this;
06933         }
06934 
06936         reference operator*() const
06937         {
06938             return const_cast<reference>(base_iterator::operator*());
06939         }
06940 
06942         pointer operator->() const
06943         {
06944             return const_cast<pointer>(base_iterator::operator->());
06945         }
06946 
06948         iterator operator++(int)
06949         {
06950             iterator result = *this;
06951             base_iterator::operator++();
06952             return result;
06953         }
06954 
06956         iterator& operator++()
06957         {
06958             base_iterator::operator++();
06959             return *this;
06960         }
06961 
06963         iterator operator--(int)
06964         {
06965             iterator result = *this;
06966             base_iterator::operator--();
06967             return result;
06968         }
06969 
06971         iterator& operator--()
06972         {
06973             base_iterator::operator--();
06974             return *this;
06975         }
06976 
06978         iterator& operator+=(difference_type i)
06979         {
06980             base_iterator::operator+=(i);
06981             return *this;
06982         }
06983 
06985         iterator& operator-=(difference_type i)
06986         {
06987             base_iterator::operator-=(i);
06988             return *this;
06989         }
06990 
06992         iterator operator+(difference_type i)
06993         {
06994             auto result = *this;
06995             result += i;
06996             return result;
06997         }
06998 
07000         iterator operator-(difference_type i)
07001         {
07002             auto result = *this;
07003             result -= i;
07004             return result;
07005         }
07006 
07008         difference_type operator-(const iterator& other) const
07009         {
07010             return base_iterator::operator-(other);
07011         }
07012 
07014         reference operator[](difference_type n) const
07015         {
07016             return const_cast<reference>(base_iterator::operator[](n));
07017         }
07018 
07020         reference value() const
07021         {
07022             return const_cast<reference>(base_iterator::value());
07023         }
07024     };
07025 
07043     template<typename Base>
07044     class json_reverse_iterator : public std::reverse_iterator<Base>
07045     {
07046       public:
07048         using base_iterator = std::reverse_iterator<Base>;
07050         using reference = typename Base::reference;
07051 
07053         json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
07054             : base_iterator(it)
07055         {}
07056 
07058         json_reverse_iterator(const base_iterator& it) noexcept
07059             : base_iterator(it)
07060         {}
07061 
07063         json_reverse_iterator operator++(int)
07064         {
07065             return base_iterator::operator++(1);
07066         }
07067 
07069         json_reverse_iterator& operator++()
07070         {
07071             base_iterator::operator++();
07072             return *this;
07073         }
07074 
07076         json_reverse_iterator operator--(int)
07077         {
07078             return base_iterator::operator--(1);
07079         }
07080 
07082         json_reverse_iterator& operator--()
07083         {
07084             base_iterator::operator--();
07085             return *this;
07086         }
07087 
07089         json_reverse_iterator& operator+=(difference_type i)
07090         {
07091             base_iterator::operator+=(i);
07092             return *this;
07093         }
07094 
07096         json_reverse_iterator operator+(difference_type i) const
07097         {
07098             auto result = *this;
07099             result += i;
07100             return result;
07101         }
07102 
07104         json_reverse_iterator operator-(difference_type i) const
07105         {
07106             auto result = *this;
07107             result -= i;
07108             return result;
07109         }
07110 
07112         difference_type operator-(const json_reverse_iterator& other) const
07113         {
07114             return this->base() - other.base();
07115         }
07116 
07118         reference operator[](difference_type n) const
07119         {
07120             return *(this->operator+(n));
07121         }
07122 
07124         typename object_t::key_type key() const
07125         {
07126             auto it = --this->base();
07127             return it.key();
07128         }
07129 
07131         reference value() const
07132         {
07133             auto it = --this->base();
07134             return it.operator * ();
07135         }
07136     };
07137 
07138 
07139   private:
07141     // lexer and parser //
07143 
07151     class lexer
07152     {
07153       public:
07155         enum class token_type
07156         {
07157             uninitialized,   
07158             literal_true,    
07159             literal_false,   
07160             literal_null,    
07161             value_string,    
07162             value_number,    
07163             begin_array,     
07164             begin_object,    
07165             end_array,       
07166             end_object,      
07167             name_separator,  
07168             value_separator, 
07169             parse_error,     
07170             end_of_input     
07171         };
07172 
07174         using lexer_char_t = unsigned char;
07175 
07177         explicit lexer(const string_t& s) noexcept
07178             : m_stream(nullptr), m_buffer(s)
07179         {
07180             m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
07181             assert(m_content != nullptr);
07182             m_start = m_cursor = m_content;
07183             m_limit = m_content + s.size();
07184         }
07185 
07187         explicit lexer(std::istream* s) noexcept
07188             : m_stream(s), m_buffer()
07189         {
07190             assert(m_stream != nullptr);
07191             getline(*m_stream, m_buffer);
07192             m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
07193             assert(m_content != nullptr);
07194             m_start = m_cursor = m_content;
07195             m_limit = m_content + m_buffer.size();
07196         }
07197 
07199         lexer() = default;
07200 
07201         // switch off unwanted functions
07202         lexer(const lexer&) = delete;
07203         lexer operator=(const lexer&) = delete;
07204 
07220         static string_t to_unicode(const std::size_t codepoint1,
07221                                    const std::size_t codepoint2 = 0)
07222         {
07223             // calculate the codepoint from the given code points
07224             std::size_t codepoint = codepoint1;
07225 
07226             // check if codepoint1 is a high surrogate
07227             if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
07228             {
07229                 // check if codepoint2 is a low surrogate
07230                 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
07231                 {
07232                     codepoint =
07233                         // high surrogate occupies the most significant 22 bits
07234                         (codepoint1 << 10)
07235                         // low surrogate occupies the least significant 15 bits
07236                         + codepoint2
07237                         // there is still the 0xD800, 0xDC00 and 0x10000 noise
07238                         // in the result so we have to subtract with:
07239                         // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
07240                         - 0x35FDC00;
07241                 }
07242                 else
07243                 {
07244                     throw std::invalid_argument("missing or wrong low surrogate");
07245                 }
07246             }
07247 
07248             string_t result;
07249 
07250             if (codepoint < 0x80)
07251             {
07252                 // 1-byte characters: 0xxxxxxx (ASCII)
07253                 result.append(1, static_cast<typename string_t::value_type>(codepoint));
07254             }
07255             else if (codepoint <= 0x7ff)
07256             {
07257                 // 2-byte characters: 110xxxxx 10xxxxxx
07258                 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
07259                 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
07260             }
07261             else if (codepoint <= 0xffff)
07262             {
07263                 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
07264                 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
07265                 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
07266                 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
07267             }
07268             else if (codepoint <= 0x10ffff)
07269             {
07270                 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
07271                 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
07272                 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
07273                 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
07274                 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
07275             }
07276             else
07277             {
07278                 throw std::out_of_range("code points above 0x10FFFF are invalid");
07279             }
07280 
07281             return result;
07282         }
07283 
07285         static std::string token_type_name(token_type t)
07286         {
07287             switch (t)
07288             {
07289                 case token_type::uninitialized:
07290                     return "<uninitialized>";
07291                 case token_type::literal_true:
07292                     return "true literal";
07293                 case token_type::literal_false:
07294                     return "false literal";
07295                 case token_type::literal_null:
07296                     return "null literal";
07297                 case token_type::value_string:
07298                     return "string literal";
07299                 case token_type::value_number:
07300                     return "number literal";
07301                 case token_type::begin_array:
07302                     return "'['";
07303                 case token_type::begin_object:
07304                     return "'{'";
07305                 case token_type::end_array:
07306                     return "']'";
07307                 case token_type::end_object:
07308                     return "'}'";
07309                 case token_type::name_separator:
07310                     return "':'";
07311                 case token_type::value_separator:
07312                     return "','";
07313                 case token_type::parse_error:
07314                     return "<parse error>";
07315                 case token_type::end_of_input:
07316                     return "end of input";
07317                 default:
07318                 {
07319                     // catch non-enum values
07320                     return "unknown token"; // LCOV_EXCL_LINE
07321                 }
07322             }
07323         }
07324 
07335         token_type scan() noexcept
07336         {
07337             // pointer for backtracking information
07338             m_marker = nullptr;
07339 
07340             // remember the begin of the token
07341             m_start = m_cursor;
07342             assert(m_start != nullptr);
07343 
07344 
07345             {
07346                 lexer_char_t yych;
07347                 unsigned int yyaccept = 0;
07348                 static const unsigned char yybm[] =
07349                 {
07350                     0,   0,   0,   0,   0,   0,   0,   0,
07351                     0,  32,  32,   0,   0,  32,   0,   0,
07352                     128, 128, 128, 128, 128, 128, 128, 128,
07353                     128, 128, 128, 128, 128, 128, 128, 128,
07354                     160, 128,   0, 128, 128, 128, 128, 128,
07355                     128, 128, 128, 128, 128, 128, 128, 128,
07356                     192, 192, 192, 192, 192, 192, 192, 192,
07357                     192, 192, 128, 128, 128, 128, 128, 128,
07358                     128, 128, 128, 128, 128, 128, 128, 128,
07359                     128, 128, 128, 128, 128, 128, 128, 128,
07360                     128, 128, 128, 128, 128, 128, 128, 128,
07361                     128, 128, 128, 128,   0, 128, 128, 128,
07362                     128, 128, 128, 128, 128, 128, 128, 128,
07363                     128, 128, 128, 128, 128, 128, 128, 128,
07364                     128, 128, 128, 128, 128, 128, 128, 128,
07365                     128, 128, 128, 128, 128, 128, 128, 128,
07366                     128, 128, 128, 128, 128, 128, 128, 128,
07367                     128, 128, 128, 128, 128, 128, 128, 128,
07368                     128, 128, 128, 128, 128, 128, 128, 128,
07369                     128, 128, 128, 128, 128, 128, 128, 128,
07370                     128, 128, 128, 128, 128, 128, 128, 128,
07371                     128, 128, 128, 128, 128, 128, 128, 128,
07372                     128, 128, 128, 128, 128, 128, 128, 128,
07373                     128, 128, 128, 128, 128, 128, 128, 128,
07374                     128, 128, 128, 128, 128, 128, 128, 128,
07375                     128, 128, 128, 128, 128, 128, 128, 128,
07376                     128, 128, 128, 128, 128, 128, 128, 128,
07377                     128, 128, 128, 128, 128, 128, 128, 128,
07378                     128, 128, 128, 128, 128, 128, 128, 128,
07379                     128, 128, 128, 128, 128, 128, 128, 128,
07380                     128, 128, 128, 128, 128, 128, 128, 128,
07381                     128, 128, 128, 128, 128, 128, 128, 128,
07382                 };
07383                 if ((m_limit - m_cursor) < 5)
07384                 {
07385                     yyfill();    // LCOV_EXCL_LINE;
07386                 }
07387                 yych = *m_cursor;
07388                 if (yybm[0 + yych] & 32)
07389                 {
07390                     goto basic_json_parser_6;
07391                 }
07392                 if (yych <= '\\')
07393                 {
07394                     if (yych <= '-')
07395                     {
07396                         if (yych <= '"')
07397                         {
07398                             if (yych <= 0x00)
07399                             {
07400                                 goto basic_json_parser_2;
07401                             }
07402                             if (yych <= '!')
07403                             {
07404                                 goto basic_json_parser_4;
07405                             }
07406                             goto basic_json_parser_9;
07407                         }
07408                         else
07409                         {
07410                             if (yych <= '+')
07411                             {
07412                                 goto basic_json_parser_4;
07413                             }
07414                             if (yych <= ',')
07415                             {
07416                                 goto basic_json_parser_10;
07417                             }
07418                             goto basic_json_parser_12;
07419                         }
07420                     }
07421                     else
07422                     {
07423                         if (yych <= '9')
07424                         {
07425                             if (yych <= '/')
07426                             {
07427                                 goto basic_json_parser_4;
07428                             }
07429                             if (yych <= '0')
07430                             {
07431                                 goto basic_json_parser_13;
07432                             }
07433                             goto basic_json_parser_15;
07434                         }
07435                         else
07436                         {
07437                             if (yych <= ':')
07438                             {
07439                                 goto basic_json_parser_17;
07440                             }
07441                             if (yych == '[')
07442                             {
07443                                 goto basic_json_parser_19;
07444                             }
07445                             goto basic_json_parser_4;
07446                         }
07447                     }
07448                 }
07449                 else
07450                 {
07451                     if (yych <= 't')
07452                     {
07453                         if (yych <= 'f')
07454                         {
07455                             if (yych <= ']')
07456                             {
07457                                 goto basic_json_parser_21;
07458                             }
07459                             if (yych <= 'e')
07460                             {
07461                                 goto basic_json_parser_4;
07462                             }
07463                             goto basic_json_parser_23;
07464                         }
07465                         else
07466                         {
07467                             if (yych == 'n')
07468                             {
07469                                 goto basic_json_parser_24;
07470                             }
07471                             if (yych <= 's')
07472                             {
07473                                 goto basic_json_parser_4;
07474                             }
07475                             goto basic_json_parser_25;
07476                         }
07477                     }
07478                     else
07479                     {
07480                         if (yych <= '|')
07481                         {
07482                             if (yych == '{')
07483                             {
07484                                 goto basic_json_parser_26;
07485                             }
07486                             goto basic_json_parser_4;
07487                         }
07488                         else
07489                         {
07490                             if (yych <= '}')
07491                             {
07492                                 goto basic_json_parser_28;
07493                             }
07494                             if (yych == 0xEF)
07495                             {
07496                                 goto basic_json_parser_30;
07497                             }
07498                             goto basic_json_parser_4;
07499                         }
07500                     }
07501                 }
07502 basic_json_parser_2:
07503                 ++m_cursor;
07504                 {
07505                     return token_type::end_of_input;
07506                 }
07507 basic_json_parser_4:
07508                 ++m_cursor;
07509 basic_json_parser_5:
07510                 {
07511                     return token_type::parse_error;
07512                 }
07513 basic_json_parser_6:
07514                 ++m_cursor;
07515                 if (m_limit <= m_cursor)
07516                 {
07517                     yyfill();    // LCOV_EXCL_LINE;
07518                 }
07519                 yych = *m_cursor;
07520                 if (yybm[0 + yych] & 32)
07521                 {
07522                     goto basic_json_parser_6;
07523                 }
07524                 {
07525                     return scan();
07526                 }
07527 basic_json_parser_9:
07528                 yyaccept = 0;
07529                 yych = *(m_marker = ++m_cursor);
07530                 if (yych <= 0x0F)
07531                 {
07532                     goto basic_json_parser_5;
07533                 }
07534                 goto basic_json_parser_32;
07535 basic_json_parser_10:
07536                 ++m_cursor;
07537                 {
07538                     return token_type::value_separator;
07539                 }
07540 basic_json_parser_12:
07541                 yych = *++m_cursor;
07542                 if (yych <= '/')
07543                 {
07544                     goto basic_json_parser_5;
07545                 }
07546                 if (yych <= '0')
07547                 {
07548                     goto basic_json_parser_13;
07549                 }
07550                 if (yych <= '9')
07551                 {
07552                     goto basic_json_parser_15;
07553                 }
07554                 goto basic_json_parser_5;
07555 basic_json_parser_13:
07556                 yyaccept = 1;
07557                 yych = *(m_marker = ++m_cursor);
07558                 if (yych <= 'D')
07559                 {
07560                     if (yych == '.')
07561                     {
07562                         goto basic_json_parser_37;
07563                     }
07564                 }
07565                 else
07566                 {
07567                     if (yych <= 'E')
07568                     {
07569                         goto basic_json_parser_38;
07570                     }
07571                     if (yych == 'e')
07572                     {
07573                         goto basic_json_parser_38;
07574                     }
07575                 }
07576 basic_json_parser_14:
07577                 {
07578                     return token_type::value_number;
07579                 }
07580 basic_json_parser_15:
07581                 yyaccept = 1;
07582                 m_marker = ++m_cursor;
07583                 if ((m_limit - m_cursor) < 3)
07584                 {
07585                     yyfill();    // LCOV_EXCL_LINE;
07586                 }
07587                 yych = *m_cursor;
07588                 if (yybm[0 + yych] & 64)
07589                 {
07590                     goto basic_json_parser_15;
07591                 }
07592                 if (yych <= 'D')
07593                 {
07594                     if (yych == '.')
07595                     {
07596                         goto basic_json_parser_37;
07597                     }
07598                     goto basic_json_parser_14;
07599                 }
07600                 else
07601                 {
07602                     if (yych <= 'E')
07603                     {
07604                         goto basic_json_parser_38;
07605                     }
07606                     if (yych == 'e')
07607                     {
07608                         goto basic_json_parser_38;
07609                     }
07610                     goto basic_json_parser_14;
07611                 }
07612 basic_json_parser_17:
07613                 ++m_cursor;
07614                 {
07615                     return token_type::name_separator;
07616                 }
07617 basic_json_parser_19:
07618                 ++m_cursor;
07619                 {
07620                     return token_type::begin_array;
07621                 }
07622 basic_json_parser_21:
07623                 ++m_cursor;
07624                 {
07625                     return token_type::end_array;
07626                 }
07627 basic_json_parser_23:
07628                 yyaccept = 0;
07629                 yych = *(m_marker = ++m_cursor);
07630                 if (yych == 'a')
07631                 {
07632                     goto basic_json_parser_39;
07633                 }
07634                 goto basic_json_parser_5;
07635 basic_json_parser_24:
07636                 yyaccept = 0;
07637                 yych = *(m_marker = ++m_cursor);
07638                 if (yych == 'u')
07639                 {
07640                     goto basic_json_parser_40;
07641                 }
07642                 goto basic_json_parser_5;
07643 basic_json_parser_25:
07644                 yyaccept = 0;
07645                 yych = *(m_marker = ++m_cursor);
07646                 if (yych == 'r')
07647                 {
07648                     goto basic_json_parser_41;
07649                 }
07650                 goto basic_json_parser_5;
07651 basic_json_parser_26:
07652                 ++m_cursor;
07653                 {
07654                     return token_type::begin_object;
07655                 }
07656 basic_json_parser_28:
07657                 ++m_cursor;
07658                 {
07659                     return token_type::end_object;
07660                 }
07661 basic_json_parser_30:
07662                 yyaccept = 0;
07663                 yych = *(m_marker = ++m_cursor);
07664                 if (yych == 0xBB)
07665                 {
07666                     goto basic_json_parser_42;
07667                 }
07668                 goto basic_json_parser_5;
07669 basic_json_parser_31:
07670                 ++m_cursor;
07671                 if (m_limit <= m_cursor)
07672                 {
07673                     yyfill();    // LCOV_EXCL_LINE;
07674                 }
07675                 yych = *m_cursor;
07676 basic_json_parser_32:
07677                 if (yybm[0 + yych] & 128)
07678                 {
07679                     goto basic_json_parser_31;
07680                 }
07681                 if (yych <= 0x0F)
07682                 {
07683                     goto basic_json_parser_33;
07684                 }
07685                 if (yych <= '"')
07686                 {
07687                     goto basic_json_parser_34;
07688                 }
07689                 goto basic_json_parser_36;
07690 basic_json_parser_33:
07691                 m_cursor = m_marker;
07692                 if (yyaccept == 0)
07693                 {
07694                     goto basic_json_parser_5;
07695                 }
07696                 else
07697                 {
07698                     goto basic_json_parser_14;
07699                 }
07700 basic_json_parser_34:
07701                 ++m_cursor;
07702                 {
07703                     return token_type::value_string;
07704                 }
07705 basic_json_parser_36:
07706                 ++m_cursor;
07707                 if (m_limit <= m_cursor)
07708                 {
07709                     yyfill();    // LCOV_EXCL_LINE;
07710                 }
07711                 yych = *m_cursor;
07712                 if (yych <= 'e')
07713                 {
07714                     if (yych <= '/')
07715                     {
07716                         if (yych == '"')
07717                         {
07718                             goto basic_json_parser_31;
07719                         }
07720                         if (yych <= '.')
07721                         {
07722                             goto basic_json_parser_33;
07723                         }
07724                         goto basic_json_parser_31;
07725                     }
07726                     else
07727                     {
07728                         if (yych <= '\\')
07729                         {
07730                             if (yych <= '[')
07731                             {
07732                                 goto basic_json_parser_33;
07733                             }
07734                             goto basic_json_parser_31;
07735                         }
07736                         else
07737                         {
07738                             if (yych == 'b')
07739                             {
07740                                 goto basic_json_parser_31;
07741                             }
07742                             goto basic_json_parser_33;
07743                         }
07744                     }
07745                 }
07746                 else
07747                 {
07748                     if (yych <= 'q')
07749                     {
07750                         if (yych <= 'f')
07751                         {
07752                             goto basic_json_parser_31;
07753                         }
07754                         if (yych == 'n')
07755                         {
07756                             goto basic_json_parser_31;
07757                         }
07758                         goto basic_json_parser_33;
07759                     }
07760                     else
07761                     {
07762                         if (yych <= 's')
07763                         {
07764                             if (yych <= 'r')
07765                             {
07766                                 goto basic_json_parser_31;
07767                             }
07768                             goto basic_json_parser_33;
07769                         }
07770                         else
07771                         {
07772                             if (yych <= 't')
07773                             {
07774                                 goto basic_json_parser_31;
07775                             }
07776                             if (yych <= 'u')
07777                             {
07778                                 goto basic_json_parser_43;
07779                             }
07780                             goto basic_json_parser_33;
07781                         }
07782                     }
07783                 }
07784 basic_json_parser_37:
07785                 yych = *++m_cursor;
07786                 if (yych <= '/')
07787                 {
07788                     goto basic_json_parser_33;
07789                 }
07790                 if (yych <= '9')
07791                 {
07792                     goto basic_json_parser_44;
07793                 }
07794                 goto basic_json_parser_33;
07795 basic_json_parser_38:
07796                 yych = *++m_cursor;
07797                 if (yych <= ',')
07798                 {
07799                     if (yych == '+')
07800                     {
07801                         goto basic_json_parser_46;
07802                     }
07803                     goto basic_json_parser_33;
07804                 }
07805                 else
07806                 {
07807                     if (yych <= '-')
07808                     {
07809                         goto basic_json_parser_46;
07810                     }
07811                     if (yych <= '/')
07812                     {
07813                         goto basic_json_parser_33;
07814                     }
07815                     if (yych <= '9')
07816                     {
07817                         goto basic_json_parser_47;
07818                     }
07819                     goto basic_json_parser_33;
07820                 }
07821 basic_json_parser_39:
07822                 yych = *++m_cursor;
07823                 if (yych == 'l')
07824                 {
07825                     goto basic_json_parser_49;
07826                 }
07827                 goto basic_json_parser_33;
07828 basic_json_parser_40:
07829                 yych = *++m_cursor;
07830                 if (yych == 'l')
07831                 {
07832                     goto basic_json_parser_50;
07833                 }
07834                 goto basic_json_parser_33;
07835 basic_json_parser_41:
07836                 yych = *++m_cursor;
07837                 if (yych == 'u')
07838                 {
07839                     goto basic_json_parser_51;
07840                 }
07841                 goto basic_json_parser_33;
07842 basic_json_parser_42:
07843                 yych = *++m_cursor;
07844                 if (yych == 0xBF)
07845                 {
07846                     goto basic_json_parser_52;
07847                 }
07848                 goto basic_json_parser_33;
07849 basic_json_parser_43:
07850                 ++m_cursor;
07851                 if (m_limit <= m_cursor)
07852                 {
07853                     yyfill();    // LCOV_EXCL_LINE;
07854                 }
07855                 yych = *m_cursor;
07856                 if (yych <= '@')
07857                 {
07858                     if (yych <= '/')
07859                     {
07860                         goto basic_json_parser_33;
07861                     }
07862                     if (yych <= '9')
07863                     {
07864                         goto basic_json_parser_54;
07865                     }
07866                     goto basic_json_parser_33;
07867                 }
07868                 else
07869                 {
07870                     if (yych <= 'F')
07871                     {
07872                         goto basic_json_parser_54;
07873                     }
07874                     if (yych <= '`')
07875                     {
07876                         goto basic_json_parser_33;
07877                     }
07878                     if (yych <= 'f')
07879                     {
07880                         goto basic_json_parser_54;
07881                     }
07882                     goto basic_json_parser_33;
07883                 }
07884 basic_json_parser_44:
07885                 yyaccept = 1;
07886                 m_marker = ++m_cursor;
07887                 if ((m_limit - m_cursor) < 3)
07888                 {
07889                     yyfill();    // LCOV_EXCL_LINE;
07890                 }
07891                 yych = *m_cursor;
07892                 if (yych <= 'D')
07893                 {
07894                     if (yych <= '/')
07895                     {
07896                         goto basic_json_parser_14;
07897                     }
07898                     if (yych <= '9')
07899                     {
07900                         goto basic_json_parser_44;
07901                     }
07902                     goto basic_json_parser_14;
07903                 }
07904                 else
07905                 {
07906                     if (yych <= 'E')
07907                     {
07908                         goto basic_json_parser_38;
07909                     }
07910                     if (yych == 'e')
07911                     {
07912                         goto basic_json_parser_38;
07913                     }
07914                     goto basic_json_parser_14;
07915                 }
07916 basic_json_parser_46:
07917                 yych = *++m_cursor;
07918                 if (yych <= '/')
07919                 {
07920                     goto basic_json_parser_33;
07921                 }
07922                 if (yych >= ':')
07923                 {
07924                     goto basic_json_parser_33;
07925                 }
07926 basic_json_parser_47:
07927                 ++m_cursor;
07928                 if (m_limit <= m_cursor)
07929                 {
07930                     yyfill();    // LCOV_EXCL_LINE;
07931                 }
07932                 yych = *m_cursor;
07933                 if (yych <= '/')
07934                 {
07935                     goto basic_json_parser_14;
07936                 }
07937                 if (yych <= '9')
07938                 {
07939                     goto basic_json_parser_47;
07940                 }
07941                 goto basic_json_parser_14;
07942 basic_json_parser_49:
07943                 yych = *++m_cursor;
07944                 if (yych == 's')
07945                 {
07946                     goto basic_json_parser_55;
07947                 }
07948                 goto basic_json_parser_33;
07949 basic_json_parser_50:
07950                 yych = *++m_cursor;
07951                 if (yych == 'l')
07952                 {
07953                     goto basic_json_parser_56;
07954                 }
07955                 goto basic_json_parser_33;
07956 basic_json_parser_51:
07957                 yych = *++m_cursor;
07958                 if (yych == 'e')
07959                 {
07960                     goto basic_json_parser_58;
07961                 }
07962                 goto basic_json_parser_33;
07963 basic_json_parser_52:
07964                 ++m_cursor;
07965                 {
07966                     return scan();
07967                 }
07968 basic_json_parser_54:
07969                 ++m_cursor;
07970                 if (m_limit <= m_cursor)
07971                 {
07972                     yyfill();    // LCOV_EXCL_LINE;
07973                 }
07974                 yych = *m_cursor;
07975                 if (yych <= '@')
07976                 {
07977                     if (yych <= '/')
07978                     {
07979                         goto basic_json_parser_33;
07980                     }
07981                     if (yych <= '9')
07982                     {
07983                         goto basic_json_parser_60;
07984                     }
07985                     goto basic_json_parser_33;
07986                 }
07987                 else
07988                 {
07989                     if (yych <= 'F')
07990                     {
07991                         goto basic_json_parser_60;
07992                     }
07993                     if (yych <= '`')
07994                     {
07995                         goto basic_json_parser_33;
07996                     }
07997                     if (yych <= 'f')
07998                     {
07999                         goto basic_json_parser_60;
08000                     }
08001                     goto basic_json_parser_33;
08002                 }
08003 basic_json_parser_55:
08004                 yych = *++m_cursor;
08005                 if (yych == 'e')
08006                 {
08007                     goto basic_json_parser_61;
08008                 }
08009                 goto basic_json_parser_33;
08010 basic_json_parser_56:
08011                 ++m_cursor;
08012                 {
08013                     return token_type::literal_null;
08014                 }
08015 basic_json_parser_58:
08016                 ++m_cursor;
08017                 {
08018                     return token_type::literal_true;
08019                 }
08020 basic_json_parser_60:
08021                 ++m_cursor;
08022                 if (m_limit <= m_cursor)
08023                 {
08024                     yyfill();    // LCOV_EXCL_LINE;
08025                 }
08026                 yych = *m_cursor;
08027                 if (yych <= '@')
08028                 {
08029                     if (yych <= '/')
08030                     {
08031                         goto basic_json_parser_33;
08032                     }
08033                     if (yych <= '9')
08034                     {
08035                         goto basic_json_parser_63;
08036                     }
08037                     goto basic_json_parser_33;
08038                 }
08039                 else
08040                 {
08041                     if (yych <= 'F')
08042                     {
08043                         goto basic_json_parser_63;
08044                     }
08045                     if (yych <= '`')
08046                     {
08047                         goto basic_json_parser_33;
08048                     }
08049                     if (yych <= 'f')
08050                     {
08051                         goto basic_json_parser_63;
08052                     }
08053                     goto basic_json_parser_33;
08054                 }
08055 basic_json_parser_61:
08056                 ++m_cursor;
08057                 {
08058                     return token_type::literal_false;
08059                 }
08060 basic_json_parser_63:
08061                 ++m_cursor;
08062                 if (m_limit <= m_cursor)
08063                 {
08064                     yyfill();    // LCOV_EXCL_LINE;
08065                 }
08066                 yych = *m_cursor;
08067                 if (yych <= '@')
08068                 {
08069                     if (yych <= '/')
08070                     {
08071                         goto basic_json_parser_33;
08072                     }
08073                     if (yych <= '9')
08074                     {
08075                         goto basic_json_parser_31;
08076                     }
08077                     goto basic_json_parser_33;
08078                 }
08079                 else
08080                 {
08081                     if (yych <= 'F')
08082                     {
08083                         goto basic_json_parser_31;
08084                     }
08085                     if (yych <= '`')
08086                     {
08087                         goto basic_json_parser_33;
08088                     }
08089                     if (yych <= 'f')
08090                     {
08091                         goto basic_json_parser_31;
08092                     }
08093                     goto basic_json_parser_33;
08094                 }
08095             }
08096 
08097         }
08098 
08100         void yyfill() noexcept
08101         {
08102             if (m_stream == nullptr or not * m_stream)
08103             {
08104                 return;
08105             }
08106 
08107             const auto offset_start = m_start - m_content;
08108             const auto offset_marker = m_marker - m_start;
08109             const auto offset_cursor = m_cursor - m_start;
08110 
08111             m_buffer.erase(0, static_cast<size_t>(offset_start));
08112             std::string line;
08113             assert(m_stream != nullptr);
08114             std::getline(*m_stream, line);
08115             m_buffer += "\n" + line; // add line with newline symbol
08116 
08117             m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
08118             assert(m_content != nullptr);
08119             m_start  = m_content;
08120             m_marker = m_start + offset_marker;
08121             m_cursor = m_start + offset_cursor;
08122             m_limit  = m_start + m_buffer.size() - 1;
08123         }
08124 
08126         string_t get_token() const
08127         {
08128             assert(m_start != nullptr);
08129             return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
08130                             static_cast<size_t>(m_cursor - m_start));
08131         }
08132 
08155         string_t get_string() const
08156         {
08157             string_t result;
08158             result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
08159 
08160             // iterate the result between the quotes
08161             for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
08162             {
08163                 // process escaped characters
08164                 if (*i == '\\')
08165                 {
08166                     // read next character
08167                     ++i;
08168 
08169                     switch (*i)
08170                     {
08171                         // the default escapes
08172                         case 't':
08173                         {
08174                             result += "\t";
08175                             break;
08176                         }
08177                         case 'b':
08178                         {
08179                             result += "\b";
08180                             break;
08181                         }
08182                         case 'f':
08183                         {
08184                             result += "\f";
08185                             break;
08186                         }
08187                         case 'n':
08188                         {
08189                             result += "\n";
08190                             break;
08191                         }
08192                         case 'r':
08193                         {
08194                             result += "\r";
08195                             break;
08196                         }
08197                         case '\\':
08198                         {
08199                             result += "\\";
08200                             break;
08201                         }
08202                         case '/':
08203                         {
08204                             result += "/";
08205                             break;
08206                         }
08207                         case '"':
08208                         {
08209                             result += "\"";
08210                             break;
08211                         }
08212 
08213                         // unicode
08214                         case 'u':
08215                         {
08216                             // get code xxxx from uxxxx
08217                             auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
08218                                                           4).c_str(), nullptr, 16);
08219 
08220                             // check if codepoint is a high surrogate
08221                             if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
08222                             {
08223                                 // make sure there is a subsequent unicode
08224                                 if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
08225                                 {
08226                                     throw std::invalid_argument("missing low surrogate");
08227                                 }
08228 
08229                                 // get code yyyy from uxxxx\uyyyy
08230                                 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
08231                                                                (i + 7), 4).c_str(), nullptr, 16);
08232                                 result += to_unicode(codepoint, codepoint2);
08233                                 // skip the next 10 characters (xxxx\uyyyy)
08234                                 i += 10;
08235                             }
08236                             else
08237                             {
08238                                 // add unicode character(s)
08239                                 result += to_unicode(codepoint);
08240                                 // skip the next four characters (xxxx)
08241                                 i += 4;
08242                             }
08243                             break;
08244                         }
08245                     }
08246                 }
08247                 else
08248                 {
08249                     // all other characters are just copied to the end of the
08250                     // string
08251                     result.append(1, static_cast<typename string_t::value_type>(*i));
08252                 }
08253             }
08254 
08255             return result;
08256         }
08257 
08278         long double str_to_float_t(long double* /* type */, char** endptr) const
08279         {
08280             return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
08281         }
08282 
08298         double str_to_float_t(double* /* type */, char** endptr) const
08299         {
08300             return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
08301         }
08302 
08318         float str_to_float_t(float* /* type */, char** endptr) const
08319         {
08320             return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
08321         }
08322 
08344         void get_number(basic_json& result) const
08345         {
08346             assert(m_start != nullptr);
08347 
08348             const lexer::lexer_char_t* curptr = m_start;
08349 
08350             // accumulate the integer conversion result (unsigned for now)
08351             number_unsigned_t value = 0;
08352 
08353             // maximum absolute value of the relevant integer type
08354             number_unsigned_t max;
08355 
08356             // temporarily store the type to avoid unecessary bitfield access
08357             value_t type;
08358 
08359             // look for sign
08360             if (*curptr == '-')
08361             {
08362                 type = value_t::number_integer;
08363                 max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
08364                 curptr++;
08365             }
08366             else
08367             {
08368                 type = value_t::number_unsigned;
08369                 max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
08370             }
08371 
08372             // count the significant figures
08373             for (; curptr < m_cursor; curptr++)
08374             {
08375                 // quickly skip tests if a digit
08376                 if (*curptr < '0' || *curptr > '9')
08377                 {
08378                     if (*curptr == '.')
08379                     {
08380                         // don't count '.' but change to float
08381                         type = value_t::number_float;
08382                         continue;
08383                     }
08384                     // assume exponent (if not then will fail parse): change to
08385                     // float, stop counting and record exponent details
08386                     type = value_t::number_float;
08387                     break;
08388                 }
08389 
08390                 // skip if definitely not an integer
08391                 if (type != value_t::number_float)
08392                 {
08393                     // multiply last value by ten and add the new digit
08394                     auto temp = value * 10 + *curptr - 0x30;
08395 
08396                     // test for overflow
08397                     if (temp < value || temp > max)
08398                     {
08399                         // overflow
08400                         type = value_t::number_float;
08401                     }
08402                     else
08403                     {
08404                         // no overflow - save it
08405                         value = temp;
08406                     }
08407                 }
08408             }
08409 
08410             // save the value (if not a float)
08411             if (type == value_t::number_unsigned)
08412             {
08413                 result.m_value.number_unsigned = value;
08414             }
08415             else if (type == value_t::number_integer)
08416             {
08417                 result.m_value.number_integer = -static_cast<number_integer_t>(value);
08418             }
08419             else
08420             {
08421                 // parse with strtod
08422                 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
08423             }
08424 
08425             // save the type
08426             result.m_type = type;
08427         }
08428 
08429       private:
08431         std::istream* m_stream = nullptr;
08433         string_t m_buffer;
08435         const lexer_char_t* m_content = nullptr;
08437         const lexer_char_t* m_start = nullptr;
08439         const lexer_char_t* m_marker = nullptr;
08441         const lexer_char_t* m_cursor = nullptr;
08443         const lexer_char_t* m_limit = nullptr;
08444     };
08445 
08451     class parser
08452     {
08453       public:
08455         parser(const string_t& s, parser_callback_t cb = nullptr) noexcept
08456             : callback(cb), m_lexer(s)
08457         {
08458             // read first token
08459             get_token();
08460         }
08461 
08463         parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept
08464             : callback(cb), m_lexer(&_is)
08465         {
08466             // read first token
08467             get_token();
08468         }
08469 
08471         basic_json parse()
08472         {
08473             basic_json result = parse_internal(true);
08474 
08475             expect(lexer::token_type::end_of_input);
08476 
08477             // return parser result and replace it with null in case the
08478             // top-level value was discarded by the callback function
08479             return result.is_discarded() ? basic_json() : result;
08480         }
08481 
08482       private:
08484         basic_json parse_internal(bool keep)
08485         {
08486             auto result = basic_json(value_t::discarded);
08487 
08488             switch (last_token)
08489             {
08490                 case lexer::token_type::begin_object:
08491                 {
08492                     if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
08493                     {
08494                         // explicitly set result to object to cope with {}
08495                         result.m_type = value_t::object;
08496                         result.m_value = json_value(value_t::object);
08497                     }
08498 
08499                     // read next token
08500                     get_token();
08501 
08502                     // closing } -> we are done
08503                     if (last_token == lexer::token_type::end_object)
08504                     {
08505                         get_token();
08506                         if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
08507                         {
08508                             result = basic_json(value_t::discarded);
08509                         }
08510                         return result;
08511                     }
08512 
08513                     // no comma is expected here
08514                     unexpect(lexer::token_type::value_separator);
08515 
08516                     // otherwise: parse key-value pairs
08517                     do
08518                     {
08519                         // ugly, but could be fixed with loop reorganization
08520                         if (last_token == lexer::token_type::value_separator)
08521                         {
08522                             get_token();
08523                         }
08524 
08525                         // store key
08526                         expect(lexer::token_type::value_string);
08527                         const auto key = m_lexer.get_string();
08528 
08529                         bool keep_tag = false;
08530                         if (keep)
08531                         {
08532                             if (callback)
08533                             {
08534                                 basic_json k(key);
08535                                 keep_tag = callback(depth, parse_event_t::key, k);
08536                             }
08537                             else
08538                             {
08539                                 keep_tag = true;
08540                             }
08541                         }
08542 
08543                         // parse separator (:)
08544                         get_token();
08545                         expect(lexer::token_type::name_separator);
08546 
08547                         // parse and add value
08548                         get_token();
08549                         auto value = parse_internal(keep);
08550                         if (keep and keep_tag and not value.is_discarded())
08551                         {
08552                             result[key] = std::move(value);
08553                         }
08554                     }
08555                     while (last_token == lexer::token_type::value_separator);
08556 
08557                     // closing }
08558                     expect(lexer::token_type::end_object);
08559                     get_token();
08560                     if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
08561                     {
08562                         result = basic_json(value_t::discarded);
08563                     }
08564 
08565                     return result;
08566                 }
08567 
08568                 case lexer::token_type::begin_array:
08569                 {
08570                     if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
08571                     {
08572                         // explicitly set result to object to cope with []
08573                         result.m_type = value_t::array;
08574                         result.m_value = json_value(value_t::array);
08575                     }
08576 
08577                     // read next token
08578                     get_token();
08579 
08580                     // closing ] -> we are done
08581                     if (last_token == lexer::token_type::end_array)
08582                     {
08583                         get_token();
08584                         if (callback and not callback(--depth, parse_event_t::array_end, result))
08585                         {
08586                             result = basic_json(value_t::discarded);
08587                         }
08588                         return result;
08589                     }
08590 
08591                     // no comma is expected here
08592                     unexpect(lexer::token_type::value_separator);
08593 
08594                     // otherwise: parse values
08595                     do
08596                     {
08597                         // ugly, but could be fixed with loop reorganization
08598                         if (last_token == lexer::token_type::value_separator)
08599                         {
08600                             get_token();
08601                         }
08602 
08603                         // parse value
08604                         auto value = parse_internal(keep);
08605                         if (keep and not value.is_discarded())
08606                         {
08607                             result.push_back(std::move(value));
08608                         }
08609                     }
08610                     while (last_token == lexer::token_type::value_separator);
08611 
08612                     // closing ]
08613                     expect(lexer::token_type::end_array);
08614                     get_token();
08615                     if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
08616                     {
08617                         result = basic_json(value_t::discarded);
08618                     }
08619 
08620                     return result;
08621                 }
08622 
08623                 case lexer::token_type::literal_null:
08624                 {
08625                     get_token();
08626                     result.m_type = value_t::null;
08627                     break;
08628                 }
08629 
08630                 case lexer::token_type::value_string:
08631                 {
08632                     const auto s = m_lexer.get_string();
08633                     get_token();
08634                     result = basic_json(s);
08635                     break;
08636                 }
08637 
08638                 case lexer::token_type::literal_true:
08639                 {
08640                     get_token();
08641                     result.m_type = value_t::boolean;
08642                     result.m_value = true;
08643                     break;
08644                 }
08645 
08646                 case lexer::token_type::literal_false:
08647                 {
08648                     get_token();
08649                     result.m_type = value_t::boolean;
08650                     result.m_value = false;
08651                     break;
08652                 }
08653 
08654                 case lexer::token_type::value_number:
08655                 {
08656                     m_lexer.get_number(result);
08657                     get_token();
08658                     break;
08659                 }
08660 
08661                 default:
08662                 {
08663                     // the last token was unexpected
08664                     unexpect(last_token);
08665                 }
08666             }
08667 
08668             if (keep and callback and not callback(depth, parse_event_t::value, result))
08669             {
08670                 result = basic_json(value_t::discarded);
08671             }
08672             return result;
08673         }
08674 
08676         typename lexer::token_type get_token() noexcept
08677         {
08678             last_token = m_lexer.scan();
08679             return last_token;
08680         }
08681 
08682         void expect(typename lexer::token_type t) const
08683         {
08684             if (t != last_token)
08685             {
08686                 std::string error_msg = "parse error - unexpected ";
08687                 error_msg += (last_token == lexer::token_type::parse_error ? ("'" +  m_lexer.get_token() + "'") :
08688                               lexer::token_type_name(last_token));
08689                 error_msg += "; expected " + lexer::token_type_name(t);
08690                 throw std::invalid_argument(error_msg);
08691             }
08692         }
08693 
08694         void unexpect(typename lexer::token_type t) const
08695         {
08696             if (t == last_token)
08697             {
08698                 std::string error_msg = "parse error - unexpected ";
08699                 error_msg += (last_token == lexer::token_type::parse_error ? ("'" +  m_lexer.get_token() + "'") :
08700                               lexer::token_type_name(last_token));
08701                 throw std::invalid_argument(error_msg);
08702             }
08703         }
08704 
08705       private:
08707         int depth = 0;
08709         parser_callback_t callback;
08711         typename lexer::token_type last_token = lexer::token_type::uninitialized;
08713         lexer m_lexer;
08714     };
08715 
08716   public:
08728     class json_pointer
08729     {
08731         friend class basic_json;
08732 
08733       public:
08756         explicit json_pointer(const std::string& s = "")
08757             : reference_tokens(split(s))
08758         {}
08759 
08775         std::string to_string() const noexcept
08776         {
08777             std::string result;
08778 
08779             for (const auto& reference_token : reference_tokens)
08780             {
08781                 result += "/" + escape(reference_token);
08782             }
08783 
08784             return result;
08785         }
08786 
08788         operator std::string() const
08789         {
08790             return to_string();
08791         }
08792 
08793       private:
08795         std::string pop_back()
08796         {
08797             if (is_root())
08798             {
08799                 throw std::domain_error("JSON pointer has no parent");
08800             }
08801 
08802             auto last = reference_tokens.back();
08803             reference_tokens.pop_back();
08804             return last;
08805         }
08806 
08808         bool is_root() const
08809         {
08810             return reference_tokens.empty();
08811         }
08812 
08813         json_pointer top() const
08814         {
08815             if (is_root())
08816             {
08817                 throw std::domain_error("JSON pointer has no parent");
08818             }
08819 
08820             json_pointer result = *this;
08821             result.reference_tokens = {reference_tokens[0]};
08822             return result;
08823         }
08824 
08828         reference get_and_create(reference j) const
08829         {
08830             pointer result = &j;
08831 
08832             // in case no reference tokens exist, return a reference to the
08833             // JSON value j which will be overwritten by a primitive value
08834             for (const auto& reference_token : reference_tokens)
08835             {
08836                 switch (result->m_type)
08837                 {
08838                     case value_t::null:
08839                     {
08840                         if (reference_token == "0")
08841                         {
08842                             // start a new array if reference token is 0
08843                             result = &result->operator[](0);
08844                         }
08845                         else
08846                         {
08847                             // start a new object otherwise
08848                             result = &result->operator[](reference_token);
08849                         }
08850                         break;
08851                     }
08852 
08853                     case value_t::object:
08854                     {
08855                         // create an entry in the object
08856                         result = &result->operator[](reference_token);
08857                         break;
08858                     }
08859 
08860                     case value_t::array:
08861                     {
08862                         // create an entry in the array
08863                         result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
08864                         break;
08865                     }
08866 
08867                     /*
08868                     The following code is only reached if there exists a
08869                     reference token _and_ the current value is primitive. In
08870                     this case, we have an error situation, because primitive
08871                     values may only occur as single value; that is, with an
08872                     empty list of reference tokens.
08873                     */
08874                     default:
08875                     {
08876                         throw std::domain_error("invalid value to unflatten");
08877                     }
08878                 }
08879             }
08880 
08881             return *result;
08882         }
08883 
08897         reference get_unchecked(pointer ptr) const
08898         {
08899             for (const auto& reference_token : reference_tokens)
08900             {
08901                 switch (ptr->m_type)
08902                 {
08903                     case value_t::object:
08904                     {
08905                         // use unchecked object access
08906                         ptr = &ptr->operator[](reference_token);
08907                         break;
08908                     }
08909 
08910                     case value_t::array:
08911                     {
08912                         // error condition (cf. RFC 6901, Sect. 4)
08913                         if (reference_token.size() > 1 and reference_token[0] == '0')
08914                         {
08915                             throw std::domain_error("array index must not begin with '0'");
08916                         }
08917 
08918                         if (reference_token == "-")
08919                         {
08920                             // explicityly treat "-" as index beyond the end
08921                             ptr = &ptr->operator[](ptr->m_value.array->size());
08922                         }
08923                         else
08924                         {
08925                             // convert array index to number; unchecked access
08926                             ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
08927                         }
08928                         break;
08929                     }
08930 
08931                     default:
08932                     {
08933                         throw std::out_of_range("unresolved reference token '" + reference_token + "'");
08934                     }
08935                 }
08936             }
08937 
08938             return *ptr;
08939         }
08940 
08941         reference get_checked(pointer ptr) const
08942         {
08943             for (const auto& reference_token : reference_tokens)
08944             {
08945                 switch (ptr->m_type)
08946                 {
08947                     case value_t::object:
08948                     {
08949                         // note: at performs range check
08950                         ptr = &ptr->at(reference_token);
08951                         break;
08952                     }
08953 
08954                     case value_t::array:
08955                     {
08956                         if (reference_token == "-")
08957                         {
08958                             // "-" always fails the range check
08959                             throw std::out_of_range("array index '-' (" +
08960                                                     std::to_string(ptr->m_value.array->size()) +
08961                                                     ") is out of range");
08962                         }
08963 
08964                         // error condition (cf. RFC 6901, Sect. 4)
08965                         if (reference_token.size() > 1 and reference_token[0] == '0')
08966                         {
08967                             throw std::domain_error("array index must not begin with '0'");
08968                         }
08969 
08970                         // note: at performs range check
08971                         ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
08972                         break;
08973                     }
08974 
08975                     default:
08976                     {
08977                         throw std::out_of_range("unresolved reference token '" + reference_token + "'");
08978                     }
08979                 }
08980             }
08981 
08982             return *ptr;
08983         }
08984 
08993         const_reference get_unchecked(const_pointer ptr) const
08994         {
08995             for (const auto& reference_token : reference_tokens)
08996             {
08997                 switch (ptr->m_type)
08998                 {
08999                     case value_t::object:
09000                     {
09001                         // use unchecked object access
09002                         ptr = &ptr->operator[](reference_token);
09003                         break;
09004                     }
09005 
09006                     case value_t::array:
09007                     {
09008                         if (reference_token == "-")
09009                         {
09010                             // "-" cannot be used for const access
09011                             throw std::out_of_range("array index '-' (" +
09012                                                     std::to_string(ptr->m_value.array->size()) +
09013                                                     ") is out of range");
09014                         }
09015 
09016                         // error condition (cf. RFC 6901, Sect. 4)
09017                         if (reference_token.size() > 1 and reference_token[0] == '0')
09018                         {
09019                             throw std::domain_error("array index must not begin with '0'");
09020                         }
09021 
09022                         // use unchecked array access
09023                         ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
09024                         break;
09025                     }
09026 
09027                     default:
09028                     {
09029                         throw std::out_of_range("unresolved reference token '" + reference_token + "'");
09030                     }
09031                 }
09032             }
09033 
09034             return *ptr;
09035         }
09036 
09037         const_reference get_checked(const_pointer ptr) const
09038         {
09039             for (const auto& reference_token : reference_tokens)
09040             {
09041                 switch (ptr->m_type)
09042                 {
09043                     case value_t::object:
09044                     {
09045                         // note: at performs range check
09046                         ptr = &ptr->at(reference_token);
09047                         break;
09048                     }
09049 
09050                     case value_t::array:
09051                     {
09052                         if (reference_token == "-")
09053                         {
09054                             // "-" always fails the range check
09055                             throw std::out_of_range("array index '-' (" +
09056                                                     std::to_string(ptr->m_value.array->size()) +
09057                                                     ") is out of range");
09058                         }
09059 
09060                         // error condition (cf. RFC 6901, Sect. 4)
09061                         if (reference_token.size() > 1 and reference_token[0] == '0')
09062                         {
09063                             throw std::domain_error("array index must not begin with '0'");
09064                         }
09065 
09066                         // note: at performs range check
09067                         ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
09068                         break;
09069                     }
09070 
09071                     default:
09072                     {
09073                         throw std::out_of_range("unresolved reference token '" + reference_token + "'");
09074                     }
09075                 }
09076             }
09077 
09078             return *ptr;
09079         }
09080 
09082         static std::vector<std::string> split(std::string reference_string)
09083         {
09084             std::vector<std::string> result;
09085 
09086             // special case: empty reference string -> no reference tokens
09087             if (reference_string.empty())
09088             {
09089                 return result;
09090             }
09091 
09092             // check if nonempty reference string begins with slash
09093             if (reference_string[0] != '/')
09094             {
09095                 throw std::domain_error("JSON pointer must be empty or begin with '/'");
09096             }
09097 
09098             // extract the reference tokens:
09099             // - slash: position of the last read slash (or end of string)
09100             // - start: position after the previous slash
09101             for (
09102                 // search for the first slash after the first character
09103                 size_t slash = reference_string.find_first_of("/", 1),
09104                 // set the beginning of the first reference token
09105                 start = 1;
09106                 // we can stop if start == string::npos+1 = 0
09107                 start != 0;
09108                 // set the beginning of the next reference token
09109                 // (will eventually be 0 if slash == std::string::npos)
09110                 start = slash + 1,
09111                 // find next slash
09112                 slash = reference_string.find_first_of("/", start))
09113             {
09114                 // use the text between the beginning of the reference token
09115                 // (start) and the last slash (slash).
09116                 auto reference_token = reference_string.substr(start, slash - start);
09117 
09118                 // check reference tokens are properly escaped
09119                 for (size_t pos = reference_token.find_first_of("~");
09120                         pos != std::string::npos;
09121                         pos = reference_token.find_first_of("~", pos + 1))
09122                 {
09123                     assert(reference_token[pos] == '~');
09124 
09125                     // ~ must be followed by 0 or 1
09126                     if (pos == reference_token.size() - 1 or
09127                             (reference_token[pos + 1] != '0' and
09128                              reference_token[pos + 1] != '1'))
09129                     {
09130                         throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
09131                     }
09132                 }
09133 
09134                 // finally, store the reference token
09135                 unescape(reference_token);
09136                 result.push_back(reference_token);
09137             }
09138 
09139             return result;
09140         }
09141 
09142       private:
09157         static void replace_substring(std::string& s,
09158                                       const std::string& f,
09159                                       const std::string& t)
09160         {
09161             assert(not f.empty());
09162 
09163             for (
09164                 size_t pos = s.find(f);         // find first occurrence of f
09165                 pos != std::string::npos;       // make sure f was found
09166                 s.replace(pos, f.size(), t),    // replace with t
09167                 pos = s.find(f, pos + t.size()) // find next occurrence of f
09168             );
09169         }
09170 
09172         static std::string escape(std::string s)
09173         {
09174             // escape "~"" to "~0" and "/" to "~1"
09175             replace_substring(s, "~", "~0");
09176             replace_substring(s, "/", "~1");
09177             return s;
09178         }
09179 
09181         static void unescape(std::string& s)
09182         {
09183             // first transform any occurrence of the sequence '~1' to '/'
09184             replace_substring(s, "~1", "/");
09185             // then transform any occurrence of the sequence '~0' to '~'
09186             replace_substring(s, "~0", "~");
09187         }
09188 
09196         static void flatten(const std::string& reference_string,
09197                             const basic_json& value,
09198                             basic_json& result)
09199         {
09200             switch (value.m_type)
09201             {
09202                 case value_t::array:
09203                 {
09204                     if (value.m_value.array->empty())
09205                     {
09206                         // flatten empty array as null
09207                         result[reference_string] = nullptr;
09208                     }
09209                     else
09210                     {
09211                         // iterate array and use index as reference string
09212                         for (size_t i = 0; i < value.m_value.array->size(); ++i)
09213                         {
09214                             flatten(reference_string + "/" + std::to_string(i),
09215                                     value.m_value.array->operator[](i), result);
09216                         }
09217                     }
09218                     break;
09219                 }
09220 
09221                 case value_t::object:
09222                 {
09223                     if (value.m_value.object->empty())
09224                     {
09225                         // flatten empty object as null
09226                         result[reference_string] = nullptr;
09227                     }
09228                     else
09229                     {
09230                         // iterate object and use keys as reference string
09231                         for (const auto& element : *value.m_value.object)
09232                         {
09233                             flatten(reference_string + "/" + escape(element.first),
09234                                     element.second, result);
09235                         }
09236                     }
09237                     break;
09238                 }
09239 
09240                 default:
09241                 {
09242                     // add primitive value with its reference string
09243                     result[reference_string] = value;
09244                     break;
09245                 }
09246             }
09247         }
09248 
09254         static basic_json unflatten(const basic_json& value)
09255         {
09256             if (not value.is_object())
09257             {
09258                 throw std::domain_error("only objects can be unflattened");
09259             }
09260 
09261             basic_json result;
09262 
09263             // iterate the JSON object values
09264             for (const auto& element : *value.m_value.object)
09265             {
09266                 if (not element.second.is_primitive())
09267                 {
09268                     throw std::domain_error("values in object must be primitive");
09269                 }
09270 
09271                 // assign value to reference pointed to by JSON pointer; Note
09272                 // that if the JSON pointer is "" (i.e., points to the whole
09273                 // value), function get_and_create returns a reference to
09274                 // result itself. An assignment will then create a primitive
09275                 // value.
09276                 json_pointer(element.first).get_and_create(result) = element.second;
09277             }
09278 
09279             return result;
09280         }
09281 
09282       private:
09284         std::vector<std::string> reference_tokens {};
09285     };
09286 
09288     // JSON Pointer support //
09290 
09293 
09327     reference operator[](const json_pointer& ptr)
09328     {
09329         return ptr.get_unchecked(this);
09330     }
09331 
09354     const_reference operator[](const json_pointer& ptr) const
09355     {
09356         return ptr.get_unchecked(this);
09357     }
09358 
09379     reference at(const json_pointer& ptr)
09380     {
09381         return ptr.get_checked(this);
09382     }
09383 
09404     const_reference at(const json_pointer& ptr) const
09405     {
09406         return ptr.get_checked(this);
09407     }
09408 
09431     basic_json flatten() const
09432     {
09433         basic_json result(value_t::object);
09434         json_pointer::flatten("", *this, result);
09435         return result;
09436     }
09437 
09465     basic_json unflatten() const
09466     {
09467         return json_pointer::unflatten(*this);
09468     }
09469 
09471 
09473     // JSON Patch functions //
09475 
09478 
09515     basic_json patch(const basic_json& json_patch) const
09516     {
09517         // make a working copy to apply the patch to
09518         basic_json result = *this;
09519 
09520         // the valid JSON Patch operations
09521         enum class patch_operations {add, remove, replace, move, copy, test, invalid};
09522 
09523         const auto get_op = [](const std::string op)
09524         {
09525             if (op == "add")
09526             {
09527                 return patch_operations::add;
09528             }
09529             if (op == "remove")
09530             {
09531                 return patch_operations::remove;
09532             }
09533             if (op == "replace")
09534             {
09535                 return patch_operations::replace;
09536             }
09537             if (op == "move")
09538             {
09539                 return patch_operations::move;
09540             }
09541             if (op == "copy")
09542             {
09543                 return patch_operations::copy;
09544             }
09545             if (op == "test")
09546             {
09547                 return patch_operations::test;
09548             }
09549 
09550             return patch_operations::invalid;
09551         };
09552 
09553         // wrapper for "add" operation; add value at ptr
09554         const auto operation_add = [&result](json_pointer & ptr, basic_json val)
09555         {
09556             // adding to the root of the target document means replacing it
09557             if (ptr.is_root())
09558             {
09559                 result = val;
09560             }
09561             else
09562             {
09563                 // make sure the top element of the pointer exists
09564                 json_pointer top_pointer = ptr.top();
09565                 if (top_pointer != ptr)
09566                 {
09567                     basic_json& x = result.at(top_pointer);
09568                 }
09569 
09570                 // get reference to parent of JSON pointer ptr
09571                 const auto last_path = ptr.pop_back();
09572                 basic_json& parent = result[ptr];
09573 
09574                 switch (parent.m_type)
09575                 {
09576                     case value_t::null:
09577                     case value_t::object:
09578                     {
09579                         // use operator[] to add value
09580                         parent[last_path] = val;
09581                         break;
09582                     }
09583 
09584                     case value_t::array:
09585                     {
09586                         if (last_path == "-")
09587                         {
09588                             // special case: append to back
09589                             parent.push_back(val);
09590                         }
09591                         else
09592                         {
09593                             const auto idx = std::stoi(last_path);
09594                             if (static_cast<size_type>(idx) > parent.size())
09595                             {
09596                                 // avoid undefined behavior
09597                                 throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
09598                             }
09599                             else
09600                             {
09601                                 // default case: insert add offset
09602                                 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
09603                             }
09604                         }
09605                         break;
09606                     }
09607 
09608                     default:
09609                     {
09610                         // if there exists a parent it cannot be primitive
09611                         assert(false);  // LCOV_EXCL_LINE
09612                     }
09613                 }
09614             }
09615         };
09616 
09617         // wrapper for "remove" operation; remove value at ptr
09618         const auto operation_remove = [&result](json_pointer & ptr)
09619         {
09620             // get reference to parent of JSON pointer ptr
09621             const auto last_path = ptr.pop_back();
09622             basic_json& parent = result.at(ptr);
09623 
09624             // remove child
09625             if (parent.is_object())
09626             {
09627                 // perform range check
09628                 auto it = parent.find(last_path);
09629                 if (it != parent.end())
09630                 {
09631                     parent.erase(it);
09632                 }
09633                 else
09634                 {
09635                     throw std::out_of_range("key '" + last_path + "' not found");
09636                 }
09637             }
09638             else if (parent.is_array())
09639             {
09640                 // note erase performs range check
09641                 parent.erase(static_cast<size_type>(std::stoi(last_path)));
09642             }
09643         };
09644 
09645         // type check
09646         if (not json_patch.is_array())
09647         {
09648             // a JSON patch must be an array of objects
09649             throw std::invalid_argument("JSON patch must be an array of objects");
09650         }
09651 
09652         // iterate and apply th eoperations
09653         for (const auto& val : json_patch)
09654         {
09655             // wrapper to get a value for an operation
09656             const auto get_value = [&val](const std::string & op,
09657                                           const std::string & member,
09658                                           bool string_type) -> basic_json&
09659             {
09660                 // find value
09661                 auto it = val.m_value.object->find(member);
09662 
09663                 // context-sensitive error message
09664                 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
09665 
09666                 // check if desired value is present
09667                 if (it == val.m_value.object->end())
09668                 {
09669                     throw std::invalid_argument(error_msg + " must have member '" + member + "'");
09670                 }
09671 
09672                 // check if result is of type string
09673                 if (string_type and not it->second.is_string())
09674                 {
09675                     throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
09676                 }
09677 
09678                 // no error: return value
09679                 return it->second;
09680             };
09681 
09682             // type check
09683             if (not val.is_object())
09684             {
09685                 throw std::invalid_argument("JSON patch must be an array of objects");
09686             }
09687 
09688             // collect mandatory members
09689             const std::string op = get_value("op", "op", true);
09690             const std::string path = get_value(op, "path", true);
09691             json_pointer ptr(path);
09692 
09693             switch (get_op(op))
09694             {
09695                 case patch_operations::add:
09696                 {
09697                     operation_add(ptr, get_value("add", "value", false));
09698                     break;
09699                 }
09700 
09701                 case patch_operations::remove:
09702                 {
09703                     operation_remove(ptr);
09704                     break;
09705                 }
09706 
09707                 case patch_operations::replace:
09708                 {
09709                     // the "path" location must exist - use at()
09710                     result.at(ptr) = get_value("replace", "value", false);
09711                     break;
09712                 }
09713 
09714                 case patch_operations::move:
09715                 {
09716                     const std::string from_path = get_value("move", "from", true);
09717                     json_pointer from_ptr(from_path);
09718 
09719                     // the "from" location must exist - use at()
09720                     basic_json v = result.at(from_ptr);
09721 
09722                     // The move operation is functionally identical to a
09723                     // "remove" operation on the "from" location, followed
09724                     // immediately by an "add" operation at the target
09725                     // location with the value that was just removed.
09726                     operation_remove(from_ptr);
09727                     operation_add(ptr, v);
09728                     break;
09729                 }
09730 
09731                 case patch_operations::copy:
09732                 {
09733                     const std::string from_path = get_value("copy", "from", true);;
09734                     const json_pointer from_ptr(from_path);
09735 
09736                     // the "from" location must exist - use at()
09737                     result[ptr] = result.at(from_ptr);
09738                     break;
09739                 }
09740 
09741                 case patch_operations::test:
09742                 {
09743                     bool success = false;
09744                     try
09745                     {
09746                         // check if "value" matches the one at "path"
09747                         // the "path" location must exist - use at()
09748                         success = (result.at(ptr) == get_value("test", "value", false));
09749                     }
09750                     catch (std::out_of_range&)
09751                     {
09752                         // ignore out of range errors: success remains false
09753                     }
09754 
09755                     // throw an exception if test fails
09756                     if (not success)
09757                     {
09758                         throw std::domain_error("unsuccessful: " + val.dump());
09759                     }
09760 
09761                     break;
09762                 }
09763 
09764                 case patch_operations::invalid:
09765                 {
09766                     // op must be "add", "remove", "replace", "move", "copy", or
09767                     // "test"
09768                     throw std::invalid_argument("operation value '" + op + "' is invalid");
09769                 }
09770             }
09771         }
09772 
09773         return result;
09774     }
09775 
09808     static basic_json diff(const basic_json& source,
09809                            const basic_json& target,
09810                            std::string path = "")
09811     {
09812         // the patch
09813         basic_json result(value_t::array);
09814 
09815         // if the values are the same, return empty patch
09816         if (source == target)
09817         {
09818             return result;
09819         }
09820 
09821         if (source.type() != target.type())
09822         {
09823             // different types: replace value
09824             result.push_back(
09825             {
09826                 {"op", "replace"},
09827                 {"path", path},
09828                 {"value", target}
09829             });
09830         }
09831         else
09832         {
09833             switch (source.type())
09834             {
09835                 case value_t::array:
09836                 {
09837                     // first pass: traverse common elements
09838                     size_t i = 0;
09839                     while (i < source.size() and i < target.size())
09840                     {
09841                         // recursive call to compare array values at index i
09842                         auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
09843                         result.insert(result.end(), temp_diff.begin(), temp_diff.end());
09844                         ++i;
09845                     }
09846 
09847                     // i now reached the end of at least one array
09848                     // in a second pass, traverse the remaining elements
09849 
09850                     // remove my remaining elements
09851                     const auto end_index = static_cast<difference_type>(result.size());
09852                     while (i < source.size())
09853                     {
09854                         // add operations in reverse order to avoid invalid
09855                         // indices
09856                         result.insert(result.begin() + end_index, object(
09857                         {
09858                             {"op", "remove"},
09859                             {"path", path + "/" + std::to_string(i)}
09860                         }));
09861                         ++i;
09862                     }
09863 
09864                     // add other remaining elements
09865                     while (i < target.size())
09866                     {
09867                         result.push_back(
09868                         {
09869                             {"op", "add"},
09870                             {"path", path + "/" + std::to_string(i)},
09871                             {"value", target[i]}
09872                         });
09873                         ++i;
09874                     }
09875 
09876                     break;
09877                 }
09878 
09879                 case value_t::object:
09880                 {
09881                     // first pass: traverse this object's elements
09882                     for (auto it = source.begin(); it != source.end(); ++it)
09883                     {
09884                         // escape the key name to be used in a JSON patch
09885                         const auto key = json_pointer::escape(it.key());
09886 
09887                         if (target.find(it.key()) != target.end())
09888                         {
09889                             // recursive call to compare object values at key it
09890                             auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
09891                             result.insert(result.end(), temp_diff.begin(), temp_diff.end());
09892                         }
09893                         else
09894                         {
09895                             // found a key that is not in o -> remove it
09896                             result.push_back(object(
09897                             {
09898                                 {"op", "remove"},
09899                                 {"path", path + "/" + key}
09900                             }));
09901                         }
09902                     }
09903 
09904                     // second pass: traverse other object's elements
09905                     for (auto it = target.begin(); it != target.end(); ++it)
09906                     {
09907                         if (source.find(it.key()) == source.end())
09908                         {
09909                             // found a key that is not in this -> add it
09910                             const auto key = json_pointer::escape(it.key());
09911                             result.push_back(
09912                             {
09913                                 {"op", "add"},
09914                                 {"path", path + "/" + key},
09915                                 {"value", it.value()}
09916                             });
09917                         }
09918                     }
09919 
09920                     break;
09921                 }
09922 
09923                 default:
09924                 {
09925                     // both primitive type: replace value
09926                     result.push_back(
09927                     {
09928                         {"op", "replace"},
09929                         {"path", path},
09930                         {"value", target}
09931                     });
09932                     break;
09933                 }
09934             }
09935         }
09936 
09937         return result;
09938     }
09939 
09941 };
09942 
09943 
09945 // presets //
09947 
09956 using json = basic_json<>;
09957 }
09958 
09959 
09961 // nonmember support //
09963 
09964 // specialization of std::swap, and std::hash
09965 namespace std
09966 {
09972 template <>
09973 inline void swap(nlohmann::json& j1,
09974                  nlohmann::json& j2) noexcept(
09975                      is_nothrow_move_constructible<nlohmann::json>::value and
09976                      is_nothrow_move_assignable<nlohmann::json>::value
09977                  )
09978 {
09979     j1.swap(j2);
09980 }
09981 
09983 template <>
09984 struct hash<nlohmann::json>
09985 {
09991     std::size_t operator()(const nlohmann::json& j) const
09992     {
09993         // a naive hashing via the string representation
09994         const auto& h = hash<nlohmann::json::string_t>();
09995         return h(j.dump());
09996     }
09997 };
09998 }
09999 
10012 inline nlohmann::json operator "" _json(const char* s, std::size_t)
10013 {
10014     return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
10015 }
10016 
10022 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
10023 {
10024     return nlohmann::json::json_pointer(s);
10025 }
10026 
10027 // restore GCC/clang diagnostic settings
10028 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10029     #pragma GCC diagnostic pop
10030 #endif
10031 
10032 #endif


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:05