Index: head/net/zerotier/Makefile =================================================================== --- head/net/zerotier/Makefile (revision 507240) +++ head/net/zerotier/Makefile (revision 507241) @@ -1,54 +1,56 @@ # Created by: Corey Smith # $FreeBSD$ PORTNAME= zerotier -DISTVERSION= 1.2.12 -PORTREVISION= 3 +DISTVERSION= 1.2.12-310 +DISTVERSIONSUFFIX= -g8a0b75c + CATEGORIES= net MAINTAINER= dch@FreeBSD.org COMMENT= Network virtualization everywhere LICENSE= GPLv3+ MIT PD LICENSE_COMB= multi LICENSE_FILE_GPLv3+ =${WRKSRC}/LICENSE.GPL-3 LICENSE_FILE_MIT=${WRKSRC}/ext/json/LICENSE.MIT USES= gmake compiler:c++14-lang USE_RC_SUBR= zerotier USE_GITHUB= yes GH_PROJECT= ZeroTierOne +GH_TAGNAME= 8a0b75c CFLAGS+= -flax-vector-conversions OPTIONS_DEFINE= DBG DBG_DESC= Enable foreground debugging for zerotier-one daemon DBG_ALL_TARGET= debug PLIST_FILES= bin/zerotier-cli bin/zerotier-idtool sbin/zerotier-one .include .if ${OPSYS} == "FreeBSD" # log output via syslog when daemon(8) supports it .if ((${OSVERSION} >= 1100513 && ${OSVERSION} < 1200000) || ${OSVERSION} >= 1200015) SUB_LIST+= ZEROTIER_SYSLOG="-s debug -T zerotier" .else SUB_LIST+= ZEROTIER_SYSLOG="" .endif # after r347241 tun(4) and tap(4) have been merged to tuntap(4) .if (${OSVERSION} >= 1300028) SUB_LIST+= ZEROTIER_IF_TAP="if_tuntap" .else SUB_LIST+= ZEROTIER_IF_TAP="if_tap" .endif .endif do-install: ${INSTALL_PROGRAM} ${WRKSRC}/zerotier-one ${STAGEDIR}${PREFIX}/sbin/ .for l in zerotier-cli zerotier-idtool ${RLN} ${STAGEDIR}${PREFIX}/sbin/zerotier-one ${STAGEDIR}${PREFIX}/bin/${l} .endfor .include Index: head/net/zerotier/distinfo =================================================================== --- head/net/zerotier/distinfo (revision 507240) +++ head/net/zerotier/distinfo (revision 507241) @@ -1,3 +1,3 @@ -TIMESTAMP = 1535097824 -SHA256 (zerotier-ZeroTierOne-1.2.12_GH0.tar.gz) = 212799bfaeb5e7dff20f2cd83f15742c8e13b8e9535606cfb85abcfb5fb6fed4 -SIZE (zerotier-ZeroTierOne-1.2.12_GH0.tar.gz) = 6058902 +TIMESTAMP = 1563871634 +SHA256 (zerotier-ZeroTierOne-1.2.12-310-g8a0b75c-8a0b75c_GH0.tar.gz) = 2e545c37a54277ac4e754f893d904bf39d15557abce8360d807595a5670dfa67 +SIZE (zerotier-ZeroTierOne-1.2.12-310-g8a0b75c-8a0b75c_GH0.tar.gz) = 13054805 Index: head/net/zerotier/files/patch-node_Utils.hpp =================================================================== --- head/net/zerotier/files/patch-node_Utils.hpp (revision 507240) +++ head/net/zerotier/files/patch-node_Utils.hpp (nonexistent) @@ -1,41 +0,0 @@ ---- node/Utils.hpp.orig 2015-08-25 16:55:14 UTC -+++ node/Utils.hpp -@@ -39,6 +39,10 @@ - #include - #include - -+#if defined(__FreeBSD__) -+#include -+#endif -+ - #include "Constants.hpp" - - namespace ZeroTier { -@@ -321,8 +325,12 @@ public: - throw() - { - #if __BYTE_ORDER == __LITTLE_ENDIAN --#if defined(__GNUC__) && (!defined(__OpenBSD__)) -+#if defined(__GNUC__) -+#if defined(__FreeBSD__) -+ return bswap64(n); -+#elif (!defined(__OpenBSD__)) - return __builtin_bswap64(n); -+#endif - #else - return ( - ((n & 0x00000000000000FFULL) << 56) | -@@ -351,8 +359,12 @@ public: - throw() - { - #if __BYTE_ORDER == __LITTLE_ENDIAN --#if defined(__GNUC__) && !defined(__OpenBSD__) -+#if defined(__GNUC__) -+#if defined(__FreeBSD__) -+ return bswap64(n); -+#elif (!defined(__OpenBSD__)) - return __builtin_bswap64(n); -+#endif - #else - return ( - ((n & 0x00000000000000FFULL) << 56) | Property changes on: head/net/zerotier/files/patch-node_Utils.hpp ___________________________________________________________________ Deleted: fbsd:nokeywords ## -1 +0,0 ## -yes \ No newline at end of property Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/net/zerotier/files/patch-ext_json_json.hpp =================================================================== --- head/net/zerotier/files/patch-ext_json_json.hpp (revision 507240) +++ head/net/zerotier/files/patch-ext_json_json.hpp (nonexistent) @@ -1,10678 +0,0 @@ ---- ext/json/json.hpp.orig 2018-05-11 20:40:22 UTC -+++ ext/json/json.hpp -@@ -1,11 +1,12 @@ - /* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ --| | |__ | | | | | | version 3.0.1 -+| | |__ | | | | | | version 3.2.0 - |_____|_____|_____|_|___| https://github.com/nlohmann/json - - Licensed under the MIT License . --Copyright (c) 2013-2017 Niels Lohmann . -+SPDX-License-Identifier: MIT -+Copyright (c) 2013-2018 Niels Lohmann . - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal -@@ -29,43 +30,105 @@ SOFTWARE. - #ifndef NLOHMANN_JSON_HPP - #define NLOHMANN_JSON_HPP - --#include // all_of, copy, fill, find, for_each, generate_n, none_of, remove, reverse, transform --#include // array -+#define NLOHMANN_JSON_VERSION_MAJOR 3 -+#define NLOHMANN_JSON_VERSION_MINOR 2 -+#define NLOHMANN_JSON_VERSION_PATCH 0 -+ -+#include // all_of, find, for_each - #include // assert - #include // and, not, or --#include // lconv, localeconv --#include // isfinite, labs, ldexp, signbit - #include // nullptr_t, ptrdiff_t, size_t --#include // int64_t, uint64_t --#include // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull --#include // memcpy, strlen --#include // forward_list --#include // function, hash, less -+#include // hash, less - #include // initializer_list --#include // hex --#include // istream, ostream --#include // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator --#include // numeric_limits --#include // locale --#include // map --#include // addressof, allocator, allocator_traits, unique_ptr -+#include // istream, ostream -+#include // iterator_traits, random_access_iterator_tag - #include // accumulate --#include // stringstream --#include // getline, stoi, string, to_string --#include // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type --#include // declval, forward, make_pair, move, pair, swap --#include // valarray -+#include // string, stoi, to_string -+#include // declval, forward, move, pair, swap -+ -+// #include -+#ifndef NLOHMANN_JSON_FWD_HPP -+#define NLOHMANN_JSON_FWD_HPP -+ -+#include // int64_t, uint64_t -+#include // map -+#include // allocator -+#include // string - #include // vector - -+/*! -+@brief namespace for Niels Lohmann -+@see https://github.com/nlohmann -+@since version 1.0.0 -+*/ -+namespace nlohmann -+{ -+/*! -+@brief default JSONSerializer template argument -+ -+This serializer ignores the template arguments and uses ADL -+([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) -+for serialization. -+*/ -+template -+struct adl_serializer; -+ -+template class ObjectType = -+ std::map, -+ template class ArrayType = std::vector, -+ class StringType = std::string, class BooleanType = bool, -+ class NumberIntegerType = std::int64_t, -+ class NumberUnsignedType = std::uint64_t, -+ class NumberFloatType = double, -+ template class AllocatorType = std::allocator, -+ template class JSONSerializer = -+ adl_serializer> -+class basic_json; -+ -+/*! -+@brief JSON Pointer -+ -+A JSON pointer defines a string syntax for identifying a specific value -+within a JSON document. It can be used with functions `at` and -+`operator[]`. Furthermore, JSON pointers are the base for JSON patches. -+ -+@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) -+ -+@since version 2.0.0 -+*/ -+template -+class json_pointer; -+ -+/*! -+@brief default JSON class -+ -+This type is the default specialization of the @ref basic_json class which -+uses the standard template types. -+ -+@since version 1.0.0 -+*/ -+using json = basic_json<>; -+} -+ -+#endif -+ -+// #include -+ -+ -+// This file contains all internal macro definitions -+// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them -+ - // exclude unsupported compilers --#if defined(__clang__) -- #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 -- #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" -+#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) -+ #if defined(__clang__) -+ #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 -+ #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" -+ #endif -+ #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) -+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 -+ #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" -+ #endif - #endif --#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) -- #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 -- #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" -- #endif - #endif - - // disable float-equal warnings on GCC/clang -@@ -90,16 +153,37 @@ SOFTWARE. - #endif - - // allow to disable exceptions --#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(JSON_NOEXCEPTION) -+#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) -+ #define JSON_INTERNAL_CATCH(exception) catch(exception) - #else - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) -+ #define JSON_INTERNAL_CATCH(exception) if(false) - #endif - -+// override exception macros -+#if defined(JSON_THROW_USER) -+ #undef JSON_THROW -+ #define JSON_THROW JSON_THROW_USER -+#endif -+#if defined(JSON_TRY_USER) -+ #undef JSON_TRY -+ #define JSON_TRY JSON_TRY_USER -+#endif -+#if defined(JSON_CATCH_USER) -+ #undef JSON_CATCH -+ #define JSON_CATCH JSON_CATCH_USER -+ #define JSON_INTERNAL_CATCH JSON_CATCH_USER -+#endif -+#if defined(JSON_INTERNAL_CATCH_USER) -+ #undef JSON_INTERNAL_CATCH -+ #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER -+#endif -+ - // manual branch prediction - #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #define JSON_LIKELY(x) __builtin_expect(!!(x), 1) -@@ -117,27 +201,6 @@ SOFTWARE. - #define JSON_HAS_CPP_14 - #endif - --/*! --@brief namespace for Niels Lohmann --@see https://github.com/nlohmann --@since version 1.0.0 --*/ --namespace nlohmann --{ --template --struct adl_serializer; -- --// forward declaration of basic_json (required to split the class) --template class ObjectType = std::map, -- template class ArrayType = std::vector, -- class StringType = std::string, class BooleanType = bool, -- class NumberIntegerType = std::int64_t, -- class NumberUnsignedType = std::uint64_t, -- class NumberFloatType = double, -- template class AllocatorType = std::allocator, -- template class JSONSerializer = adl_serializer> --class basic_json; -- - // Ugly macros to avoid uglier copy-paste when specializing basic_json. They - // may be removed in the future once the class is split. - -@@ -154,17 +217,334 @@ class basic_json; - NumberIntegerType, NumberUnsignedType, NumberFloatType, \ - AllocatorType, JSONSerializer> - -+/*! -+@brief Helper to determine whether there's a key_type for T. - -+This helper is used to tell associative containers apart from other containers -+such as sequence containers. For instance, `std::map` passes the test as it -+contains a `mapped_type`, whereas `std::vector` fails the test. -+ -+@sa http://stackoverflow.com/a/7728728/266378 -+@since version 1.0.0, overworked in version 2.0.6 -+*/ -+#define NLOHMANN_JSON_HAS_HELPER(type) \ -+ template struct has_##type { \ -+ private: \ -+ template \ -+ static int detect(U &&); \ -+ static void detect(...); \ -+ public: \ -+ static constexpr bool value = \ -+ std::is_integral()))>::value; \ -+ } -+ -+// #include -+ -+ -+#include // not -+#include // size_t -+#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -+ -+namespace nlohmann -+{ -+namespace detail -+{ -+// alias templates to reduce boilerplate -+template -+using enable_if_t = typename std::enable_if::type; -+ -+template -+using uncvref_t = typename std::remove_cv::type>::type; -+ -+// implementation of C++14 index_sequence and affiliates -+// source: https://stackoverflow.com/a/32223343 -+template -+struct index_sequence -+{ -+ using type = index_sequence; -+ using value_type = std::size_t; -+ static constexpr std::size_t size() noexcept -+ { -+ return sizeof...(Ints); -+ } -+}; -+ -+template -+struct merge_and_renumber; -+ -+template -+struct merge_and_renumber, index_sequence> -+ : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; -+ -+template -+struct make_index_sequence -+ : merge_and_renumber < typename make_index_sequence < N / 2 >::type, -+ typename make_index_sequence < N - N / 2 >::type > {}; -+ -+template<> struct make_index_sequence<0> : index_sequence<> {}; -+template<> struct make_index_sequence<1> : index_sequence<0> {}; -+ -+template -+using index_sequence_for = make_index_sequence; -+ -+/* -+Implementation of two C++17 constructs: conjunction, negation. This is needed -+to avoid evaluating all the traits in a condition -+ -+For example: not std::is_same::value and has_value_type::value -+will not compile when T = void (on MSVC at least). Whereas -+conjunction>, has_value_type>::value will -+stop evaluating if negation<...>::value == false -+ -+Please note that those constructs must be used with caution, since symbols can -+become very long quickly (which can slow down compilation and cause MSVC -+internal compiler errors). Only use it when you have to (see example ahead). -+*/ -+template struct conjunction : std::true_type {}; -+template struct conjunction : B1 {}; -+template -+struct conjunction : std::conditional, B1>::type {}; -+ -+template struct negation : std::integral_constant {}; -+ -+// dispatch utility (taken from ranges-v3) -+template struct priority_tag : priority_tag < N - 1 > {}; -+template<> struct priority_tag<0> {}; -+ -+// taken from ranges-v3 -+template -+struct static_const -+{ -+ static constexpr T value{}; -+}; -+ -+template -+constexpr T static_const::value; -+} -+} -+ -+// #include -+ -+ -+#include // not -+#include // numeric_limits -+#include // false_type, is_constructible, is_integral, is_same, true_type -+#include // declval -+ -+// #include -+ -+// #include -+ -+// #include -+ -+ -+namespace nlohmann -+{ - /*! --@brief unnamed namespace with internal helper functions -+@brief detail namespace with internal helper functions - --This namespace collects some functions that could not be defined inside the --@ref basic_json class. -+This namespace collects functions that should not be exposed, -+implementations of some @ref basic_json methods, and meta-programming helpers. - - @since version 2.1.0 - */ - namespace detail - { -+///////////// -+// helpers // -+///////////// -+ -+template struct is_basic_json : std::false_type {}; -+ -+NLOHMANN_BASIC_JSON_TPL_DECLARATION -+struct is_basic_json : std::true_type {}; -+ -+//////////////////////// -+// has_/is_ functions // -+//////////////////////// -+ -+// source: https://stackoverflow.com/a/37193089/4116453 -+ -+template -+struct is_complete_type : std::false_type {}; -+ -+template -+struct is_complete_type : std::true_type {}; -+ -+NLOHMANN_JSON_HAS_HELPER(mapped_type); -+NLOHMANN_JSON_HAS_HELPER(key_type); -+NLOHMANN_JSON_HAS_HELPER(value_type); -+NLOHMANN_JSON_HAS_HELPER(iterator); -+ -+template -+struct is_compatible_object_type_impl : std::false_type {}; -+ -+template -+struct is_compatible_object_type_impl -+{ -+ static constexpr auto value = -+ std::is_constructible::value and -+ std::is_constructible::value; -+}; -+ -+template -+struct is_compatible_string_type_impl : std::false_type {}; -+ -+template -+struct is_compatible_string_type_impl -+{ -+ static constexpr auto value = -+ std::is_same::value and -+ std::is_constructible::value; -+}; -+ -+template -+struct is_compatible_object_type -+{ -+ static auto constexpr value = is_compatible_object_type_impl < -+ conjunction>, -+ has_mapped_type, -+ has_key_type>::value, -+ typename BasicJsonType::object_t, CompatibleObjectType >::value; -+}; -+ -+template -+struct is_compatible_string_type -+{ -+ static auto constexpr value = is_compatible_string_type_impl < -+ conjunction>, -+ has_value_type>::value, -+ typename BasicJsonType::string_t, CompatibleStringType >::value; -+}; -+ -+template -+struct is_basic_json_nested_type -+{ -+ static auto constexpr value = std::is_same::value or -+ std::is_same::value or -+ std::is_same::value or -+ std::is_same::value; -+}; -+ -+template -+struct is_compatible_array_type -+{ -+ static auto constexpr value = -+ conjunction>, -+ negation>, -+ negation>, -+ negation>, -+ has_value_type, -+ has_iterator>::value; -+}; -+ -+template -+struct is_compatible_integer_type_impl : std::false_type {}; -+ -+template -+struct is_compatible_integer_type_impl -+{ -+ // is there an assert somewhere on overflows? -+ using RealLimits = std::numeric_limits; -+ using CompatibleLimits = std::numeric_limits; -+ -+ static constexpr auto value = -+ std::is_constructible::value and -+ CompatibleLimits::is_integer and -+ RealLimits::is_signed == CompatibleLimits::is_signed; -+}; -+ -+template -+struct is_compatible_integer_type -+{ -+ static constexpr auto value = -+ is_compatible_integer_type_impl < -+ std::is_integral::value and -+ not std::is_same::value, -+ RealIntegerType, CompatibleNumberIntegerType > ::value; -+}; -+ -+// trait checking if JSONSerializer::from_json(json const&, udt&) exists -+template -+struct has_from_json -+{ -+ private: -+ // also check the return type of from_json -+ template::from_json( -+ std::declval(), std::declval()))>::value>> -+ static int detect(U&&); -+ static void detect(...); -+ -+ public: -+ static constexpr bool value = std::is_integral>()))>::value; -+}; -+ -+// This trait checks if JSONSerializer::from_json(json const&) exists -+// this overload is used for non-default-constructible user-defined-types -+template -+struct has_non_default_from_json -+{ -+ private: -+ template < -+ typename U, -+ typename = enable_if_t::from_json(std::declval()))>::value >> -+ static int detect(U&&); -+ static void detect(...); -+ -+ public: -+ static constexpr bool value = std::is_integral>()))>::value; -+}; -+ -+// This trait checks if BasicJsonType::json_serializer::to_json exists -+template -+struct has_to_json -+{ -+ private: -+ template::to_json( -+ std::declval(), std::declval()))> -+ static int detect(U&&); -+ static void detect(...); -+ -+ public: -+ static constexpr bool value = std::is_integral>()))>::value; -+}; -+ -+template -+struct is_compatible_complete_type -+{ -+ static constexpr bool value = -+ not std::is_base_of::value and -+ not is_basic_json::value and -+ not is_basic_json_nested_type::value and -+ has_to_json::value; -+}; -+ -+template -+struct is_compatible_type -+ : conjunction, -+ is_compatible_complete_type> -+{ -+}; -+} -+} -+ -+// #include -+ -+ -+#include // exception -+#include // runtime_error -+#include // to_string -+ -+namespace nlohmann -+{ -+namespace detail -+{ - //////////////// - // exceptions // - //////////////// -@@ -419,6 +799,8 @@ json.exception.out_of_range.403 | key 'foo' not found - json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. - json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. - json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. -+json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON only supports integers numbers up to 9223372036854775807. | -+json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | - - @liveexample{The following code shows how an `out_of_range` exception can be - caught.,out_of_range} -@@ -481,9 +863,21 @@ class other_error : public exception - private: - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} - }; -+} -+} - -+// #include - - -+#include // array -+#include // and -+#include // size_t -+#include // uint8_t -+ -+namespace nlohmann -+{ -+namespace detail -+{ - /////////////////////////// - // JSON type enumeration // - /////////////////////////// -@@ -512,7 +906,7 @@ value with the default value for a given type - - @since version 1.0.0 - */ --enum class value_t : uint8_t -+enum class value_t : std::uint8_t - { - null, ///< null value - object, ///< object (unordered set of name/value pairs) -@@ -537,7 +931,7 @@ Returns an ordering that is similar to Python: - */ - inline bool operator<(const value_t lhs, const value_t rhs) noexcept - { -- static constexpr std::array order = {{ -+ static constexpr std::array order = {{ - 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, - 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */ - } -@@ -547,80 +941,558 @@ inline bool operator<(const value_t lhs, const value_t - const auto r_index = static_cast(rhs); - return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index]; - } -+} -+} - -+// #include - --///////////// --// helpers // --///////////// - --template struct is_basic_json : std::false_type {}; -+#include // transform -+#include // array -+#include // and, not -+#include // forward_list -+#include // inserter, front_inserter, end -+#include // map -+#include // string -+#include // tuple, make_tuple -+#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible -+#include // unordered_map -+#include // pair, declval -+#include // valarray - --NLOHMANN_BASIC_JSON_TPL_DECLARATION --struct is_basic_json : std::true_type {}; -+// #include - --// alias templates to reduce boilerplate --template --using enable_if_t = typename std::enable_if::type; -+// #include - --template --using uncvref_t = typename std::remove_cv::type>::type; -+// #include - --// implementation of C++14 index_sequence and affiliates --// source: https://stackoverflow.com/a/32223343 --template --struct index_sequence -+// #include -+ -+// #include -+ -+ -+namespace nlohmann - { -- using type = index_sequence; -- using value_type = std::size_t; -- static constexpr std::size_t size() noexcept -+namespace detail -+{ -+template -+void from_json(const BasicJsonType& j, typename std::nullptr_t& n) -+{ -+ if (JSON_UNLIKELY(not j.is_null())) - { -- return sizeof...(Ints); -+ JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()))); - } -+ n = nullptr; -+} -+ -+// overloads for basic_json template parameters -+template::value and -+ not std::is_same::value, -+ int> = 0> -+void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) -+{ -+ switch (static_cast(j)) -+ { -+ case value_t::number_unsigned: -+ { -+ val = static_cast(*j.template get_ptr()); -+ break; -+ } -+ case value_t::number_integer: -+ { -+ val = static_cast(*j.template get_ptr()); -+ break; -+ } -+ case value_t::number_float: -+ { -+ val = static_cast(*j.template get_ptr()); -+ break; -+ } -+ -+ default: -+ JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); -+ } -+} -+ -+template -+void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) -+{ -+ if (JSON_UNLIKELY(not j.is_boolean())) -+ { -+ JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); -+ } -+ b = *j.template get_ptr(); -+} -+ -+template -+void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) -+{ -+ if (JSON_UNLIKELY(not j.is_string())) -+ { -+ JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); -+ } -+ s = *j.template get_ptr(); -+} -+ -+template < -+ typename BasicJsonType, typename CompatibleStringType, -+ enable_if_t < -+ is_compatible_string_type::value and -+ not std::is_same::value, -+ int > = 0 > -+void from_json(const BasicJsonType& j, CompatibleStringType& s) -+{ -+ if (JSON_UNLIKELY(not j.is_string())) -+ { -+ JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); -+ } -+ -+ s = *j.template get_ptr(); -+} -+ -+template -+void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) -+{ -+ get_arithmetic_value(j, val); -+} -+ -+template -+void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) -+{ -+ get_arithmetic_value(j, val); -+} -+ -+template -+void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) -+{ -+ get_arithmetic_value(j, val); -+} -+ -+template::value, int> = 0> -+void from_json(const BasicJsonType& j, EnumType& e) -+{ -+ typename std::underlying_type::type val; -+ get_arithmetic_value(j, val); -+ e = static_cast(val); -+} -+ -+template -+void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) -+{ -+ if (JSON_UNLIKELY(not j.is_array())) -+ { -+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); -+ } -+ arr = *j.template get_ptr(); -+} -+ -+// forward_list doesn't have an insert method -+template::value, int> = 0> -+void from_json(const BasicJsonType& j, std::forward_list& l) -+{ -+ if (JSON_UNLIKELY(not j.is_array())) -+ { -+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); -+ } -+ std::transform(j.rbegin(), j.rend(), -+ std::front_inserter(l), [](const BasicJsonType & i) -+ { -+ return i.template get(); -+ }); -+} -+ -+// valarray doesn't have an insert method -+template::value, int> = 0> -+void from_json(const BasicJsonType& j, std::valarray& l) -+{ -+ if (JSON_UNLIKELY(not j.is_array())) -+ { -+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); -+ } -+ l.resize(j.size()); -+ std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l)); -+} -+ -+template -+void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/) -+{ -+ using std::end; -+ -+ std::transform(j.begin(), j.end(), -+ std::inserter(arr, end(arr)), [](const BasicJsonType & i) -+ { -+ // get() returns *this, this won't call a from_json -+ // method when value_type is BasicJsonType -+ return i.template get(); -+ }); -+} -+ -+template -+auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/) -+-> decltype( -+ arr.reserve(std::declval()), -+ void()) -+{ -+ using std::end; -+ -+ arr.reserve(j.size()); -+ std::transform(j.begin(), j.end(), -+ std::inserter(arr, end(arr)), [](const BasicJsonType & i) -+ { -+ // get() returns *this, this won't call a from_json -+ // method when value_type is BasicJsonType -+ return i.template get(); -+ }); -+} -+ -+template -+void from_json_array_impl(const BasicJsonType& j, std::array& arr, priority_tag<2> /*unused*/) -+{ -+ for (std::size_t i = 0; i < N; ++i) -+ { -+ arr[i] = j.at(i).template get(); -+ } -+} -+ -+template < -+ typename BasicJsonType, typename CompatibleArrayType, -+ enable_if_t < -+ is_compatible_array_type::value and -+ not std::is_same::value and -+ std::is_constructible < -+ BasicJsonType, typename CompatibleArrayType::value_type >::value, -+ int > = 0 > -+void from_json(const BasicJsonType& j, CompatibleArrayType& arr) -+{ -+ if (JSON_UNLIKELY(not j.is_array())) -+ { -+ JSON_THROW(type_error::create(302, "type must be array, but is " + -+ std::string(j.type_name()))); -+ } -+ -+ from_json_array_impl(j, arr, priority_tag<2> {}); -+} -+ -+template::value, int> = 0> -+void from_json(const BasicJsonType& j, CompatibleObjectType& obj) -+{ -+ if (JSON_UNLIKELY(not j.is_object())) -+ { -+ JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); -+ } -+ -+ auto inner_object = j.template get_ptr(); -+ using value_type = typename CompatibleObjectType::value_type; -+ std::transform( -+ inner_object->begin(), inner_object->end(), -+ std::inserter(obj, obj.begin()), -+ [](typename BasicJsonType::object_t::value_type const & p) -+ { -+ return value_type(p.first, p.second.template get()); -+ }); -+} -+ -+// overload for arithmetic types, not chosen for basic_json template arguments -+// (BooleanType, etc..); note: Is it really necessary to provide explicit -+// overloads for boolean_t etc. in case of a custom BooleanType which is not -+// an arithmetic type? -+template::value and -+ not std::is_same::value and -+ not std::is_same::value and -+ not std::is_same::value and -+ not std::is_same::value, -+ int> = 0> -+void from_json(const BasicJsonType& j, ArithmeticType& val) -+{ -+ switch (static_cast(j)) -+ { -+ case value_t::number_unsigned: -+ { -+ val = static_cast(*j.template get_ptr()); -+ break; -+ } -+ case value_t::number_integer: -+ { -+ val = static_cast(*j.template get_ptr()); -+ break; -+ } -+ case value_t::number_float: -+ { -+ val = static_cast(*j.template get_ptr()); -+ break; -+ } -+ case value_t::boolean: -+ { -+ val = static_cast(*j.template get_ptr()); -+ break; -+ } -+ -+ default: -+ JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); -+ } -+} -+ -+template -+void from_json(const BasicJsonType& j, std::pair& p) -+{ -+ p = {j.at(0).template get(), j.at(1).template get()}; -+} -+ -+template -+void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence) -+{ -+ t = std::make_tuple(j.at(Idx).template get::type>()...); -+} -+ -+template -+void from_json(const BasicJsonType& j, std::tuple& t) -+{ -+ from_json_tuple_impl(j, t, index_sequence_for {}); -+} -+ -+template ::value>> -+void from_json(const BasicJsonType& j, std::map& m) -+{ -+ if (JSON_UNLIKELY(not j.is_array())) -+ { -+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); -+ } -+ for (const auto& p : j) -+ { -+ if (JSON_UNLIKELY(not p.is_array())) -+ { -+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); -+ } -+ m.emplace(p.at(0).template get(), p.at(1).template get()); -+ } -+} -+ -+template ::value>> -+void from_json(const BasicJsonType& j, std::unordered_map& m) -+{ -+ if (JSON_UNLIKELY(not j.is_array())) -+ { -+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); -+ } -+ for (const auto& p : j) -+ { -+ if (JSON_UNLIKELY(not p.is_array())) -+ { -+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); -+ } -+ m.emplace(p.at(0).template get(), p.at(1).template get()); -+ } -+} -+ -+struct from_json_fn -+{ -+ private: -+ template -+ auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const -+ noexcept(noexcept(from_json(j, val))) -+ -> decltype(from_json(j, val), void()) -+ { -+ return from_json(j, val); -+ } -+ -+ template -+ void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept -+ { -+ static_assert(sizeof(BasicJsonType) == 0, -+ "could not find from_json() method in T's namespace"); -+#ifdef _MSC_VER -+ // MSVC does not show a stacktrace for the above assert -+ using decayed = uncvref_t; -+ static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, -+ "forcing MSVC stacktrace to show which T we're talking about."); -+#endif -+ } -+ -+ public: -+ template -+ void operator()(const BasicJsonType& j, T& val) const -+ noexcept(noexcept(std::declval().call(j, val, priority_tag<1> {}))) -+ { -+ return call(j, val, priority_tag<1> {}); -+ } - }; -+} - --template --struct merge_and_renumber; -+/// namespace to hold default `from_json` function -+/// to see why this is required: -+/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html -+namespace -+{ -+constexpr const auto& from_json = detail::static_const::value; -+} -+} - --template --struct merge_and_renumber, index_sequence> -- : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; -+// #include - --template --struct make_index_sequence -- : merge_and_renumber < typename make_index_sequence < N / 2 >::type, -- typename make_index_sequence < N - N / 2 >::type > {}; - --template<> struct make_index_sequence<0> : index_sequence<> {}; --template<> struct make_index_sequence<1> : index_sequence<0> {}; -+#include // or, and, not -+#include // begin, end -+#include // tuple, get -+#include // is_same, is_constructible, is_floating_point, is_enum, underlying_type -+#include // move, forward, declval, pair -+#include // valarray -+#include // vector - --template --using index_sequence_for = make_index_sequence; -+// #include - --/* --Implementation of two C++17 constructs: conjunction, negation. This is needed --to avoid evaluating all the traits in a condition -+// #include - --For example: not std::is_same::value and has_value_type::value --will not compile when T = void (on MSVC at least). Whereas --conjunction>, has_value_type>::value will --stop evaluating if negation<...>::value == false -+// #include - --Please note that those constructs must be used with caution, since symbols can --become very long quickly (which can slow down compilation and cause MSVC --internal compiler errors). Only use it when you have to (see example ahead). --*/ --template struct conjunction : std::true_type {}; --template struct conjunction : B1 {}; --template --struct conjunction : std::conditional, B1>::type {}; -+// #include - --template struct negation : std::integral_constant {}; - --// dispatch utility (taken from ranges-v3) --template struct priority_tag : priority_tag < N - 1 > {}; --template<> struct priority_tag<0> {}; -+#include // size_t -+#include // string, to_string -+#include // input_iterator_tag - -+// #include - -+ -+namespace nlohmann -+{ -+namespace detail -+{ -+/// proxy class for the items() function -+template class iteration_proxy -+{ -+ private: -+ /// helper class for iteration -+ class iteration_proxy_internal -+ { -+ public: -+ using difference_type = std::ptrdiff_t; -+ using value_type = iteration_proxy_internal; -+ using pointer = iteration_proxy_internal*; -+ using reference = iteration_proxy_internal&; -+ using iterator_category = std::input_iterator_tag; -+ -+ private: -+ /// the iterator -+ IteratorType anchor; -+ /// an index for arrays (used to create key names) -+ std::size_t array_index = 0; -+ /// last stringified array index -+ mutable std::size_t array_index_last = 0; -+ /// a string representation of the array index -+ mutable std::string array_index_str = "0"; -+ /// an empty string (to return a reference for primitive values) -+ const std::string empty_str = ""; -+ -+ public: -+ explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {} -+ -+ iteration_proxy_internal(const iteration_proxy_internal&) = default; -+ iteration_proxy_internal& operator=(const iteration_proxy_internal&) = default; -+ -+ /// dereference operator (needed for range-based for) -+ iteration_proxy_internal& operator*() -+ { -+ return *this; -+ } -+ -+ /// increment operator (needed for range-based for) -+ iteration_proxy_internal& operator++() -+ { -+ ++anchor; -+ ++array_index; -+ -+ return *this; -+ } -+ -+ /// equality operator (needed for InputIterator) -+ bool operator==(const iteration_proxy_internal& o) const noexcept -+ { -+ return anchor == o.anchor; -+ } -+ -+ /// inequality operator (needed for range-based for) -+ bool operator!=(const iteration_proxy_internal& o) const noexcept -+ { -+ return anchor != o.anchor; -+ } -+ -+ /// return key of the iterator -+ const std::string& key() const -+ { -+ assert(anchor.m_object != nullptr); -+ -+ switch (anchor.m_object->type()) -+ { -+ // use integer array index as key -+ case value_t::array: -+ { -+ if (array_index != array_index_last) -+ { -+ array_index_str = std::to_string(array_index); -+ array_index_last = array_index; -+ } -+ return array_index_str; -+ } -+ -+ // use key from the object -+ case value_t::object: -+ return anchor.key(); -+ -+ // use an empty key for all primitive types -+ default: -+ return empty_str; -+ } -+ } -+ -+ /// return value of the iterator -+ typename IteratorType::reference value() const -+ { -+ return anchor.value(); -+ } -+ }; -+ -+ /// the container to iterate -+ typename IteratorType::reference container; -+ -+ public: -+ /// construct iteration proxy from a container -+ explicit iteration_proxy(typename IteratorType::reference cont) noexcept -+ : container(cont) {} -+ -+ /// return iterator begin (needed for range-based for) -+ iteration_proxy_internal begin() noexcept -+ { -+ return iteration_proxy_internal(container.begin()); -+ } -+ -+ /// return iterator end (needed for range-based for) -+ iteration_proxy_internal end() noexcept -+ { -+ return iteration_proxy_internal(container.end()); -+ } -+}; -+} -+} -+ -+ -+namespace nlohmann -+{ -+namespace detail -+{ - ////////////////// - // constructors // - ////////////////// -@@ -657,6 +1529,16 @@ struct external_constructor - j.m_value = std::move(s); - j.assert_invariant(); - } -+ -+ template::value, -+ int> = 0> -+ static void construct(BasicJsonType& j, const CompatibleStringType& str) -+ { -+ j.m_type = value_t::string; -+ j.m_value.string = j.template create(str); -+ j.assert_invariant(); -+ } - }; - - template<> -@@ -783,159 +1665,6 @@ struct external_constructor - } - }; - -- --//////////////////////// --// has_/is_ functions // --//////////////////////// -- --/*! --@brief Helper to determine whether there's a key_type for T. -- --This helper is used to tell associative containers apart from other containers --such as sequence containers. For instance, `std::map` passes the test as it --contains a `mapped_type`, whereas `std::vector` fails the test. -- --@sa http://stackoverflow.com/a/7728728/266378 --@since version 1.0.0, overworked in version 2.0.6 --*/ --#define NLOHMANN_JSON_HAS_HELPER(type) \ -- template struct has_##type { \ -- private: \ -- template \ -- static int detect(U &&); \ -- static void detect(...); \ -- public: \ -- static constexpr bool value = \ -- std::is_integral()))>::value; \ -- } -- --NLOHMANN_JSON_HAS_HELPER(mapped_type); --NLOHMANN_JSON_HAS_HELPER(key_type); --NLOHMANN_JSON_HAS_HELPER(value_type); --NLOHMANN_JSON_HAS_HELPER(iterator); -- --#undef NLOHMANN_JSON_HAS_HELPER -- -- --template --struct is_compatible_object_type_impl : std::false_type {}; -- --template --struct is_compatible_object_type_impl --{ -- static constexpr auto value = -- std::is_constructible::value and -- std::is_constructible::value; --}; -- --template --struct is_compatible_object_type --{ -- static auto constexpr value = is_compatible_object_type_impl < -- conjunction>, -- has_mapped_type, -- has_key_type>::value, -- typename BasicJsonType::object_t, CompatibleObjectType >::value; --}; -- --template --struct is_basic_json_nested_type --{ -- static auto constexpr value = std::is_same::value or -- std::is_same::value or -- std::is_same::value or -- std::is_same::value; --}; -- --template --struct is_compatible_array_type --{ -- static auto constexpr value = -- conjunction>, -- negation>, -- negation>, -- negation>, -- has_value_type, -- has_iterator>::value; --}; -- --template --struct is_compatible_integer_type_impl : std::false_type {}; -- --template --struct is_compatible_integer_type_impl --{ -- // is there an assert somewhere on overflows? -- using RealLimits = std::numeric_limits; -- using CompatibleLimits = std::numeric_limits; -- -- static constexpr auto value = -- std::is_constructible::value and -- CompatibleLimits::is_integer and -- RealLimits::is_signed == CompatibleLimits::is_signed; --}; -- --template --struct is_compatible_integer_type --{ -- static constexpr auto value = -- is_compatible_integer_type_impl < -- std::is_integral::value and -- not std::is_same::value, -- RealIntegerType, CompatibleNumberIntegerType >::value; --}; -- -- --// trait checking if JSONSerializer::from_json(json const&, udt&) exists --template --struct has_from_json --{ -- private: -- // also check the return type of from_json -- template::from_json( -- std::declval(), std::declval()))>::value>> -- static int detect(U&&); -- static void detect(...); -- -- public: -- static constexpr bool value = std::is_integral>()))>::value; --}; -- --// This trait checks if JSONSerializer::from_json(json const&) exists --// this overload is used for non-default-constructible user-defined-types --template --struct has_non_default_from_json --{ -- private: -- template::from_json(std::declval()))>::value>> -- static int detect(U&&); -- static void detect(...); -- -- public: -- static constexpr bool value = std::is_integral>()))>::value; --}; -- --// This trait checks if BasicJsonType::json_serializer::to_json exists --template --struct has_to_json --{ -- private: -- template::to_json( -- std::declval(), std::declval()))> -- static int detect(U&&); -- static void detect(...); -- -- public: -- static constexpr bool value = std::is_integral>()))>::value; --}; -- -- - ///////////// - // to_json // - ///////////// -@@ -1006,7 +1735,7 @@ void to_json(BasicJsonType& j, const CompatibleArrayTy - - template::value, int> = 0> --void to_json(BasicJsonType& j, std::valarray arr) -+void to_json(BasicJsonType& j, const std::valarray& arr) - { - external_constructor::construct(j, std::move(arr)); - } -@@ -1043,6 +1772,14 @@ void to_json(BasicJsonType& j, const std::pair::iteration_proxy_internal>::value, int> = 0> -+void to_json(BasicJsonType& j, T b) noexcept -+{ -+ j = {{b.key(), b.value()}}; -+} -+ - template - void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence) - { -@@ -1055,261 +1792,6 @@ void to_json(BasicJsonType& j, const std::tuple {}); - } - --/////////////// --// from_json // --/////////////// -- --// overloads for basic_json template parameters --template::value and -- not std::is_same::value, -- int> = 0> --void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) --{ -- switch (static_cast(j)) -- { -- case value_t::number_unsigned: -- { -- val = static_cast(*j.template get_ptr()); -- break; -- } -- case value_t::number_integer: -- { -- val = static_cast(*j.template get_ptr()); -- break; -- } -- case value_t::number_float: -- { -- val = static_cast(*j.template get_ptr()); -- break; -- } -- -- default: -- JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); -- } --} -- --template --void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) --{ -- if (JSON_UNLIKELY(not j.is_boolean())) -- { -- JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); -- } -- b = *j.template get_ptr(); --} -- --template --void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) --{ -- if (JSON_UNLIKELY(not j.is_string())) -- { -- JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); -- } -- s = *j.template get_ptr(); --} -- --template --void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) --{ -- get_arithmetic_value(j, val); --} -- --template --void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) --{ -- get_arithmetic_value(j, val); --} -- --template --void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) --{ -- get_arithmetic_value(j, val); --} -- --template::value, int> = 0> --void from_json(const BasicJsonType& j, EnumType& e) --{ -- typename std::underlying_type::type val; -- get_arithmetic_value(j, val); -- e = static_cast(val); --} -- --template --void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) --{ -- if (JSON_UNLIKELY(not j.is_array())) -- { -- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); -- } -- arr = *j.template get_ptr(); --} -- --// forward_list doesn't have an insert method --template::value, int> = 0> --void from_json(const BasicJsonType& j, std::forward_list& l) --{ -- if (JSON_UNLIKELY(not j.is_array())) -- { -- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); -- } -- std::transform(j.rbegin(), j.rend(), -- std::front_inserter(l), [](const BasicJsonType & i) -- { -- return i.template get(); -- }); --} -- --// valarray doesn't have an insert method --template::value, int> = 0> --void from_json(const BasicJsonType& j, std::valarray& l) --{ -- if (JSON_UNLIKELY(not j.is_array())) -- { -- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); -- } -- l.resize(j.size()); -- std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l)); --} -- --template --void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/) --{ -- using std::end; -- -- std::transform(j.begin(), j.end(), -- std::inserter(arr, end(arr)), [](const BasicJsonType & i) -- { -- // get() returns *this, this won't call a from_json -- // method when value_type is BasicJsonType -- return i.template get(); -- }); --} -- --template --auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/) ---> decltype( -- arr.reserve(std::declval()), -- void()) --{ -- using std::end; -- -- arr.reserve(j.size()); -- std::transform(j.begin(), j.end(), -- std::inserter(arr, end(arr)), [](const BasicJsonType & i) -- { -- // get() returns *this, this won't call a from_json -- // method when value_type is BasicJsonType -- return i.template get(); -- }); --} -- --template --void from_json_array_impl(const BasicJsonType& j, std::array& arr, priority_tag<2> /*unused*/) --{ -- for (std::size_t i = 0; i < N; ++i) -- { -- arr[i] = j.at(i).template get(); -- } --} -- --template::value and -- std::is_convertible::value and -- not std::is_same::value, int> = 0> --void from_json(const BasicJsonType& j, CompatibleArrayType& arr) --{ -- if (JSON_UNLIKELY(not j.is_array())) -- { -- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); -- } -- -- from_json_array_impl(j, arr, priority_tag<2> {}); --} -- --template::value, int> = 0> --void from_json(const BasicJsonType& j, CompatibleObjectType& obj) --{ -- if (JSON_UNLIKELY(not j.is_object())) -- { -- JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); -- } -- -- auto inner_object = j.template get_ptr(); -- using value_type = typename CompatibleObjectType::value_type; -- std::transform( -- inner_object->begin(), inner_object->end(), -- std::inserter(obj, obj.begin()), -- [](typename BasicJsonType::object_t::value_type const & p) -- { -- return value_type(p.first, p.second.template get()); -- }); --} -- --// overload for arithmetic types, not chosen for basic_json template arguments --// (BooleanType, etc..); note: Is it really necessary to provide explicit --// overloads for boolean_t etc. in case of a custom BooleanType which is not --// an arithmetic type? --template::value and -- not std::is_same::value and -- not std::is_same::value and -- not std::is_same::value and -- not std::is_same::value, -- int> = 0> --void from_json(const BasicJsonType& j, ArithmeticType& val) --{ -- switch (static_cast(j)) -- { -- case value_t::number_unsigned: -- { -- val = static_cast(*j.template get_ptr()); -- break; -- } -- case value_t::number_integer: -- { -- val = static_cast(*j.template get_ptr()); -- break; -- } -- case value_t::number_float: -- { -- val = static_cast(*j.template get_ptr()); -- break; -- } -- case value_t::boolean: -- { -- val = static_cast(*j.template get_ptr()); -- break; -- } -- -- default: -- JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); -- } --} -- --template --void from_json(const BasicJsonType& j, std::pair& p) --{ -- p = {j.at(0).template get(), j.at(1).template get()}; --} -- --template --void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence) --{ -- t = std::make_tuple(j.at(Idx).template get::type>()...); --} -- --template --void from_json(const BasicJsonType& j, std::tuple& t) --{ -- from_json_tuple_impl(j, t, index_sequence_for {}); --} -- - struct to_json_fn - { - private: -@@ -1342,50 +1824,39 @@ struct to_json_fn - return call(j, std::forward(val), priority_tag<1> {}); - } - }; -+} - --struct from_json_fn -+/// namespace to hold default `to_json` function -+namespace - { -- private: -- template -- auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const -- noexcept(noexcept(from_json(j, val))) -- -> decltype(from_json(j, val), void()) -- { -- return from_json(j, val); -- } -+constexpr const auto& to_json = detail::static_const::value; -+} -+} - -- template -- void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept -- { -- static_assert(sizeof(BasicJsonType) == 0, -- "could not find from_json() method in T's namespace"); --#ifdef _MSC_VER -- // MSVC does not show a stacktrace for the above assert -- using decayed = uncvref_t; -- static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, -- "forcing MSVC stacktrace to show which T we're talking about."); --#endif -- } -+// #include - -- public: -- template -- void operator()(const BasicJsonType& j, T& val) const -- noexcept(noexcept(std::declval().call(j, val, priority_tag<1> {}))) -- { -- return call(j, val, priority_tag<1> {}); -- } --}; - --// taken from ranges-v3 --template --struct static_const --{ -- static constexpr T value{}; --}; -+#include // assert -+#include // size_t -+#include // strlen -+#include // istream -+#include // begin, end, iterator_traits, random_access_iterator_tag, distance, next -+#include // shared_ptr, make_shared, addressof -+#include // accumulate -+#include // string, char_traits -+#include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer -+#include // pair, declval - --template --constexpr T static_const::value; -+// #include - -+ -+namespace nlohmann -+{ -+namespace detail -+{ -+/// the supported input formats -+enum class input_format_t { json, cbor, msgpack, ubjson }; -+ - //////////////////// - // input adapters // - //////////////////// -@@ -1394,19 +1865,17 @@ constexpr T static_const::value; - @brief abstract input adapter interface - - Produces a stream of std::char_traits::int_type characters from a --std::istream, a buffer, or some other input type. Accepts the return of exactly --one non-EOF character for future input. The int_type characters returned --consist of all valid char values as positive values (typically unsigned char), --plus an EOF value outside that range, specified by the value of the function --std::char_traits::eof(). This value is typically -1, but could be any --arbitrary value which is not a valid char value. -+std::istream, a buffer, or some other input type. Accepts the return of -+exactly one non-EOF character for future input. The int_type characters -+returned consist of all valid char values as positive values (typically -+unsigned char), plus an EOF value outside that range, specified by the value -+of the function std::char_traits::eof(). This value is typically -1, but -+could be any arbitrary value which is not a valid char value. - */ - struct input_adapter_protocol - { - /// get a character [0,255] or std::char_traits::eof(). - virtual std::char_traits::int_type get_character() = 0; -- /// restore the last non-eof() character to input -- virtual void unget_character() = 0; - virtual ~input_adapter_protocol() = default; - }; - -@@ -1434,34 +1903,7 @@ class input_stream_adapter : public input_adapter_prot - - explicit input_stream_adapter(std::istream& i) - : is(i), sb(*i.rdbuf()) -- { -- // skip byte order mark -- std::char_traits::int_type c; -- if ((c = get_character()) == 0xEF) -- { -- if ((c = get_character()) == 0xBB) -- { -- if ((c = get_character()) == 0xBF) -- { -- return; // Ignore BOM -- } -- else if (c != std::char_traits::eof()) -- { -- is.unget(); -- } -- is.putback('\xBB'); -- } -- else if (c != std::char_traits::eof()) -- { -- is.unget(); -- } -- is.putback('\xEF'); -- } -- else if (c != std::char_traits::eof()) -- { -- is.unget(); // no byte order mark; process as usual -- } -- } -+ {} - - // delete because of pointer members - input_stream_adapter(const input_stream_adapter&) = delete; -@@ -1475,11 +1917,6 @@ class input_stream_adapter : public input_adapter_prot - return sb.sbumpc(); - } - -- void unget_character() override -- { -- sb.sungetc(); // is.unget() avoided for performance -- } -- - private: - /// the associated input stream - std::istream& is; -@@ -1491,14 +1928,8 @@ class input_buffer_adapter : public input_adapter_prot - { - public: - input_buffer_adapter(const char* b, const std::size_t l) -- : cursor(b), limit(b + l), start(b) -- { -- // skip byte order mark -- if (l >= 3 and b[0] == '\xEF' and b[1] == '\xBB' and b[2] == '\xBF') -- { -- cursor += 3; -- } -- } -+ : cursor(b), limit(b + l) -+ {} - - // delete because of pointer members - input_buffer_adapter(const input_buffer_adapter&) = delete; -@@ -1514,21 +1945,164 @@ class input_buffer_adapter : public input_adapter_prot - return std::char_traits::eof(); - } - -- void unget_character() noexcept override -+ private: -+ /// pointer to the current character -+ const char* cursor; -+ /// pointer past the last character -+ const char* const limit; -+}; -+ -+template -+class wide_string_input_adapter : public input_adapter_protocol -+{ -+ public: -+ explicit wide_string_input_adapter(const WideStringType& w) : str(w) {} -+ -+ std::char_traits::int_type get_character() noexcept override - { -- if (JSON_LIKELY(cursor > start)) -+ // check if buffer needs to be filled -+ if (utf8_bytes_index == utf8_bytes_filled) - { -- --cursor; -+ if (sizeof(typename WideStringType::value_type) == 2) -+ { -+ fill_buffer_utf16(); -+ } -+ else -+ { -+ fill_buffer_utf32(); -+ } -+ -+ assert(utf8_bytes_filled > 0); -+ assert(utf8_bytes_index == 0); - } -+ -+ // use buffer -+ assert(utf8_bytes_filled > 0); -+ assert(utf8_bytes_index < utf8_bytes_filled); -+ return utf8_bytes[utf8_bytes_index++]; - } - - private: -- /// pointer to the current character -- const char* cursor; -- /// pointer past the last character -- const char* limit; -- /// pointer to the first character -- const char* start; -+ void fill_buffer_utf16() -+ { -+ utf8_bytes_index = 0; -+ -+ if (current_wchar == str.size()) -+ { -+ utf8_bytes[0] = std::char_traits::eof(); -+ utf8_bytes_filled = 1; -+ } -+ else -+ { -+ // get the current character -+ const int wc = static_cast(str[current_wchar++]); -+ -+ // UTF-16 to UTF-8 encoding -+ if (wc < 0x80) -+ { -+ utf8_bytes[0] = wc; -+ utf8_bytes_filled = 1; -+ } -+ else if (wc <= 0x7FF) -+ { -+ utf8_bytes[0] = 0xC0 | ((wc >> 6)); -+ utf8_bytes[1] = 0x80 | (wc & 0x3F); -+ utf8_bytes_filled = 2; -+ } -+ else if (0xD800 > wc or wc >= 0xE000) -+ { -+ utf8_bytes[0] = 0xE0 | ((wc >> 12)); -+ utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F); -+ utf8_bytes[2] = 0x80 | (wc & 0x3F); -+ utf8_bytes_filled = 3; -+ } -+ else -+ { -+ if (current_wchar < str.size()) -+ { -+ const int wc2 = static_cast(str[current_wchar++]); -+ const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF)); -+ utf8_bytes[0] = 0xf0 | (charcode >> 18); -+ utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F); -+ utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F); -+ utf8_bytes[3] = 0x80 | (charcode & 0x3F); -+ utf8_bytes_filled = 4; -+ } -+ else -+ { -+ // unknown character -+ ++current_wchar; -+ utf8_bytes[0] = wc; -+ utf8_bytes_filled = 1; -+ } -+ } -+ } -+ } -+ -+ void fill_buffer_utf32() -+ { -+ utf8_bytes_index = 0; -+ -+ if (current_wchar == str.size()) -+ { -+ utf8_bytes[0] = std::char_traits::eof(); -+ utf8_bytes_filled = 1; -+ } -+ else -+ { -+ // get the current character -+ const int wc = static_cast(str[current_wchar++]); -+ -+ // UTF-32 to UTF-8 encoding -+ if (wc < 0x80) -+ { -+ utf8_bytes[0] = wc; -+ utf8_bytes_filled = 1; -+ } -+ else if (wc <= 0x7FF) -+ { -+ utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F); -+ utf8_bytes[1] = 0x80 | (wc & 0x3F); -+ utf8_bytes_filled = 2; -+ } -+ else if (wc <= 0xFFFF) -+ { -+ utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F); -+ utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F); -+ utf8_bytes[2] = 0x80 | (wc & 0x3F); -+ utf8_bytes_filled = 3; -+ } -+ else if (wc <= 0x10FFFF) -+ { -+ utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07); -+ utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F); -+ utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F); -+ utf8_bytes[3] = 0x80 | (wc & 0x3F); -+ utf8_bytes_filled = 4; -+ } -+ else -+ { -+ // unknown character -+ utf8_bytes[0] = wc; -+ utf8_bytes_filled = 1; -+ } -+ } -+ } -+ -+ private: -+ /// the wstring to process -+ const WideStringType& str; -+ -+ /// index of the current wchar in str -+ std::size_t current_wchar = 0; -+ -+ /// a buffer for UTF-8 bytes -+ std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; -+ -+ /// index to the utf8_codes array for the next valid byte -+ std::size_t utf8_bytes_index = 0; -+ /// number of valid bytes in the utf8_codes array -+ std::size_t utf8_bytes_filled = 0; - }; - - class input_adapter -@@ -1544,6 +2118,15 @@ class input_adapter - input_adapter(std::istream&& i) - : ia(std::make_shared(i)) {} - -+ input_adapter(const std::wstring& ws) -+ : ia(std::make_shared>(ws)) {} -+ -+ input_adapter(const std::u16string& ws) -+ : ia(std::make_shared>(ws)) {} -+ -+ input_adapter(const std::u32string& ws) -+ : ia(std::make_shared>(ws)) {} -+ - /// input adapter for buffer - template - -+ -+#include // localeconv -+#include // size_t -+#include // strtof, strtod, strtold, strtoll, strtoull -+#include // snprintf -+#include // initializer_list -+#include // char_traits, string -+#include // vector -+ -+// #include -+ -+// #include -+ -+ -+namespace nlohmann -+{ -+namespace detail -+{ -+/////////// -+// lexer // -+/////////// -+ - /*! - @brief lexical analysis - -@@ -1640,6 +2245,7 @@ class lexer - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; -+ using string_t = typename BasicJsonType::string_t; - - public: - /// token types for the parser -@@ -1701,12 +2307,14 @@ class lexer - return "end of input"; - case token_type::literal_or_value: - return "'[', '{', or a literal"; -+ // LCOV_EXCL_START - default: // catch non-enum values -- return "unknown token"; // LCOV_EXCL_LINE -+ return "unknown token"; -+ // LCOV_EXCL_STOP - } - } - -- explicit lexer(detail::input_adapter_t adapter) -+ explicit lexer(detail::input_adapter_t&& adapter) - : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {} - - // delete because of pointer members -@@ -1819,9 +2427,10 @@ class lexer - @brief scan a string literal - - This function scans a string according to Sect. 7 of RFC 7159. While -- scanning, bytes are escaped and copied into buffer yytext. Then the function -- returns successfully, yytext is *not* null-terminated (as it may contain \0 -- bytes), and yytext.size() is the number of bytes in the string. -+ scanning, bytes are escaped and copied into buffer token_buffer. Then the -+ function returns successfully, token_buffer is *not* null-terminated (as it -+ may contain \0 bytes), and token_buffer.size() is the number of bytes in the -+ string. - - @return token_type::value_string if string could be successfully scanned, - token_type::parse_error otherwise -@@ -1831,7 +2440,7 @@ class lexer - */ - token_type scan_string() - { -- // reset yytext (ignore opening quote) -+ // reset token_buffer (ignore opening quote) - reset(); - - // we entered the function by reading an open quote -@@ -2303,7 +2912,7 @@ class lexer - contains cycles, but any cycle can be left when EOF is read. Therefore, - the function is guaranteed to terminate. - -- During scanning, the read bytes are stored in yytext. This string is -+ During scanning, the read bytes are stored in token_buffer. This string is - then converted to a signed integer, an unsigned integer, or a - floating-point number. - -@@ -2317,7 +2926,7 @@ class lexer - */ - token_type scan_number() - { -- // reset yytext to store the number's bytes -+ // reset token_buffer to store the number's bytes - reset(); - - // the type of the parsed number; initially set to unsigned; will be -@@ -2353,11 +2962,13 @@ class lexer - goto scan_number_any1; - } - -+ // LCOV_EXCL_START - default: - { - // all other characters are rejected outside scan_number() -- assert(false); // LCOV_EXCL_LINE -+ assert(false); - } -+ // LCOV_EXCL_STOP - } - - scan_number_minus: -@@ -2601,10 +3212,10 @@ scan_number_done: - // try to parse integers first and fall back to floats - if (number_type == token_type::value_unsigned) - { -- const auto x = std::strtoull(yytext.data(), &endptr, 10); -+ const auto x = std::strtoull(token_buffer.data(), &endptr, 10); - - // we checked the number format before -- assert(endptr == yytext.data() + yytext.size()); -+ assert(endptr == token_buffer.data() + token_buffer.size()); - - if (errno == 0) - { -@@ -2617,10 +3228,10 @@ scan_number_done: - } - else if (number_type == token_type::value_integer) - { -- const auto x = std::strtoll(yytext.data(), &endptr, 10); -+ const auto x = std::strtoll(token_buffer.data(), &endptr, 10); - - // we checked the number format before -- assert(endptr == yytext.data() + yytext.size()); -+ assert(endptr == token_buffer.data() + token_buffer.size()); - - if (errno == 0) - { -@@ -2634,10 +3245,10 @@ scan_number_done: - - // this code is reached if we parse a floating-point number or if an - // integer conversion above failed -- strtof(value_float, yytext.data(), &endptr); -+ strtof(value_float, token_buffer.data(), &endptr); - - // we checked the number format before -- assert(endptr == yytext.data() + yytext.size()); -+ assert(endptr == token_buffer.data() + token_buffer.size()); - - return token_type::value_float; - } -@@ -2666,10 +3277,10 @@ scan_number_done: - // input management - ///////////////////// - -- /// reset yytext; current character is beginning of token -+ /// reset token_buffer; current character is beginning of token - void reset() noexcept - { -- yytext.clear(); -+ token_buffer.clear(); - token_string.clear(); - token_string.push_back(std::char_traits::to_char_type(current)); - } -@@ -2687,7 +3298,16 @@ scan_number_done: - std::char_traits::int_type get() - { - ++chars_read; -- current = ia->get_character(); -+ if (next_unget) -+ { -+ // just reset the next_unget variable and work with current -+ next_unget = false; -+ } -+ else -+ { -+ current = ia->get_character(); -+ } -+ - if (JSON_LIKELY(current != std::char_traits::eof())) - { - token_string.push_back(std::char_traits::to_char_type(current)); -@@ -2695,22 +3315,29 @@ scan_number_done: - return current; - } - -- /// unget current character (return it again on next get) -+ /*! -+ @brief unget current character (read it again on next get) -+ -+ We implement unget by setting variable next_unget to true. The input is not -+ changed - we just simulate ungetting by modifying chars_read and -+ token_string. The next call to get() will behave as if the unget character -+ is read again. -+ */ - void unget() - { -+ next_unget = true; - --chars_read; - if (JSON_LIKELY(current != std::char_traits::eof())) - { -- ia->unget_character(); - assert(token_string.size() != 0); - token_string.pop_back(); - } - } - -- /// add a character to yytext -+ /// add a character to token_buffer - void add(int c) - { -- yytext.push_back(std::char_traits::to_char_type(c)); -+ token_buffer.push_back(std::char_traits::to_char_type(c)); - } - - public: -@@ -2737,9 +3364,9 @@ scan_number_done: - } - - /// return current string value (implicitly resets the token; useful only once) -- std::string move_string() -+ string_t& get_string() - { -- return std::move(yytext); -+ return token_buffer; - } - - ///////////////////// -@@ -2764,10 +3391,9 @@ scan_number_done: - if ('\x00' <= c and c <= '\x1F') - { - // escape control characters -- std::stringstream ss; -- ss << "(c) << ">"; -- result += ss.str(); -+ char cs[9]; -+ snprintf(cs, 9, "", static_cast(c)); -+ result += cs; - } - else - { -@@ -2789,8 +3415,43 @@ scan_number_done: - // actual scanner - ///////////////////// - -+ /*! -+ @brief skip the UTF-8 byte order mark -+ @return true iff there is no BOM or the correct BOM has been skipped -+ */ -+ bool skip_bom() -+ { -+ if (get() == 0xEF) -+ { -+ if (get() == 0xBB and get() == 0xBF) -+ { -+ // we completely parsed the BOM -+ return true; -+ } -+ else -+ { -+ // after reading 0xEF, an unexpected character followed -+ return false; -+ } -+ } -+ else -+ { -+ // the first character is not the beginning of the BOM; unget it to -+ // process is later -+ unget(); -+ return true; -+ } -+ } -+ - token_type scan() - { -+ // initially, skip the BOM -+ if (chars_read == 0 and not skip_bom()) -+ { -+ error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; -+ return token_type::parse_error; -+ } -+ - // read next character and ignore whitespace - do - { -@@ -2860,6 +3521,9 @@ scan_number_done: - /// the current character - std::char_traits::int_type current = std::char_traits::eof(); - -+ /// whether the next get() call should just return current -+ bool next_unget = false; -+ - /// the number of characters read - std::size_t chars_read = 0; - -@@ -2867,7 +3531,7 @@ scan_number_done: - std::vector token_string {}; - - /// buffer for variable-length tokens (numbers, strings) -- std::string yytext {}; -+ string_t token_buffer {}; - - /// a description of occurred lexer errors - const char* error_message = ""; -@@ -2880,8 +3544,957 @@ scan_number_done: - /// the decimal point - const char decimal_point_char = '.'; - }; -+} -+} - -+// #include -+ -+ -+#include // assert -+#include // isfinite -+#include // uint8_t -+#include // function -+#include // string -+#include // move -+ -+// #include -+ -+// #include -+ -+// #include -+ -+ -+#include // size_t -+#include // declval -+ -+// #include -+ -+ -+#include -+ -+// #include -+ -+ -+namespace nlohmann -+{ -+namespace detail -+{ -+template -+using void_t = void; -+} -+} -+ -+ -+// http://en.cppreference.com/w/cpp/experimental/is_detected -+namespace nlohmann -+{ -+namespace detail -+{ -+struct nonesuch -+{ -+ nonesuch() = delete; -+ ~nonesuch() = delete; -+ nonesuch(nonesuch const&) = delete; -+ void operator=(nonesuch const&) = delete; -+}; -+ -+template class Op, -+ class... Args> -+struct detector -+{ -+ using value_t = std::false_type; -+ using type = Default; -+}; -+ -+template class Op, class... Args> -+struct detector>, Op, Args...> -+{ -+ using value_t = std::true_type; -+ using type = Op; -+}; -+ -+template