summaryrefslogtreecommitdiff
path: root/vendor/jsoncons-0.104.0/jsoncons
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/jsoncons-0.104.0/jsoncons')
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/detail/heap_only_string.hpp155
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/detail/number_parsers.hpp266
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/detail/number_printers.hpp374
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/detail/obufferedstream.hpp264
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/detail/type_traits_helper.hpp226
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/detail/unicode_traits.hpp1463
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/detail/writer.hpp155
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json.hpp4959
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_decoder.hpp310
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_deserializer.hpp12
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_error_category.hpp148
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_exception.hpp107
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_filter.hpp465
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_input_handler.hpp308
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_output_handler.hpp300
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_parser.hpp2830
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_reader.hpp408
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_serializer.hpp585
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_structures.hpp1864
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/json_type_traits.hpp966
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/jsoncons_config.hpp106
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/jsoncons_utilities.hpp954
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/parse_error_handler.hpp165
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/serialization_options.hpp279
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/serialization_traits.hpp315
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/version.hpp50
26 files changed, 18034 insertions, 0 deletions
diff --git a/vendor/jsoncons-0.104.0/jsoncons/detail/heap_only_string.hpp b/vendor/jsoncons-0.104.0/jsoncons/detail/heap_only_string.hpp
new file mode 100644
index 00000000..5348b436
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/detail/heap_only_string.hpp
@@ -0,0 +1,155 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_DETAIL_HEAPONLYSTRING_HPP
+#define JSONCONS_DETAIL_HEAPONLYSTRING_HPP
+
+#include <stdexcept>
+#include <string>
+#include <cstdlib>
+#include <exception>
+#include <ostream>
+#include <jsoncons/jsoncons_config.hpp>
+
+namespace jsoncons { namespace detail {
+
+template <class Allocator>
+class heap_only_string_base
+{
+ Allocator allocator_;
+public:
+ Allocator& get_allocator()
+ {
+ return allocator_;
+ }
+
+ const Allocator& get_allocator() const
+ {
+ return allocator_;
+ }
+protected:
+ heap_only_string_base(const Allocator& allocator)
+ : allocator_(allocator)
+ {
+ }
+
+ ~heap_only_string_base() {}
+};
+
+template <class CharT,class Allocator>
+class heap_only_string_factory;
+
+template <class CharT, class Allocator>
+class heap_only_string : public heap_only_string_base<Allocator>
+{
+ typedef typename std::allocator_traits<Allocator>::template rebind_alloc<CharT> allocator_type;
+ typedef std::allocator_traits<allocator_type> allocator_traits_type;
+ typedef typename allocator_traits_type::pointer pointer;
+
+ friend class heap_only_string_factory<CharT, Allocator>;
+public:
+ typedef CharT char_type;
+ typedef heap_only_string<CharT,Allocator> value_type;
+
+ ~heap_only_string() {}
+
+ const char_type* c_str() const { return to_plain_pointer(p_); }
+ const char_type* data() const { return to_plain_pointer(p_); }
+ size_t length() const { return length_; }
+
+ using heap_only_string_base<Allocator>::get_allocator;
+
+
+ friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const heap_only_string& s)
+ {
+ os.write(s.data(),s.length());
+ return os;
+ }
+private:
+ heap_only_string()
+ : heap_only_string_base<Allocator>(Allocator())
+ {
+
+ }
+ heap_only_string(const Allocator& allocator)
+ : heap_only_string_base<Allocator>(allocator)
+ {
+
+ }
+
+ pointer p_;
+ size_t length_;
+
+ heap_only_string(const heap_only_string&) = delete;
+ heap_only_string& operator=(const heap_only_string&) = delete;
+
+};
+
+template <class CharT, class Allocator>
+class heap_only_string_factory
+{
+ typedef CharT char_type;
+ typedef typename std::allocator_traits<Allocator>::template rebind_alloc<char> byte_allocator_type;
+ typedef std::allocator_traits<byte_allocator_type> byte_allocator_traits_type;
+ typedef typename byte_allocator_traits_type::pointer byte_pointer;
+ typedef typename heap_only_string<CharT,Allocator>::pointer pointer;
+public:
+
+ typedef typename std::allocator_traits<Allocator>::template rebind_alloc<heap_only_string<CharT,Allocator>> string_allocator_type;
+ typedef std::allocator_traits<string_allocator_type> string_allocator_traits_type;
+ typedef typename string_allocator_traits_type::pointer string_pointer;
+
+ typedef heap_only_string<char_type,Allocator>* raw_string_pointer_type;
+
+ struct string_storage
+ {
+ heap_only_string<CharT,Allocator> data;
+ char_type c[1];
+ };
+ typedef typename std::aligned_storage<sizeof(string_storage), JSONCONS_ALIGNOF(string_storage)>::type storage_type;
+
+ static size_t aligned_size(size_t n)
+ {
+ return sizeof(storage_type) + n;
+ }
+public:
+ static string_pointer create(const char_type* s, size_t length)
+ {
+ return create(s, length, Allocator());
+ }
+ static string_pointer create(const char_type* s, size_t length, const Allocator& allocator)
+ {
+ size_t mem_size = aligned_size(length*sizeof(char_type));
+
+ byte_allocator_type alloc(allocator);
+ byte_pointer ptr = alloc.allocate(mem_size);
+
+ char* storage = to_plain_pointer(ptr);
+ raw_string_pointer_type ps = new(storage)heap_only_string<char_type,Allocator>(alloc);
+ auto psa = reinterpret_cast<string_storage*>(storage);
+
+ CharT* p = new(&psa->c)char_type[length + 1];
+ memcpy(p, s, length*sizeof(char_type));
+ p[length] = 0;
+ ps->p_ = std::pointer_traits<pointer>::pointer_to(*p);
+ ps->length_ = length;
+ return std::pointer_traits<string_pointer>::pointer_to(*ps);
+ }
+
+ static void destroy(string_pointer ptr)
+ {
+ raw_string_pointer_type rawp = to_plain_pointer(ptr);
+ char* p = reinterpret_cast<char*>(rawp);
+ size_t mem_size = aligned_size(ptr->length_*sizeof(char_type));
+ byte_allocator_type alloc(ptr->get_allocator());
+ alloc.deallocate(p,mem_size);
+ }
+};
+
+
+}}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/detail/number_parsers.hpp b/vendor/jsoncons-0.104.0/jsoncons/detail/number_parsers.hpp
new file mode 100644
index 00000000..1a8fc0a9
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/detail/number_parsers.hpp
@@ -0,0 +1,266 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_DETAIL_NUMBERPARSERS_HPP
+#define JSONCONS_DETAIL_NUMBERPARSERS_HPP
+
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cstdarg>
+#include <locale>
+#include <limits>
+#include <type_traits>
+#include <algorithm>
+#include <exception>
+#include <jsoncons/jsoncons_config.hpp>
+
+namespace jsoncons { namespace detail {
+
+struct to_integer_result
+{
+ int64_t value;
+ bool overflow;
+};
+
+// Precondition: s satisfies
+
+// digit
+// digit1-digits
+// - digit
+// - digit1-digits
+
+template <class CharT>
+to_integer_result to_integer(const CharT* s, size_t length)
+{
+ JSONCONS_ASSERT(length > 0);
+
+ int64_t n = 0;
+ bool overflow = false;
+ const CharT* end = s + length;
+ if (*s == '-')
+ {
+ static const int64_t min_value = (std::numeric_limits<int64_t>::min)();
+ static const int64_t min_value_div_10 = min_value / 10;
+ ++s;
+ for (; s < end; ++s)
+ {
+ int64_t x = *s - '0';
+ if (n < min_value_div_10)
+ {
+ overflow = true;
+ break;
+ }
+ n = n * 10;
+ if (n < min_value + x)
+ {
+ overflow = true;
+ break;
+ }
+
+ n -= x;
+ }
+ }
+ else
+ {
+ static const int64_t max_value = (std::numeric_limits<int64_t>::max)();
+ static const int64_t max_value_div_10 = max_value / 10;
+ for (; s < end; ++s)
+ {
+ int64_t x = *s - '0';
+ if (n > max_value_div_10)
+ {
+ overflow = true;
+ break;
+ }
+ n = n * 10;
+ if (n > max_value - x)
+ {
+ overflow = true;
+ break;
+ }
+
+ n += x;
+ }
+ }
+
+ return to_integer_result({ n,overflow });
+}
+
+struct to_uinteger_result
+{
+ uint64_t value;
+ bool overflow;
+};
+
+// Precondition: s satisfies
+
+// digit
+// digit1-digits
+// - digit
+// - digit1-digits
+
+template <class CharT>
+to_uinteger_result to_uinteger(const CharT* s, size_t length)
+{
+ JSONCONS_ASSERT(length > 0);
+
+ static const uint64_t max_value = (std::numeric_limits<uint64_t>::max)();
+ static const uint64_t max_value_div_10 = max_value / 10;
+ uint64_t n = 0;
+ bool overflow = false;
+
+ const CharT* end = s + length;
+ for (; s < end; ++s)
+ {
+ uint64_t x = *s - '0';
+ if (n > max_value_div_10)
+ {
+ overflow = true;
+ break;
+ }
+ n = n * 10;
+ if (n > max_value - x)
+ {
+ overflow = true;
+ break;
+ }
+
+ n += x;
+ }
+ return to_uinteger_result{ n,overflow };
+}
+
+#if defined(JSONCONS_HAS_MSC__STRTOD_L)
+
+class string_to_double
+{
+private:
+ _locale_t locale_;
+public:
+ string_to_double()
+ {
+ locale_ = _create_locale(LC_NUMERIC, "C");
+ }
+ ~string_to_double()
+ {
+ _free_locale(locale_);
+ }
+
+ char get_decimal_point() const
+ {
+ return '.';
+ }
+
+ double operator()(const char* s, size_t) const
+ {
+ const char *begin = s;
+ char *end = nullptr;
+ double val = _strtod_l(begin, &end, locale_);
+ if (begin == end)
+ {
+ JSONCONS_THROW(json_exception_impl<std::invalid_argument>("Invalid float value"));
+ }
+ return val;
+ }
+private:
+ // noncopyable and nonmoveable
+ string_to_double(const string_to_double&) = delete;
+ string_to_double& operator=(const string_to_double&) = delete;
+};
+
+#elif defined(JSONCONS_HAS_STRTOLD_L)
+
+class string_to_double
+{
+private:
+ locale_t locale_;
+public:
+ string_to_double()
+ {
+ locale_ = newlocale(LC_ALL_MASK, "C", (locale_t) 0);
+ }
+ ~string_to_double()
+ {
+ freelocale(locale_);
+ }
+
+ char get_decimal_point() const
+ {
+ return '.';
+ }
+
+ double operator()(const char* s, size_t length) const
+ {
+ const char *begin = s;
+ char *end = nullptr;
+ double val = strtold_l(begin, &end, locale_);
+ if (begin == end)
+ {
+ JSONCONS_THROW(json_exception_impl<std::invalid_argument>("Invalid float value"));
+ }
+ return val;
+ }
+
+private:
+ // noncopyable and nonmoveable
+ string_to_double(const string_to_double& fr) = delete;
+ string_to_double& operator=(const string_to_double& fr) = delete;
+};
+
+#else
+class string_to_double
+{
+private:
+ std::vector<char> buffer_;
+ char decimal_point_;
+public:
+ string_to_double()
+ : buffer_()
+ {
+ struct lconv * lc = localeconv();
+ if (lc != nullptr && lc->decimal_point[0] != 0)
+ {
+ decimal_point_ = lc->decimal_point[0];
+ }
+ else
+ {
+ decimal_point_ = '.';
+ }
+ buffer_.reserve(100);
+ }
+
+ char get_decimal_point() const
+ {
+ return decimal_point_;
+ }
+
+ double operator()(const char* s, size_t /*length*/) const
+ {
+ char *end = nullptr;
+ double val = strtod(s, &end);
+ if (s == end)
+ {
+ JSONCONS_THROW(json_exception_impl<std::invalid_argument>("string_to_double failed"));
+ }
+ return val;
+ }
+
+private:
+ // noncopyable and nonmoveable
+ string_to_double(const string_to_double& fr) = delete;
+ string_to_double& operator=(const string_to_double& fr) = delete;
+};
+#endif
+
+}}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/detail/number_printers.hpp b/vendor/jsoncons-0.104.0/jsoncons/detail/number_printers.hpp
new file mode 100644
index 00000000..58779280
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/detail/number_printers.hpp
@@ -0,0 +1,374 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_DETAIL_NUMBERPRINTERS_HPP
+#define JSONCONS_DETAIL_NUMBERPRINTERS_HPP
+
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+#include <cstdarg>
+#include <locale>
+#include <limits>
+#include <algorithm>
+#include <exception>
+#include <jsoncons/jsoncons_config.hpp>
+#include <jsoncons/detail/obufferedstream.hpp>
+
+namespace jsoncons { namespace detail {
+
+// print_integer
+
+template<class Writer>
+void print_integer(int64_t value, Writer& os)
+{
+ typedef typename Writer::char_type char_type;
+
+ char_type buf[255];
+ uint64_t u = (value < 0) ? static_cast<uint64_t>(-value) : static_cast<uint64_t>(value);
+ char_type* p = buf;
+ do
+ {
+ *p++ = static_cast<char_type>(48 + u%10);
+ }
+ while (u /= 10);
+ if (value < 0)
+ {
+ os.put('-');
+ }
+ while (--p >= buf)
+ {
+ os.put(*p);
+ }
+}
+
+// print_uinteger
+
+template<class Writer>
+void print_uinteger(uint64_t value, Writer& os)
+{
+ typedef typename Writer::char_type char_type;
+
+ char_type buf[255];
+ char_type* p = buf;
+ do
+ {
+ *p++ = static_cast<char_type>(48 + value % 10);
+ } while (value /= 10);
+ while (--p >= buf)
+ {
+ os.put(*p);
+ }
+}
+
+// print_double
+
+#if defined(JSONCONS_HAS__ECVT_S)
+
+class print_double
+{
+private:
+ uint8_t precision_override_;
+public:
+ print_double(uint8_t precision)
+ : precision_override_(precision)
+ {
+ }
+
+ template <class Writer>
+ void operator()(double val, uint8_t precision, Writer& writer)
+ {
+ typedef typename Writer::char_type char_type;
+
+ char buf[_CVTBUFSIZE];
+ int decimal_point = 0;
+ int sign = 0;
+
+ int prec;
+ if (precision_override_ != 0)
+ {
+ prec = precision_override_;
+ }
+ else if (precision != 0)
+ {
+ prec = precision;
+ }
+ else
+ {
+ prec = std::numeric_limits<double>::digits10;
+ }
+
+ int err = _ecvt_s(buf, _CVTBUFSIZE, val, prec, &decimal_point, &sign);
+ if (err != 0)
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Failed attempting double to string conversion"));
+ }
+ //std::cout << "prec:" << prec << ", buf:" << buf << std::endl;
+ char* s = buf;
+ char* se = s + prec;
+
+ int i, k;
+ int j;
+
+ if (sign)
+ {
+ writer.put('-');
+ }
+ if (decimal_point <= -4 || decimal_point > se - s + 5)
+ {
+ writer.put(*s++);
+ if (s < se)
+ {
+ writer.put('.');
+ while ((se-1) > s && *(se-1) == '0')
+ {
+ --se;
+ }
+
+ while(s < se)
+ {
+ writer.put(*s++);
+ }
+ }
+ writer.put('e');
+ /* sprintf(b, "%+.2d", decimal_point - 1); */
+ if (--decimal_point < 0) {
+ writer.put('-');
+ decimal_point = -decimal_point;
+ }
+ else
+ writer.put('+');
+ for(j = 2, k = 10; 10*k <= decimal_point; j++, k *= 10);
+ for(;;)
+ {
+ i = decimal_point / k;
+ writer.put(static_cast<char_type>(i) + '0');
+ if (--j <= 0)
+ break;
+ decimal_point -= i*k;
+ decimal_point *= 10;
+ }
+ }
+ else if (decimal_point <= 0)
+ {
+ writer.put('0');
+ writer.put('.');
+ while ((se-1) > s && *(se-1) == '0')
+ {
+ --se;
+ }
+ for(; decimal_point < 0; decimal_point++)
+ {
+ writer.put('0');
+ }
+ while(s < se)
+ {
+ writer.put(*s++);
+ }
+ }
+ else {
+ while(s < se)
+ {
+ writer.put(*s++);
+ if ((--decimal_point == 0) && s < se)
+ {
+ writer.put('.');
+ while ((se-1) > s && *(se-1) == '0')
+ {
+ --se;
+ }
+ }
+ }
+ for(; decimal_point > 0; decimal_point--)
+ {
+ writer.put('0');
+ }
+ }
+ }
+};
+
+#elif defined(JSONCONS_NO_LOCALECONV)
+
+class print_double
+{
+private:
+ uint8_t precision_override_;
+ basic_obufferedstream<char> os_;
+public:
+ print_double(uint8_t precision)
+ : precision_override_(precision)
+ {
+ os_.imbue(std::locale::classic());
+ os_.precision(precision);
+ }
+
+ template <class Writer>
+ void operator()(double val, uint8_t precision, Writer& writer)
+ {
+ typedef typename Writer::char_type char_type;
+
+ int prec;
+ if (precision_override_ != 0)
+ {
+ prec = precision_override_;
+ }
+ else if (precision != 0)
+ {
+ prec = precision;
+ }
+ else
+ {
+ prec = std::numeric_limits<double>::digits10;
+ }
+
+ os_.clear_sequence();
+ os_.precision(prec);
+ os_ << val;
+
+ //std::cout << "precision_override_:" << (int)precision_override_ << ", precision:" << (int)precision << ", buf:" << os_.data() << std::endl;
+
+ const char_type* sbeg = os_.data();
+ const char_type* send = sbeg + os_.length();
+ const char_type* pexp = send;
+
+ if (sbeg != send)
+ {
+ bool dot = false;
+ for (pexp = sbeg; *pexp != 'e' && *pexp != 'E' && pexp < send; ++pexp)
+ {
+ }
+
+ const char_type* qend = pexp;
+ while (qend >= sbeg+2 && *(qend-1) == '0' && *(qend-2) != '.')
+ {
+ --qend;
+ }
+ if (pexp == send)
+ {
+ qend = ((qend >= sbeg+2) && *(qend-2) == '.') ? qend : send;
+ }
+
+ for (const char_type* q = sbeg; q < qend; ++q)
+ {
+ if (*q == '.')
+ {
+ dot = true;
+ }
+ writer.put(*q);
+ }
+ if (!dot)
+ {
+ writer.put('.');
+ writer.put('0');
+ dot = true;
+ }
+ for (const char_type* q = pexp; q < send; ++q)
+ {
+ writer.put(*q);
+ }
+ }
+ }
+};
+#else
+
+class print_double
+{
+private:
+ uint8_t precision_override_;
+ char decimal_point_;
+public:
+ print_double(uint8_t precision)
+ : precision_override_(precision)
+ {
+ struct lconv * lc = localeconv();
+ if (lc != nullptr && lc->decimal_point[0] != 0)
+ {
+ decimal_point_ = lc->decimal_point[0];
+ }
+ else
+ {
+ decimal_point_ = '.';
+ }
+ }
+
+ template <class Writer>
+ void operator()(double val, uint8_t precision, Writer& writer)
+ {
+ typedef typename Writer::char_type char_type;
+
+ int prec;
+ if (precision_override_ != 0)
+ {
+ prec = precision_override_;
+ }
+ else if (precision != 0)
+ {
+ prec = precision;
+ }
+ else
+ {
+ prec = std::numeric_limits<double>::digits10;
+ }
+
+ char number_buffer[100];
+ int length = snprintf(number_buffer, 100, "%1.*g", prec, val);
+ if (length < 0)
+ {
+ JSONCONS_THROW(json_exception_impl<std::invalid_argument>("print_double failed."));
+ }
+
+ const char* sbeg = number_buffer;
+ const char* send = sbeg + length;
+ const char* pexp = send;
+
+ if (sbeg != send)
+ {
+ bool dot = false;
+ for (pexp = sbeg; *pexp != 'e' && *pexp != 'E' && pexp < send; ++pexp)
+ {
+ }
+
+ for (const char* q = sbeg; q < pexp; ++q)
+ {
+ switch (*q)
+ {
+ case '-':case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
+ writer.put(*q);
+ break;
+ default:
+ if (*q == decimal_point_)
+ {
+ dot = true;
+ writer.put('.');
+ }
+ break;
+ }
+ }
+ if (!dot)
+ {
+ writer.put('.');
+ writer.put('0');
+ dot = true;
+ }
+ for (const char* q = pexp; q < send; ++q)
+ {
+ writer.put(*q);
+ }
+ }
+ }
+};
+
+#endif
+
+}}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/detail/obufferedstream.hpp b/vendor/jsoncons-0.104.0/jsoncons/detail/obufferedstream.hpp
new file mode 100644
index 00000000..7b499f4b
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/detail/obufferedstream.hpp
@@ -0,0 +1,264 @@
+// Copyright 2016 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_DETAIL_OBUFFEREDSTREAM_HPP
+#define JSONCONS_DETAIL_OBUFFEREDSTREAM_HPP
+
+#include <ios>
+#include <ostream>
+#include <string>
+#include <cstddef>
+#include <vector>
+#include <locale>
+#include <jsoncons/jsoncons_config.hpp>
+
+namespace jsoncons {
+
+template<
+ class CharT,
+ class Traits = std::char_traits<CharT>
+> class basic_obufferedstream;
+
+template<class CharT, class Traits>
+class basic_ovectorbuf
+ : public std::basic_streambuf<CharT, Traits>
+{
+private:
+ std::ios_base::openmode mode_;
+ std::vector<CharT> buf_;
+
+public:
+ typedef CharT char_type;
+ typedef typename Traits::int_type int_type;
+ typedef typename Traits::pos_type pos_type;
+ typedef typename Traits::off_type off_type;
+ typedef Traits traits_type;
+
+public:
+
+ explicit basic_ovectorbuf() JSONCONS_NOEXCEPT
+ : mode_(std::ios_base::out | std::ios_base::binary),
+ buf_(100u)
+ {
+ // Set write position to beginning of buffer.
+ this->setp(buf_.data(), buf_.data() + buf_.size());
+ this->setg(buf_.data(), 0, buf_.data());
+ }
+
+ explicit basic_ovectorbuf(std::size_t length) JSONCONS_NOEXCEPT
+ : mode_(std::ios_base::out | std::ios_base::binary),
+ buf_(length)
+ {
+ // Set write position to beginning of buffer.
+ this->setp(buf_.data(), buf_.data() + buf_.size());
+ this->setg(buf_.data(), 0, buf_.data());
+ }
+
+ virtual ~basic_ovectorbuf() JSONCONS_NOEXCEPT {}
+
+ basic_ovectorbuf(const basic_ovectorbuf<CharT,Traits>&) = delete;
+
+ //basic_ovectorbuf(basic_ovectorbuf<CharT,Traits>&&) = default;
+
+ basic_ovectorbuf<CharT,Traits>& operator=(const basic_ovectorbuf<CharT,Traits>&) = delete;
+
+ //basic_ovectorbuf<CharT,Traits>& operator=(basic_ovectorbuf<CharT,Traits>&&) = default;
+
+ const CharT* data() const
+ {
+ return buf_.data();
+ }
+
+ size_t length() const
+ {
+ return this->pptr() - this->pbase();
+ }
+
+ virtual int sync() override
+ {
+ return EOF;
+ }
+
+protected:
+ int_type underflow() override
+ {
+ return this->gptr() != this->egptr() ?
+ Traits::to_int_type(*this->gptr()) : Traits::eof();
+ }
+
+ int_type pbackfail(int_type c = Traits::eof()) override
+ {
+ if (this->gptr() != this->eback())
+ {
+ if (!Traits::eq_int_type(c, Traits::eof()))
+ {
+ if (Traits::eq(Traits::to_char_type(c), this->gptr()[-1]))
+ {
+ this->gbump(-1);
+ return c;
+ }
+ this->gbump(-1);
+ *this->gptr() = static_cast<CharT>(c);
+ return c;
+ }
+ else
+ {
+ this->gbump(-1);
+ return Traits::not_eof(c);
+ }
+ }
+ else
+ {
+ return Traits::eof();
+ }
+ }
+
+ int_type overflow(int_type c = Traits::eof()) override
+ {
+ if (!Traits::eq_int_type(c, Traits::eof()))
+ {
+ size_t pos = buf_.size()+1;
+ buf_.resize(pos*2);
+ this->setp(buf_.data(), buf_.data() + buf_.size());
+ this->pubseekpos(pos, std::ios_base::out);
+ *this->pptr() = Traits::to_char_type(c);
+ this->pbump(1);
+ this->pubsync();
+ return c;
+ }
+ else
+ {
+ return Traits::not_eof(c);
+ }
+ }
+
+ pos_type seekoff(off_type off, std::ios_base::seekdir dir,
+ std::ios_base::openmode mode = std::ios_base::out) override
+ {
+ (void)mode; // Always out
+
+ std::streamoff newoff;
+ switch (dir)
+ {
+ case std::ios_base::beg:
+ newoff = 0;
+ break;
+ case std::ios_base::end:
+ newoff = static_cast<std::streamoff>(buf_.size());
+ break;
+ case std::ios_base::cur:
+ newoff = static_cast<std::streamoff>(this->pptr() - this->pbase());
+ break;
+ default:
+ return pos_type(off_type(-1));
+ }
+
+ off += newoff;
+
+ std::ptrdiff_t n = this->epptr() - this->pbase();
+
+ if (off < 0 || off > n) return pos_type(off_type(-1));
+ else
+ {
+ this->setp(this->pbase(), this->pbase() + n);
+ this->pbump(static_cast<int>(off));
+ }
+
+ return pos_type(off);
+ }
+
+ pos_type seekoff_beg(off_type off)
+ {
+ std::ptrdiff_t n = this->epptr() - this->pbase();
+
+ if (off < 0 || off > n)
+ {
+ return pos_type(off_type(-1));
+ }
+ else
+ {
+ this->setp(this->pbase(), this->pbase() + n);
+ this->pbump(static_cast<int>(off));
+ }
+
+ return pos_type(off);
+ }
+
+ pos_type seekpos(pos_type pos, std::ios_base::openmode mode
+ = std::ios_base::out) override
+ {
+
+ (void)mode; // Always out
+
+ return seekoff_beg(pos - pos_type(off_type(0)));
+ }
+};
+
+template<class CharT, class Traits>
+class basic_obufferedstream :
+ public std::basic_ostream<CharT, Traits>
+{
+public:
+ typedef typename std::basic_ios<CharT, Traits>::char_type char_type;
+ typedef typename std::basic_ios<char_type, Traits>::int_type int_type;
+ typedef typename std::basic_ios<char_type, Traits>::pos_type pos_type;
+ typedef typename std::basic_ios<char_type, Traits>::off_type off_type;
+ typedef typename std::basic_ios<char_type, Traits>::traits_type traits_type;
+
+private:
+ typedef basic_ovectorbuf<CharT, Traits> base_ouputbuf;
+ typedef std::basic_ios<char_type, Traits> base_ios;
+
+ basic_ovectorbuf<CharT, Traits> buf_;
+
+public:
+ basic_obufferedstream() JSONCONS_NOEXCEPT
+ : std::basic_ostream<CharT, Traits>( (std::basic_streambuf<CharT, Traits>*)(&buf_)),
+ buf_()
+ {}
+ basic_obufferedstream(std::size_t length) JSONCONS_NOEXCEPT
+ : std::basic_ostream<CharT, Traits>( (std::basic_streambuf<CharT, Traits>*)(&buf_)),
+ buf_(length)
+ {}
+
+ basic_obufferedstream(const basic_obufferedstream<CharT,Traits>&) = delete;
+
+ //basic_obufferedstream(basic_obufferedstream<CharT,Traits>&&) = default;
+
+ virtual ~basic_obufferedstream() JSONCONS_NOEXCEPT
+ {
+ }
+
+ basic_obufferedstream<CharT,Traits>& operator=(const basic_obufferedstream<CharT,Traits>&) = delete;
+
+ //basic_obufferedstream<CharT,Traits>& operator=(basic_obufferedstream<CharT,Traits>&&) = default;
+
+ const CharT* data() const
+ {
+ return buf_.data();
+ }
+
+ size_t length() const
+ {
+ return buf_.length();
+ }
+
+ void set_locale(const std::locale& loc)
+ {
+ std::locale result = std::basic_ostream<CharT, Traits>::imbue(loc);
+ //this->pubimbue(loc);
+ }
+
+ void clear_sequence()
+ {
+ this->clear();
+ this->seekp(0, std::ios::beg);
+ }
+};
+
+}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/detail/type_traits_helper.hpp b/vendor/jsoncons-0.104.0/jsoncons/detail/type_traits_helper.hpp
new file mode 100644
index 00000000..4dce8e63
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/detail/type_traits_helper.hpp
@@ -0,0 +1,226 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_DETAIL_TYPETRAITSHELPER_HPP
+#define JSONCONS_DETAIL_TYPETRAITSHELPER_HPP
+
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+#include <cstdarg>
+#include <locale>
+#include <limits>
+#include <type_traits>
+#include <algorithm>
+#include <memory>
+#include <iterator>
+#include <exception>
+#include <array>
+#include <initializer_list>
+#include <jsoncons/jsoncons_config.hpp>
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/detail/obufferedstream.hpp>
+
+namespace jsoncons
+{
+// static_max
+
+template <size_t arg1, size_t ... argn>
+struct static_max;
+
+template <size_t arg>
+struct static_max<arg>
+{
+ static const size_t value = arg;
+};
+
+template <size_t arg1, size_t arg2, size_t ... argn>
+struct static_max<arg1,arg2,argn ...>
+{
+ static const size_t value = arg1 >= arg2 ?
+ static_max<arg1,argn...>::value :
+ static_max<arg2,argn...>::value;
+};
+
+// type_wrapper
+
+template <class T>
+struct type_wrapper
+{
+ typedef T* pointer_type;
+ typedef const T* const_pointer_type;
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+};
+
+template <class T>
+struct type_wrapper<const T>
+{
+ typedef T* pointer_type;
+ typedef const T* const_pointer_type;
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+};
+
+template <class T>
+struct type_wrapper<T&>
+{
+ typedef T* pointer_type;
+ typedef const T* const_pointer_type;
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+};
+
+template <class T>
+struct type_wrapper<const T&>
+{
+ typedef T* pointer_type;
+ typedef const T* const_pointer_type;
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+};
+
+// json_literals
+
+namespace detail {
+JSONCONS_DEFINE_LITERAL(null_literal,"null")
+JSONCONS_DEFINE_LITERAL(true_literal,"true")
+JSONCONS_DEFINE_LITERAL(false_literal,"false")
+}
+
+inline
+unsigned char to_hex_character(unsigned char c)
+{
+ JSONCONS_ASSERT(c <= 0xF);
+
+ return (c < 10) ? ('0' + c) : ('A' - 10 + c);
+}
+
+inline
+bool is_control_character(uint32_t c)
+{
+ return c <= 0x1F || c == 0x7f;
+}
+
+inline
+bool is_non_ascii_codepoint(uint32_t cp)
+{
+ return cp >= 0x80;
+}
+
+template <typename T>
+struct is_stateless
+ : public std::integral_constant<bool,
+ (std::is_default_constructible<T>::value &&
+ std::is_empty<T>::value)>
+{};
+
+// type traits extensions
+
+
+namespace detail {
+
+// to_plain_pointer
+
+template<class Pointer> inline
+typename std::pointer_traits<Pointer>::element_type* to_plain_pointer(Pointer ptr)
+{
+ return (std::addressof(*ptr));
+}
+
+template<class T> inline
+T * to_plain_pointer(T * ptr)
+{
+ return (ptr);
+}
+
+// is_string_like
+
+template <class T, class Enable=void>
+struct is_string_like : std::false_type {};
+
+template <class T>
+struct is_string_like<T,
+ typename std::enable_if<!std::is_void<typename T::traits_type>::value
+>::type> : std::true_type {};
+
+// is_integer_like
+
+template <class T, class Enable=void>
+struct is_integer_like : std::false_type {};
+
+template <class T>
+struct is_integer_like<T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_signed<T>::value &&
+ !std::is_same<T,bool>::value>::type> : std::true_type {};
+
+// is_uinteger_like
+
+template <class T, class Enable=void>
+struct is_uinteger_like : std::false_type {};
+
+template <class T>
+struct is_uinteger_like<T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ !std::is_signed<T>::value &&
+ !std::is_same<T,bool>::value>::type> : std::true_type {};
+
+// is_floating_point_like
+
+template <class T, class Enable=void>
+struct is_floating_point_like : std::false_type {};
+
+template <class T>
+struct is_floating_point_like<T,
+ typename std::enable_if<std::is_floating_point<T>::value>::type> : std::true_type {};
+
+// is_map_like
+
+template <class T, class Enable=void>
+struct is_map_like : std::false_type {};
+
+template <class T>
+struct is_map_like<T,
+ typename std::enable_if<!std::is_void<typename T::mapped_type>::value>::type>
+ : std::true_type {};
+
+// is_array_like
+template<class T>
+struct is_array_like : std::false_type {};
+
+template<class E, size_t N>
+struct is_array_like<std::array<E, N>> : std::true_type {};
+
+// is_vector_like
+
+template <class T, class Enable=void>
+struct is_vector_like : std::false_type {};
+
+template <class T>
+struct is_vector_like<T,
+ typename std::enable_if<!std::is_void<typename T::value_type>::value &&
+ !is_array_like<T>::value &&
+ !is_string_like<T>::value &&
+ !is_map_like<T>::value
+>::type>
+ : std::true_type {};
+
+}
+
+}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/detail/unicode_traits.hpp b/vendor/jsoncons-0.104.0/jsoncons/detail/unicode_traits.hpp
new file mode 100644
index 00000000..affbb9b7
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/detail/unicode_traits.hpp
@@ -0,0 +1,1463 @@
+// Copyright 2016 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/unicode_traits for latest version
+
+/*
+ * Includes code derived from Unicode, Inc decomposition code in ConvertUTF.h and ConvertUTF.c
+ * http://www.unicode.org/
+ *
+ * "Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard."
+*/
+
+#ifndef UNICONS_UNICODE_TRAITS_HPP
+#define UNICONS_UNICODE_TRAITS_HPP
+
+#if defined (__clang__)
+#if defined(_GLIBCXX_USE_NOEXCEPT)
+#define UNICONS_NOEXCEPT _GLIBCXX_USE_NOEXCEPT
+#else
+#define UNICONS_NOEXCEPT noexcept
+#endif
+#elif defined(__GNUC__)
+#define UNICONS_NOEXCEPT _GLIBCXX_USE_NOEXCEPT
+#elif defined(_MSC_VER)
+#if _MSC_VER >= 1900
+#define UNICONS_NOEXCEPT noexcept
+#else
+#define UNICONS_NOEXCEPT
+#endif
+#else
+#define UNICONS_NOEXCEPT
+#endif
+
+#include <string>
+#include <iterator>
+#include <type_traits>
+#include <system_error>
+
+namespace unicons {
+
+/*
+ * Magic values subtracted from a buffer value during UTF8 conversion.
+ * This table contains as many values as there might be trailing bytes
+ * in a UTF-8 sequence. Source: ConvertUTF.c
+ */
+const uint32_t offsets_from_utf8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+
+/*
+ * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+ * into the first byte, depending on how many bytes follow. There are
+ * as many entries in this table as there are UTF-8 sequence types.
+ * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
+ * for *legal* UTF-8 will be 4 or fewer bytes total. Source: ConvertUTF.c
+ */
+const uint8_t first_byte_mark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+/*
+ * Index into the table below with the first byte of a UTF-8 sequence to
+ * get the number of trailing bytes that are supposed to follow it.
+ * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
+ * left as-is for anyone who may want to do such conversion, which was
+ * allowed in earlier algorithms. Source: ConvertUTF.c
+ */
+const uint8_t trailing_bytes_for_utf8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+// Some fundamental constants. Source: ConvertUTF.h
+const uint32_t replacement_char = 0x0000FFFD;
+const uint32_t max_bmp = 0x0000FFFF;
+const uint32_t max_utf16 = 0x0010FFFF;
+const uint32_t max_utf32 = 0x7FFFFFFF;
+const uint32_t max_legal_utf32 = 0x0010FFFF;
+
+const int half_shift = 10; // used for shifting by 10 bits
+const uint32_t half_base = 0x0010000UL;
+const uint32_t half_mask = 0x3FFUL;
+
+const uint16_t sur_high_start = 0xD800;
+const uint16_t sur_high_end = 0xDBFF;
+const uint16_t sur_low_start = 0xDC00;
+const uint16_t sur_low_end = 0xDFFF;
+
+inline
+static bool is_continuation_byte(unsigned char ch)
+{
+ return (ch & 0xC0) == 0x80;
+}
+
+inline
+bool is_high_surrogate(uint32_t ch) UNICONS_NOEXCEPT
+{
+ return (ch >= sur_high_start && ch <= sur_high_end);
+}
+
+inline
+bool is_low_surrogate(uint32_t ch) UNICONS_NOEXCEPT
+{
+ return (ch >= sur_low_start && ch <= sur_low_end);
+}
+
+inline
+bool is_surrogate(uint32_t ch) UNICONS_NOEXCEPT
+{
+ return (ch >= sur_high_start && ch <= sur_low_end);
+}
+
+enum class conv_flags
+{
+ strict = 0,
+ lenient
+};
+
+// conv_errc
+
+enum class conv_errc
+{
+ ok = 0,
+ over_long_utf8_sequence = 1, // over long utf8 sequence
+ expected_continuation_byte, // expected continuation byte
+ unpaired_high_surrogate, // unpaired high surrogate UTF-16
+ illegal_surrogate_value, // UTF-16 surrogate values are illegal in UTF-32
+ source_exhausted, // partial character in source, but hit end
+ source_illegal // source sequence is illegal/malformed
+};
+
+class Unicode_traits_error_category_impl_
+ : public std::error_category
+{
+public:
+ virtual const char* name() const UNICONS_NOEXCEPT
+ {
+ return "unicons conversion error";
+ }
+ virtual std::string message(int ev) const
+ {
+ switch (static_cast<conv_errc>(ev))
+ {
+ case conv_errc::over_long_utf8_sequence:
+ return "Over long utf8 sequence";
+ case conv_errc::expected_continuation_byte:
+ return "Expected continuation byte";
+ case conv_errc::unpaired_high_surrogate:
+ return "Unpaired high surrogate UTF-16";
+ case conv_errc::illegal_surrogate_value:
+ return "UTF-16 surrogate values are illegal in UTF-32";
+ case conv_errc::source_exhausted:
+ return "Partial character in source, but hit end";
+ case conv_errc::source_illegal:
+ return "Source sequence is illegal/malformed";
+ default:
+ return "";
+ break;
+ }
+ }
+};
+
+inline
+const std::error_category& unicode_traits_error_category()
+{
+ static Unicode_traits_error_category_impl_ instance;
+ return instance;
+}
+
+inline
+std::error_code make_error_code(conv_errc result)
+{
+ return std::error_code(static_cast<int>(result),unicode_traits_error_category());
+}
+
+// encoding_errc
+
+enum class encoding_errc
+{
+ ok = 0,
+ expected_u8_found_u16 = 1,
+ expected_u8_found_u32,
+ expected_u16_found_fffe,
+ expected_u32_found_fffe
+};
+
+class Encoding_errc_impl_
+ : public std::error_category
+{
+public:
+ virtual const char* name() const UNICONS_NOEXCEPT
+ {
+ return "unicons encoding error";
+ }
+ virtual std::string message(int ev) const
+ {
+ switch (static_cast<encoding_errc>(ev))
+ {
+ case encoding_errc::expected_u8_found_u16:
+ return "Expected UTF-8, found UTF-16";
+ case encoding_errc::expected_u8_found_u32:
+ return "Expected UTF-8, found UTF-32";
+ case encoding_errc::expected_u16_found_fffe:
+ return "Expected UTF-16, found non character";
+ case encoding_errc::expected_u32_found_fffe:
+ return "Expected UTF-32, found non character";
+ default:
+ return "";
+ break;
+ }
+ }
+};
+
+inline
+const std::error_category& encoding_error_category()
+{
+ static Encoding_errc_impl_ instance;
+ return instance;
+}
+
+inline
+std::error_code make_error_code(encoding_errc result)
+{
+ return std::error_code(static_cast<int>(result),encoding_error_category());
+}
+}
+
+namespace std {
+ template<>
+ struct is_error_code_enum<unicons::conv_errc> : public true_type
+ {
+ };
+ template<>
+ struct is_error_code_enum<unicons::encoding_errc> : public true_type
+ {
+ };
+}
+
+namespace unicons {
+
+// utf8
+
+template <class Iterator>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<Iterator>::value_type>::value
+ && sizeof(typename std::iterator_traits<Iterator>::value_type) == sizeof(uint8_t),
+ conv_errc >::type
+is_legal_utf8(Iterator first, size_t length)
+{
+ uint8_t a;
+ Iterator srcptr = first+length;
+ switch (length) {
+ default:
+ return conv_errc::over_long_utf8_sequence;
+ case 4:
+ if (((a = (*--srcptr))& 0xC0) != 0x80)
+ return conv_errc::expected_continuation_byte;
+ // FALLTHRU
+ case 3:
+ if (((a = (*--srcptr))& 0xC0) != 0x80)
+ return conv_errc::expected_continuation_byte;
+ // FALLTHRU
+ case 2:
+ if (((a = (*--srcptr))& 0xC0) != 0x80)
+ return conv_errc::expected_continuation_byte;
+
+ switch (static_cast<uint8_t>(*first))
+ {
+ /* no fall-through in this inner switch */
+ case 0xE0: if (a < 0xA0) return conv_errc::source_illegal; break;
+ case 0xED: if (a > 0x9F) return conv_errc::source_illegal; break;
+ case 0xF0: if (a < 0x90) return conv_errc::source_illegal; break;
+ case 0xF4: if (a > 0x8F) return conv_errc::source_illegal; break;
+ default: if (a < 0x80) return conv_errc::source_illegal;
+ }
+
+ // FALLTHRU
+ case 1:
+ if (static_cast<uint8_t>(*first) >= 0x80 && static_cast<uint8_t>(*first) < 0xC2)
+ return conv_errc::source_illegal;
+ // FALLTHRU
+ }
+ if (static_cast<uint8_t>(*first) > 0xF4)
+ return conv_errc::source_illegal;
+
+ return conv_errc();
+}
+
+template <class...> using void_t = void;
+
+template <class, class, class = void>
+struct is_output_iterator : std::false_type {};
+
+template <class I, class E>
+struct is_output_iterator<I, E, void_t<
+ typename std::iterator_traits<I>::iterator_category,
+ decltype(*std::declval<I>() = std::declval<E>())>> : std::true_type {};
+
+// is_same_size fixes issue with vs2013
+
+// primary template
+template<class T1, class T2, class Enable = void>
+struct is_same_size : std::false_type
+{
+};
+
+// specialization for non void types
+template<class T1, class T2>
+struct is_same_size<T1, T2, typename std::enable_if<!std::is_void<T1>::value && !std::is_void<T2>::value>::type>
+{
+ static const bool value = (sizeof(T1) == sizeof(T2));
+};
+
+template<class OutputIt, class CharT, class Enable = void>
+struct is_compatible_output_iterator : std::false_type {};
+
+template<class OutputIt, class CharT>
+struct is_compatible_output_iterator<OutputIt,CharT,
+ typename std::enable_if<is_output_iterator<OutputIt,CharT>::value
+ && std::is_void<typename std::iterator_traits<OutputIt>::value_type>::value
+ && std::is_integral<typename OutputIt::container_type::value_type>::value
+ && !std::is_void<typename OutputIt::container_type::value_type>::value
+ && is_same_size<typename OutputIt::container_type::value_type,CharT>::value>::type
+> : std::true_type {};
+
+template<class OutputIt, class CharT>
+struct is_compatible_output_iterator<OutputIt,CharT,
+ typename std::enable_if<is_output_iterator<OutputIt,CharT>::value
+ && std::is_integral<typename std::iterator_traits<OutputIt>::value_type>::value
+ && is_same_size<typename std::iterator_traits<OutputIt>::value_type,CharT>::value>::type
+> : std::true_type {};
+
+template<class OutputIt, class CharT>
+struct is_compatible_output_iterator<OutputIt,CharT,
+ typename std::enable_if<is_output_iterator<OutputIt,CharT>::value
+ && std::is_void<typename std::iterator_traits<OutputIt>::value_type>::value
+ && is_same_size<typename OutputIt::char_type,CharT>::value>::type
+> : std::true_type {};
+
+// convert
+
+template <class Iterator>
+struct convert_result
+{
+ Iterator it;
+ conv_errc ec;
+};
+
+template <class InputIt,class OutputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint8_t)
+ && is_compatible_output_iterator<OutputIt,uint8_t>::value,convert_result<InputIt>>::type
+convert(InputIt first, InputIt last, OutputIt target, conv_flags flags=conv_flags::strict)
+{
+ (void)flags;
+
+ conv_errc result = conv_errc();
+ while (first != last)
+ {
+ size_t length = trailing_bytes_for_utf8[static_cast<uint8_t>(*first)] + 1;
+ if (length > (size_t)(last - first))
+ {
+ return convert_result<InputIt>{first, conv_errc::source_exhausted};
+ }
+ if ((result=is_legal_utf8(first, length)) != conv_errc())
+ {
+ return convert_result<InputIt>{first,result};
+ }
+
+ switch (length) {
+ case 4: *target++ = (static_cast<uint8_t>(*first++));
+ case 3: *target++ = (static_cast<uint8_t>(*first++));
+ case 2: *target++ = (static_cast<uint8_t>(*first++));
+ case 1: *target++ = (static_cast<uint8_t>(*first++));
+ }
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+template <class InputIt,class OutputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint8_t)
+ && is_compatible_output_iterator<OutputIt,uint16_t>::value,convert_result<InputIt>>::type
+convert(InputIt first, InputIt last,
+ OutputIt target,
+ conv_flags flags = conv_flags::strict)
+{
+ conv_errc result = conv_errc();
+
+ while (first != last)
+ {
+ uint32_t ch = 0;
+ unsigned short extra_bytes_to_read = trailing_bytes_for_utf8[static_cast<uint8_t>(*first)];
+ if (extra_bytes_to_read >= last - first)
+ {
+ result = conv_errc::source_exhausted;
+ break;
+ }
+ /* Do this check whether lenient or strict */
+ if ((result=is_legal_utf8(first, extra_bytes_to_read+1)) != conv_errc())
+ {
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extra_bytes_to_read) {
+ case 5: ch += static_cast<uint8_t>(*first++); ch <<= 6; /* remember, illegal UTF-8 */
+ case 4: ch += static_cast<uint8_t>(*first++); ch <<= 6; /* remember, illegal UTF-8 */
+ case 3: ch += static_cast<uint8_t>(*first++); ch <<= 6;
+ case 2: ch += static_cast<uint8_t>(*first++); ch <<= 6;
+ case 1: ch += static_cast<uint8_t>(*first++); ch <<= 6;
+ case 0: ch += static_cast<uint8_t>(*first++);
+ }
+ ch -= offsets_from_utf8[extra_bytes_to_read];
+
+ if (ch <= max_bmp) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (is_surrogate(ch) ) {
+ if (flags == conv_flags::strict) {
+ first -= (extra_bytes_to_read+1); /* return to the illegal value itself */
+ result = conv_errc::source_illegal;
+ break;
+ } else {
+ *target++ = (replacement_char);
+ }
+ } else {
+ *target++ = ((uint16_t)ch); /* normal case */
+ }
+ } else if (ch > max_utf16) {
+ if (flags == conv_flags::strict) {
+ result = conv_errc::source_illegal;
+ first -= (extra_bytes_to_read+1); /* return to the start */
+ break; /* Bail out; shouldn't continue */
+ } else {
+ *target++ = (replacement_char);
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ ch -= half_base;
+ *target++ = ((uint16_t)((ch >> half_shift) + sur_high_start));
+ *target++ = ((uint16_t)((ch & half_mask) + sur_low_start));
+ }
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+template <class InputIt,class OutputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint8_t)
+ && is_compatible_output_iterator<OutputIt,uint32_t>::value,convert_result<InputIt>>::type
+convert(InputIt first, InputIt last,
+ OutputIt target,
+ conv_flags flags = conv_flags::strict)
+{
+ conv_errc result = conv_errc();
+
+ while (first < last)
+ {
+ uint32_t ch = 0;
+ unsigned short extra_bytes_to_read = trailing_bytes_for_utf8[static_cast<uint8_t>(*first)];
+ if (extra_bytes_to_read >= last - first)
+ {
+ result = conv_errc::source_exhausted;
+ break;
+ }
+ /* Do this check whether lenient or strict */
+ if ((result=is_legal_utf8(first, extra_bytes_to_read+1)) != conv_errc()) {
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extra_bytes_to_read) {
+ case 5: ch += static_cast<uint8_t>(*first++); ch <<= 6;
+ case 4: ch += static_cast<uint8_t>(*first++); ch <<= 6;
+ case 3: ch += static_cast<uint8_t>(*first++); ch <<= 6;
+ case 2: ch += static_cast<uint8_t>(*first++); ch <<= 6;
+ case 1: ch += static_cast<uint8_t>(*first++); ch <<= 6;
+ case 0: ch += static_cast<uint8_t>(*first++);
+ }
+ ch -= offsets_from_utf8[extra_bytes_to_read];
+
+ if (ch <= max_legal_utf32) {
+ /*
+ * UTF-16 surrogate values are illegal in UTF-32, and anything
+ * over Plane 17 (> 0x10FFFF) is illegal.
+ */
+ if (is_surrogate(ch) ) {
+ if (flags == conv_flags::strict) {
+ first -= (extra_bytes_to_read+1); /* return to the illegal value itself */
+ result = conv_errc::source_illegal;
+ break;
+ } else {
+ *target++ = (replacement_char);
+ }
+ } else {
+ *target++ = (ch);
+ }
+ } else { /* i.e., ch > max_legal_utf32 */
+ result = conv_errc::source_illegal;
+ *target++ = (replacement_char);
+ }
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+// utf16
+
+template <class InputIt,class OutputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint16_t)
+ && is_compatible_output_iterator<OutputIt,uint8_t>::value,convert_result<InputIt>>::type
+convert(InputIt first, InputIt last,
+ OutputIt target,
+ conv_flags flags = conv_flags::strict) {
+ conv_errc result = conv_errc();
+ while (first < last) {
+ unsigned short bytes_to_write = 0;
+ const uint32_t byteMask = 0xBF;
+ const uint32_t byteMark = 0x80;
+ uint32_t ch = *first++;
+ /* If we have a surrogate pair, convert to uint32_t first. */
+ if (is_high_surrogate(ch)) {
+ /* If the 16 bits following the high surrogate are in the first buffer... */
+ if (first < last) {
+ uint32_t ch2 = *first;
+ /* If it's a low surrogate, convert to uint32_t. */
+ if (ch2 >= sur_low_start && ch2 <= sur_low_end) {
+ ch = ((ch - sur_high_start) << half_shift)
+ + (ch2 - sur_low_start) + half_base;
+ ++first;
+ } else if (flags == conv_flags::strict) { /* it's an unpaired high surrogate */
+ --first; /* return to the illegal value itself */
+ result = conv_errc::unpaired_high_surrogate;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --first; /* return to the high surrogate */
+ result = conv_errc::source_exhausted;
+ break;
+ }
+ } else if (flags == conv_flags::strict) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (is_low_surrogate(ch)) {
+ --first; /* return to the illegal value itself */
+ result = conv_errc::source_illegal;
+ break;
+ }
+ }
+ /* Figure out how many bytes the result will require */
+ if (ch < (uint32_t)0x80) {
+ bytes_to_write = 1;
+ } else if (ch < (uint32_t)0x800) {
+ bytes_to_write = 2;
+ } else if (ch < (uint32_t)0x10000) {
+ bytes_to_write = 3;
+ } else if (ch < (uint32_t)0x110000) {
+ bytes_to_write = 4;
+ } else {
+ bytes_to_write = 3;
+ ch = replacement_char;
+ }
+
+ uint8_t byte1 = 0;
+ uint8_t byte2 = 0;
+ uint8_t byte3 = 0;
+ uint8_t byte4 = 0;
+
+ switch (bytes_to_write) { // note: everything falls through
+ case 4: byte4 = (uint8_t)((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: byte3 = (uint8_t)((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: byte2 = (uint8_t)((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: byte1 = (uint8_t)(ch | first_byte_mark[bytes_to_write]);
+ }
+ switch (bytes_to_write)
+ {
+ case 4:
+ *target++ = (byte1);
+ *target++ = (byte2);
+ *target++ = (byte3);
+ *target++ = (byte4);
+ break;
+ case 3:
+ *target++ = (byte1);
+ *target++ = (byte2);
+ *target++ = (byte3);
+ break;
+ case 2:
+ *target++ = (byte1);
+ *target++ = (byte2);
+ break;
+ case 1:
+ *target++ = (byte1);
+ break;
+ }
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+template <class InputIt,class OutputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint16_t)
+ && is_compatible_output_iterator<OutputIt,uint16_t>::value,convert_result<InputIt>>::type
+convert(InputIt first, InputIt last,
+ OutputIt target,
+ conv_flags flags = conv_flags::strict)
+{
+ conv_errc result = conv_errc();
+
+ while (first != last)
+ {
+ uint32_t ch = *first++;
+ /* If we have a surrogate pair, convert to uint32_t first. */
+ if (is_high_surrogate(ch))
+ {
+ /* If the 16 bits following the high surrogate are in the first buffer... */
+ if (first < last) {
+ uint32_t ch2 = *first;
+ /* If it's a low surrogate, */
+ if (ch2 >= sur_low_start && ch2 <= sur_low_end) {
+ *target++ = ((uint16_t)ch);
+ *target++ = ((uint16_t)ch2);
+ ++first;
+ } else if (flags == conv_flags::strict) { /* it's an unpaired high surrogate */
+ --first; /* return to the illegal value itself */
+ result = conv_errc::unpaired_high_surrogate;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --first; /* return to the high surrogate */
+ result = conv_errc::source_exhausted;
+ break;
+ }
+ } else if (is_low_surrogate(ch))
+ {
+ // illegal leading low surrogate
+ if (flags == conv_flags::strict) {
+ --first; /* return to the illegal value itself */
+ result = conv_errc::source_illegal;
+ break;
+ }
+ else
+ {
+ *target++ = ((uint16_t)ch);
+ }
+ }
+ else
+ {
+ *target++ = ((uint16_t)ch);
+ }
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+template <class InputIt,class OutputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint16_t)
+ && is_compatible_output_iterator<OutputIt,uint32_t>::value,convert_result<InputIt>>::type
+convert(InputIt first, InputIt last,
+ OutputIt target,
+ conv_flags flags = conv_flags::strict)
+{
+ conv_errc result = conv_errc();
+
+ while (first != last)
+ {
+ uint32_t ch = *first++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (is_high_surrogate(ch)) {
+ /* If the 16 bits following the high surrogate are in the first buffer... */
+ if (first < last) {
+ uint32_t ch2 = *first;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= sur_low_start && ch2 <= sur_low_end ) {
+ ch = ((ch - sur_high_start) << half_shift)
+ + (ch2 - sur_low_start) + half_base;
+ ++first;
+ } else if (flags == conv_flags::strict) { /* it's an unpaired high surrogate */
+ --first; /* return to the illegal value itself */
+ result = conv_errc::source_illegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --first; /* return to the high surrogate */
+ result = conv_errc::source_exhausted;
+ break;
+ }
+ } else if (flags == conv_flags::strict) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (is_low_surrogate(ch) ) {
+ --first; /* return to the illegal value itself */
+ result = conv_errc::source_illegal;
+ break;
+ }
+ }
+ *target++ = (ch);
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+// utf32
+
+template <class InputIt,class OutputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint32_t)
+ && is_compatible_output_iterator<OutputIt,uint8_t>::value,convert_result<InputIt>>::type
+convert(InputIt first, InputIt last,
+ OutputIt target,
+ conv_flags flags = conv_flags::strict)
+{
+ conv_errc result = conv_errc();
+ while (first < last) {
+ unsigned short bytes_to_write = 0;
+ const uint32_t byteMask = 0xBF;
+ const uint32_t byteMark = 0x80;
+ uint32_t ch = *first++;
+ if (flags == conv_flags::strict ) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (is_surrogate(ch)) {
+ --first; /* return to the illegal value itself */
+ result = conv_errc::illegal_surrogate_value;
+ break;
+ }
+ }
+ /*
+ * Figure out how many bytes the result will require. Turn any
+ * illegally large UTF32 things (> Plane 17) into replacement chars.
+ */
+ if (ch < (uint32_t)0x80) { bytes_to_write = 1;
+ } else if (ch < (uint32_t)0x800) { bytes_to_write = 2;
+ } else if (ch < (uint32_t)0x10000) { bytes_to_write = 3;
+ } else if (ch <= max_legal_utf32) { bytes_to_write = 4;
+ } else {
+ bytes_to_write = 3;
+ ch = replacement_char;
+ result = conv_errc::source_illegal;
+ }
+
+ uint8_t byte1 = 0;
+ uint8_t byte2 = 0;
+ uint8_t byte3 = 0;
+ uint8_t byte4 = 0;
+
+ switch (bytes_to_write) {
+ case 4:
+ byte4 = (uint8_t)((ch | byteMark) & byteMask); ch >>= 6;
+ // FALLTHRU
+ case 3:
+ byte3 = (uint8_t)((ch | byteMark) & byteMask); ch >>= 6;
+ // FALLTHRU
+ case 2:
+ byte2 = (uint8_t)((ch | byteMark) & byteMask); ch >>= 6;
+ // FALLTHRU
+ case 1:
+ byte1 = (uint8_t) (ch | first_byte_mark[bytes_to_write]);
+ }
+
+ switch (bytes_to_write)
+ {
+ case 4:
+ *target++ = (byte1);
+ *target++ = (byte2);
+ *target++ = (byte3);
+ *target++ = (byte4);
+ break;
+ case 3:
+ *target++ = (byte1);
+ *target++ = (byte2);
+ *target++ = (byte3);
+ break;
+ case 2:
+ *target++ = (byte1);
+ *target++ = (byte2);
+ break;
+ case 1:
+ *target++ = (byte1);
+ break;
+ }
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+template <class InputIt,class OutputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint32_t)
+ && is_compatible_output_iterator<OutputIt,uint16_t>::value,convert_result<InputIt>>::type
+convert(InputIt first, InputIt last,
+ OutputIt target,
+ conv_flags flags = conv_flags::strict)
+{
+ conv_errc result = conv_errc();
+
+ while (first != last)
+ {
+ uint32_t ch = *first++;
+ if (ch <= max_bmp) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
+ if (is_surrogate(ch) ) {
+ if (flags == conv_flags::strict) {
+ --first; /* return to the illegal value itself */
+ result = conv_errc::source_illegal;
+ break;
+ } else {
+ *target++ = (replacement_char);
+ }
+ } else {
+ *target++ = ((uint16_t)ch); /* normal case */
+ }
+ } else if (ch > max_legal_utf32) {
+ if (flags == conv_flags::strict) {
+ result = conv_errc::source_illegal;
+ } else {
+ *target++ = (replacement_char);
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ ch -= half_base;
+ *target++ = ((uint16_t)((ch >> half_shift) + sur_high_start));
+ *target++ = ((uint16_t)((ch & half_mask) + sur_low_start));
+ }
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+template <class InputIt,class OutputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint32_t)
+ && is_compatible_output_iterator<OutputIt,uint32_t>::value,convert_result<InputIt>>::type
+convert(InputIt first, InputIt last,
+ OutputIt target,
+ conv_flags flags = conv_flags::strict)
+{
+ conv_errc result = conv_errc();
+
+ while (first != last)
+ {
+ uint32_t ch = *first++;
+ if (flags == conv_flags::strict ) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (is_surrogate(ch)) {
+ --first; /* return to the illegal value itself */
+ result = conv_errc::illegal_surrogate_value;
+ break;
+ }
+ }
+ if (ch <= max_legal_utf32)
+ {
+ *target++ = (ch);
+ }
+ else
+ {
+ *target++ = (replacement_char);
+ result = conv_errc::source_illegal;
+ }
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+// validate
+
+template <class InputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint8_t)
+ ,convert_result<InputIt>>::type
+validate(InputIt first, InputIt last) UNICONS_NOEXCEPT
+{
+ conv_errc result = conv_errc();
+ while (first != last)
+ {
+ size_t length = trailing_bytes_for_utf8[static_cast<uint8_t>(*first)] + 1;
+ if (length > (size_t)(last - first))
+ {
+ return convert_result<InputIt>{first, conv_errc::source_exhausted};
+ }
+ if ((result=is_legal_utf8(first, length)) != conv_errc())
+ {
+ return convert_result<InputIt>{first,result} ;
+ }
+ first += length;
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+// utf16
+
+template <class InputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint16_t)
+ ,convert_result<InputIt>>::type
+validate(InputIt first, InputIt last) UNICONS_NOEXCEPT
+{
+ conv_errc result = conv_errc();
+
+ while (first != last)
+ {
+ uint32_t ch = *first++;
+ /* If we have a surrogate pair, validate to uint32_t first. */
+ if (is_high_surrogate(ch))
+ {
+ /* If the 16 bits following the high surrogate are in the first buffer... */
+ if (first < last) {
+ uint32_t ch2 = *first;
+ /* If it's a low surrogate, */
+ if (ch2 >= sur_low_start && ch2 <= sur_low_end) {
+ ++first;
+ } else {
+ --first; /* return to the illegal value itself */
+ result = conv_errc::unpaired_high_surrogate;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --first; /* return to the high surrogate */
+ result = conv_errc::source_exhausted;
+ break;
+ }
+ } else if (is_low_surrogate(ch))
+ {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ --first; /* return to the illegal value itself */
+ result = conv_errc::source_illegal;
+ break;
+ }
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+
+// utf32
+
+
+template <class InputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint32_t)
+ ,convert_result<InputIt>>::type
+validate(InputIt first, InputIt last) UNICONS_NOEXCEPT
+{
+ conv_errc result = conv_errc();
+
+ while (first != last)
+ {
+ uint32_t ch = *first++;
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (is_surrogate(ch)) {
+ --first; /* return to the illegal value itself */
+ result = conv_errc::illegal_surrogate_value;
+ break;
+ }
+ if (!(ch <= max_legal_utf32))
+ {
+ result = conv_errc::source_illegal;
+ }
+ }
+ return convert_result<InputIt>{first,result} ;
+}
+
+// sequence
+
+template <class Iterator>
+class sequence
+{
+ Iterator first_;
+ size_t length_;
+public:
+ sequence(Iterator first, size_t length)
+ : first_(first), length_(length)
+ {
+ }
+
+ Iterator begin() const
+ {
+ return first_;
+ }
+
+ size_t length() const
+ {
+ return length_;
+ }
+
+ template <class CharT = typename std::iterator_traits<Iterator>::value_type>
+ typename std::enable_if<sizeof(CharT) == sizeof(uint8_t),uint32_t>::type
+ codepoint() const UNICONS_NOEXCEPT
+ {
+ uint32_t ch = 0;
+ Iterator it = first_;
+ switch (length_)
+ {
+ default:
+ return replacement_char;
+ break;
+ case 4:
+ ch += static_cast<uint8_t>(*it++); ch <<= 6;
+ // FALLTHRU
+ case 3:
+ ch += static_cast<uint8_t>(*it++); ch <<= 6;
+ // FALLTHRU
+ case 2:
+ ch += static_cast<uint8_t>(*it++); ch <<= 6;
+ // FALLTHRU
+ case 1:
+ ch += static_cast<uint8_t>(*it++);
+ ch -= offsets_from_utf8[length_ - 1];
+ break;
+ }
+ if (ch <= max_legal_utf32)
+ {
+ if (is_surrogate(ch))
+ {
+ ch = replacement_char;
+ }
+ }
+ else // ch > max_legal_utf32
+ {
+ ch = replacement_char;
+ }
+ return ch;
+ }
+
+ template <class CharT = typename std::iterator_traits<Iterator>::value_type>
+ typename std::enable_if<sizeof(CharT) == sizeof(uint16_t),uint32_t>::type
+ codepoint() const UNICONS_NOEXCEPT
+ {
+ if (length_ == 0)
+ {
+ return replacement_char;
+ }
+ if (length_ == 2)
+ {
+ uint32_t ch = *first_;
+ uint32_t ch2 = *(first_+ 1);
+ ch = ((ch - sur_high_start) << half_shift)
+ + (ch2 - sur_low_start) + half_base;
+ return ch;
+ }
+ else
+ {
+ return *first_;
+ }
+ }
+
+ template <class CharT = typename std::iterator_traits<Iterator>::value_type>
+ typename std::enable_if<sizeof(CharT) == sizeof(uint32_t),uint32_t>::type
+ codepoint() const UNICONS_NOEXCEPT
+ {
+ if (length_ == 0)
+ {
+ return replacement_char;
+ }
+ return *(first_);
+ }
+};
+
+// sequence_generator
+
+template <class Iterator>
+class sequence_generator
+{
+ Iterator begin_;
+ Iterator last_;
+ conv_flags flags_;
+ size_t length_;
+ conv_errc err_cd_;
+public:
+ typedef sequence<Iterator> sequence_type;
+
+ sequence_generator(Iterator first, Iterator last,
+ conv_flags flags = conv_flags::strict) UNICONS_NOEXCEPT
+ : begin_(first), last_(last), flags_(flags),
+ length_(0), err_cd_(conv_errc())
+ {
+ next();
+ }
+
+ bool done() const UNICONS_NOEXCEPT
+ {
+ return err_cd_ != conv_errc() || begin_ == last_;
+ }
+
+ conv_errc status() const UNICONS_NOEXCEPT
+ {
+ return err_cd_;
+ }
+
+ sequence_type get() const UNICONS_NOEXCEPT
+ {
+ return sequence<Iterator>(begin_,length_);
+ }
+
+ template <class CharT = typename std::iterator_traits<Iterator>::value_type>
+ typename std::enable_if<sizeof(CharT) == sizeof(uint8_t)>::type
+ next() UNICONS_NOEXCEPT
+ {
+ begin_ += length_;
+ if (begin_ != last_)
+ {
+ size_t length = trailing_bytes_for_utf8[static_cast<uint8_t>(*begin_)] + 1;
+ if (length > (size_t)(last_ - begin_))
+ {
+ err_cd_ = conv_errc::source_exhausted;
+ }
+ else if ((err_cd_ = is_legal_utf8(begin_, length)) != conv_errc())
+ {
+ }
+ else
+ {
+ length_ = length;
+ }
+ }
+ }
+
+ template <class CharT = typename std::iterator_traits<Iterator>::value_type>
+ typename std::enable_if<sizeof(CharT) == sizeof(uint16_t)>::type
+ next() UNICONS_NOEXCEPT
+ {
+ begin_ += length_;
+ if (begin_ != last_)
+ {
+ if (begin_ != last_)
+ {
+
+ Iterator it = begin_;
+
+ uint32_t ch = *it++;
+ /* If we have a surrogate pair, validate to uint32_t it. */
+ if (is_high_surrogate(ch))
+ {
+ /* If the 16 bits following the high surrogate are in the it buffer... */
+ if (it < last_) {
+ uint32_t ch2 = *it;
+ /* If it's a low surrogate, */
+ if (ch2 >= sur_low_start && ch2 <= sur_low_end)
+ {
+ ++it;
+ length_ = 2;
+ }
+ else
+ {
+ err_cd_ = conv_errc::unpaired_high_surrogate;
+ }
+ }
+ else
+ {
+ // We don't have the 16 bits following the high surrogate.
+ err_cd_ = conv_errc::source_exhausted;
+ }
+ }
+ else if (is_low_surrogate(ch))
+ {
+ /* leading low surrogate */
+ err_cd_ = conv_errc::source_illegal;
+ }
+ else
+ {
+ length_ = 1;
+ }
+ }
+ }
+ }
+
+ template <class CharT = typename std::iterator_traits<Iterator>::value_type>
+ typename std::enable_if<sizeof(CharT) == sizeof(uint32_t)>::type
+ next() UNICONS_NOEXCEPT
+ {
+ begin_ += length_;
+ length_ = 1;
+ }
+};
+
+template <class Iterator>
+sequence_generator<Iterator> make_sequence_generator(Iterator first, Iterator last,
+ conv_flags flags = conv_flags::strict)
+{
+ return sequence_generator<Iterator>(first, last, flags);
+}
+
+template <class InputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value
+ && (sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint8_t) || sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint16_t)),
+ sequence<InputIt>>::type
+sequence_at(InputIt first, InputIt last, size_t index)
+{
+ sequence_generator<InputIt> g(first, last, unicons::conv_flags::strict);
+
+ size_t count = 0;
+ while (!g.done() && count < index)
+ {
+ g.next();
+ ++count;
+ }
+ return (!g.done() && count == index) ? g.get() : sequence<InputIt>(last,0);
+}
+
+template <class InputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint32_t),
+ sequence<InputIt>>::type
+sequence_at(InputIt first, InputIt last, size_t index)
+{
+ size_t size = std::distance(first,last);
+ return index < size ? sequence<InputIt>(first+index,1) : sequence<InputIt>(last,0);
+}
+
+// u8_length
+
+template <class InputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint8_t),size_t>::type
+u8_length(InputIt first, InputIt last) UNICONS_NOEXCEPT
+{
+ return std::distance(first,last);
+}
+
+// utf16
+
+template <class InputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint16_t),size_t>::type
+u8_length(InputIt first, InputIt last) UNICONS_NOEXCEPT
+{
+ conv_flags flags = conv_flags::strict;
+ size_t count = 0;
+ for (InputIt p = first; p != last; ++p)
+ {
+ uint32_t ch = *p;
+ if (is_high_surrogate(ch)) {
+ /* If the 16 bits following the high surrogate are in the p buffer... */
+ if (p < last) {
+ uint32_t ch2 = *(++p);
+ /* If it's a low surrogate, convert to uint32_t. */
+ if (ch2 >= sur_low_start && ch2 <= sur_low_end) {
+ ch = ((ch - sur_high_start) << half_shift)
+ + (ch2 - sur_low_start) + half_base;
+
+ } else if (flags == conv_flags::strict) { /* it's an unpaired high surrogate */
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ break;
+ }
+ } else if (flags == conv_flags::strict) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (is_low_surrogate(ch)) {
+ break;
+ }
+ }
+ if (ch < (uint32_t)0x80) {
+ ++count;
+ } else if (ch < (uint32_t)0x800) {
+ count += 2;
+ } else if (ch < (uint32_t)0x10000) {
+ count += 3;
+ } else if (ch < (uint32_t)0x110000) {
+ count += 4;
+ } else {
+ count += 3;
+ }
+ }
+ return count;
+}
+
+
+// utf32
+
+template <class InputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint32_t),size_t>::type
+u8_length(InputIt first, InputIt last) UNICONS_NOEXCEPT
+{
+ size_t count = 0;
+ for (InputIt p = first; p < last; ++p)
+ {
+ uint32_t ch = *p;
+ if (ch < (uint32_t)0x80) {
+ ++count;
+ } else if (ch < (uint32_t)0x800) {
+ count += 2;
+ } else if (ch < (uint32_t)0x10000) {
+ count += 3;
+ } else if (ch <= max_legal_utf32) {
+ count += 4;
+ } else {
+ count += 3;
+ }
+ }
+ return count;
+}
+
+// u32_length
+
+template <class InputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value
+ && (sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint8_t) || sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint16_t)),
+ size_t>::type
+u32_length(InputIt first, InputIt last) UNICONS_NOEXCEPT
+{
+ sequence_generator<InputIt> g(first, last, unicons::conv_flags::strict);
+
+ size_t count = 0;
+ while (!g.done())
+ {
+ g.next();
+ ++count;
+ }
+ return count;
+}
+
+template <class InputIt>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<InputIt>::value_type>::value && sizeof(typename std::iterator_traits<InputIt>::value_type) == sizeof(uint32_t),
+ size_t>::type
+u32_length(InputIt first, InputIt last) UNICONS_NOEXCEPT
+{
+ return std::distance(first,last);
+}
+
+enum class encoding {u8,u16le,u16be,u32le,u32be,undetected};
+
+template <class Iterator>
+struct detect_encoding_result
+{
+ Iterator it;
+ encoding ec;
+};
+
+template <class Iterator>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<Iterator>::value_type>::value && sizeof(typename std::iterator_traits<Iterator>::value_type) == sizeof(uint8_t),
+ detect_encoding_result<Iterator>>::type
+detect_encoding(Iterator first, Iterator last) UNICONS_NOEXCEPT
+{
+ Iterator it1 = first;
+ if (std::distance(first,last) < 4)
+ {
+ if (std::distance(first,last) == 3)
+ {
+ Iterator it2 = ++first;
+ Iterator it3 = ++first;
+ if (static_cast<uint8_t>(*it1) == 0xEF && static_cast<uint8_t>(*it2) == 0xBB && static_cast<uint8_t>(*it3) == 0xBF)
+ {
+ return detect_encoding_result<Iterator>{last,encoding::u8};
+ }
+ }
+ return detect_encoding_result<Iterator>{it1,encoding::undetected};
+ }
+ else
+ {
+ Iterator it2 = ++first;
+ Iterator it3 = ++first;
+ Iterator it4 = ++first;
+
+ uint32_t bom = static_cast<uint8_t>(*it1) | (static_cast<uint8_t>(*it2) << 8) | (static_cast<uint8_t>(*it3) << 16) | (static_cast<uint8_t>(*it4) << 24);
+ if (bom == 0xFFFE0000)
+ {
+ return detect_encoding_result<Iterator>{it4++,encoding::u32be};
+ }
+ else if (bom == 0x0000FEFF)
+ {
+ return detect_encoding_result<Iterator>{first,encoding::u32le};
+ }
+ else if ((bom & 0xFFFF) == 0xFFFE)
+ {
+ return detect_encoding_result<Iterator>{it3,encoding::u16be};
+ }
+ else if ((bom & 0xFFFF) == 0xFEFF)
+ {
+ return detect_encoding_result<Iterator>{it3,encoding::u16le};
+ }
+ else if ((bom & 0xFFFFFF) == 0xBFBBEF)
+ {
+ return detect_encoding_result<Iterator>{it4,encoding::u8};
+ }
+ else
+ {
+ uint32_t pattern = (static_cast<uint8_t>(*it1) ? 1 : 0) | (static_cast<uint8_t>(*it2) ? 2 : 0) | (static_cast<uint8_t>(*it3) ? 4 : 0) | (static_cast<uint8_t>(*it4) ? 8 : 0);
+ switch (pattern) {
+ case 0x08:
+ return detect_encoding_result<Iterator>{it1,encoding::u32be};
+ case 0x0A:
+ return detect_encoding_result<Iterator>{it1,encoding::u16be};
+ case 0x01:
+ return detect_encoding_result<Iterator>{it1,encoding::u32le};
+ case 0x05:
+ return detect_encoding_result<Iterator>{it1,encoding::u16le};
+ case 0x0F:
+ return detect_encoding_result<Iterator>{it1,encoding::u8};
+ default:
+ return detect_encoding_result<Iterator>{it1,encoding::undetected};
+ }
+ }
+ }
+}
+
+template <class Iterator>
+struct skip_bom_result
+{
+ Iterator it;
+ encoding_errc ec;
+};
+
+template <class Iterator>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<Iterator>::value_type>::value && sizeof(typename std::iterator_traits<Iterator>::value_type) == sizeof(uint8_t),
+ skip_bom_result<Iterator>>::type
+skip_bom(Iterator first, Iterator last) UNICONS_NOEXCEPT
+{
+ auto result = unicons::detect_encoding(first,last);
+ switch (result.ec)
+ {
+ case unicons::encoding::u8:
+ return skip_bom_result<Iterator>{result.it,encoding_errc()};
+ break;
+ case unicons::encoding::u16le:
+ case unicons::encoding::u16be:
+ return skip_bom_result<Iterator>{result.it,encoding_errc::expected_u8_found_u16};
+ break;
+ case unicons::encoding::u32le:
+ case unicons::encoding::u32be:
+ return skip_bom_result<Iterator>{result.it,encoding_errc::expected_u8_found_u32};
+ break;
+ default:
+ return skip_bom_result<Iterator>{result.it,encoding_errc()};
+ break;
+ }
+}
+
+template <class Iterator>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<Iterator>::value_type>::value && sizeof(typename std::iterator_traits<Iterator>::value_type) == sizeof(uint16_t),
+ skip_bom_result<Iterator>>::type
+skip_bom(Iterator first, Iterator last) UNICONS_NOEXCEPT
+{
+ if (first == last)
+ {
+ return skip_bom_result<Iterator>{first,encoding_errc()};
+ }
+ uint16_t bom = static_cast<uint16_t>(*first);
+ if (bom == 0xFEFF)
+ {
+ return skip_bom_result<Iterator>{++first,encoding_errc()};
+ }
+ else if (bom == 0xFFFE)
+ {
+ return skip_bom_result<Iterator>{last,encoding_errc::expected_u16_found_fffe};
+ }
+ else
+ {
+ return skip_bom_result<Iterator>{first,encoding_errc()};
+ }
+}
+
+template <class Iterator>
+typename std::enable_if<std::is_integral<typename std::iterator_traits<Iterator>::value_type>::value && sizeof(typename std::iterator_traits<Iterator>::value_type) == sizeof(uint32_t),
+ skip_bom_result<Iterator>>::type
+skip_bom(Iterator first, Iterator last) UNICONS_NOEXCEPT
+{
+ if (first == last)
+ {
+ return skip_bom_result<Iterator>{first,encoding_errc()};
+ }
+ uint32_t bom = static_cast<uint32_t>(*first);
+ if (bom == 0xFEFF0000)
+ {
+ return skip_bom_result<Iterator>{++first,encoding_errc()};
+ }
+ else if (bom == 0xFFFE0000)
+ {
+ return skip_bom_result<Iterator>{last,encoding_errc::expected_u32_found_fffe};
+ }
+ else
+ {
+ return skip_bom_result<Iterator>{first,encoding_errc()};
+ }
+}
+
+}
+
+#endif
+
diff --git a/vendor/jsoncons-0.104.0/jsoncons/detail/writer.hpp b/vendor/jsoncons-0.104.0/jsoncons/detail/writer.hpp
new file mode 100644
index 00000000..c832f06f
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/detail/writer.hpp
@@ -0,0 +1,155 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_DETAIL_WRITERS_HPP
+#define JSONCONS_DETAIL_WRITERS_HPP
+
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+#include <cstdarg>
+#include <locale>
+#include <limits>
+#include <type_traits>
+#include <algorithm>
+#include <exception>
+#include <jsoncons/jsoncons_config.hpp>
+#include <jsoncons/detail/type_traits_helper.hpp>
+
+namespace jsoncons { namespace detail {
+
+template <class CharT>
+class ostream_buffered_writer
+{
+public:
+ typedef basic_string_view_ext<CharT> string_view_type;
+ typedef CharT char_type;
+ typedef std::basic_ostream<CharT> output_type;
+private:
+ static const size_t default_buffer_length = 16384;
+
+ std::basic_ostream<CharT>& os_;
+ std::vector<CharT> buffer_;
+ CharT * begin_buffer_;
+ const CharT* end_buffer_;
+ CharT* p_;
+
+ // Noncopyable and nonmoveable
+ ostream_buffered_writer(const ostream_buffered_writer&) = delete;
+ ostream_buffered_writer& operator=(const ostream_buffered_writer&) = delete;
+
+public:
+ ostream_buffered_writer(std::basic_ostream<CharT>& os)
+ : os_(os), buffer_(default_buffer_length), begin_buffer_(buffer_.data()), end_buffer_(begin_buffer_+buffer_.size()), p_(begin_buffer_)
+ {
+ }
+ ostream_buffered_writer(std::basic_ostream<CharT>& os, size_t buflen)
+ : os_(os), buffer_(buflen), begin_buffer_(buffer_.data()), end_buffer_(begin_buffer_+buffer_.size()), p_(begin_buffer_)
+ {
+ }
+ ~ostream_buffered_writer()
+ {
+ os_.write(begin_buffer_, buffer_length());
+ os_.flush();
+ }
+
+ void flush()
+ {
+ os_.write(begin_buffer_, buffer_length());
+ p_ = buffer_.data();
+ }
+
+ void write(const CharT* s, size_t length)
+ {
+ size_t diff = end_buffer_ - p_;
+ if (diff >= length)
+ {
+ std::memcpy(p_, s, length*sizeof(CharT));
+ p_ += length;
+ }
+ else
+ {
+ os_.write(begin_buffer_, buffer_length());
+ os_.write(s,length);
+ p_ = begin_buffer_;
+ }
+ }
+
+ void write(const string_view_type& s)
+ {
+ write(s.data(),s.length());
+ }
+
+ void put(CharT ch)
+ {
+ if (p_ < end_buffer_)
+ {
+ *p_++ = ch;
+ }
+ else
+ {
+ os_.write(begin_buffer_, buffer_length());
+ p_ = begin_buffer_;
+ put(ch);
+ }
+ }
+private:
+
+ size_t buffer_length() const
+ {
+ return p_ - begin_buffer_;
+ }
+};
+
+template <class CharT>
+class string_writer
+{
+public:
+ typedef basic_string_view_ext<CharT> string_view_type;
+ typedef CharT char_type;
+ typedef std::basic_string<CharT> output_type;
+private:
+ std::basic_string<CharT>& s_;
+
+ // Noncopyable and nonmoveable
+ string_writer(const string_writer&) = delete;
+ string_writer& operator=(const string_writer&) = delete;
+public:
+
+ string_writer(std::basic_string<CharT>& s)
+ : s_(s)
+ {
+ }
+
+ void flush()
+ {
+ }
+
+ void write(const CharT* s, size_t length)
+ {
+ s_.append(s,length);
+ }
+
+ void write(const string_view_type& s)
+ {
+ s_.append(s.data(),s.length());
+ }
+
+ void put(CharT ch)
+ {
+ s_.push_back(ch);
+ }
+};
+
+}}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json.hpp b/vendor/jsoncons-0.104.0/jsoncons/json.hpp
new file mode 100644
index 00000000..fe9aec4e
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json.hpp
@@ -0,0 +1,4959 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_HPP
+#define JSONCONS_JSON_HPP
+
+#include <limits>
+#include <string>
+#include <vector>
+#include <exception>
+#include <cstdlib>
+#include <cstring>
+#include <ostream>
+#include <memory>
+#include <typeinfo>
+#include <cstring>
+#include <jsoncons/version.hpp>
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/jsoncons_utilities.hpp>
+#include <jsoncons/json_structures.hpp>
+#include <jsoncons/json_output_handler.hpp>
+#include <jsoncons/serialization_options.hpp>
+#include <jsoncons/json_serializer.hpp>
+#include <jsoncons/json_decoder.hpp>
+#include <jsoncons/json_reader.hpp>
+#include <jsoncons/json_type_traits.hpp>
+#include <jsoncons/json_error_category.hpp>
+#include <jsoncons/detail/heap_only_string.hpp>
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+#endif
+
+namespace jsoncons {
+
+struct sorted_policy
+{
+ static const bool preserve_order = false;
+
+ template <class T,class Allocator>
+ using object_storage = std::vector<T,Allocator>;
+
+ template <class T,class Allocator>
+ using array_storage = std::vector<T,Allocator>;
+
+ template <class CharT, class CharTraits, class Allocator>
+ using key_storage = std::basic_string<CharT, CharTraits,Allocator>;
+
+ template <class CharT, class CharTraits, class Allocator>
+ using string_storage = std::basic_string<CharT, CharTraits,Allocator>;
+
+ typedef default_parse_error_handler parse_error_handler_type;
+};
+
+struct preserve_order_policy : public sorted_policy
+{
+ static const bool preserve_order = true;
+};
+
+template <typename IteratorT>
+class range
+{
+ IteratorT first_;
+ IteratorT last_;
+public:
+ range(const IteratorT& first, const IteratorT& last)
+ : first_(first), last_(last)
+ {
+ }
+
+public:
+ IteratorT begin()
+ {
+ return first_;
+ }
+ IteratorT end()
+ {
+ return last_;
+ }
+};
+
+enum class json_type_tag : uint8_t
+{
+ null_t = 0,
+ empty_object_t,
+ bool_t,
+ integer_t,
+ uinteger_t,
+ double_t,
+ small_string_t,
+ string_t,
+ byte_string_t,
+ array_t,
+ object_t
+};
+
+template <class CharT,
+ class ImplementationPolicy = sorted_policy,
+ class Allocator = std::allocator<CharT>>
+class basic_json
+{
+public:
+
+ typedef Allocator allocator_type;
+
+ typedef ImplementationPolicy implementation_policy;
+
+ typedef typename ImplementationPolicy::parse_error_handler_type parse_error_handler_type;
+
+ typedef CharT char_type;
+ typedef typename std::char_traits<char_type> char_traits_type;
+
+ typedef basic_string_view_ext<char_type,char_traits_type> string_view_type;
+
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<char_type> char_allocator_type;
+ using string_storage_type = typename implementation_policy::template string_storage<CharT,char_traits_type,char_allocator_type>;
+ using key_storage_type = typename implementation_policy::template key_storage<CharT,char_traits_type,char_allocator_type>;
+
+ // string_type is for interface only, not storage
+ typedef std::basic_string<CharT,char_traits_type,char_allocator_type> string_type;
+
+ typedef basic_json<CharT,ImplementationPolicy,Allocator> value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef key_value_pair<key_storage_type,value_type> key_value_pair_type;
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+ typedef value_type json_type;
+ typedef key_value_pair_type kvp_type;
+ typedef key_value_pair_type member_type;
+ typedef jsoncons::null_type null_type;
+#endif
+
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<basic_json> val_allocator_type;
+ using array_storage_type = typename implementation_policy::template array_storage<basic_json, val_allocator_type>;
+
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<uint8_t> byte_allocator_type;
+ using byte_string_storage_type = typename implementation_policy::template array_storage<uint8_t, byte_allocator_type>;
+
+ typedef json_array<basic_json> array;
+
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<key_value_pair_type> kvp_allocator_type;
+
+ using object_storage_type = typename implementation_policy::template object_storage<key_value_pair_type , kvp_allocator_type>;
+ typedef json_object<key_storage_type,basic_json,implementation_policy::preserve_order> object;
+
+ typedef typename std::allocator_traits<Allocator>:: template rebind_alloc<array> array_allocator;
+ typedef typename std::allocator_traits<Allocator>:: template rebind_alloc<object> object_allocator;
+
+ typedef typename object::iterator object_iterator;
+ typedef typename object::const_iterator const_object_iterator;
+ typedef typename array::iterator array_iterator;
+ typedef typename array::const_iterator const_array_iterator;
+
+ struct variant
+ {
+ struct data_base
+ {
+ json_type_tag type_id_;
+
+ data_base(json_type_tag id)
+ : type_id_(id)
+ {}
+ };
+
+ class null_data final : public data_base
+ {
+ public:
+ null_data()
+ : data_base(json_type_tag::null_t)
+ {
+ }
+ };
+
+ class empty_object_data final : public data_base
+ {
+ public:
+ empty_object_data()
+ : data_base(json_type_tag::empty_object_t)
+ {
+ }
+ };
+
+ class bool_data final : public data_base
+ {
+ bool val_;
+ public:
+ bool_data(bool val)
+ : data_base(json_type_tag::bool_t),val_(val)
+ {
+ }
+
+ bool_data(const bool_data& val)
+ : data_base(json_type_tag::bool_t),val_(val.val_)
+ {
+ }
+
+ bool value() const
+ {
+ return val_;
+ }
+
+ };
+
+ class integer_data final : public data_base
+ {
+ int64_t val_;
+ public:
+ integer_data(int64_t val)
+ : data_base(json_type_tag::integer_t),val_(val)
+ {
+ }
+
+ integer_data(const integer_data& val)
+ : data_base(json_type_tag::integer_t),val_(val.val_)
+ {
+ }
+
+ int64_t value() const
+ {
+ return val_;
+ }
+ };
+
+ class uinteger_data final : public data_base
+ {
+ uint64_t val_;
+ public:
+ uinteger_data(uint64_t val)
+ : data_base(json_type_tag::uinteger_t),val_(val)
+ {
+ }
+
+ uinteger_data(const uinteger_data& val)
+ : data_base(json_type_tag::uinteger_t),val_(val.val_)
+ {
+ }
+
+ uint64_t value() const
+ {
+ return val_;
+ }
+ };
+
+ class double_data final : public data_base
+ {
+ chars_format format_;
+ uint8_t precision_;
+ uint8_t decimal_places_;
+ double val_;
+ public:
+ double_data(double val)
+ : data_base(json_type_tag::double_t),
+ precision_(0),
+ decimal_places_(0),
+ val_(val)
+ {
+ }
+ double_data(double val, const number_format& fmt)
+ : data_base(json_type_tag::double_t),
+ format_(fmt.floating_point_format()),
+ precision_(fmt.precision()),
+ decimal_places_(fmt.decimal_places()),
+ val_(val)
+ {
+ }
+
+ double_data(const double_data& val)
+ : data_base(json_type_tag::double_t),
+ precision_(val.precision_),
+ decimal_places_(val.decimal_places_),
+ val_(val.val_)
+ {
+ }
+
+ double value() const
+ {
+ return val_;
+ }
+
+ uint8_t precision() const
+ {
+ return precision_;
+ }
+
+ uint8_t decimal_places() const
+ {
+ return precision_;
+ }
+ };
+
+ class small_string_data final : public data_base
+ {
+ static const size_t capacity = 14/sizeof(char_type);
+ uint8_t length_;
+ char_type data_[capacity];
+ public:
+ static const size_t max_length = (14 / sizeof(char_type)) - 1;
+
+ small_string_data(const char_type* p, uint8_t length)
+ : data_base(json_type_tag::small_string_t), length_(length)
+ {
+ JSONCONS_ASSERT(length <= max_length);
+ std::memcpy(data_,p,length*sizeof(char_type));
+ data_[length] = 0;
+ }
+
+ small_string_data(const small_string_data& val)
+ : data_base(json_type_tag::small_string_t), length_(val.length_)
+ {
+ std::memcpy(data_,val.data_,val.length_*sizeof(char_type));
+ data_[length_] = 0;
+ }
+
+ uint8_t length() const
+ {
+ return length_;
+ }
+
+ const char_type* data() const
+ {
+ return data_;
+ }
+
+ const char_type* c_str() const
+ {
+ return data_;
+ }
+ };
+
+ // string_data
+ class string_data final : public data_base
+ {
+ typedef typename detail::heap_only_string_factory<char_type, Allocator>::string_pointer pointer;
+
+ pointer ptr_;
+ public:
+ string_data(const string_data& val)
+ : data_base(json_type_tag::string_t)
+ {
+ ptr_ = detail::heap_only_string_factory<char_type,Allocator>::create(val.data(),val.length(),val.get_allocator());
+ }
+
+ string_data(string_data&& val)
+ : data_base(json_type_tag::string_t), ptr_(nullptr)
+ {
+ std::swap(val.ptr_,ptr_);
+ }
+
+ string_data(const string_data& val, const Allocator& a)
+ : data_base(json_type_tag::string_t)
+ {
+ ptr_ = detail::heap_only_string_factory<char_type,Allocator>::create(val.data(),val.length(),a);
+ }
+
+ string_data(const char_type* data, size_t length, const Allocator& a)
+ : data_base(json_type_tag::string_t)
+ {
+ ptr_ = detail::heap_only_string_factory<char_type,Allocator>::create(data,length,a);
+ }
+
+ ~string_data()
+ {
+ if (ptr_ != nullptr)
+ {
+ detail::heap_only_string_factory<char_type,Allocator>::destroy(ptr_);
+ }
+ }
+
+ void swap(string_data& val)
+ {
+ std::swap(val.ptr_,ptr_);
+ }
+
+ const char_type* data() const
+ {
+ return ptr_->data();
+ }
+
+ const char_type* c_str() const
+ {
+ return ptr_->c_str();
+ }
+
+ size_t length() const
+ {
+ return ptr_->length();
+ }
+
+ allocator_type get_allocator() const
+ {
+ return ptr_->get_allocator();
+ }
+ };
+
+ // byte_string_data
+ class byte_string_data final : public data_base
+ {
+ typedef typename std::allocator_traits<Allocator>:: template rebind_alloc<byte_string_storage_type> string_holder_allocator_type;
+ typedef typename std::allocator_traits<string_holder_allocator_type>::pointer pointer;
+
+ pointer ptr_;
+
+ template <typename... Args>
+ void create(string_holder_allocator_type allocator, Args&& ... args)
+ {
+ typename std::allocator_traits<Allocator>:: template rebind_alloc<byte_string_storage_type> alloc(allocator);
+ ptr_ = alloc.allocate(1);
+ try
+ {
+ std::allocator_traits<string_holder_allocator_type>:: template rebind_traits<byte_string_storage_type>::construct(alloc, detail::to_plain_pointer(ptr_), std::forward<Args>(args)...);
+ }
+ catch (...)
+ {
+ alloc.deallocate(ptr_,1);
+ throw;
+ }
+ }
+ public:
+ byte_string_data(const byte_string_data& val)
+ : data_base(json_type_tag::byte_string_t)
+ {
+ create(val.ptr_->get_allocator(), *(val.ptr_));
+ }
+
+ byte_string_data(byte_string_data&& val)
+ : data_base(json_type_tag::byte_string_t), ptr_(nullptr)
+ {
+ std::swap(val.ptr_,ptr_);
+ }
+
+ byte_string_data(const byte_string_data& val, const Allocator& a)
+ : data_base(json_type_tag::byte_string_t)
+ {
+ create(string_holder_allocator_type(a), *(val.ptr_), a);
+ }
+
+ byte_string_data(const uint8_t* data, size_t length, const Allocator& a)
+ : data_base(json_type_tag::byte_string_t)
+ {
+ create(string_holder_allocator_type(a), data, data+length, a);
+ }
+
+ ~byte_string_data()
+ {
+ if (ptr_ != nullptr)
+ {
+ typename std::allocator_traits<string_holder_allocator_type>:: template rebind_alloc<byte_string_storage_type> alloc(ptr_->get_allocator());
+ std::allocator_traits<string_holder_allocator_type>:: template rebind_traits<byte_string_storage_type>::destroy(alloc, detail::to_plain_pointer(ptr_));
+ alloc.deallocate(ptr_,1);
+ }
+ }
+
+ void swap(byte_string_data& val)
+ {
+ std::swap(val.ptr_,ptr_);
+ }
+
+ const uint8_t* data() const
+ {
+ return ptr_->data();
+ }
+
+ size_t length() const
+ {
+ return ptr_->size();
+ }
+
+ allocator_type get_allocator() const
+ {
+ return ptr_->get_allocator();
+ }
+ };
+
+ // array_data
+ class array_data final : public data_base
+ {
+ typedef typename std::allocator_traits<array_allocator>::pointer pointer;
+ pointer ptr_;
+
+ template <typename... Args>
+ void create(array_allocator allocator, Args&& ... args)
+ {
+ typename std::allocator_traits<Allocator>:: template rebind_alloc<array> alloc(allocator);
+ ptr_ = alloc.allocate(1);
+ try
+ {
+ std::allocator_traits<array_allocator>:: template rebind_traits<array>::construct(alloc, detail::to_plain_pointer(ptr_), std::forward<Args>(args)...);
+ }
+ catch (...)
+ {
+ alloc.deallocate(ptr_,1);
+ throw;
+ }
+ }
+ public:
+ array_data(const array& val)
+ : data_base(json_type_tag::array_t)
+ {
+ create(val.get_allocator(), val);
+ }
+
+ array_data(const array& val, const Allocator& a)
+ : data_base(json_type_tag::array_t)
+ {
+ create(array_allocator(a), val, a);
+ }
+
+ array_data(const array_data& val)
+ : data_base(json_type_tag::array_t)
+ {
+ create(val.ptr_->get_allocator(), *(val.ptr_));
+ }
+
+ array_data(array_data&& val)
+ : data_base(json_type_tag::array_t), ptr_(nullptr)
+ {
+ std::swap(val.ptr_, ptr_);
+ }
+
+ array_data(const array_data& val, const Allocator& a)
+ : data_base(json_type_tag::array_t)
+ {
+ create(array_allocator(a), *(val.ptr_), a);
+ }
+ ~array_data()
+ {
+ if (ptr_ != nullptr)
+ {
+ typename std::allocator_traits<array_allocator>:: template rebind_alloc<array> alloc(ptr_->get_allocator());
+ std::allocator_traits<array_allocator>:: template rebind_traits<array>::destroy(alloc, detail::to_plain_pointer(ptr_));
+ alloc.deallocate(ptr_,1);
+ }
+ }
+
+ allocator_type get_allocator() const
+ {
+ return ptr_->get_allocator();
+ }
+
+ void swap(array_data& val)
+ {
+ std::swap(val.ptr_,ptr_);
+ }
+
+ array& value()
+ {
+ return *ptr_;
+ }
+
+ const array& value() const
+ {
+ return *ptr_;
+ }
+ };
+
+ // object_data
+ class object_data final : public data_base
+ {
+ typedef typename std::allocator_traits<object_allocator>::pointer pointer;
+ pointer ptr_;
+
+ template <typename... Args>
+ void create(Allocator allocator, Args&& ... args)
+ {
+ typename std::allocator_traits<object_allocator>:: template rebind_alloc<object> alloc(allocator);
+ ptr_ = alloc.allocate(1);
+ try
+ {
+ std::allocator_traits<object_allocator>:: template rebind_traits<object>::construct(alloc, detail::to_plain_pointer(ptr_), std::forward<Args>(args)...);
+ }
+ catch (...)
+ {
+ alloc.deallocate(ptr_,1);
+ throw;
+ }
+ }
+ public:
+ explicit object_data(const Allocator& a)
+ : data_base(json_type_tag::object_t)
+ {
+ create(a,a);
+ }
+
+ explicit object_data(const object& val)
+ : data_base(json_type_tag::object_t)
+ {
+ create(val.get_allocator(), val);
+ }
+
+ explicit object_data(const object& val, const Allocator& a)
+ : data_base(json_type_tag::object_t)
+ {
+ create(object_allocator(a), val, a);
+ }
+
+ explicit object_data(const object_data& val)
+ : data_base(json_type_tag::object_t)
+ {
+ create(val.ptr_->get_allocator(), *(val.ptr_));
+ }
+
+ explicit object_data(object_data&& val)
+ : data_base(json_type_tag::object_t), ptr_(nullptr)
+ {
+ std::swap(val.ptr_,ptr_);
+ }
+
+ explicit object_data(const object_data& val, const Allocator& a)
+ : data_base(json_type_tag::object_t)
+ {
+ create(object_allocator(a), *(val.ptr_), a);
+ }
+
+ ~object_data()
+ {
+ if (ptr_ != nullptr)
+ {
+ typename std::allocator_traits<Allocator>:: template rebind_alloc<object> alloc(ptr_->get_allocator());
+ std::allocator_traits<Allocator>:: template rebind_traits<object>::destroy(alloc, detail::to_plain_pointer(ptr_));
+ alloc.deallocate(ptr_,1);
+ }
+ }
+
+ void swap(object_data& val)
+ {
+ std::swap(val.ptr_,ptr_);
+ }
+
+ object& value()
+ {
+ return *ptr_;
+ }
+
+ const object& value() const
+ {
+ return *ptr_;
+ }
+
+ allocator_type get_allocator() const
+ {
+ return ptr_->get_allocator();
+ }
+ };
+
+ private:
+ static const size_t data_size = static_max<sizeof(uinteger_data),sizeof(double_data),sizeof(small_string_data), sizeof(string_data), sizeof(array_data), sizeof(object_data)>::value;
+ static const size_t data_align = static_max<JSONCONS_ALIGNOF(uinteger_data),JSONCONS_ALIGNOF(double_data),JSONCONS_ALIGNOF(small_string_data),JSONCONS_ALIGNOF(string_data),JSONCONS_ALIGNOF(array_data),JSONCONS_ALIGNOF(object_data)>::value;
+
+ typedef typename std::aligned_storage<data_size,data_align>::type data_t;
+
+ data_t data_;
+ public:
+ variant()
+ {
+ new(reinterpret_cast<void*>(&data_))empty_object_data();
+ }
+
+ variant(const Allocator& a)
+ {
+ new(reinterpret_cast<void*>(&data_))object_data(a);
+ }
+
+ variant(const variant& val)
+ {
+ Init_(val);
+ }
+
+ variant(const variant& val, const Allocator& allocator)
+ {
+ Init_(val,allocator);
+ }
+
+ variant(variant&& val) JSONCONS_NOEXCEPT
+ {
+ Init_rv_(std::forward<variant>(val));
+ }
+
+ variant(variant&& val, const Allocator& allocator) JSONCONS_NOEXCEPT
+ {
+ Init_rv_(std::forward<variant>(val), allocator,
+ typename std::allocator_traits<Allocator>::propagate_on_container_move_assignment());
+ }
+
+ explicit variant(null_type)
+ {
+ new(reinterpret_cast<void*>(&data_))null_data();
+ }
+ explicit variant(bool val)
+ {
+ new(reinterpret_cast<void*>(&data_))bool_data(val);
+ }
+ explicit variant(int64_t val)
+ {
+ new(reinterpret_cast<void*>(&data_))integer_data(val);
+ }
+ explicit variant(uint64_t val, const Allocator&)
+ {
+ new(reinterpret_cast<void*>(&data_))uinteger_data(val);
+ }
+ explicit variant(uint64_t val)
+ {
+ new(reinterpret_cast<void*>(&data_))uinteger_data(val);
+ }
+ variant(double val)
+ {
+ new(reinterpret_cast<void*>(&data_))double_data(val);
+ }
+ variant(double val, const number_format& fmt)
+ {
+ new(reinterpret_cast<void*>(&data_))double_data(val, fmt);
+ }
+ variant(const char_type* s, size_t length)
+ {
+ if (length <= small_string_data::max_length)
+ {
+ new(reinterpret_cast<void*>(&data_))small_string_data(s, static_cast<uint8_t>(length));
+ }
+ else
+ {
+ new(reinterpret_cast<void*>(&data_))string_data(s, length, char_allocator_type());
+ }
+ }
+ variant(const uint8_t* s, size_t length)
+ {
+ new(reinterpret_cast<void*>(&data_))byte_string_data(s, length, byte_allocator_type());
+ }
+
+ variant(const uint8_t* s, size_t length, const Allocator& alloc)
+ {
+ new(reinterpret_cast<void*>(&data_))byte_string_data(s, length, alloc);
+ }
+
+ variant(const char_type* s)
+ {
+ size_t length = char_traits_type::length(s);
+ if (length <= small_string_data::max_length)
+ {
+ new(reinterpret_cast<void*>(&data_))small_string_data(s, static_cast<uint8_t>(length));
+ }
+ else
+ {
+ new(reinterpret_cast<void*>(&data_))string_data(s, length, char_allocator_type());
+ }
+ }
+
+ variant(const char_type* s, const Allocator& alloc)
+ {
+ size_t length = char_traits_type::length(s);
+ if (length <= small_string_data::max_length)
+ {
+ new(reinterpret_cast<void*>(&data_))small_string_data(s, static_cast<uint8_t>(length));
+ }
+ else
+ {
+ new(reinterpret_cast<void*>(&data_))string_data(s, length, alloc);
+ }
+ }
+
+ variant(const char_type* s, size_t length, const Allocator& alloc)
+ {
+ if (length <= small_string_data::max_length)
+ {
+ new(reinterpret_cast<void*>(&data_))small_string_data(s, static_cast<uint8_t>(length));
+ }
+ else
+ {
+ new(reinterpret_cast<void*>(&data_))string_data(s, length, alloc);
+ }
+ }
+ variant(const object& val)
+ {
+ new(reinterpret_cast<void*>(&data_))object_data(val);
+ }
+ variant(const object& val, const Allocator& alloc)
+ {
+ new(reinterpret_cast<void*>(&data_))object_data(val, alloc);
+ }
+ variant(const array& val)
+ {
+ new(reinterpret_cast<void*>(&data_))array_data(val);
+ }
+ variant(const array& val, const Allocator& alloc)
+ {
+ new(reinterpret_cast<void*>(&data_))array_data(val,alloc);
+ }
+
+ ~variant()
+ {
+ Destroy_();
+ }
+
+ void Destroy_()
+ {
+ switch (type_id())
+ {
+ case json_type_tag::string_t:
+ reinterpret_cast<string_data*>(&data_)->~string_data();
+ break;
+ case json_type_tag::byte_string_t:
+ reinterpret_cast<byte_string_data*>(&data_)->~byte_string_data();
+ break;
+ case json_type_tag::object_t:
+ reinterpret_cast<object_data*>(&data_)->~object_data();
+ break;
+ case json_type_tag::array_t:
+ reinterpret_cast<array_data*>(&data_)->~array_data();
+ break;
+ default:
+ break;
+ }
+ }
+
+ variant& operator=(const variant& val)
+ {
+ if (this !=&val)
+ {
+ Destroy_();
+ switch (val.type_id())
+ {
+ case json_type_tag::null_t:
+ new(reinterpret_cast<void*>(&data_))null_data();
+ break;
+ case json_type_tag::empty_object_t:
+ new(reinterpret_cast<void*>(&data_))empty_object_data();
+ break;
+ case json_type_tag::bool_t:
+ new(reinterpret_cast<void*>(&data_))bool_data(*(val.bool_data_cast()));
+ break;
+ case json_type_tag::integer_t:
+ new(reinterpret_cast<void*>(&data_))integer_data(*(val.integer_data_cast()));
+ break;
+ case json_type_tag::uinteger_t:
+ new(reinterpret_cast<void*>(&data_))uinteger_data(*(val.uinteger_data_cast()));
+ break;
+ case json_type_tag::double_t:
+ new(reinterpret_cast<void*>(&data_))double_data(*(val.double_data_cast()));
+ break;
+ case json_type_tag::small_string_t:
+ new(reinterpret_cast<void*>(&data_))small_string_data(*(val.small_string_data_cast()));
+ break;
+ case json_type_tag::string_t:
+ new(reinterpret_cast<void*>(&data_))string_data(*(val.string_data_cast()));
+ break;
+ case json_type_tag::byte_string_t:
+ new(reinterpret_cast<void*>(&data_))byte_string_data(*(val.byte_string_data_cast()));
+ break;
+ case json_type_tag::array_t:
+ new(reinterpret_cast<void*>(&data_))array_data(*(val.array_data_cast()));
+ break;
+ case json_type_tag::object_t:
+ new(reinterpret_cast<void*>(&data_))object_data(*(val.object_data_cast()));
+ break;
+ default:
+ JSONCONS_UNREACHABLE();
+ break;
+ }
+ }
+ return *this;
+ }
+
+ variant& operator=(variant&& val) JSONCONS_NOEXCEPT
+ {
+ if (this !=&val)
+ {
+ swap(val);
+ }
+ return *this;
+ }
+
+ json_type_tag type_id() const
+ {
+ return reinterpret_cast<const data_base*>(&data_)->type_id_;
+ }
+
+ const null_data* null_data_cast() const
+ {
+ return reinterpret_cast<const null_data*>(&data_);
+ }
+
+ const empty_object_data* empty_object_data_cast() const
+ {
+ return reinterpret_cast<const empty_object_data*>(&data_);
+ }
+
+ const bool_data* bool_data_cast() const
+ {
+ return reinterpret_cast<const bool_data*>(&data_);
+ }
+
+ const integer_data* integer_data_cast() const
+ {
+ return reinterpret_cast<const integer_data*>(&data_);
+ }
+
+ const uinteger_data* uinteger_data_cast() const
+ {
+ return reinterpret_cast<const uinteger_data*>(&data_);
+ }
+
+ const double_data* double_data_cast() const
+ {
+ return reinterpret_cast<const double_data*>(&data_);
+ }
+
+ const small_string_data* small_string_data_cast() const
+ {
+ return reinterpret_cast<const small_string_data*>(&data_);
+ }
+
+ string_data* string_data_cast()
+ {
+ return reinterpret_cast<string_data*>(&data_);
+ }
+
+ const string_data* string_data_cast() const
+ {
+ return reinterpret_cast<const string_data*>(&data_);
+ }
+
+ byte_string_data* byte_string_data_cast()
+ {
+ return reinterpret_cast<byte_string_data*>(&data_);
+ }
+
+ const byte_string_data* byte_string_data_cast() const
+ {
+ return reinterpret_cast<const byte_string_data*>(&data_);
+ }
+
+ object_data* object_data_cast()
+ {
+ return reinterpret_cast<object_data*>(&data_);
+ }
+
+ const object_data* object_data_cast() const
+ {
+ return reinterpret_cast<const object_data*>(&data_);
+ }
+
+ array_data* array_data_cast()
+ {
+ return reinterpret_cast<array_data*>(&data_);
+ }
+
+ const array_data* array_data_cast() const
+ {
+ return reinterpret_cast<const array_data*>(&data_);
+ }
+
+ string_view_type as_string_view() const
+ {
+ switch (type_id())
+ {
+ case json_type_tag::small_string_t:
+ return string_view_type(small_string_data_cast()->data(),small_string_data_cast()->length());
+ case json_type_tag::string_t:
+ return string_view_type(string_data_cast()->data(),string_data_cast()->length());
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a string"));
+ }
+ }
+
+ byte_string_view as_byte_string_view() const
+ {
+ switch (type_id())
+ {
+ case json_type_tag::byte_string_t:
+ return byte_string_view(byte_string_data_cast()->data(),byte_string_data_cast()->length());
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a byte string"));
+ }
+ }
+
+ bool operator==(const variant& rhs) const
+ {
+ if (this ==&rhs)
+ {
+ return true;
+ }
+ switch (type_id())
+ {
+ case json_type_tag::null_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::null_t:
+ return true;
+ default:
+ return false;
+ }
+ break;
+ case json_type_tag::empty_object_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ return true;
+ case json_type_tag::object_t:
+ return rhs.object_data_cast()->value().size() == 0;
+ default:
+ return false;
+ }
+ break;
+ case json_type_tag::bool_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::bool_t:
+ return bool_data_cast()->value() == rhs.bool_data_cast()->value();
+ default:
+ return false;
+ }
+ break;
+ case json_type_tag::integer_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::integer_t:
+ return integer_data_cast()->value() == rhs.integer_data_cast()->value();
+ case json_type_tag::uinteger_t:
+ return integer_data_cast()->value() >= 0 ? static_cast<uint64_t>(integer_data_cast()->value()) == rhs.uinteger_data_cast()->value() : false;
+ case json_type_tag::double_t:
+ return static_cast<double>(integer_data_cast()->value()) == rhs.double_data_cast()->value();
+ default:
+ return false;
+ }
+ break;
+ case json_type_tag::uinteger_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::integer_t:
+ return rhs.integer_data_cast()->value() >= 0 ? uinteger_data_cast()->value() == static_cast<uint64_t>(rhs.integer_data_cast()->value()) : false;
+ case json_type_tag::uinteger_t:
+ return uinteger_data_cast()->value() == rhs.uinteger_data_cast()->value();
+ case json_type_tag::double_t:
+ return static_cast<double>(uinteger_data_cast()->value()) == rhs.double_data_cast()->value();
+ default:
+ return false;
+ }
+ break;
+ case json_type_tag::double_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::integer_t:
+ return double_data_cast()->value() == static_cast<double>(rhs.integer_data_cast()->value());
+ case json_type_tag::uinteger_t:
+ return double_data_cast()->value() == static_cast<double>(rhs.uinteger_data_cast()->value());
+ case json_type_tag::double_t:
+ return double_data_cast()->value() == rhs.double_data_cast()->value();
+ default:
+ return false;
+ }
+ break;
+ case json_type_tag::small_string_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::small_string_t:
+ return as_string_view() == rhs.as_string_view();
+ case json_type_tag::string_t:
+ return as_string_view() == rhs.as_string_view();
+ default:
+ return false;
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::byte_string_t:
+ {
+ return as_byte_string_view() == rhs.as_byte_string_view();
+ }
+ default:
+ return false;
+ }
+ break;
+ case json_type_tag::string_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::small_string_t:
+ return as_string_view() == rhs.as_string_view();
+ case json_type_tag::string_t:
+ return as_string_view() == rhs.as_string_view();
+ default:
+ return false;
+ }
+ break;
+ case json_type_tag::array_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::array_t:
+ return array_data_cast()->value() == rhs.array_data_cast()->value();
+ default:
+ return false;
+ }
+ break;
+ case json_type_tag::object_t:
+ switch (rhs.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ return object_data_cast()->value().size() == 0;
+ case json_type_tag::object_t:
+ return object_data_cast()->value() == rhs.object_data_cast()->value();
+ default:
+ return false;
+ }
+ break;
+ default:
+ JSONCONS_UNREACHABLE();
+ break;
+ }
+ }
+
+ bool operator!=(const variant& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ template <class Alloc = allocator_type>
+ typename std::enable_if<std::is_pod<typename std::allocator_traits<Alloc>::pointer>::value,void>::type
+ swap(variant& other) JSONCONS_NOEXCEPT
+ {
+ if (this ==&other)
+ {
+ return;
+ }
+
+ std::swap(data_,other.data_);
+ }
+
+ template <class Alloc = allocator_type>
+ typename std::enable_if<!std::is_pod<typename std::allocator_traits<Alloc>::pointer>::value, void>::type
+ swap(variant& other) JSONCONS_NOEXCEPT
+ {
+ if (this ==&other)
+ {
+ return;
+ }
+ switch (type_id())
+ {
+ case json_type_tag::null_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::string_t:
+ {
+ string_data temp(std::move(*other.string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))null_data();
+ new(reinterpret_cast<void*>(&data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ byte_string_data temp(std::move(*other.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))null_data();
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ array_data temp(std::move(*other.array_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))null_data();
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ object_data temp(std::move(*other.object_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))null_data();
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(temp));
+ }
+ break;
+ default:
+ std::swap(data_,other.data_);
+ break;
+ }
+ }
+ break;
+ case json_type_tag::empty_object_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::string_t:
+ {
+ string_data temp(std::move(*other.string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))empty_object_data();
+ new(reinterpret_cast<void*>(&data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ byte_string_data temp(std::move(*other.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))empty_object_data();
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ array_data temp(std::move(*other.array_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))empty_object_data();
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ object_data temp(std::move(*other.object_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))empty_object_data();
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(temp));
+ }
+ break;
+ default:
+ std::swap(data_,other.data_);
+ break;
+ }
+ }
+ break;
+ case json_type_tag::bool_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::string_t:
+ {
+ string_data temp(std::move(*other.string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))bool_data(*bool_data_cast());
+ new(reinterpret_cast<void*>(&data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ byte_string_data temp(std::move(*other.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))bool_data(*bool_data_cast());
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ array_data temp(std::move(*other.array_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))bool_data(*bool_data_cast());
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ object_data temp(std::move(*other.object_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))bool_data(*bool_data_cast());
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(temp));
+ }
+ break;
+ default:
+ std::swap(data_,other.data_);
+ break;
+ }
+ }
+ break;
+ case json_type_tag::integer_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::string_t:
+ {
+ string_data temp(std::move(*other.string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))integer_data(*integer_data_cast());
+ new(reinterpret_cast<void*>(&data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ byte_string_data temp(std::move(*other.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))integer_data(*integer_data_cast());
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ array_data temp(std::move(*other.array_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))integer_data(*integer_data_cast());
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ object_data temp(std::move(*other.object_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))integer_data(*integer_data_cast());
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(temp));
+ }
+ break;
+ default:
+ std::swap(data_,other.data_);
+ break;
+ }
+ }
+ break;
+ case json_type_tag::uinteger_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::string_t:
+ {
+ string_data temp(std::move(*other.string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))uinteger_data(*uinteger_data_cast());
+ new(reinterpret_cast<void*>(&data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ byte_string_data temp(std::move(*other.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))uinteger_data(*uinteger_data_cast());
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ array_data temp(std::move(*other.array_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))uinteger_data(*uinteger_data_cast());
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ object_data temp(std::move(*other.object_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))uinteger_data(*uinteger_data_cast());
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(temp));
+ }
+ break;
+ default:
+ std::swap(data_,other.data_);
+ break;
+ }
+ }
+ break;
+ case json_type_tag::double_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::string_t:
+ {
+ string_data temp(std::move(*other.string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))double_data(*double_data_cast());
+ new(reinterpret_cast<void*>(&data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ byte_string_data temp(std::move(*other.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))double_data(*double_data_cast());
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ array_data temp(std::move(*other.array_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))double_data(*double_data_cast());
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ object_data temp(std::move(*other.object_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))double_data(*double_data_cast());
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(temp));
+ }
+ break;
+ default:
+ std::swap(data_,other.data_);
+ break;
+ }
+ }
+ break;
+ case json_type_tag::small_string_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::string_t:
+ {
+ string_data temp(std::move(*other.string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))small_string_data(*small_string_data_cast());
+ new(reinterpret_cast<void*>(&data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ byte_string_data temp(std::move(*other.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))small_string_data(*small_string_data_cast());
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ array_data temp(std::move(*other.array_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))small_string_data(*small_string_data_cast());
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ object_data temp(std::move(*other.object_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))small_string_data(*small_string_data_cast());
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(temp));
+ }
+ break;
+ default:
+ std::swap(data_,other.data_);
+ break;
+ }
+ }
+ break;
+ case json_type_tag::string_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::null_t:
+ {
+ string_data temp(std::move(*string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))null_data();
+ new(reinterpret_cast<void*>(&other.data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::empty_object_t:
+ {
+ string_data temp(std::move(*string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))empty_object_data();
+ new(reinterpret_cast<void*>(&other.data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::bool_t:
+ {
+ string_data temp(std::move(*string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))bool_data(*(other.bool_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::integer_t:
+ {
+ string_data temp(std::move(*string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))integer_data(*(other.integer_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::uinteger_t:
+ {
+ string_data temp(std::move(*string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))uinteger_data(*(other.uinteger_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::double_t:
+ {
+ string_data temp(std::move(*string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))double_data(*(other.double_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::small_string_t:
+ {
+ string_data temp(std::move(*string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))small_string_data(*(other.small_string_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::string_t:
+ {
+ string_data_cast()->swap(*other.string_data_cast());
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ string_data temp(std::move(*string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(*other.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ string_data temp(std::move(*string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(*other.array_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ string_data temp(std::move(*string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(*other.object_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))string_data(std::move(temp));
+ }
+ break;
+ default:
+ JSONCONS_UNREACHABLE();
+ break;
+ }
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::null_t:
+ {
+ byte_string_data temp(std::move(*byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))null_data();
+ new(reinterpret_cast<void*>(&other.data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::empty_object_t:
+ {
+ byte_string_data temp(std::move(*byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))empty_object_data();
+ new(reinterpret_cast<void*>(&other.data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::bool_t:
+ {
+ byte_string_data temp(std::move(*byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))bool_data(*(other.bool_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::integer_t:
+ {
+ byte_string_data temp(std::move(*byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))integer_data(*(other.integer_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::uinteger_t:
+ {
+ byte_string_data temp(std::move(*byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))uinteger_data(*(other.uinteger_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::double_t:
+ {
+ byte_string_data temp(std::move(*byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))double_data(*(other.double_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::small_string_t:
+ {
+ byte_string_data temp(std::move(*byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))small_string_data(*(other.small_string_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::string_t:
+ {
+ byte_string_data temp(std::move(*byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))string_data(*(other.string_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ byte_string_data_cast()->swap(*other.byte_string_data_cast());
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ byte_string_data temp(std::move(*byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(*other.array_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))byte_string_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ byte_string_data temp(std::move(*byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(*other.object_data_cast()));
+ new(reinterpret_cast<void*>(&other.data_))byte_string_data(std::move(temp));
+ }
+ break;
+ default:
+ JSONCONS_UNREACHABLE();
+ break;
+ }
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::null_t:
+ {
+ array_data temp(std::move(*array_data_cast()));
+ new(reinterpret_cast<void*>(&data_))null_data();
+ new(reinterpret_cast<void*>(&(other.data_)))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::empty_object_t:
+ {
+ array_data temp(std::move(*array_data_cast()));
+ new(reinterpret_cast<void*>(&data_))empty_object_data();
+ new(reinterpret_cast<void*>(&(other.data_)))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::bool_t:
+ {
+ array_data temp(std::move(*array_data_cast()));
+ new(reinterpret_cast<void*>(&data_))bool_data(*(other.bool_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::integer_t:
+ {
+ array_data temp(std::move(*array_data_cast()));
+ new(reinterpret_cast<void*>(&data_))integer_data(*(other.integer_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::uinteger_t:
+ {
+ array_data temp(std::move(*array_data_cast()));
+ new(reinterpret_cast<void*>(&data_))uinteger_data(*(other.uinteger_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::double_t:
+ {
+ array_data temp(std::move(*array_data_cast()));
+ new(reinterpret_cast<void*>(&data_))double_data(*(other.double_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::small_string_t:
+ {
+ array_data temp(std::move(*array_data_cast()));
+ new(reinterpret_cast<void*>(&data_))small_string_data(*(other.small_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::string_t:
+ {
+ array_data temp(std::move(*array_data_cast()));
+ new(reinterpret_cast<void*>(&data_))string_data(std::move(*other.string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ array_data temp(std::move(*array_data_cast()));
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(*other.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))array_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ array_data_cast()->swap(*other.array_data_cast());
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ array_data temp(std::move(*array_data_cast()));
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(*other.object_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))array_data(std::move(temp));
+ }
+ break;
+ default:
+ JSONCONS_UNREACHABLE();
+ break;
+ }
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ switch (other.type_id())
+ {
+ case json_type_tag::null_t:
+ {
+ object_data temp(std::move(*object_data_cast()));
+ new(reinterpret_cast<void*>(&data_))null_data();
+ new(reinterpret_cast<void*>(&(other.data_)))object_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::empty_object_t:
+ {
+ object_data temp(std::move(*object_data_cast()));
+ new(reinterpret_cast<void*>(&data_))empty_object_data();
+ new(reinterpret_cast<void*>(&(other.data_)))object_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::bool_t:
+ {
+ object_data temp(std::move(*object_data_cast()));
+ new(reinterpret_cast<void*>(&data_))bool_data(*(other.bool_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))object_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::integer_t:
+ {
+ object_data temp(std::move(*object_data_cast()));
+ new(reinterpret_cast<void*>(&data_))integer_data(*(other.integer_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))object_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::uinteger_t:
+ {
+ object_data temp(std::move(*object_data_cast()));
+ new(reinterpret_cast<void*>(&data_))uinteger_data(*(other.uinteger_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))object_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::double_t:
+ {
+ object_data temp(std::move(*object_data_cast()));
+ new(reinterpret_cast<void*>(&data_))double_data(*(other.double_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))object_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::small_string_t:
+ {
+ object_data temp(std::move(*object_data_cast()));
+ new(reinterpret_cast<void*>(&data_))small_string_data(*(other.small_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))object_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::string_t:
+ {
+ object_data temp(std::move(*object_data_cast()));
+ new(reinterpret_cast<void*>(&data_))string_data(std::move(*other.string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))object_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ object_data temp(std::move(*object_data_cast()));
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(*other.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))object_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ object_data temp(std::move(*object_data_cast()));
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(*other.array_data_cast()));
+ new(reinterpret_cast<void*>(&(other.data_)))object_data(std::move(temp));
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ object_data_cast()->swap(*other.object_data_cast());
+ }
+ break;
+ default:
+ JSONCONS_UNREACHABLE();
+ break;
+ }
+ }
+ break;
+ default:
+ JSONCONS_UNREACHABLE();
+ break;
+ }
+ }
+ private:
+
+ void Init_(const variant& val)
+ {
+ switch (val.type_id())
+ {
+ case json_type_tag::null_t:
+ new(reinterpret_cast<void*>(&data_))null_data();
+ break;
+ case json_type_tag::empty_object_t:
+ new(reinterpret_cast<void*>(&data_))empty_object_data();
+ break;
+ case json_type_tag::bool_t:
+ new(reinterpret_cast<void*>(&data_))bool_data(*(val.bool_data_cast()));
+ break;
+ case json_type_tag::integer_t:
+ new(reinterpret_cast<void*>(&data_))integer_data(*(val.integer_data_cast()));
+ break;
+ case json_type_tag::uinteger_t:
+ new(reinterpret_cast<void*>(&data_))uinteger_data(*(val.uinteger_data_cast()));
+ break;
+ case json_type_tag::double_t:
+ new(reinterpret_cast<void*>(&data_))double_data(*(val.double_data_cast()));
+ break;
+ case json_type_tag::small_string_t:
+ new(reinterpret_cast<void*>(&data_))small_string_data(*(val.small_string_data_cast()));
+ break;
+ case json_type_tag::string_t:
+ new(reinterpret_cast<void*>(&data_))string_data(*(val.string_data_cast()));
+ break;
+ case json_type_tag::byte_string_t:
+ new(reinterpret_cast<void*>(&data_))byte_string_data(*(val.byte_string_data_cast()));
+ break;
+ case json_type_tag::object_t:
+ new(reinterpret_cast<void*>(&data_))object_data(*(val.object_data_cast()));
+ break;
+ case json_type_tag::array_t:
+ new(reinterpret_cast<void*>(&data_))array_data(*(val.array_data_cast()));
+ break;
+ default:
+ break;
+ }
+ }
+
+ void Init_(const variant& val, const Allocator& a)
+ {
+ switch (val.type_id())
+ {
+ case json_type_tag::null_t:
+ case json_type_tag::empty_object_t:
+ case json_type_tag::bool_t:
+ case json_type_tag::integer_t:
+ case json_type_tag::uinteger_t:
+ case json_type_tag::double_t:
+ case json_type_tag::small_string_t:
+ Init_(val);
+ break;
+ case json_type_tag::string_t:
+ new(reinterpret_cast<void*>(&data_))string_data(*(val.string_data_cast()),a);
+ break;
+ case json_type_tag::byte_string_t:
+ new(reinterpret_cast<void*>(&data_))byte_string_data(*(val.byte_string_data_cast()),a);
+ break;
+ case json_type_tag::array_t:
+ new(reinterpret_cast<void*>(&data_))array_data(*(val.array_data_cast()),a);
+ break;
+ case json_type_tag::object_t:
+ new(reinterpret_cast<void*>(&data_))object_data(*(val.object_data_cast()),a);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void Init_rv_(variant&& val) JSONCONS_NOEXCEPT
+ {
+ switch (val.type_id())
+ {
+ case json_type_tag::null_t:
+ case json_type_tag::empty_object_t:
+ case json_type_tag::double_t:
+ case json_type_tag::integer_t:
+ case json_type_tag::uinteger_t:
+ case json_type_tag::bool_t:
+ case json_type_tag::small_string_t:
+ Init_(val);
+ break;
+ case json_type_tag::string_t:
+ {
+ new(reinterpret_cast<void*>(&data_))string_data(std::move(*val.string_data_cast()));
+ new(reinterpret_cast<void*>(&val.data_))null_data();
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ new(reinterpret_cast<void*>(&data_))byte_string_data(std::move(*val.byte_string_data_cast()));
+ new(reinterpret_cast<void*>(&val.data_))null_data();
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ new(reinterpret_cast<void*>(&data_))array_data(std::move(*val.array_data_cast()));
+ new(reinterpret_cast<void*>(&val.data_))null_data();
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ new(reinterpret_cast<void*>(&data_))object_data(std::move(*val.object_data_cast()));
+ new(reinterpret_cast<void*>(&val.data_))null_data();
+ }
+ break;
+ default:
+ JSONCONS_UNREACHABLE();
+ break;
+ }
+ }
+
+ void Init_rv_(variant&& val, const Allocator& a, std::true_type) JSONCONS_NOEXCEPT
+ {
+ Init_rv_(std::forward<variant>(val));
+ }
+
+ void Init_rv_(variant&& val, const Allocator& a, std::false_type) JSONCONS_NOEXCEPT
+ {
+ switch (val.type_id())
+ {
+ case json_type_tag::null_t:
+ case json_type_tag::empty_object_t:
+ case json_type_tag::double_t:
+ case json_type_tag::integer_t:
+ case json_type_tag::uinteger_t:
+ case json_type_tag::bool_t:
+ case json_type_tag::small_string_t:
+ Init_(std::forward<variant>(val));
+ break;
+ case json_type_tag::string_t:
+ {
+ if (a == val.string_data_cast()->get_allocator())
+ {
+ Init_rv_(std::forward<variant>(val), a, std::true_type());
+ }
+ else
+ {
+ Init_(val,a);
+ }
+ }
+ break;
+ case json_type_tag::byte_string_t:
+ {
+ if (a == val.byte_string_data_cast()->get_allocator())
+ {
+ Init_rv_(std::forward<variant>(val), a, std::true_type());
+ }
+ else
+ {
+ Init_(val,a);
+ }
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ if (a == val.object_data_cast()->get_allocator())
+ {
+ Init_rv_(std::forward<variant>(val), a, std::true_type());
+ }
+ else
+ {
+ Init_(val,a);
+ }
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ if (a == val.array_data_cast()->get_allocator())
+ {
+ Init_rv_(std::forward<variant>(val), a, std::true_type());
+ }
+ else
+ {
+ Init_(val,a);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ template <class ParentT>
+ class json_proxy
+ {
+ private:
+ typedef json_proxy<ParentT> proxy_type;
+
+ ParentT& parent_;
+ key_storage_type key_;
+
+ json_proxy() = delete;
+ json_proxy& operator = (const json_proxy& other) = delete;
+
+ json_proxy(ParentT& parent, key_storage_type&& name)
+ : parent_(parent), key_(std::forward<key_storage_type>(name))
+ {
+ }
+
+ basic_json& evaluate()
+ {
+ return parent_.evaluate(string_view_type(key_.data(),key_.size()));
+ }
+
+ const basic_json& evaluate() const
+ {
+ return parent_.evaluate(string_view_type(key_.data(),key_.size()));
+ }
+
+ basic_json& evaluate_with_default()
+ {
+ basic_json& val = parent_.evaluate_with_default();
+ auto it = val.find(string_view_type(key_.data(),key_.size()));
+ if (it == val.object_range().end())
+ {
+ it = val.set_(val.object_range().begin(),std::move(key_),object(val.object_value().get_allocator()));
+ }
+ return it->value();
+ }
+
+ basic_json& evaluate(size_t index)
+ {
+ return evaluate().at(index);
+ }
+
+ const basic_json& evaluate(size_t index) const
+ {
+ return evaluate().at(index);
+ }
+
+ basic_json& evaluate(const string_view_type& index)
+ {
+ return evaluate().at(index);
+ }
+
+ const basic_json& evaluate(const string_view_type& index) const
+ {
+ return evaluate().at(index);
+ }
+ public:
+
+ friend class basic_json<CharT,ImplementationPolicy,Allocator>;
+
+ range<object_iterator> object_range()
+ {
+ return evaluate().object_range();
+ }
+
+ range<const_object_iterator> object_range() const
+ {
+ return evaluate().object_range();
+ }
+
+ range<array_iterator> array_range()
+ {
+ return evaluate().array_range();
+ }
+
+ range<const_array_iterator> array_range() const
+ {
+ return evaluate().array_range();
+ }
+
+ size_t size() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().size();
+ }
+
+ json_type_tag type_id() const
+ {
+ return evaluate().type_id();
+ }
+
+ size_t count(const string_view_type& name) const
+ {
+ return evaluate().count(name);
+ }
+
+ bool has_key(const string_view_type& name) const
+ {
+ return evaluate().has_key(name);
+ }
+
+ bool is_null() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_null();
+ }
+
+ bool empty() const
+ {
+ return evaluate().empty();
+ }
+
+ size_t capacity() const
+ {
+ return evaluate().capacity();
+ }
+
+ void reserve(size_t n)
+ {
+ evaluate().reserve(n);
+ }
+
+ void resize(size_t n)
+ {
+ evaluate().resize(n);
+ }
+
+ template <class T>
+ void resize(size_t n, T val)
+ {
+ evaluate().resize(n,val);
+ }
+
+ template<class T, class... Args>
+ bool is(Args&&... args) const
+ {
+ return evaluate().template is<T>(std::forward<Args>(args)...);
+ }
+
+ bool is_string() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_string();
+ }
+
+ bool is_byte_string() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_byte_string();
+ }
+
+ bool is_number() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_number();
+ }
+ bool is_bool() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_bool();
+ }
+
+ bool is_object() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_object();
+ }
+
+ bool is_array() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_array();
+ }
+ bool is_integer() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_integer();
+ }
+
+ bool is_uinteger() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_uinteger();
+ }
+
+ bool is_double() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_double();
+ }
+
+ string_view_type as_string_view() const
+ {
+ return evaluate().as_string_view();
+ }
+
+ byte_string_view as_byte_string_view() const
+ {
+ return evaluate().as_byte_string_view();
+ }
+
+ string_type as_string() const
+ {
+ return evaluate().as_string();
+ }
+
+ template <class SAllocator>
+ string_type as_string(const SAllocator& allocator) const
+ {
+ return evaluate().as_string(allocator);
+ }
+
+ string_type as_string(const basic_serialization_options<char_type>& options) const
+ {
+ return evaluate().as_string(options);
+ }
+
+ template <class SAllocator>
+ string_type as_string(const basic_serialization_options<char_type>& options,
+ const SAllocator& allocator) const
+ {
+ return evaluate().as_string(options,allocator);
+ }
+
+ template<class T, class... Args>
+ T as(Args&&... args) const
+ {
+ return evaluate().template as<T>(std::forward<Args>(args)...);
+ }
+
+ template<class T>
+ typename std::enable_if<std::is_same<string_type,T>::value,T>::type
+ as(const char_allocator_type& allocator) const
+ {
+ return evaluate().template as<T>(allocator);
+ }
+ bool as_bool() const
+ {
+ return evaluate().as_bool();
+ }
+
+ double as_double() const
+ {
+ return evaluate().as_double();
+ }
+
+ int64_t as_integer() const
+ {
+ return evaluate().as_integer();
+ }
+
+ unsigned long long as_ulonglong() const
+ {
+ return evaluate().as_ulonglong();
+ }
+
+ uint64_t as_uinteger() const
+ {
+ return evaluate().as_uinteger();
+ }
+
+ template <class T>
+ json_proxy& operator=(T&& val)
+ {
+ parent_.evaluate_with_default().set_(std::move(key_), std::forward<T>(val));
+ return *this;
+ }
+
+ bool operator==(const basic_json& val) const
+ {
+ return evaluate() == val;
+ }
+
+ bool operator!=(const basic_json& val) const
+ {
+ return evaluate() != val;
+ }
+
+ basic_json& operator[](size_t i)
+ {
+ return evaluate_with_default().at(i);
+ }
+
+ const basic_json& operator[](size_t i) const
+ {
+ return evaluate().at(i);
+ }
+
+ json_proxy<proxy_type> operator[](const string_view_type& name)
+ {
+ return json_proxy<proxy_type>(*this,key_storage_type(name.begin(),name.end(),key_.get_allocator()));
+ }
+
+ const basic_json& operator[](const string_view_type& name) const
+ {
+ return at(name);
+ }
+
+ basic_json& at(const string_view_type& name)
+ {
+ return evaluate().at(name);
+ }
+
+ const basic_json& at(const string_view_type& name) const
+ {
+ return evaluate().at(name);
+ }
+
+ const basic_json& at(size_t index)
+ {
+ return evaluate().at(index);
+ }
+
+ const basic_json& at(size_t index) const
+ {
+ return evaluate().at(index);
+ }
+
+ object_iterator find(const string_view_type& name)
+ {
+ return evaluate().find(name);
+ }
+
+ const_object_iterator find(const string_view_type& name) const
+ {
+ return evaluate().find(name);
+ }
+
+ template <class T>
+ basic_json get(const string_view_type& name, T&& default_val) const
+ {
+ return evaluate().get(name,std::forward<T>(default_val));
+ }
+
+ template <class T>
+ T get_with_default(const string_view_type& name, const T& default_val) const
+ {
+ return evaluate().get_with_default(name,default_val);
+ }
+
+ const CharT* get_with_default(const string_view_type& name, const CharT* default_val) const
+ {
+ return evaluate().get_with_default(name,default_val);
+ }
+
+ void shrink_to_fit()
+ {
+ evaluate_with_default().shrink_to_fit();
+ }
+
+ void clear()
+ {
+ evaluate().clear();
+ }
+ // Remove all elements from an array or object
+
+ void erase(const_object_iterator pos)
+ {
+ evaluate().erase(pos);
+ }
+ // Remove a range of elements from an object
+
+ void erase(const_object_iterator first, const_object_iterator last)
+ {
+ evaluate().erase(first, last);
+ }
+ // Remove a range of elements from an object
+
+ void erase(const string_view_type& name)
+ {
+ evaluate().erase(name);
+ }
+
+ void erase(const_array_iterator pos)
+ {
+ evaluate().erase(pos);
+ }
+ // Removes the element at pos
+
+ void erase(const_array_iterator first, const_array_iterator last)
+ {
+ evaluate().erase(first, last);
+ }
+ // Remove a range of elements from an array
+
+ // merge
+
+ void merge(const basic_json& source)
+ {
+ return evaluate().merge(source);
+ }
+
+ void merge(basic_json&& source)
+ {
+ return evaluate().merge(std::forward<basic_json>(source));
+ }
+
+ void merge(object_iterator hint, const basic_json& source)
+ {
+ return evaluate().merge(hint, source);
+ }
+
+ void merge(object_iterator hint, basic_json&& source)
+ {
+ return evaluate().merge(hint, std::forward<basic_json>(source));
+ }
+
+ // merge_or_update
+
+ void merge_or_update(const basic_json& source)
+ {
+ return evaluate().merge_or_update(source);
+ }
+
+ void merge_or_update(basic_json&& source)
+ {
+ return evaluate().merge_or_update(std::forward<basic_json>(source));
+ }
+
+ void merge_or_update(object_iterator hint, const basic_json& source)
+ {
+ return evaluate().merge_or_update(hint, source);
+ }
+
+ void merge_or_update(object_iterator hint, basic_json&& source)
+ {
+ return evaluate().merge_or_update(hint, std::forward<basic_json>(source));
+ }
+
+ // set
+
+ template <class T>
+ std::pair<object_iterator,bool> set(const string_view_type& name, T&& val)
+ {
+ return evaluate().set(name,std::forward<T>(val));
+ }
+
+ template <class T>
+ std::pair<object_iterator,bool> insert_or_assign(const string_view_type& name, T&& val)
+ {
+ return evaluate().insert_or_assign(name,std::forward<T>(val));
+ }
+
+ template <class T>
+ void set_(key_storage_type&& name, T&& val)
+ {
+ evaluate().set_(std::forward<key_storage_type>(name),std::forward<T>(val));
+ }
+
+ // emplace
+
+ template <class ... Args>
+ std::pair<object_iterator,bool> try_emplace(const string_view_type& name, Args&&... args)
+ {
+ return evaluate().try_emplace(name,std::forward<Args>(args)...);
+ }
+
+ template <class T>
+ object_iterator set(object_iterator hint, const string_view_type& name, T&& val)
+ {
+ return evaluate().set(hint, name, std::forward<T>(val));
+ }
+
+ template <class T>
+ object_iterator insert_or_assign(object_iterator hint, const string_view_type& name, T&& val)
+ {
+ return evaluate().insert_or_assign(hint, name, std::forward<T>(val));
+ }
+
+ template <class ... Args>
+ object_iterator try_emplace(object_iterator hint, const string_view_type& name, Args&&... args)
+ {
+ return evaluate().try_emplace(hint, name, std::forward<Args>(args)...);
+ }
+
+ template <class T>
+ object_iterator set_(object_iterator hint, key_storage_type&& name, T&& val)
+ {
+ return evaluate().set_(hint, std::forward<key_storage_type>(name), std::forward<T>(val));
+ }
+
+ template <class... Args>
+ array_iterator emplace(const_array_iterator pos, Args&&... args)
+ {
+ evaluate_with_default().emplace(pos, std::forward<Args>(args)...);
+ }
+
+ template <class... Args>
+ basic_json& emplace_back(Args&&... args)
+ {
+ return evaluate_with_default().emplace_back(std::forward<Args>(args)...);
+ }
+
+ template <class T>
+ void add(T&& val)
+ {
+ evaluate_with_default().add(std::forward<T>(val));
+ }
+
+ template <class T>
+ void push_back(T&& val)
+ {
+ evaluate_with_default().push_back(std::forward<T>(val));
+ }
+
+ template <class T>
+ array_iterator add(const_array_iterator pos, T&& val)
+ {
+ return evaluate_with_default().add(pos, std::forward<T>(val));
+ }
+
+ template <class T>
+ array_iterator insert(const_array_iterator pos, T&& val)
+ {
+ return evaluate_with_default().insert(pos, std::forward<T>(val));
+ }
+
+ template <class InputIt>
+ array_iterator insert(const_array_iterator pos, InputIt first, InputIt last)
+ {
+ return evaluate_with_default().insert(pos, first, last);
+ }
+
+ template <class SAllocator>
+ void dump(std::basic_string<char_type,char_traits_type,SAllocator>& s) const
+ {
+ evaluate().dump(s);
+ }
+
+ template <class SAllocator>
+ void dump(std::basic_string<char_type,char_traits_type,SAllocator>& s,
+ const basic_serialization_options<char_type>& options) const
+ {
+ evaluate().dump(s,options);
+ }
+ void dump(basic_json_output_handler<char_type>& handler) const
+ {
+ evaluate().dump(handler);
+ }
+
+ void dump(std::basic_ostream<char_type>& os) const
+ {
+ evaluate().dump(os);
+ }
+
+ void dump(std::basic_ostream<char_type>& os, bool pprint) const
+ {
+ evaluate().dump(os, pprint);
+ }
+
+ void dump(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options) const
+ {
+ evaluate().dump(os,options);
+ }
+
+ void dump(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options, bool pprint) const
+ {
+ evaluate().dump(os,options,pprint);
+ }
+#if !defined(JSONCONS_NO_DEPRECATED)
+
+ string_type to_string(const char_allocator_type& allocator = char_allocator_type()) const JSONCONS_NOEXCEPT
+ {
+ return evaluate().to_string(allocator);
+ }
+ void write(basic_json_output_handler<char_type>& handler) const
+ {
+ evaluate().write(handler);
+ }
+
+ void write(std::basic_ostream<char_type>& os) const
+ {
+ evaluate().write(os);
+ }
+
+ void write(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options) const
+ {
+ evaluate().write(os,options);
+ }
+
+ void write(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options, bool pprint) const
+ {
+ evaluate().write(os,options,pprint);
+ }
+
+ string_type to_string(const basic_serialization_options<char_type>& options, char_allocator_type& allocator = char_allocator_type()) const
+ {
+ return evaluate().to_string(options,allocator);
+ }
+
+ range<object_iterator> members()
+ {
+ return evaluate().members();
+ }
+
+ range<const_object_iterator> members() const
+ {
+ return evaluate().members();
+ }
+
+ range<array_iterator> elements()
+ {
+ return evaluate().elements();
+ }
+
+ range<const_array_iterator> elements() const
+ {
+ return evaluate().elements();
+ }
+ void to_stream(basic_json_output_handler<char_type>& handler) const
+ {
+ evaluate().to_stream(handler);
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os) const
+ {
+ evaluate().to_stream(os);
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options) const
+ {
+ evaluate().to_stream(os,options);
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options, bool pprint) const
+ {
+ evaluate().to_stream(os,options,pprint);
+ }
+#endif
+ void swap(basic_json& val)
+ {
+ evaluate_with_default().swap(val);
+ }
+
+ friend std::basic_ostream<char_type>& operator<<(std::basic_ostream<char_type>& os, const json_proxy& o)
+ {
+ o.dump(os);
+ return os;
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+
+ void resize_array(size_t n)
+ {
+ evaluate().resize_array(n);
+ }
+
+ template <class T>
+ void resize_array(size_t n, T val)
+ {
+ evaluate().resize_array(n,val);
+ }
+
+ object_iterator begin_members()
+ {
+ return evaluate().begin_members();
+ }
+
+ const_object_iterator begin_members() const
+ {
+ return evaluate().begin_members();
+ }
+
+ object_iterator end_members()
+ {
+ return evaluate().end_members();
+ }
+
+ const_object_iterator end_members() const
+ {
+ return evaluate().end_members();
+ }
+
+ array_iterator begin_elements()
+ {
+ return evaluate().begin_elements();
+ }
+
+ const_array_iterator begin_elements() const
+ {
+ return evaluate().begin_elements();
+ }
+
+ array_iterator end_elements()
+ {
+ return evaluate().end_elements();
+ }
+
+ const_array_iterator end_elements() const
+ {
+ return evaluate().end_elements();
+ }
+
+ const basic_json& get(const string_view_type& name) const
+ {
+ return evaluate().get(name);
+ }
+
+ bool is_ulonglong() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_ulonglong();
+ }
+
+ bool is_longlong() const JSONCONS_NOEXCEPT
+ {
+ return evaluate().is_longlong();
+ }
+
+ int as_int() const
+ {
+ return evaluate().as_int();
+ }
+
+ unsigned int as_uint() const
+ {
+ return evaluate().as_uint();
+ }
+
+ long as_long() const
+ {
+ return evaluate().as_long();
+ }
+
+ unsigned long as_ulong() const
+ {
+ return evaluate().as_ulong();
+ }
+
+ long long as_longlong() const
+ {
+ return evaluate().as_longlong();
+ }
+
+ void add(size_t index, const basic_json& value)
+ {
+ evaluate_with_default().add(index, value);
+ }
+
+ void add(size_t index, basic_json&& value)
+ {
+ evaluate_with_default().add(index, std::forward<basic_json>(value));
+ }
+
+ bool has_member(const key_storage_type& name) const
+ {
+ return evaluate().has_member(name);
+ }
+
+ // Remove a range of elements from an array
+ void remove_range(size_t from_index, size_t to_index)
+ {
+ evaluate().remove_range(from_index, to_index);
+ }
+ // Remove a range of elements from an array
+ void remove(const string_view_type& name)
+ {
+ evaluate().remove(name);
+ }
+ void remove_member(const string_view_type& name)
+ {
+ evaluate().remove(name);
+ }
+ bool is_empty() const JSONCONS_NOEXCEPT
+ {
+ return empty();
+ }
+ bool is_numeric() const JSONCONS_NOEXCEPT
+ {
+ return is_number();
+ }
+#endif
+ };
+
+ static basic_json parse(std::basic_istream<char_type>& is);
+ static basic_json parse(std::basic_istream<char_type>& is, parse_error_handler& err_handler);
+
+ static basic_json parse(const string_view_type& s)
+ {
+ parse_error_handler_type err_handler;
+ return parse(s,err_handler);
+ }
+
+ static basic_json parse(const char_type* s, size_t length)
+ {
+ parse_error_handler_type err_handler;
+ return parse(s,length,err_handler);
+ }
+
+ static basic_json parse(const char_type* s, size_t length, parse_error_handler& err_handler)
+ {
+ return parse(string_view_type(s,length),err_handler);
+ }
+
+ static basic_json parse(const string_view_type& s, parse_error_handler& err_handler)
+ {
+ json_decoder<basic_json> decoder;
+ basic_json_parser<char_type> parser(decoder,err_handler);
+
+ auto result = unicons::skip_bom(s.begin(), s.end());
+ if (result.ec != unicons::encoding_errc())
+ {
+ throw parse_error(result.ec,1,1);
+ }
+ size_t offset = result.it - s.begin();
+ parser.set_source(s.data()+offset,s.size()-offset);
+ parser.parse_some();
+ parser.end_parse();
+ parser.check_done();
+ if (!decoder.is_valid())
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Failed to parse json string"));
+ }
+ return decoder.get_result();
+ }
+
+ static basic_json make_array()
+ {
+ return basic_json(variant(array()));
+ }
+
+ static basic_json make_array(const array& a)
+ {
+ return basic_json(variant(a));
+ }
+
+ static basic_json make_array(const array& a, allocator_type allocator)
+ {
+ return basic_json(variant(a,allocator));
+ }
+
+ static basic_json make_array(std::initializer_list<basic_json> init, const Allocator& allocator = Allocator())
+ {
+ return array(std::move(init),allocator);
+ }
+
+ static basic_json make_array(size_t n, const Allocator& allocator = Allocator())
+ {
+ return array(n,allocator);
+ }
+
+ template <class T>
+ static basic_json make_array(size_t n, const T& val, const Allocator& allocator = Allocator())
+ {
+ return basic_json::array(n, val,allocator);
+ }
+
+ template <size_t dim>
+ static typename std::enable_if<dim==1,basic_json>::type make_array(size_t n)
+ {
+ return array(n);
+ }
+
+ template <size_t dim, class T>
+ static typename std::enable_if<dim==1,basic_json>::type make_array(size_t n, const T& val, const Allocator& allocator = Allocator())
+ {
+ return array(n,val,allocator);
+ }
+
+ template <size_t dim, typename... Args>
+ static typename std::enable_if<(dim>1),basic_json>::type make_array(size_t n, Args... args)
+ {
+ const size_t dim1 = dim - 1;
+
+ basic_json val = make_array<dim1>(args...);
+ val.resize(n);
+ for (size_t i = 0; i < n; ++i)
+ {
+ val[i] = make_array<dim1>(args...);
+ }
+ return val;
+ }
+
+ static const basic_json& null()
+ {
+ static basic_json a_null = basic_json(variant(null_type()));
+ return a_null;
+ }
+
+ variant var_;
+
+ basic_json()
+ : var_()
+ {
+ }
+
+ explicit basic_json(const Allocator& allocator)
+ : var_(allocator)
+ {
+ }
+
+ basic_json(const basic_json& val)
+ : var_(val.var_)
+ {
+ }
+
+ basic_json(const basic_json& val, const Allocator& allocator)
+ : var_(val.var_,allocator)
+ {
+ }
+
+ basic_json(basic_json&& other) JSONCONS_NOEXCEPT
+ : var_(std::move(other.var_))
+ {
+ }
+
+ basic_json(basic_json&& other, const Allocator& allocator) JSONCONS_NOEXCEPT
+ : var_(std::move(other.var_) /*,allocator*/ )
+ {
+ }
+
+ basic_json(const variant& val)
+ : var_(val)
+ {
+ }
+
+ basic_json(variant&& other)
+ : var_(std::forward<variant>(other))
+ {
+ }
+
+ basic_json(const array& val)
+ : var_(val)
+ {
+ }
+
+ basic_json(array&& other)
+ : var_(std::forward<array>(other))
+ {
+ }
+
+ basic_json(const object& other)
+ : var_(other)
+ {
+ }
+
+ basic_json(object&& other)
+ : var_(std::forward<object>(other))
+ {
+ }
+
+ template <class ParentT>
+ basic_json(const json_proxy<ParentT>& proxy)
+ : var_(proxy.evaluate().var_)
+ {
+ }
+
+ template <class ParentT>
+ basic_json(const json_proxy<ParentT>& proxy, const Allocator& allocator)
+ : var_(proxy.evaluate().var_,allocator)
+ {
+ }
+
+ template <class T>
+ basic_json(const T& val)
+ : var_(json_type_traits<basic_json,T>::to_json(val).var_)
+ {
+ }
+
+ template <class T>
+ basic_json(const T& val, const Allocator& allocator)
+ : var_(json_type_traits<basic_json,T>::to_json(val,allocator).var_)
+ {
+ }
+
+ basic_json(const char_type* s)
+ : var_(s)
+ {
+ }
+
+ basic_json(const char_type* s, const Allocator& allocator)
+ : var_(s,allocator)
+ {
+ }
+
+ basic_json(double val, uint8_t precision)
+ : var_(val, number_format(precision, 0))
+ {
+ }
+
+ basic_json(double val, const number_format& fmt)
+ : var_(val, fmt)
+ {
+ }
+
+ basic_json(const char_type *s, size_t length)
+ : var_(s, length)
+ {
+ }
+
+ basic_json(const char_type *s, size_t length, const Allocator& allocator)
+ : var_(s, length, allocator)
+ {
+ }
+
+ basic_json(const uint8_t* s, size_t length)
+ : var_(s, length)
+ {
+ }
+
+ explicit basic_json(const byte_string_view& s)
+ : var_(s.data(), s.length())
+ {
+ }
+
+ basic_json(const uint8_t* s, size_t length, const Allocator& allocator)
+ : var_(s, length, allocator)
+ {
+ }
+#if !defined(JSONCONS_NO_DEPRECATED)
+ template<class InputIterator>
+ basic_json(InputIterator first, InputIterator last, const Allocator& allocator = Allocator())
+ : var_(first,last,allocator)
+ {
+ }
+#endif
+
+ ~basic_json()
+ {
+ }
+
+ basic_json& operator=(const basic_json& rhs)
+ {
+ if (this != &rhs)
+ {
+ var_ = rhs.var_;
+ }
+ return *this;
+ }
+
+ basic_json& operator=(basic_json&& rhs) JSONCONS_NOEXCEPT
+ {
+ if (this !=&rhs)
+ {
+ var_ = std::move(rhs.var_);
+ }
+ return *this;
+ }
+
+ template <class T>
+ basic_json& operator=(const T& val)
+ {
+ var_ = json_type_traits<basic_json,T>::to_json(val).var_;
+ return *this;
+ }
+
+ basic_json& operator=(const char_type* s)
+ {
+ var_ = variant(s);
+ return *this;
+ }
+
+ bool operator!=(const basic_json& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ bool operator==(const basic_json& rhs) const
+ {
+ return var_ == rhs.var_;
+ }
+
+ size_t size() const JSONCONS_NOEXCEPT
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ return 0;
+ case json_type_tag::object_t:
+ return object_value().size();
+ case json_type_tag::array_t:
+ return array_value().size();
+ default:
+ return 0;
+ }
+ }
+
+ basic_json& operator[](size_t i)
+ {
+ return at(i);
+ }
+
+ const basic_json& operator[](size_t i) const
+ {
+ return at(i);
+ }
+
+ json_proxy<basic_json> operator[](const string_view_type& name)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return json_proxy<basic_json>(*this, key_storage_type(name.begin(),name.end(),char_allocator_type(object_value().get_allocator())));
+ break;
+ default:
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ break;
+ }
+ }
+
+ const basic_json& operator[](const string_view_type& name) const
+ {
+ return at(name);
+ }
+
+ template <class SAllocator>
+ void dump(std::basic_string<char_type,char_traits_type,SAllocator>& s) const
+ {
+ basic_json_serializer<char_type,detail::string_writer<char_type>> serializer(s);
+ dump(serializer);
+ }
+
+ template <class SAllocator>
+ void dump(std::basic_string<char_type,char_traits_type,SAllocator>& s,
+ const basic_serialization_options<char_type>& options) const
+ {
+ basic_json_serializer<char_type,detail::string_writer<char_type>> serializer(s, options);
+ dump(serializer);
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+ void dump_body(basic_json_output_handler<char_type>& handler) const
+ {
+ dump_fragment(handler);
+ }
+#endif
+ void dump_fragment(basic_json_output_handler<char_type>& handler) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ case json_type_tag::string_t:
+ handler.string_value(as_string_view());
+ break;
+ case json_type_tag::byte_string_t:
+ handler.byte_string_value(var_.byte_string_data_cast()->data(), var_.byte_string_data_cast()->length());
+ break;
+ case json_type_tag::double_t:
+ handler.double_value(var_.double_data_cast()->value(), number_format(var_.double_data_cast()->precision(), var_.double_data_cast()->decimal_places()));
+ break;
+ case json_type_tag::integer_t:
+ handler.integer_value(var_.integer_data_cast()->value());
+ break;
+ case json_type_tag::uinteger_t:
+ handler.uinteger_value(var_.uinteger_data_cast()->value());
+ break;
+ case json_type_tag::bool_t:
+ handler.bool_value(var_.bool_data_cast()->value());
+ break;
+ case json_type_tag::null_t:
+ handler.null_value();
+ break;
+ case json_type_tag::empty_object_t:
+ handler.begin_object(0);
+ handler.end_object();
+ break;
+ case json_type_tag::object_t:
+ {
+ handler.begin_object(size());
+ const object& o = object_value();
+ for (const_object_iterator it = o.begin(); it != o.end(); ++it)
+ {
+ handler.name(string_view_type((it->key()).data(),it->key().length()));
+ it->value().dump_fragment(handler);
+ }
+ handler.end_object();
+ }
+ break;
+ case json_type_tag::array_t:
+ {
+ handler.begin_array(size());
+ const array& o = array_value();
+ for (const_array_iterator it = o.begin(); it != o.end(); ++it)
+ {
+ it->dump_fragment(handler);
+ }
+ handler.end_array();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ void dump(basic_json_output_handler<char_type>& handler) const
+ {
+ handler.begin_json();
+ dump_fragment(handler);
+ handler.end_json();
+ }
+
+ void dump(std::basic_ostream<char_type>& os) const
+ {
+ basic_json_serializer<char_type> serializer(os);
+ dump(serializer);
+ }
+
+ void dump(std::basic_ostream<char_type>& os, bool pprint) const
+ {
+ basic_json_serializer<char_type> serializer(os, pprint);
+ dump(serializer);
+ }
+
+ void dump(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options) const
+ {
+ basic_json_serializer<char_type> serializer(os, options);
+ dump(serializer);
+ }
+
+ void dump(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options, bool pprint) const
+ {
+ basic_json_serializer<char_type> serializer(os, options, pprint);
+ dump(serializer);
+ }
+
+ string_type to_string(const char_allocator_type& allocator=char_allocator_type()) const JSONCONS_NOEXCEPT
+ {
+ string_type s(allocator);
+ basic_json_serializer<char_type,detail::string_writer<char_type>> serializer(s);
+ dump_fragment(serializer);
+ return s;
+ }
+
+ string_type to_string(const basic_serialization_options<char_type>& options,
+ const char_allocator_type& allocator=char_allocator_type()) const
+ {
+ string_type s(allocator);
+ basic_json_serializer<char_type,detail::string_writer<char_type>> serializer(s,options);
+ dump_fragment(serializer);
+ return s;
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+
+ void write_body(basic_json_output_handler<char_type>& handler) const
+ {
+ dump(handler);
+ }
+ void write(basic_json_output_handler<char_type>& handler) const
+ {
+ dump(handler);
+ }
+
+ void write(std::basic_ostream<char_type>& os) const
+ {
+ dump(os);
+ }
+
+ void write(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options) const
+ {
+ dump(os,options);
+ }
+
+ void write(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options, bool pprint) const
+ {
+ dump(os,options,pprint);
+ }
+
+ void to_stream(basic_json_output_handler<char_type>& handler) const
+ {
+ handler.begin_json();
+ dump_fragment(handler);
+ handler.end_json();
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os) const
+ {
+ basic_json_serializer<char_type> serializer(os);
+ to_stream(serializer);
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options) const
+ {
+ basic_json_serializer<char_type> serializer(os, options);
+ to_stream(serializer);
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os, const basic_serialization_options<char_type>& options, bool pprint) const
+ {
+ basic_json_serializer<char_type> serializer(os, options, pprint);
+ to_stream(serializer);
+ }
+#endif
+ bool is_null() const JSONCONS_NOEXCEPT
+ {
+ return var_.type_id() == json_type_tag::null_t;
+ }
+
+ bool has_key(const string_view_type& name) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::object_t:
+ {
+ const_object_iterator it = object_value().find(name);
+ return it != object_range().end();
+ }
+ break;
+ default:
+ return false;
+ }
+ }
+
+ size_t count(const string_view_type& name) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::object_t:
+ {
+ auto it = object_value().find(name);
+ if (it == object_range().end())
+ {
+ return 0;
+ }
+ size_t count = 0;
+ while (it != object_range().end()&& it->key() == name)
+ {
+ ++count;
+ ++it;
+ }
+ return count;
+ }
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ template<class T, class... Args>
+ bool is(Args&&... args) const
+ {
+ return json_type_traits<basic_json,T>::is(*this,std::forward<Args>(args)...);
+ }
+
+ bool is_string() const JSONCONS_NOEXCEPT
+ {
+ return (var_.type_id() == json_type_tag::string_t) || (var_.type_id() == json_type_tag::small_string_t);
+ }
+
+ bool is_byte_string() const JSONCONS_NOEXCEPT
+ {
+ return (var_.type_id() == json_type_tag::byte_string_t);
+ }
+
+ bool is_bool() const JSONCONS_NOEXCEPT
+ {
+ return var_.type_id() == json_type_tag::bool_t;
+ }
+
+ bool is_object() const JSONCONS_NOEXCEPT
+ {
+ return var_.type_id() == json_type_tag::object_t || var_.type_id() == json_type_tag::empty_object_t;
+ }
+
+ bool is_array() const JSONCONS_NOEXCEPT
+ {
+ return var_.type_id() == json_type_tag::array_t;
+ }
+
+ bool is_integer() const JSONCONS_NOEXCEPT
+ {
+ return var_.type_id() == json_type_tag::integer_t || (var_.type_id() == json_type_tag::uinteger_t&& (as_uinteger() <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)())));
+ }
+
+ bool is_uinteger() const JSONCONS_NOEXCEPT
+ {
+ return var_.type_id() == json_type_tag::uinteger_t || (var_.type_id() == json_type_tag::integer_t&& as_integer() >= 0);
+ }
+
+ bool is_double() const JSONCONS_NOEXCEPT
+ {
+ return var_.type_id() == json_type_tag::double_t;
+ }
+
+ bool is_number() const JSONCONS_NOEXCEPT
+ {
+ return var_.type_id() == json_type_tag::integer_t || var_.type_id() == json_type_tag::uinteger_t || var_.type_id() == json_type_tag::double_t;
+ }
+
+ bool empty() const JSONCONS_NOEXCEPT
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ return var_.small_string_data_cast()->length() == 0;
+ case json_type_tag::string_t:
+ return var_.string_data_cast()->length() == 0;
+ case json_type_tag::array_t:
+ return array_value().size() == 0;
+ case json_type_tag::empty_object_t:
+ return true;
+ case json_type_tag::object_t:
+ return object_value().size() == 0;
+ default:
+ return false;
+ }
+ }
+
+ size_t capacity() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ return array_value().capacity();
+ case json_type_tag::object_t:
+ return object_value().capacity();
+ default:
+ return 0;
+ }
+ }
+
+ template<class U=Allocator>
+ typename std::enable_if<is_stateless<U>::value,void>::type
+ create_object_implicitly()
+ {
+ var_ = variant(Allocator());
+ }
+
+ template<class U=Allocator>
+ typename std::enable_if<!is_stateless<U>::value,void>::type
+ create_object_implicitly() const
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Cannot create object implicitly - allocator is not default constructible."));
+ }
+
+ void reserve(size_t n)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ array_value().reserve(n);
+ break;
+ case json_type_tag::empty_object_t:
+ {
+ create_object_implicitly();
+ object_value().reserve(n);
+ }
+ break;
+ case json_type_tag::object_t:
+ {
+ object_value().reserve(n);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ void resize(size_t n)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ array_value().resize(n);
+ break;
+ default:
+ break;
+ }
+ }
+
+ template <class T>
+ void resize(size_t n, T val)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ array_value().resize(n, val);
+ break;
+ default:
+ break;
+ }
+ }
+
+ template<class T, class... Args>
+ T as(Args&&... args) const
+ {
+ return json_type_traits<basic_json,T>::as(*this,std::forward<Args>(args)...);
+ }
+
+ template<class T>
+ typename std::enable_if<std::is_same<string_type,T>::value,T>::type
+ as(const char_allocator_type& allocator) const
+ {
+ return json_type_traits<basic_json,T>::as(*this,allocator);
+ }
+
+ bool as_bool() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ case json_type_tag::string_t:
+ try
+ {
+ basic_json j = basic_json::parse(as_string_view().data(),as_string_view().length());
+ return j.as_bool();
+ }
+ catch (...)
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a bool"));
+ }
+ break;
+ case json_type_tag::bool_t:
+ return var_.bool_data_cast()->value();
+ case json_type_tag::double_t:
+ return var_.double_data_cast()->value() != 0.0;
+ case json_type_tag::integer_t:
+ return var_.integer_data_cast()->value() != 0;
+ case json_type_tag::uinteger_t:
+ return var_.uinteger_data_cast()->value() != 0;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a bool"));
+ }
+ }
+
+ int64_t as_integer() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ case json_type_tag::string_t:
+ try
+ {
+ basic_json j = basic_json::parse(as_string_view().data(),as_string_view().length());
+ return j.as<int64_t>();
+ }
+ catch (...)
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an integer"));
+ }
+ break;
+ case json_type_tag::double_t:
+ return static_cast<int64_t>(var_.double_data_cast()->value());
+ case json_type_tag::integer_t:
+ return static_cast<int64_t>(var_.integer_data_cast()->value());
+ case json_type_tag::uinteger_t:
+ return static_cast<int64_t>(var_.uinteger_data_cast()->value());
+ case json_type_tag::bool_t:
+ return var_.bool_data_cast()->value() ? 1 : 0;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an integer"));
+ }
+ }
+
+ uint64_t as_uinteger() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ case json_type_tag::string_t:
+ try
+ {
+ basic_json j = basic_json::parse(as_string_view().data(),as_string_view().length());
+ return j.as<uint64_t>();
+ }
+ catch (...)
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an unsigned integer"));
+ }
+ break;
+ case json_type_tag::double_t:
+ return static_cast<uint64_t>(var_.double_data_cast()->value());
+ case json_type_tag::integer_t:
+ return static_cast<uint64_t>(var_.integer_data_cast()->value());
+ case json_type_tag::uinteger_t:
+ return static_cast<uint64_t>(var_.uinteger_data_cast()->value());
+ case json_type_tag::bool_t:
+ return var_.bool_data_cast()->value() ? 1 : 0;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an unsigned integer"));
+ }
+ }
+
+ size_t precision() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::double_t:
+ return var_.double_data_cast()->precision();
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a double"));
+ }
+ }
+
+ size_t decimal_places() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::double_t:
+ return var_.double_data_cast()->decimal_places();
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a double"));
+ }
+ }
+
+ double as_double() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ case json_type_tag::string_t:
+ try
+ {
+ basic_json j = basic_json::parse(as_string_view().data(),as_string_view().length());
+ return j.as<double>();
+ }
+ catch (...)
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a double"));
+ }
+ break;
+ case json_type_tag::double_t:
+ return var_.double_data_cast()->value();
+ case json_type_tag::integer_t:
+ return static_cast<double>(var_.integer_data_cast()->value());
+ case json_type_tag::uinteger_t:
+ return static_cast<double>(var_.uinteger_data_cast()->value());
+ //case json_type_tag::null_t:
+ // return std::numeric_limits<double>::quiet_NaN();
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a double"));
+ }
+ }
+
+ string_view_type as_string_view() const
+ {
+ return var_.as_string_view();
+ }
+
+ byte_string_view as_byte_string_view() const
+ {
+ return var_.as_byte_string_view();
+ }
+
+ string_type as_string() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ case json_type_tag::string_t:
+ return string_type(as_string_view().data(),as_string_view().length());
+ default:
+ return to_string();
+ }
+ }
+
+ template <class SAllocator>
+ string_type as_string(const SAllocator& allocator) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ case json_type_tag::string_t:
+ return string_type(as_string_view().data(),as_string_view().length(),allocator);
+ default:
+ return to_string(allocator);
+ }
+ }
+
+ string_type as_string(const basic_serialization_options<char_type>& options) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ case json_type_tag::string_t:
+ return string_type(as_string_view().data(),as_string_view().length());
+ default:
+ return to_string(options);
+ }
+ }
+
+ template <class SAllocator>
+ string_type as_string(const basic_serialization_options<char_type>& options,
+ const SAllocator& allocator) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ case json_type_tag::string_t:
+ return string_type(as_string_view().data(),as_string_view().length(),allocator);
+ default:
+ return to_string(options,allocator);
+ }
+ }
+
+ const char_type* as_cstring() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::small_string_t:
+ return var_.small_string_data_cast()->c_str();
+ case json_type_tag::string_t:
+ return var_.string_data_cast()->c_str();
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a cstring"));
+ }
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+
+ size_t double_precision() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::double_t:
+ return var_.double_data_cast()->precision();
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a double"));
+ }
+ }
+#endif
+
+ basic_json& at(const string_view_type& name)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ JSONCONS_THROW(key_not_found(name.data(),name.length()));
+ case json_type_tag::object_t:
+ {
+ auto it = object_value().find(name);
+ if (it == object_range().end())
+ {
+ JSONCONS_THROW(key_not_found(name.data(),name.length()));
+ }
+ return it->value();
+ }
+ break;
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ basic_json& evaluate()
+ {
+ return *this;
+ }
+
+ basic_json& evaluate_with_default()
+ {
+ return *this;
+ }
+
+ const basic_json& evaluate() const
+ {
+ return *this;
+ }
+ basic_json& evaluate(const string_view_type& name)
+ {
+ return at(name);
+ }
+
+ const basic_json& evaluate(const string_view_type& name) const
+ {
+ return at(name);
+ }
+
+ const basic_json& at(const string_view_type& name) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ JSONCONS_THROW(key_not_found(name.data(),name.length()));
+ case json_type_tag::object_t:
+ {
+ auto it = object_value().find(name);
+ if (it == object_range().end())
+ {
+ JSONCONS_THROW(key_not_found(name.data(),name.length()));
+ }
+ return it->value();
+ }
+ break;
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ basic_json& at(size_t i)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ if (i >= array_value().size())
+ {
+ JSONCONS_THROW(json_exception_impl<std::out_of_range>("Invalid array subscript"));
+ }
+ return array_value().operator[](i);
+ case json_type_tag::object_t:
+ return object_value().at(i);
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Index on non-array value not supported"));
+ }
+ }
+
+ const basic_json& at(size_t i) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ if (i >= array_value().size())
+ {
+ JSONCONS_THROW(json_exception_impl<std::out_of_range>("Invalid array subscript"));
+ }
+ return array_value().operator[](i);
+ case json_type_tag::object_t:
+ return object_value().at(i);
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Index on non-array value not supported"));
+ }
+ }
+
+ object_iterator find(const string_view_type& name)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ return object_range().end();
+ case json_type_tag::object_t:
+ return object_value().find(name);
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ const_object_iterator find(const string_view_type& name) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ return object_range().end();
+ case json_type_tag::object_t:
+ return object_value().find(name);
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ template<class T>
+ basic_json get(const string_view_type& name, T&& default_val) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ {
+ return basic_json(std::forward<T>(default_val));
+ }
+ case json_type_tag::object_t:
+ {
+ const_object_iterator it = object_value().find(name);
+ if (it != object_range().end())
+ {
+ return it->value();
+ }
+ else
+ {
+ return basic_json(std::forward<T>(default_val));
+ }
+ }
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ template<class T>
+ T get_with_default(const string_view_type& name, const T& default_val) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ {
+ return default_val;
+ }
+ case json_type_tag::object_t:
+ {
+ const_object_iterator it = object_value().find(name);
+ if (it != object_range().end())
+ {
+ return it->value().template as<T>();
+ }
+ else
+ {
+ return default_val;
+ }
+ }
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ const CharT* get_with_default(const string_view_type& name, const CharT* default_val) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ {
+ return default_val;
+ }
+ case json_type_tag::object_t:
+ {
+ const_object_iterator it = object_value().find(name);
+ if (it != object_range().end())
+ {
+ return it->value().as_cstring();
+ }
+ else
+ {
+ return default_val;
+ }
+ }
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ // Modifiers
+
+ void shrink_to_fit()
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ array_value().shrink_to_fit();
+ break;
+ case json_type_tag::object_t:
+ object_value().shrink_to_fit();
+ break;
+ default:
+ break;
+ }
+ }
+
+ void clear()
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ array_value().clear();
+ break;
+ case json_type_tag::object_t:
+ object_value().clear();
+ break;
+ default:
+ break;
+ }
+ }
+
+ void erase(const_object_iterator pos)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ break;
+ case json_type_tag::object_t:
+ object_value().erase(pos);
+ break;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an object"));
+ break;
+ }
+ }
+
+ void erase(const_object_iterator first, const_object_iterator last)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ break;
+ case json_type_tag::object_t:
+ object_value().erase(first, last);
+ break;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an object"));
+ break;
+ }
+ }
+
+ void erase(const_array_iterator pos)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ array_value().erase(pos);
+ break;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an array"));
+ break;
+ }
+ }
+
+ void erase(const_array_iterator first, const_array_iterator last)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ array_value().erase(first, last);
+ break;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an array"));
+ break;
+ }
+ }
+
+ // Removes all elements from an array value whose index is between from_index, inclusive, and to_index, exclusive.
+
+ void erase(const string_view_type& name)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ break;
+ case json_type_tag::object_t:
+ object_value().erase(name);
+ break;
+ default:
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ break;
+ }
+ }
+
+ template <class T>
+ std::pair<object_iterator,bool> set(const string_view_type& name, T&& val)
+ {
+ return insert_or_assign(name, std::forward<T>(val));
+ }
+
+ template <class T>
+ std::pair<object_iterator,bool> insert_or_assign(const string_view_type& name, T&& val)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().insert_or_assign(name, std::forward<T>(val));
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ template <class ... Args>
+ std::pair<object_iterator,bool> try_emplace(const string_view_type& name, Args&&... args)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().try_emplace(name, std::forward<Args>(args)...);
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ template <class T>
+ void set_(key_storage_type&& name, T&& val)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ object_value().set_(std::forward<key_storage_type>(name), std::forward<T>(val));
+ break;
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ // merge
+
+ void merge(const basic_json& source)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().merge(source.object_value());
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to merge a value that is not an object"));
+ }
+ }
+ }
+
+ void merge(basic_json&& source)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().merge(std::move(source.object_value()));
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to merge a value that is not an object"));
+ }
+ }
+ }
+
+ void merge(object_iterator hint, const basic_json& source)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().merge(hint, source.object_value());
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to merge a value that is not an object"));
+ }
+ }
+ }
+
+ void merge(object_iterator hint, basic_json&& source)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().merge(hint, std::move(source.object_value()));
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to merge a value that is not an object"));
+ }
+ }
+ }
+
+ // merge_or_update
+
+ void merge_or_update(const basic_json& source)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().merge_or_update(source.object_value());
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to merge or update a value that is not an object"));
+ }
+ }
+ }
+
+ void merge_or_update(basic_json&& source)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().merge_or_update(std::move(source.object_value()));
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to merge or update a value that is not an object"));
+ }
+ }
+ }
+
+ void merge_or_update(object_iterator hint, const basic_json& source)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().merge_or_update(hint, source.object_value());
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to merge or update a value that is not an object"));
+ }
+ }
+ }
+
+ void merge_or_update(object_iterator hint, basic_json&& source)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().merge_or_update(hint, std::move(source.object_value()));
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to merge or update a value that is not an object"));
+ }
+ }
+ }
+
+ // set
+
+ template <class T>
+ object_iterator set(object_iterator hint, const string_view_type& name, T&& val)
+ {
+ return insert_or_assign(hint, name, std::forward<T>(val));
+ }
+
+ template <class T>
+ object_iterator insert_or_assign(object_iterator hint, const string_view_type& name, T&& val)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().insert_or_assign(hint, name, std::forward<T>(val));
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ template <class ... Args>
+ object_iterator try_emplace(object_iterator hint, const string_view_type& name, Args&&... args)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().try_emplace(hint, name, std::forward<Args>(args)...);
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ template <class T>
+ object_iterator set_(object_iterator hint, key_storage_type&& name, T&& val)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return object_value().set_(hint, std::forward<key_storage_type>(name), std::forward<T>(val));
+ break;
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ template <class T>
+ void add(T&& val)
+ {
+ push_back(std::forward<T>(val));
+ }
+
+ template <class T>
+ void push_back(T&& val)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ array_value().push_back(std::forward<T>(val));
+ break;
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to insert into a value that is not an array"));
+ }
+ }
+ }
+
+ template <class T>
+ array_iterator add(const_array_iterator pos, T&& val)
+ {
+ return insert(pos, std::forward<T>(val));
+ }
+
+ template <class T>
+ array_iterator insert(const_array_iterator pos, T&& val)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ return array_value().insert(pos, std::forward<T>(val));
+ break;
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to insert into a value that is not an array"));
+ }
+ }
+ }
+
+ template <class InputIt>
+ array_iterator insert(const_array_iterator pos, InputIt first, InputIt last)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ return array_value().insert(pos, first, last);
+ break;
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to insert into a value that is not an array"));
+ }
+ }
+ }
+
+ template <class... Args>
+ array_iterator emplace(const_array_iterator pos, Args&&... args)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ return array_value().emplace(pos, std::forward<Args>(args)...);
+ break;
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to insert into a value that is not an array"));
+ }
+ }
+ }
+
+ template <class... Args>
+ basic_json& emplace_back(Args&&... args)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ return array_value().emplace_back(std::forward<Args>(args)...);
+ default:
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempting to insert into a value that is not an array"));
+ }
+ }
+ }
+
+ json_type_tag type_id() const
+ {
+ return var_.type_id();
+ }
+
+ void swap(basic_json& b)
+ {
+ var_.swap(b.var_);
+ }
+
+ friend void swap(basic_json& a, basic_json& b)
+ {
+ a.swap(b);
+ }
+
+ static basic_json make_string(const string_view_type& s)
+ {
+ return basic_json(variant(s.data(),s.length()));
+ }
+
+ static basic_json make_string(const char_type* rhs, size_t length)
+ {
+ return basic_json(variant(rhs,length));
+ }
+
+ static basic_json make_string(const string_view_type& s, allocator_type allocator)
+ {
+ return basic_json(variant(s.data(),s.length(),allocator));
+ }
+
+ static basic_json from_integer(int64_t val)
+ {
+ return basic_json(variant(val));
+ }
+
+ static basic_json from_integer(int64_t val, allocator_type)
+ {
+ return basic_json(variant(val));
+ }
+
+ static basic_json from_uinteger(uint64_t val)
+ {
+ return basic_json(variant(val));
+ }
+
+ static basic_json from_uinteger(uint64_t val, allocator_type)
+ {
+ return basic_json(variant(val));
+ }
+
+ static basic_json from_floating_point(double val)
+ {
+ return basic_json(variant(val));
+ }
+
+ static basic_json from_floating_point(double val, allocator_type)
+ {
+ return basic_json(variant(val));
+ }
+
+ static basic_json from_bool(bool val)
+ {
+ return basic_json(variant(val));
+ }
+
+ static basic_json make_object(const object& o)
+ {
+ return basic_json(variant(o));
+ }
+
+ static basic_json make_object(const object& o, allocator_type allocator)
+ {
+ return basic_json(variant(o,allocator));
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+
+ static basic_json parse_file(const std::basic_string<char_type,char_traits_type>& filename)
+ {
+ parse_error_handler_type err_handler;
+ return parse_file(filename,err_handler);
+ }
+
+ static basic_json parse_file(const std::basic_string<char_type,char_traits_type>& filename,
+ parse_error_handler& err_handler)
+ {
+ std::basic_ifstream<CharT> is(filename);
+ return parse(is,err_handler);
+ }
+
+ static basic_json parse_stream(std::basic_istream<char_type>& is)
+ {
+ return parse(is);
+ }
+ static basic_json parse_stream(std::basic_istream<char_type>& is, parse_error_handler& err_handler)
+ {
+ return parse(is,err_handler);
+ }
+
+ static basic_json parse_string(const string_type& s)
+ {
+ return parse(s);
+ }
+
+ static basic_json parse_string(const string_type& s, parse_error_handler& err_handler)
+ {
+ return parse(s,err_handler);
+ }
+
+ void resize_array(size_t n)
+ {
+ resize(n);
+ }
+
+ template <class T>
+ void resize_array(size_t n, T val)
+ {
+ resize(n,val);
+ }
+
+ object_iterator begin_members()
+ {
+ return object_range().begin();
+ }
+
+ const_object_iterator begin_members() const
+ {
+ return object_range().begin();
+ }
+
+ object_iterator end_members()
+ {
+ return object_range().end();
+ }
+
+ const_object_iterator end_members() const
+ {
+ return object_range().end();
+ }
+
+ array_iterator begin_elements()
+ {
+ return array_range().begin();
+ }
+
+ const_array_iterator begin_elements() const
+ {
+ return array_range().begin();
+ }
+
+ array_iterator end_elements()
+ {
+ return array_range().end();
+ }
+
+ const_array_iterator end_elements() const
+ {
+ return array_range().end();
+ }
+
+ const basic_json& get(const string_view_type& name) const
+ {
+ static const basic_json a_null = null_type();
+
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ return a_null;
+ case json_type_tag::object_t:
+ {
+ const_object_iterator it = object_value().find(name);
+ return it != object_range().end() ? it->value() : a_null;
+ }
+ default:
+ {
+ JSONCONS_THROW(not_an_object(name.data(),name.length()));
+ }
+ }
+ }
+
+ bool is_longlong() const JSONCONS_NOEXCEPT
+ {
+ return var_.type_id() == json_type_tag::integer_t;
+ }
+
+ bool is_ulonglong() const JSONCONS_NOEXCEPT
+ {
+ return var_.type_id() == json_type_tag::uinteger_t;
+ }
+
+ long long as_longlong() const
+ {
+ return as_integer();
+ }
+
+ unsigned long long as_ulonglong() const
+ {
+ return as_uinteger();
+ }
+
+ int as_int() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::double_t:
+ return static_cast<int>(var_.double_data_cast()->value());
+ case json_type_tag::integer_t:
+ return static_cast<int>(var_.integer_data_cast()->value());
+ case json_type_tag::uinteger_t:
+ return static_cast<int>(var_.uinteger_data_cast()->value());
+ case json_type_tag::bool_t:
+ return var_.bool_data_cast()->value() ? 1 : 0;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an int"));
+ }
+ }
+
+ unsigned int as_uint() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::double_t:
+ return static_cast<unsigned int>(var_.double_data_cast()->value());
+ case json_type_tag::integer_t:
+ return static_cast<unsigned int>(var_.integer_data_cast()->value());
+ case json_type_tag::uinteger_t:
+ return static_cast<unsigned int>(var_.uinteger_data_cast()->value());
+ case json_type_tag::bool_t:
+ return var_.bool_data_cast()->value() ? 1 : 0;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an unsigned int"));
+ }
+ }
+
+ long as_long() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::double_t:
+ return static_cast<long>(var_.double_data_cast()->value());
+ case json_type_tag::integer_t:
+ return static_cast<long>(var_.integer_data_cast()->value());
+ case json_type_tag::uinteger_t:
+ return static_cast<long>(var_.uinteger_data_cast()->value());
+ case json_type_tag::bool_t:
+ return var_.bool_data_cast()->value() ? 1 : 0;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not a long"));
+ }
+ }
+
+ unsigned long as_ulong() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::double_t:
+ return static_cast<unsigned long>(var_.double_data_cast()->value());
+ case json_type_tag::integer_t:
+ return static_cast<unsigned long>(var_.integer_data_cast()->value());
+ case json_type_tag::uinteger_t:
+ return static_cast<unsigned long>(var_.uinteger_data_cast()->value());
+ case json_type_tag::bool_t:
+ return var_.bool_data_cast()->value() ? 1 : 0;
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an unsigned long"));
+ }
+ }
+
+ bool has_member(const key_storage_type& name) const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::object_t:
+ {
+ const_object_iterator it = object_value().find(name);
+ return it != object_range().end();
+ }
+ break;
+ default:
+ return false;
+ }
+ }
+
+ void remove_range(size_t from_index, size_t to_index)
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ array_value().remove_range(from_index, to_index);
+ break;
+ default:
+ break;
+ }
+ }
+ // Removes all elements from an array value whose index is between from_index, inclusive, and to_index, exclusive.
+
+ void remove(const string_view_type& name)
+ {
+ erase(name);
+ }
+ void remove_member(const string_view_type& name)
+ {
+ erase(name);
+ }
+ // Removes a member from an object value
+
+ bool is_empty() const JSONCONS_NOEXCEPT
+ {
+ return empty();
+ }
+ bool is_numeric() const JSONCONS_NOEXCEPT
+ {
+ return is_number();
+ }
+
+ template<int size>
+ static typename std::enable_if<size==1,basic_json>::type make_multi_array()
+ {
+ return make_array();
+ }
+ template<size_t size>
+ static typename std::enable_if<size==1,basic_json>::type make_multi_array(size_t n)
+ {
+ return make_array(n);
+ }
+ template<size_t size,typename T>
+ static typename std::enable_if<size==1,basic_json>::type make_multi_array(size_t n, T val)
+ {
+ return make_array(n,val);
+ }
+ template<size_t size>
+ static typename std::enable_if<size==2,basic_json>::type make_multi_array(size_t m, size_t n)
+ {
+ return make_array<2>(m, n);
+ }
+ template<size_t size,typename T>
+ static typename std::enable_if<size==2,basic_json>::type make_multi_array(size_t m, size_t n, T val)
+ {
+ return make_array<2>(m, n, val);
+ }
+ template<size_t size>
+ static typename std::enable_if<size==3,basic_json>::type make_multi_array(size_t m, size_t n, size_t k)
+ {
+ return make_array<3>(m, n, k);
+ }
+ template<size_t size,typename T>
+ static typename std::enable_if<size==3,basic_json>::type make_multi_array(size_t m, size_t n, size_t k, T val)
+ {
+ return make_array<3>(m, n, k, val);
+ }
+ range<object_iterator> members()
+ {
+ return object_range();
+ }
+
+ range<const_object_iterator> members() const
+ {
+ return object_range();
+ }
+
+ range<array_iterator> elements()
+ {
+ return array_range();
+ }
+
+ range<const_array_iterator> elements() const
+ {
+ return array_range();
+ }
+#endif
+
+ range<object_iterator> object_range()
+ {
+ static basic_json empty_object = object();
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ return range<object_iterator>(empty_object.object_range().begin(), empty_object.object_range().end());
+ case json_type_tag::object_t:
+ return range<object_iterator>(object_value().begin(),object_value().end());
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an object"));
+ }
+ }
+
+ range<const_object_iterator> object_range() const
+ {
+ static const basic_json empty_object = object();
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ return range<const_object_iterator>(empty_object.object_range().begin(), empty_object.object_range().end());
+ case json_type_tag::object_t:
+ return range<const_object_iterator>(object_value().begin(),object_value().end());
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an object"));
+ }
+ }
+
+ range<array_iterator> array_range()
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ return range<array_iterator>(array_value().begin(),array_value().end());
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an array"));
+ }
+ }
+
+ range<const_array_iterator> array_range() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ return range<const_array_iterator>(array_value().begin(),array_value().end());
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Not an array"));
+ }
+ }
+
+ array& array_value()
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ return var_.array_data_cast()->value();
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Bad array cast"));
+ break;
+ }
+ }
+
+ const array& array_value() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::array_t:
+ return var_.array_data_cast()->value();
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Bad array cast"));
+ break;
+ }
+ }
+
+ object& object_value()
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ create_object_implicitly();
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return var_.object_data_cast()->value();
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Bad object cast"));
+ break;
+ }
+ }
+
+ const object& object_value() const
+ {
+ switch (var_.type_id())
+ {
+ case json_type_tag::empty_object_t:
+ const_cast<basic_json*>(this)->create_object_implicitly(); // HERE
+ // FALLTHRU
+ case json_type_tag::object_t:
+ return var_.object_data_cast()->value();
+ default:
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Bad object cast"));
+ break;
+ }
+ }
+
+private:
+
+ friend std::basic_ostream<char_type>& operator<<(std::basic_ostream<char_type>& os, const basic_json& o)
+ {
+ o.dump(os);
+ return os;
+ }
+
+ friend std::basic_istream<char_type>& operator<<(std::basic_istream<char_type>& is, basic_json& o)
+ {
+ json_decoder<basic_json> handler;
+ basic_json_reader<char_type> reader(is, handler);
+ reader.read_next();
+ reader.check_done();
+ if (!handler.is_valid())
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Failed to parse json stream"));
+ }
+ o = handler.get_result();
+ return is;
+ }
+};
+
+template <class Json>
+void swap(typename Json::key_value_pair_type& a, typename Json::key_value_pair_type& b)
+{
+ a.swap(b);
+}
+
+template<class CharT,class ImplementationPolicy,class Allocator>
+basic_json<CharT,ImplementationPolicy,Allocator> basic_json<CharT,ImplementationPolicy,Allocator>::parse(std::basic_istream<char_type>& is)
+{
+ parse_error_handler_type err_handler;
+ return parse(is,err_handler);
+}
+
+template<class CharT,class ImplementationPolicy,class Allocator>
+basic_json<CharT,ImplementationPolicy,Allocator> basic_json<CharT,ImplementationPolicy,Allocator>::parse(std::basic_istream<char_type>& is,
+ parse_error_handler& err_handler)
+{
+ json_decoder<basic_json<CharT,ImplementationPolicy,Allocator>> handler;
+ basic_json_reader<char_type> reader(is, handler, err_handler);
+ reader.read_next();
+ reader.check_done();
+ if (!handler.is_valid())
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Failed to parse json stream"));
+ }
+ return handler.get_result();
+}
+
+template <class Json>
+std::basic_istream<typename Json::char_type>& operator>>(std::basic_istream<typename Json::char_type>& is, Json& o)
+{
+ json_decoder<Json> handler;
+ basic_json_reader<typename Json::char_type> reader(is, handler);
+ reader.read_next();
+ reader.check_done();
+ if (!handler.is_valid())
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Failed to parse json stream"));
+ }
+ o = handler.get_result();
+ return is;
+}
+
+template<class Json>
+class json_printable
+{
+public:
+ typedef typename Json::char_type char_type;
+
+ json_printable(const Json& o,
+ bool is_pretty_print)
+ : o_(&o), is_pretty_print_(is_pretty_print)
+ {
+ }
+
+ json_printable(const Json& o,
+ bool is_pretty_print,
+ const basic_serialization_options<char_type>& options)
+ : o_(&o), is_pretty_print_(is_pretty_print), options_(options)
+ {
+ ;
+ }
+
+ void dump(std::basic_ostream<char_type>& os) const
+ {
+ o_->dump(os, options_, is_pretty_print_);
+ }
+
+ friend std::basic_ostream<char_type>& operator<<(std::basic_ostream<char_type>& os, const json_printable<Json>& o)
+ {
+ o.dump(os);
+ return os;
+ }
+
+ const Json *o_;
+ bool is_pretty_print_;
+ basic_serialization_options<char_type> options_;
+private:
+ json_printable();
+};
+
+template<class Json>
+json_printable<Json> print(const Json& val)
+{
+ return json_printable<Json>(val,false);
+}
+
+template<class Json>
+json_printable<Json> print(const Json& val,
+ const basic_serialization_options<typename Json::char_type>& options)
+{
+ return json_printable<Json>(val, false, options);
+}
+
+template<class Json>
+json_printable<Json> pretty_print(const Json& val)
+{
+ return json_printable<Json>(val,true);
+}
+
+template<class Json>
+json_printable<Json> pretty_print(const Json& val,
+ const basic_serialization_options<typename Json::char_type>& options)
+{
+ return json_printable<Json>(val, true, options);
+}
+
+typedef basic_json<char,sorted_policy,std::allocator<char>> json;
+typedef basic_json<wchar_t,sorted_policy,std::allocator<wchar_t>> wjson;
+typedef basic_json<char, preserve_order_policy, std::allocator<char>> ojson;
+typedef basic_json<wchar_t, preserve_order_policy, std::allocator<wchar_t>> wojson;
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+typedef basic_json<wchar_t, preserve_order_policy, std::allocator<wchar_t>> owjson;
+typedef json_decoder<json> json_deserializer;
+typedef json_decoder<wjson> wjson_deserializer;
+typedef json_decoder<ojson> ojson_deserializer;
+typedef json_decoder<wojson> wojson_deserializer;
+#endif
+
+#if defined(JSONCONS_HAS_USER_DEFINED_LITERALS)
+namespace literals {
+
+inline
+jsoncons::json operator "" _json(const char* s, std::size_t n)
+{
+ return jsoncons::json::parse(s, n);
+}
+
+inline
+jsoncons::wjson operator "" _json(const wchar_t* s, std::size_t n)
+{
+ return jsoncons::wjson::parse(s, n);
+}
+
+inline
+jsoncons::ojson operator "" _ojson(const char* s, std::size_t n)
+{
+ return jsoncons::ojson::parse(s, n);
+}
+
+inline
+jsoncons::wojson operator "" _ojson(const wchar_t* s, std::size_t n)
+{
+ return jsoncons::wojson::parse(s, n);
+}
+
+}
+#endif
+
+}
+
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_decoder.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_decoder.hpp
new file mode 100644
index 00000000..9ca5bd4c
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_decoder.hpp
@@ -0,0 +1,310 @@
+// Copyright 2013-2016 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_DECODER_HPP
+#define JSONCONS_JSON_DECODER_HPP
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <memory>
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/json_input_handler.hpp>
+
+namespace jsoncons {
+
+template <class Json,class Allocator=std::allocator<typename Json::char_type>>
+class json_decoder final : public basic_json_input_handler<typename Json::char_type>
+{
+public:
+ typedef typename Json::char_type char_type;
+ using typename basic_json_input_handler<char_type>::string_view_type;
+
+ typedef typename Json::key_value_pair_type key_value_pair_type;
+ typedef typename Json::key_storage_type key_storage_type;
+ typedef typename Json::string_type string_type;
+ typedef typename Json::array array;
+ typedef typename Json::object object;
+ typedef typename Json::allocator_type json_allocator_type;
+ typedef typename string_type::allocator_type json_string_allocator;
+ typedef typename array::allocator_type json_array_allocator;
+ typedef typename object::allocator_type json_object_allocator;
+
+ json_string_allocator string_allocator_;
+ json_object_allocator object_allocator_;
+ json_array_allocator array_allocator_;
+
+ Json result_;
+
+ struct stack_item
+ {
+ stack_item(key_storage_type&& name)
+ : name_(std::forward<key_storage_type>(name))
+ {
+ }
+ stack_item(Json&& value)
+ : value_(std::forward<Json>(value))
+ {
+ }
+
+ stack_item() = default;
+ stack_item(const stack_item&) = default;
+ stack_item(stack_item&&) = default;
+ stack_item& operator=(const stack_item&) = default;
+ stack_item& operator=(stack_item&&) = default;
+
+ key_storage_type name_;
+ Json value_;
+ };
+
+ struct structure_offset
+ {
+ size_t offset_;
+ bool is_object_;
+ };
+
+ typedef Allocator allocator_type;
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<stack_item> stack_item_allocator_type;
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<structure_offset> size_t_allocator_type;
+
+
+ std::vector<stack_item,stack_item_allocator_type> stack_;
+ std::vector<structure_offset,size_t_allocator_type> stack_offsets_;
+ bool is_valid_;
+
+public:
+ json_decoder(const json_allocator_type& jallocator = json_allocator_type())
+ : string_allocator_(jallocator),
+ object_allocator_(jallocator),
+ array_allocator_(jallocator),
+ is_valid_(false)
+
+ {
+ stack_offsets_.reserve(100);
+ stack_.reserve(1000);
+ }
+
+ bool is_valid() const
+ {
+ return is_valid_;
+ }
+
+ Json get_result()
+ {
+ is_valid_ = false;
+ return std::move(result_);
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+ Json& root()
+ {
+ return result_;
+ }
+#endif
+
+private:
+
+ void push_object()
+ {
+ if (stack_offsets_.back().is_object_)
+ {
+ stack_.back().value_ = Json(object(object_allocator_));
+ }
+ else
+ {
+ stack_.push_back(Json(object(object_allocator_)));
+ }
+ stack_offsets_.push_back({stack_.size()-1,true});
+ }
+
+ void pop_object()
+ {
+ stack_.erase(stack_.begin()+stack_offsets_.back().offset_+1, stack_.end());
+ stack_offsets_.pop_back();
+ }
+
+ void push_array()
+ {
+ if (stack_offsets_.back().is_object_)
+ {
+ stack_.back().value_ = Json(array(array_allocator_));
+ }
+ else
+ {
+ stack_.push_back(Json(array(array_allocator_)));
+ }
+ stack_offsets_.push_back({stack_.size()-1,false});
+ }
+
+ void pop_array()
+ {
+ stack_.erase(stack_.begin()+stack_offsets_.back().offset_+1, stack_.end());
+ stack_offsets_.pop_back();
+ }
+
+ void do_begin_json() override
+ {
+ stack_offsets_.clear();
+ stack_.clear();
+ stack_offsets_.push_back({0,false});
+ is_valid_ = false;
+ }
+
+ void do_end_json() override
+ {
+ if (stack_.size() == 1)
+ {
+ result_.swap(stack_.front().value_);
+ stack_.pop_back();
+ is_valid_ = true;
+ }
+ }
+
+ void do_begin_object(const parsing_context&) override
+ {
+ push_object();
+ }
+
+ void do_end_object(const parsing_context&) override
+ {
+ end_structure();
+ pop_object();
+ }
+
+ void do_begin_array(const parsing_context&) override
+ {
+ push_array();
+ }
+
+ void do_end_array(const parsing_context&) override
+ {
+ end_structure();
+ pop_array();
+ }
+
+ void end_structure()
+ {
+ JSONCONS_ASSERT(stack_offsets_.size() > 0);
+ const size_t structure_index = stack_offsets_.back().offset_;
+ JSONCONS_ASSERT(stack_.size() > structure_index);
+ const size_t count = stack_.size() - (structure_index + 1);
+
+ auto first = stack_.begin() + (structure_index+1);
+ auto last = first + count;
+ if (stack_offsets_.back().is_object_)
+ {
+ stack_[structure_index].value_.object_value().insert(
+ std::make_move_iterator(first),
+ std::make_move_iterator(last),
+ [](stack_item&& val){return key_value_pair_type(std::move(val.name_),std::move(val.value_));});
+ }
+ else
+ {
+ auto& j = stack_[structure_index].value_;
+ j.reserve(count);
+ while (first != last)
+ {
+ j.push_back(std::move(first->value_));
+ ++first;
+ }
+ }
+ }
+
+ void do_name(const string_view_type& name, const parsing_context&) override
+ {
+ stack_.push_back(key_storage_type(name.begin(),name.end(),string_allocator_));
+ }
+
+ void do_string_value(const string_view_type& val, const parsing_context&) override
+ {
+ if (stack_offsets_.back().is_object_)
+ {
+ stack_.back().value_ = Json(val.data(),val.length(),string_allocator_);
+ }
+ else
+ {
+ stack_.push_back(Json(val.data(),val.length(),string_allocator_));
+ }
+ }
+
+ void do_byte_string_value(const uint8_t* data, size_t length, const parsing_context&) override
+ {
+ if (stack_offsets_.back().is_object_)
+ {
+ stack_.back().value_ = Json(data,length,string_allocator_);
+ }
+ else
+ {
+ stack_.push_back(Json(data,length,string_allocator_));
+ }
+ }
+
+ void do_integer_value(int64_t value, const parsing_context&) override
+ {
+ if (stack_offsets_.back().is_object_)
+ {
+ stack_.back().value_ = value;
+ }
+ else
+ {
+ stack_.push_back(Json(value));
+ }
+ }
+
+ void do_uinteger_value(uint64_t value, const parsing_context&) override
+ {
+ if (stack_offsets_.back().is_object_)
+ {
+ stack_.back().value_ = value;
+ }
+ else
+ {
+ stack_.push_back(Json(value));
+ }
+ }
+
+ void do_double_value(double value, const number_format& fmt, const parsing_context&) override
+ {
+ if (stack_offsets_.back().is_object_)
+ {
+ stack_.back().value_ = Json(value,fmt);
+ }
+ else
+ {
+ stack_.push_back(Json(value,fmt));
+ }
+ }
+
+ void do_bool_value(bool value, const parsing_context&) override
+ {
+ if (stack_offsets_.back().is_object_)
+ {
+ stack_.back().value_ = value;
+ }
+ else
+ {
+ stack_.push_back(Json(value));
+ }
+ }
+
+ void do_null_value(const parsing_context&) override
+ {
+ if (stack_offsets_.back().is_object_)
+ {
+ stack_.back().value_ = Json::null();
+ }
+ else
+ {
+ stack_.push_back(Json(Json::null()));
+ }
+ }
+};
+
+}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_deserializer.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_deserializer.hpp
new file mode 100644
index 00000000..05b44a40
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_deserializer.hpp
@@ -0,0 +1,12 @@
+// Copyright 2013-2016 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_DESERIALIZER_HPP
+#define JSONCONS_JSON_DESERIALIZER_HPP
+
+#include <jsoncons/json_decoder.hpp>
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_error_category.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_error_category.hpp
new file mode 100644
index 00000000..c09b847a
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_error_category.hpp
@@ -0,0 +1,148 @@
+/// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_ERROR_CATEGORY_HPP
+#define JSONCONS_JSON_ERROR_CATEGORY_HPP
+
+#include <system_error>
+#include <jsoncons/jsoncons_config.hpp>
+
+namespace jsoncons {
+
+ enum class json_parser_errc
+ {
+ ok = 0,
+ unexpected_eof = 1,
+ source_error,
+ invalid_json_text,
+ extra_character,
+ max_depth_exceeded,
+ single_quote,
+ illegal_character_in_string,
+ extra_comma,
+ expected_name,
+ expected_value,
+ invalid_value,
+ expected_colon,
+ illegal_control_character,
+ illegal_escaped_character,
+ expected_codepoint_surrogate_pair,
+ invalid_hex_escape_sequence,
+ invalid_unicode_escape_sequence,
+ leading_zero,
+ invalid_number,
+ expected_comma_or_right_brace,
+ expected_comma_or_right_bracket,
+ unexpected_right_bracket,
+ unexpected_right_brace,
+ illegal_comment,
+ expected_continuation_byte,
+ over_long_utf8_sequence,
+ illegal_codepoint,
+ illegal_surrogate_value,
+ unpaired_high_surrogate
+ };
+
+class json_error_category_impl
+ : public std::error_category
+{
+public:
+ virtual const char* name() const JSONCONS_NOEXCEPT
+ {
+ return "jsoncons";
+ }
+ virtual std::string message(int ev) const
+ {
+ switch (static_cast<json_parser_errc>(ev))
+ {
+ case json_parser_errc::unexpected_eof:
+ return "Unexpected end of file";
+ case json_parser_errc::source_error:
+ return "Source error";
+ case json_parser_errc::invalid_json_text:
+ return "Invalid JSON text";
+ case json_parser_errc::extra_character:
+ return "Unexpected non-whitespace character after JSON text";
+ case json_parser_errc::max_depth_exceeded:
+ return "Maximum JSON depth exceeded";
+ case json_parser_errc::single_quote:
+ return "JSON strings cannot be quoted with single quotes";
+ case json_parser_errc::illegal_character_in_string:
+ return "Illegal character in string";
+ case json_parser_errc::extra_comma:
+ return "Extra comma";
+ case json_parser_errc::expected_name:
+ return "Expected object member name";
+ case json_parser_errc::expected_value:
+ return "Expected value";
+ case json_parser_errc::invalid_value:
+ return "Invalid value";
+ case json_parser_errc::expected_colon:
+ return "Expected name separator ':'";
+ case json_parser_errc::illegal_control_character:
+ return "Illegal control character in string";
+ case json_parser_errc::illegal_escaped_character:
+ return "Illegal escaped character in string";
+ case json_parser_errc::expected_codepoint_surrogate_pair:
+ return "Invalid codepoint, expected another \\u token to begin the second half of a codepoint surrogate pair.";
+ case json_parser_errc::invalid_hex_escape_sequence:
+ return "Invalid codepoint, expected hexadecimal digit.";
+ case json_parser_errc::invalid_unicode_escape_sequence:
+ return "Invalid codepoint, expected four hexadecimal digits.";
+ case json_parser_errc::leading_zero:
+ return "A number cannot have a leading zero";
+ case json_parser_errc::invalid_number:
+ return "Invalid number";
+ case json_parser_errc::expected_comma_or_right_brace:
+ return "Expected comma or right brace ']'";
+ case json_parser_errc::expected_comma_or_right_bracket:
+ return "Expected comma or right bracket ']'";
+ case json_parser_errc::unexpected_right_brace:
+ return "Unexpected right brace '}'";
+ case json_parser_errc::unexpected_right_bracket:
+ return "Unexpected right bracket ']'";
+ case json_parser_errc::illegal_comment:
+ return "Illegal comment";
+ case json_parser_errc::expected_continuation_byte:
+ return "Expected continuation byte";
+ case json_parser_errc::over_long_utf8_sequence:
+ return "Over long UTF-8 sequence";
+ case json_parser_errc::illegal_codepoint:
+ return "Illegal codepoint (>= 0xd800 && <= 0xdfff)";
+ case json_parser_errc::illegal_surrogate_value:
+ return "UTF-16 surrogate values are illegal in UTF-32";
+ case json_parser_errc::unpaired_high_surrogate:
+ return "Expected low surrogate following the high surrogate";
+ default:
+ return "Unknown JSON parser error";
+ }
+ }
+};
+
+inline
+const std::error_category& json_error_category()
+{
+ static json_error_category_impl instance;
+ return instance;
+}
+
+inline
+std::error_code make_error_code(json_parser_errc result)
+{
+ return std::error_code(static_cast<int>(result),json_error_category());
+}
+
+
+}
+
+namespace std {
+ template<>
+ struct is_error_code_enum<jsoncons::json_parser_errc> : public true_type
+ {
+ };
+}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_exception.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_exception.hpp
new file mode 100644
index 00000000..668fa3c5
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_exception.hpp
@@ -0,0 +1,107 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSON_EXCEPTION_HPP
+#define JSON_EXCEPTION_HPP
+
+#include <locale>
+#include <string>
+#include <vector>
+#include <cstdlib>
+#include <cwchar>
+#include <cstdint>
+#include <iostream>
+#include <vector>
+#include <iterator>
+#include <jsoncons/detail/unicode_traits.hpp>
+#include <jsoncons/jsoncons_config.hpp>
+
+namespace jsoncons {
+
+// json_exception
+
+class json_exception
+{
+public:
+ virtual const char* what() const JSONCONS_NOEXCEPT = 0;
+};
+
+template <class Base>
+class json_exception_impl : public Base, public virtual json_exception
+{
+public:
+ json_exception_impl(const std::string& s) JSONCONS_NOEXCEPT
+ : Base(""), message_(s)
+ {
+ }
+ ~json_exception_impl() JSONCONS_NOEXCEPT
+ {
+ }
+ const char* what() const JSONCONS_NOEXCEPT override
+ {
+ return message_.c_str();
+ }
+private:
+ std::string message_;
+};
+
+class key_not_found : public std::out_of_range, public virtual json_exception
+{
+public:
+ template <class CharT>
+ explicit key_not_found(const CharT* key, size_t length) JSONCONS_NOEXCEPT
+ : std::out_of_range("")
+ {
+ buffer_.append("Key '");
+ unicons::convert(key, key+length, std::back_inserter(buffer_),
+ unicons::conv_flags::strict);
+ buffer_.append("' not found");
+ }
+ ~key_not_found() JSONCONS_NOEXCEPT
+ {
+ }
+ const char* what() const JSONCONS_NOEXCEPT override
+ {
+ return buffer_.c_str();
+ }
+private:
+ std::string buffer_;
+};
+
+class not_an_object : public std::runtime_error, public virtual json_exception
+{
+public:
+ template <class CharT>
+ explicit not_an_object(const CharT* key, size_t length) JSONCONS_NOEXCEPT
+ : std::runtime_error("")
+ {
+ buffer_.append("Attempting to access or modify '");
+ unicons::convert(key, key+length, std::back_inserter(buffer_),
+ unicons::conv_flags::strict);
+ buffer_.append("' on a value that is not an object");
+ }
+ ~not_an_object() JSONCONS_NOEXCEPT
+ {
+ }
+ const char* what() const JSONCONS_NOEXCEPT override
+ {
+ return buffer_.c_str();
+ }
+private:
+ std::string buffer_;
+};
+
+#define JSONCONS_STR2(x) #x
+#define JSONCONS_STR(x) JSONCONS_STR2(x)
+
+#define JSONCONS_ASSERT(x) if (!(x)) { \
+ throw jsoncons::json_exception_impl<std::runtime_error>("assertion '" #x "' failed at " __FILE__ ":" \
+ JSONCONS_STR(__LINE__)); }
+
+#define JSONCONS_THROW(x) throw (x)
+
+}
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_filter.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_filter.hpp
new file mode 100644
index 00000000..30b69e18
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_filter.hpp
@@ -0,0 +1,465 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_FILTER_HPP
+#define JSONCONS_JSON_FILTER_HPP
+
+#include <string>
+
+#include <jsoncons/json_input_handler.hpp>
+#include <jsoncons/json_output_handler.hpp>
+#include <jsoncons/parse_error_handler.hpp>
+
+namespace jsoncons {
+
+template <class CharT>
+class basic_json_output_input_adapter : public basic_json_input_handler<CharT>
+{
+public:
+ using typename basic_json_input_handler<CharT>::string_view_type;
+private:
+
+ basic_null_json_output_handler<CharT> null_output_handler_;
+ basic_json_output_handler<CharT>& output_handler_;
+
+ // noncopyable and nonmoveable
+ basic_json_output_input_adapter<CharT>(const basic_json_output_input_adapter<CharT>&) = delete;
+ basic_json_output_input_adapter<CharT>& operator=(const basic_json_output_input_adapter<CharT>&) = delete;
+
+public:
+ basic_json_output_input_adapter()
+ : output_handler_(null_output_handler_)
+ {
+ }
+
+ basic_json_output_input_adapter(basic_json_output_handler<CharT>& handler)
+ : output_handler_(handler)
+ {
+ }
+
+private:
+
+ void do_begin_json() override
+ {
+ output_handler_.begin_json();
+ }
+
+ void do_end_json() override
+ {
+ output_handler_.end_json();
+ }
+
+ void do_begin_object(const parsing_context&) override
+ {
+ output_handler_.begin_object();
+ }
+
+ void do_begin_object(size_t length, const parsing_context&) override
+ {
+ output_handler_.begin_object(length);
+ }
+
+ void do_end_object(const parsing_context&) override
+ {
+ output_handler_.end_object();
+ }
+
+ void do_begin_array(const parsing_context&) override
+ {
+ output_handler_.begin_array();
+ }
+
+ void do_begin_array(size_t length, const parsing_context&) override
+ {
+ output_handler_.begin_array(length);
+ }
+
+ void do_end_array(const parsing_context&) override
+ {
+ output_handler_.end_array();
+ }
+
+ void do_name(const string_view_type& name,
+ const parsing_context&) override
+ {
+ output_handler_.name(name);
+ }
+
+ void do_string_value(const string_view_type& value,
+ const parsing_context&) override
+ {
+ output_handler_.string_value(value);
+ }
+
+ void do_byte_string_value(const uint8_t* data, size_t length,
+ const parsing_context&) override
+ {
+ output_handler_.byte_string_value(data, length);
+ }
+
+ void do_integer_value(int64_t value, const parsing_context&) override
+ {
+ output_handler_.integer_value(value);
+ }
+
+ void do_uinteger_value(uint64_t value,
+ const parsing_context&) override
+ {
+ output_handler_.uinteger_value(value);
+ }
+
+ void do_double_value(double value, const number_format& fmt, const parsing_context&) override
+ {
+ output_handler_.double_value(value, fmt);
+ }
+
+ void do_bool_value(bool value, const parsing_context&) override
+ {
+ output_handler_.bool_value(value);
+ }
+
+ void do_null_value(const parsing_context&) override
+ {
+ output_handler_.null_value();
+ }
+};
+
+template <class CharT>
+class basic_json_input_output_adapter : public basic_json_output_handler<CharT>
+{
+public:
+ using typename basic_json_output_handler<CharT>::string_view_type ;
+private:
+ class null_parsing_context : public parsing_context
+ {
+ size_t do_line_number() const override { return 0; }
+
+ size_t do_column_number() const override { return 0; }
+ };
+ const null_parsing_context default_context_ = null_parsing_context();
+
+ basic_null_json_input_handler<CharT> null_input_handler_;
+ basic_json_output_input_adapter<CharT> default_input_output_adapter_;
+ basic_json_input_handler<CharT>& input_handler_;
+ const basic_json_output_input_adapter<CharT>& input_output_adapter_;
+
+ // noncopyable and nonmoveable
+ basic_json_input_output_adapter<CharT>(const basic_json_input_output_adapter<CharT>&) = delete;
+ basic_json_input_output_adapter<CharT>& operator=(const basic_json_input_output_adapter<CharT>&) = delete;
+
+public:
+ basic_json_input_output_adapter()
+ : input_handler_(null_input_handler_),
+ input_output_adapter_(default_input_output_adapter_)
+ {
+ }
+ basic_json_input_output_adapter(basic_json_input_handler<CharT>& input_handler)
+ : input_handler_(input_handler),
+ input_output_adapter_(default_input_output_adapter_)
+ {
+ }
+ basic_json_input_output_adapter(basic_json_input_handler<CharT>& input_handler,
+ const basic_json_output_input_adapter<CharT>& input_output_adapter)
+ : input_handler_(input_handler),
+ input_output_adapter_(input_output_adapter)
+ {
+ }
+
+private:
+
+ void do_begin_json() override
+ {
+ input_handler_.begin_json();
+ }
+
+ void do_end_json() override
+ {
+ input_handler_.end_json();
+ }
+
+ void do_begin_object() override
+ {
+ input_handler_.begin_object(default_context_);
+ }
+
+ void do_begin_object(size_t length) override
+ {
+ input_handler_.begin_object(length, default_context_);
+ }
+
+ void do_end_object() override
+ {
+ input_handler_.end_object(default_context_);
+ }
+
+ void do_begin_array() override
+ {
+ input_handler_.begin_array(default_context_);
+ }
+
+ void do_begin_array(size_t length) override
+ {
+ input_handler_.begin_array(length, default_context_);
+ }
+
+ void do_end_array() override
+ {
+ input_handler_.end_array(default_context_);
+ }
+
+ void do_name(const string_view_type& name) override
+ {
+ input_handler_.name(name, default_context_);
+ }
+
+ void do_string_value(const string_view_type& value) override
+ {
+ input_handler_.string_value(value, default_context_);
+ }
+
+ void do_byte_string_value(const uint8_t* data, size_t length) override
+ {
+ input_handler_.byte_string_value(data, length, default_context_);
+ }
+
+ void do_integer_value(int64_t value) override
+ {
+ input_handler_.integer_value(value, default_context_);
+ }
+
+ void do_uinteger_value(uint64_t value) override
+ {
+ input_handler_.uinteger_value(value, default_context_);
+ }
+
+ void do_double_value(double value, const number_format& fmt) override
+ {
+ input_handler_.double_value(value, fmt, default_context_);
+ }
+
+ void do_bool_value(bool value) override
+ {
+ input_handler_.bool_value(value, default_context_);
+ }
+
+ void do_null_value() override
+ {
+ input_handler_.null_value(default_context_);
+ }
+};
+
+template <class CharT>
+class basic_json_filter : public basic_json_input_handler<CharT>
+{
+public:
+ using typename basic_json_input_handler<CharT>::string_view_type ;
+private:
+ basic_json_output_input_adapter<CharT> input_output_adapter_;
+ basic_json_input_output_adapter<CharT> output_input_adapter_;
+ basic_json_output_handler<CharT>& output_handler_;
+ basic_json_input_handler<CharT>& downstream_handler_;
+
+ // noncopyable and nonmoveable
+ basic_json_filter<CharT>(const basic_json_filter<CharT>&) = delete;
+ basic_json_filter<CharT>& operator=(const basic_json_filter<CharT>&) = delete;
+public:
+ basic_json_filter(basic_json_output_handler<CharT>& handler)
+ : input_output_adapter_(handler),
+ output_input_adapter_(*this),
+ output_handler_(output_input_adapter_),
+ downstream_handler_(input_output_adapter_)
+ {
+ }
+
+ basic_json_filter(basic_json_input_handler<CharT>& handler)
+ : output_input_adapter_(*this),
+ output_handler_(output_input_adapter_),
+ downstream_handler_(handler)
+ {
+ }
+
+ operator basic_json_output_handler<CharT>&()
+ {
+ return output_handler_;
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+ basic_json_input_handler<CharT>& input_handler()
+ {
+ return downstream_handler_;
+ }
+#endif
+
+ basic_json_input_handler<CharT>& downstream_handler()
+ {
+ return downstream_handler_;
+ }
+
+private:
+ void do_begin_json() override
+ {
+ downstream_handler_.begin_json();
+ }
+
+ void do_end_json() override
+ {
+ downstream_handler_.end_json();
+ }
+
+ void do_begin_object(const parsing_context& context) override
+ {
+ downstream_handler_.begin_object(context);
+ }
+
+ void do_begin_object(size_t length, const parsing_context& context) override
+ {
+ downstream_handler_.begin_object(length, context);
+ }
+
+ void do_end_object(const parsing_context& context) override
+ {
+ downstream_handler_.end_object(context);
+ }
+
+ void do_begin_array(const parsing_context& context) override
+ {
+ downstream_handler_.begin_array(context);
+ }
+
+ void do_begin_array(size_t length, const parsing_context& context) override
+ {
+ downstream_handler_.begin_array(length, context);
+ }
+
+ void do_end_array(const parsing_context& context) override
+ {
+ downstream_handler_.end_array(context);
+ }
+
+ void do_name(const string_view_type& name,
+ const parsing_context& context) override
+ {
+ downstream_handler_.name(name,context);
+ }
+
+ void do_string_value(const string_view_type& value,
+ const parsing_context& context) override
+ {
+ downstream_handler_.string_value(value,context);
+ }
+
+ void do_byte_string_value(const uint8_t* data, size_t length,
+ const parsing_context& context) override
+ {
+ downstream_handler_.byte_string_value(data, length, context);
+ }
+
+ void do_double_value(double value, const number_format& fmt,
+ const parsing_context& context) override
+ {
+ downstream_handler_.double_value(value, fmt, context);
+ }
+
+ void do_integer_value(int64_t value,
+ const parsing_context& context) override
+ {
+ downstream_handler_.integer_value(value,context);
+ }
+
+ void do_uinteger_value(uint64_t value,
+ const parsing_context& context) override
+ {
+ downstream_handler_.uinteger_value(value,context);
+ }
+
+ void do_bool_value(bool value,
+ const parsing_context& context) override
+ {
+ downstream_handler_.bool_value(value,context);
+ }
+
+ void do_null_value(const parsing_context& context) override
+ {
+ downstream_handler_.null_value(context);
+ }
+
+};
+
+// Filters out begin_json and end_json events
+template <class CharT>
+class basic_json_fragment_filter : public basic_json_filter<CharT>
+{
+public:
+ using typename basic_json_filter<CharT>::string_view_type;
+
+ basic_json_fragment_filter(basic_json_input_handler<CharT>& handler)
+ : basic_json_filter<CharT>(handler)
+ {
+ }
+private:
+ void do_begin_json() override
+ {
+ }
+
+ void do_end_json() override
+ {
+ }
+};
+
+template <class CharT>
+class basic_rename_object_member_filter : public basic_json_filter<CharT>
+{
+public:
+ using typename basic_json_filter<CharT>::string_view_type;
+
+private:
+ std::basic_string<CharT> name_;
+ std::basic_string<CharT> new_name_;
+public:
+ basic_rename_object_member_filter(const std::basic_string<CharT>& name,
+ const std::basic_string<CharT>& new_name,
+ basic_json_output_handler<CharT>& handler)
+ : basic_json_filter<CharT>(handler),
+ name_(name), new_name_(new_name)
+ {
+ }
+
+ basic_rename_object_member_filter(const std::basic_string<CharT>& name,
+ const std::basic_string<CharT>& new_name,
+ basic_json_input_handler<CharT>& handler)
+ : basic_json_filter<CharT>(handler),
+ name_(name), new_name_(new_name)
+ {
+ }
+
+private:
+ void do_name(const string_view_type& name,
+ const parsing_context& context) override
+ {
+ if (name == name_)
+ {
+ this->downstream_handler().name(new_name_,context);
+ }
+ else
+ {
+ this->downstream_handler().name(name,context);
+ }
+ }
+};
+
+typedef basic_json_filter<char> json_filter;
+typedef basic_json_filter<wchar_t> wjson_filter;
+typedef basic_rename_object_member_filter<char> rename_object_member_filter;
+typedef basic_rename_object_member_filter<wchar_t> wrename_object_member_filter;
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+typedef basic_rename_object_member_filter<char> rename_name_filter;
+typedef basic_rename_object_member_filter<wchar_t> wrename_name_filter;
+#endif
+
+}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_input_handler.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_input_handler.hpp
new file mode 100644
index 00000000..ed014287
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_input_handler.hpp
@@ -0,0 +1,308 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_INPUT_HANDLER_HPP
+#define JSONCONS_JSON_INPUT_HANDLER_HPP
+
+#include <string>
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/jsoncons_utilities.hpp>
+#if !defined(JSONCONS_NO_DEPRECATED)
+#include <jsoncons/json_type_traits.hpp> // for null_type
+#endif
+
+namespace jsoncons {
+
+class parsing_context;
+
+template <class CharT>
+class basic_json_input_handler
+{
+public:
+ typedef CharT char_type;
+ typedef std::char_traits<char_type> char_traits_type;
+
+ typedef basic_string_view_ext<char_type,char_traits_type> string_view_type;
+
+ virtual ~basic_json_input_handler() {}
+
+ void begin_json()
+ {
+ do_begin_json();
+ }
+
+ void end_json()
+ {
+ do_end_json();
+ }
+
+ void begin_object(const parsing_context& context)
+ {
+ do_begin_object(context);
+ }
+
+ void begin_object(size_t length, const parsing_context& context)
+ {
+ do_begin_object(length, context);
+ }
+
+ void end_object(const parsing_context& context)
+ {
+ do_end_object(context);
+ }
+
+ void begin_array(const parsing_context& context)
+ {
+ do_begin_array(context);
+ }
+
+ void begin_array(size_t length, const parsing_context& context)
+ {
+ do_begin_array(length, context);
+ }
+
+ void end_array(const parsing_context& context)
+ {
+ do_end_array(context);
+ }
+
+ void name(const string_view_type& name, const parsing_context& context)
+ {
+ do_name(name, context);
+ }
+
+// new
+
+ void string_value(const string_view_type& value, const parsing_context& context)
+ {
+ do_string_value(value, context);
+ }
+
+ void byte_string_value(const uint8_t* data, size_t length, const parsing_context& context)
+ {
+ do_byte_string_value(data, length, context);
+ }
+
+ void integer_value(int64_t value, const parsing_context& context)
+ {
+ do_integer_value(value,context);
+ }
+
+ void uinteger_value(uint64_t value, const parsing_context& context)
+ {
+ do_uinteger_value(value,context);
+ }
+
+ void double_value(double value, const parsing_context& context)
+ {
+ do_double_value(value, number_format(), context);
+ }
+
+ void double_value(double value, uint8_t precision, const parsing_context& context)
+ {
+ do_double_value(value, number_format(precision, 0), context);
+ }
+
+ void double_value(double value, const number_format& fmt, const parsing_context& context)
+ {
+ do_double_value(value, fmt, context);
+ }
+
+ void bool_value(bool value, const parsing_context& context)
+ {
+ do_bool_value(value,context);
+ }
+
+ void null_value(const parsing_context& context)
+ {
+ do_null_value(context);
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+
+ void name(const CharT* p, size_t length, const parsing_context& context)
+ {
+ do_name(string_view_type(p, length), context);
+ }
+
+ void value(const std::basic_string<CharT>& value, const parsing_context& context)
+ {
+ do_string_value(value, context);
+ }
+
+ void value(const CharT* p, size_t length, const parsing_context& context)
+ {
+ do_string_value(string_view_type(p, length), context);
+ }
+
+ void value(const CharT* p, const parsing_context& context)
+ {
+ do_string_value(string_view_type(p), context);
+ }
+
+ void value(int value, const parsing_context& context)
+ {
+ do_integer_value(value,context);
+ }
+
+ void value(long value, const parsing_context& context)
+ {
+ do_integer_value(value,context);
+ }
+
+ void value(long long value, const parsing_context& context)
+ {
+ do_integer_value(value,context);
+ }
+
+ void value(unsigned int value, const parsing_context& context)
+ {
+ do_uinteger_value(value,context);
+ }
+
+ void value(unsigned long value, const parsing_context& context)
+ {
+ do_uinteger_value(value,context);
+ }
+
+ void value(unsigned long long value, const parsing_context& context)
+ {
+ do_uinteger_value(value,context);
+ }
+
+ void value(float value, uint8_t precision, const parsing_context& context)
+ {
+ do_double_value(value, number_format(precision, 0), context);
+ }
+
+ void value(double value, uint8_t precision, const parsing_context& context)
+ {
+ do_double_value(value, number_format(precision, 0), context);
+ }
+
+ void value(bool value, const parsing_context& context)
+ {
+ do_bool_value(value,context);
+ }
+
+ void value(null_type, const parsing_context& context)
+ {
+ do_null_value(context);
+ }
+#endif
+
+private:
+ virtual void do_begin_json() = 0;
+
+ virtual void do_end_json() = 0;
+
+ virtual void do_begin_object(const parsing_context& context) = 0;
+
+ virtual void do_begin_object(size_t length, const parsing_context& context)
+ {
+ do_begin_object(context);
+ }
+
+ virtual void do_end_object(const parsing_context& context) = 0;
+
+ virtual void do_begin_array(const parsing_context& context) = 0;
+
+ virtual void do_begin_array(size_t length, const parsing_context& context)
+ {
+ do_begin_array(context);
+ }
+
+ virtual void do_end_array(const parsing_context& context) = 0;
+
+ virtual void do_name(const string_view_type& name, const parsing_context& context) = 0;
+
+ virtual void do_null_value(const parsing_context& context) = 0;
+
+ virtual void do_string_value(const string_view_type& value, const parsing_context& context) = 0;
+
+ virtual void do_byte_string_value(const uint8_t* data, size_t length, const parsing_context& context) = 0;
+
+ virtual void do_double_value(double value, const number_format& fmt, const parsing_context& context) = 0;
+
+ virtual void do_integer_value(int64_t value, const parsing_context& context) = 0;
+
+ virtual void do_uinteger_value(uint64_t value, const parsing_context& context) = 0;
+
+ virtual void do_bool_value(bool value, const parsing_context& context) = 0;
+};
+
+template <class CharT>
+class basic_null_json_input_handler final : public basic_json_input_handler<CharT>
+{
+public:
+ using typename basic_json_input_handler<CharT>::string_view_type ;
+private:
+ void do_begin_json() override
+ {
+ }
+
+ void do_end_json() override
+ {
+ }
+
+ void do_begin_object(const parsing_context&) override
+ {
+ }
+
+ void do_end_object(const parsing_context&) override
+ {
+ }
+
+ void do_begin_array(const parsing_context&) override
+ {
+ }
+
+ void do_end_array(const parsing_context&) override
+ {
+ }
+
+ void do_name(const string_view_type&, const parsing_context&) override
+ {
+ }
+
+ void do_null_value(const parsing_context&) override
+ {
+ }
+
+ void do_string_value(const string_view_type&, const parsing_context&) override
+ {
+ }
+
+ void do_byte_string_value(const uint8_t* data, size_t length, const parsing_context&) override
+ {
+ }
+
+ void do_double_value(double, const number_format& fmt, const parsing_context&) override
+ {
+ }
+
+ void do_integer_value(int64_t, const parsing_context&) override
+ {
+ }
+
+ void do_uinteger_value(uint64_t, const parsing_context&) override
+ {
+ }
+
+ void do_bool_value(bool, const parsing_context&) override
+ {
+ }
+};
+
+typedef basic_json_input_handler<char> json_input_handler;
+typedef basic_json_input_handler<wchar_t> wjson_input_handler;
+
+typedef basic_null_json_input_handler<char> null_json_input_handler;
+typedef basic_null_json_input_handler<wchar_t> wnull_json_input_handler;
+
+}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_output_handler.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_output_handler.hpp
new file mode 100644
index 00000000..b16f098e
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_output_handler.hpp
@@ -0,0 +1,300 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_OUTPUT_HANDLER_HPP
+#define JSONCONS_JSON_OUTPUT_HANDLER_HPP
+
+#include <string>
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/jsoncons_utilities.hpp>
+#if !defined(JSONCONS_NO_DEPRECATED)
+#include <jsoncons/json_type_traits.hpp> // for null_type
+#endif
+
+namespace jsoncons {
+
+template <class CharT>
+class basic_json_output_handler
+{
+public:
+ typedef CharT char_type;
+ typedef std::char_traits<char_type> char_traits_type;
+
+ typedef basic_string_view_ext<char_type,char_traits_type> string_view_type;
+
+ virtual ~basic_json_output_handler() {}
+
+ // Overloaded methods
+
+ void begin_json()
+ {
+ do_begin_json();
+ }
+
+ void end_json()
+ {
+ do_end_json();
+ }
+
+ void begin_object()
+ {
+ do_begin_object();
+ }
+
+ void begin_object(size_t length)
+ {
+ do_begin_object(length);
+ }
+
+ void end_object()
+ {
+ do_end_object();
+ }
+
+ void begin_array()
+ {
+ do_begin_array();
+ }
+
+ void begin_array(size_t length)
+ {
+ do_begin_array(length);
+ }
+
+ void end_array()
+ {
+ do_end_array();
+ }
+
+ void name(const string_view_type& name)
+ {
+ do_name(name);
+ }
+
+ void string_value(const string_view_type& value)
+ {
+ do_string_value(value);
+ }
+
+ void byte_string_value(const uint8_t* data, size_t length)
+ {
+ do_byte_string_value(data, length);
+ }
+
+ void integer_value(int64_t value)
+ {
+ do_integer_value(value);
+ }
+
+ void uinteger_value(uint64_t value)
+ {
+ do_uinteger_value(value);
+ }
+
+ void double_value(double value)
+ {
+ do_double_value(value, number_format());
+ }
+
+ void double_value(double value, uint8_t precision)
+ {
+ do_double_value(value, number_format(precision, 0));
+ }
+
+ void double_value(double value, const number_format& fmt)
+ {
+ do_double_value(value, fmt);
+ }
+
+ void bool_value(bool value)
+ {
+ do_bool_value(value);
+ }
+
+ void null_value()
+ {
+ do_null_value();
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+
+ void name(const CharT* p, size_t length)
+ {
+ do_name(string_view_type(p, length));
+ }
+
+ void value(const string_view_type& value)
+ {
+ do_string_value(value);
+ }
+
+ void value(const CharT* p, size_t length)
+ {
+ do_string_value(string_view_type(p, length));
+ }
+
+ void value(const CharT* p)
+ {
+ do_string_value(string_view_type(p));
+ }
+
+ void value(int value)
+ {
+ do_integer_value(value);
+ }
+
+ void value(long value)
+ {
+ do_integer_value(value);
+ }
+
+ void value(long long value)
+ {
+ do_integer_value(value);
+ }
+
+ void value(unsigned int value)
+ {
+ do_uinteger_value(value);
+ }
+
+ void value(unsigned long value)
+ {
+ do_uinteger_value(value);
+ }
+
+ void value(unsigned long long value)
+ {
+ do_uinteger_value(value);
+ }
+
+ void value(double value, uint8_t precision = 0, uint8_t decimal_places = 0)
+ {
+ do_double_value(value, precision, decimal_places);
+ }
+
+ void value(bool value)
+ {
+ do_bool_value(value);
+ }
+
+ void value(null_type)
+ {
+ do_null_value();
+ }
+#endif
+
+private:
+
+ virtual void do_begin_json() = 0;
+
+ virtual void do_end_json() = 0;
+
+ virtual void do_name(const string_view_type& name) = 0;
+
+ virtual void do_begin_object() = 0;
+
+ virtual void do_begin_object(size_t length)
+ {
+ do_begin_object();
+ }
+
+ virtual void do_end_object() = 0;
+
+ virtual void do_begin_array() = 0;
+
+ virtual void do_begin_array(size_t length)
+ {
+ do_begin_array();
+ }
+
+ virtual void do_end_array() = 0;
+
+ virtual void do_null_value() = 0;
+
+ virtual void do_string_value(const string_view_type& value) = 0;
+
+ virtual void do_byte_string_value(const uint8_t* data, size_t length) = 0;
+
+ virtual void do_double_value(double value, const number_format& fmt) = 0;
+
+ virtual void do_integer_value(int64_t value) = 0;
+
+ virtual void do_uinteger_value(uint64_t value) = 0;
+
+ virtual void do_bool_value(bool value) = 0;
+};
+
+template <class CharT>
+class basic_null_json_output_handler : public basic_json_output_handler<CharT>
+{
+public:
+ using typename basic_json_output_handler<CharT>::string_view_type ;
+private:
+
+ void do_begin_json() override
+ {
+ }
+
+ void do_end_json() override
+ {
+ }
+
+ void do_name(const string_view_type&) override
+ {
+ }
+
+ void do_begin_object() override
+ {
+ }
+
+ void do_end_object() override
+ {
+ }
+
+ void do_begin_array() override
+ {
+ }
+
+ void do_end_array() override
+ {
+ }
+
+ void do_null_value() override
+ {
+ }
+
+ void do_string_value(const string_view_type&) override
+ {
+ }
+
+ void do_byte_string_value(const uint8_t* data, size_t length) override
+ {
+ }
+
+ void do_double_value(double, const number_format&) override
+ {
+ }
+
+ void do_integer_value(int64_t) override
+ {
+ }
+
+ void do_uinteger_value(uint64_t) override
+ {
+ }
+
+ void do_bool_value(bool) override
+ {
+ }
+
+};
+
+typedef basic_json_output_handler<char> json_output_handler;
+typedef basic_json_output_handler<wchar_t> wjson_output_handler;
+
+}
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_parser.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_parser.hpp
new file mode 100644
index 00000000..13bd9500
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_parser.hpp
@@ -0,0 +1,2830 @@
+// Copyright 2015 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_PARSER_HPP
+#define JSONCONS_JSON_PARSER_HPP
+
+#include <memory>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <stdexcept>
+#include <system_error>
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/json_input_handler.hpp>
+#include <jsoncons/parse_error_handler.hpp>
+#include <jsoncons/json_error_category.hpp>
+#include <jsoncons/detail/number_parsers.hpp>
+
+#define JSONCONS_ILLEGAL_CONTROL_CHARACTER \
+ case 0x00:case 0x01:case 0x02:case 0x03:case 0x04:case 0x05:case 0x06:case 0x07:case 0x08:case 0x0b: \
+ case 0x0c:case 0x0e:case 0x0f:case 0x10:case 0x11:case 0x12:case 0x13:case 0x14:case 0x15:case 0x16: \
+ case 0x17:case 0x18:case 0x19:case 0x1a:case 0x1b:case 0x1c:case 0x1d:case 0x1e:case 0x1f
+
+namespace jsoncons {
+
+enum class parse_state : uint8_t
+{
+ root,
+ start,
+ slash,
+ slash_slash,
+ slash_star,
+ slash_star_star,
+ expect_comma_or_end,
+ object,
+ expect_member_name_or_end,
+ expect_member_name,
+ expect_colon,
+ expect_value_or_end,
+ expect_value,
+ array,
+ string_u1,
+ member_name,
+ escape,
+ escape_u1,
+ escape_u2,
+ escape_u3,
+ escape_u4,
+ escape_expect_surrogate_pair1,
+ escape_expect_surrogate_pair2,
+ escape_u6,
+ escape_u7,
+ escape_u8,
+ escape_u9,
+ minus,
+ zero,
+ integer,
+ fraction1,
+ fraction2,
+ exp1,
+ exp2,
+ exp3,
+ n,
+ nu,
+ nul,
+ t,
+ tr,
+ tru,
+ f,
+ fa,
+ fal,
+ fals,
+ cr,
+ lf,
+ done
+};
+
+template <class CharT, class Allocator = std::allocator<char>>
+class basic_json_parser : private parsing_context
+{
+ static const size_t initial_string_buffer_capacity_ = 1024;
+ static const size_t initial_number_buffer_capacity_ = 64;
+ static const int default_initial_stack_capacity_ = 100;
+ typedef typename basic_json_input_handler<CharT>::string_view_type string_view_type;
+
+ basic_null_json_input_handler<CharT> default_input_handler_;
+ default_parse_error_handler default_err_handler_;
+
+ basic_json_input_handler<CharT>& handler_;
+ parse_error_handler& err_handler_;
+ uint32_t cp_;
+ uint32_t cp2_;
+
+ typedef Allocator allocator_type;
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<CharT> char_allocator_type;
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<char> numeral_allocator_type;
+
+ std::basic_string<CharT,std::char_traits<CharT>,char_allocator_type> string_buffer_;
+ std::basic_string<char,std::char_traits<char>,numeral_allocator_type> number_buffer_;
+
+ bool is_negative_;
+ uint8_t precision_;
+ uint8_t decimal_places_;
+
+ size_t line_;
+ size_t column_;
+ int nesting_depth_;
+ int initial_stack_capacity_;
+
+ int max_depth_;
+ detail::string_to_double to_double_;
+ const CharT* begin_input_;
+ const CharT* input_end_;
+ const CharT* input_ptr_;
+
+ parse_state state_;
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<parse_state> parse_state_allocator_type;
+ std::vector<parse_state,parse_state_allocator_type> state_stack_;
+
+ // Noncopyable and nonmoveable
+ basic_json_parser(const basic_json_parser&) = delete;
+ basic_json_parser& operator=(const basic_json_parser&) = delete;
+
+public:
+
+ basic_json_parser()
+ : handler_(default_input_handler_),
+ err_handler_(default_err_handler_),
+ cp_(0),
+ cp2_(0),
+ is_negative_(false),
+ precision_(0),
+ decimal_places_(0),
+ line_(1),
+ column_(1),
+ nesting_depth_(0),
+ initial_stack_capacity_(default_initial_stack_capacity_),
+ begin_input_(nullptr),
+ input_end_(nullptr),
+ input_ptr_(nullptr),
+ state_(parse_state::start)
+ {
+ string_buffer_.reserve(initial_string_buffer_capacity_);
+ number_buffer_.reserve(initial_number_buffer_capacity_);
+ max_depth_ = (std::numeric_limits<int>::max)();
+
+ state_stack_.reserve(initial_stack_capacity_);
+ push_state(parse_state::root);
+ }
+
+ basic_json_parser(parse_error_handler& err_handler)
+ : handler_(default_input_handler_),
+ err_handler_(err_handler),
+ cp_(0),
+ cp2_(0),
+ is_negative_(false),
+ precision_(0),
+ decimal_places_(0),
+ line_(1),
+ column_(1),
+ nesting_depth_(0),
+ initial_stack_capacity_(default_initial_stack_capacity_),
+ begin_input_(nullptr),
+ input_end_(nullptr),
+ input_ptr_(nullptr),
+ state_(parse_state::start)
+ {
+ string_buffer_.reserve(initial_string_buffer_capacity_);
+ number_buffer_.reserve(initial_number_buffer_capacity_);
+ max_depth_ = (std::numeric_limits<int>::max)();
+
+ state_stack_.reserve(initial_stack_capacity_);
+ push_state(parse_state::root);
+ }
+
+ basic_json_parser(basic_json_input_handler<CharT>& handler)
+ : handler_(handler),
+ err_handler_(default_err_handler_),
+ cp_(0),
+ cp2_(0),
+ is_negative_(false),
+ precision_(0),
+ decimal_places_(0),
+ line_(1),
+ column_(1),
+ nesting_depth_(0),
+ initial_stack_capacity_(default_initial_stack_capacity_),
+ begin_input_(nullptr),
+ input_end_(nullptr),
+ input_ptr_(nullptr),
+ state_(parse_state::start)
+ {
+ string_buffer_.reserve(initial_string_buffer_capacity_);
+ number_buffer_.reserve(initial_number_buffer_capacity_);
+ max_depth_ = (std::numeric_limits<int>::max)();
+
+ state_stack_.reserve(initial_stack_capacity_);
+ push_state(parse_state::root);
+ }
+
+ basic_json_parser(basic_json_input_handler<CharT>& handler,
+ parse_error_handler& err_handler)
+ : handler_(handler),
+ err_handler_(err_handler),
+ cp_(0),
+ cp2_(0),
+ is_negative_(false),
+ precision_(0),
+ decimal_places_(0),
+ line_(1),
+ column_(1),
+ nesting_depth_(0),
+ initial_stack_capacity_(default_initial_stack_capacity_),
+ begin_input_(nullptr),
+ input_end_(nullptr),
+ input_ptr_(nullptr),
+ state_(parse_state::start)
+ {
+ string_buffer_.reserve(initial_string_buffer_capacity_);
+ number_buffer_.reserve(initial_number_buffer_capacity_);
+ max_depth_ = (std::numeric_limits<int>::max)();
+
+ state_stack_.reserve(initial_stack_capacity_);
+ push_state(parse_state::root);
+ }
+
+ size_t line_number() const
+ {
+ return line_;
+ }
+
+ size_t column_number() const
+ {
+ return column_;
+ }
+
+ void set_column_number(size_t column)
+ {
+ column_ = column;
+ }
+
+ bool source_exhausted() const
+ {
+ return input_ptr_ == input_end_;
+ }
+
+ const parsing_context& parsing_context() const
+ {
+ return *this;
+ }
+
+ ~basic_json_parser()
+ {
+ }
+
+ size_t max_nesting_depth() const
+ {
+ return static_cast<size_t>(max_depth_);
+ }
+
+ void max_nesting_depth(size_t max_nesting_depth)
+ {
+ max_depth_ = static_cast<int>((std::min)(max_nesting_depth,static_cast<size_t>((std::numeric_limits<int>::max)())));
+ }
+
+ parse_state parent() const
+ {
+ JSONCONS_ASSERT(state_stack_.size() >= 1);
+ return state_stack_.back();
+ }
+
+ bool done() const
+ {
+ return state_ == parse_state::done;
+ }
+
+ void skip_whitespace()
+ {
+ const CharT* local_input_end = input_end_;
+ for (;;)
+ {
+ if (JSONCONS_UNLIKELY(input_ptr_ == local_input_end))
+ {
+ return;
+ }
+ else if (*input_ptr_ == ' ' || *input_ptr_ == '\t')
+ {
+ ++input_ptr_;
+ ++column_;
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+
+ void do_begin_object(std::error_code& ec)
+ {
+ if (++nesting_depth_ >= max_depth_)
+ {
+ if (err_handler_.error(json_parser_errc::max_depth_exceeded, *this))
+ {
+ ec = json_parser_errc::max_depth_exceeded;
+ return;
+ }
+ }
+ push_state(parse_state::object);
+ state_ = parse_state::expect_member_name_or_end;
+ handler_.begin_object(*this);
+ }
+
+ void do_end_object(std::error_code& ec)
+ {
+ --nesting_depth_;
+ state_ = pop_state();
+ if (state_ == parse_state::object)
+ {
+ handler_.end_object(*this);
+ }
+ else if (state_ == parse_state::array)
+ {
+ err_handler_.fatal_error(json_parser_errc::expected_comma_or_right_bracket, *this);
+ ec = json_parser_errc::expected_comma_or_right_bracket;
+ return;
+ }
+ else
+ {
+ err_handler_.fatal_error(json_parser_errc::unexpected_right_brace, *this);
+ ec = json_parser_errc::unexpected_right_brace;
+ return;
+ }
+
+ if (parent() == parse_state::root)
+ {
+ state_ = parse_state::done;
+ handler_.end_json();
+ }
+ else
+ {
+ state_ = parse_state::expect_comma_or_end;
+ }
+ }
+
+ void do_begin_array(std::error_code& ec)
+ {
+ if (++nesting_depth_ >= max_depth_)
+ {
+ if (err_handler_.error(json_parser_errc::max_depth_exceeded, *this))
+ {
+ ec = json_parser_errc::max_depth_exceeded;
+ return;
+ }
+
+ }
+ push_state(parse_state::array);
+ state_ = parse_state::expect_value_or_end;
+ handler_.begin_array(*this);
+ }
+
+ void do_end_array(std::error_code& ec)
+ {
+ --nesting_depth_;
+ state_ = pop_state();
+ if (state_ == parse_state::array)
+ {
+ handler_.end_array(*this);
+ }
+ else if (state_ == parse_state::object)
+ {
+ err_handler_.fatal_error(json_parser_errc::expected_comma_or_right_brace, *this);
+ ec = json_parser_errc::expected_comma_or_right_brace;
+ return;
+ }
+ else
+ {
+ err_handler_.fatal_error(json_parser_errc::unexpected_right_bracket, *this);
+ ec = json_parser_errc::unexpected_right_bracket;
+ return;
+ }
+ if (parent() == parse_state::root)
+ {
+ state_ = parse_state::done;
+ handler_.end_json();
+ }
+ else
+ {
+ state_ = parse_state::expect_comma_or_end;
+ }
+ }
+
+ void reset()
+ {
+ state_stack_.clear();
+ state_stack_.reserve(initial_stack_capacity_);
+ push_state(parse_state::root);
+ state_ = parse_state::start;
+ line_ = 1;
+ column_ = 1;
+ nesting_depth_ = 0;
+ }
+
+ void check_done()
+ {
+ std::error_code ec;
+ check_done(ec);
+ if (ec)
+ {
+ throw parse_error(ec,line_,column_);
+ }
+ }
+
+ void check_done(std::error_code& ec)
+ {
+ if (state_ != parse_state::done)
+ {
+ if (err_handler_.error(json_parser_errc::unexpected_eof, *this))
+ {
+ ec = json_parser_errc::unexpected_eof;
+ return;
+ }
+ }
+ for (; input_ptr_ != input_end_; ++input_ptr_)
+ {
+ CharT curr_char_ = *input_ptr_;
+ switch (curr_char_)
+ {
+ case '\n':
+ case '\r':
+ case '\t':
+ case ' ':
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::extra_character, *this))
+ {
+ ec = json_parser_errc::extra_character;
+ return;
+ }
+ break;
+ }
+ }
+ }
+
+ void parse_some(std::error_code& ec)
+ {
+ const CharT* local_input_end = input_end_;
+
+ while ((input_ptr_ < local_input_end) && (state_ != parse_state::done))
+ {
+ switch (state_)
+ {
+ case parse_state::cr:
+ ++line_;
+ column_ = 1;
+ switch (*input_ptr_)
+ {
+ case '\n':
+ state_ = pop_state();
+ ++input_ptr_;
+ break;
+ default:
+ state_ = pop_state();
+ break;
+ }
+ break;
+ case parse_state::lf:
+ ++line_;
+ column_ = 1;
+ state_ = pop_state();
+ break;
+ case parse_state::start:
+ {
+ handler_.begin_json();
+ switch (*input_ptr_)
+ {
+ JSONCONS_ILLEGAL_CONTROL_CHARACTER:
+ if (err_handler_.error(json_parser_errc::illegal_control_character, *this))
+ {
+ ec = json_parser_errc::illegal_control_character;
+ return;
+ }
+ break;
+ case '\r':
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::cr;
+ break;
+ case '\n':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::lf;
+ break;
+ case ' ':case '\t':
+ skip_whitespace();
+ break;
+ case '/':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::slash;
+ break;
+ case '{':
+ do_begin_object(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '[':
+ do_begin_array(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\"':
+ state_ = parse_state::string_u1;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '-':
+ number_buffer_.clear();
+ is_negative_ = true;
+ precision_ = 0;
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::minus;
+ parse_number(ec);
+ if (ec) {return;}
+ break;
+ case '0':
+ number_buffer_.clear();
+ is_negative_ = false;
+ precision_ = 1;
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ state_ = parse_state::zero;
+ ++input_ptr_;
+ ++column_;
+ parse_number(ec);
+ if (ec) {return;}
+ break;
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.clear();
+ is_negative_ = false;
+ precision_ = 1;
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::integer;
+ parse_number(ec);
+ if (ec) {return;}
+ break;
+ case 'n':
+ parse_null(ec);
+ if (ec) {return;}
+ break;
+ case 't':
+ parse_true(ec);
+ if (ec) {return;}
+ break;
+ case 'f':
+ parse_false(ec);
+ if (ec) {return;}
+ break;
+ case '}':
+ err_handler_.fatal_error(json_parser_errc::unexpected_right_brace, *this);
+ ec = json_parser_errc::unexpected_right_brace;
+ return;
+ case ']':
+ err_handler_.fatal_error(json_parser_errc::unexpected_right_bracket, *this);
+ ec = json_parser_errc::unexpected_right_bracket;
+ return;
+ default:
+ err_handler_.fatal_error(json_parser_errc::invalid_json_text, *this);
+ ec = json_parser_errc::invalid_json_text;
+ return;
+ }
+ }
+ break;
+
+ case parse_state::expect_comma_or_end:
+ {
+ switch (*input_ptr_)
+ {
+ JSONCONS_ILLEGAL_CONTROL_CHARACTER:
+ if (err_handler_.error(json_parser_errc::illegal_control_character, *this))
+ {
+ ec = json_parser_errc::illegal_control_character;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\r':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::cr;
+ break;
+ case '\n':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::lf;
+ break;
+ case ' ':case '\t':
+ skip_whitespace();
+ break;
+ case '/':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::slash;
+ break;
+ case '}':
+ do_end_object(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case ']':
+ do_end_array(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case ',':
+ begin_member_or_element(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ default:
+ if (parent() == parse_state::array)
+ {
+ if (err_handler_.error(json_parser_errc::expected_comma_or_right_bracket, *this))
+ {
+ ec = json_parser_errc::expected_comma_or_right_bracket;
+ return;
+ }
+ }
+ else if (parent() == parse_state::object)
+ {
+ if (err_handler_.error(json_parser_errc::expected_comma_or_right_brace, *this))
+ {
+ ec = json_parser_errc::expected_comma_or_right_brace;
+ return;
+ }
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ }
+ }
+ break;
+ case parse_state::expect_member_name_or_end:
+ {
+ switch (*input_ptr_)
+ {
+ JSONCONS_ILLEGAL_CONTROL_CHARACTER:
+ if (err_handler_.error(json_parser_errc::illegal_control_character, *this))
+ {
+ ec = json_parser_errc::illegal_control_character;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\r':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::cr;
+ break;
+ case '\n':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::lf;
+ break;
+ case ' ':case '\t':
+ skip_whitespace();
+ break;
+ case '/':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::slash;
+ break;
+ case '}':
+ do_end_object(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\"':
+ ++input_ptr_;
+ ++column_;
+ push_state(parse_state::member_name);
+ state_ = parse_state::string_u1;
+ break;
+ case '\'':
+ if (err_handler_.error(json_parser_errc::single_quote, *this))
+ {
+ ec = json_parser_errc::single_quote;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::expected_name, *this))
+ {
+ ec = json_parser_errc::expected_name;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ }
+ }
+ break;
+ case parse_state::expect_member_name:
+ {
+ switch (*input_ptr_)
+ {
+ JSONCONS_ILLEGAL_CONTROL_CHARACTER:
+ if (err_handler_.error(json_parser_errc::illegal_control_character, *this))
+ {
+ ec = json_parser_errc::illegal_control_character;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\r':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::cr;
+ break;
+ case '\n':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::lf;
+ break;
+ case ' ':case '\t':
+ skip_whitespace();
+ break;
+ case '/':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::slash;
+ break;
+ case '\"':
+ ++input_ptr_;
+ ++column_;
+ push_state(parse_state::member_name);
+ state_ = parse_state::string_u1;
+ break;
+ case '}':
+ if (err_handler_.error(json_parser_errc::extra_comma, *this))
+ {
+ ec = json_parser_errc::extra_comma;
+ return;
+ }
+ do_end_object(ec); // Recover
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\'':
+ if (err_handler_.error(json_parser_errc::single_quote, *this))
+ {
+ ec = json_parser_errc::single_quote;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::expected_name, *this))
+ {
+ ec = json_parser_errc::expected_name;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ }
+ }
+ break;
+ case parse_state::expect_colon:
+ {
+ switch (*input_ptr_)
+ {
+ JSONCONS_ILLEGAL_CONTROL_CHARACTER:
+ if (err_handler_.error(json_parser_errc::illegal_control_character, *this))
+ {
+ ec = json_parser_errc::illegal_control_character;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\r':
+ push_state(state_);
+ state_ = parse_state::cr;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\n':
+ push_state(state_);
+ state_ = parse_state::lf;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case ' ':case '\t':
+ skip_whitespace();
+ break;
+ case '/':
+ push_state(state_);
+ state_ = parse_state::slash;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case ':':
+ state_ = parse_state::expect_value;
+ ++input_ptr_;
+ ++column_;
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::expected_colon, *this))
+ {
+ ec = json_parser_errc::expected_colon;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ }
+ }
+ break;
+
+ case parse_state::expect_value:
+ {
+ switch (*input_ptr_)
+ {
+ JSONCONS_ILLEGAL_CONTROL_CHARACTER:
+ if (err_handler_.error(json_parser_errc::illegal_control_character, *this))
+ {
+ ec = json_parser_errc::illegal_control_character;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\r':
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::cr;
+ break;
+ case '\n':
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::lf;
+ break;
+ case ' ':case '\t':
+ skip_whitespace();
+ break;
+ case '/':
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::slash;
+ break;
+ case '{':
+ do_begin_object(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '[':
+ do_begin_array(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\"':
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::string_u1;
+ break;
+ case '-':
+ number_buffer_.clear();
+ is_negative_ = true;
+ precision_ = 0;
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::minus;
+ parse_number(ec);
+ if (ec) {return;}
+ break;
+ case '0':
+ number_buffer_.clear();
+ is_negative_ = false;
+ precision_ = 1;
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::zero;
+ parse_number(ec);
+ if (ec) {return;}
+ break;
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.clear();
+ is_negative_ = false;
+ precision_ = 1;
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::integer;
+ parse_number(ec);
+ if (ec) {return;}
+ break;
+ case 'n':
+ parse_null(ec);
+ if (ec) {return;}
+ break;
+ case 't':
+ parse_true(ec);
+ if (ec) {return;}
+ break;
+ case 'f':
+ parse_false(ec);
+ if (ec) {return;}
+ break;
+ case ']':
+ if (parent() == parse_state::array)
+ {
+ if (err_handler_.error(json_parser_errc::extra_comma, *this))
+ {
+ ec = json_parser_errc::extra_comma;
+ return;
+ }
+ do_end_array(ec); // Recover
+ if (ec) return;
+ }
+ else
+ {
+ if (err_handler_.error(json_parser_errc::expected_value, *this))
+ {
+ ec = json_parser_errc::expected_value;
+ return;
+ }
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\'':
+ if (err_handler_.error(json_parser_errc::single_quote, *this))
+ {
+ ec = json_parser_errc::single_quote;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::expected_value, *this))
+ {
+ ec = json_parser_errc::expected_value;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ }
+ }
+ break;
+ case parse_state::expect_value_or_end:
+ {
+ switch (*input_ptr_)
+ {
+ JSONCONS_ILLEGAL_CONTROL_CHARACTER:
+ if (err_handler_.error(json_parser_errc::illegal_control_character, *this))
+ {
+ ec = json_parser_errc::illegal_control_character;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\r':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::cr;
+ break;
+ case '\n':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::lf;
+ break;
+ case ' ':case '\t':
+ skip_whitespace();
+ break;
+ case '/':
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::slash;
+ break;
+ case '{':
+ do_begin_object(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '[':
+ do_begin_array(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case ']':
+ do_end_array(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ break;
+ case '\"':
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::string_u1;
+ break;
+ case '-':
+ number_buffer_.clear();
+ is_negative_ = true;
+ precision_ = 0;
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::minus;
+ parse_number(ec);
+ if (ec) {return;}
+ break;
+ case '0':
+ number_buffer_.clear();
+ is_negative_ = false;
+ precision_ = 1;
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::zero;
+ parse_number(ec);
+ if (ec) {return;}
+ break;
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.clear();
+ is_negative_ = false;
+ precision_ = 1;
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::integer;
+ parse_number(ec);
+ if (ec) {return;}
+ break;
+ case 'n':
+ parse_null(ec);
+ if (ec) {return;}
+ break;
+ case 't':
+ parse_true(ec);
+ if (ec) {return;}
+ break;
+ case 'f':
+ parse_false(ec);
+ if (ec) {return;}
+ break;
+ case '\'':
+ if (err_handler_.error(json_parser_errc::single_quote, *this))
+ {
+ ec = json_parser_errc::single_quote;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::expected_value, *this))
+ {
+ ec = json_parser_errc::expected_value;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ }
+ }
+ break;
+ case parse_state::string_u1:
+ case parse_state::escape:
+ case parse_state::escape_u1:
+ case parse_state::escape_u2:
+ case parse_state::escape_u3:
+ case parse_state::escape_u4:
+ case parse_state::escape_expect_surrogate_pair1:
+ case parse_state::escape_expect_surrogate_pair2:
+ case parse_state::escape_u6:
+ case parse_state::escape_u7:
+ case parse_state::escape_u8:
+ case parse_state::escape_u9:
+ parse_string(ec);
+ if (ec) return;
+ break;
+ case parse_state::minus:
+ case parse_state::zero:
+ case parse_state::integer:
+ case parse_state::fraction1:
+ case parse_state::fraction2:
+ case parse_state::exp1:
+ case parse_state::exp2:
+ case parse_state::exp3:
+ parse_number(ec);
+ if (ec) return;
+ break;
+ case parse_state::t:
+ switch (*input_ptr_)
+ {
+ case 'r':
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::tr;
+ break;
+ default:
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ break;
+ case parse_state::tr:
+ switch (*input_ptr_)
+ {
+ case 'u':
+ state_ = parse_state::tru;
+ break;
+ default:
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case parse_state::tru:
+ switch (*input_ptr_)
+ {
+ case 'e':
+ handler_.bool_value(true,*this);
+ if (parent() == parse_state::root)
+ {
+ state_ = parse_state::done;
+ handler_.end_json();
+ }
+ else
+ {
+ state_ = parse_state::expect_comma_or_end;
+ }
+ break;
+ default:
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case parse_state::f:
+ switch (*input_ptr_)
+ {
+ case 'a':
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::fa;
+ break;
+ default:
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ break;
+ case parse_state::fa:
+ switch (*input_ptr_)
+ {
+ case 'l':
+ state_ = parse_state::fal;
+ break;
+ default:
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case parse_state::fal:
+ switch (*input_ptr_)
+ {
+ case 's':
+ state_ = parse_state::fals;
+ break;
+ default:
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case parse_state::fals:
+ switch (*input_ptr_)
+ {
+ case 'e':
+ handler_.bool_value(false,*this);
+ if (parent() == parse_state::root)
+ {
+ state_ = parse_state::done;
+ handler_.end_json();
+ }
+ else
+ {
+ state_ = parse_state::expect_comma_or_end;
+ }
+ break;
+ default:
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case parse_state::n:
+ switch (*input_ptr_)
+ {
+ case 'u':
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::nu;
+ break;
+ default:
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ break;
+ case parse_state::nu:
+ switch (*input_ptr_)
+ {
+ case 'l':
+ state_ = parse_state::nul;
+ break;
+ default:
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case parse_state::nul:
+ switch (*input_ptr_)
+ {
+ case 'l':
+ handler_.null_value(*this);
+ if (parent() == parse_state::root)
+ {
+ state_ = parse_state::done;
+ handler_.end_json();
+ }
+ else
+ {
+ state_ = parse_state::expect_comma_or_end;
+ }
+ break;
+ default:
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case parse_state::slash:
+ {
+ switch (*input_ptr_)
+ {
+ case '*':
+ state_ = parse_state::slash_star;
+ if (err_handler_.error(json_parser_errc::illegal_comment, *this))
+ {
+ ec = json_parser_errc::illegal_comment;
+ return;
+ }
+ break;
+ case '/':
+ state_ = parse_state::slash_slash;
+ if (err_handler_.error(json_parser_errc::illegal_comment, *this))
+ {
+ ec = json_parser_errc::illegal_comment;
+ return;
+ }
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::invalid_json_text, *this))
+ {
+ ec = json_parser_errc::invalid_json_text;
+ return;
+ }
+ break;
+ }
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case parse_state::slash_star:
+ {
+ switch (*input_ptr_)
+ {
+ case '\r':
+ push_state(state_);
+ state_ = parse_state::cr;
+ break;
+ case '\n':
+ push_state(state_);
+ state_ = parse_state::lf;
+ break;
+ case '*':
+ state_ = parse_state::slash_star_star;
+ break;
+ }
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ case parse_state::slash_slash:
+ {
+ switch (*input_ptr_)
+ {
+ case '\r':
+ state_ = pop_state();
+ break;
+ case '\n':
+ state_ = pop_state();
+ break;
+ default:
+ ++input_ptr_;
+ ++column_;
+ }
+ }
+ break;
+ case parse_state::slash_star_star:
+ {
+ switch (*input_ptr_)
+ {
+ case '/':
+ state_ = pop_state();
+ break;
+ default:
+ state_ = parse_state::slash_star;
+ break;
+ }
+ }
+ ++input_ptr_;
+ ++column_;
+ break;
+ default:
+ JSONCONS_ASSERT(false);
+ break;
+ }
+ }
+ }
+
+ void parse_true(std::error_code& ec)
+ {
+ if (JSONCONS_LIKELY(input_end_ - input_ptr_ >= 4))
+ {
+ if (*(input_ptr_+1) == 'r' && *(input_ptr_+2) == 'u' && *(input_ptr_+3) == 'e')
+ {
+ handler_.bool_value(true,*this);
+ input_ptr_ += 4;
+ column_ += 4;
+ if (parent() == parse_state::root)
+ {
+ handler_.end_json();
+ state_ = parse_state::done;
+ }
+ else
+ {
+ state_ = parse_state::expect_comma_or_end;
+ }
+ }
+ else
+ {
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ }
+ else
+ {
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::t;
+ }
+ }
+
+ void parse_null(std::error_code& ec)
+ {
+ if (JSONCONS_LIKELY(input_end_ - input_ptr_ >= 4))
+ {
+ if (*(input_ptr_+1) == 'u' && *(input_ptr_+2) == 'l' && *(input_ptr_+3) == 'l')
+ {
+ handler_.null_value(*this);
+ input_ptr_ += 4;
+ column_ += 4;
+ if (parent() == parse_state::root)
+ {
+ handler_.end_json();
+ state_ = parse_state::done;
+ }
+ else
+ {
+ state_ = parse_state::expect_comma_or_end;
+ }
+ }
+ else
+ {
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ }
+ else
+ {
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::n;
+ }
+ }
+
+ void parse_false(std::error_code& ec)
+ {
+ if (JSONCONS_LIKELY(input_end_ - input_ptr_ >= 5))
+ {
+ if (*(input_ptr_+1) == 'a' && *(input_ptr_+2) == 'l' && *(input_ptr_+3) == 's' && *(input_ptr_+4) == 'e')
+ {
+ handler_.bool_value(false,*this);
+ input_ptr_ += 5;
+ column_ += 5;
+ if (parent() == parse_state::root)
+ {
+ handler_.end_json();
+ state_ = parse_state::done;
+ }
+ else
+ {
+ state_ = parse_state::expect_comma_or_end;
+ }
+ }
+ else
+ {
+ err_handler_.error(json_parser_errc::invalid_value, *this);
+ ec = json_parser_errc::invalid_value;
+ return;
+ }
+ }
+ else
+ {
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::f;
+ }
+ }
+
+ void parse_number(std::error_code& ec)
+ {
+ const CharT* local_input_end = input_end_;
+
+ switch (state_)
+ {
+ case parse_state::minus:
+ goto minus_sign;
+ case parse_state::zero:
+ goto zero;
+ case parse_state::integer:
+ goto integer;
+ case parse_state::fraction1:
+ goto fraction1;
+ case parse_state::fraction2:
+ goto fraction2;
+ case parse_state::exp1:
+ goto exp1;
+ case parse_state::exp2:
+ goto exp2;
+ case parse_state::exp3:
+ goto exp3;
+ default:
+ JSONCONS_UNREACHABLE();
+ }
+minus_sign:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::minus;
+ return;
+ }
+ switch (*input_ptr_)
+ {
+ case '0':
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++precision_;
+ ++input_ptr_;
+ ++column_;
+ goto zero;
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++precision_;
+ ++input_ptr_;
+ ++column_;
+ goto integer;
+ default:
+ err_handler_.error(json_parser_errc::expected_value, *this);
+ ec = json_parser_errc::expected_value;
+ return;
+ }
+zero:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::zero;
+ return;
+ }
+ switch (*input_ptr_)
+ {
+ case '\r':
+ end_integer_value(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::cr;
+ return;
+ case '\n':
+ end_integer_value(ec);
+ if (ec) return;
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::lf;
+ return;
+ case ' ':case '\t':
+ end_integer_value(ec);
+ if (ec) return;
+ skip_whitespace();
+ return;
+ case '/':
+ end_integer_value(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::slash;
+ return;
+ case '}':
+ end_integer_value(ec);
+ if (ec) return;
+ do_end_object(ec);
+ ++input_ptr_;
+ ++column_;
+ if (ec) return;
+ return;
+ case ']':
+ end_integer_value(ec);
+ if (ec) return;
+ do_end_array(ec);
+ ++input_ptr_;
+ ++column_;
+ if (ec) return;
+ return;
+ case '.':
+ decimal_places_ = 0;
+ JSONCONS_ASSERT(precision_ == number_buffer_.length());
+ number_buffer_.push_back(to_double_.get_decimal_point());
+ ++input_ptr_;
+ ++column_;
+ goto fraction1;
+ case 'e':case 'E':
+ JSONCONS_ASSERT(precision_ == number_buffer_.length());
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ goto exp1;
+ case ',':
+ end_integer_value(ec);
+ if (ec) return;
+ begin_member_or_element(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ return;
+ case '0': case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ err_handler_.error(json_parser_errc::leading_zero, *this);
+ ec = json_parser_errc::leading_zero;
+ state_ = parse_state::zero;
+ return;
+ default:
+ err_handler_.error(json_parser_errc::invalid_number, *this);
+ ec = json_parser_errc::invalid_number;
+ state_ = parse_state::zero;
+ return;
+ }
+integer:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::integer;
+ return;
+ }
+ switch (*input_ptr_)
+ {
+ case '\r':
+ end_integer_value(ec);
+ if (ec) return;
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::cr;
+ return;
+ case '\n':
+ end_integer_value(ec);
+ if (ec) return;
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::lf;
+ return;
+ case ' ':case '\t':
+ end_integer_value(ec);
+ if (ec) return;
+ skip_whitespace();
+ return;
+ case '/':
+ end_integer_value(ec);
+ if (ec) return;
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::slash;
+ return;
+ case '}':
+ end_integer_value(ec);
+ if (ec) return;
+ do_end_object(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ return;
+ case ']':
+ end_integer_value(ec);
+ if (ec) return;
+ do_end_array(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ return;
+ case '0': case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++precision_;
+ ++input_ptr_;
+ ++column_;
+ goto integer;
+ case '.':
+ decimal_places_ = 0;
+ JSONCONS_ASSERT(precision_ == number_buffer_.length());
+ number_buffer_.push_back(to_double_.get_decimal_point());
+ ++input_ptr_;
+ ++column_;
+ goto fraction1;
+ case 'e':case 'E':
+ JSONCONS_ASSERT(precision_ == number_buffer_.length());
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ goto exp1;
+ case ',':
+ end_integer_value(ec);
+ if (ec) return;
+ begin_member_or_element(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ return;
+ default:
+ err_handler_.error(json_parser_errc::invalid_number, *this);
+ ec = json_parser_errc::invalid_number;
+ state_ = parse_state::integer;
+ return;
+ }
+fraction1:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::fraction1;
+ return;
+ }
+ switch (*input_ptr_)
+ {
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ ++precision_;
+ ++decimal_places_;
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ goto fraction2;
+ default:
+ err_handler_.error(json_parser_errc::invalid_number, *this);
+ ec = json_parser_errc::invalid_number;
+ state_ = parse_state::fraction1;
+ return;
+ }
+fraction2:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::fraction2;
+ return;
+ }
+ switch (*input_ptr_)
+ {
+ case '\r':
+ end_fraction_value(chars_format::fixed,ec);
+ if (ec) return;
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::cr;
+ return;
+ case '\n':
+ end_fraction_value(chars_format::fixed,ec);
+ if (ec) return;
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::lf;
+ return;
+ case ' ':case '\t':
+ end_fraction_value(chars_format::fixed,ec);
+ if (ec) return;
+ skip_whitespace();
+ return;
+ case '/':
+ end_fraction_value(chars_format::fixed,ec);
+ if (ec) return;
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::slash;
+ return;
+ case '}':
+ end_fraction_value(chars_format::fixed,ec);
+ if (ec) return;
+ do_end_object(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ return;
+ case ']':
+ end_fraction_value(chars_format::fixed,ec);
+ if (ec) return;
+ do_end_array(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ return;
+ case ',':
+ end_fraction_value(chars_format::fixed,ec);
+ if (ec) return;
+ begin_member_or_element(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ return;
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ ++precision_;
+ ++decimal_places_;
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ goto fraction2;
+ case 'e':case 'E':
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ goto exp1;
+ default:
+ err_handler_.error(json_parser_errc::invalid_number, *this);
+ ec = json_parser_errc::invalid_number;
+ state_ = parse_state::fraction2;
+ return;
+ }
+exp1:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::exp1;
+ return;
+ }
+ switch (*input_ptr_)
+ {
+ case '+':
+ ++input_ptr_;
+ ++column_;
+ goto exp2;
+ case '-':
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ goto exp2;
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ goto exp3;
+ default:
+ err_handler_.error(json_parser_errc::expected_value, *this);
+ ec = json_parser_errc::expected_value;
+ state_ = parse_state::exp1;
+ return;
+ }
+exp2:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::exp2;
+ return;
+ }
+ switch (*input_ptr_)
+ {
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ goto exp3;
+ default:
+ err_handler_.error(json_parser_errc::expected_value, *this);
+ ec = json_parser_errc::expected_value;
+ state_ = parse_state::exp2;
+ return;
+ }
+
+exp3:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::exp3;
+ return;
+ }
+ switch (*input_ptr_)
+ {
+ case '\r':
+ end_fraction_value(chars_format::scientific,ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::cr;
+ return;
+ case '\n':
+ end_fraction_value(chars_format::scientific,ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ push_state(state_);
+ state_ = parse_state::lf;
+ return;
+ case ' ':case '\t':
+ end_fraction_value(chars_format::scientific,ec);
+ if (ec) return;
+ skip_whitespace();
+ return;
+ case '/':
+ end_fraction_value(chars_format::scientific,ec);
+ if (ec) return;
+ push_state(state_);
+ ++input_ptr_;
+ ++column_;
+ state_ = parse_state::slash;
+ return;
+ case '}':
+ end_fraction_value(chars_format::scientific,ec);
+ if (ec) return;
+ do_end_object(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ return;
+ case ']':
+ end_fraction_value(chars_format::scientific,ec);
+ if (ec) return;
+ do_end_array(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ return;
+ case ',':
+ end_fraction_value(chars_format::scientific,ec);
+ if (ec) return;
+ begin_member_or_element(ec);
+ if (ec) return;
+ ++input_ptr_;
+ ++column_;
+ return;
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*input_ptr_));
+ ++input_ptr_;
+ ++column_;
+ goto exp3;
+ default:
+ err_handler_.error(json_parser_errc::invalid_number, *this);
+ ec = json_parser_errc::invalid_number;
+ state_ = parse_state::exp3;
+ return;
+ }
+
+ JSONCONS_UNREACHABLE();
+ }
+
+ void parse_string(std::error_code& ec)
+ {
+ const CharT* local_input_end = input_end_;
+ const CharT* sb = input_ptr_;
+
+ switch (state_)
+ {
+ case parse_state::string_u1:
+ goto string_u1;
+ case parse_state::escape:
+ goto escape;
+ case parse_state::escape_u1:
+ goto escape_u1;
+ case parse_state::escape_u2:
+ goto escape_u2;
+ case parse_state::escape_u3:
+ goto escape_u3;
+ case parse_state::escape_u4:
+ goto escape_u4;
+ case parse_state::escape_expect_surrogate_pair1:
+ goto escape_expect_surrogate_pair1;
+ case parse_state::escape_expect_surrogate_pair2:
+ goto escape_expect_surrogate_pair2;
+ case parse_state::escape_u6:
+ goto escape_u6;
+ case parse_state::escape_u7:
+ goto escape_u7;
+ case parse_state::escape_u8:
+ goto escape_u8;
+ case parse_state::escape_u9:
+ goto escape_u9;
+ default:
+ JSONCONS_UNREACHABLE();
+ }
+
+string_u1:
+ while (input_ptr_ < local_input_end)
+ {
+ switch (*input_ptr_)
+ {
+ JSONCONS_ILLEGAL_CONTROL_CHARACTER:
+ {
+ column_ += (input_ptr_ - sb + 1);
+ if (err_handler_.error(json_parser_errc::illegal_control_character, *this))
+ {
+ ec = json_parser_errc::illegal_control_character;
+ state_ = parse_state::string_u1;
+ return;
+ }
+ // recovery - skip
+ auto result = unicons::validate(sb,input_ptr_);
+ if (result.ec != unicons::conv_errc())
+ {
+ translate_conv_errc(result.ec,ec);
+ column_ += (result.it - sb);
+ return;
+ }
+ string_buffer_.append(sb,input_ptr_-sb);
+ ++input_ptr_;
+ state_ = parse_state::string_u1;
+ return;
+ }
+ case '\r':
+ {
+ column_ += (input_ptr_ - sb + 1);
+ if (err_handler_.error(json_parser_errc::illegal_character_in_string, *this))
+ {
+ ec = json_parser_errc::illegal_character_in_string;
+ state_ = parse_state::string_u1;
+ return;
+ }
+ // recovery - keep
+ auto result = unicons::validate(sb,input_ptr_);
+ if (result.ec != unicons::conv_errc())
+ {
+ translate_conv_errc(result.ec,ec);
+ column_ += (result.it - sb);
+ return;
+ }
+ string_buffer_.append(sb, input_ptr_ - sb + 1);
+ ++input_ptr_;
+ push_state(state_);
+ state_ = parse_state::cr;
+ return;
+ }
+ case '\n':
+ {
+ column_ += (input_ptr_ - sb + 1);
+ if (err_handler_.error(json_parser_errc::illegal_character_in_string, *this))
+ {
+ ec = json_parser_errc::illegal_character_in_string;
+ state_ = parse_state::string_u1;
+ return;
+ }
+ // recovery - keep
+ auto result = unicons::validate(sb,input_ptr_);
+ if (result.ec != unicons::conv_errc())
+ {
+ translate_conv_errc(result.ec,ec);
+ column_ += (result.it - sb);
+ return;
+ }
+ string_buffer_.append(sb, input_ptr_ - sb + 1);
+ ++input_ptr_;
+ push_state(state_);
+ state_ = parse_state::lf;
+ return;
+ }
+ case '\t':
+ {
+ column_ += (input_ptr_ - sb + 1);
+ if (err_handler_.error(json_parser_errc::illegal_character_in_string, *this))
+ {
+ ec = json_parser_errc::illegal_character_in_string;
+ state_ = parse_state::string_u1;
+ return;
+ }
+ // recovery - keep
+ auto result = unicons::validate(sb,input_ptr_);
+ if (result.ec != unicons::conv_errc())
+ {
+ translate_conv_errc(result.ec,ec);
+ column_ += (result.it - sb);
+ return;
+ }
+ string_buffer_.append(sb, input_ptr_ - sb + 1);
+ ++input_ptr_;
+ state_ = parse_state::string_u1;
+ return;
+ }
+ case '\\':
+ {
+ auto result = unicons::validate(sb,input_ptr_);
+ if (result.ec != unicons::conv_errc())
+ {
+ translate_conv_errc(result.ec,ec);
+ column_ += (result.it - sb);
+ return;
+ }
+ string_buffer_.append(sb,input_ptr_-sb);
+ column_ += (input_ptr_ - sb + 1);
+ ++input_ptr_;
+ goto escape;
+ }
+ case '\"':
+ {
+ auto result = unicons::validate(sb,input_ptr_);
+ if (result.ec != unicons::conv_errc())
+ {
+ translate_conv_errc(result.ec,ec);
+ column_ += (result.it - sb);
+ return;
+ }
+ if (string_buffer_.length() == 0)
+ {
+ end_string_value(sb,input_ptr_-sb, ec);
+ if (ec) {return;}
+ }
+ else
+ {
+ string_buffer_.append(sb,input_ptr_-sb);
+ end_string_value(string_buffer_.data(),string_buffer_.length(), ec);
+ string_buffer_.clear();
+ if (ec) {return;}
+ }
+ column_ += (input_ptr_ - sb + 1);
+ ++input_ptr_;
+ return;
+ }
+ default:
+ break;
+ }
+ ++input_ptr_;
+ }
+
+ // Buffer exhausted
+ {
+ auto result = unicons::validate(sb,input_ptr_);
+ if (result.ec != unicons::conv_errc())
+ {
+ translate_conv_errc(result.ec,ec);
+ column_ += (result.it - sb);
+ return;
+ }
+ string_buffer_.append(sb,input_ptr_-sb);
+ column_ += (input_ptr_ - sb + 1);
+ state_ = parse_state::string_u1;
+ return;
+ }
+
+escape:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape;
+ return;
+ }
+ switch (*input_ptr_)
+ {
+ case '\"':
+ string_buffer_.push_back('\"');
+ sb = ++input_ptr_;
+ ++column_;
+ goto string_u1;
+ case '\\':
+ string_buffer_.push_back('\\');
+ sb = ++input_ptr_;
+ ++column_;
+ goto string_u1;
+ case '/':
+ string_buffer_.push_back('/');
+ sb = ++input_ptr_;
+ ++column_;
+ goto string_u1;
+ case 'b':
+ string_buffer_.push_back('\b');
+ sb = ++input_ptr_;
+ ++column_;
+ goto string_u1;
+ case 'f':
+ string_buffer_.push_back('\f');
+ sb = ++input_ptr_;
+ ++column_;
+ goto string_u1;
+ case 'n':
+ string_buffer_.push_back('\n');
+ sb = ++input_ptr_;
+ ++column_;
+ goto string_u1;
+ case 'r':
+ string_buffer_.push_back('\r');
+ sb = ++input_ptr_;
+ ++column_;
+ goto string_u1;
+ case 't':
+ string_buffer_.push_back('\t');
+ sb = ++input_ptr_;
+ ++column_;
+ goto string_u1;
+ case 'u':
+ cp_ = 0;
+ ++input_ptr_;
+ ++column_;
+ goto escape_u1;
+ default:
+ err_handler_.error(json_parser_errc::illegal_escaped_character, *this);
+ ec = json_parser_errc::illegal_escaped_character;
+ state_ = parse_state::escape;
+ return;
+ }
+
+escape_u1:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape_u1;
+ return;
+ }
+ {
+ append_codepoint(*input_ptr_,ec);
+ if (ec)
+ {
+ state_ = parse_state::escape_u1;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ goto escape_u2;
+ }
+
+escape_u2:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape_u2;
+ return;
+ }
+ {
+ append_codepoint(*input_ptr_, ec);
+ if (ec)
+ {
+ state_ = parse_state::escape_u2;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ goto escape_u3;
+ }
+
+escape_u3:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape_u3;
+ return;
+ }
+ {
+ append_codepoint(*input_ptr_, ec);
+ if (ec)
+ {
+ state_ = parse_state::escape_u3;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ goto escape_u4;
+ }
+
+escape_u4:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape_u4;
+ return;
+ }
+ {
+ append_codepoint(*input_ptr_, ec);
+ if (ec)
+ {
+ state_ = parse_state::escape_u4;
+ return;
+ }
+ if (unicons::is_high_surrogate(cp_))
+ {
+ ++input_ptr_;
+ ++column_;
+ goto escape_expect_surrogate_pair1;
+ }
+ else
+ {
+ unicons::convert(&cp_, &cp_ + 1, std::back_inserter(string_buffer_));
+ sb = ++input_ptr_;
+ ++column_;
+ state_ = parse_state::string_u1;
+ return;
+ }
+ }
+
+escape_expect_surrogate_pair1:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape_expect_surrogate_pair1;
+ return;
+ }
+ {
+ switch (*input_ptr_)
+ {
+ case '\\':
+ cp2_ = 0;
+ ++input_ptr_;
+ ++column_;
+ goto escape_expect_surrogate_pair2;
+ default:
+ err_handler_.error(json_parser_errc::expected_codepoint_surrogate_pair, *this);
+ ec = json_parser_errc::expected_codepoint_surrogate_pair;
+ state_ = parse_state::escape_expect_surrogate_pair1;
+ return;
+ }
+ }
+
+escape_expect_surrogate_pair2:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape_expect_surrogate_pair2;
+ return;
+ }
+ {
+ switch (*input_ptr_)
+ {
+ case 'u':
+ ++input_ptr_;
+ ++column_;
+ goto escape_u6;
+ default:
+ err_handler_.error(json_parser_errc::expected_codepoint_surrogate_pair, *this);
+ ec = json_parser_errc::expected_codepoint_surrogate_pair;
+ state_ = parse_state::escape_expect_surrogate_pair2;
+ return;
+ }
+ }
+
+escape_u6:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape_u6;
+ return;
+ }
+ {
+ append_second_codepoint(*input_ptr_, ec);
+ if (ec)
+ {
+ state_ = parse_state::escape_u6;
+ return;
+ }
+ }
+ ++input_ptr_;
+ ++column_;
+ goto escape_u7;
+
+escape_u7:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape_u7;
+ return;
+ }
+ {
+ append_second_codepoint(*input_ptr_, ec);
+ if (ec)
+ {
+ state_ = parse_state::escape_u7;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ goto escape_u8;
+ }
+
+escape_u8:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape_u8;
+ return;
+ }
+ {
+ append_second_codepoint(*input_ptr_, ec);
+ if (ec)
+ {
+ state_ = parse_state::escape_u8;
+ return;
+ }
+ ++input_ptr_;
+ ++column_;
+ goto escape_u9;
+ }
+
+escape_u9:
+ if (JSONCONS_UNLIKELY(input_ptr_ >= local_input_end)) // Buffer exhausted
+ {
+ state_ = parse_state::escape_u9;
+ return;
+ }
+ {
+ append_second_codepoint(*input_ptr_, ec);
+ if (ec)
+ {
+ state_ = parse_state::escape_u9;
+ return;
+ }
+ uint32_t cp = 0x10000 + ((cp_ & 0x3FF) << 10) + (cp2_ & 0x3FF);
+ unicons::convert(&cp, &cp + 1, std::back_inserter(string_buffer_));
+ sb = ++input_ptr_;
+ ++column_;
+ goto string_u1;
+ }
+
+ JSONCONS_UNREACHABLE();
+ }
+
+ void translate_conv_errc(unicons::conv_errc result, std::error_code& ec)
+ {
+ switch (result)
+ {
+ case unicons::conv_errc():
+ break;
+ case unicons::conv_errc::over_long_utf8_sequence:
+ if (err_handler_.error(json_parser_errc::over_long_utf8_sequence, *this))
+ {
+ ec = json_parser_errc::over_long_utf8_sequence;
+ return;
+ }
+ break;
+ case unicons::conv_errc::unpaired_high_surrogate:
+ if (err_handler_.error(json_parser_errc::unpaired_high_surrogate, *this))
+ {
+ ec = json_parser_errc::unpaired_high_surrogate;
+ return;
+ }
+ break;
+ case unicons::conv_errc::expected_continuation_byte:
+ if (err_handler_.error(json_parser_errc::expected_continuation_byte, *this))
+ {
+ ec = json_parser_errc::expected_continuation_byte;
+ return;
+ }
+ break;
+ case unicons::conv_errc::illegal_surrogate_value:
+ if (err_handler_.error(json_parser_errc::illegal_surrogate_value, *this))
+ {
+ ec = json_parser_errc::illegal_surrogate_value;
+ return;
+ }
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::illegal_codepoint, *this))
+ {
+ ec = json_parser_errc::illegal_codepoint;
+ return;
+ }
+ break;
+ }
+ }
+
+ void parse_some()
+ {
+ std::error_code ec;
+ parse_some(ec);
+ if (ec)
+ {
+ throw parse_error(ec,line_,column_);
+ }
+ }
+
+ void end_parse()
+ {
+ std::error_code ec;
+ end_parse(ec);
+ if (ec)
+ {
+ throw parse_error(ec,line_,column_);
+ }
+ }
+
+ void end_parse(std::error_code& ec)
+ {
+ if (parent() == parse_state::root)
+ {
+ switch (state_)
+ {
+ case parse_state::zero:
+ case parse_state::integer:
+ end_integer_value(ec);
+ if (ec) return;
+ break;
+ case parse_state::fraction2:
+ end_fraction_value(chars_format::fixed,ec);
+ if (ec) return;
+ break;
+ case parse_state::exp3:
+ end_fraction_value(chars_format::scientific,ec);
+ if (ec) return;
+ break;
+ default:
+ break;
+ }
+ }
+ if (state_ == parse_state::lf || state_ == parse_state::cr)
+ {
+ state_ = pop_state();
+ }
+ if (!(state_ == parse_state::done || state_ == parse_state::start))
+ {
+ if (err_handler_.error(json_parser_errc::unexpected_eof, *this))
+ {
+ ec = json_parser_errc::unexpected_eof;
+ return;
+ }
+ }
+ }
+
+ parse_state state() const
+ {
+ return state_;
+ }
+
+ void set_source(const CharT* input, size_t length)
+ {
+ begin_input_ = input;
+ input_end_ = input + length;
+ input_ptr_ = begin_input_;
+ }
+private:
+
+ void end_integer_value(std::error_code& ec)
+ {
+ if (is_negative_)
+ {
+ end_negative_value(ec);
+ }
+ else
+ {
+ end_positive_value(ec);
+ }
+ }
+
+ void end_negative_value(std::error_code& ec)
+ {
+ static const int64_t min_value = (std::numeric_limits<int64_t>::min)();
+ static const int64_t min_value_div_10 = min_value / 10;
+
+ const char* s = number_buffer_.data();
+ size_t length = number_buffer_.length();
+ int64_t n = 0;
+ bool overflow = false;
+ const char* end = s + length;
+ for (; s < end; ++s)
+ {
+ int64_t x = *s - '0';
+ if (n < min_value_div_10)
+ {
+ overflow = true;
+ break;
+ }
+ n = n * 10;
+ if (n < min_value + x)
+ {
+ overflow = true;
+ break;
+ }
+
+ n -= x;
+ }
+
+ if (!overflow)
+ {
+ handler_.integer_value(n, *this);
+
+ switch (parent())
+ {
+ case parse_state::array:
+ case parse_state::object:
+ state_ = parse_state::expect_comma_or_end;
+ break;
+ case parse_state::root:
+ state_ = parse_state::done;
+ handler_.end_json();
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::invalid_json_text, *this))
+ {
+ ec = json_parser_errc::invalid_json_text;
+ return;
+ }
+ break;
+ }
+ }
+ else
+ {
+ end_fraction_value(chars_format::general,ec);
+ }
+ }
+
+ void end_positive_value(std::error_code& ec)
+ {
+ static const uint64_t max_value = (std::numeric_limits<uint64_t>::max)();
+ static const uint64_t max_value_div_10 = max_value / 10;
+ uint64_t n = 0;
+ bool overflow = false;
+ const char* s = number_buffer_.data();
+ size_t length = number_buffer_.length();
+
+ const char* end = s + length;
+ for (; s < end; ++s)
+ {
+ uint64_t x = *s - '0';
+ if (n > max_value_div_10)
+ {
+ overflow = true;
+ break;
+ }
+ n = n * 10;
+ if (n > max_value - x)
+ {
+ overflow = true;
+ break;
+ }
+
+ n += x;
+ }
+
+ if (!overflow)
+ {
+ handler_.uinteger_value(n, *this);
+
+ switch (parent())
+ {
+ case parse_state::array:
+ case parse_state::object:
+ state_ = parse_state::expect_comma_or_end;
+ break;
+ case parse_state::root:
+ state_ = parse_state::done;
+ handler_.end_json();
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::invalid_json_text, *this))
+ {
+ ec = json_parser_errc::invalid_json_text;
+ return;
+ }
+ break;
+ }
+ }
+ else
+ {
+ end_fraction_value(chars_format::general,ec);
+ }
+ }
+
+ void end_fraction_value(chars_format format, std::error_code& ec)
+ {
+ try
+ {
+ double d = to_double_(number_buffer_.c_str(), number_buffer_.length());
+ if (is_negative_)
+ d = -d;
+
+ if (precision_ > std::numeric_limits<double>::max_digits10)
+ {
+ handler_.double_value(d, number_format(format,std::numeric_limits<double>::max_digits10, decimal_places_), *this);
+ }
+ else
+ {
+ handler_.double_value(d, number_format(format,static_cast<uint8_t>(precision_), decimal_places_), *this);
+ }
+ }
+ catch (...)
+ {
+ if (err_handler_.error(json_parser_errc::invalid_number, *this))
+ {
+ ec = json_parser_errc::invalid_number;
+ return;
+ }
+ handler_.null_value(*this); // recovery
+ }
+
+ switch (parent())
+ {
+ case parse_state::array:
+ case parse_state::object:
+ state_ = parse_state::expect_comma_or_end;
+ break;
+ case parse_state::root:
+ state_ = parse_state::done;
+ handler_.end_json();
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::invalid_json_text, *this))
+ {
+ ec = json_parser_errc::invalid_json_text;
+ return;
+ }
+ break;
+ }
+ }
+
+ void append_codepoint(int c, std::error_code& ec)
+ {
+ switch (c)
+ {
+ case '0': case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
+ case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
+ cp_ = append_to_codepoint(cp_, c, ec);
+ if (ec) return;
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::expected_value, *this))
+ {
+ ec = json_parser_errc::expected_value;
+ return;
+ }
+ break;
+ }
+ }
+
+ void append_second_codepoint(int c, std::error_code& ec)
+ {
+ switch (c)
+ {
+ case '0':
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
+ case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
+ cp2_ = append_to_codepoint(cp2_, c, ec);
+ if (ec) return;
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::expected_value, *this))
+ {
+ ec = json_parser_errc::expected_value;
+ return;
+ }
+ break;
+ }
+ }
+
+ void end_string_value(const CharT* s, size_t length, std::error_code& ec)
+ {
+ switch (parent())
+ {
+ case parse_state::member_name:
+ handler_.name(string_view_type(s, length), *this);
+ state_ = pop_state();
+ state_ = parse_state::expect_colon;
+ break;
+ case parse_state::object:
+ case parse_state::array:
+ handler_.string_value(string_view_type(s, length), *this);
+ state_ = parse_state::expect_comma_or_end;
+ break;
+ case parse_state::root:
+ handler_.string_value(string_view_type(s, length), *this);
+ state_ = parse_state::done;
+ handler_.end_json();
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::invalid_json_text, *this))
+ {
+ ec = json_parser_errc::invalid_json_text;
+ return;
+ }
+ break;
+ }
+ }
+
+ void begin_member_or_element(std::error_code& ec)
+ {
+ switch (parent())
+ {
+ case parse_state::object:
+ state_ = parse_state::expect_member_name;
+ break;
+ case parse_state::array:
+ state_ = parse_state::expect_value;
+ break;
+ case parse_state::root:
+ break;
+ default:
+ if (err_handler_.error(json_parser_errc::invalid_json_text, *this))
+ {
+ ec = json_parser_errc::invalid_json_text;
+ return;
+ }
+ break;
+ }
+ }
+
+ void push_state(parse_state state)
+ {
+ state_stack_.push_back(state);
+ }
+
+ parse_state pop_state()
+ {
+ JSONCONS_ASSERT(!state_stack_.empty())
+ parse_state state = state_stack_.back();
+ state_stack_.pop_back();
+ return state;
+ }
+
+ uint32_t append_to_codepoint(uint32_t cp, int c, std::error_code& ec)
+ {
+ cp *= 16;
+ if (c >= '0' && c <= '9')
+ {
+ cp += c - '0';
+ }
+ else if (c >= 'a' && c <= 'f')
+ {
+ cp += c - 'a' + 10;
+ }
+ else if (c >= 'A' && c <= 'F')
+ {
+ cp += c - 'A' + 10;
+ }
+ else
+ {
+ if (err_handler_.error(json_parser_errc::invalid_hex_escape_sequence, *this))
+ {
+ ec = json_parser_errc::invalid_hex_escape_sequence;
+ return cp;
+ }
+ }
+ return cp;
+ }
+
+ size_t do_line_number() const override
+ {
+ return line_;
+ }
+
+ size_t do_column_number() const override
+ {
+ return column_;
+ }
+};
+
+typedef basic_json_parser<char> json_parser;
+typedef basic_json_parser<wchar_t> wjson_parser;
+
+}
+
+#endif
+
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_reader.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_reader.hpp
new file mode 100644
index 00000000..d419e2d8
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_reader.hpp
@@ -0,0 +1,408 @@
+// Copyright 2015 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_READER_HPP
+#define JSONCONS_JSON_READER_HPP
+
+#include <memory>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <stdexcept>
+#include <system_error>
+#include <ios>
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/json_input_handler.hpp>
+#include <jsoncons/parse_error_handler.hpp>
+#include <jsoncons/json_parser.hpp>
+
+namespace jsoncons {
+
+// utf8_other_json_input_adapter
+
+template <class CharT>
+class json_utf8_other_input_handler_adapter : public json_input_handler
+{
+public:
+ using json_input_handler::string_view_type;
+private:
+ basic_null_json_input_handler<CharT> default_input_handler_;
+ basic_json_input_handler<CharT>& other_handler_;
+ //parse_error_handler& err_handler_;
+
+ // noncopyable and nonmoveable
+ json_utf8_other_input_handler_adapter<CharT>(const json_utf8_other_input_handler_adapter<CharT>&) = delete;
+ json_utf8_other_input_handler_adapter<CharT>& operator=(const json_utf8_other_input_handler_adapter<CharT>&) = delete;
+
+public:
+ json_utf8_other_input_handler_adapter()
+ : other_handler_(default_input_handler_)
+ {
+ }
+
+ json_utf8_other_input_handler_adapter(basic_json_input_handler<CharT>& other_handler/*,
+ parse_error_handler& err_handler*/)
+ : other_handler_(other_handler)/*,
+ err_handler_(err_handler)*/
+ {
+ }
+
+private:
+
+ void do_begin_json() override
+ {
+ other_handler_.begin_json();
+ }
+
+ void do_end_json() override
+ {
+ other_handler_.end_json();
+ }
+
+ void do_begin_object(const parsing_context& context) override
+ {
+ other_handler_.begin_object(context);
+ }
+
+ void do_end_object(const parsing_context& context) override
+ {
+ other_handler_.end_object(context);
+ }
+
+ void do_begin_array(const parsing_context& context) override
+ {
+ other_handler_.begin_array(context);
+ }
+
+ void do_end_array(const parsing_context& context) override
+ {
+ other_handler_.end_array(context);
+ }
+
+ void do_name(const string_view_type& name, const parsing_context& context) override
+ {
+ std::basic_string<CharT> target;
+ auto result = unicons::convert(
+ name.begin(), name.end(), std::back_inserter(target),
+ unicons::conv_flags::strict);
+ if (result.ec != unicons::conv_errc())
+ {
+ throw parse_error(result.ec,context.line_number(),context.column_number());
+ }
+ other_handler_.name(target, context);
+ }
+
+ void do_string_value(const string_view_type& value, const parsing_context& context) override
+ {
+ std::basic_string<CharT> target;
+ auto result = unicons::convert(
+ value.begin(), value.end(), std::back_inserter(target),
+ unicons::conv_flags::strict);
+ if (result.ec != unicons::conv_errc())
+ {
+ throw parse_error(result.ec,context.line_number(),context.column_number());
+ }
+ other_handler_.string_value(target, context);
+ }
+
+ void do_integer_value(int64_t value, const parsing_context& context) override
+ {
+ other_handler_.integer_value(value, context);
+ }
+
+ void do_uinteger_value(uint64_t value, const parsing_context& context) override
+ {
+ other_handler_.uinteger_value(value, context);
+ }
+
+ void do_double_value(double value, const number_format& fmt, const parsing_context& context) override
+ {
+ other_handler_.double_value(value, fmt, context);
+ }
+
+ void do_bool_value(bool value, const parsing_context& context) override
+ {
+ other_handler_.bool_value(value, context);
+ }
+
+ void do_null_value(const parsing_context& context) override
+ {
+ other_handler_.null_value(context);
+ }
+};
+
+template<class CharT,class Allocator=std::allocator<char>>
+class basic_json_reader
+{
+ static const size_t default_max_buffer_length = 16384;
+
+ typedef CharT char_type;
+ typedef Allocator allocator_type;
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<CharT> char_allocator_type;
+
+ basic_json_parser<CharT,Allocator> parser_;
+ std::basic_istream<CharT>& is_;
+ bool eof_;
+ std::vector<CharT,char_allocator_type> buffer_;
+ size_t buffer_length_;
+ bool begin_;
+
+ // Noncopyable and nonmoveable
+ basic_json_reader(const basic_json_reader&) = delete;
+ basic_json_reader& operator=(const basic_json_reader&) = delete;
+
+public:
+
+ basic_json_reader(std::basic_istream<CharT>& is)
+ : parser_(),
+ is_(is),
+ eof_(false),
+ buffer_length_(default_max_buffer_length),
+ begin_(true)
+ {
+ buffer_.reserve(buffer_length_);
+ }
+
+ basic_json_reader(std::basic_istream<CharT>& is,
+ parse_error_handler& err_handler)
+ : parser_(err_handler),
+ is_(is),
+ eof_(false),
+ buffer_length_(default_max_buffer_length),
+ begin_(true)
+ {
+ buffer_.reserve(buffer_length_);
+ }
+
+ basic_json_reader(std::basic_istream<CharT>& is,
+ basic_json_input_handler<CharT>& handler)
+ : parser_(handler),
+ is_(is),
+ eof_(false),
+ buffer_length_(default_max_buffer_length),
+ begin_(true)
+ {
+ buffer_.reserve(buffer_length_);
+ }
+
+ basic_json_reader(std::basic_istream<CharT>& is,
+ basic_json_input_handler<CharT>& handler,
+ parse_error_handler& err_handler)
+ : parser_(handler,err_handler),
+ is_(is),
+ eof_(false),
+ buffer_length_(default_max_buffer_length),
+ begin_(true)
+ {
+ buffer_.reserve(buffer_length_);
+ }
+
+ size_t buffer_length() const
+ {
+ return buffer_length_;
+ }
+
+ void buffer_length(size_t length)
+ {
+ buffer_length_ = length;
+ buffer_.reserve(buffer_length_);
+ }
+
+ size_t max_nesting_depth() const
+ {
+ return parser_.max_nesting_depth();
+ }
+
+ void max_nesting_depth(size_t depth)
+ {
+ parser_.max_nesting_depth(depth);
+ }
+
+ void read_next()
+ {
+ std::error_code ec;
+ read_next(ec);
+ if (ec)
+ {
+ throw parse_error(ec,parser_.line_number(),parser_.column_number());
+ }
+ }
+
+ void read_buffer(std::error_code& ec)
+ {
+ buffer_.clear();
+ buffer_.resize(buffer_length_);
+ is_.read(buffer_.data(), buffer_length_);
+ buffer_.resize(static_cast<size_t>(is_.gcount()));
+ if (buffer_.size() == 0)
+ {
+ eof_ = true;
+ }
+ else if (begin_)
+ {
+ auto result = unicons::skip_bom(buffer_.begin(), buffer_.end());
+ if (result.ec != unicons::encoding_errc())
+ {
+ ec = result.ec;
+ return;
+ }
+ size_t offset = result.it - buffer_.begin();
+ parser_.set_source(buffer_.data()+offset,buffer_.size()-offset);
+ begin_ = false;
+ }
+ else
+ {
+ parser_.set_source(buffer_.data(),buffer_.size());
+ }
+ }
+
+ void read_next(std::error_code& ec)
+ {
+ parser_.reset();
+ while (!eof_ && !parser_.done())
+ {
+ if (parser_.source_exhausted())
+ {
+ if (!is_.eof())
+ {
+ if (is_.fail())
+ {
+ ec = json_parser_errc::source_error;
+ return;
+ }
+ read_buffer(ec);
+ if (ec) return;
+ }
+ else
+ {
+ eof_ = true;
+ }
+ }
+ if (!eof_)
+ {
+ parser_.parse_some(ec);
+ if (ec) return;
+ }
+ }
+ if (eof_)
+ {
+ parser_.end_parse(ec);
+ if (ec) return;
+ }
+ }
+
+ void check_done()
+ {
+ std::error_code ec;
+ check_done(ec);
+ if (ec)
+ {
+ throw parse_error(ec,parser_.line_number(),parser_.column_number());
+ }
+ }
+
+ size_t line_number() const
+ {
+ return parser_.line_number();
+ }
+
+ size_t column_number() const
+ {
+ return parser_.column_number();
+ }
+
+ void check_done(std::error_code& ec)
+ {
+ if (eof_)
+ {
+ parser_.check_done(ec);
+ if (ec) return;
+ }
+ else
+ {
+ while (!eof_)
+ {
+ if (parser_.source_exhausted())
+ {
+ if (!is_.eof())
+ {
+ if (is_.fail())
+ {
+ ec = json_parser_errc::source_error;
+ return;
+ }
+ read_buffer(ec);
+ if (ec) return;
+ }
+ else
+ {
+ eof_ = true;
+ }
+ }
+ if (!eof_)
+ {
+ parser_.check_done(ec);
+ if (ec) return;
+ }
+ }
+ }
+ }
+
+ bool eof() const
+ {
+ return eof_;
+ }
+
+ void read()
+ {
+ read_next();
+ check_done();
+ }
+
+ void read(std::error_code& ec)
+ {
+ read_next(ec);
+ if (!ec)
+ {
+ check_done(ec);
+ }
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+
+ size_t buffer_capacity() const
+ {
+ return buffer_length_;
+ }
+
+ void buffer_capacity(size_t length)
+ {
+ buffer_length_ = length;
+ buffer_.reserve(buffer_length_);
+ }
+ size_t max_depth() const
+ {
+ return parser_.max_nesting_depth();
+ }
+
+ void max_depth(size_t depth)
+ {
+ parser_.max_nesting_depth(depth);
+ }
+#endif
+
+private:
+};
+
+typedef basic_json_reader<char> json_reader;
+typedef basic_json_reader<wchar_t> wjson_reader;
+
+}
+
+#endif
+
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_serializer.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_serializer.hpp
new file mode 100644
index 00000000..42538671
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_serializer.hpp
@@ -0,0 +1,585 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_SERIALIZER_HPP
+#define JSONCONS_JSON_SERIALIZER_HPP
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <cstdlib>
+#include <limits> // std::numeric_limits
+#include <fstream>
+#include <memory>
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/jsoncons_utilities.hpp>
+#include <jsoncons/serialization_options.hpp>
+#include <jsoncons/json_output_handler.hpp>
+#include <jsoncons/detail/writer.hpp>
+#include <jsoncons/detail/number_printers.hpp>
+
+namespace jsoncons {
+
+template<class CharT,class Writer=detail::ostream_buffered_writer<CharT>>
+class basic_json_serializer final : public basic_json_output_handler<CharT>
+{
+public:
+ using typename basic_json_output_handler<CharT>::string_view_type;
+ typedef Writer writer_type;
+ typedef typename Writer::output_type output_type;
+
+private:
+ static const size_t default_buffer_length = 16384;
+
+ struct stack_item
+ {
+ stack_item(bool is_object)
+ : is_object_(is_object), count_(0), split_lines_(line_split_kind::same_line), indent_once_(false), unindent_at_end_(false)
+ {
+ }
+ stack_item(bool is_object, line_split_kind split_lines, bool indent_once = false)
+ : is_object_(is_object), count_(0), split_lines_(split_lines), indent_once_(indent_once), unindent_at_end_(false)
+ {
+ }
+
+ size_t count() const
+ {
+ return count_;
+ }
+
+ bool unindent_at_end() const
+ {
+ return unindent_at_end_;
+ }
+
+ bool is_object() const
+ {
+ return is_object_;
+ }
+
+ bool is_new_line() const
+ {
+ return split_lines_ != line_split_kind::same_line;
+ }
+
+ bool is_multi_line() const
+ {
+ return split_lines_ == line_split_kind::multi_line;
+ }
+
+ bool is_indent_once() const
+ {
+ return count_ == 0 ? indent_once_ : false;
+ }
+
+ bool is_object_;
+ size_t count_;
+ line_split_kind split_lines_;
+ bool indent_once_;
+ bool unindent_at_end_;
+ };
+ basic_serialization_options<CharT> options_;
+ std::vector<stack_item> stack_;
+ int indent_;
+ bool indenting_;
+ detail::print_double fp_;
+ Writer writer_;
+
+ // Noncopyable and nonmoveable
+ basic_json_serializer(const basic_json_serializer&) = delete;
+ basic_json_serializer& operator=(const basic_json_serializer&) = delete;
+public:
+ basic_json_serializer(output_type& os)
+ : indent_(0),
+ indenting_(false),
+ fp_(options_.precision()),
+ writer_(os)
+ {
+ }
+
+ basic_json_serializer(output_type& os, bool pprint)
+ : indent_(0),
+ indenting_(pprint),
+ fp_(options_.precision()),
+ writer_(os)
+ {
+ }
+
+ basic_json_serializer(output_type& os, const basic_serialization_options<CharT>& options)
+ : options_(options),
+ indent_(0),
+ indenting_(false),
+ fp_(options_.precision()),
+ writer_(os)
+ {
+ }
+ basic_json_serializer(output_type& os, const basic_serialization_options<CharT>& options, bool pprint)
+ : options_(options),
+ indent_(0),
+ indenting_(pprint),
+ fp_(options_.precision()),
+ writer_(os)
+ {
+ }
+
+ ~basic_json_serializer()
+ {
+ }
+
+private:
+ void escape_string(const CharT* s,
+ size_t length,
+ const basic_serialization_options<CharT>& options,
+ writer_type& writer)
+ {
+ const CharT* begin = s;
+ const CharT* end = s + length;
+ for (const CharT* it = begin; it != end; ++it)
+ {
+ CharT c = *it;
+ switch (c)
+ {
+ case '\\':
+ writer.put('\\');
+ writer.put('\\');
+ break;
+ case '"':
+ writer.put('\\');
+ writer.put('\"');
+ break;
+ case '\b':
+ writer.put('\\');
+ writer.put('b');
+ break;
+ case '\f':
+ writer.put('\\');
+ writer.put('f');
+ break;
+ case '\n':
+ writer.put('\\');
+ writer.put('n');
+ break;
+ case '\r':
+ writer.put('\\');
+ writer.put('r');
+ break;
+ case '\t':
+ writer.put('\\');
+ writer.put('t');
+ break;
+ default:
+ if (options.escape_solidus() && c == '/')
+ {
+ writer.put('\\');
+ writer.put('/');
+ }
+ else if (is_control_character(c) || options.escape_all_non_ascii())
+ {
+ // convert utf8 to codepoint
+ unicons::sequence_generator<const CharT*> g(it,end,unicons::conv_flags::strict);
+ if (g.done() || g.status() != unicons::conv_errc())
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Invalid codepoint"));
+ }
+ uint32_t cp = g.get().codepoint();
+ it += (g.get().length() - 1);
+ if (is_non_ascii_codepoint(cp) || is_control_character(c))
+ {
+ if (cp > 0xFFFF)
+ {
+ cp -= 0x10000;
+ uint32_t first = (cp >> 10) + 0xD800;
+ uint32_t second = ((cp & 0x03FF) + 0xDC00);
+
+ writer.put('\\');
+ writer.put('u');
+ writer.put(to_hex_character(first >> 12 & 0x000F));
+ writer.put(to_hex_character(first >> 8 & 0x000F));
+ writer.put(to_hex_character(first >> 4 & 0x000F));
+ writer.put(to_hex_character(first & 0x000F));
+ writer.put('\\');
+ writer.put('u');
+ writer.put(to_hex_character(second >> 12 & 0x000F));
+ writer.put(to_hex_character(second >> 8 & 0x000F));
+ writer.put(to_hex_character(second >> 4 & 0x000F));
+ writer.put(to_hex_character(second & 0x000F));
+ }
+ else
+ {
+ writer.put('\\');
+ writer.put('u');
+ writer.put(to_hex_character(cp >> 12 & 0x000F));
+ writer.put(to_hex_character(cp >> 8 & 0x000F));
+ writer.put(to_hex_character(cp >> 4 & 0x000F));
+ writer.put(to_hex_character(cp & 0x000F));
+ }
+ }
+ else
+ {
+ writer.put(c);
+ }
+ }
+ else
+ {
+ writer.put(c);
+ }
+ break;
+ }
+ }
+ }
+ // Implementing methods
+ void do_begin_json() override
+ {
+ }
+
+ void do_end_json() override
+ {
+ writer_.flush();
+ }
+
+ void do_begin_object() override
+ {
+ if (!stack_.empty() && !stack_.back().is_object())
+ {
+ if (!stack_.empty())
+ {
+ if (stack_.back().count_ > 0)
+ {
+ writer_. put(',');
+ }
+ }
+ }
+
+ if (indenting_)
+ {
+ if (!stack_.empty() && stack_.back().is_object())
+ {
+ stack_.push_back(stack_item(true,options_.object_object_split_lines(), false));
+ }
+ else if (!stack_.empty())
+ {
+ if (options_.array_object_split_lines() != line_split_kind::same_line)
+ {
+ stack_.back().unindent_at_end_ = true;
+ stack_.push_back(stack_item(true,options_.array_object_split_lines(), false));
+ write_indent1();
+ }
+ else
+ {
+ stack_.push_back(stack_item(true,options_.array_object_split_lines(), false));
+ }
+ }
+ else
+ {
+ stack_.push_back(stack_item(true, line_split_kind::multi_line, false));
+ }
+ indent();
+ }
+ else
+ {
+ stack_.push_back(stack_item(true));
+ }
+ writer_.put('{');
+ }
+
+ void do_end_object() override
+ {
+ JSONCONS_ASSERT(!stack_.empty());
+ if (indenting_)
+ {
+ unindent();
+ if (stack_.back().unindent_at_end())
+ {
+ write_indent();
+ }
+ }
+ stack_.pop_back();
+ writer_.put('}');
+
+ end_value();
+ }
+
+
+ void do_begin_array() override
+ {
+ if (!stack_.empty() && !stack_.back().is_object())
+ {
+ if (!stack_.empty())
+ {
+ if (stack_.back().count_ > 0)
+ {
+ writer_. put(',');
+ }
+ }
+ }
+ if (indenting_)
+ {
+ if (!stack_.empty() && stack_.back().is_object())
+ {
+ writer_.put('[');
+ indent();
+ if (options_.object_array_split_lines() != line_split_kind::same_line)
+ {
+ stack_.push_back(stack_item(false,options_.object_array_split_lines(),true));
+ }
+ else
+ {
+ stack_.push_back(stack_item(false,options_.object_array_split_lines(),false));
+ }
+ }
+ else if (!stack_.empty())
+ {
+ if (options_.array_array_split_lines() != line_split_kind::same_line)
+ {
+ write_indent();
+ }
+ stack_.push_back(stack_item(false,options_.array_array_split_lines(), false));
+ indent();
+ writer_.put('[');
+ }
+ else
+ {
+ stack_.push_back(stack_item(false, line_split_kind::multi_line, false));
+ indent();
+ writer_.put('[');
+ }
+ }
+ else
+ {
+ stack_.push_back(stack_item(false));
+ writer_.put('[');
+ }
+ }
+
+ void do_end_array() override
+ {
+ JSONCONS_ASSERT(!stack_.empty());
+ if (indenting_)
+ {
+ unindent();
+ if (stack_.back().unindent_at_end())
+ {
+ write_indent();
+ }
+ }
+ stack_.pop_back();
+ writer_.put(']');
+ end_value();
+ }
+
+ void do_name(const string_view_type& name) override
+ {
+ if (!stack_.empty())
+ {
+ if (stack_.back().count_ > 0)
+ {
+ writer_. put(',');
+ }
+ if (indenting_)
+ {
+ if (stack_.back().is_multi_line())
+ {
+ write_indent();
+ }
+ }
+ }
+
+ writer_.put('\"');
+ escape_string(name.data(), name.length(), options_, writer_);
+ writer_.put('\"');
+ writer_.put(':');
+ if (indenting_)
+ {
+ writer_.put(' ');
+ }
+ }
+
+ void do_null_value() override
+ {
+ if (!stack_.empty() && !stack_.back().is_object())
+ {
+ begin_scalar_value();
+ }
+
+ auto buf = detail::null_literal<CharT>();
+ writer_.write(buf, 4);
+
+ end_value();
+ }
+
+ void do_string_value(const string_view_type& value) override
+ {
+ if (!stack_.empty() && !stack_.back().is_object())
+ {
+ begin_scalar_value();
+ }
+
+ writer_. put('\"');
+ escape_string(value.data(), value.length(), options_, writer_);
+ writer_. put('\"');
+
+ end_value();
+ }
+
+ void do_byte_string_value(const uint8_t* data, size_t length) override
+ {
+ std::basic_string<CharT> s;
+ encode_base64url(data,data+length,s);
+ do_string_value(s);
+ }
+
+ void do_double_value(double value, const number_format& fmt) override
+ {
+ if (!stack_.empty() && !stack_.back().is_object())
+ {
+ begin_scalar_value();
+ }
+
+ if ((std::isnan)(value))
+ {
+ writer_.write(options_.nan_replacement());
+ }
+ else if (value == std::numeric_limits<double>::infinity())
+ {
+ writer_.write(options_.pos_inf_replacement());
+ }
+ else if (!(std::isfinite)(value))
+ {
+ writer_.write(options_.neg_inf_replacement());
+ }
+ else
+ {
+ fp_(value, fmt.precision(), writer_);
+ }
+
+ end_value();
+ }
+
+ void do_integer_value(int64_t value) override
+ {
+ if (!stack_.empty() && !stack_.back().is_object())
+ {
+ begin_scalar_value();
+ }
+ detail::print_integer(value, writer_);
+ end_value();
+ }
+
+ void do_uinteger_value(uint64_t value) override
+ {
+ if (!stack_.empty() && !stack_.back().is_object())
+ {
+ begin_scalar_value();
+ }
+ detail::print_uinteger(value, writer_);
+ end_value();
+ }
+
+ void do_bool_value(bool value) override
+ {
+ if (!stack_.empty() && !stack_.back().is_object())
+ {
+ begin_scalar_value();
+ }
+
+ if (value)
+ {
+ auto buf = detail::true_literal<CharT>();
+ writer_.write(buf,4);
+ }
+ else
+ {
+ auto buf = detail::false_literal<CharT>();
+ writer_.write(buf,5);
+ }
+
+ end_value();
+ }
+
+ void begin_scalar_value()
+ {
+ if (!stack_.empty())
+ {
+ if (stack_.back().count_ > 0)
+ {
+ writer_. put(',');
+ }
+ if (indenting_)
+ {
+ if (stack_.back().is_multi_line() || stack_.back().is_indent_once())
+ {
+ write_indent();
+ }
+ }
+ }
+ }
+
+ void begin_value()
+ {
+ if (!stack_.empty())
+ {
+ if (stack_.back().count_ > 0)
+ {
+ writer_. put(',');
+ }
+ if (indenting_)
+ {
+ if (stack_.back().is_new_line())
+ {
+ write_indent();
+ }
+ }
+ }
+ }
+
+ void end_value()
+ {
+ if (!stack_.empty())
+ {
+ ++stack_.back().count_;
+ }
+ }
+
+ void indent()
+ {
+ indent_ += static_cast<int>(options_.indent());
+ }
+
+ void unindent()
+ {
+ indent_ -= static_cast<int>(options_.indent());
+ }
+
+ void write_indent()
+ {
+ if (!stack_.empty())
+ {
+ stack_.back().unindent_at_end_ = true;
+ }
+ writer_. put('\n');
+ for (int i = 0; i < indent_; ++i)
+ {
+ writer_. put(' ');
+ }
+ }
+
+ void write_indent1()
+ {
+ writer_. put('\n');
+ for (int i = 0; i < indent_; ++i)
+ {
+ writer_. put(' ');
+ }
+ }
+};
+
+typedef basic_json_serializer<char,detail::ostream_buffered_writer<char>> json_serializer;
+typedef basic_json_serializer<wchar_t, detail::ostream_buffered_writer<wchar_t>> wjson_serializer;
+
+}
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_structures.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_structures.hpp
new file mode 100644
index 00000000..74aa1507
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_structures.hpp
@@ -0,0 +1,1864 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_STRUCTURES_HPP
+#define JSONCONS_JSON_STRUCTURES_HPP
+
+#include <string>
+#include <vector>
+#include <deque>
+#include <exception>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <algorithm>
+#include <sstream>
+#include <iomanip>
+#include <utility>
+#include <initializer_list>
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/jsoncons_utilities.hpp>
+#include <jsoncons/json_type_traits.hpp>
+
+namespace jsoncons {
+
+// json_array
+
+template <class Json>
+class Json_array_base_
+{
+public:
+ typedef typename Json::allocator_type allocator_type;
+
+public:
+ Json_array_base_()
+ : self_allocator_()
+ {
+ }
+ Json_array_base_(const allocator_type& allocator)
+ : self_allocator_(allocator)
+ {
+ }
+
+ allocator_type get_allocator() const
+ {
+ return self_allocator_;
+ }
+
+ allocator_type self_allocator_;
+};
+
+// json_array
+
+template <class Json>
+class json_array: public Json_array_base_<Json>
+{
+public:
+ typedef typename Json::allocator_type allocator_type;
+ typedef Json value_type;
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<value_type> val_allocator_type;
+
+ typedef typename Json::array_storage_type array_storage_type;
+
+ typedef typename array_storage_type::iterator iterator;
+ typedef typename array_storage_type::const_iterator const_iterator;
+
+ typedef typename std::iterator_traits<iterator>::reference reference;
+ typedef typename std::iterator_traits<const_iterator>::reference const_reference;
+
+ using Json_array_base_<Json>::get_allocator;
+
+ json_array()
+ : Json_array_base_<Json>(),
+ elements_()
+ {
+ }
+
+ explicit json_array(const allocator_type& allocator)
+ : Json_array_base_<Json>(allocator),
+ elements_(val_allocator_type(allocator))
+ {
+ }
+
+ explicit json_array(size_t n,
+ const allocator_type& allocator = allocator_type())
+ : Json_array_base_<Json>(allocator),
+ elements_(n,Json(),val_allocator_type(allocator))
+ {
+ }
+
+ explicit json_array(size_t n,
+ const Json& value,
+ const allocator_type& allocator = allocator_type())
+ : Json_array_base_<Json>(allocator),
+ elements_(n,value,val_allocator_type(allocator))
+ {
+ }
+
+ template <class InputIterator>
+ json_array(InputIterator begin, InputIterator end, const allocator_type& allocator = allocator_type())
+ : Json_array_base_<Json>(allocator),
+ elements_(begin,end,val_allocator_type(allocator))
+ {
+ }
+ json_array(const json_array& val)
+ : Json_array_base_<Json>(val.get_allocator()),
+ elements_(val.elements_)
+ {
+ }
+ json_array(const json_array& val, const allocator_type& allocator)
+ : Json_array_base_<Json>(allocator),
+ elements_(val.elements_,val_allocator_type(allocator))
+ {
+ }
+
+ json_array(json_array&& val) JSONCONS_NOEXCEPT
+ : Json_array_base_<Json>(val.get_allocator()),
+ elements_(std::move(val.elements_))
+ {
+ }
+ json_array(json_array&& val, const allocator_type& allocator)
+ : Json_array_base_<Json>(allocator),
+ elements_(std::move(val.elements_),val_allocator_type(allocator))
+ {
+ }
+
+ json_array(std::initializer_list<Json> init)
+ : Json_array_base_<Json>(),
+ elements_(std::move(init))
+ {
+ }
+
+ json_array(std::initializer_list<Json> init,
+ const allocator_type& allocator)
+ : Json_array_base_<Json>(allocator),
+ elements_(std::move(init),val_allocator_type(allocator))
+ {
+ }
+ ~json_array()
+ {
+ }
+
+ void swap(json_array<Json>& val)
+ {
+ elements_.swap(val.elements_);
+ }
+
+ size_t size() const {return elements_.size();}
+
+ size_t capacity() const {return elements_.capacity();}
+
+ void clear() {elements_.clear();}
+
+ void shrink_to_fit()
+ {
+ for (size_t i = 0; i < elements_.size(); ++i)
+ {
+ elements_[i].shrink_to_fit();
+ }
+ elements_.shrink_to_fit();
+ }
+
+ void reserve(size_t n) {elements_.reserve(n);}
+
+ void resize(size_t n) {elements_.resize(n);}
+
+ void resize(size_t n, const Json& val) {elements_.resize(n,val);}
+
+ void remove_range(size_t from_index, size_t to_index)
+ {
+ JSONCONS_ASSERT(from_index <= to_index);
+ JSONCONS_ASSERT(to_index <= elements_.size());
+ elements_.erase(elements_.begin()+from_index,elements_.begin()+to_index);
+ }
+
+ void erase(const_iterator pos)
+ {
+ elements_.erase(pos);
+ }
+
+ void erase(const_iterator first, const_iterator last)
+ {
+ elements_.erase(first,last);
+ }
+
+ Json& operator[](size_t i) {return elements_[i];}
+
+ const Json& operator[](size_t i) const {return elements_[i];}
+
+ // push_back
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<is_stateless<A>::value,void>::type
+ push_back(T&& value)
+ {
+ elements_.emplace_back(std::forward<T>(value));
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!is_stateless<A>::value,void>::type
+ push_back(T&& value)
+ {
+ elements_.emplace_back(std::forward<T>(value),get_allocator());
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<is_stateless<A>::value,iterator>::type
+ insert(const_iterator pos, T&& value)
+ {
+#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 9
+ // work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54577
+ iterator it = elements_.begin() + (pos - elements_.begin());
+ return elements_.emplace(it, std::forward<T>(value));
+#else
+ return elements_.emplace(pos, std::forward<T>(value));
+#endif
+ }
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!is_stateless<A>::value,iterator>::type
+ insert(const_iterator pos, T&& value)
+ {
+#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 9
+ // work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54577
+ iterator it = elements_.begin() + (pos - elements_.begin());
+ return elements_.emplace(it, std::forward<T>(value), get_allocator());
+#else
+ return elements_.emplace(pos, std::forward<T>(value), get_allocator());
+#endif
+ }
+
+ template <class InputIt>
+ iterator insert(const_iterator pos, InputIt first, InputIt last)
+ {
+#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 9
+ // work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54577
+ iterator it = elements_.begin() + (pos - elements_.begin());
+ return elements_.insert(it, first, last);
+#else
+ return elements_.insert(pos, first, last);
+#endif
+ }
+
+#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 9
+ // work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54577
+ template <class A=allocator_type, class... Args>
+ typename std::enable_if<is_stateless<A>::value,iterator>::type
+ emplace(const_iterator pos, Args&&... args)
+ {
+ iterator it = elements_.begin() + (pos - elements_.begin());
+ return elements_.emplace(it, std::forward<Args>(args)...);
+ }
+#else
+ template <class A=allocator_type, class... Args>
+ typename std::enable_if<is_stateless<A>::value,iterator>::type
+ emplace(const_iterator pos, Args&&... args)
+ {
+ return elements_.emplace(pos, std::forward<Args>(args)...);
+ }
+#endif
+ template <class... Args>
+ Json& emplace_back(Args&&... args)
+ {
+ elements_.emplace_back(std::forward<Args>(args)...);
+ return elements_.back();
+ }
+
+ iterator begin() {return elements_.begin();}
+
+ iterator end() {return elements_.end();}
+
+ const_iterator begin() const {return elements_.begin();}
+
+ const_iterator end() const {return elements_.end();}
+
+ bool operator==(const json_array<Json>& rhs) const
+ {
+ if (size() != rhs.size())
+ {
+ return false;
+ }
+ for (size_t i = 0; i < size(); ++i)
+ {
+ if (elements_[i] != rhs.elements_[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+private:
+ array_storage_type elements_;
+
+ json_array& operator=(const json_array<Json>&) = delete;
+};
+
+// json_object
+
+template <class BidirectionalIt,class BinaryPredicate>
+BidirectionalIt last_wins_unique_sequence(BidirectionalIt first, BidirectionalIt last, BinaryPredicate compare)
+{
+
+ if (first == last)
+ {
+ return last;
+ }
+
+ typedef typename BidirectionalIt::value_type value_type;
+ typedef typename BidirectionalIt::pointer pointer;
+ std::vector<value_type> dups;
+ {
+ std::vector<pointer> v(std::distance(first,last));
+ auto p = v.begin();
+ for (auto it = first; it != last; ++it)
+ {
+ *p++ = &(*it);
+ }
+ std::sort(v.begin(), v.end(), [&](pointer a, pointer b){return compare(*a,*b)<0;});
+ auto it = v.begin();
+ auto end = v.end();
+ for (auto begin = it+1; begin != end; ++it, ++begin)
+ {
+ if (compare(*(*it),*(*begin)) == 0)
+ {
+ dups.push_back(*(*it));
+ }
+ }
+ }
+ if (dups.size() == 0)
+ {
+ return last;
+ }
+
+ auto it = last;
+ for (auto p = first; p != last && p != it; )
+ {
+ bool no_dup = true;
+ if (dups.size() > 0)
+ {
+ for (auto q = dups.begin(); no_dup && q != dups.end();)
+ {
+ if (compare(*p,*q) == 0)
+ {
+ dups.erase(q);
+ no_dup = false;
+ }
+ else
+ {
+ ++q;
+ }
+ }
+ }
+ if (!no_dup)
+ {
+ --it;
+ for (auto r = p; r != it; ++r)
+ {
+ *r = std::move(*(r+1));
+ }
+ }
+ else
+ {
+ ++p;
+ }
+ }
+
+ return it;
+}
+
+template <class KeyT, class ValueT>
+class key_value_pair
+{
+public:
+ typedef KeyT key_storage_type;
+ typedef typename KeyT::value_type char_type;
+ typedef typename KeyT::allocator_type allocator_type;
+ typedef typename ValueT::string_view_type string_view_type;
+
+ key_value_pair()
+ {
+ }
+
+ key_value_pair(const key_storage_type& name, const ValueT& val)
+ : key_(name), value_(val)
+ {
+ }
+
+ template <class T>
+ key_value_pair(key_storage_type&& name, T&& val)
+ : key_(std::forward<key_storage_type>(name)),
+ value_(std::forward<T>(val))
+ {
+ }
+
+ template <class T>
+ key_value_pair(key_storage_type&& name,
+ T&& val,
+ const allocator_type& allocator)
+ : key_(std::forward<key_storage_type>(name)), value_(std::forward<T>(val), allocator)
+ {
+ }
+
+ key_value_pair(const key_value_pair& member)
+ : key_(member.key_), value_(member.value_)
+ {
+ }
+
+ key_value_pair(key_value_pair&& member)
+ : key_(std::move(member.key_)), value_(std::move(member.value_))
+ {
+ }
+
+ string_view_type key() const
+ {
+ return string_view_type(key_.data(),key_.size());
+ }
+
+ ValueT& value()
+ {
+ return value_;
+ }
+
+ const ValueT& value() const
+ {
+ return value_;
+ }
+
+ template <class T>
+ void value(T&& value)
+ {
+ value_ = std::forward<T>(value);
+ }
+
+ void swap(key_value_pair& member)
+ {
+ key_.swap(member.key_);
+ value_.swap(member.value_);
+ }
+
+ key_value_pair& operator=(const key_value_pair& member)
+ {
+ if (this != & member)
+ {
+ key_ = member.key_;
+ value_ = member.value_;
+ }
+ return *this;
+ }
+
+ key_value_pair& operator=(key_value_pair&& member)
+ {
+ if (this != &member)
+ {
+ key_.swap(member.key_);
+ value_.swap(member.value_);
+ }
+ return *this;
+ }
+
+ void shrink_to_fit()
+ {
+ key_.shrink_to_fit();
+ value_.shrink_to_fit();
+ }
+#if !defined(JSONCONS_NO_DEPRECATED)
+ const key_storage_type& name() const
+ {
+ return key_;
+ }
+#endif
+private:
+ key_storage_type key_;
+ ValueT value_;
+};
+
+template <class KeyT,class Json>
+class Json_object_
+{
+public:
+ typedef typename Json::allocator_type allocator_type;
+ typedef typename Json::char_type char_type;
+ typedef typename Json::char_allocator_type char_allocator_type;
+ typedef KeyT key_storage_type;
+ typedef typename Json::string_view_type string_view_type;
+ typedef key_value_pair<KeyT,Json> value_type;
+
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<value_type> kvp_allocator_type;
+ typedef typename Json::object_storage_type object_storage_type;
+
+ typedef typename object_storage_type::iterator iterator;
+ typedef typename object_storage_type::const_iterator const_iterator;
+
+protected:
+ allocator_type self_allocator_;
+ object_storage_type members_;
+public:
+ Json_object_()
+ : self_allocator_(), members_()
+ {
+ }
+ Json_object_(const allocator_type& allocator)
+ : self_allocator_(allocator),
+ members_(kvp_allocator_type(allocator))
+ {
+ }
+
+ Json_object_(const Json_object_& val)
+ : self_allocator_(val.get_allocator()), members_(val.members_)
+ {
+ }
+
+ Json_object_(Json_object_&& val)
+ : self_allocator_(val.get_allocator()),
+ members_(std::move(val.members_))
+ {
+ }
+
+ Json_object_(const Json_object_& val, const allocator_type& allocator) :
+ self_allocator_(allocator),
+ members_(val.members_,kvp_allocator_type(allocator))
+ {
+ }
+
+ Json_object_(Json_object_&& val,const allocator_type& allocator) :
+ self_allocator_(allocator), members_(std::move(val.members_),kvp_allocator_type(allocator))
+ {
+ }
+
+ void swap(Json_object_& val)
+ {
+ members_.swap(val.members_);
+ }
+
+ allocator_type get_allocator() const
+ {
+ return this->self_allocator_;
+ }
+};
+
+// json_object
+
+template <class KeyT,class Json,bool PreserveOrder>
+class json_object
+{
+};
+
+// Do not preserve order
+template <class KeyT,class Json>
+class json_object<KeyT,Json,false> final : public Json_object_<KeyT,Json>
+{
+public:
+ using typename Json_object_<KeyT,Json>::allocator_type;
+ using typename Json_object_<KeyT,Json>::char_type;
+ using typename Json_object_<KeyT,Json>::char_allocator_type;
+ using typename Json_object_<KeyT,Json>::key_storage_type;
+ using typename Json_object_<KeyT,Json>::string_view_type;
+ using typename Json_object_<KeyT,Json>::value_type;
+ using typename Json_object_<KeyT,Json>::kvp_allocator_type;
+ using typename Json_object_<KeyT,Json>::object_storage_type;
+ using typename Json_object_<KeyT,Json>::iterator;
+ using typename Json_object_<KeyT,Json>::const_iterator;
+ using Json_object_<KeyT,Json>::get_allocator;
+
+ json_object()
+ : Json_object_<KeyT,Json>()
+ {
+ }
+ json_object(const allocator_type& allocator)
+ : Json_object_<KeyT,Json>(allocator)
+ {
+ }
+
+ json_object(const json_object& val)
+ : Json_object_<KeyT,Json>(val)
+ {
+ }
+
+ json_object(json_object&& val)
+ : Json_object_<KeyT,Json>(std::forward<json_object>(val))
+ {
+ }
+
+ json_object(const json_object& val, const allocator_type& allocator)
+ : Json_object_<KeyT,Json>(val,allocator)
+ {
+ }
+
+ json_object(json_object&& val,const allocator_type& allocator)
+ : Json_object_<KeyT,Json>(std::forward<json_object>(val),allocator)
+ {
+ }
+
+ json_object(std::initializer_list<std::pair<string_view_type,Json>> init)
+ : Json_object_<KeyT,Json>()
+ {
+ this->members_.reserve(init.size());
+ for (auto& item : init)
+ {
+ insert_or_assign(item.first, std::move(item.second));
+ }
+ }
+
+ json_object(std::initializer_list<std::pair<string_view_type,Json>> init,
+ const allocator_type& allocator)
+ : Json_object_<KeyT,Json>(allocator)
+ {
+ this->members_.reserve(init.size());
+ for (auto& item : init)
+ {
+ insert_or_assign(item.first, std::move(item.second), allocator);
+ }
+ }
+
+ void swap(json_object& val)
+ {
+ Json_object_<KeyT,Json>::swap(val);
+ }
+
+ iterator begin()
+ {
+ return this->members_.begin();
+ }
+
+ iterator end()
+ {
+ return this->members_.end();
+ }
+
+ const_iterator begin() const
+ {
+ return this->members_.begin();
+ }
+
+ const_iterator end() const
+ {
+ return this->members_.end();
+ }
+
+ size_t size() const {return this->members_.size();}
+
+ size_t capacity() const {return this->members_.capacity();}
+
+ void clear() {this->members_.clear();}
+
+ void shrink_to_fit()
+ {
+ for (size_t i = 0; i < this->members_.size(); ++i)
+ {
+ this->members_[i].shrink_to_fit();
+ }
+ this->members_.shrink_to_fit();
+ }
+
+ void reserve(size_t n) {this->members_.reserve(n);}
+
+ Json& at(size_t i)
+ {
+ if (i >= this->members_.size())
+ {
+ JSONCONS_THROW(json_exception_impl<std::out_of_range>("Invalid array subscript"));
+ }
+ return this->members_[i].value();
+ }
+
+ const Json& at(size_t i) const
+ {
+ if (i >= this->members_.size())
+ {
+ JSONCONS_THROW(json_exception_impl<std::out_of_range>("Invalid array subscript"));
+ }
+ return this->members_[i].value();
+ }
+
+ iterator find(const string_view_type& name)
+ {
+ auto it = std::lower_bound(this->members_.begin(),this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ auto result = (it != this->members_.end() && it->key() == name) ? it : this->members_.end();
+ return result;
+ }
+
+ const_iterator find(const string_view_type& name) const
+ {
+ auto it = std::lower_bound(this->members_.begin(),this->members_.end(),
+ name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ auto result = (it != this->members_.end() && it->key() == name) ? it : this->members_.end();
+ return result;
+ }
+
+ void erase(const_iterator pos)
+ {
+ this->members_.erase(pos);
+ }
+
+ void erase(const_iterator first, const_iterator last)
+ {
+ this->members_.erase(first,last);
+ }
+
+ void erase(const string_view_type& name)
+ {
+ auto it = std::lower_bound(this->members_.begin(),this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ if (it != this->members_.end() && it->key() == name)
+ {
+ this->members_.erase(it);
+ }
+ }
+
+ template<class InputIt, class UnaryPredicate>
+ void insert(InputIt first, InputIt last, UnaryPredicate pred)
+ {
+ size_t count = std::distance(first,last);
+ this->members_.reserve(this->members_.size() + count);
+ for (auto s = first; s != last; ++s)
+ {
+ this->members_.emplace_back(pred(*s));
+ }
+ std::stable_sort(this->members_.begin(),this->members_.end(),
+ [](const value_type& a, const value_type& b){return a.key().compare(b.key()) < 0;});
+ auto it = std::unique(this->members_.rbegin(), this->members_.rend(),
+ [](const value_type& a, const value_type& b){ return !(a.key().compare(b.key()));});
+ this->members_.erase(this->members_.begin(),it.base());
+ }
+
+ // merge
+
+ void merge(const json_object& source)
+ {
+ for (auto it = source.begin(); it != source.end(); ++it)
+ {
+ try_emplace(it->key(),it->value());
+ }
+ }
+
+ void merge(json_object&& source)
+ {
+ auto it = std::make_move_iterator(source.begin());
+ auto end = std::make_move_iterator(source.end());
+ for (; it != end; ++it)
+ {
+ auto pos = std::lower_bound(this->members_.begin(),this->members_.end(), it->key(),
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ if (pos == this->members_.end() )
+ {
+ this->members_.emplace_back(*it);
+ }
+ else if (it->key() != pos->key())
+ {
+ this->members_.emplace(pos,*it);
+ }
+ }
+ }
+
+ void merge(iterator hint, const json_object& source)
+ {
+ for (auto it = source.begin(); it != source.end(); ++it)
+ {
+ hint = try_emplace(hint, it->key(),it->value());
+ }
+ }
+
+ void merge(iterator hint, json_object&& source)
+ {
+ auto it = std::make_move_iterator(source.begin());
+ auto end = std::make_move_iterator(source.end());
+ for (; it != end; ++it)
+ {
+ iterator pos;
+ if (hint != this->members_.end() && hint->key() <= it->key())
+ {
+ pos = std::lower_bound(hint,this->members_.end(), it->key(),
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+ else
+ {
+ pos = std::lower_bound(this->members_.begin(),this->members_.end(), it->key(),
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+ if (pos == this->members_.end() )
+ {
+ this->members_.emplace_back(*it);
+ hint = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else if (it->key() != pos->key())
+ {
+ hint = this->members_.emplace(pos,*it);
+ }
+ }
+ }
+
+ // merge_or_update
+
+ void merge_or_update(const json_object& source)
+ {
+ for (auto it = source.begin(); it != source.end(); ++it)
+ {
+ insert_or_assign(it->key(),it->value());
+ }
+ }
+
+ void merge_or_update(json_object&& source)
+ {
+ auto it = std::make_move_iterator(source.begin());
+ auto end = std::make_move_iterator(source.end());
+ for (; it != end; ++it)
+ {
+ auto pos = std::lower_bound(this->members_.begin(),this->members_.end(), it->key(),
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ if (pos == this->members_.end() )
+ {
+ this->members_.emplace_back(*it);
+ }
+ else
+ {
+ pos->value(it->value());
+ }
+ }
+ }
+
+ void merge_or_update(iterator hint, const json_object& source)
+ {
+ for (auto it = source.begin(); it != source.end(); ++it)
+ {
+ hint = insert_or_assign(hint, it->key(),it->value());
+ }
+ }
+
+ void merge_or_update(iterator hint, json_object&& source)
+ {
+ auto it = std::make_move_iterator(source.begin());
+ auto end = std::make_move_iterator(source.end());
+ for (; it != end; ++it)
+ {
+ iterator pos;
+ if (hint != this->members_.end() && hint->key() <= it->key())
+ {
+ pos = std::lower_bound(hint,this->members_.end(), it->key(),
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+ else
+ {
+ pos = std::lower_bound(this->members_.begin(),this->members_.end(), it->key(),
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+ if (pos == this->members_.end() )
+ {
+ this->members_.emplace_back(*it);
+ hint = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else
+ {
+ pos->value(it->value());
+ hint = pos;
+ }
+ }
+ }
+
+ // insert_or_assign
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<is_stateless<A>::value,std::pair<iterator,bool>>::type
+ insert_or_assign(const string_view_type& name, T&& value)
+ {
+ bool inserted;
+ auto it = std::lower_bound(this->members_.begin(),this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(name.begin(),name.end()),
+ std::forward<T>(value));
+ inserted = true;
+ it = this->members_.begin() + this->members_.size() - 1;
+ }
+ else if (it->key() == name)
+ {
+ it->value(Json(std::forward<T>(value)));
+ inserted = false; // assigned
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ key_storage_type(name.begin(),name.end()),
+ std::forward<T>(value));
+ inserted = true;
+ }
+ return std::make_pair(it,inserted);
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!is_stateless<A>::value,std::pair<iterator,bool>>::type
+ insert_or_assign(const string_view_type& name, T&& value)
+ {
+ bool inserted;
+ auto it = std::lower_bound(this->members_.begin(),this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(name.begin(),name.end(), get_allocator()),
+ std::forward<T>(value),get_allocator());
+ inserted = true;
+ it = this->members_.begin() + this->members_.size() - 1;
+ }
+ else if (it->key() == name)
+ {
+ it->value(Json(std::forward<T>(value), get_allocator()));
+ inserted = false; // assigned
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ key_storage_type(name.begin(),name.end(), get_allocator()),
+ std::forward<T>(value),get_allocator());
+ inserted = true;
+ }
+ return std::make_pair(it,inserted);
+ }
+
+ // try_emplace
+
+ template <class A=allocator_type, class... Args>
+ typename std::enable_if<is_stateless<A>::value,std::pair<iterator,bool>>::type
+ try_emplace(const string_view_type& name, Args&&... args)
+ {
+ bool inserted;
+ auto it = std::lower_bound(this->members_.begin(),this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(name.begin(),name.end()),
+ std::forward<Args>(args)...);
+ it = this->members_.begin() + this->members_.size() - 1;
+ inserted = true;
+ }
+ else if (it->key() == name)
+ {
+ inserted = false;
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ key_storage_type(name.begin(),name.end()),
+ std::forward<Args>(args)...);
+ inserted = true;
+ }
+ return std::make_pair(it,inserted);
+ }
+
+ template <class A=allocator_type, class... Args>
+ typename std::enable_if<!is_stateless<A>::value,std::pair<iterator,bool>>::type
+ try_emplace(const string_view_type& name, Args&&... args)
+ {
+ bool inserted;
+ auto it = std::lower_bound(this->members_.begin(),this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(name.begin(),name.end(), get_allocator()),
+ std::forward<Args>(args)...);
+ it = this->members_.begin() + this->members_.size() - 1;
+ inserted = true;
+ }
+ else if (it->key() == name)
+ {
+ inserted = false;
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ key_storage_type(name.begin(),name.end(), get_allocator()),
+ std::forward<Args>(args)...);
+ inserted = true;
+ }
+ return std::make_pair(it,inserted);
+ }
+
+ template <class A=allocator_type, class ... Args>
+ typename std::enable_if<is_stateless<A>::value,iterator>::type
+ try_emplace(iterator hint, const string_view_type& name, Args&&... args)
+ {
+ iterator it;
+ if (hint != this->members_.end() && hint->key() <= name)
+ {
+ it = std::lower_bound(hint,this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+ else
+ {
+ it = std::lower_bound(this->members_.begin(),this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(name.begin(),name.end()),
+ std::forward<Args>(args)...);
+ it = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else if (it->key() == name)
+ {
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ key_storage_type(name.begin(),name.end()),
+ std::forward<Args>(args)...);
+ }
+ return it;
+ }
+
+ template <class A=allocator_type, class ... Args>
+ typename std::enable_if<!is_stateless<A>::value,iterator>::type
+ try_emplace(iterator hint, const string_view_type& name, Args&&... args)
+ {
+ iterator it;
+ if (hint != this->members_.end() && hint->key() <= name)
+ {
+ it = std::lower_bound(hint,this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+ else
+ {
+ it = std::lower_bound(this->members_.begin(),this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(name.begin(),name.end(), get_allocator()),
+ std::forward<Args>(args)...);
+ it = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else if (it->key() == name)
+ {
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ key_storage_type(name.begin(),name.end(), get_allocator()),
+ std::forward<Args>(args)...);
+ }
+ return it;
+ }
+
+ // set_
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<is_stateless<A>::value,void>::type
+ set_(key_storage_type&& name, T&& value)
+ {
+ string_view_type s(name.data(), name.size());
+ auto it = std::lower_bound(this->members_.begin(),this->members_.end(), s,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(std::forward<key_storage_type>(name),
+ std::forward<T>(value));
+ }
+ else if (string_view_type(it->key().data(),it->key().length()) == s)
+ {
+ it->value(Json(std::forward<T>(value)));
+ }
+ else
+ {
+ this->members_.emplace(it,
+ std::forward<key_storage_type>(name),
+ std::forward<T>(value));
+ }
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!is_stateless<A>::value,void>::type
+ set_(key_storage_type&& name, T&& value)
+ {
+ string_view_type s(name.data(), name.size());
+ auto it = std::lower_bound(this->members_.begin(),this->members_.end(), s,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(std::forward<key_storage_type>(name),
+ std::forward<T>(value),get_allocator() );
+ }
+ else if (string_view_type(it->key().data(), it->key().length()) == s)
+ {
+ it->value(Json(std::forward<T>(value),get_allocator() ));
+ }
+ else
+ {
+ this->members_.emplace(it,
+ std::forward<key_storage_type>(name),
+ std::forward<T>(value),get_allocator() );
+ }
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<is_stateless<A>::value,iterator>::type
+ insert_or_assign(iterator hint, const string_view_type& name, T&& value)
+ {
+ iterator it;
+ if (hint != this->members_.end() && hint->key() <= name)
+ {
+ it = std::lower_bound(hint,this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+ else
+ {
+ it = std::lower_bound(this->members_.begin(),this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(name.begin(),name.end()),
+ std::forward<T>(value));
+ it = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else if (it->key() == name)
+ {
+ it->value(Json(std::forward<T>(value)));
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ key_storage_type(name.begin(),name.end()),
+ std::forward<T>(value));
+ }
+ return it;
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!is_stateless<A>::value,iterator>::type
+ insert_or_assign(iterator hint, const string_view_type& name, T&& value)
+ {
+ iterator it;
+ if (hint != this->members_.end() && hint->key() <= name)
+ {
+ it = std::lower_bound(hint,this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+ else
+ {
+ it = std::lower_bound(this->members_.begin(),this->members_.end(), name,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(name.begin(),name.end(), get_allocator()),
+ std::forward<T>(value),get_allocator());
+ it = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else if (it->key() == name)
+ {
+ it->value(Json(std::forward<T>(value),get_allocator()));
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ key_storage_type(name.begin(),name.end(), get_allocator()),
+ std::forward<T>(value),get_allocator());
+ }
+ return it;
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<is_stateless<A>::value,iterator>::type
+ set_(iterator hint, key_storage_type&& name, T&& value)
+ {
+ string_view_type s(name.data(), name.size());
+ iterator it;
+ if (hint != this->members_.end() && hint->key() <= s)
+ {
+ it = std::lower_bound(hint,this->members_.end(), s,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+ else
+ {
+ it = std::lower_bound(this->members_.begin(),this->members_.end(), s,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(std::forward<key_storage_type>(name),
+ std::forward<T>(value));
+ it = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else if (string_view_type(it->key().data(), it->key().length()) == s)
+ {
+ it->value(Json(std::forward<T>(value)));
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ std::forward<key_storage_type>(name),
+ std::forward<T>(value));
+ }
+ return it;
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!is_stateless<A>::value,iterator>::type
+ set_(iterator hint, key_storage_type&& name, T&& value)
+ {
+ string_view_type s(name.data(), name.size());
+ iterator it;
+ if (hint != this->members_.end() && hint->key() <= s)
+ {
+ it = std::lower_bound(hint,this->members_.end(), s,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+ else
+ {
+ it = std::lower_bound(this->members_.begin(),this->members_.end(), s,
+ [](const value_type& a, const string_view_type& k){return a.key().compare(k) < 0;});
+ }
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(std::forward<key_storage_type>(name),
+ std::forward<T>(value),get_allocator() );
+ it = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else if (string_view_type(it->key().data(), it->key().length()) == s)
+ {
+ it->value(Json(std::forward<T>(value),get_allocator() ));
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ std::forward<key_storage_type>(name),
+ std::forward<T>(value),get_allocator() );
+ }
+ return it;
+ }
+
+ bool operator==(const json_object& rhs) const
+ {
+ if (size() != rhs.size())
+ {
+ return false;
+ }
+ for (auto it = this->members_.begin(); it != this->members_.end(); ++it)
+ {
+
+ auto rhs_it = std::lower_bound(rhs.begin(), rhs.end(), *it,
+ [](const value_type& a, const value_type& b){return a.key().compare(b.key()) < 0;});
+ if (rhs_it == rhs.end() || rhs_it->key() != it->key() || rhs_it->value() != it->value())
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+private:
+ json_object& operator=(const json_object&) = delete;
+};
+
+// Preserve order
+template <class KeyT,class Json>
+class json_object<KeyT,Json,true> final : public Json_object_<KeyT,Json>
+{
+public:
+ using typename Json_object_<KeyT,Json>::allocator_type;
+ using typename Json_object_<KeyT,Json>::char_type;
+ using typename Json_object_<KeyT,Json>::char_allocator_type;
+ using typename Json_object_<KeyT,Json>::key_storage_type;
+ using typename Json_object_<KeyT,Json>::string_view_type;
+ using typename Json_object_<KeyT,Json>::value_type;
+ using typename Json_object_<KeyT,Json>::kvp_allocator_type;
+ using typename Json_object_<KeyT,Json>::object_storage_type;
+ using typename Json_object_<KeyT,Json>::iterator;
+ using typename Json_object_<KeyT,Json>::const_iterator;
+ using Json_object_<KeyT,Json>::get_allocator;
+
+ json_object()
+ : Json_object_<KeyT,Json>()
+ {
+ }
+ json_object(const allocator_type& allocator)
+ : Json_object_<KeyT,Json>(allocator)
+ {
+ }
+
+ json_object(const json_object& val)
+ : Json_object_<KeyT,Json>(val)
+ {
+ }
+
+ json_object(json_object&& val)
+ : Json_object_<KeyT,Json>(std::forward<json_object>(val))
+ {
+ }
+
+ json_object(const json_object& val, const allocator_type& allocator)
+ : Json_object_<KeyT,Json>(val,allocator)
+ {
+ }
+
+ json_object(json_object&& val,const allocator_type& allocator)
+ : Json_object_<KeyT,Json>(std::forward<json_object>(val),allocator)
+ {
+ }
+
+ json_object(std::initializer_list<typename Json::array> init)
+ : Json_object_<KeyT,Json>()
+ {
+ for (const auto& element : init)
+ {
+ if (element.size() != 2 || !element[0].is_string())
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Cannot create object from initializer list"));
+ break;
+ }
+ }
+ for (auto& element : init)
+ {
+ insert_or_assign(element[0].as_string_view(), std::move(element[1]));
+ }
+ }
+
+ json_object(std::initializer_list<typename Json::array> init,
+ const allocator_type& allocator)
+ : Json_object_<KeyT,Json>(allocator)
+ {
+ for (const auto& element : init)
+ {
+ if (element.size() != 2 || !element[0].is_string())
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Cannot create object from initializer list"));
+ break;
+ }
+ }
+ for (auto& element : init)
+ {
+ insert_or_assign(element[0].as_string_view(), std::move(element[1]));
+ }
+ }
+
+ void swap(json_object& val)
+ {
+ Json_object_<KeyT,Json>::swap(val);
+ }
+
+ iterator begin()
+ {
+ return this->members_.begin();
+ }
+
+ iterator end()
+ {
+ return this->members_.end();
+ }
+
+ const_iterator begin() const
+ {
+ return this->members_.begin();
+ }
+
+ const_iterator end() const
+ {
+ return this->members_.end();
+ }
+
+ size_t size() const {return this->members_.size();}
+
+ size_t capacity() const {return this->members_.capacity();}
+
+ void clear() {this->members_.clear();}
+
+ void shrink_to_fit()
+ {
+ for (size_t i = 0; i < this->members_.size(); ++i)
+ {
+ this->members_[i].shrink_to_fit();
+ }
+ this->members_.shrink_to_fit();
+ }
+
+ void reserve(size_t n) {this->members_.reserve(n);}
+
+ Json& at(size_t i)
+ {
+ if (i >= this->members_.size())
+ {
+ JSONCONS_THROW(json_exception_impl<std::out_of_range>("Invalid array subscript"));
+ }
+ return this->members_[i].value();
+ }
+
+ const Json& at(size_t i) const
+ {
+ if (i >= this->members_.size())
+ {
+ JSONCONS_THROW(json_exception_impl<std::out_of_range>("Invalid array subscript"));
+ }
+ return this->members_[i].value();
+ }
+
+ iterator find(const string_view_type& name)
+ {
+ return std::find_if(this->members_.begin(),this->members_.end(),
+ [name](const value_type& kv){return kv.key() == name;});
+ }
+
+ const_iterator find(const string_view_type& name) const
+ {
+ return std::find_if(this->members_.begin(),this->members_.end(),
+ [name](const value_type& kv){return kv.key() == name;});
+ }
+
+ void erase(const_iterator first, const_iterator last)
+ {
+ this->members_.erase(first,last);
+ }
+
+ void erase(const string_view_type& name)
+ {
+ auto it = std::find_if(this->members_.begin(),this->members_.end(),
+ [name](const value_type& kv){return kv.key() == name;});
+ if (it != this->members_.end())
+ {
+ this->members_.erase(it);
+ }
+ }
+
+ template<class InputIt, class UnaryPredicate>
+ void insert(InputIt first, InputIt last, UnaryPredicate pred)
+ {
+ size_t count = std::distance(first,last);
+ this->members_.reserve(this->members_.size() + count);
+ for (auto s = first; s != last; ++s)
+ {
+ this->members_.emplace_back(pred(*s));
+ }
+ auto it = last_wins_unique_sequence(this->members_.begin(), this->members_.end(),
+ [](const value_type& a, const value_type& b){ return a.key().compare(b.key());});
+ this->members_.erase(it,this->members_.end());
+ }
+
+ // insert_or_assign
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<is_stateless<A>::value,std::pair<iterator,bool>>::type
+ insert_or_assign(const string_view_type& name, T&& value)
+ {
+ bool inserted;
+ auto it = std::find_if(this->members_.begin(),this->members_.end(),
+ [name](const value_type& a){return a.key() == name;});
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(name.begin(),name.end()),
+ std::forward<T>(value));
+ it = this->members_.begin() + this->members_.size() - 1;
+ inserted = true;
+ }
+ else
+ {
+ it->value(Json(std::forward<T>(value)));
+ inserted = false; // assigned
+ }
+ return std::make_pair(it,inserted);
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!is_stateless<A>::value,std::pair<iterator,bool>>::type
+ insert_or_assign(const string_view_type& name, T&& value)
+ {
+ bool inserted;
+ auto it = std::find_if(this->members_.begin(),this->members_.end(),
+ [name](const value_type& a){return a.key() == name;});
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(name.begin(),name.end(),get_allocator()),
+ std::forward<T>(value),get_allocator());
+ it = this->members_.begin() + this->members_.size() - 1;
+ inserted = true;
+ }
+ else
+ {
+ it->value(Json(std::forward<T>(value),get_allocator()));
+ inserted = false; // assigned
+ }
+ return std::make_pair(it,inserted);
+ }
+
+ template <class A=allocator_type, class T>
+ typename std::enable_if<is_stateless<A>::value,iterator>::type
+ insert_or_assign(iterator hint, const string_view_type& key, T&& value)
+ {
+ iterator it;
+ if (hint == this->members_.end())
+ {
+ auto result = insert_or_assign(key, std::forward<T>(value));
+ it = result.first;
+ }
+ else
+ {
+ it = std::find_if(this->members_.begin(),this->members_.end(),
+ [key](const value_type& a){return a.key() == key;});
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(key.begin(),key.end()),
+ std::forward<T>(value));
+ it = this->members_.begin() + this->members_.size() - 1;
+ }
+ else
+ {
+ it->value(Json(std::forward<T>(value)));
+ }
+ }
+ return it;
+ }
+
+ template <class A=allocator_type, class T>
+ typename std::enable_if<!is_stateless<A>::value,iterator>::type
+ insert_or_assign(iterator hint, const string_view_type& key, T&& value)
+ {
+ iterator it;
+ if (hint == this->members_.end())
+ {
+ auto result = insert_or_assign(key, std::forward<T>(value));
+ it = result.first;
+ }
+ else
+ {
+ it = std::find_if(this->members_.begin(),this->members_.end(),
+ [key](const value_type& a){return a.key() == key;});
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(key.begin(),key.end(),get_allocator()),
+ std::forward<T>(value),get_allocator());
+ it = this->members_.begin() + this->members_.size() - 1;
+ }
+ else
+ {
+ it->value(Json(std::forward<T>(value),get_allocator()));
+ }
+ }
+ return it;
+ }
+
+ // merge
+
+ void merge(const json_object& source)
+ {
+ for (auto it = source.begin(); it != source.end(); ++it)
+ {
+ try_emplace(it->key(),it->value());
+ }
+ }
+
+ void merge(json_object&& source)
+ {
+ auto it = std::make_move_iterator(source.begin());
+ auto end = std::make_move_iterator(source.end());
+ for (; it != end; ++it)
+ {
+ auto pos = std::find_if(this->members_.begin(),this->members_.end(),
+ [it](const value_type& a){return a.key() == it->key();});
+ if (pos == this->members_.end() )
+ {
+ this->members_.emplace_back(*it);
+ }
+ }
+ }
+
+ void merge(iterator hint, const json_object& source)
+ {
+ for (auto it = source.begin(); it != source.end(); ++it)
+ {
+ hint = try_emplace(hint, it->key(),it->value());
+ }
+ }
+
+ void merge(iterator hint, json_object&& source)
+ {
+ auto it = std::make_move_iterator(source.begin());
+ auto end = std::make_move_iterator(source.end());
+ for (; it != end; ++it)
+ {
+ auto pos = std::find_if(this->members_.begin(),this->members_.end(),
+ [it](const value_type& a){return a.key() == it->key();});
+ if (pos == this->members_.end() )
+ {
+ hint = this->members_.emplace(hint,*it);
+ }
+ }
+ }
+
+ // merge_or_update
+
+ void merge_or_update(const json_object& source)
+ {
+ for (auto it = source.begin(); it != source.end(); ++it)
+ {
+ insert_or_assign(it->key(),it->value());
+ }
+ }
+
+ void merge_or_update(json_object&& source)
+ {
+ auto it = std::make_move_iterator(source.begin());
+ auto end = std::make_move_iterator(source.end());
+ for (; it != end; ++it)
+ {
+ auto pos = std::find_if(this->members_.begin(),this->members_.end(),
+ [it](const value_type& a){return a.key() == it->key();});
+ if (pos == this->members_.end() )
+ {
+ this->members_.emplace_back(*it);
+ }
+ else
+ {
+ pos->value(it->value());
+ }
+ }
+ }
+
+ void merge_or_update(iterator hint, const json_object& source)
+ {
+ for (auto it = source.begin(); it != source.end(); ++it)
+ {
+ hint = insert_or_assign(hint, it->key(),it->value());
+ }
+ }
+
+ void merge_or_update(iterator hint, json_object&& source)
+ {
+ auto it = std::make_move_iterator(source.begin());
+ auto end = std::make_move_iterator(source.end());
+ for (; it != end; ++it)
+ {
+ auto pos = std::find_if(this->members_.begin(),this->members_.end(),
+ [it](const value_type& a){return a.key() == it->key();});
+ if (pos == this->members_.end() )
+ {
+ hint = this->members_.emplace(hint,*it);
+ }
+ else
+ {
+ pos->value(it->value());
+ hint = pos;
+ }
+ }
+ }
+
+ // try_emplace
+ template <class A=allocator_type, class... Args>
+ typename std::enable_if<is_stateless<A>::value,std::pair<iterator,bool>>::type
+ try_emplace(const string_view_type& key, Args&&... args)
+ {
+ bool inserted;
+ auto it = std::find_if(this->members_.begin(),this->members_.end(),
+ [key](const value_type& a){return a.key() == key;});
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(key.begin(),key.end()),
+ std::forward<Args>(args)...);
+ it = this->members_.begin() + this->members_.size() - 1;
+ inserted = true;
+
+ }
+ else
+ {
+ inserted = false;
+ }
+ return std::make_pair(it,inserted);
+ }
+
+ template <class A=allocator_type, class... Args>
+ typename std::enable_if<!is_stateless<A>::value,std::pair<iterator,bool>>::type
+ try_emplace(const string_view_type& key, Args&&... args)
+ {
+ bool inserted;
+ auto it = std::find_if(this->members_.begin(),this->members_.end(),
+ [key](const value_type& a){return a.key() == key;});
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(key.begin(),key.end(), get_allocator()),
+ std::forward<Args>(args)...);
+ it = this->members_.begin() + this->members_.size() - 1;
+ inserted = true;
+
+ }
+ else
+ {
+ inserted = false;
+ }
+ return std::make_pair(it,inserted);
+ }
+
+ template <class A=allocator_type, class ... Args>
+ typename std::enable_if<is_stateless<A>::value,iterator>::type
+ try_emplace(iterator hint, const string_view_type& key, Args&&... args)
+ {
+ auto it = std::find_if(this->members_.begin(),this->members_.end(),
+ [key](const value_type& a){return a.key() == key;});
+
+ if (it == this->members_.end())
+ {
+ if (hint == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(key.begin(),key.end()),
+ std::forward<Args>(args)...);
+ it = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else
+ {
+ it = this->members_.emplace(hint,
+ key_storage_type(key.begin(),key.end()),
+ std::forward<Args>(args)...);
+ }
+ }
+ return it;
+ }
+
+ template <class A=allocator_type, class ... Args>
+ typename std::enable_if<!is_stateless<A>::value,iterator>::type
+ try_emplace(iterator hint, const string_view_type& key, Args&&... args)
+ {
+ auto it = std::find_if(this->members_.begin(),this->members_.end(),
+ [key](const value_type& a){return a.key() == key;});
+
+ if (it == this->members_.end())
+ {
+ if (hint == this->members_.end())
+ {
+ this->members_.emplace_back(key_storage_type(key.begin(),key.end(), get_allocator()),
+ std::forward<Args>(args)...);
+ it = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else
+ {
+ it = this->members_.emplace(hint,
+ key_storage_type(key.begin(),key.end(), get_allocator()),
+ std::forward<Args>(args)...);
+ }
+ }
+ return it;
+ }
+
+ // set_
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<is_stateless<A>::value,void>::type
+ set_(key_storage_type&& key, T&& value)
+ {
+ string_view_type s(key.data(),key.size());
+ auto it = std::find_if(this->members_.begin(),this->members_.end(),
+ [s](const value_type& a){return a.key().compare(s) == 0;});
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(std::forward<key_storage_type>(key),
+ std::forward<T>(value));
+ }
+ else
+ {
+ it->value(Json(std::forward<T>(value)));
+ }
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!is_stateless<A>::value,void>::type
+ set_(key_storage_type&& key, T&& value)
+ {
+ string_view_type s(key.data(),key.size());
+ auto it = std::find_if(this->members_.begin(),this->members_.end(),
+ [s](const value_type& a){return a.key().compare(s) == 0;});
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(std::forward<key_storage_type>(key),
+ std::forward<T>(value),get_allocator());
+ }
+ else
+ {
+ it->value(Json(std::forward<T>(value),get_allocator()));
+ }
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<is_stateless<A>::value,iterator>::type
+ set_(iterator hint, key_storage_type&& key, T&& value)
+ {
+ iterator it = hint;
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(std::forward<key_storage_type>(key),
+ std::forward<T>(value));
+ it = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else if (it->key() == key)
+ {
+ it->value(Json(std::forward<T>(value)));
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ std::forward<key_storage_type>(key),
+ std::forward<T>(value));
+ }
+ return it;
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!is_stateless<A>::value,iterator>::type
+ set_(iterator hint, key_storage_type&& key, T&& value)
+ {
+ iterator it = hint;
+
+ if (it == this->members_.end())
+ {
+ this->members_.emplace_back(std::forward<key_storage_type>(key),
+ std::forward<T>(value), get_allocator());
+ it = this->members_.begin() + (this->members_.size() - 1);
+ }
+ else if (it->key() == key)
+ {
+ it->value(Json(std::forward<T>(value), get_allocator()));
+ }
+ else
+ {
+ it = this->members_.emplace(it,
+ std::forward<key_storage_type>(key),
+ std::forward<T>(value), get_allocator());
+ }
+ return it;
+ }
+
+ bool operator==(const json_object& rhs) const
+ {
+ if (size() != rhs.size())
+ {
+ return false;
+ }
+ for (auto it = this->members_.begin(); it != this->members_.end(); ++it)
+ {
+ auto rhs_it = std::find_if(rhs.begin(),rhs.end(),
+ [it](const value_type& a){return a.key() == it->key();});
+ if (rhs_it == rhs.end() || rhs_it->key() != it->key() || rhs_it->value() != it->value())
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+private:
+ json_object& operator=(const json_object&) = delete;
+};
+
+}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/json_type_traits.hpp b/vendor/jsoncons-0.104.0/jsoncons/json_type_traits.hpp
new file mode 100644
index 00000000..1c76c4c0
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/json_type_traits.hpp
@@ -0,0 +1,966 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSON_TYPE_TRAITS_HPP
+#define JSONCONS_JSON_TYPE_TRAITS_HPP
+
+#include <array>
+#include <string>
+#include <vector>
+#include <valarray>
+#include <exception>
+#include <cstdlib>
+#include <cstring>
+#include <utility>
+#include <algorithm>
+#include <fstream>
+#include <limits>
+#include <type_traits>
+#include <jsoncons/jsoncons_utilities.hpp>
+#include <jsoncons/detail/type_traits_helper.hpp>
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+#endif
+
+namespace jsoncons {
+
+// null_type
+
+struct null_type
+{
+};
+
+// json_type_traits
+
+template <class Json, class T, class Enable=void>
+struct json_type_traits
+{
+ static const bool is_compatible = false;
+
+ static bool is(const Json&)
+ {
+ return false;
+ }
+};
+
+namespace detail {
+
+// is_incompatible
+template<class Json, class T, class Enable = void>
+struct is_incompatible : std::false_type {};
+
+
+// is_incompatible
+template<class Json, class T>
+struct is_incompatible<Json,T,
+ typename std::enable_if<!std::integral_constant<bool, json_type_traits<Json, T>::is_compatible>::value>::type
+> : std::true_type {};
+
+// is_compatible_string_type
+template<class Json, class T, class Enable=void>
+struct is_compatible_string_type : std::false_type {};
+
+template<class Json, class T>
+struct is_compatible_string_type<Json,T,
+ typename std::enable_if<!std::is_same<T,typename Json::array>::value &&
+ detail::is_string_like<T>::value &&
+ !is_incompatible<Json,typename std::iterator_traits<typename T::iterator>::value_type>::value
+>::type> : std::true_type {};
+
+// is_compatible_array_type
+template<class Json, class T, class Enable=void>
+struct is_compatible_array_type : std::false_type {};
+
+template<class Json, class T>
+struct is_compatible_array_type<Json,T,
+ typename std::enable_if<!std::is_same<T,typename Json::array>::value &&
+ detail::is_vector_like<T>::value &&
+ !is_incompatible<Json,typename std::iterator_traits<typename T::iterator>::value_type>::value
+>::type> : std::true_type {};
+
+// is_compatible_object_type
+template<class Json, class T, class Enable=void>
+struct is_compatible_object_type : std::false_type {};
+
+template<class Json, class T>
+struct is_compatible_object_type<Json,T,
+ typename std::enable_if<
+ !is_incompatible<Json,typename T::mapped_type>::value
+>::type> : std::true_type {};
+
+// is_std_array
+template<class T>
+struct is_std_array : std::false_type {};
+
+template<class E, size_t N>
+struct is_std_array<std::array<E, N>> : std::true_type {};
+
+template <class Json, class T>
+class json_array_input_iterator
+{
+public:
+ typedef typename Json::const_array_iterator iterator_base;
+ typedef typename std::iterator_traits<iterator_base>::value_type value_type;
+ typedef typename std::iterator_traits<iterator_base>::difference_type difference_type;
+ typedef typename std::iterator_traits<iterator_base>::pointer pointer;
+ typedef T reference;
+ typedef std::input_iterator_tag iterator_category;
+
+ json_array_input_iterator()
+ {
+ }
+
+ json_array_input_iterator(iterator_base it)
+ : it_(it)
+ {
+ }
+
+ json_array_input_iterator& operator=(json_array_input_iterator rhs)
+ {
+ swap(*this,rhs);
+ return *this;
+ }
+
+ json_array_input_iterator& operator++()
+ {
+ ++it_;
+ return *this;
+ }
+
+ json_array_input_iterator operator++(int) // postfix increment
+ {
+ json_array_input_iterator temp(*this);
+ ++it_;
+ return temp;
+ }
+
+ json_array_input_iterator& operator--()
+ {
+ --it_;
+ return *this;
+ }
+
+ json_array_input_iterator operator--(int)
+ {
+ json_array_input_iterator temp(*this);
+ --it_;
+ return temp;
+ }
+
+ reference operator*() const
+ {
+ return json_type_traits<Json,T>::as(*it_);
+ }
+
+ friend bool operator==(const json_array_input_iterator& it1, const json_array_input_iterator& it2)
+ {
+ return it1.it_ == it2.it_;
+ }
+ friend bool operator!=(const json_array_input_iterator& it1, const json_array_input_iterator& it2)
+ {
+ return !(it1.it_ == it2.it_);
+ }
+ friend void swap(json_array_input_iterator& lhs, json_array_input_iterator& rhs)
+ {
+ using std::swap;
+ swap(lhs.it_,rhs.it_);
+ swap(lhs.empty_,rhs.empty_);
+ }
+
+private:
+ iterator_base it_;
+};
+
+template <class Json, class T>
+class json_object_input_iterator
+{
+public:
+ typedef typename Json::const_object_iterator iterator_base;
+ typedef typename std::iterator_traits<iterator_base>::value_type value_type;
+ typedef typename std::iterator_traits<iterator_base>::difference_type difference_type;
+ typedef typename std::iterator_traits<iterator_base>::pointer pointer;
+ typedef T reference;
+ typedef std::input_iterator_tag iterator_category;
+ typedef typename T::first_type key_type;
+ typedef typename T::second_type mapped_type;
+
+ json_object_input_iterator()
+ {
+ }
+
+ json_object_input_iterator(iterator_base it)
+ : it_(it)
+ {
+ }
+
+ json_object_input_iterator& operator=(json_object_input_iterator rhs)
+ {
+ swap(*this,rhs);
+ return *this;
+ }
+
+ json_object_input_iterator& operator++()
+ {
+ ++it_;
+ return *this;
+ }
+
+ json_object_input_iterator operator++(int) // postfix increment
+ {
+ json_object_input_iterator temp(*this);
+ ++it_;
+ return temp;
+ }
+
+ json_object_input_iterator& operator--()
+ {
+ --it_;
+ return *this;
+ }
+
+ json_object_input_iterator operator--(int)
+ {
+ json_object_input_iterator temp(*this);
+ --it_;
+ return temp;
+ }
+
+ reference operator*() const
+ {
+ return T(key_type(it_->key()),json_type_traits<Json,mapped_type>::as(it_->value()));
+ }
+
+ friend bool operator==(const json_object_input_iterator& it1, const json_object_input_iterator& it2)
+ {
+ return it1.it_ == it2.it_;
+ }
+ friend bool operator!=(const json_object_input_iterator& it1, const json_object_input_iterator& it2)
+ {
+ return !(it1.it_ == it2.it_);
+ }
+ friend void swap(json_object_input_iterator& lhs, json_object_input_iterator& rhs)
+ {
+ using std::swap;
+ swap(lhs.it_,rhs.it_);
+ swap(lhs.empty_,rhs.empty_);
+ }
+
+private:
+ iterator_base it_;
+};
+
+}
+
+template<class Json>
+struct json_type_traits<Json, typename type_wrapper<typename Json::char_type>::const_pointer_type>
+{
+ typedef typename Json::char_type char_type;
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_string();
+ }
+ static const char_type* as(const Json& j)
+ {
+ return j.as_cstring();
+ }
+ template <class ... Args>
+ static Json to_json(Args&&... args)
+ {
+ return Json(typename Json::variant(std::forward<Args>(args)...));
+ }
+};
+
+template<class Json>
+struct json_type_traits<Json, typename type_wrapper<typename Json::char_type>::pointer_type>
+{
+ typedef typename Json::char_type char_type;
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_string();
+ }
+ template <class ... Args>
+ static Json to_json(Args&&... args)
+ {
+ return Json(typename Json::variant(std::forward<Args>(args)...));
+ }
+};
+
+// integral
+
+template<class Json, class T>
+struct json_type_traits<Json, T,
+ typename std::enable_if<detail::is_integer_like<T>::value
+>::type>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ if (j.is_integer())
+ {
+ return j.as_integer() >= (std::numeric_limits<T>::min)() && j.as_integer() <= (std::numeric_limits<T>::max)();
+ }
+ else if (j.is_uinteger())
+ {
+ return j.as_uinteger() <= static_cast<uint64_t>((std::numeric_limits<T>::max)());
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static T as(const Json& j)
+ {
+ return static_cast<T>(j.as_integer());
+ }
+ template <class ... Args>
+ static Json to_json(Args&&... args)
+ {
+ return Json::from_integer(std::forward<Args>(args)...);
+ }
+};
+
+template<class Json, class T>
+struct json_type_traits<Json, T,
+ typename std::enable_if<detail::is_uinteger_like<T>::value
+>::type >
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ if (j.is_integer())
+ {
+ return j.as_integer() >= 0 && static_cast<uint64_t>(j.as_integer()) <= (std::numeric_limits<T>::max)();
+ }
+ else if (j.is_uinteger())
+ {
+ return j.as_uinteger() <= (std::numeric_limits<T>::max)();
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static T as(const Json& j)
+ {
+ return static_cast<T>(j.as_uinteger());
+ }
+
+ template <class ... Args>
+ static Json to_json(Args&&... args)
+ {
+ return Json::from_uinteger(std::forward<Args>(args)...);
+ }
+};
+
+template<class Json,class T>
+struct json_type_traits<Json, T,
+ typename std::enable_if<std::is_floating_point<T>::value
+>::type>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_double();
+ }
+ static T as(const Json& j)
+ {
+ return static_cast<T>(j.as_double());
+ }
+ template <class ... Args>
+ static Json to_json(Args&&... args)
+ {
+ return Json::from_floating_point(std::forward<Args>(args)...);
+ }
+};
+
+template<class Json>
+struct json_type_traits<Json, typename Json::object>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_object();
+ }
+ template <class ... Args>
+ static Json to_json(Args&&... args)
+ {
+ return Json(typename Json::variant(std::forward<Args>(args)...));
+ }
+};
+
+template<class Json>
+struct json_type_traits<Json, typename Json::array>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_array();
+ }
+ template <class ... Args>
+ static Json to_json(Args&&... args)
+ {
+ return Json(typename Json::variant(std::forward<Args>(args)...));
+ }
+};
+
+template<class Json>
+struct json_type_traits<Json, Json>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json&) JSONCONS_NOEXCEPT
+ {
+ return true;
+ }
+ static Json as(Json j)
+ {
+ return j;
+ }
+ static Json to_json(const Json& val)
+ {
+ return val;
+ }
+ static Json to_json(const Json& val, allocator_type)
+ {
+ return val;
+ }
+};
+
+template<class Json>
+struct json_type_traits<Json, jsoncons::null_type>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_null();
+ }
+ static typename jsoncons::null_type as(const Json& j)
+ {
+ JSONCONS_ASSERT(j.is_null());
+ return jsoncons::null_type();
+ }
+ static Json to_json(jsoncons::null_type)
+ {
+ return Json::null();
+ }
+ static Json to_json(jsoncons::null_type, allocator_type)
+ {
+ return Json::null();
+ }
+};
+
+template<class Json>
+struct json_type_traits<Json, bool>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_bool();
+ }
+ static bool as(const Json& j)
+ {
+ return j.as_bool();
+ }
+ template <class ... Args>
+ static Json to_json(Args&&... args)
+ {
+ return Json(typename Json::variant(std::forward<Args>(args)...));
+ }
+};
+
+template<class Json,class T>
+struct json_type_traits<Json, T, typename std::enable_if<std::is_same<T,
+ std::conditional<!std::is_same<bool,std::vector<bool>::const_reference>::value,
+ std::vector<bool>::const_reference,
+ void>::type>::value>::type>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_bool();
+ }
+ static bool as(const Json& j)
+ {
+ return j.as_bool();
+ }
+ template <class ... Args>
+ static Json to_json(Args&&... args)
+ {
+ return Json(typename Json::variant(std::forward<Args>(args)...));
+ }
+};
+
+template<class Json>
+struct json_type_traits<Json, std::vector<bool>::reference>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_bool();
+ }
+ static bool as(const Json& j)
+ {
+ return j.as_bool();
+ }
+ template <class ... Args>
+ static Json to_json(Args&&... args)
+ {
+ return Json(typename Json::variant(std::forward<Args>(args)...));
+ }
+};
+
+template<class Json, typename T>
+struct json_type_traits<Json, T,
+ typename std::enable_if<detail::is_compatible_array_type<Json,T>::value &&
+ !detail::is_std_array<T>::value>::type>
+{
+ typedef typename std::iterator_traits<typename T::iterator>::value_type element_type;
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ bool result = j.is_array();
+ if (result)
+ {
+ for (auto e : j.array_range())
+ {
+ if (!e.template is<element_type>())
+ {
+ result = false;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ template <class Ty = element_type>
+ static typename std::enable_if<!(std::is_integral<Ty>::value && !std::is_same<Ty,bool>::value),T>::type
+ as(const Json& j)
+ {
+ if (j.is_array())
+ {
+ T v(detail::json_array_input_iterator<Json, element_type>(j.array_range().begin()),
+ detail::json_array_input_iterator<Json, element_type>(j.array_range().end()));
+ return v;
+ }
+ else
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempt to cast json non-array to array"));
+ }
+ }
+
+ template <class Ty = element_type>
+ static typename std::enable_if<std::is_integral<Ty>::value && !std::is_same<Ty,bool>::value,T>::type
+ as(const Json& j)
+ {
+ if (j.is_array())
+ {
+ T v(detail::json_array_input_iterator<Json, element_type>(j.array_range().begin()),
+ detail::json_array_input_iterator<Json, element_type>(j.array_range().end()));
+ return v;
+ }
+ else if (j.is_byte_string())
+ {
+ T v(j.as_byte_string_view().begin(),j.as_byte_string_view().end());
+ return v;
+ }
+ else
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempt to cast json non-array to array"));
+ }
+ }
+
+ static Json to_json(const T& val)
+ {
+ Json j = typename Json::array();
+ auto first = std::begin(val);
+ auto last = std::end(val);
+ size_t size = std::distance(first,last);
+ j.reserve(size);
+ for (auto it = first; it != last; ++it)
+ {
+ j.push_back(*it);
+ }
+ return j;
+ }
+
+ static Json to_json(const T& val, const allocator_type& allocator)
+ {
+ Json j = typename Json::array(allocator);
+ auto first = std::begin(val);
+ auto last = std::end(val);
+ size_t size = std::distance(first, last);
+ j.reserve(size);
+ for (auto it = first; it != last; ++it)
+ {
+ j.push_back(*it);
+ }
+ return j;
+ }
+};
+
+template<class Json, typename T>
+struct json_type_traits<Json, T,
+ typename std::enable_if<detail::is_compatible_string_type<Json,T>::value>::type>
+{
+ typedef typename std::iterator_traits<typename T::iterator>::value_type element_type;
+ typedef typename Json::allocator_type allocator_type;
+ typedef typename T::allocator_type string_allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_string();
+ }
+
+ static T as(const Json& j)
+ {
+ if (j.is_string())
+ {
+ return j.as_string(string_allocator_type());
+ }
+ else
+ {
+ T s;
+ j.dump(s);
+ return s;
+ }
+ }
+
+ static Json to_json(const T& val)
+ {
+ return Json(typename Json::variant(val.data(), val.size()));
+ }
+
+ static Json to_json(const T& val, const allocator_type& allocator)
+ {
+ return Json(typename Json::variant(val.data(),val.size(),allocator));
+ }
+};
+
+template<class Json, typename T>
+struct json_type_traits<Json, T,
+ typename std::enable_if<detail::is_compatible_object_type<Json,T>::value>::type
+>
+{
+ typedef typename T::mapped_type mapped_type;
+ typedef typename T::value_type value_type;
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ bool result = j.is_object();
+ for (auto member : j.object_range())
+ {
+ if (!member.value().template is<mapped_type>())
+ {
+ result = false;
+ }
+ }
+ return result;
+ }
+
+ static T as(const Json& j)
+ {
+ T v(detail::json_object_input_iterator<Json,value_type>(j.object_range().begin()),
+ detail::json_object_input_iterator<Json,value_type>(j.object_range().end()));
+ return v;
+ }
+
+ static Json to_json(const T& val)
+ {
+ Json j;
+ j.reserve(val.size());
+ for (auto p: val)
+ {
+ j.set(p.first, p.second);
+ }
+ return j;
+ }
+
+ static Json to_json(const T& val, const allocator_type& allocator)
+ {
+ Json j(allocator);
+ j.reserve(val.size());
+ for (auto p: val)
+ {
+ j.set(p.first, p.second);
+ }
+ return j;
+ }
+};
+
+template<class Json, class E, size_t N>
+struct json_type_traits<Json, std::array<E, N>>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ typedef E element_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ bool result = j.is_array() && j.size() == N;
+ if (result)
+ {
+ for (auto e : j.array_range())
+ {
+ if (!e.template is<element_type>())
+ {
+ result = false;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ static std::array<E, N> as(const Json& j)
+ {
+ std::array<E, N> buff;
+ JSONCONS_ASSERT(j.size() == N);
+ for (size_t i = 0; i < N; i++)
+ {
+ buff[i] = j[i].template as<E>();
+ }
+ return buff;
+ }
+
+ static Json to_json(const std::array<E, N>& val)
+ {
+ Json j = typename Json::array();
+ j.reserve(N);
+ for (auto it = val.begin(); it != val.end(); ++it)
+ {
+ j.push_back(*it);
+ }
+ return j;
+ }
+
+ static Json to_json(const std::array<E, N>& val,
+ const allocator_type& allocator)
+ {
+ Json j = typename Json::array(allocator);
+ j.reserve(N);
+ for (auto it = val.begin(); it != val.end(); ++it)
+ {
+ j.push_back(*it);
+ }
+ return j;
+ }
+};
+
+namespace detail
+{
+
+template<size_t Pos, class Json, class Tuple>
+struct json_tuple_helper
+{
+ using element_type = typename std::tuple_element<Pos - 1, Tuple>::type;
+ using next = json_tuple_helper<Pos - 1, Json, Tuple>;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ if(j[Pos - 1].template is<element_type>())
+ {
+ return next::is(j);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ static void as(Tuple& tuple, const Json& j)
+ {
+ std::get<Pos - 1>(tuple) = j[Pos - 1].template as<element_type>();
+ next::as(tuple, j);
+ }
+
+ static void to_json(const Tuple& tuple, std::array<Json, std::tuple_size<Tuple>::value>& jsons)
+ {
+ jsons[Pos - 1] = json_type_traits<Json, element_type>::to_json(std::get<Pos-1>(tuple));
+ next::to_json(tuple, jsons);
+ }
+};
+
+template<class Json, class Tuple>
+struct json_tuple_helper<0, Json, Tuple>
+{
+ static bool is(const Json&) JSONCONS_NOEXCEPT
+ {
+ return true;
+ }
+
+ static void as(Tuple&, const Json&)
+ {
+ }
+
+ static void to_json(const Tuple&, std::array<Json, std::tuple_size<Tuple>::value>&)
+ {
+ }
+};
+
+}
+
+template<class Json, typename... E>
+struct json_type_traits<Json, std::tuple<E...>>
+{
+private:
+ using helper = detail::json_tuple_helper<sizeof...(E), Json, std::tuple<E...>>;
+
+public:
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return helper::is(j);
+ }
+
+ static std::tuple<E...> as(const Json& j)
+ {
+ std::tuple<E...> buff;
+ helper::as(buff, j);
+ return buff;
+ }
+
+ static Json to_json(const std::tuple<E...>& val)
+ {
+ std::array<Json, sizeof...(E)> buf;
+ helper::to_json(val, buf);
+ return Json(typename Json::array(buf.begin(), buf.end()));
+ }
+};
+
+template<class Json, class T1, class T2>
+struct json_type_traits<Json, std::pair<T1,T2>>
+{
+public:
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_array() && j.size() == 2;
+ }
+
+ static std::pair<T1,T2> as(const Json& j)
+ {
+ return std::make_pair<T1,T2>(j[0]. template as<T1>(),j[1]. template as<T2>());
+ }
+
+ static Json to_json(const std::pair<T1,T2>& val)
+ {
+ return typename Json::array{val.first,val.second};
+ }
+};
+
+template<class Json, class Allocator>
+struct json_type_traits<Json, basic_byte_string<Allocator>>
+{
+public:
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ return j.is_byte_string();
+ }
+
+ static basic_byte_string<Allocator> as(const Json& j)
+ {
+ return basic_byte_string<Allocator>(j.as_byte_string_view());
+ }
+
+ static Json to_json(const basic_byte_string<Allocator>& val)
+ {
+ return Json(val.data(),val.length());
+ }
+};
+
+// std::valarray
+
+template<class Json, class T>
+struct json_type_traits<Json, std::valarray<T>>
+{
+ typedef typename Json::allocator_type allocator_type;
+
+ static bool is(const Json& j) JSONCONS_NOEXCEPT
+ {
+ bool result = j.is_array();
+ if (result)
+ {
+ for (auto e : j.array_range())
+ {
+ if (!e.template is<T>())
+ {
+ result = false;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ static std::valarray<T> as(const Json& j)
+ {
+ if (j.is_array())
+ {
+ std::valarray<T> v(j.size());
+ for (size_t i = 0; i < j.size(); ++i)
+ {
+ v[i] = j[i].template as<T>();
+ }
+ return v;
+ }
+ else
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Attempt to cast json non-array to array"));
+ }
+ }
+
+ static Json to_json(const std::valarray<T>& val)
+ {
+ Json j = typename Json::array();
+ auto first = std::begin(val);
+ auto last = std::end(val);
+ size_t size = std::distance(first,last);
+ j.reserve(size);
+ for (auto it = first; it != last; ++it)
+ {
+ j.push_back(*it);
+ }
+ return j;
+ }
+
+ static Json to_json(const std::valarray<T>& val, const allocator_type& allocator)
+ {
+ Json j = typename Json::array(allocator);
+ auto first = std::begin(val);
+ auto last = std::end(val);
+ size_t size = std::distance(first,last);
+ j.reserve(size);
+ for (auto it = first; it != last; ++it)
+ {
+ j.push_back(*it);
+ }
+ return j;
+ }
+};
+
+}
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/jsoncons_config.hpp b/vendor/jsoncons-0.104.0/jsoncons/jsoncons_config.hpp
new file mode 100644
index 00000000..59c6b650
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/jsoncons_config.hpp
@@ -0,0 +1,106 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSONCONS_CONFIG_HPP
+#define JSONCONS_JSONCONS_CONFIG_HPP
+
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+#include <cstdarg>
+#include <exception>
+#include <limits> // std::numeric_limits
+
+// Uncomment the following line to suppress deprecated names (recommended for new code)
+//#define JSONCONS_NO_DEPRECATED
+
+// The definitions below follow the definitions in compiler_support_p.h, https://github.com/01org/tinycbor
+// MIT license
+
+#if defined(__GNUC__) || defined(__clang__)
+#define JSONCONS_LIKELY(x) __builtin_expect(!!(x), 1)
+#define JSONCONS_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#define JSONCONS_UNREACHABLE() __builtin_unreachable()
+#elif defined(_MSC_VER)
+#define JSONCONS_LIKELY(x) x
+#define JSONCONS_UNLIKELY(x) x
+#define JSONCONS_UNREACHABLE() __assume(0)
+#else
+#define JSONCONS_LIKELY(x) x
+#define JSONCONS_UNLIKELY(x) x
+#define JSONCONS_UNREACHABLE() do {} while (0)
+#endif
+
+namespace jsoncons
+{
+
+#if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013
+#else
+#define JSONCONS_NO_CONSTEXPR
+#endif
+
+#define JSONCONS_NO_TO_CHARS
+
+#if defined(_MSC_VER)
+#if _MSC_VER >= 1900
+#define JSONCONS_HAS_USER_DEFINED_LITERALS
+#endif
+#else
+#define JSONCONS_HAS_USER_DEFINED_LITERALS
+#endif
+
+//#define JSONCONS_HAS_STRING_VIEW
+
+#if defined(ANDROID) || defined(__ANDROID__)
+#define JSONCONS_HAS_STRTOLD_L
+#define JSONCONS_NO_LOCALECONV
+#endif
+
+#if defined (__clang__)
+#if defined(_GLIBCXX_USE_NOEXCEPT)
+#define JSONCONS_NOEXCEPT _GLIBCXX_USE_NOEXCEPT
+#else
+#define JSONCONS_NOEXCEPT noexcept
+#endif
+#elif defined(__GNUC__)
+#define JSONCONS_NOEXCEPT _GLIBCXX_USE_NOEXCEPT
+#elif defined(_MSC_VER)
+#if _MSC_VER >= 1900
+#define JSONCONS_NOEXCEPT noexcept
+#else
+#define JSONCONS_NOEXCEPT
+#endif
+#else
+#define JSONCONS_NOEXCEPT
+#endif
+
+#if defined(_MSC_VER)
+#define JSONCONS_HAS_MSC__STRTOD_L
+#define JSONCONS_HAS__ECVT_S
+#define JSONCONS_HAS_FOPEN_S
+#if _MSC_VER >= 1900
+#define JSONCONS_ALIGNOF alignof
+#else
+#define JSONCONS_ALIGNOF __alignof
+#endif
+#else
+#define JSONCONS_ALIGNOF alignof
+#endif
+
+#define JSONCONS_DEFINE_LITERAL( name, lit ) \
+template< class Ch > Ch const* name(); \
+template<> inline char const * name<char>() { return lit; } \
+template<> inline wchar_t const* name<wchar_t>() { return L ## lit; }
+
+}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/jsoncons_utilities.hpp b/vendor/jsoncons-0.104.0/jsoncons/jsoncons_utilities.hpp
new file mode 100644
index 00000000..28a9eb71
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/jsoncons_utilities.hpp
@@ -0,0 +1,954 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSONCONSUTILITIES_HPP
+#define JSONCONS_JSONCONSUTILITIES_HPP
+
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+#include <cstdarg>
+#include <locale>
+#include <limits>
+#include <type_traits>
+#include <algorithm>
+#include <memory>
+#include <iterator>
+#include <exception>
+#include <array>
+#include <initializer_list>
+#include <jsoncons/jsoncons_config.hpp>
+#include <jsoncons/json_exception.hpp>
+#if !defined(JSONCONS_NO_TO_CHARS)
+#include <charconv>
+#endif
+#include <jsoncons/detail/obufferedstream.hpp>
+
+namespace jsoncons
+{
+
+#if !defined(JSONCONS_HAS_STRING_VIEW)
+template <class CharT, class Traits = std::char_traits<CharT>>
+class Basic_string_view_
+{
+private:
+ const CharT* data_;
+ size_t length_;
+public:
+ typedef CharT value_type;
+ typedef const CharT& const_reference;
+ typedef Traits traits_type;
+ typedef std::size_t size_type;
+ static const size_type npos = size_type(-1);
+ typedef const CharT* const_iterator;
+ typedef const CharT* iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ Basic_string_view_()
+ : data_(nullptr), length_(0)
+ {
+ }
+ Basic_string_view_(const CharT* data, size_t length)
+ : data_(data), length_(length)
+ {
+ }
+ Basic_string_view_(const CharT* data)
+ : data_(data), length_(Traits::length(data))
+ {
+ }
+ Basic_string_view_(const Basic_string_view_& other) = default;
+
+ template <class Allocator>
+ Basic_string_view_(const std::basic_string<CharT,Traits,Allocator>& s)
+ : data_(s.data()), length_(s.length())
+ {
+ }
+
+ template <class Allocator>
+ explicit operator std::basic_string<CharT,Traits,Allocator>() const
+ {
+ return std::basic_string<CharT,Traits>(data_,length_);
+ }
+
+ // iterator support
+ const_iterator begin() const JSONCONS_NOEXCEPT
+ {
+ return data_;
+ }
+ const_iterator end() const JSONCONS_NOEXCEPT
+ {
+ return data_ + length_;
+ }
+ const_iterator cbegin() const JSONCONS_NOEXCEPT
+ {
+ return data_;
+ }
+ const_iterator cend() const JSONCONS_NOEXCEPT
+ {
+ return data_ + length_;
+ }
+ const_reverse_iterator rbegin() const JSONCONS_NOEXCEPT
+ {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator rend() const JSONCONS_NOEXCEPT
+ {
+ return const_reverse_iterator(begin());
+ }
+ const_reverse_iterator crbegin() const JSONCONS_NOEXCEPT
+ {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator crend() const JSONCONS_NOEXCEPT
+ {
+ return const_reverse_iterator(begin());
+ }
+
+ // capacity
+
+ size_t size() const
+ {
+ return length_;
+ }
+
+ size_t length() const
+ {
+ return length_;
+ }
+ size_type max_size() const JSONCONS_NOEXCEPT
+ {
+ return length_;
+ }
+ bool empty() const JSONCONS_NOEXCEPT
+ {
+ return length_ == 0;
+ }
+
+ // element access
+
+ const_reference operator[](size_type pos) const
+ {
+ return data_[pos];
+ }
+
+ const_reference at(size_t pos) const
+ {
+ if (pos >= length_)
+ {
+ JSONCONS_THROW(json_exception_impl<std::out_of_range>("pos exceeds length"));
+ }
+ return data_[pos];
+ }
+
+ const_reference front() const
+ {
+ return data_[0];
+ }
+ const_reference back() const
+ {
+ return data_[length_-1];
+ }
+
+ const CharT* data() const
+ {
+ return data_;
+ }
+
+ // string operations
+
+ Basic_string_view_ substr(size_type pos, size_type n=npos) const
+ {
+ if (pos > length_)
+ {
+ JSONCONS_THROW(json_exception_impl<std::out_of_range>("pos exceeds size"));
+ }
+ if (n == npos || pos + n > length_)
+ {
+ n = length_ - pos;
+ }
+ return Basic_string_view_(data_ + pos, n);
+ }
+
+ int compare(Basic_string_view_ s) const
+ {
+ const int rc = Traits::compare(data_, s.data_, (std::min)(length_, s.length_));
+ return rc != 0 ? rc : (length_ == s.length_ ? 0 : length_ < s.length_ ? -1 : 1);
+ }
+
+ int compare(const CharT* data) const
+ {
+ const size_t length = Traits::length(data);
+ const int rc = Traits::compare(data_, data, (std::min)(length_, length));
+ return rc != 0 ? rc : (length_ == length? 0 : length_ < length? -1 : 1);
+ }
+
+ template <class Allocator>
+ int compare(const std::basic_string<CharT,Traits,Allocator>& s) const
+ {
+ const int rc = Traits::compare(data_, s.data(), (std::min)(length_, s.length()));
+ return rc != 0 ? rc : (length_ == s.length() ? 0 : length_ < s.length() ? -1 : 1);
+ }
+
+ size_type find(Basic_string_view_ s, size_type pos = 0) const JSONCONS_NOEXCEPT
+ {
+ if (pos > length_)
+ {
+ return npos;
+ }
+ if (s.length_ == 0)
+ {
+ return pos;
+ }
+ const_iterator it = std::search(cbegin() + pos, cend(),
+ s.cbegin(), s.cend(), Traits::eq);
+ return it == cend() ? npos : std::distance(cbegin(), it);
+ }
+ size_type find(CharT ch, size_type pos = 0) const JSONCONS_NOEXCEPT
+ {
+ return find(Basic_string_view_(&ch, 1), pos);
+ }
+ size_type find(const CharT* s, size_type pos, size_type n) const JSONCONS_NOEXCEPT
+ {
+ return find(Basic_string_view_(s, n), pos);
+ }
+ size_type find(const CharT* s, size_type pos = 0) const JSONCONS_NOEXCEPT
+ {
+ return find(Basic_string_view_(s), pos);
+ }
+
+ size_type rfind(Basic_string_view_ s, size_type pos = npos) const JSONCONS_NOEXCEPT
+ {
+ if (length_ < s.length_)
+ {
+ return npos;
+ }
+ if (pos > length_ - s.length_)
+ {
+ pos = length_ - s.length_;
+ }
+ if (s.length_ == 0)
+ {
+ return pos;
+ }
+ for (const CharT* p = data_ + pos; true; --p)
+ {
+ if (Traits::compare(p, s.data_, s.length_) == 0)
+ {
+ return p - data_;
+ }
+ if (p == data_)
+ {
+ return npos;
+ }
+ };
+ }
+ size_type rfind(CharT ch, size_type pos = npos) const JSONCONS_NOEXCEPT
+ {
+ return rfind(Basic_string_view_(&ch, 1), pos);
+ }
+ size_type rfind(const CharT* s, size_type pos, size_type n) const JSONCONS_NOEXCEPT
+ {
+ return rfind(Basic_string_view_(s, n), pos);
+ }
+ size_type rfind(const CharT* s, size_type pos = npos) const JSONCONS_NOEXCEPT
+ {
+ return rfind(Basic_string_view_(s), pos);
+ }
+
+ size_type find_first_of(Basic_string_view_ s, size_type pos = 0) const JSONCONS_NOEXCEPT
+ {
+ if (pos >= length_ || s.length_ == 0)
+ {
+ return npos;
+ }
+ const_iterator it = std::find_first_of
+ (cbegin() + pos, cend(), s.cbegin(), s.cend(), Traits::eq);
+ return it == cend() ? npos : std::distance (cbegin(), it);
+ }
+ size_type find_first_of(CharT ch, size_type pos = 0) const JSONCONS_NOEXCEPT
+ {
+ return find_first_of(Basic_string_view_(&ch, 1), pos);
+ }
+ size_type find_first_of(const CharT* s, size_type pos, size_type n) const JSONCONS_NOEXCEPT
+ {
+ return find_first_of(Basic_string_view_(s, n), pos);
+ }
+ size_type find_first_of(const CharT* s, size_type pos = 0) const JSONCONS_NOEXCEPT
+ {
+ return find_first_of(Basic_string_view_(s), pos);
+ }
+
+ size_type find_last_of(Basic_string_view_ s, size_type pos = npos) const JSONCONS_NOEXCEPT
+ {
+ if (s.length_ == 0)
+ {
+ return npos;
+ }
+ if (pos >= length_)
+ {
+ pos = 0;
+ }
+ else
+ {
+ pos = length_ - (pos+1);
+ }
+ const_reverse_iterator it = std::find_first_of
+ (crbegin() + pos, crend(), s.cbegin(), s.cend(), Traits::eq);
+ return it == crend() ? npos : (length_ - 1 - std::distance(crbegin(), it));
+ }
+ size_type find_last_of(CharT ch, size_type pos = npos) const JSONCONS_NOEXCEPT
+ {
+ return find_last_of(Basic_string_view_(&ch, 1), pos);
+ }
+ size_type find_last_of(const CharT* s, size_type pos, size_type n) const JSONCONS_NOEXCEPT
+ {
+ return find_last_of(Basic_string_view_(s, n), pos);
+ }
+ size_type find_last_of(const CharT* s, size_type pos = npos) const JSONCONS_NOEXCEPT
+ {
+ return find_last_of(Basic_string_view_(s), pos);
+ }
+
+ size_type find_first_not_of(Basic_string_view_ s, size_type pos = 0) const JSONCONS_NOEXCEPT
+ {
+ if (pos >= length_)
+ return npos;
+ if (s.length_ == 0)
+ return pos;
+
+ const_iterator it = cend();
+ for (auto p = cbegin()+pos; p != cend(); ++p)
+ {
+ if (Traits::find(s.data_, s.length_, *p) == 0)
+ {
+ it = p;
+ break;
+ }
+ }
+ return it == cend() ? npos : std::distance (cbegin(), it);
+ }
+ size_type find_first_not_of(CharT ch, size_type pos = 0) const JSONCONS_NOEXCEPT
+ {
+ return find_first_not_of(Basic_string_view_(&ch, 1), pos);
+ }
+ size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const JSONCONS_NOEXCEPT
+ {
+ return find_first_not_of(Basic_string_view_(s, n), pos);
+ }
+ size_type find_first_not_of(const CharT* s, size_type pos = 0) const JSONCONS_NOEXCEPT
+ {
+ return find_first_not_of(Basic_string_view_(s), pos);
+ }
+
+ size_type find_last_not_of(Basic_string_view_ s, size_type pos = npos) const JSONCONS_NOEXCEPT
+ {
+ if (pos >= length_)
+ {
+ pos = length_ - 1;
+ }
+ if (s.length_ == 0)
+ {
+ return pos;
+ }
+ pos = length_ - (pos+1);
+
+ const_iterator it = crend();
+ for (auto p = crbegin()+pos; p != crend(); ++p)
+ {
+ if (Traits::find(s.data_, s.length_, *p) == 0)
+ {
+ it = p;
+ break;
+ }
+ }
+ return it == crend() ? npos : (length_ - 1 - std::distance(crbegin(), it));
+ }
+ size_type find_last_not_of(CharT ch, size_type pos = npos) const JSONCONS_NOEXCEPT
+ {
+ return find_last_not_of(Basic_string_view_(&ch, 1), pos);
+ }
+ size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const JSONCONS_NOEXCEPT
+ {
+ return find_last_not_of(Basic_string_view_(s, n), pos);
+ }
+ size_type find_last_not_of(const CharT* s, size_type pos = npos) const JSONCONS_NOEXCEPT
+ {
+ return find_last_not_of(Basic_string_view_(s), pos);
+ }
+
+ friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const Basic_string_view_& sv)
+ {
+ os.write(sv.data_,sv.length_);
+ return os;
+ }
+};
+
+// ==
+template<class CharT,class Traits>
+bool operator==(const Basic_string_view_<CharT,Traits>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return lhs.compare(rhs) == 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator==(const Basic_string_view_<CharT,Traits>& lhs,
+ const std::basic_string<CharT,Traits,Allocator>& rhs)
+{
+ return lhs.compare(rhs) == 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator==(const std::basic_string<CharT,Traits,Allocator>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return rhs.compare(lhs) == 0;
+}
+template<class CharT,class Traits>
+bool operator==(const Basic_string_view_<CharT,Traits>& lhs,
+ const CharT* rhs)
+{
+ return lhs.compare(rhs) == 0;
+}
+template<class CharT,class Traits>
+bool operator==(const CharT* lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return rhs.compare(lhs) == 0;
+}
+
+// !=
+template<class CharT,class Traits>
+bool operator!=(const Basic_string_view_<CharT,Traits>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return lhs.compare(rhs) != 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator!=(const Basic_string_view_<CharT,Traits>& lhs,
+ const std::basic_string<CharT,Traits,Allocator>& rhs)
+{
+ return lhs.compare(rhs) != 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator!=(const std::basic_string<CharT,Traits,Allocator>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return rhs.compare(lhs) != 0;
+}
+template<class CharT,class Traits>
+bool operator!=(const Basic_string_view_<CharT,Traits>& lhs,
+ const CharT* rhs)
+{
+ return lhs.compare(rhs) != 0;
+}
+template<class CharT,class Traits>
+bool operator!=(const CharT* lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return rhs.compare(lhs) != 0;
+}
+
+// <=
+template<class CharT,class Traits>
+bool operator<=(const Basic_string_view_<CharT,Traits>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return lhs.compare(rhs) <= 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator<=(const Basic_string_view_<CharT,Traits>& lhs,
+ const std::basic_string<CharT,Traits,Allocator>& rhs)
+{
+ return lhs.compare(rhs) <= 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator<=(const std::basic_string<CharT,Traits,Allocator>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return rhs.compare(lhs) >= 0;
+}
+
+// <
+template<class CharT,class Traits>
+bool operator<(const Basic_string_view_<CharT,Traits>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return lhs.compare(rhs) < 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator<(const Basic_string_view_<CharT,Traits>& lhs,
+ const std::basic_string<CharT,Traits,Allocator>& rhs)
+{
+ return lhs.compare(rhs) < 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator<(const std::basic_string<CharT,Traits,Allocator>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return rhs.compare(lhs) > 0;
+}
+
+// >=
+template<class CharT,class Traits>
+bool operator>=(const Basic_string_view_<CharT,Traits>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return lhs.compare(rhs) >= 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator>=(const Basic_string_view_<CharT,Traits>& lhs,
+ const std::basic_string<CharT,Traits,Allocator>& rhs)
+{
+ return lhs.compare(rhs) >= 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator>=(const std::basic_string<CharT,Traits,Allocator>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return rhs.compare(lhs) <= 0;
+}
+
+// >
+template<class CharT,class Traits>
+bool operator>(const Basic_string_view_<CharT,Traits>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return lhs.compare(rhs) > 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator>(const Basic_string_view_<CharT,Traits>& lhs,
+ const std::basic_string<CharT,Traits,Allocator>& rhs)
+{
+ return lhs.compare(rhs) > 0;
+}
+template<class CharT,class Traits,class Allocator>
+bool operator>(const std::basic_string<CharT,Traits,Allocator>& lhs,
+ const Basic_string_view_<CharT,Traits>& rhs)
+{
+ return rhs.compare(lhs) < 0;
+}
+#endif
+
+#if !defined(JSONCONS_HAS_STRING_VIEW)
+template <class CharT, class Traits = std::char_traits<CharT>>
+using basic_string_view_ext = Basic_string_view_<CharT, Traits>;
+#else
+#include <string_view>
+template <class CharT, class Traits = std::char_traits<CharT>>
+using basic_string_view_ext = std::basic_string_view<CharT, Traits>;
+#endif
+
+#if !defined(JSONCONS_NO_TO_CHARS)
+using chars_format = std::chars_format;
+#else
+enum class chars_format : uint8_t {fixed=1,scientific=2,hex=4,general=fixed|scientific};
+#endif
+
+// number_format
+
+class number_format
+{
+ chars_format format_;
+ uint8_t precision_;
+ uint8_t decimal_places_;
+public:
+ number_format()
+ : format_(chars_format::general), precision_(0), decimal_places_(0)
+ {
+ }
+
+ number_format(uint8_t precision, uint8_t decimal_places)
+ : format_(chars_format::general), precision_(precision), decimal_places_(decimal_places)
+ {
+ }
+
+ number_format(chars_format format, uint8_t precision, uint8_t decimal_places)
+ : format_(format), precision_(precision), decimal_places_(decimal_places)
+ {
+ }
+
+ number_format(chars_format format)
+ : format_(format), precision_(0), decimal_places_(0)
+ {
+ }
+
+ number_format(const number_format&) = default;
+ number_format(number_format&&) = default;
+ number_format& operator=(const number_format& e) = default;
+ number_format& operator=(number_format&& e) = default;
+
+ uint8_t precision() const
+ {
+ return precision_;
+ }
+
+ uint8_t decimal_places() const
+ {
+ return decimal_places_;
+ }
+
+ chars_format floating_point_format() const
+ {
+ return format_;
+ }
+};
+
+// byte_string_view
+class byte_string_view
+{
+ const uint8_t* data_;
+ size_t length_;
+public:
+ typedef const uint8_t* const_iterator;
+ typedef const uint8_t* iterator;
+ typedef std::size_t size_type;
+
+ byte_string_view(const uint8_t* data, size_t length)
+ : data_(data), length_(length)
+ {
+ }
+
+ const uint8_t* data() const
+ {
+ return data_;
+ }
+
+ size_t length() const
+ {
+ return length_;
+ }
+
+ size_t size() const
+ {
+ return length_;
+ }
+
+ // iterator support
+ const_iterator begin() const JSONCONS_NOEXCEPT
+ {
+ return data_;
+ }
+ const_iterator end() const JSONCONS_NOEXCEPT
+ {
+ return data_ + length_;
+ }
+
+ uint8_t operator[](size_type pos) const
+ {
+ return data_[pos];
+ }
+
+ friend bool operator==(const byte_string_view& lhs, const byte_string_view& rhs)
+ {
+ if (lhs.length() != rhs.length())
+ {
+ return false;
+ }
+ for (size_t i = 0; i < lhs.length(); ++i)
+ {
+ if (lhs[i] != rhs[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ friend bool operator!=(const byte_string_view& lhs, const byte_string_view& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+ template <class CharT>
+ friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const byte_string_view& o)
+ {
+ std::basic_ostringstream<CharT> ss;
+ ss.flags(std::ios::hex | std::ios::showbase);
+ for (auto b : o)
+ {
+ ss << (int)b;
+ }
+ os << ss.str();
+ return os;
+ }
+};
+
+// basic_byte_string
+template <class Allocator = std::allocator<uint8_t>>
+class basic_byte_string
+{
+ std::vector<uint8_t,Allocator> data_;
+public:
+ typedef typename std::vector<uint8_t,Allocator>::const_iterator const_iterator;
+ typedef typename std::vector<uint8_t,Allocator>::const_iterator iterator;
+ typedef std::size_t size_type;
+
+ basic_byte_string() = default;
+
+ explicit basic_byte_string(const Allocator& alloc)
+ : data_(alloc)
+ {
+ }
+
+ basic_byte_string(std::initializer_list<uint8_t> init)
+ : data_(std::move(init))
+ {
+ }
+
+ basic_byte_string(std::initializer_list<uint8_t> init, const Allocator& alloc)
+ : data_(std::move(init), alloc)
+ {
+ }
+
+ explicit basic_byte_string(const byte_string_view& v)
+ : data_(v.begin(),v.end())
+ {
+ }
+
+ basic_byte_string(const byte_string_view& v, const Allocator& alloc)
+ : data_(v.begin(),v.end(),alloc)
+ {
+ }
+
+ basic_byte_string(const char* s)
+ {
+ while (*s)
+ {
+ data_.push_back(*s++);
+ }
+ }
+
+ basic_byte_string(const uint8_t* data, size_t length)
+ {
+ data_.insert(data,data+length);
+ }
+
+ basic_byte_string(const basic_byte_string& s) = default;
+
+ basic_byte_string(basic_byte_string&& s) = default;
+
+ basic_byte_string& operator=(const basic_byte_string& s) = default;
+
+ basic_byte_string& operator=(basic_byte_string&& s) = default;
+
+ operator byte_string_view() const JSONCONS_NOEXCEPT
+ {
+ return byte_string_view(data(),length());
+ }
+
+ void push_back(uint8_t b)
+ {
+ data_.push_back(b);
+ }
+
+ void assign(const uint8_t* s, size_t count)
+ {
+ data_.clear();
+ data_.insert(s, s+count);
+ }
+
+ void append(const uint8_t* s, size_t count)
+ {
+ data_.insert(s, s+count);
+ }
+
+ void clear()
+ {
+ data_.clear();
+ }
+
+ uint8_t operator[](size_type pos) const
+ {
+ return data_[pos];
+ }
+
+ // iterator support
+ const_iterator begin() const JSONCONS_NOEXCEPT
+ {
+ return data_.begin();
+ }
+ const_iterator end() const JSONCONS_NOEXCEPT
+ {
+ return data_.end();
+ }
+
+ const uint8_t* data() const
+ {
+ return data_.data();
+ }
+
+ size_t size() const
+ {
+ return data_.size();
+ }
+
+ size_t length() const
+ {
+ return data_.size();
+ }
+
+ friend bool operator==(const basic_byte_string& lhs, const basic_byte_string& rhs)
+ {
+ return byte_string_view(lhs) == byte_string_view(rhs);
+ }
+
+ friend bool operator!=(const basic_byte_string& lhs, const basic_byte_string& rhs)
+ {
+ return byte_string_view(lhs) != byte_string_view(rhs);
+ }
+
+ template <class CharT>
+ friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const basic_byte_string& o)
+ {
+ os << byte_string_view(o);
+ return os;
+ }
+};
+
+typedef basic_byte_string<std::allocator<uint8_t>> byte_string;
+
+static const std::string base64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/"
+ "=";
+static const std::string base64url_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789-_"
+ "\0";
+
+inline
+static bool is_base64(uint8_t c)
+{
+ return isalnum(c) || c == '+' || c == '/';
+}
+
+template <class InputIt,class CharT>
+void encode_base64(InputIt first, InputIt last, const std::string& alphabet, std::basic_string<CharT>& result)
+{
+ unsigned char a3[3];
+ unsigned char a4[4];
+ unsigned char fill = alphabet.back();
+ int i = 0;
+ int j = 0;
+
+ while (first != last)
+ {
+ a3[i++] = *first++;
+ if (i == 3)
+ {
+ a4[0] = (a3[0] & 0xfc) >> 2;
+ a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
+ a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
+ a4[3] = a3[2] & 0x3f;
+
+ for (i = 0; i < 4; i++)
+ {
+ result.push_back(alphabet[a4[i]]);
+ }
+ i = 0;
+ }
+ }
+
+ if (i > 0)
+ {
+ for (j = i; j < 3; ++j)
+ {
+ a3[j] = 0;
+ }
+
+ a4[0] = (a3[0] & 0xfc) >> 2;
+ a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
+ a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
+
+ for (j = 0; j < i + 1; ++j)
+ {
+ result.push_back(alphabet[a4[j]]);
+ }
+
+ if (fill != 0)
+ {
+ while (i++ < 3)
+ {
+ result.push_back(fill);
+ }
+ }
+ }
+}
+
+template <class InputIt,class CharT>
+void encode_base64url(InputIt first, InputIt last, std::basic_string<CharT>& result)
+{
+ return encode_base64(first,last,base64url_alphabet,result);
+}
+
+template <class InputIt,class CharT>
+void encode_base64(InputIt first, InputIt last, std::basic_string<CharT>& result)
+{
+ encode_base64(first,last,base64_alphabet,result);
+}
+
+inline
+std::string decode_base64(const std::string& base64_string)
+{
+ std::string result;
+ uint8_t a4[4], a3[3];
+ uint8_t i = 0;
+ uint8_t j = 0;
+
+ auto first = base64_string.begin();
+ auto last = base64_string.end();
+
+ while (first != last && *first != '=')
+ {
+ JSONCONS_ASSERT(is_base64(*first));
+
+ a4[i++] = *first++;
+ if (i == 4)
+ {
+ for (i = 0; i < 4; ++i)
+ {
+ a4[i] = static_cast<uint8_t>(base64_alphabet.find(a4[i]));
+ }
+
+ a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
+ a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
+ a3[2] = ((a4[2] & 0x3) << 6) + a4[3];
+
+ for (i = 0; i < 3; i++)
+ {
+ result.push_back(a3[i]);
+ }
+ i = 0;
+ }
+ }
+
+ if (i > 0)
+ {
+ for (j = 0; j < i; ++j)
+ {
+ a4[j] = static_cast<uint8_t>(base64_alphabet.find(a4[j]));
+ }
+
+ a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
+ a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
+
+ for (j = 0; j < i - 1; ++j)
+ {
+ result.push_back(a3[j]);
+ }
+ }
+
+ return result;
+}
+
+}
+
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/parse_error_handler.hpp b/vendor/jsoncons-0.104.0/jsoncons/parse_error_handler.hpp
new file mode 100644
index 00000000..e38785ae
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/parse_error_handler.hpp
@@ -0,0 +1,165 @@
+/// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_PARSE_ERROR_HANDLER_HPP
+#define JSONCONS_PARSE_ERROR_HANDLER_HPP
+
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/json_error_category.hpp>
+#include <system_error>
+
+namespace jsoncons {
+
+class parse_error : public std::exception, public virtual json_exception
+{
+public:
+ parse_error()
+ : line_number_(0),
+ column_number_(0)
+ {
+ }
+ parse_error(std::error_code ec,
+ size_t line,
+ size_t column)
+ : error_code_(ec),
+ line_number_(line),
+ column_number_(column)
+ {
+ }
+ parse_error(const parse_error& other)
+ : error_code_(other.error_code_),
+ line_number_(other.line_number_),
+ column_number_(other.column_number_)
+ {
+ }
+
+ const char* what() const JSONCONS_NOEXCEPT override
+ {
+ try
+ {
+ std::ostringstream os;
+ os << error_code_.message() << " at line " << line_number_ << " and column " << column_number_;
+ const_cast<std::string&>(buffer_) = os.str();
+ return buffer_.c_str();
+ }
+ catch (...)
+ {
+ return "";
+ }
+ }
+
+ const std::error_code code() const
+ {
+ return error_code_;
+ }
+
+ size_t line_number() const
+ {
+ return line_number_;
+ }
+
+ size_t column_number() const
+ {
+ return column_number_;
+ }
+
+ parse_error& operator=(const parse_error& e)
+ {
+ error_code_ = e.error_code_;
+ line_number_ = e.line_number_;
+ column_number_ = e.column_number_;
+ return *this;
+ }
+private:
+ std::error_code error_code_;
+ std::string buffer_;
+ size_t line_number_;
+ size_t column_number_;
+};
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+typedef parse_error json_parse_exception;
+typedef parse_error parse_exception;
+#endif
+
+class parsing_context
+{
+public:
+ virtual ~parsing_context() = default;
+
+ size_t line_number() const
+ {
+ return do_line_number();
+ }
+ size_t column_number() const
+ {
+ return do_column_number();
+ }
+
+private:
+ virtual size_t do_line_number() const = 0;
+ virtual size_t do_column_number() const = 0;
+};
+
+class parse_error_handler
+{
+public:
+ virtual ~parse_error_handler()
+ {
+ }
+
+ bool error(std::error_code ec,
+ const parsing_context& context) JSONCONS_NOEXCEPT
+ {
+ return do_error(ec,context);
+ }
+
+ void fatal_error(std::error_code ec,
+ const parsing_context& context) JSONCONS_NOEXCEPT
+ {
+ do_fatal_error(ec,context);
+ }
+
+private:
+ virtual bool do_error(std::error_code,
+ const parsing_context& context) JSONCONS_NOEXCEPT = 0;
+
+ virtual void do_fatal_error(std::error_code,
+ const parsing_context&) JSONCONS_NOEXCEPT
+ {
+ }
+};
+
+class default_parse_error_handler : public parse_error_handler
+{
+private:
+ bool do_error(std::error_code code,
+ const parsing_context&) JSONCONS_NOEXCEPT override
+ {
+ static const std::error_code illegal_comment = make_error_code(json_parser_errc::illegal_comment);
+
+ if (code == illegal_comment)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+};
+
+class strict_parse_error_handler : public parse_error_handler
+{
+private:
+ bool do_error(std::error_code, const parsing_context&) JSONCONS_NOEXCEPT override
+ {
+ return true;
+ }
+};
+
+}
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/serialization_options.hpp b/vendor/jsoncons-0.104.0/jsoncons/serialization_options.hpp
new file mode 100644
index 00000000..18be2ce3
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/serialization_options.hpp
@@ -0,0 +1,279 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_SERIALIZATION_OPTIONS_HPP
+#define JSONCONS_SERIALIZATION_OPTIONS_HPP
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <cstdlib>
+#include <limits>
+#include <cwchar>
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/jsoncons_utilities.hpp>
+#include <jsoncons/detail/type_traits_helper.hpp>
+
+namespace jsoncons {
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+enum class block_options {next_line,same_line};
+#endif
+
+enum class line_split_kind{same_line,new_line,multi_line};
+
+template <class CharT,class Allocator=std::allocator<CharT>>
+class basic_serialization_options
+{
+public:
+ typedef basic_string_view_ext<CharT> string_view_type;
+ typedef CharT char_type;
+ typedef Allocator allocator_type;
+ typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<CharT> char_allocator_type;
+ typedef std::basic_string<CharT,std::char_traits<CharT>,char_allocator_type> string_type;
+private:
+ int indent_;
+ uint8_t precision_;
+ uint8_t decimal_places_;
+ bool replace_nan_;
+ bool replace_pos_inf_;
+ bool replace_neg_inf_;
+ string_type nan_replacement_;
+ string_type pos_inf_replacement_;
+ string_type neg_inf_replacement_;
+ bool escape_all_non_ascii_;
+ bool escape_solidus_;
+
+ line_split_kind object_object_split_lines_;
+ line_split_kind object_array_split_lines_;
+ line_split_kind array_array_split_lines_;
+ line_split_kind array_object_split_lines_;
+
+ chars_format floating_point_format_;
+public:
+ static const size_t default_indent = 4;
+
+// Constructors
+
+ basic_serialization_options()
+ :
+ indent_(default_indent),
+ precision_(0),
+ replace_nan_(true),
+ replace_pos_inf_(true),
+ replace_neg_inf_(true),
+ nan_replacement_(detail::null_literal<CharT>()),
+ pos_inf_replacement_(detail::null_literal<CharT>()),
+ neg_inf_replacement_(detail::null_literal<CharT>()),
+ escape_all_non_ascii_(false),
+ escape_solidus_(false),
+ object_object_split_lines_(line_split_kind::multi_line),
+ object_array_split_lines_(line_split_kind::same_line),
+ array_array_split_lines_(line_split_kind::new_line),
+ array_object_split_lines_(line_split_kind::multi_line)
+ {
+ }
+
+// Accessors
+ line_split_kind object_object_split_lines() const {return object_object_split_lines_;}
+ line_split_kind array_object_split_lines() const {return array_object_split_lines_;}
+ line_split_kind object_array_split_lines() const {return object_array_split_lines_;}
+ line_split_kind array_array_split_lines() const {return array_array_split_lines_;}
+
+ basic_serialization_options<CharT>& object_object_split_lines(line_split_kind value) {object_object_split_lines_ = value; return *this;}
+ basic_serialization_options<CharT>& array_object_split_lines(line_split_kind value) {array_object_split_lines_ = value; return *this;}
+ basic_serialization_options<CharT>& object_array_split_lines(line_split_kind value) {object_array_split_lines_ = value; return *this;}
+ basic_serialization_options<CharT>& array_array_split_lines(line_split_kind value) {array_array_split_lines_ = value; return *this;}
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+ block_options array_array_block_option()
+ {
+ return (array_array_split_lines_ == line_split_kind::same_line) ? block_options::same_line : block_options::next_line;
+ }
+
+ basic_serialization_options<CharT>& array_array_block_option(block_options value)
+ {
+ array_array_split_lines_ = (value == block_options::same_line) ? line_split_kind::same_line : line_split_kind::new_line;
+ return *this;
+ }
+
+ block_options array_object_block_option()
+ {
+ return (array_object_split_lines_ == line_split_kind::same_line) ? block_options::same_line : block_options::next_line;
+ }
+
+ basic_serialization_options<CharT>& array_object_block_option(block_options value)
+ {
+ array_object_split_lines_ = (value == block_options::same_line) ? line_split_kind::same_line : line_split_kind::new_line;
+ return *this;
+ }
+
+ block_options object_array_block_option()
+ {
+ return (object_array_split_lines_ == line_split_kind::same_line) ? block_options::same_line : block_options::next_line;
+ }
+
+ basic_serialization_options<CharT>& object_array_block_option(block_options value)
+ {
+ object_array_split_lines_ = (value == block_options::same_line) ? line_split_kind::same_line : line_split_kind::new_line;
+ return *this;
+ }
+
+ block_options object_object_block_option()
+ {
+ return (object_object_split_lines_ == line_split_kind::same_line) ? block_options::same_line : block_options::next_line;
+ }
+
+ basic_serialization_options<CharT>& object_object_block_option(block_options value)
+ {
+ object_object_split_lines_ = (value == block_options::same_line) ? line_split_kind::same_line : line_split_kind::new_line;
+ return *this;
+ }
+#endif
+
+ int indent() const
+ {
+ return indent_;
+ }
+
+ basic_serialization_options<CharT>& indent(int value)
+ {
+ indent_ = value;
+ return *this;
+ }
+
+ chars_format floating_point_format() const
+ {
+ return floating_point_format_;
+ }
+
+ basic_serialization_options<CharT>& floating_point_format(chars_format value)
+ {
+ floating_point_format_ = value;
+ return *this;
+ }
+
+ uint8_t precision() const
+ {
+ return precision_;
+ }
+
+ basic_serialization_options<CharT>& precision(uint8_t value)
+ {
+ precision_ = value;
+ return *this;
+ }
+
+ uint8_t decimal_places() const
+ {
+ return decimal_places_;
+ }
+
+ basic_serialization_options<CharT>& decimal_places(uint8_t value)
+ {
+ decimal_places_ = value;
+ return *this;
+ }
+
+ bool escape_all_non_ascii() const
+ {
+ return escape_all_non_ascii_;
+ }
+
+ basic_serialization_options<CharT>& escape_all_non_ascii(bool value)
+ {
+ escape_all_non_ascii_ = value;
+ return *this;
+ }
+
+ bool escape_solidus() const
+ {
+ return escape_solidus_;
+ }
+
+ basic_serialization_options<CharT>& escape_solidus(bool value)
+ {
+ escape_solidus_ = value;
+ return *this;
+ }
+
+ bool replace_nan() const {return replace_nan_;}
+
+ basic_serialization_options<CharT>& replace_nan(bool replace)
+ {
+ replace_nan_ = replace;
+ return *this;
+ }
+
+ bool replace_pos_inf() const {return replace_pos_inf_;}
+
+ bool replace_neg_inf() const {return replace_neg_inf_;}
+
+ basic_serialization_options<CharT>& replace_inf(bool replace)
+ {
+ replace_pos_inf_ = replace;
+ replace_neg_inf_ = replace;
+ return *this;
+ }
+
+ basic_serialization_options<CharT>& replace_pos_inf(bool replace)
+ {
+ replace_pos_inf_ = replace;
+ return *this;
+ }
+
+ basic_serialization_options<CharT>& replace_neg_inf(bool replace)
+ {
+ replace_neg_inf_ = replace;
+ return *this;
+ }
+
+ const string_type& nan_replacement() const
+ {
+ return nan_replacement_;
+ }
+
+ basic_serialization_options<CharT>& nan_replacement(const string_type& replacement)
+ {
+ nan_replacement_ = replacement;
+ return *this;
+ }
+
+ basic_serialization_options<CharT>& neg_inf_replacement(const string_type& replacement)
+ {
+ neg_inf_replacement_ = replacement;
+ return *this;
+ }
+
+ const string_type& pos_inf_replacement() const
+ {
+ return pos_inf_replacement_;
+ }
+
+ basic_serialization_options<CharT>& pos_inf_replacement(const string_type& replacement)
+ {
+ pos_inf_replacement_ = replacement;
+ return *this;
+ }
+
+ const string_type& neg_inf_replacement() const
+ {
+ return neg_inf_replacement_;
+ }
+};
+
+typedef basic_serialization_options<char> serialization_options;
+typedef basic_serialization_options<wchar_t> wserialization_options;
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+typedef basic_serialization_options<char> output_format;
+typedef basic_serialization_options<wchar_t> woutput_format;
+#endif
+
+}
+#endif
diff --git a/vendor/jsoncons-0.104.0/jsoncons/serialization_traits.hpp b/vendor/jsoncons-0.104.0/jsoncons/serialization_traits.hpp
new file mode 100644
index 00000000..aa22769f
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/serialization_traits.hpp
@@ -0,0 +1,315 @@
+// Copyright 2017 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_SERIALIZATION_TRAITS_HPP
+#define JSONCONS_SERIALIZATION_TRAITS_HPP
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+#endif
+
+#include <iostream>
+#include <string>
+#include <tuple>
+#include <array>
+#include <type_traits>
+#include <memory>
+#include <jsoncons/json_output_handler.hpp>
+#include <jsoncons/serialization_options.hpp>
+#include <jsoncons/json_serializer.hpp>
+#include <jsoncons/jsoncons_utilities.hpp>
+
+namespace jsoncons {
+
+// serialization_traits
+
+template <class T, class Enable = void>
+struct serialization_traits
+{
+ template <class CharT>
+ static void encode(const T&, basic_json_output_handler<CharT>&)
+ {
+ }
+};
+
+// dump
+
+template <class CharT, class T>
+void dump(const T& val, basic_json_output_handler<CharT>& handler)
+{
+ handler.begin_json();
+ serialization_traits<T>::encode(val,handler);
+ handler.end_json();
+}
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+template <class CharT, class T>
+void dump_body(const T& val, basic_json_output_handler<CharT>& handler)
+{
+ dump_fragment(val,handler);
+}
+#endif
+
+template <class CharT, class T>
+void dump_fragment(const T& val, basic_json_output_handler<CharT>& handler)
+{
+ serialization_traits<T>::encode(val,handler);
+}
+
+template <class CharT, class T>
+void dump(const T& val, std::basic_ostream<CharT>& os)
+{
+ basic_json_serializer<CharT> serializer(os);
+ dump(val, serializer);
+}
+
+template <class CharT, class T>
+void dump(const T& val, const basic_serialization_options<CharT>& options,
+ std::basic_ostream<CharT>& os)
+{
+ basic_json_serializer<CharT> serializer(os, options);
+ dump(val, serializer);
+}
+
+template <class CharT, class T>
+void dump(const T& val, std::basic_ostream<CharT>& os, bool pprint)
+{
+ basic_json_serializer<CharT> serializer(os, pprint);
+ dump(val, serializer);
+}
+
+template <class CharT, class T>
+void dump(const T& val, const basic_serialization_options<CharT>& options,
+ std::basic_ostream<CharT>& os, bool pprint)
+{
+ basic_json_serializer<CharT> serializer(os, options, pprint);
+ dump(val, serializer);
+}
+
+// integer
+
+template<class T>
+struct serialization_traits<T,
+ typename std::enable_if<detail::is_integer_like<T>::value
+>::type>
+{
+ template <class CharT>
+ static void encode(T val, basic_json_output_handler<CharT>& handler)
+ {
+ handler.integer_value(val);
+ }
+};
+
+// uinteger
+
+template<class T>
+struct serialization_traits<T,
+ typename std::enable_if<detail::is_uinteger_like<T>::value
+>::type>
+{
+ template <class CharT>
+ static void encode(T val, basic_json_output_handler<CharT>& handler)
+ {
+ handler.uinteger_value(val);
+ }
+};
+
+// double
+
+template<class T>
+struct serialization_traits<T,
+ typename std::enable_if<detail::is_floating_point_like<T>::value
+>::type>
+{
+ template <class CharT>
+ static void encode(T val, basic_json_output_handler<CharT>& handler)
+ {
+ handler.double_value(val);
+ }
+};
+
+// bool
+
+template<>
+struct serialization_traits<bool>
+{
+ template <class CharT>
+ static void encode(bool val, basic_json_output_handler<CharT>& handler)
+ {
+ handler.bool_value(val);
+ }
+};
+
+// string
+
+template<class T>
+struct serialization_traits<T,
+ typename std::enable_if<detail::is_string_like<T>::value
+>::type>
+{
+ template <class CharT>
+ static void encode(const T& val, basic_json_output_handler<CharT>& handler)
+ {
+ handler.string_value(val);
+ }
+};
+
+/*template<>
+struct serialization_traits<typename type_wrapper<CharT>::const_pointer_type>
+{
+ template <class CharT>
+ static void encode(typename type_wrapper<CharT>::const_pointer_type val, basic_json_output_handler<CharT>& handler)
+ {
+ handler.string_value(val);
+ }
+};*/
+
+// sequence container (except string and array)
+
+template<class T>
+struct serialization_traits<T,
+ typename std::enable_if<detail::is_vector_like<T>::value
+>::type>
+{
+ typedef typename std::iterator_traits<typename T::iterator>::value_type value_type;
+
+ template <class CharT>
+ static void encode(const T& val, basic_json_output_handler<CharT>& handler)
+ {
+ handler.begin_array();
+ for (auto it = std::begin(val); it != std::end(val); ++it)
+ {
+ serialization_traits<value_type>::encode(*it,handler);
+ }
+ handler.end_array();
+ }
+};
+
+// std::array
+
+template<class T, size_t N>
+struct serialization_traits<std::array<T,N>>
+{
+ typedef typename std::array<T,N>::value_type value_type;
+public:
+
+ template <class CharT>
+ static void encode(const std::array<T, N>& val, basic_json_output_handler<CharT>& handler)
+ {
+ handler.begin_array();
+ for (auto it = std::begin(val); it != std::end(val); ++it)
+ {
+ serialization_traits<value_type>::encode(*it,handler);
+ }
+ handler.end_array();
+ }
+};
+
+// associative container
+
+template<class T>
+struct serialization_traits<T,
+ typename std::enable_if<detail::is_map_like<T>::value
+>::type>
+{
+ typedef typename T::mapped_type mapped_type;
+ typedef typename T::value_type value_type;
+
+ template <class CharT>
+ static void encode(const T& val, basic_json_output_handler<CharT>& handler)
+ {
+ handler.begin_object();
+ for (auto it = std::begin(val); it != std::end(val); ++it)
+ {
+ handler.name(it->first);
+ serialization_traits<mapped_type>::encode(it->second,handler);
+ }
+ handler.end_object();
+ }
+};
+
+namespace detail { namespace streaming {
+
+template<size_t Pos, class Tuple>
+struct tuple_helper
+{
+ using element_type = typename std::tuple_element<std::tuple_size<Tuple>::value - Pos, Tuple>::type;
+ using next = tuple_helper<Pos - 1, Tuple>;
+
+ template <class CharT>
+ static void encode(const Tuple& tuple, basic_json_output_handler<CharT>& handler)
+ {
+ serialization_traits<element_type>::encode(std::get<std::tuple_size<Tuple>::value - Pos>(tuple),handler);
+ next::encode(tuple, handler);
+ }
+};
+
+template<class Tuple>
+struct tuple_helper<0, Tuple>
+{
+ template <class CharT>
+ static void encode(const Tuple&, basic_json_output_handler<CharT>&)
+ {
+ }
+};
+
+}}
+
+template<typename... E>
+struct serialization_traits<std::tuple<E...>>
+{
+private:
+ using helper = detail::streaming::tuple_helper<sizeof...(E), std::tuple<E...>>;
+
+public:
+ template <class CharT>
+ static void encode(const std::tuple<E...>& value, basic_json_output_handler<CharT>& handler)
+ {
+ handler.begin_array();
+ helper::encode(value, handler);
+ handler.end_array();
+ }
+};
+
+template<class T1, class T2>
+struct serialization_traits<std::pair<T1,T2>>
+{
+public:
+
+ template <class CharT>
+ static void encode(const std::pair<T1,T2>& value, basic_json_output_handler<CharT>& handler)
+ {
+ handler.begin_array();
+ serialization_traits<T1>::encode(value.first, handler);
+ serialization_traits<T2>::encode(value.second, handler);
+ handler.end_array();
+ }
+};
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+template<class T>
+struct serialization_traits<std::shared_ptr<T>>
+{
+public:
+
+ template <class CharT>
+ static void encode(std::shared_ptr<T> p, basic_json_output_handler<CharT>& handler)
+ {
+ serialization_traits<T>::encode(*p, handler);
+ }
+};
+#endif
+
+}
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif
+
+
diff --git a/vendor/jsoncons-0.104.0/jsoncons/version.hpp b/vendor/jsoncons-0.104.0/jsoncons/version.hpp
new file mode 100644
index 00000000..c7971685
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/version.hpp
@@ -0,0 +1,50 @@
+// Copyright 2017 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_VERSION_HPP
+#define JSONCONS_VERSION_HPP
+
+#include <iostream>
+
+namespace jsoncons {
+
+struct versioning_info
+{
+ versioning_info(unsigned int major,
+ unsigned int minor,
+ unsigned int patch)
+ : major_(major),
+ minor_(minor),
+ patch_(patch)
+ {}
+
+ unsigned int const major_;
+ unsigned int const minor_;
+ unsigned int const patch_;
+
+ friend std::ostream& operator<<(std::ostream& os, const versioning_info& ver)
+ {
+ os << ver.major_ << '.'
+ << ver.minor_ << '.'
+ << ver.patch_;
+ return os;
+ }
+
+ versioning_info(const versioning_info&) = default;
+ versioning_info() = delete;
+ versioning_info& operator=(const versioning_info&) = delete;
+};
+
+inline
+versioning_info version()
+{
+ static versioning_info ver(0, 104, 0);
+ return ver;
+}
+
+}
+
+#endif