diff options
Diffstat (limited to 'vendor/jsoncons-0.104.0/jsoncons')
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 |