From 0f36ab53cbac06b61d1b4b6509590759ed8c6703 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 5 Oct 2016 18:45:08 +0200 Subject: Introduce jsoncons as replacement for jansson --- vendor/jsoncons-0.99.2/jsoncons/json.hpp | 3574 ++++++++++++++++++++ .../jsoncons-0.99.2/jsoncons/json_deserializer.hpp | 267 ++ .../jsoncons/json_error_category.hpp | 111 + vendor/jsoncons-0.99.2/jsoncons/json_filter.hpp | 324 ++ .../jsoncons/json_input_handler.hpp | 282 ++ .../jsoncons/json_output_handler.hpp | 262 ++ vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp | 1587 +++++++++ .../jsoncons-0.99.2/jsoncons/json_parser.hpp.orig | 2157 ++++++++++++ vendor/jsoncons-0.99.2/jsoncons/json_reader.hpp | 176 + .../jsoncons-0.99.2/jsoncons/json_serializer.hpp | 435 +++ .../jsoncons-0.99.2/jsoncons/json_structures.hpp | 860 +++++ .../jsoncons-0.99.2/jsoncons/json_type_traits.hpp | 594 ++++ vendor/jsoncons-0.99.2/jsoncons/jsoncons.hpp | 347 ++ .../jsoncons-0.99.2/jsoncons/jsoncons_config.hpp | 123 + vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp | 358 ++ vendor/jsoncons-0.99.2/jsoncons/output_format.hpp | 330 ++ vendor/jsoncons-0.99.2/jsoncons/ovectorstream.hpp | 227 ++ .../jsoncons/parse_error_handler.hpp | 172 + 18 files changed, 12186 insertions(+) create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_deserializer.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_error_category.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_filter.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_input_handler.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_output_handler.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp.orig create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_reader.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_serializer.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_structures.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/json_type_traits.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/jsoncons.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/jsoncons_config.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/output_format.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/ovectorstream.hpp create mode 100644 vendor/jsoncons-0.99.2/jsoncons/parse_error_handler.hpp (limited to 'vendor/jsoncons-0.99.2/jsoncons') diff --git a/vendor/jsoncons-0.99.2/jsoncons/json.hpp b/vendor/jsoncons-0.99.2/jsoncons/json.hpp new file mode 100644 index 00000000..b9058b59 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json.hpp @@ -0,0 +1,3574 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "jsoncons/json_structures.hpp" +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/json_output_handler.hpp" +#include "jsoncons/output_format.hpp" +#include "jsoncons/json_serializer.hpp" +#include "jsoncons/json_deserializer.hpp" +#include "jsoncons/json_reader.hpp" +#include "jsoncons/json_type_traits.hpp" + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch" +#endif + +namespace jsoncons { + +template +T* create_impl(const Alloc& allocator, Args&& ... args) +{ + typename std::allocator_traits:: template rebind_alloc alloc(allocator); + T* storage = alloc.allocate(1); + try + { + std::allocator_traits:: template rebind_traits::construct(alloc, storage, std::forward(args)...); + } + catch (...) + { + alloc.deallocate(storage,1); + throw; + } + return storage; +} + +template +void destroy_impl(const Alloc& allocator, T* p) +{ + typename std::allocator_traits:: template rebind_alloc alloc(allocator); + std::allocator_traits:: template rebind_traits::destroy(alloc, p); + alloc.deallocate(p,1); +} + +template +class serializable_any +{ +public: + typedef Alloc allocator_type; + + serializable_any(const Alloc& allocator = Alloc()) + : impl_(nullptr) + { + (void)allocator; + } + serializable_any(const serializable_any& val) + : allocator_(std::allocator_traits::select_on_container_copy_construction(val.get_allocator())) + { + impl_ = val.impl_ != nullptr ? val.impl_->clone(allocator_) : nullptr; + } + serializable_any(const serializable_any& val, const Alloc& allocator) + { + (void)allocator; + impl_ = val.impl_ != nullptr ? val.impl_->clone(Alloc()) : nullptr; + } + + serializable_any(serializable_any&& val) + : impl_(std::move(val.impl_)) + { + val.impl_ = nullptr; + } + serializable_any(serializable_any&& val, const Alloc& allocator) + : impl_(std::move(val.impl_)) + { + (void)allocator; + val.impl_ = nullptr; + } + ~serializable_any() + { + if (impl_ != nullptr) + { + destroy_impl(allocator_,impl_); + } + } + + template + explicit serializable_any(T val) + { + impl_ = create_impl::value_type>>(allocator_,val); + } + + Alloc get_allocator() const + { + return allocator_; + } + + template + typename type_wrapper::reference cast() + { + if (typeid(*impl_) != typeid(any_handle_impl::value_type>)) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad serializable_any cast"); + } + return static_cast::value_type>&>(*impl_).value_; + } + + template + typename type_wrapper::const_reference cast() const + { + if (typeid(*impl_) != typeid(any_handle_impl::value_type>)) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad serializable_any cast"); + } + return static_cast::value_type>&>(*impl_).value_; + } + + serializable_any& operator=(serializable_any rhs) + { + std::swap(impl_,rhs.impl_); + return *this; + } + + void to_stream(basic_json_output_handler& os) const + { + impl_->to_stream(os); + } + + class any_handle + { + public: + virtual ~any_handle() + { + } + + virtual any_handle* clone(const Alloc& allocator) const = 0; + + virtual void to_stream(basic_json_output_handler& os) const = 0; + }; + + template + class any_handle_impl : public any_handle + { + public: + any_handle_impl(T value, const Alloc& allocator = Alloc()) + : value_(value) + { + (void)allocator; + } + + virtual any_handle* clone(const Alloc& allocator) const + { + return create_impl>(allocator, value_); + } + + virtual void to_stream(basic_json_output_handler& os) const + { + serialize(os,value_); + } + + T value_; + }; + + Alloc allocator_; + any_handle* impl_; +}; + +template inline +void serialize(basic_json_output_handler& os, const T&) +{ + os.value(null_type()); +} + +template +class basic_parse_error_handler; + +enum class value_types : uint8_t +{ + // Simple types + empty_object_t, + small_string_t, + double_t, + integer_t, + uinteger_t, + bool_t, + null_t, + // Non simple types + string_t, + object_t, + array_t, + any_t +}; + +inline +bool is_simple(value_types type) +{ + return type < value_types::string_t; +} + +template > +class basic_json +{ +public: + + typedef Alloc allocator_type; + + typedef CharT char_type; + typedef typename std::char_traits char_traits_type; + + typedef typename std::allocator_traits:: template rebind_alloc string_allocator; + typedef std::basic_string string_type; + typedef basic_json value_type; + typedef name_value_pair member_type; + + typedef typename std::allocator_traits:: template rebind_alloc> array_allocator; + + typedef typename std::allocator_traits:: template rebind_alloc object_allocator; + + typedef json_array,array_allocator> array; + typedef json_object,object_allocator> object; + typedef serializable_any any; + + typedef jsoncons::null_type null_type; + + 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; + + template + class range + { + IteratorT first_; + IteratorT last_; + public: + range(const IteratorT& first, const IteratorT& last) + : first_(first), last_(last) + { + } + + public: + friend class basic_json; + + IteratorT begin() + { + return first_; + } + IteratorT end() + { + return last_; + } + }; + + typedef range object_range; + typedef range const_object_range; + typedef range array_range; + typedef range const_array_range; + + struct variant + { + struct string_data : public string_allocator + { + const char_type* c_str() const { return p_; } + const char_type* data() const { return p_; } + size_t length() const { return length_; } + string_allocator get_allocator() const + { + return *this; + } + + bool operator==(const string_data& rhs) const + { + return length() == rhs.length() ? std::char_traits::compare(data(), rhs.data(), length()) == 0 : false; + } + + string_data(const string_allocator& allocator) + : string_allocator(allocator), p_(nullptr), length_(0) + { + } + + char_type* p_; + size_t length_; + private: + string_data(const string_data&); + string_data& operator=(const string_data&); + }; + + struct string_dataA + { + string_data data; + char_type c[1]; + }; + typedef typename std::aligned_storage::type storage_type; + + static size_t aligned_size(size_t n) + { + return sizeof(storage_type) + n; + } + + string_data* create_string_data(const char_type* s, size_t length, const string_allocator& allocator) + { + size_t mem_size = aligned_size(length*sizeof(char_type)); + + typename std::allocator_traits:: template rebind_alloc alloc(allocator); + + char* storage = alloc.allocate(mem_size); + string_data* ps = new(storage)string_data(allocator); + auto psa = reinterpret_cast(storage); + + ps->p_ = new(&psa->c)char_type[length + 1]; + memcpy(ps->p_, s, length*sizeof(char_type)); + ps->p_[length] = 0; + ps->length_ = length; + return ps; + } + + void destroy_string_data(const string_allocator& allocator, string_data* p) + { + size_t mem_size = aligned_size(p->length_*sizeof(char_type)); + typename std::allocator_traits:: template rebind_alloc alloc(allocator); + alloc.deallocate(reinterpret_cast(p),mem_size); + } + + static const size_t small_string_capacity = (sizeof(int64_t)/sizeof(char_type)) - 1; + + variant() + : type_(value_types::empty_object_t) + { + } + + variant(const Alloc& a) + : type_(value_types::object_t) + { + value_.object_val_ = create_impl(a, object_allocator(a)); + } + + variant(std::initializer_list init, + const Alloc& a) + : type_(value_types::array_t) + { + value_.array_val_ = create_impl(a, std::move(init), array_allocator(a)); + } + + explicit variant(variant&& var) + : type_(value_types::null_t) + { + swap(var); + } + + explicit variant(variant&& var, const Alloc& a) + : type_(value_types::null_t) + { + swap(var); + } + + explicit variant(const variant& var) + { + init_variant(var); + } + explicit variant(const variant& var, const Alloc& a) + : type_(var.type_) + { + init_variant(var); + } + + variant(const object & val) + : type_(value_types::object_t) + { + value_.object_val_ = create_impl(val.get_allocator(), val) ; + } + + variant(const object & val, const Alloc& a) + : type_(value_types::object_t) + { + value_.object_val_ = create_impl(a, val, object_allocator(a)) ; + } + + variant(object&& val) + : type_(value_types::object_t) + { + value_.object_val_ = create_impl(val.get_allocator(), std::move(val)); + } + + variant(object&& val, const Alloc& a) + : type_(value_types::object_t) + { + value_.object_val_ = create_impl(a, std::move(val), object_allocator(a)); + } + + variant(const array& val) + : type_(value_types::array_t) + { + value_.array_val_ = create_impl(val.get_allocator(), val); + } + + variant(const array& val, const Alloc& a) + : type_(value_types::array_t) + { + value_.array_val_ = create_impl(a, val, array_allocator(a)); + } + + variant(array&& val) + : type_(value_types::array_t) + { + value_.array_val_ = create_impl(val.get_allocator(), std::move(val)); + } + + variant(array&& val, const Alloc& a) + : type_(value_types::array_t) + { + value_.array_val_ = create_impl(a, std::move(val), array_allocator(a)); + } + + explicit variant(const any& val, const Alloc& a) + : type_(value_types::any_t) + { + value_.any_val_ = create_impl(a, val); + } + + explicit variant(null_type) + : type_(value_types::null_t) + { + } + + explicit variant(bool val) + : type_(value_types::bool_t) + { + value_.bool_val_ = val; + } + + explicit variant(double val, uint8_t precision) + : type_(value_types::double_t), length_or_precision_(precision) + { + value_.double_val_ = val; + } + + explicit variant(int64_t val) + : type_(value_types::integer_t) + { + value_.integer_val_ = val; + } + + explicit variant(uint64_t val) + : type_(value_types::uinteger_t) + { + value_.uinteger_val_ = val; + } + + explicit variant(const string_type& s, const Alloc& a) + { + if (s.length() > variant::small_string_capacity) + { + type_ = value_types::string_t; + //value_.string_val_ = create_impl(a, s, string_allocator(a)); + value_.string_val_ = create_string_data(s.data(), s.length(), string_allocator(a)); + } + else + { + type_ = value_types::small_string_t; + length_or_precision_ = static_cast(s.length()); + std::memcpy(value_.small_string_val_,s.data(),s.length()*sizeof(char_type)); + value_.small_string_val_[length_or_precision_] = 0; + } + } + + explicit variant(const char_type* s, const Alloc& a) + { + size_t length = std::char_traits::length(s); + if (length > variant::small_string_capacity) + { + type_ = value_types::string_t; + //value_.string_val_ = create_impl(a, s, string_allocator(a)); + value_.string_val_ = create_string_data(s, length, string_allocator(a)); + } + else + { + type_ = value_types::small_string_t; + length_or_precision_ = static_cast(length); + std::memcpy(value_.small_string_val_,s,length*sizeof(char_type)); + value_.small_string_val_[length_or_precision_] = 0; + } + } + + explicit variant(const char_type* s, size_t length, const Alloc& a) + { + if (length > variant::small_string_capacity) + { + type_ = value_types::string_t; + //value_.string_val_ = create_impl(a, s, length, string_allocator(a)); + value_.string_val_ = create_string_data(s, length, string_allocator(a)); + } + else + { + type_ = value_types::small_string_t; + length_or_precision_ = static_cast(length); + std::memcpy(value_.small_string_val_,s,length*sizeof(char_type)); + value_.small_string_val_[length_or_precision_] = 0; + } + } + + template + variant(InputIterator first, InputIterator last, const Alloc& a) + : type_(value_types::array_t) + { + value_.array_val_ = create_impl(a, first, last, array_allocator(a)); + } + + void init_variant(const variant& var) + { + type_ = var.type_; + switch (type_) + { + case value_types::null_t: + case value_types::empty_object_t: + break; + case value_types::double_t: + length_or_precision_ = 0; + value_.double_val_ = var.value_.double_val_; + break; + case value_types::integer_t: + value_.integer_val_ = var.value_.integer_val_; + break; + case value_types::uinteger_t: + value_.uinteger_val_ = var.value_.uinteger_val_; + break; + case value_types::bool_t: + value_.bool_val_ = var.value_.bool_val_; + break; + case value_types::small_string_t: + length_or_precision_ = var.length_or_precision_; + std::memcpy(value_.small_string_val_,var.value_.small_string_val_,var.length_or_precision_*sizeof(char_type)); + value_.small_string_val_[length_or_precision_] = 0; + break; + case value_types::string_t: + //value_.string_val_ = create_impl(var.value_.string_val_->get_allocator(), *(var.value_.string_val_), string_allocator(var.value_.string_val_->get_allocator())); + value_.string_val_ = create_string_data(var.value_.string_val_->data(), var.value_.string_val_->length(), string_allocator(var.value_.string_val_->get_allocator())); + break; + case value_types::array_t: + value_.array_val_ = create_impl(var.value_.array_val_->get_allocator(), *(var.value_.array_val_), array_allocator(var.value_.array_val_->get_allocator())); + break; + case value_types::object_t: + value_.object_val_ = create_impl(var.value_.object_val_->get_allocator(), *(var.value_.object_val_), object_allocator(var.value_.object_val_->get_allocator())); + break; + case value_types::any_t: + value_.any_val_ = create_impl(var.value_.any_val_->get_allocator(), *(var.value_.any_val_)); + break; + default: + break; + } + } + + ~variant() + { + destroy_variant(); + } + + void destroy_variant() + { + switch (type_) + { + case value_types::string_t: + //destroy_impl(value_.string_val_->get_allocator(), value_.string_val_); + destroy_string_data(value_.string_val_->get_allocator(), value_.string_val_); + break; + case value_types::array_t: + destroy_impl(value_.array_val_->get_allocator(), value_.array_val_); + break; + case value_types::object_t: + destroy_impl(value_.object_val_->get_allocator(), value_.object_val_); + break; + case value_types::any_t: + destroy_impl(value_.any_val_->get_allocator(), value_.any_val_); + break; + default: + break; + } + } + + variant& operator=(const variant& val) + { + if (this != &val) + { + if (is_simple(type_)) + { + if (is_simple(val.type_)) + { + type_ = val.type_; + length_or_precision_ = val.length_or_precision_; + value_ = val.value_; + } + else + { + init_variant(val); + } + } + else + { + destroy_variant(); + init_variant(val); + } + } + return *this; + } + + variant& operator=(variant&& val) + { + if (this != &val) + { + val.swap(*this); + } + return *this; + } + + void assign(const object & val) + { + destroy_variant(); + type_ = value_types::object_t; + value_.object_val_ = create_impl(val.get_allocator(), val, object_allocator(val.get_allocator())); + } + + void assign(object && val) + { + switch (type_) + { + case value_types::object_t: + value_.object_val_->swap(val); + break; + default: + destroy_variant(); + type_ = value_types::object_t; + value_.object_val_ = create_impl(val.get_allocator(), std::move(val), object_allocator(val.get_allocator())); + break; + } + } + + void assign(const array& val) + { + destroy_variant(); + type_ = value_types::array_t; + value_.array_val_ = create_impl(val.get_allocator(), val, array_allocator(val.get_allocator())) ; + } + + void assign(array&& val) + { + switch (type_) + { + case value_types::array_t: + value_.array_val_->swap(val); + break; + default: + destroy_variant(); + type_ = value_types::array_t; + value_.array_val_ = create_impl(val.get_allocator(), std::move(val), array_allocator(val.get_allocator())); + break; + } + } + + void assign(const string_type& s) + { + destroy_variant(); + if (s.length() > variant::small_string_capacity) + { + type_ = value_types::string_t; + //value_.string_val_ = create_impl(s.get_allocator(), s, string_allocator(s.get_allocator())); + value_.string_val_ = create_string_data(s.data(), s.length(), string_allocator(s.get_allocator())); + } + else + { + type_ = value_types::small_string_t; + length_or_precision_ = static_cast(s.length()); + std::memcpy(value_.small_string_val_,s.data(),s.length()*sizeof(char_type)); + value_.small_string_val_[length_or_precision_] = 0; + } + } + + void assign_string(const char_type* s, size_t length, const Alloc& allocator = Alloc()) + { + destroy_variant(); + if (length > variant::small_string_capacity) + { + type_ = value_types::string_t; + //value_.string_val_ = create_impl(allocator, s, length, string_allocator(allocator)); + value_.string_val_ = create_string_data(s, length, string_allocator(allocator)); + } + else + { + type_ = value_types::small_string_t; + length_or_precision_ = static_cast(length); + std::memcpy(value_.small_string_val_,s,length*sizeof(char_type)); + value_.small_string_val_[length_or_precision_] = 0; + } + } + + void assign(int64_t val) + { + destroy_variant(); + type_ = value_types::integer_t; + value_.integer_val_ = val; + } + + void assign(uint64_t val) + { + destroy_variant(); + type_ = value_types::uinteger_t; + value_.uinteger_val_ = val; + } + + void assign(double val, uint8_t precision = 0) + { + destroy_variant(); + type_ = value_types::double_t; + length_or_precision_ = precision; + value_.double_val_ = val; + } + + void assign(bool val) + { + destroy_variant(); + type_ = value_types::bool_t; + value_.bool_val_ = val; + } + + void assign(null_type) + { + destroy_variant(); + type_ = value_types::null_t; + } + + void assign(const any& rhs) + { + destroy_variant(); + type_ = value_types::any_t; + value_.any_val_ = create_impl(rhs.get_allocator(), rhs); + } + + bool operator!=(const variant& rhs) const + { + return !(*this == rhs); + } + + bool operator==(const variant& rhs) const + { + if (is_number() & rhs.is_number()) + { + switch (type_) + { + case value_types::integer_t: + switch (rhs.type_) + { + case value_types::integer_t: + return value_.integer_val_ == rhs.value_.integer_val_; + case value_types::uinteger_t: + return value_.integer_val_ == rhs.value_.uinteger_val_; + case value_types::double_t: + return value_.integer_val_ == rhs.value_.double_val_; + default: + break; + } + break; + case value_types::uinteger_t: + switch (rhs.type_) + { + case value_types::integer_t: + return value_.uinteger_val_ == rhs.value_.integer_val_; + case value_types::uinteger_t: + return value_.uinteger_val_ == rhs.value_.uinteger_val_; + case value_types::double_t: + return value_.uinteger_val_ == rhs.value_.double_val_; + default: + break; + } + break; + case value_types::double_t: + switch (rhs.type_) + { + case value_types::integer_t: + return value_.double_val_ == rhs.value_.integer_val_; + case value_types::uinteger_t: + return value_.double_val_ == rhs.value_.uinteger_val_; + case value_types::double_t: + return value_.double_val_ == rhs.value_.double_val_; + default: + break; + } + break; + default: + break; + } + } + + switch (type_) + { + case value_types::bool_t: + return type_ == rhs.type_ && value_.bool_val_ == rhs.value_.bool_val_; + case value_types::null_t: + return type_ == rhs.type_; + case value_types::empty_object_t: + return type_ == rhs.type_ || (rhs.type_ == value_types::object_t && rhs.empty()); + case value_types::small_string_t: + return type_ == rhs.type_ && length_or_precision_ == rhs.length_or_precision_ ? std::char_traits::compare(value_.small_string_val_,rhs.value_.small_string_val_,length_or_precision_) == 0 : false; + case value_types::string_t: + return type_ == rhs.type_ && *(value_.string_val_) == *(rhs.value_.string_val_); + case value_types::array_t: + return type_ == rhs.type_ && *(value_.array_val_) == *(rhs.value_.array_val_); + break; + case value_types::object_t: + return (type_ == rhs.type_ && *(value_.object_val_) == *(rhs.value_.object_val_)) || (rhs.type_ == value_types::empty_object_t && empty()); + break; + case value_types::any_t: + return type_ == rhs.type_; + default: + // throw + break; + } + return false; + } + + bool is_null() const JSONCONS_NOEXCEPT + { + return type_ == value_types::null_t; + } + + bool is_bool() const JSONCONS_NOEXCEPT + { + return type_ == value_types::bool_t; + } + + bool empty() const JSONCONS_NOEXCEPT + { + switch (type_) + { + case value_types::small_string_t: + return length_or_precision_ == 0; + case value_types::string_t: + return value_.string_val_->length() == 0; + case value_types::array_t: + return value_.array_val_->size() == 0; + case value_types::empty_object_t: + return true; + case value_types::object_t: + return value_.object_val_->size() == 0; + default: + return false; + } + } + + bool is_string() const JSONCONS_NOEXCEPT + { + return (type_ == value_types::string_t) | (type_ == value_types::small_string_t); + } + + bool is_number() const JSONCONS_NOEXCEPT + { + return type_ == value_types::double_t || type_ == value_types::integer_t || type_ == value_types::uinteger_t; + } + + void swap(variant& rhs) + { + using std::swap; + if (this == &rhs) + { + // same object, do nothing + } + else + { + swap(type_, rhs.type_); + swap(length_or_precision_, rhs.length_or_precision_); + swap(value_, rhs.value_); + } + } + + value_types type_; + uint8_t length_or_precision_; + union + { + double double_val_; + int64_t integer_val_; + uint64_t uinteger_val_; + bool bool_val_; + object* object_val_; + array* array_val_; + any* any_val_; + string_data* string_val_; + char_type small_string_val_[sizeof(int64_t)/sizeof(char_type)]; + } value_; + }; + + template + class json_proxy + { + private: + typedef json_proxy proxy_type; + + ParentT& parent_; + const string_type& name_; + + json_proxy() = delete; + json_proxy& operator = (const json_proxy& other) = delete; + + json_proxy(ParentT& parent, const string_type& name) + : parent_(parent), name_(name) + { + } + + basic_json& evaluate() + { + return parent_.evaluate(name_); + } + + const basic_json& evaluate() const + { + return parent_.evaluate(name_); + } + + basic_json& evaluate_with_default() + { + basic_json& val = parent_.evaluate_with_default(); + auto it = val.find(name_.data(),name_.length()); + if (it == val.members().end()) + { + it = val.set(val.members().begin(),name_,object(val.object_value().get_allocator())); + } + return it->value(); + } + + basic_json& evaluate(size_t index) + { + return parent_.evaluate(name_).at(index); + } + + const basic_json& evaluate(size_t index) const + { + return parent_.evaluate(name_).at(index); + } + + basic_json& evaluate(const string_type& index) + { + return parent_.evaluate(name_).at(index); + } + + const basic_json& evaluate(const string_type& index) const + { + return parent_.evaluate(name_).at(index); + } + public: + + friend class basic_json; + + object_range members() + { + return evaluate().members(); + } + + const_object_range members() const + { + return evaluate().members(); + } + + array_range elements() + { + return evaluate().elements(); + } + + const_array_range elements() const + { + return evaluate().elements(); + } + + size_t size() const JSONCONS_NOEXCEPT + { + return evaluate().size(); + } + + value_types type() const + { + return evaluate().type(); + } + + size_t count(const string_type& name) const + { + return evaluate().count(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 + void resize(size_t n, T val) + { + evaluate().resize(n,val); + } + + template + bool is() const + { + return evaluate().template is(); + } + + bool is_string() const JSONCONS_NOEXCEPT + { + return evaluate().is_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_any() const JSONCONS_NOEXCEPT + { + return evaluate().is_any(); + } + + 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_type as_string() const JSONCONS_NOEXCEPT + { + return evaluate().as_string(); + } + + string_type as_string(const string_allocator& allocator) const JSONCONS_NOEXCEPT + { + return evaluate().as_string(allocator); + } + + string_type as_string(const basic_output_format& format) const + { + return evaluate().as_string(format); + } + + string_type as_string(const basic_output_format& format, + const string_allocator& allocator) const + { + return evaluate().as_string(format,allocator); + } + + template + T as() const + { + return evaluate().template as(); + } + + template + typename std::enable_if::value>::type as(const string_allocator& allocator) const + { + return evaluate().template as(allocator); + } + + any& any_value() + { + return evaluate().any_value(); + } + + const any& any_value() const + { + return evaluate().any_value(); + } + + bool as_bool() const JSONCONS_NOEXCEPT + { + return evaluate().as_bool(); + } + + template + std::vector as_vector() const + { + return evaluate().template as_vector(); + } + + 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 + const T& any_cast() const + { + return evaluate().template any_cast(); + } + // Returns a const reference to the custom data associated with name + + template + T& any_cast() + { + return evaluate().template any_cast(); + } + // Returns a reference to the custom data associated with name + + operator basic_json&() + { + return evaluate(); + } + + operator const basic_json&() const + { + return evaluate(); + } + + template + json_proxy& operator=(T val) + { + parent_.evaluate_with_default().set(name_, val); + return *this; + } + + json_proxy& operator=(const basic_json& val) + { + parent_.evaluate_with_default().set(name_, val); + return *this; + } + + json_proxy& operator=(basic_json&& val) + { + parent_.evaluate_with_default().set(name_, std::move(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 operator[](const string_type& name) + { + return json_proxy(*this,name); + } + + const json_proxy operator[](const string_type& name) const + { + return json_proxy(*this,name); + } + + basic_json& at(const string_type& name) + { + return evaluate().at(name); + } + + const basic_json& at(const string_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_type& name) + { + return evaluate().find(name); + } + + const_object_iterator find(const string_type& name) const + { + return evaluate().find(name); + } + + object_iterator find(const char_type* name) + { + return evaluate().find(name); + } + + const_object_iterator find(const char_type* name) const + { + return evaluate().find(name); + } + + object_iterator find(const char_type* name, size_t length) + { + return evaluate().find(name,length); + } + + const_object_iterator find(const char_type* name, size_t length) const + { + return evaluate().find(name,length); + } + + template + basic_json get(const string_type& name, T&& default_val) const + { + return evaluate().get(name,std::forward(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(object_iterator first, object_iterator last) + { + evaluate().erase(first, last); + } + // Remove a range of elements from an object + + void erase(array_iterator first, array_iterator last) + { + evaluate().erase(first, last); + } + + void erase(const string_type& name) + { + evaluate().erase(name); + } + + // Remove a member from an object + + void set(const string_type& name, const basic_json& value) + { + evaluate().set(name,value); + } + + void set(string_type&& name, const basic_json& value) + + { + evaluate().set(std::move(name),value); + } + + void set(const string_type& name, basic_json&& value) + + { + evaluate().set(name,std::move(value)); + } + + void set(string_type&& name, basic_json&& value) + + { + evaluate().set(std::move(name),std::move(value)); + } + + object_iterator set(object_iterator hint, const string_type& name, const basic_json& value) + { + return evaluate().set(hint, name,value); + } + + object_iterator set(object_iterator hint, string_type&& name, const basic_json& value) + + { + return evaluate().set(hint, std::move(name),value); + } + + object_iterator set(object_iterator hint, const string_type& name, basic_json&& value) + + { + return evaluate().set(hint, name,std::move(value)); + } + + object_iterator set(object_iterator hint, string_type&& name, basic_json&& value) + + { + return evaluate().set(hint, std::move(name),std::move(value)); + } + + void add(basic_json&& value) + { + evaluate_with_default().add(std::move(value)); + } + + void add(const basic_json& value) + { + evaluate_with_default().add(value); + } + + array_iterator add(const_array_iterator pos, const basic_json& value) + { + return evaluate_with_default().add(pos, value); + } + + array_iterator add(const_array_iterator pos, basic_json&& value) + { + return evaluate_with_default().add(pos, std::move(value)); + } + + string_type to_string(const string_allocator& allocator = string_allocator()) const JSONCONS_NOEXCEPT + { + return evaluate().to_string(allocator); + } + + string_type to_string(const basic_output_format& format, string_allocator& allocator = string_allocator()) const + { + return evaluate().to_string(format,allocator); + } + + void to_stream(std::basic_ostream& os) const + { + evaluate().to_stream(os); + } + + void to_stream(std::basic_ostream& os, const basic_output_format& format) const + { + evaluate().to_stream(os,format); + } + + void to_stream(std::basic_ostream& os, const basic_output_format& format, bool indenting) const + { + evaluate().to_stream(os,format,indenting); + } + + void swap(basic_json& val) + { + evaluate_with_default().swap(val); + } + + friend std::basic_ostream& operator<<(std::basic_ostream& os, const json_proxy& o) + { + o.to_stream(os); + return os; + } + +#if !defined(JSONCONS_NO_DEPRECATED) + + void resize_array(size_t n) + { + evaluate().resize_array(n); + } + + template + 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_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::move(value)); + } + + bool has_member(const string_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_type& name) + { + evaluate().remove(name); + } + void remove_member(const string_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_stream(std::basic_istream& is); + static basic_json parse_stream(std::basic_istream& is, basic_parse_error_handler& err_handler); + + static basic_json parse(const string_type& s) + { + basic_json_deserializer> handler; + basic_json_parser parser(handler); + parser.begin_parse(); + parser.parse(s.data(),0,s.length()); + parser.end_parse(); + parser.check_done(s.data(),parser.index(),s.length()); + if (!handler.is_valid()) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Failed to parse json string"); + } + return handler.get_result(); + } + + static basic_json parse(const string_type& s, basic_parse_error_handler& err_handler) + { + basic_json_deserializer> handler; + basic_json_parser parser(handler,err_handler); + parser.begin_parse(); + parser.parse(s.data(),0,s.length()); + parser.end_parse(); + parser.check_done(s.data(),parser.index(),s.length()); + if (!handler.is_valid()) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Failed to parse json string"); + } + return handler.get_result(); + } + + static basic_json parse_file(const std::string& s); + + static basic_json parse_file(const std::string& s, basic_parse_error_handler& err_handler); + + static basic_json make_array() + { + return basic_json::array(); + } + + static basic_json make_array(size_t n, const array_allocator& allocator = array_allocator()) + { + return basic_json::array(n,allocator); + } + + template + static basic_json make_array(size_t n, const T& val, const array_allocator& allocator = array_allocator()) + { + return basic_json::array(n, val,allocator); + } + + template + static typename std::enable_if::type make_array(size_t n) + { + return array(n); + } + + template + static typename std::enable_if::type make_array(size_t n, const T& val, const Alloc& allocator = Alloc()) + { + return array(n,val,allocator); + } + + template + 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(args...); + val.resize(n); + for (size_t i = 0; i < n; ++i) + { + val[i] = make_array(args...); + } + return val; + } + + variant var_; + + basic_json() + : var_() + { + } + + basic_json(const Alloc& allocator) + : var_(allocator) + { + } + + basic_json(std::initializer_list init, + const Alloc& allocator = Alloc()) + : var_(std::move(init), allocator) + { + } + + basic_json(const basic_json& val) + : var_(val.var_) + { + } + + basic_json(const basic_json& val, const Alloc& allocator) + : var_(val.var_,allocator) + { + } + + basic_json(basic_json&& other) + : var_(std::move(other.var_)) + { + } + + basic_json(basic_json&& other, const Alloc& allocator) + : var_(std::move(other.var_),allocator) + { + } + + basic_json(const array& val) + : var_(val) + { + } + + basic_json(array&& other) + : var_(std::move(other)) + { + } + + basic_json(const object& other) + : var_(other) + { + } + + basic_json(object&& other) + : var_(std::move(other)) + { + } + + template + basic_json(const json_proxy& proxy, const Alloc& allocator = Alloc()) + : var_(proxy.evaluate().var_,allocator) + { + } + + template + basic_json(T val) + : var_(null_type()) + { + json_type_traits::assign(*this,val); + } + + basic_json(double val, uint8_t precision) + : var_(val,precision) + { + } + + template + basic_json(T val, const Alloc& allocator) + : var_(allocator) + { + json_type_traits::assign(*this,val); + } + + basic_json(const char_type *s, size_t length, const Alloc& allocator = Alloc()) + : var_(s, length, allocator) + { + } + template + basic_json(InputIterator first, InputIterator last, const Alloc& allocator = Alloc()) + : var_(first,last,allocator) + { + } + + ~basic_json() + { + } + + basic_json& operator=(const basic_json& rhs) + { + var_ = rhs.var_; + return *this; + } + + basic_json& operator=(basic_json&& rhs) + { + if (this != &rhs) + { + var_ = std::move(rhs.var_); + } + return *this; + } + + basic_json& operator=(std::initializer_list init) + { + basic_json val(init); + swap(val); + return *this; + } + + template + basic_json& operator=(T val) + { + json_type_traits::assign(*this,val); + return *this; + } + + bool operator!=(const basic_json& rhs) const; + + bool operator==(const basic_json& rhs) const; + + size_t size() const JSONCONS_NOEXCEPT + { + switch (var_.type_) + { + case value_types::empty_object_t: + return 0; + case value_types::object_t: + return var_.value_.object_val_->size(); + case value_types::array_t: + return var_.value_.array_val_->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> operator[](const string_type& name) + { + switch (var_.type_) + { + case value_types::empty_object_t: + create_object_implicitly(); + case value_types::object_t: + return json_proxy>(*this, name); + break; + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an object"); + break; + } + } + + const basic_json& operator[](const string_type& name) const + { + return at(name); + } + + string_type to_string(const string_allocator& allocator=string_allocator()) const JSONCONS_NOEXCEPT + { + string_type s(allocator); + std::basic_ostringstream os(s); + { + basic_json_serializer serializer(os); + to_stream(serializer); + } + return os.str(); + } + + string_type to_string(const basic_output_format& format, + const string_allocator& allocator=string_allocator()) const + { + string_type s(allocator); + std::basic_ostringstream os(s); + { + basic_json_serializer serializer(os, format); + to_stream(serializer); + } + return os.str(); + } + + void to_stream(basic_json_output_handler& handler) const + { + switch (var_.type_) + { + case value_types::small_string_t: + handler.value(var_.value_.small_string_val_,var_.length_or_precision_); + break; + case value_types::string_t: + handler.value(var_.value_.string_val_->data(),var_.value_.string_val_->length()); + break; + case value_types::double_t: + handler.value(var_.value_.double_val_, var_.length_or_precision_); + break; + case value_types::integer_t: + handler.value(var_.value_.integer_val_); + break; + case value_types::uinteger_t: + handler.value(var_.value_.uinteger_val_); + break; + case value_types::bool_t: + handler.value(var_.value_.bool_val_); + break; + case value_types::null_t: + handler.value(null_type()); + break; + case value_types::empty_object_t: + handler.begin_object(); + handler.end_object(); + break; + case value_types::object_t: + { + handler.begin_object(); + object* o = var_.value_.object_val_; + for (const_object_iterator it = o->begin(); it != o->end(); ++it) + { + handler.name((it->name()).data(),it->name().length()); + it->value().to_stream(handler); + } + handler.end_object(); + } + break; + case value_types::array_t: + { + handler.begin_array(); + array *o = var_.value_.array_val_; + for (const_array_iterator it = o->begin(); it != o->end(); ++it) + { + it->to_stream(handler); + } + handler.end_array(); + } + break; + case value_types::any_t: + var_.value_.any_val_->to_stream(handler); + break; + default: + break; + } + } + + void to_stream(std::basic_ostream& os) const + { + basic_json_serializer serializer(os); + to_stream(serializer); + } + + void to_stream(std::basic_ostream& os, const basic_output_format& format) const + { + basic_json_serializer serializer(os, format); + to_stream(serializer); + } + + void to_stream(std::basic_ostream& os, const basic_output_format& format, bool indenting) const + { + basic_json_serializer serializer(os, format, indenting); + to_stream(serializer); + } + + bool is_null() const JSONCONS_NOEXCEPT + { + return var_.is_null(); + } + + size_t count(const string_type& name) const + { + switch (var_.type_) + { + case value_types::object_t: + { + auto it = var_.value_.object_val_->find(name.data(),name.length()); + if (it == members().end()) + { + return 0; + } + size_t count = 0; + while (it != members().end() && it->name() == name) + { + ++count; + ++it; + } + return count; + } + break; + default: + return 0; + } + } + + template + bool is() const + { + return json_type_traits::is(*this); + } + + bool is_string() const JSONCONS_NOEXCEPT + { + return var_.is_string(); + } + + + bool is_bool() const JSONCONS_NOEXCEPT + { + return var_.is_bool(); + } + + bool is_object() const JSONCONS_NOEXCEPT + { + return var_.type_ == value_types::object_t || var_.type_ == value_types::empty_object_t; + } + + bool is_array() const JSONCONS_NOEXCEPT + { + return var_.type_ == value_types::array_t; + } + + bool is_any() const JSONCONS_NOEXCEPT + { + return var_.type_ == value_types::any_t; + } + + bool is_integer() const JSONCONS_NOEXCEPT + { + return var_.type_ == value_types::integer_t || (var_.type_ == value_types::uinteger_t && (as_uinteger() <= static_cast(std::numeric_limits::max JSONCONS_NO_MACRO_EXP()))); + } + + bool is_uinteger() const JSONCONS_NOEXCEPT + { + return var_.type_ == value_types::uinteger_t || (var_.type_ == value_types::integer_t && as_integer() >= 0); + } + + bool is_double() const JSONCONS_NOEXCEPT + { + return var_.type_ == value_types::double_t; + } + + bool is_number() const JSONCONS_NOEXCEPT + { + return var_.is_number(); + } + + bool empty() const JSONCONS_NOEXCEPT + { + return var_.empty(); + } + + size_t capacity() const + { + switch (var_.type_) + { + case value_types::array_t: + return var_.value_.array_val_->capacity(); + case value_types::object_t: + return var_.value_.object_val_->capacity(); + default: + return 0; + } + } + + template::value + >::type* = nullptr> + void create_object_implicitly() + { + var_.type_ = value_types::object_t; + var_.value_.object_val_ = create_impl(Alloc(),object_allocator(Alloc())); + } + + template::value + >::type* = nullptr> + void create_object_implicitly() const + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Cannot create_impl object implicitly - allocator is not default constructible."); + } + + void reserve(size_t n) + { + switch (var_.type_) + { + case value_types::array_t: + var_.value_.array_val_->reserve(n); + break; + case value_types::empty_object_t: + { + create_object_implicitly(); + var_.value_.object_val_->reserve(n); + } + break; + case value_types::object_t: + { + var_.value_.object_val_->reserve(n); + } + break; + default: + break; + } + } + + void resize(size_t n) + { + switch (var_.type_) + { + case value_types::array_t: + var_.value_.array_val_->resize(n); + break; + default: + break; + } + } + + template + void resize(size_t n, T val) + { + switch (var_.type_) + { + case value_types::array_t: + var_.value_.array_val_->resize(n, val); + break; + default: + break; + } + } + + template + T as() const + { + return json_type_traits::as(*this); + } + + template + typename std::enable_if::value>::type as(const string_allocator& allocator) const + { + return json_type_traits::as(*this,allocator); + } + + bool as_bool() const JSONCONS_NOEXCEPT + { + switch (var_.type_) + { + case value_types::null_t: + case value_types::empty_object_t: + return false; + case value_types::bool_t: + return var_.value_.bool_val_; + case value_types::double_t: + return var_.value_.double_val_ != 0.0; + case value_types::integer_t: + return var_.value_.integer_val_ != 0; + case value_types::uinteger_t: + return var_.value_.uinteger_val_ != 0; + case value_types::small_string_t: + return var_.length_or_precision_ != 0; + case value_types::string_t: + return var_.value_.string_val_->length() != 0; + case value_types::array_t: + return var_.value_.array_val_->size() != 0; + case value_types::object_t: + return var_.value_.object_val_->size() != 0; + case value_types::any_t: + return true; + default: + return false; + } + } + + int64_t as_integer() const + { + switch (var_.type_) + { + case value_types::double_t: + return static_cast(var_.value_.double_val_); + case value_types::integer_t: + return static_cast(var_.value_.integer_val_); + case value_types::uinteger_t: + return static_cast(var_.value_.uinteger_val_); + case value_types::bool_t: + return var_.value_.bool_val_ ? 1 : 0; + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an integer"); + } + } + + uint64_t as_uinteger() const + { + switch (var_.type_) + { + case value_types::double_t: + return static_cast(var_.value_.double_val_); + case value_types::integer_t: + return static_cast(var_.value_.integer_val_); + case value_types::uinteger_t: + return static_cast(var_.value_.uinteger_val_); + case value_types::bool_t: + return var_.value_.bool_val_ ? 1 : 0; + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an unsigned integer"); + } + } + + double as_double() const + { + switch (var_.type_) + { + case value_types::double_t: + return var_.value_.double_val_; + case value_types::integer_t: + return static_cast(var_.value_.integer_val_); + case value_types::uinteger_t: + return static_cast(var_.value_.uinteger_val_); + case value_types::null_t: + return std::numeric_limits::quiet_NaN(); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not a double"); + } + } + + string_type as_string() const JSONCONS_NOEXCEPT + { + switch (var_.type_) + { + case value_types::small_string_t: + return string_type(var_.value_.small_string_val_,var_.length_or_precision_); + case value_types::string_t: + return string_type(var_.value_.string_val_->data(),var_.value_.string_val_->length(),var_.value_.string_val_->get_allocator()); + default: + return to_string(); + } + } + + string_type as_string(const string_allocator& allocator) const JSONCONS_NOEXCEPT + { + switch (var_.type_) + { + case value_types::small_string_t: + return string_type(var_.value_.small_string_val_,var_.length_or_precision_,allocator); + case value_types::string_t: + return string_type(var_.value_.string_val_->data(),var_.value_.string_val_->length(),allocator); + default: + return to_string(allocator); + } + } + + string_type as_string(const basic_output_format& format) const + { + switch (var_.type_) + { + case value_types::small_string_t: + return string_type(var_.value_.small_string_val_,var_.length_or_precision_); + case value_types::string_t: + return string_type(var_.value_.string_val_->data(),var_.value_.string_val_->length(),var_.value_.string_val_->get_allocator()); + default: + return to_string(format); + } + } + + string_type as_string(const basic_output_format& format, + const string_allocator& allocator) const + { + switch (var_.type_) + { + case value_types::small_string_t: + return string_type(var_.value_.small_string_val_,var_.length_or_precision_,allocator); + case value_types::string_t: + return string_type(var_.value_.string_val_->data(),var_.value_.string_val_->length(),allocator); + default: + return to_string(format,allocator); + } + } + + const char_type* as_cstring() const + { + switch (var_.type_) + { + case value_types::small_string_t: + return var_.value_.small_string_val_; + case value_types::string_t: + return var_.value_.string_val_->c_str(); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not a cstring"); + } + } + + any& any_value(); + + const any& any_value() const; + + basic_json& at(const string_type& name) + { + switch (var_.type_) + { + case value_types::empty_object_t: + JSONCONS_THROW_EXCEPTION_1(std::out_of_range,"%s not found", name); + case value_types::object_t: + { + auto it = var_.value_.object_val_->find(name.data(),name.length()); + if (it == members().end()) + { + JSONCONS_THROW_EXCEPTION_1(std::out_of_range, "%s not found", name); + } + return it->value(); + } + break; + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to get %s from a value that is not an object", name); + } + } + } + + basic_json& evaluate() + { + return *this; + } + + basic_json& evaluate_with_default() + { + return *this; + } + + const basic_json& evaluate() const + { + return *this; + } + + basic_json& evaluate(size_t i) + { + return at(i); + } + + const basic_json& evaluate(size_t i) const + { + return at(i); + } + + basic_json& evaluate(const string_type& name) + { + return at(name); + } + + const basic_json& evaluate(const string_type& name) const + { + return at(name); + } + + const basic_json& at(const string_type& name) const + { + switch (var_.type_) + { + case value_types::empty_object_t: + JSONCONS_THROW_EXCEPTION_1(std::out_of_range,"%s not found", name); + case value_types::object_t: + { + auto it = var_.value_.object_val_->find(name.data(),name.length()); + if (it == members().end()) + { + JSONCONS_THROW_EXCEPTION_1(std::out_of_range, "%s not found", name); + } + return it->value(); + } + break; + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to get %s from a value that is not an object", name); + } + } + } + + basic_json& at(size_t i) + { + switch (var_.type_) + { + case value_types::array_t: + if (i >= var_.value_.array_val_->size()) + { + JSONCONS_THROW_EXCEPTION(std::out_of_range,"Invalid array subscript"); + } + return var_.value_.array_val_->operator[](i); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Index on non-array value not supported"); + } + } + + const basic_json& at(size_t i) const + { + switch (var_.type_) + { + case value_types::array_t: + if (i >= var_.value_.array_val_->size()) + { + JSONCONS_THROW_EXCEPTION(std::out_of_range,"Invalid array subscript"); + } + return var_.value_.array_val_->operator[](i); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Index on non-array value not supported"); + } + } + + object_iterator find(const string_type& name) + { + switch (var_.type_) + { + case value_types::empty_object_t: + return members().end(); + case value_types::object_t: + return var_.value_.object_val_->find(name.data(),name.length()); + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to get %s from a value that is not an object", name); + } + } + } + + const_object_iterator find(const string_type& name) const + { + switch (var_.type_) + { + case value_types::empty_object_t: + return members().end(); + case value_types::object_t: + return var_.value_.object_val_->find(name.data(),name.length()); + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to get %s from a value that is not an object", name); + } + } + } + + object_iterator find(const char_type* name) + { + switch (var_.type_) + { + case value_types::empty_object_t: + return members().end(); + case value_types::object_t: + return var_.value_.object_val_->find(name, std::char_traits::length(name)); + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to get %s from a value that is not an object", name); + } + } + } + + const_object_iterator find(const char_type* name) const + { + switch (var_.type_) + { + case value_types::empty_object_t: + return members().end(); + case value_types::object_t: + return var_.value_.object_val_->find(name, std::char_traits::length(name)); + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to get %s from a value that is not an object", name); + } + } + } + + object_iterator find(const char_type* name, size_t length) + { + switch (var_.type_) + { + case value_types::empty_object_t: + return members().end(); + case value_types::object_t: + return var_.value_.object_val_->find(name, length); + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to get %s from a value that is not an object", name); + } + } + } + + const_object_iterator find(const char_type* name, size_t length) const + { + switch (var_.type_) + { + case value_types::empty_object_t: + return members().end(); + case value_types::object_t: + return var_.value_.object_val_->find(name, length); + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to get %s from a value that is not an object", name); + } + } + } + + template + basic_json get(const string_type& name, T&& default_val) const + { + switch (var_.type_) + { + case value_types::empty_object_t: + { + return basic_json(std::forward(default_val)); + } + case value_types::object_t: + { + const_object_iterator it = var_.value_.object_val_->find(name.data(),name.length()); + if (it != members().end()) + { + return it->value(); + } + else + { + return basic_json(std::forward(default_val)); + } + } + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to get %s from a value that is not an object", name); + } + } + } + + // Modifiers + + void shrink_to_fit() + { + switch (var_.type_) + { + case value_types::array_t: + var_.value_.array_val_->shrink_to_fit(); + break; + case value_types::object_t: + var_.value_.object_val_->shrink_to_fit(); + break; + default: + break; + } + } + + void clear() + { + switch (var_.type_) + { + case value_types::array_t: + var_.value_.array_val_->clear(); + break; + case value_types::object_t: + var_.value_.object_val_->clear(); + break; + default: + break; + } + } + + void erase(object_iterator first, object_iterator last) + { + switch (var_.type_) + { + case value_types::empty_object_t: + break; + case value_types::object_t: + var_.value_.object_val_->erase(first, last); + break; + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an object"); + break; + } + } + + void erase(array_iterator first, array_iterator last) + { + switch (var_.type_) + { + case value_types::array_t: + var_.value_.array_val_->erase(first, last); + break; + default: + JSONCONS_THROW_EXCEPTION(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_type& name) + { + switch (var_.type_) + { + case value_types::empty_object_t: + break; + case value_types::object_t: + var_.value_.object_val_->erase(name.data(),name.length()); + break; + default: + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to set %s on a value that is not an object", name); + break; + } + } + + void set(const string_type& name, const basic_json& value) + { + switch (var_.type_) + { + case value_types::empty_object_t: + create_object_implicitly(); + case value_types::object_t: + var_.value_.object_val_->set(name, value); + break; + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to set %s on a value that is not an object", name); + } + } + } + + void set(string_type&& name, const basic_json& value){ + switch (var_.type_){ + case value_types::empty_object_t: + create_object_implicitly(); + case value_types::object_t: + var_.value_.object_val_->set(std::move(name),value); + break; + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to set %s on a value that is not an object",name); + } + } + } + + void set(const string_type& name, basic_json&& value){ + switch (var_.type_){ + case value_types::empty_object_t: + create_object_implicitly(); + case value_types::object_t: + var_.value_.object_val_->set(name,std::move(value)); + break; + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to set %s on a value that is not an object",name); + } + } + } + + void set(string_type&& name, basic_json&& value) + { + switch (var_.type_) + { + case value_types::empty_object_t: + create_object_implicitly(); + case value_types::object_t: + var_.value_.object_val_->set(std::move(name),std::move(value)); + break; + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to set %s on a value that is not an object",name); + } + } + } + + object_iterator set(object_iterator hint, const string_type& name, const basic_json& value) + { + switch (var_.type_) + { + case value_types::empty_object_t: + create_object_implicitly(); + case value_types::object_t: + return var_.value_.object_val_->set(hint, name, value); + break; + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to set %s on a value that is not an object", name); + } + } + } + + object_iterator set(object_iterator hint, string_type&& name, const basic_json& value){ + switch (var_.type_){ + case value_types::empty_object_t: + create_object_implicitly(); + case value_types::object_t: + return var_.value_.object_val_->set(hint, std::move(name),value); + break; + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to set %s on a value that is not an object",name); + } + } + } + + object_iterator set(object_iterator hint, const string_type& name, basic_json&& value){ + switch (var_.type_){ + case value_types::empty_object_t: + create_object_implicitly(); + case value_types::object_t: + return var_.value_.object_val_->set(hint, name,std::move(value)); + break; + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to set %s on a value that is not an object",name); + } + } + } + + object_iterator set(object_iterator hint, string_type&& name, basic_json&& value){ + switch (var_.type_){ + case value_types::empty_object_t: + create_object_implicitly(); + case value_types::object_t: + return var_.value_.object_val_->set(hint, std::move(name),std::move(value)); + break; + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to set %s on a value that is not an object",name); + } + } + } + + void add(const basic_json& value) + { + switch (var_.type_) + { + case value_types::array_t: + var_.value_.array_val_->push_back(value); + break; + default: + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Attempting to insert into a value that is not an array"); + } + } + } + + void add(basic_json&& value){ + switch (var_.type_){ + case value_types::array_t: + var_.value_.array_val_->push_back(std::move(value)); + break; + default: + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Attempting to insert into a value that is not an array"); + } + } + } + + array_iterator add(const_array_iterator pos, const basic_json& value) + { + switch (var_.type_) + { + case value_types::array_t: + return var_.value_.array_val_->add(pos, value); + break; + default: + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Attempting to insert into a value that is not an array"); + } + } + } + + array_iterator add(const_array_iterator pos, basic_json&& value){ + switch (var_.type_){ + case value_types::array_t: + return var_.value_.array_val_->add(pos, std::move(value)); + break; + default: + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Attempting to insert into a value that is not an array"); + } + } + } + + value_types type() const + { + return var_.type_; + } + + uint8_t length_or_precision() const + { + return var_.length_or_precision_; + } + + void swap(basic_json& b) + { + var_.swap(b.var_); + } + + template + std::vector as_vector() const + { + std::vector v(size()); + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = json_type_traits::as(at(i)); + } + return v; + } + + friend void swap(basic_json& a, basic_json& b) + { + a.swap(b); + } + + void assign_any(const typename basic_json::any& rhs) + { + var_.assign(rhs); + } + + void assign_string(const string_type& rhs) + { + var_.assign(rhs); + } + + void assign_string(const char_type* rhs, size_t length) + { + var_.assign_string(rhs,length); + } + + void assign_bool(bool rhs) + { + var_.assign(rhs); + } + + void assign_object(const object & rhs) + { + var_.assign(rhs); + } + + void assign_array(const array& rhs) + { + var_.assign(rhs); + } + + void assign_null() + { + var_.assign(null_type()); + } + + template + const T& any_cast() const + { + if (var_.type_ != value_types::any_t) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad any cast"); + } + return var_.value_.any_val_->template cast(); + } + template + T& any_cast() + { + if (var_.type_ != value_types::any_t) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad any cast"); + } + return var_.value_.any_val_->template cast(); + } + + void assign_integer(int64_t rhs) + { + var_.assign(rhs); + } + + void assign_uinteger(uint64_t rhs) + { + var_.assign(rhs); + } + + void assign_double(double rhs, uint8_t precision = 0) + { + var_.assign(rhs,precision); + } + + static basic_json make_2d_array(size_t m, size_t n); + + template + static basic_json make_2d_array(size_t m, size_t n, T val); + + static basic_json make_3d_array(size_t m, size_t n, size_t k); + + template + static basic_json make_3d_array(size_t m, size_t n, size_t k, T val); + +#if !defined(JSONCONS_NO_DEPRECATED) + typedef any json_any_type; + + static basic_json parse(std::basic_istream& is) + { + return parse_stream(is); + } + static basic_json parse(std::basic_istream& is, basic_parse_error_handler& err_handler) + { + return parse_stream(is,err_handler); + } + + static basic_json parse_string(const string_type& s) + { + return parse(s); + } + + static basic_json parse_string(const string_type& s, basic_parse_error_handler& err_handler) + { + return parse(s,err_handler); + } + + void resize_array(size_t n) + { + resize(n); + } + + template + void resize_array(size_t n, T val) + { + resize(n,val); + } + + object_iterator begin_members() + { + return members().begin(); + } + + const_object_iterator begin_members() const + { + return members().begin(); + } + + object_iterator end_members() + { + return members().end(); + } + + const_object_iterator end_members() const + { + return members().end(); + } + + array_iterator begin_elements() + { + return elements().begin(); + } + + const_array_iterator begin_elements() const + { + return elements().begin(); + } + + array_iterator end_elements() + { + return elements().end(); + } + + const_array_iterator end_elements() const + { + return elements().end(); + } + + const basic_json& get(const string_type& name) const + { + static const basic_json a_null = null_type(); + + switch (var_.type_) + { + case value_types::empty_object_t: + return a_null; + case value_types::object_t: + { + const_object_iterator it = var_.value_.object_val_->find(name.data(),name.length()); + return it != members().end() ? it->value() : a_null; + } + default: + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Attempting to get %s from a value that is not an object", name); + } + } + } + + bool is_longlong() const JSONCONS_NOEXCEPT + { + return var_.type_ == value_types::integer_t; + } + + bool is_ulonglong() const JSONCONS_NOEXCEPT + { + return var_.type_ == value_types::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_) + { + case value_types::double_t: + return static_cast(var_.value_.double_val_); + case value_types::integer_t: + return static_cast(var_.value_.integer_val_); + case value_types::uinteger_t: + return static_cast(var_.value_.uinteger_val_); + case value_types::bool_t: + return var_.value_.bool_val_ ? 1 : 0; + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an int"); + } + } + + unsigned int as_uint() const + { + switch (var_.type_) + { + case value_types::double_t: + return static_cast(var_.value_.double_val_); + case value_types::integer_t: + return static_cast(var_.value_.integer_val_); + case value_types::uinteger_t: + return static_cast(var_.value_.uinteger_val_); + case value_types::bool_t: + return var_.value_.bool_val_ ? 1 : 0; + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an unsigned int"); + } + } + + long as_long() const + { + switch (var_.type_) + { + case value_types::double_t: + return static_cast(var_.value_.double_val_); + case value_types::integer_t: + return static_cast(var_.value_.integer_val_); + case value_types::uinteger_t: + return static_cast(var_.value_.uinteger_val_); + case value_types::bool_t: + return var_.value_.bool_val_ ? 1 : 0; + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not a long"); + } + } + + unsigned long as_ulong() const + { + switch (var_.type_) + { + case value_types::double_t: + return static_cast(var_.value_.double_val_); + case value_types::integer_t: + return static_cast(var_.value_.integer_val_); + case value_types::uinteger_t: + return static_cast(var_.value_.uinteger_val_); + case value_types::bool_t: + return var_.value_.bool_val_ ? 1 : 0; + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an unsigned long"); + } + } + + void add(size_t index, const basic_json& value) + { + switch (var_.type_) + { + case value_types::array_t: + var_.value_.array_val_->add(index, value); + break; + default: + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Attempting to insert into a value that is not an array"); + } + } + } + + void add(size_t index, basic_json&& value){ + switch (var_.type_){ + case value_types::array_t: + var_.value_.array_val_->add(index, std::move(value)); + break; + default: + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Attempting to insert into a value that is not an array"); + } + } + } + + bool has_member(const string_type& name) const + { + switch (var_.type_) + { + case value_types::object_t: + { + const_object_iterator it = var_.value_.object_val_->find(name.data(),name.length()); + return it != members().end(); + } + break; + default: + return false; + } + } + + void remove_range(size_t from_index, size_t to_index) + { + switch (var_.type_) + { + case value_types::array_t: + var_.value_.array_val_->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_type& name) + { + erase(name.data(),name.length()); + } + void remove_member(const string_type& name) + { + erase(name.data(),name.length()); + } + // Removes a member from an object value + + bool is_empty() const JSONCONS_NOEXCEPT + { + return empty(); + } + bool is_numeric() const JSONCONS_NOEXCEPT + { + return is_number(); + } + + void assign_longlong(long long rhs) + { + var_.assign(rhs); + } + void assign_ulonglong(unsigned long long rhs) + { + var_.assign(rhs); + } + + template + static typename std::enable_if::type make_multi_array() + { + return make_array(); + } + template + static typename std::enable_if::type make_multi_array(size_t n) + { + return make_array(n); + } + template + static typename std::enable_if::type make_multi_array(size_t n, T val) + { + return make_array(n,val); + } + template + static typename std::enable_if::type make_multi_array(size_t m, size_t n) + { + return make_array<2>(m, n); + } + template + static typename std::enable_if::type make_multi_array(size_t m, size_t n, T val) + { + return make_array<2>(m, n, val); + } + template + static typename std::enable_if::type make_multi_array(size_t m, size_t n, size_t k) + { + return make_array<3>(m, n, k); + } + template + static typename std::enable_if::type make_multi_array(size_t m, size_t n, size_t k, T val) + { + return make_array<3>(m, n, k, val); + } +#endif + + object_range members() + { + switch (var_.type_) + { + case value_types::empty_object_t: + return object_range(object_iterator(true),object_iterator(true)); + case value_types::object_t: + return object_range(object_value().begin(),object_value().end()); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an object"); + } + } + + const_object_range members() const + { + switch (var_.type_) + { + case value_types::empty_object_t: + return const_object_range(const_object_iterator(true),const_object_iterator(true)); + case value_types::object_t: + return const_object_range(object_value().begin(),object_value().end()); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an object"); + } + } + + array_range elements() + { + switch (var_.type_) + { + case value_types::array_t: + return array_range(array_value().begin(),array_value().end()); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an array"); + } + } + + const_array_range elements() const + { + switch (var_.type_) + { + case value_types::array_t: + return const_array_range(array_value().begin(),array_value().end()); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an array"); + } + } + + array& array_value() + { + switch (var_.type_) + { + case value_types::array_t: + return *(var_.value_.array_val_); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad array cast"); + break; + } + } + + const array& array_value() const + { + switch (var_.type_) + { + case value_types::array_t: + return *(var_.value_.array_val_); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad array cast"); + break; + } + } + + object& object_value() + { + switch (var_.type_) + { + case value_types::empty_object_t: + create_object_implicitly(); + case value_types::object_t: + return *(var_.value_.object_val_); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad object cast"); + break; + } + } + + const object& object_value() const + { + switch (var_.type_) + { + case value_types::empty_object_t: + const_cast(this)->create_object_implicitly(); // HERE + case value_types::object_t: + return *(var_.value_.object_val_); + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad object cast"); + break; + } + } + +private: + + friend std::basic_ostream& operator<<(std::basic_ostream& os, const basic_json& o) + { + o.to_stream(os); + return os; + } + + friend std::basic_istream& operator<<(std::basic_istream& is, basic_json& o) + { + basic_json_deserializer> handler; + basic_json_reader reader(is, handler); + reader.read_next(); + reader.check_done(); + if (!handler.is_valid()) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Failed to parse json stream"); + } + o = handler.get_result(); + return is; + } +}; + +template +void swap(typename JsonT::member_type& a, typename JsonT::member_type& b) +{ + a.swap(b); +} + +template +bool basic_json::operator!=(const basic_json& rhs) const +{ + return !(*this == rhs); +} + +template +bool basic_json::operator==(const basic_json& rhs) const +{ + return var_ == rhs.var_; +} + +template +basic_json basic_json::make_2d_array(size_t m, size_t n) +{ + basic_json a = basic_json::array(); + a.resize(m); + for (size_t i = 0; i < a.size(); ++i) + { + a[i] = basic_json::make_array(n); + } + return a; +} + +template +template +basic_json basic_json::make_2d_array(size_t m, size_t n, T val) +{ + basic_json v; + v = val; + basic_json a = make_array(m); + for (size_t i = 0; i < a.size(); ++i) + { + a[i] = basic_json::make_array(n, v); + } + return a; +} + +template +basic_json basic_json::make_3d_array(size_t m, size_t n, size_t k) +{ + basic_json a = basic_json::array(); + a.resize(m); + for (size_t i = 0; i < a.size(); ++i) + { + a[i] = basic_json::make_2d_array(n, k); + } + return a; +} + +template +template +basic_json basic_json::make_3d_array(size_t m, size_t n, size_t k, T val) +{ + basic_json v; + v = val; + basic_json a = make_array(m); + for (size_t i = 0; i < a.size(); ++i) + { + a[i] = basic_json::make_2d_array(n, k, v); + } + return a; +} + +template +basic_json basic_json::parse_stream(std::basic_istream& is) +{ + basic_json_deserializer> handler; + basic_json_reader reader(is, handler); + reader.read_next(); + reader.check_done(); + if (!handler.is_valid()) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Failed to parse json stream"); + } + return handler.get_result(); +} + +template +basic_json basic_json::parse_stream(std::basic_istream& is, + basic_parse_error_handler& err_handler) +{ + basic_json_deserializer> handler; + basic_json_reader reader(is, handler, err_handler); + reader.read_next(); + reader.check_done(); + if (!handler.is_valid()) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Failed to parse json stream"); + } + return handler.get_result(); +} + +template +basic_json basic_json::parse_file(const std::string& filename) +{ + FILE* fp; + +#if defined(JSONCONS_HAS_FOPEN_S) + errno_t err = fopen_s(&fp, filename.c_str(), "rb"); + if (err != 0) + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Cannot open file %s", filename); + } +#else + fp = std::fopen(filename.c_str(), "rb"); + if (fp == nullptr) + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Cannot open file %s", filename); + } +#endif + basic_json_deserializer> handler; + try + { + // obtain file size: + std::fseek (fp , 0 , SEEK_END); + long size = std::ftell (fp); + std::rewind(fp); + + if (size > 0) + { + std::vector buffer(size); + + // copy the file into the buffer: + size_t result = std::fread (buffer.data(),1,size,fp); + if (result != static_cast(size)) + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Error reading file %s", filename); + } + + basic_json_parser parser(handler); + parser.begin_parse(); + parser.parse(buffer.data(),0,buffer.size()); + parser.end_parse(); + parser.check_done(buffer.data(),parser.index(),buffer.size()); + } + + std::fclose (fp); + } + catch (...) + { + std::fclose (fp); + throw; + } + if (!handler.is_valid()) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Failed to parse json file"); + } + return handler.get_result(); +} + +template +basic_json basic_json::parse_file(const std::string& filename, + basic_parse_error_handler& err_handler) +{ + FILE* fp; + +#if !defined(JSONCONS_HAS_FOPEN_S) + fp = std::fopen(filename.c_str(), "rb"); + if (fp == nullptr) + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Cannot open file %s", filename); + } +#else + errno_t err = fopen_s(&fp, filename.c_str(), "rb"); + if (err != 0) + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Cannot open file %s", filename); + } +#endif + + basic_json_deserializer> handler; + try + { + // obtain file size: + std::fseek (fp , 0 , SEEK_END); + long size = std::ftell (fp); + std::rewind(fp); + + if (size > 0) + { + std::vector buffer(size); + + // copy the file into the buffer: + size_t result = std::fread (buffer.data(),1,size,fp); + if (result != static_cast(size)) + { + JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Error reading file %s", filename); + } + + basic_json_parser parser(handler,err_handler); + parser.begin_parse(); + parser.parse(buffer.data(),0,buffer.size()); + parser.end_parse(); + parser.check_done(buffer.data(),parser.index(),buffer.size()); + } + + std::fclose (fp); + } + catch (...) + { + std::fclose (fp); + throw; + } + if (!handler.is_valid()) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Failed to parse json file"); + } + return handler.get_result(); +} + +template +typename basic_json::any& basic_json::any_value() +{ + switch (var_.type_) + { + case value_types::any_t: + { + return *var_.value_.any_val_; + } + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an any value"); + } +} + +template +const typename basic_json::any& basic_json::any_value() const +{ + switch (var_.type_) + { + case value_types::any_t: + { + return *var_.value_.any_val_; + } + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an any value"); + } +} + +template +std::basic_istream& operator>>(std::basic_istream& is, JsonT& o) +{ + basic_json_deserializer handler; + basic_json_reader reader(is, handler); + reader.read_next(); + reader.check_done(); + if (!handler.is_valid()) + { + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Failed to parse json stream"); + } + o = handler.get_result(); + return is; +} + +template +class json_printable +{ +public: + typedef typename JsonT::char_type char_type; + + json_printable(const JsonT& o, + bool is_pretty_print) + : o_(&o), is_pretty_print_(is_pretty_print) + { + } + + json_printable(const JsonT& o, + bool is_pretty_print, + const basic_output_format& format) + : o_(&o), is_pretty_print_(is_pretty_print), format_(format) + { + ; + } + + void to_stream(std::basic_ostream& os) const + { + o_->to_stream(os, format_, is_pretty_print_); + } + + friend std::basic_ostream& operator<<(std::basic_ostream& os, const json_printable& o) + { + o.to_stream(os); + return os; + } + + const JsonT *o_; + bool is_pretty_print_; + basic_output_format format_; +private: + json_printable(); +}; + +template +json_printable print(const JsonT& val) +{ + return json_printable(val,false); +} + +template +json_printable print(const JsonT& val, + const basic_output_format& format) +{ + return json_printable(val, false, format); +} + +template +json_printable pretty_print(const JsonT& val) +{ + return json_printable(val,true); +} + +template +json_printable pretty_print(const JsonT& val, + const basic_output_format& format) +{ + return json_printable(val, true, format); +} + +typedef basic_json> json; +typedef basic_json> wjson; + +typedef basic_json_deserializer json_deserializer; +typedef basic_json_deserializer wjson_deserializer; + +} + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_deserializer.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_deserializer.hpp new file mode 100644 index 00000000..31cd0db9 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_deserializer.hpp @@ -0,0 +1,267 @@ +// 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 +#include +#include +#include +#include +#include +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/json_input_handler.hpp" + +namespace jsoncons { + +template +class basic_json_deserializer : public basic_json_input_handler +{ + static const int default_stack_size = 1000; + + typedef typename JsonT::char_type char_type; + typedef typename JsonT::member_type member_type; + typedef typename JsonT::string_type string_type; + typedef typename string_type::allocator_type string_allocator; + typedef typename JsonT::allocator_type allocator_type; + typedef typename JsonT::array array; + typedef typename array::allocator_type array_allocator; + typedef typename JsonT::object object; + typedef typename object::allocator_type object_allocator; + typedef typename JsonT::value_type value_type; + + string_allocator sa_; + object_allocator oa_; + array_allocator aa_; + + JsonT result_; + size_t top_; + + struct stack_item + { + string_type name_; + value_type value_; + }; + std::vector stack_; + std::vector stack2_; + bool is_valid_; + +public: + basic_json_deserializer(const string_allocator& sa = string_allocator(), + const allocator_type& allocator = allocator_type()) + : sa_(sa), + oa_(allocator), + aa_(allocator), + top_(0), + stack_(default_stack_size), + stack2_(), + is_valid_(true) // initial json value is an empty object + + { + stack2_.reserve(100); + } + + bool is_valid() const + { + return is_valid_; + } + + JsonT get_result() + { + is_valid_ = false; + return std::move(result_); + } + +#if !defined(JSONCONS_NO_DEPRECATED) + JsonT& root() + { + return result_; + } +#endif + +private: + + void push_initial() + { + top_ = 0; + if (top_ >= stack_.size()) + { + stack_.resize(top_*2); + } + } + + void pop_initial() + { + JSONCONS_ASSERT(top_ == 1); + result_.swap(stack_[0].value_); + --top_; + } + + void push_object() + { + stack2_.push_back(top_); + stack_[top_].value_ = object(oa_); + if (++top_ >= stack_.size()) + { + stack_.resize(top_*2); + } + } + + void pop_object() + { + stack2_.pop_back(); + JSONCONS_ASSERT(top_ > 0); + } + + void push_array() + { + stack2_.push_back(top_); + stack_[top_].value_ = array(aa_); + if (++top_ >= stack_.size()) + { + stack_.resize(top_*2); + } + } + + void pop_array() + { + stack2_.pop_back(); + JSONCONS_ASSERT(top_ > 0); + } + + void do_begin_json() override + { + is_valid_ = false; + push_initial(); + } + + void do_end_json() override + { + is_valid_ = true; + pop_initial(); + } + + void do_begin_object(const basic_parsing_context&) override + { + push_object(); + } + + void do_end_object(const basic_parsing_context&) override + { + end_structure(); + pop_object(); + } + + void do_begin_array(const basic_parsing_context&) override + { + push_array(); + } + + void do_end_array(const basic_parsing_context&) override + { + end_structure(); + pop_array(); + } + + static member_type move_pair(stack_item&& val) + { + return member_type(std::move(val.name_),std::move(val.value_)); + } + + void end_structure() + { + JSONCONS_ASSERT(stack2_.size() > 0); + if (stack_[stack2_.back()].value_.is_object()) + { + size_t count = top_ - (stack2_.back() + 1); + auto s = stack_.begin() + (stack2_.back()+1); + auto send = s + count; + stack_[stack2_.back()].value_.object_value().insert( + std::make_move_iterator(s), + std::make_move_iterator(send), + move_pair); + top_ -= count; + } + else + { + size_t count = top_ - (stack2_.back() + 1); + stack_[stack2_.back()].value_.resize(count); + + auto s = stack_.begin() + (stack2_.back()+1); + auto dend = stack_[stack2_.back()].value_.elements().end(); + for (auto it = stack_[stack2_.back()].value_.elements().begin(); + it != dend; ++it, ++s) + { + *it = std::move(s->value_); + } + top_ -= count; + } + } + + void do_name(const char_type* p, size_t length, const basic_parsing_context&) override + { + stack_[top_].name_ = string_type(p,length,sa_); + } + + void do_string_value(const char_type* p, size_t length, const basic_parsing_context&) override + { + stack_[top_].value_ = JsonT(p,length,sa_); + if (++top_ >= stack_.size()) + { + stack_.resize(top_*2); + } + } + + void do_integer_value(int64_t value, const basic_parsing_context&) override + { + stack_[top_].value_ = value; + if (++top_ >= stack_.size()) + { + stack_.resize(top_*2); + } + } + + void do_uinteger_value(uint64_t value, const basic_parsing_context&) override + { + stack_[top_].value_ = value; + if (++top_ >= stack_.size()) + { + stack_.resize(top_*2); + } + } + + void do_double_value(double value, uint8_t precision, const basic_parsing_context&) override + { + stack_[top_].value_ = value_type(value,precision); + if (++top_ >= stack_.size()) + { + stack_.resize(top_*2); + } + } + + void do_bool_value(bool value, const basic_parsing_context&) override + { + stack_[top_].value_ = value; + if (++top_ >= stack_.size()) + { + stack_.resize(top_*2); + } + } + + void do_null_value(const basic_parsing_context&) override + { + stack_[top_].value_ = null_type(); + if (++top_ >= stack_.size()) + { + stack_.resize(top_*2); + } + } +}; + +} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_error_category.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_error_category.hpp new file mode 100644 index 00000000..90d12d56 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_error_category.hpp @@ -0,0 +1,111 @@ +/// 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_TEXT_ERROR_CATEGORY_HPP +#define JSONCONS_JSON_TEXT_ERROR_CATEGORY_HPP + +#include "jsoncons/jsoncons.hpp" +#include + +namespace jsoncons { + +namespace json_parser_errc +{ + const int unexpected_eof = 1; + const int invalid_json_text = 2; + const int extra_character = 3; + const int max_depth_exceeded = 4; + const int single_quote = 5; + const int illegal_character_in_string = 6; + const int extra_comma = 7; + const int expected_name = 8; + const int expected_value = 9; + const int invalid_value = 10; + const int expected_colon = 11; + const int illegal_control_character = 12; + const int illegal_escaped_character = 13; + const int expected_codepoint_surrogate_pair = 14; + const int invalid_hex_escape_sequence = 15; + const int invalid_unicode_escape_sequence = 16; + const int leading_zero = 17; + const int invalid_number = 18; + const int expected_comma_or_right_brace = 19; + const int expected_comma_or_right_bracket = 20; + const int unexpected_right_bracket = 21; + const int unexpected_right_brace = 22; +} + +class json_error_category_impl + : public std::error_category +{ +public: + virtual const char* name() const JSONCONS_NOEXCEPT + { + return "json"; + } + virtual std::string message(int ev) const + { + switch (ev) + { + case json_parser_errc::unexpected_eof: + return "Unexpected end of file"; + 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 ']'"; + default: + return "Unknown JSON parser error"; + } + } +}; + +inline +const std::error_category& json_error_category() +{ + static json_error_category_impl instance; + return instance; +} + +} +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_filter.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_filter.hpp new file mode 100644 index 00000000..2019c01d --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_filter.hpp @@ -0,0 +1,324 @@ +// 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 + +#include "jsoncons/json_input_handler.hpp" +#include "jsoncons/json_output_handler.hpp" +#include "jsoncons/parse_error_handler.hpp" + +namespace jsoncons { + +template +class basic_json_input_output_adapter : public basic_json_input_handler +{ +public: + basic_json_input_output_adapter() + : writer_(std::addressof(null_json_output_handler())) + { + } + + basic_json_input_output_adapter(basic_json_output_handler& handler) + : writer_(std::addressof(handler)) + { + } + +private: + + void do_begin_json() override + { + writer_->begin_json(); + } + + void do_end_json() override + { + writer_->end_json(); + } + + void do_begin_object(const basic_parsing_context& context) override + { + writer_->begin_object(); + } + + void do_end_object(const basic_parsing_context& context) override + { + writer_->end_object(); + } + + void do_begin_array(const basic_parsing_context& context) override + { + writer_->begin_array(); + } + + void do_end_array(const basic_parsing_context& context) override + { + writer_->end_array(); + } + + void do_name(const CharT* name, size_t length, + const basic_parsing_context& context) override + { + writer_->name(name, length); + } + + void do_string_value(const CharT* value, size_t length, + const basic_parsing_context& context) override + { + writer_->value(value, length); + } + + void do_integer_value(int64_t value, const basic_parsing_context& context) override + { + writer_->value(value); + } + + void do_uinteger_value(uint64_t value, + const basic_parsing_context& context) override + { + writer_->value(value); + } + + void do_double_value(double value, uint8_t precision, const basic_parsing_context& context) override + { + writer_->value(value, precision); + } + + void do_bool_value(bool value, const basic_parsing_context& context) override + { + writer_->value(value); + } + + void do_null_value(const basic_parsing_context& context) override + { + writer_->value(null_type()); + } + + basic_json_output_handler* writer_; +}; + +template +class basic_json_filter : public basic_json_input_handler +{ +public: + basic_json_filter(basic_json_input_handler& handler) + : handler_(std::addressof(handler)), + err_handler_(std::addressof(basic_default_parse_error_handler::instance())) + { + } + + basic_json_filter(basic_json_input_handler& handler, + basic_parse_error_handler& err_handler) + : handler_(std::addressof(handler)), + err_handler_(std::addressof(err_handler)) + { + } + + basic_json_filter(basic_json_output_handler& output_handler) + : input_output_adapter_(output_handler), handler_(std::addressof(input_output_adapter_)), + err_handler_(std::addressof(basic_default_parse_error_handler::instance())) + { + } + + basic_json_filter(basic_json_output_handler& output_handler, + basic_parse_error_handler& err_handler) + : input_output_adapter_(output_handler), handler_(std::addressof(input_output_adapter_)), + err_handler_(std::addressof(err_handler)) + { + } + + basic_json_input_handler& input_handler() + { + return *handler_; + } + +#if !defined(JSONCONS_NO_DEPRECATED) + basic_json_input_handler& parent() + { + return *handler_; + } +#endif + +private: + void do_begin_json() override + { + handler_->begin_json(); + } + + void do_end_json() override + { + handler_->end_json(); + } + + void do_begin_object(const basic_parsing_context& context) override + { + handler_->begin_object(context); + } + + void do_end_object(const basic_parsing_context& context) override + { + handler_->end_object(context); + } + + void do_begin_array(const basic_parsing_context& context) override + { + handler_->begin_array(context); + } + + void do_end_array(const basic_parsing_context& context) override + { + handler_->end_array(context); + } + + void do_name(const CharT* name, size_t length, const basic_parsing_context& context) override + { + handler_->name(name, length, context); + } + + void do_string_value(const CharT* value, size_t length, const basic_parsing_context& context) override + { + handler_->value(value,length,context); + } + + void do_double_value(double value, uint8_t precision, const basic_parsing_context& context) override + { + handler_->value(value,precision,context); + } + + void do_integer_value(int64_t value, const basic_parsing_context& context) override + { + handler_->value(value,context); + } + + void do_uinteger_value(uint64_t value, const basic_parsing_context& context) override + { + handler_->value(value,context); + } + + void do_bool_value(bool value, const basic_parsing_context& context) override + { + handler_->value(value,context); + } + + void do_null_value(const basic_parsing_context& context) override + { + handler_->value(null_type(),context); + } + + basic_json_input_output_adapter input_output_adapter_; + basic_json_input_handler* handler_; + basic_parse_error_handler* err_handler_; +}; + +// Filters out begin_json and end_json events +template +class basic_begin_end_json_filter : public basic_json_filter +{ +public: + basic_begin_end_json_filter(basic_json_input_handler& handler) + : basic_json_filter(handler) + { + } +private: + void do_begin_json() override + { + } + + void do_end_json() override + { + } +}; + +template +class basic_json_output_input_adapter : public basic_json_output_handler +{ +public: + basic_json_output_input_adapter(basic_json_input_handler& input_handler, + const basic_parsing_context& context) + : input_handler_(std::addressof(input_handler)), + context_(std::addressof(context)) + { + } + +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(*context_); + } + + void do_end_object() override + { + input_handler_->end_object(*context_); + } + + void do_begin_array() override + { + input_handler_->begin_array(*context_); + } + + void do_end_array() override + { + input_handler_->end_array(*context_); + } + + void do_name(const CharT* name, size_t length) override + { + input_handler_->name(name, length, *context_); + } + + void do_string_value(const CharT* value, size_t length) override + { + input_handler_->value(value, length, *context_); + } + + void do_integer_value(int64_t value) override + { + input_handler_->value(value, *context_); + } + + void do_uinteger_value(uint64_t value) override + { + input_handler_->value(value, *context_); + } + + void do_double_value(double value, uint8_t precision) override + { + input_handler_->value(value, precision, *context_); + } + + void do_bool_value(bool value) override + { + input_handler_->value(value, *context_); + } + + void do_null_value() override + { + input_handler_->value(null_type(), *context_); + } + + basic_json_input_handler* input_handler_; + const basic_parsing_context* context_; +}; + +typedef basic_json_filter json_filter; +typedef basic_json_filter wjson_filter; + +} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_input_handler.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_input_handler.hpp new file mode 100644 index 00000000..566209e5 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_input_handler.hpp @@ -0,0 +1,282 @@ +// 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 +#include "jsoncons/jsoncons.hpp" + +namespace jsoncons { + +template +uint64_t string_to_uinteger(const CharT *s, size_t length) throw(std::overflow_error) +{ + static const uint64_t max_value = std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + static const uint64_t max_value_div_10 = max_value / 10; + uint64_t n = 0; + for (size_t i = 0; i < length; ++i) + { + uint64_t x = s[i] - '0'; + if (n > max_value_div_10) + { + throw std::overflow_error("Unsigned overflow"); + } + n = n * 10; + if (n > max_value - x) + { + throw std::overflow_error("Unsigned overflow"); + } + + n += x; + } + return n; +} + +template +int64_t string_to_integer(bool has_neg, const CharT *s, size_t length) throw(std::overflow_error) +{ + const long long max_value = std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + const long long max_value_div_10 = max_value / 10; + + long long n = 0; + for (size_t i = 0; i < length; ++i) + { + long long x = s[i] - '0'; + if (n > max_value_div_10) + { + throw std::overflow_error("Integer overflow"); + } + n = n * 10; + if (n > max_value - x) + { + throw std::overflow_error("Integer overflow"); + } + + n += x; + } + return has_neg ? -n : n; +} + +template +class basic_parsing_context; + +template +class basic_json_input_handler +{ +public: + virtual ~basic_json_input_handler() {} + + void begin_json() + { + do_begin_json(); + } + + void end_json() + { + do_end_json(); + } + + void begin_object(const basic_parsing_context& context) + { + do_begin_object(context); + } + + void end_object(const basic_parsing_context& context) + { + do_end_object(context); + } + + void begin_array(const basic_parsing_context& context) + { + do_begin_array(context); + } + + void end_array(const basic_parsing_context& context) + { + do_end_array(context); + } + + void name(const std::basic_string& name, const basic_parsing_context& context) + { + do_name(name.data(), name.length(), context); + } + + void name(const CharT* p, size_t length, const basic_parsing_context& context) + { + do_name(p, length, context); + } + + void value(const std::basic_string& value, const basic_parsing_context& context) + { + do_string_value(value.data(), value.length(), context); + } + + void value(const CharT* p, size_t length, const basic_parsing_context& context) + { + do_string_value(p, length, context); + } + + void value(const CharT* p, const basic_parsing_context& context) + { + do_string_value(p, std::char_traits::length(p), context); + } + + void value(int value, const basic_parsing_context& context) + { + do_integer_value(value,context); + } + + void value(long value, const basic_parsing_context& context) + { + do_integer_value(value,context); + } + + void value(long long value, const basic_parsing_context& context) + { + do_integer_value(value,context); + } + + void value(unsigned int value, const basic_parsing_context& context) + { + do_uinteger_value(value,context); + } + + void value(unsigned long value, const basic_parsing_context& context) + { + do_uinteger_value(value,context); + } + + void value(unsigned long long value, const basic_parsing_context& context) + { + do_uinteger_value(value,context); + } + + void value(float value, uint8_t precision, const basic_parsing_context& context) + { + do_double_value(value, precision, context); + } + + void value(double value, uint8_t precision, const basic_parsing_context& context) + { + do_double_value(value, precision, context); + } + + void value(bool value, const basic_parsing_context& context) + { + do_bool_value(value,context); + } + + void value(null_type, const basic_parsing_context& context) + { + do_null_value(context); + } + +private: + virtual void do_begin_json() = 0; + + virtual void do_end_json() = 0; + + virtual void do_begin_object(const basic_parsing_context& context) = 0; + + virtual void do_end_object(const basic_parsing_context& context) = 0; + + virtual void do_begin_array(const basic_parsing_context& context) = 0; + + virtual void do_end_array(const basic_parsing_context& context) = 0; + + virtual void do_name(const CharT* name, size_t length, const basic_parsing_context& context) = 0; + + virtual void do_null_value(const basic_parsing_context& context) = 0; + + virtual void do_string_value(const CharT* value, size_t length, const basic_parsing_context& context) = 0; + + virtual void do_double_value(double value, uint8_t precision, const basic_parsing_context& context) = 0; + + virtual void do_integer_value(int64_t value, const basic_parsing_context& context) = 0; + + virtual void do_uinteger_value(uint64_t value, const basic_parsing_context& context) = 0; + + virtual void do_bool_value(bool value, const basic_parsing_context& context) = 0; +}; + + +template +class basic_empty_json_input_handler : public basic_json_input_handler +{ +public: + static basic_json_input_handler& instance() + { + static basic_empty_json_input_handler instance; + return instance; + } +private: + void do_begin_json() override + { + } + + void do_end_json() override + { + } + + void do_begin_object(const basic_parsing_context&) override + { + } + + void do_end_object(const basic_parsing_context&) override + { + } + + void do_begin_array(const basic_parsing_context&) override + { + } + + void do_end_array(const basic_parsing_context&) override + { + } + + void do_name(const CharT* p, size_t length, const basic_parsing_context&) override + { + (void)p; + (void)length; + } + + void do_null_value(const basic_parsing_context&) override + { + } + + void do_string_value(const CharT* p, size_t length, const basic_parsing_context&) override + { + (void)p; + (void)length; + } + + void do_double_value(double, uint8_t, const basic_parsing_context&) override + { + } + + void do_integer_value(int64_t, const basic_parsing_context&) override + { + } + + void do_uinteger_value(uint64_t, const basic_parsing_context&) override + { + } + + void do_bool_value(bool, const basic_parsing_context&) override + { + } +}; + +typedef basic_json_input_handler json_input_handler; +typedef basic_json_input_handler wjson_input_handler; + +typedef basic_empty_json_input_handler empty_json_input_handler; +typedef basic_empty_json_input_handler wempty_json_input_handler; + +} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_output_handler.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_output_handler.hpp new file mode 100644 index 00000000..d0f3de8f --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_output_handler.hpp @@ -0,0 +1,262 @@ +// 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 +#include "jsoncons/jsoncons.hpp" + +namespace jsoncons { + +template +void print_integer(int64_t value, buffered_ostream& os) +{ + CharT buf[255]; + uint64_t u = (value < 0) ? static_cast(-value) : static_cast(value); + CharT* p = buf; + do + { + *p++ = static_cast(48 + u%10); + } + while (u /= 10); + if (value < 0) + { + os.put('-'); + } + while (--p >= buf) + { + os.put(*p); + } +} + +template +void print_uinteger(uint64_t value, buffered_ostream& os) +{ + CharT buf[255]; + CharT* p = buf; + do + { + *p++ = static_cast(48 + value % 10); + } while (value /= 10); + while (--p >= buf) + { + os.put(*p); + } +} + +template +class basic_json_output_handler +{ +public: + 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 end_object() + { + do_end_object(); + } + + void begin_array() + { + do_begin_array(); + } + + void end_array() + { + do_end_array(); + } + + void name(const std::basic_string& name) + { + do_name(name.data(), name.length()); + } + + void name(const CharT* p, size_t length) + { + do_name(p, length); + } + + void value(const std::basic_string& value) + { + do_string_value(value.data(), value.length()); + } + + void value(const CharT* p, size_t length) + { + do_string_value(p, length); + } + + void value(const CharT* p) + { + do_string_value(p, std::char_traits::length(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) + { + do_double_value(value, precision); + } + + void value(bool value) + { + do_bool_value(value); + } + + void value(null_type) + { + do_null_value(); + } + +private: + + virtual void do_begin_json() = 0; + + virtual void do_end_json() = 0; + + virtual void do_name(const CharT* name, size_t length) = 0; + + virtual void do_begin_object() = 0; + + virtual void do_end_object() = 0; + + virtual void do_begin_array() = 0; + + virtual void do_end_array() = 0; + + virtual void do_null_value() = 0; + + virtual void do_string_value(const CharT* value, size_t length) = 0; + + virtual void do_double_value(double value, uint8_t precision) = 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 null_json_output_handler_impl : public basic_json_output_handler +{ +private: + + void do_begin_json() override + { + } + + void do_end_json() override + { + } + + void do_name(const CharT* name, size_t length) override + { + (void)name; + (void)length; + } + + 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 CharT* p, size_t length) override + { + (void)p; + (void)length; + } + + void do_double_value(double, uint8_t) override + { + } + + void do_integer_value(int64_t) override + { + } + + void do_uinteger_value(uint64_t) override + { + } + + void do_bool_value(bool) override + { + } + +}; + +template +basic_json_output_handler& null_json_output_handler() +{ + static null_json_output_handler_impl instance; + return instance; +} + +typedef basic_json_output_handler json_output_handler; +typedef basic_json_output_handler wjson_output_handler; + +} +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp new file mode 100644 index 00000000..8a06c2e7 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp @@ -0,0 +1,1587 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/json_input_handler.hpp" +#include "jsoncons/parse_error_handler.hpp" +#include "jsoncons/json_error_category.hpp" + +namespace jsoncons { + +enum class states +{ + 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, + member_name, + escape, + u1, + u2, + u3, + u4, + expect_surrogate_pair1, + expect_surrogate_pair2, + u6, + u7, + u8, + u9, + minus, + zero, + integer, + fraction, + exp1, + exp2, + exp3, + n, + t, + f, + cr, + lf, + done +}; + +template +class basic_json_parser : private basic_parsing_context +{ + static const int default_initial_stack_capacity_ = 100; + + std::vector stack_; + basic_json_input_handler *handler_; + basic_parse_error_handler *err_handler_; + size_t column_; + size_t line_; + uint32_t cp_; + uint32_t cp2_; + std::basic_string string_buffer_; + std::basic_string number_buffer_; + bool is_negative_; + size_t index_; + int initial_stack_capacity_; + int nesting_depth_; + int max_depth_; + float_reader float_reader_; + const CharT* begin_input_; + const CharT* end_input_; + const CharT* p_; + uint8_t precision_; + std::pair literal_; + size_t literal_index_; + +public: + basic_json_parser(basic_json_input_handler& handler) + : handler_(std::addressof(handler)), + err_handler_(std::addressof(basic_default_parse_error_handler::instance())), + column_(0), + line_(0), + cp_(0), + is_negative_(false), + index_(0), + initial_stack_capacity_(default_initial_stack_capacity_) + { + max_depth_ = std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + + basic_json_parser(basic_json_input_handler& handler, + basic_parse_error_handler& err_handler) + : handler_(std::addressof(handler)), + err_handler_(std::addressof(err_handler)), + column_(0), + line_(0), + cp_(0), + is_negative_(false), + index_(0), + initial_stack_capacity_(default_initial_stack_capacity_) + + { + max_depth_ = std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + + const basic_parsing_context& parsing_context() const + { + return *this; + } + + ~basic_json_parser() + { + } + + size_t max_nesting_depth() const + { + return static_cast(max_depth_); + } + + void max_nesting_depth(size_t max_nesting_depth) + { + max_depth_ = static_cast(std::min(max_nesting_depth,static_cast(std::numeric_limits::max JSONCONS_NO_MACRO_EXP()))); + } + + states parent() const + { + return stack_[stack_.size()-2]; + } + + bool done() const + { + return stack_.back() == states::done; + } + + void do_space() + { + while ((p_ + 1) < end_input_ && (*(p_ + 1) == ' ' || *(p_ + 1) == '\t')) + { + ++p_; + ++column_; + } + } + + void do_begin_object() + { + if (++nesting_depth_ >= max_depth_) + { + err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this); + } + stack_.back() = states::object; + stack_.push_back(states::expect_member_name_or_end); + handler_->begin_object(*this); + } + + void do_end_object() + { + --nesting_depth_; + JSONCONS_ASSERT(!stack_.empty()) + stack_.pop_back(); + if (stack_.back() == states::object) + { + handler_->end_object(*this); + } + else if (stack_.back() == states::array) + { + err_handler_->fatal_error(std::error_code(json_parser_errc::expected_comma_or_right_bracket, json_error_category()), *this); + } + else + { + err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_brace, json_error_category()), *this); + } + + JSONCONS_ASSERT(stack_.size() >= 2); + if (parent() == states::root) + { + stack_.back() = states::done; + handler_->end_json(); + } + else + { + stack_.back() = states::expect_comma_or_end; + } + } + + void do_begin_array() + { + if (++nesting_depth_ >= max_depth_) + { + err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this); + } + stack_.back() = states::array; + stack_.push_back(states::expect_value_or_end); + handler_->begin_array(*this); + } + + void do_end_array() + { + --nesting_depth_; + JSONCONS_ASSERT(!stack_.empty()) + stack_.pop_back(); + if (stack_.back() == states::array) + { + handler_->end_array(*this); + } + else if (stack_.back() == states::object) + { + err_handler_->fatal_error(std::error_code(json_parser_errc::expected_comma_or_right_brace, json_error_category()), *this); + } + else + { + err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_bracket, json_error_category()), *this); + } + JSONCONS_ASSERT(stack_.size() >= 2); + if (parent() == states::root) + { + stack_.back() = states::done; + handler_->end_json(); + } + else + { + stack_.back() = states::expect_comma_or_end; + } + } + + void begin_parse() + { + stack_.clear(); + stack_.reserve(initial_stack_capacity_); + stack_.push_back(states::root); + stack_.push_back(states::start); + line_ = 1; + column_ = 1; + nesting_depth_ = 0; + } + + void check_done(const CharT* input, size_t start, size_t length) + { + index_ = start; + for (; index_ < length; ++index_) + { + CharT curr_char_ = input[index_]; + switch (curr_char_) + { + case '\n': + case '\r': + case '\t': + case ' ': + break; + default: + err_handler_->error(std::error_code(json_parser_errc::extra_character, json_error_category()), *this); + break; + } + } + } + + void parse_string() + { + const CharT* sb = p_; + bool done = false; + while (!done && p_ < end_input_) + { + switch (*p_) + { + 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: + string_buffer_.append(sb,p_-sb); + column_ += (p_ - sb + 1); + err_handler_->error(std::error_code(json_parser_errc::illegal_control_character, json_error_category()), *this); + // recovery - skip + done = true; + ++p_; + break; + case '\r': + { + column_ += (p_ - sb + 1); + err_handler_->error(std::error_code(json_parser_errc::illegal_character_in_string, json_error_category()), *this); + // recovery - keep + string_buffer_.append(sb, p_ - sb + 1); + stack_.push_back(states::cr); + done = true; + ++p_; + } + break; + case '\n': + { + column_ += (p_ - sb + 1); + err_handler_->error(std::error_code(json_parser_errc::illegal_character_in_string, json_error_category()), *this); + // recovery - keep + string_buffer_.append(sb, p_ - sb + 1); + stack_.push_back(states::lf); + done = true; + ++p_; + } + break; + case '\t': + { + column_ += (p_ - sb + 1); + err_handler_->error(std::error_code(json_parser_errc::illegal_character_in_string, json_error_category()), *this); + // recovery - keep + string_buffer_.append(sb, p_ - sb + 1); + done = true; + ++p_; + } + break; + case '\\': + string_buffer_.append(sb,p_-sb); + column_ += (p_ - sb + 1); + stack_.back() = states::escape; + done = true; + ++p_; + break; + case '\"': + if (string_buffer_.length() == 0) + { + end_string_value(sb,p_-sb); + } + else + { + string_buffer_.append(sb,p_-sb); + end_string_value(string_buffer_.data(),string_buffer_.length()); + string_buffer_.clear(); + } + column_ += (p_ - sb + 1); + done = true; + ++p_; + break; + default: + ++p_; + break; + } + } + if (!done) + { + string_buffer_.append(sb,p_-sb); + column_ += (p_ - sb + 1); + } + } + + void parse(const CharT* const input, size_t start, size_t length) + { + begin_input_ = input + start; + end_input_ = input + length; + p_ = begin_input_; + + index_ = start; + while ((p_ < end_input_) && (stack_.back() != states::done)) + { + switch (*p_) + { + 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: + err_handler_->error(std::error_code(json_parser_errc::illegal_control_character, json_error_category()), *this); + break; + default: + break; + } + + switch (stack_.back()) + { + case states::cr: + ++line_; + column_ = 1; + switch (*p_) + { + case '\n': + JSONCONS_ASSERT(!stack_.empty()) + stack_.pop_back(); + ++p_; + break; + default: + JSONCONS_ASSERT(!stack_.empty()) + stack_.pop_back(); + break; + } + break; + case states::lf: + ++line_; + column_ = 1; + JSONCONS_ASSERT(!stack_.empty()) + stack_.pop_back(); + break; + case states::start: + { + switch (*p_) + { + case '\r': + stack_.push_back(states::cr); + break; + case '\n': + stack_.push_back(states::lf); + break; + case ' ':case '\t': + do_space(); + break; + case '/': + stack_.push_back(states::slash); + break; + case '{': + handler_->begin_json(); + do_begin_object(); + break; + case '[': + handler_->begin_json(); + do_begin_array(); + break; + case '\"': + handler_->begin_json(); + stack_.back() = states::string; + break; + case '-': + handler_->begin_json(); + is_negative_ = true; + stack_.back() = states::minus; + break; + case '0': + handler_->begin_json(); + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::zero; + break; + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + handler_->begin_json(); + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::integer; + break; + case 'f': + handler_->begin_json(); + stack_.back() = states::f; + literal_ = json_literals::false_literal(); + literal_index_ = 1; + break; + case 'n': + handler_->begin_json(); + stack_.back() = states::n; + literal_ = json_literals::null_literal(); + literal_index_ = 1; + break; + case 't': + handler_->begin_json(); + stack_.back() = states::t; + literal_ = json_literals::true_literal(); + literal_index_ = 1; + break; + case '}': + err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_brace, json_error_category()), *this); + break; + case ']': + err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_bracket, json_error_category()), *this); + break; + default: + err_handler_->fatal_error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + + case states::expect_comma_or_end: + { + switch (*p_) + { + case '\r': + stack_.push_back(states::cr); + break; + case '\n': + stack_.push_back(states::lf); + break; + case ' ':case '\t': + do_space(); + break; + case '/': + stack_.push_back(states::slash); + break; + case '}': + do_end_object(); + break; + case ']': + do_end_array(); + break; + case ',': + begin_member_or_element(); + break; + default: + JSONCONS_ASSERT(stack_.size() >= 2); + if (parent() == states::array) + { + err_handler_->error(std::error_code(json_parser_errc::expected_comma_or_right_bracket, json_error_category()), *this); + } + else if (parent() == states::object) + { + err_handler_->error(std::error_code(json_parser_errc::expected_comma_or_right_brace, json_error_category()), *this); + } + break; + } + } + ++p_; + ++column_; + break; + case states::expect_member_name_or_end: + { + switch (*p_) + { + case '\r': + stack_.push_back(states::cr); + break; + case '\n': + stack_.push_back(states::lf); + break; + case ' ':case '\t': + do_space(); + break; + case '/': + stack_.push_back(states::slash); + break; + case '}': + do_end_object(); + break; + case '\"': + stack_.back() = states::member_name; + stack_.push_back(states::string); + break; + case '\'': + err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_name, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::expect_member_name: + { + switch (*p_) + { + case '\r': + stack_.push_back(states::cr); + break; + case '\n': + stack_.push_back(states::lf); + break; + case ' ':case '\t': + do_space(); + break; + case '/': + stack_.push_back(states::slash); + break; + case '\"': + //stack_.back() = states::string; + stack_.back() = states::member_name; + stack_.push_back(states::string); + break; + case '}': + --nesting_depth_; + err_handler_->error(std::error_code(json_parser_errc::extra_comma, json_error_category()), *this); + break; + case '\'': + err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_name, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::expect_colon: + { + switch (*p_) + { + case '\r': + stack_.push_back(states::cr); + break; + case '\n': + stack_.push_back(states::lf); + break; + case ' ':case '\t': + do_space(); + break; + case '/': + stack_.push_back(states::slash); + break; + case ':': + stack_.back() = states::expect_value; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_colon, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::expect_value: + { + switch (*p_) + { + case '\r': + stack_.push_back(states::cr); + break; + case '\n': + stack_.push_back(states::lf); + break; + case ' ':case '\t': + do_space(); + break; + case '/': + stack_.push_back(states::slash); + break; + case '{': + do_begin_object(); + break; + case '[': + do_begin_array(); + break; + case '\"': + stack_.back() = states::string; + break; + case '-': + is_negative_ = true; + stack_.back() = states::minus; + break; + case '0': + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::zero; + break; + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::integer; + break; + case 'f': + stack_.back() = states::f; + literal_ = json_literals::false_literal(); + literal_index_ = 1; + break; + case 'n': + stack_.back() = states::n; + literal_ = json_literals::null_literal(); + literal_index_ = 1; + break; + case 't': + stack_.back() = states::t; + literal_ = json_literals::true_literal(); + literal_index_ = 1; + break; + case ']': + JSONCONS_ASSERT(stack_.size() >= 2); + if (parent() == states::array) + { + err_handler_->error(std::error_code(json_parser_errc::extra_comma, json_error_category()), *this); + } + else + { + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + } + break; + case '\'': + err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::expect_value_or_end: + { + switch (*p_) + { + case '\r': + stack_.push_back(states::cr); + break; + case '\n': + stack_.push_back(states::lf); + break; + case ' ':case '\t': + do_space(); + break; + case '/': + stack_.push_back(states::slash); + break; + case '{': + do_begin_object(); + break; + case '[': + do_begin_array(); + break; + case ']': + do_end_array(); + break; + case '\"': + stack_.back() = states::string; + break; + case '-': + is_negative_ = true; + stack_.back() = states::minus; + break; + case '0': + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::zero; + break; + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::integer; + break; + case 'f': + stack_.back() = states::f; + literal_ = json_literals::false_literal(); + literal_index_ = 1; + break; + case 'n': + stack_.back() = states::n; + literal_ = json_literals::null_literal(); + literal_index_ = 1; + break; + case 't': + stack_.back() = states::t; + literal_ = json_literals::true_literal(); + literal_index_ = 1; + break; + case '\'': + err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::string: + parse_string(); + break; + case states::escape: + { + escape_next_char(*p_); + } + ++p_; + ++column_; + break; + case states::u1: + { + append_codepoint(*p_); + stack_.back() = states::u2; + } + ++p_; + ++column_; + break; + case states::u2: + { + append_codepoint(*p_); + stack_.back() = states::u3; + } + ++p_; + ++column_; + break; + case states::u3: + { + append_codepoint(*p_); + stack_.back() = states::u4; + } + ++p_; + ++column_; + break; + case states::u4: + { + append_codepoint(*p_); + if (cp_ >= min_lead_surrogate && cp_ <= max_lead_surrogate) + { + stack_.back() = states::expect_surrogate_pair1; + } + else + { + json_char_traits::append_codepoint_to_string(cp_, string_buffer_); + stack_.back() = states::string; + } + } + ++p_; + ++column_; + break; + case states::expect_surrogate_pair1: + { + switch (*p_) + { + case '\\': + cp2_ = 0; + stack_.back() = states::expect_surrogate_pair2; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_codepoint_surrogate_pair, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::expect_surrogate_pair2: + { + switch (*p_) + { + case 'u': + stack_.back() = states::u6; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_codepoint_surrogate_pair, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::u6: + { + append_second_codepoint(*p_); + stack_.back() = states::u7; + } + ++p_; + ++column_; + break; + case states::u7: + { + append_second_codepoint(*p_); + stack_.back() = states::u8; + } + ++p_; + ++column_; + break; + case states::u8: + { + append_second_codepoint(*p_); + stack_.back() = states::u9; + } + ++p_; + ++column_; + break; + case states::u9: + { + append_second_codepoint(*p_); + uint32_t cp = 0x10000 + ((cp_ & 0x3FF) << 10) + (cp2_ & 0x3FF); + json_char_traits::append_codepoint_to_string(cp, string_buffer_); + stack_.back() = states::string; + } + ++p_; + ++column_; + break; + case states::minus: + { + switch (*p_) + { + case '0': + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::zero; + break; + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::integer; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::zero: + { + switch (*p_) + { + case '\r': + end_integer_value(); + stack_.push_back(states::cr); + break; + case '\n': + end_integer_value(); + stack_.push_back(states::lf); + break; + case ' ':case '\t': + end_integer_value(); + do_space(); + break; + case '/': + end_integer_value(); + stack_.push_back(states::slash); + break; + case '}': + end_integer_value(); + do_end_object(); + break; + case ']': + end_integer_value(); + do_end_array(); + break; + case '.': + precision_ = static_cast(number_buffer_.length()); + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::fraction; + break; + case ',': + end_integer_value(); + begin_member_or_element(); + break; + case '0': case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + err_handler_->error(std::error_code(json_parser_errc::leading_zero, json_error_category()), *this); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::integer: + { + switch (*p_) + { + case '\r': + end_integer_value(); + stack_.push_back(states::cr); + break; + case '\n': + end_integer_value(); + stack_.push_back(states::lf); + break; + case ' ':case '\t': + end_integer_value(); + do_space(); + break; + case '/': + end_integer_value(); + stack_.push_back(states::slash); + break; + case '}': + end_integer_value(); + do_end_object(); + break; + case ']': + end_integer_value(); + do_end_array(); + break; + 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(*p_)); + stack_.back() = states::integer; + break; + case '.': + precision_ = static_cast(number_buffer_.length()); + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::fraction; + break; + case ',': + end_integer_value(); + begin_member_or_element(); + break; + case 'e':case 'E': + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::exp1; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::fraction: + { + switch (*p_) + { + case '\r': + end_fraction_value(); + stack_.push_back(states::cr); + break; + case '\n': + end_fraction_value(); + stack_.push_back(states::lf); + break; + case ' ':case '\t': + end_fraction_value(); + do_space(); + break; + case '/': + end_fraction_value(); + stack_.push_back(states::slash); + break; + case '}': + end_fraction_value(); + do_end_object(); + break; + case ']': + end_fraction_value(); + do_end_array(); + break; + case '0': + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + ++precision_; + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::fraction; + break; + case ',': + end_fraction_value(); + begin_member_or_element(); + break; + case 'e':case 'E': + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::exp1; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::exp1: + { + switch (*p_) + { + case '+': + stack_.back() = states::exp2; + break; + case '-': + number_buffer_.push_back(static_cast(*p_)); + stack_.back() = states::exp2; + break; + 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(*p_)); + stack_.back() = states::exp3; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::exp2: + { + switch (*p_) + { + 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(*p_)); + stack_.back() = states::exp3; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::exp3: + { + switch (*p_) + { + case '\r': + end_fraction_value(); + stack_.push_back(states::cr); + break; + case '\n': + end_fraction_value(); + stack_.push_back(states::lf); + break; + case ' ':case '\t': + end_fraction_value(); + do_space(); + break; + case '/': + end_fraction_value(); + stack_.push_back(states::slash); + break; + case '}': + end_fraction_value(); + do_end_object(); + break; + case ']': + end_fraction_value(); + do_end_array(); + break; + case ',': + end_fraction_value(); + begin_member_or_element(); + break; + 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(*p_)); + stack_.back() = states::exp3; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::t: + while (p_ < end_input_ && literal_index_ < literal_.second) + { + if (*p_ != literal_.first[literal_index_]) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_value, json_error_category()), *this); + } + ++p_; + ++literal_index_; + ++column_; + } + if (literal_index_ == literal_.second) + { + handler_->value(true, *this); + JSONCONS_ASSERT(stack_.size() >= 2); + if (parent() == states::root) + { + stack_.back() = states::done; + handler_->end_json(); + } + else + { + stack_.back() = states::expect_comma_or_end; + } + } + break; + case states::f: + while (p_ < end_input_ && literal_index_ < literal_.second) + { + if (*p_ != literal_.first[literal_index_]) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_value, json_error_category()), *this); + } + ++p_; + ++literal_index_; + ++column_; + } + if (literal_index_ == literal_.second) + { + handler_->value(false, *this); + JSONCONS_ASSERT(stack_.size() >= 2); + if (parent() == states::root) + { + stack_.back() = states::done; + handler_->end_json(); + } + else + { + stack_.back() = states::expect_comma_or_end; + } + } + break; + case states::n: + while (p_ < end_input_ && literal_index_ < literal_.second) + { + if (*p_ != literal_.first[literal_index_]) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_value, json_error_category()), *this); + } + ++p_; + ++literal_index_; + ++column_; + } + if (literal_index_ == literal_.second) + { + handler_->value(null_type(), *this); + JSONCONS_ASSERT(stack_.size() >= 2); + if (parent() == states::root) + { + stack_.back() = states::done; + handler_->end_json(); + } + else + { + stack_.back() = states::expect_comma_or_end; + } + } + break; + case states::slash: + { + switch (*p_) + { + case '*': + stack_.back() = states::slash_star; + break; + case '/': + stack_.back() = states::slash_slash; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::slash_star: + { + switch (*p_) + { + case '\r': + stack_.push_back(states::cr); + break; + case '\n': + stack_.push_back(states::lf); + break; + case '*': + stack_.back() = states::slash_star_star; + break; + } + } + ++p_; + ++column_; + break; + case states::slash_slash: + { + switch (*p_) + { + case '\r': + stack_.pop_back(); + break; + case '\n': + stack_.pop_back(); + break; + default: + ++p_; + ++column_; + } + } + break; + case states::slash_star_star: + { + switch (*p_) + { + case '/': + JSONCONS_ASSERT(!stack_.empty()) + stack_.pop_back(); + break; + default: + stack_.back() = states::slash_star; + break; + } + } + ++p_; + ++column_; + break; + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad parser state"); + break; + } + } + index_ += (p_-begin_input_); + } + + void end_parse() + { + JSONCONS_ASSERT(stack_.size() >= 2); + if (parent() == states::root) + { + switch (stack_.back()) + { + case states::zero: + case states::integer: + end_integer_value(); + break; + case states::fraction: + case states::exp3: + end_fraction_value(); + break; + default: + break; + } + } + if (stack_.back() == states::lf || stack_.back() == states::cr) + { + stack_.pop_back(); + } + if (!(stack_.back() == states::done || stack_.back() == states::start)) + { + err_handler_->error(std::error_code(json_parser_errc::unexpected_eof, json_error_category()), *this); + } + } + + states state() const + { + return stack_.back(); + } + + size_t index() const + { + return index_; + } +private: + void end_fraction_value() + { + try + { + double d = float_reader_.read(number_buffer_.data(), precision_); + if (is_negative_) + d = -d; + handler_->value(d, static_cast(precision_), *this); + } + catch (...) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + handler_->value(null_type(), *this); // recovery + } + number_buffer_.clear(); + is_negative_ = false; + + JSONCONS_ASSERT(stack_.size() >= 2); + switch (parent()) + { + case states::array: + case states::object: + stack_.back() = states::expect_comma_or_end; + break; + case states::root: + stack_.back() = states::done; + handler_->end_json(); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + } + + void end_integer_value() + { + if (is_negative_) + { + try + { + int64_t d = string_to_integer(is_negative_, number_buffer_.data(), number_buffer_.length()); + handler_->value(d, *this); + } + catch (const std::exception&) + { + try + { + double d = float_reader_.read(number_buffer_.data(), number_buffer_.length()); + handler_->value(-d, static_cast(number_buffer_.length()), *this); + } + catch (...) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + handler_->value(null_type(), *this); + } + } + } + else + { + try + { + uint64_t d = string_to_uinteger(number_buffer_.data(), number_buffer_.length()); + handler_->value(d, *this); + } + catch (const std::exception&) + { + try + { + double d = float_reader_.read(number_buffer_.data(),number_buffer_.length()); + handler_->value(d, static_cast(number_buffer_.length()), *this); + } + catch (...) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + handler_->value(null_type(), *this); + } + } + } + + JSONCONS_ASSERT(stack_.size() >= 2); + switch (parent()) + { + case states::array: + case states::object: + stack_.back() = states::expect_comma_or_end; + break; + case states::root: + stack_.back() = states::done; + handler_->end_json(); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + number_buffer_.clear(); + is_negative_ = false; + } + + void append_codepoint(int c) + { + 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); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + + void append_second_codepoint(int c) + { + 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); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + + void escape_next_char(int next_input) + { + switch (next_input) + { + case '\"': + string_buffer_.push_back('\"'); + stack_.back() = states::string; + break; + case '\\': + string_buffer_.push_back('\\'); + stack_.back() = states::string; + break; + case '/': + string_buffer_.push_back('/'); + stack_.back() = states::string; + break; + case 'b': + string_buffer_.push_back('\b'); + stack_.back() = states::string; + break; + case 'f': + string_buffer_.push_back('\f'); + stack_.back() = states::string; + break; + case 'n': + string_buffer_.push_back('\n'); + stack_.back() = states::string; + break; + case 'r': + string_buffer_.push_back('\r'); + stack_.back() = states::string; + break; + case 't': + string_buffer_.push_back('\t'); + stack_.back() = states::string; + break; + case 'u': + cp_ = 0; + stack_.back() = states::u1; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::illegal_escaped_character, json_error_category()), *this); + break; + } + } + + void end_string_value(const CharT* s, size_t length) + { + JSONCONS_ASSERT(stack_.size() >= 2); + switch (parent()) + { + case states::member_name: + handler_->name(s, length, *this); + stack_.pop_back(); + stack_.back() = states::expect_colon; + break; + case states::object: + case states::array: + handler_->value(s, length, *this); + stack_.back() = states::expect_comma_or_end; + break; + case states::root: + handler_->value(s, length, *this); + stack_.back() = states::done; + handler_->end_json(); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + } + + void begin_member_or_element() + { + JSONCONS_ASSERT(stack_.size() >= 2); + switch (parent()) + { + case states::object: + stack_.back() = states::expect_member_name; + break; + case states::array: + stack_.back() = states::expect_value; + break; + case states::root: + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + } + + uint32_t append_to_codepoint(uint32_t cp, int c) + { + 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 + { + err_handler_->error(std::error_code(json_parser_errc::invalid_hex_escape_sequence, json_error_category()), *this); + } + return cp; + } + + size_t do_line_number() const override + { + return line_; + } + + size_t do_column_number() const override + { + return column_; + } + + CharT do_current_char() const override + { + return p_ < end_input_? *p_ : 0; + } +}; + +typedef basic_json_parser json_parser; +typedef basic_json_parser wjson_parser; + +} + +#endif + diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp.orig b/vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp.orig new file mode 100644 index 00000000..e4769d5c --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp.orig @@ -0,0 +1,2157 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/json_input_handler.hpp" +#include "jsoncons/parse_error_handler.hpp" +#include "jsoncons/json_error_category.hpp" + +namespace jsoncons { + +enum class modes +{ + done, + start, + array_element, + object_member_name, + object_member_value +}; + +enum class states +{ + start, + slash, + slash_slash, + slash_star, + slash_star_star, + expect_comma_or_end, + object, + expect_member_name, + expect_colon, + expect_value, + array, + string, + escape, + u1, + u2, + u3, + u4, + expect_surrogate_pair1, + expect_surrogate_pair2, + u6, + u7, + u8, + u9, + minus, + zero, + integer, + fraction, + exp1, + exp2, + exp3, + n, + t, + f, + cr, + lf, + done, + scalar +}; + +template +class basic_json_parser : private basic_parsing_context +{ + static const int default_depth = 100; + + std::vector state_stack_; + int top_; + std::vector stack_; + basic_json_input_handler *handler_; + basic_parse_error_handler *err_handler_; + size_t column_; + size_t line_; + uint32_t cp_; + uint32_t cp2_; + std::basic_string string_buffer_; + std::basic_string number_buffer_; + bool is_negative_; + states saved_state_; + states pre_line_break_state_; + size_t index_; + int depth_; + int max_depth_; + float_reader float_reader_; + const CharT* begin_input_; + const CharT* end_input_; + const CharT* p_; + uint8_t precision_; + std::pair literal_; + size_t literal_index_; + + std::vector stack2_; + +public: + basic_json_parser(basic_json_input_handler& handler) + : top_(-1), + stack_(default_depth), + handler_(std::addressof(handler)), + err_handler_(std::addressof(basic_default_parse_error_handler::instance())), + column_(0), + line_(0), + cp_(0), + is_negative_(false), + index_(0), + depth_(default_depth) + { + max_depth_ = std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + + basic_json_parser(basic_json_input_handler& handler, + basic_parse_error_handler& err_handler) + : top_(-1), + stack_(default_depth), + handler_(std::addressof(handler)), + err_handler_(std::addressof(err_handler)), + column_(0), + line_(0), + cp_(0), + is_negative_(false), + index_(0), + depth_(default_depth) + + { + max_depth_ = std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + + const basic_parsing_context& parsing_context() const + { + return *this; + } + + ~basic_json_parser() + { + } + + size_t max_nesting_depth() const + { + return static_cast(max_depth_); + } + + void max_nesting_depth(size_t max_nesting_depth) + { + max_depth_ = static_cast(std::min(max_nesting_depth,static_cast(std::numeric_limits::max JSONCONS_NO_MACRO_EXP()))); + if (depth_ > max_depth_) + { + depth_ = max_depth_; + stack_.resize(depth_); + } + } + + bool done() const + { + return state_stack_.back() == states::done; + } + + void begin_parse() + { + if (!push(modes::done)) + { + err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this); + } + state_stack_.clear(); + state_stack_.push_back(states::start); + line_ = 1; + column_ = 1; + stack2_.push_back(states::start); + stack2_.push_back(states::scalar); + } + + void check_done(const CharT* input, size_t start, size_t length) + { + index_ = start; + for (; index_ < length; ++index_) + { + CharT curr_char_ = input[index_]; + switch (curr_char_) + { + case '\n': + case '\r': + case '\t': + case ' ': + break; + default: + err_handler_->error(std::error_code(json_parser_errc::extra_character, json_error_category()), *this); + break; + } + } + } + + bool parse_string(const CharT** first, const CharT** last) + { + const CharT* sb = p_; + bool done = false; + bool complete = false; + while (!done && p_ < end_input_) + { + switch (*p_) + { + 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: + string_buffer_.append(sb,p_-sb); + column_ += (p_ - sb + 1); + err_handler_->error(std::error_code(json_parser_errc::illegal_control_character, json_error_category()), *this); + // recovery - skip + done = true; + ++p_; + break; + case '\r': + { + column_ += (p_ - sb + 1); + err_handler_->error(std::error_code(json_parser_errc::illegal_character_in_string, json_error_category()), *this); + // recovery - keep + string_buffer_.append(sb, p_ - sb + 1); +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + done = true; + ++p_; + + stack2_.push_back(states::cr); + } + break; + case '\n': + { + column_ += (p_ - sb + 1); + err_handler_->error(std::error_code(json_parser_errc::illegal_character_in_string, json_error_category()), *this); + // recovery - keep + string_buffer_.append(sb, p_ - sb + 1); + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; + done = true; + ++p_; + + stack2_.push_back(states::lf); + } + break; + case '\t': + { + column_ += (p_ - sb + 1); + err_handler_->error(std::error_code(json_parser_errc::illegal_character_in_string, json_error_category()), *this); + // recovery - keep + string_buffer_.append(sb, p_ - sb + 1); + done = true; + ++p_; + } + break; + case '\\': + string_buffer_.append(sb,p_-sb); + column_ += (p_ - sb + 1); +<<<<<<< HEAD + state_stack_.back() = states::escape; +======= + state_ = states::escape; + stack2_.front() = states::escape; +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + done = true; + ++p_; + break; + case '\"': + if (string_buffer_.length() == 0) + { + *first = sb; + *last = p_; + //end_string_value(sb,p_-sb); + } + else + { + string_buffer_.append(sb,p_-sb); + *first = string_buffer_.data(); + *last = string_buffer_.data() + string_buffer_.length(); + //end_string_value(string_buffer_.data(),string_buffer_.length()); + //string_buffer_.clear(); + } + column_ += (p_ - sb + 1); + done = true; + complete = true; + ++p_; + break; + default: + ++p_; + break; + } + } + if (!done) + { + string_buffer_.append(sb,p_-sb); + column_ += (p_ - sb + 1); + } + + return complete; + } + + void parse(const CharT* const input, size_t start, size_t length) + { + begin_input_ = input + start; + end_input_ = input + length; + p_ = begin_input_; + + index_ = start; + while ((p_ < end_input_) && (state_stack_.back() != states::done)) + { + switch (*p_) + { + 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: + err_handler_->error(std::error_code(json_parser_errc::illegal_control_character, json_error_category()), *this); + break; + default: + break; + } + + switch (state_stack_.back()) + { + case states::cr: + ++line_; + column_ = 1; + switch (*p_) + { + case '\n': + state_stack_.back() = pre_line_break_state_; + ++p_; + break; + default: + state_stack_.back() = pre_line_break_state_; + break; + } + JSONCONS_ASSERT(stack2_.size() > 0); + stack2_.pop_back(); + break; + case states::lf: + ++line_; + column_ = 1; +<<<<<<< HEAD + state_stack_.back() = pre_line_break_state_; +======= + state_ = pre_line_break_state_; + JSONCONS_ASSERT(stack2_.size() > 0); + stack2_.pop_back(); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case states::start: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + break; + case '{': + handler_->begin_json(); + if (!push(modes::object_member_name)) + { + err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this); + } +<<<<<<< HEAD + state_stack_.back() = states::object; +======= + state_ = states::object; + +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + handler_->begin_object(*this); + break; + case '[': + handler_->begin_json(); + if (!push(modes::array_element)) + { + err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this); + } + state_stack_.back() = states::array; + handler_->begin_array(*this); + break; + case '\"': + handler_->begin_json(); + flip(modes::done, modes::start); + state_stack_.back() = states::string; + break; + case '-': + handler_->begin_json(); + flip(modes::done, modes::start); + is_negative_ = true; + state_stack_.back() = states::minus; + break; + case '0': + handler_->begin_json(); + flip(modes::done, modes::start); + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::zero; + break; + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + handler_->begin_json(); + flip(modes::done, modes::start); + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::integer; + break; + case 'f': + handler_->begin_json(); + flip(modes::done, modes::start); + state_stack_.back() = states::f; + literal_ = json_literals::false_literal(); + literal_index_ = 1; + break; + case 'n': + handler_->begin_json(); + flip(modes::done, modes::start); + state_stack_.back() = states::n; + literal_ = json_literals::null_literal(); + literal_index_ = 1; + break; + case 't': + handler_->begin_json(); + flip(modes::done, modes::start); + state_stack_.back() = states::t; + literal_ = json_literals::true_literal(); + literal_index_ = 1; + break; + case '/': + saved_state_ = state_stack_.back(); + state_stack_.back() = states::slash; + break; + case '}': + err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_brace, json_error_category()), *this); + break; + case ']': + err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_bracket, json_error_category()), *this); + break; + default: + err_handler_->fatal_error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + + case states::expect_comma_or_end: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + break; + case '}': + if (peek() == modes::object_member_value) + { + pop(modes::object_member_value); + handler_->end_object(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + } + else if (peek() == modes::array_element) + { + err_handler_->fatal_error(std::error_code(json_parser_errc::expected_comma_or_right_bracket, json_error_category()), *this); + } + else + { + err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_brace, json_error_category()), *this); + } + break; + case ']': + if (peek() == modes::array_element) + { + pop(modes::array_element); + handler_->end_array(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + } + else if (peek() == modes::object_member_value) + { + err_handler_->fatal_error(std::error_code(json_parser_errc::expected_comma_or_right_brace, json_error_category()), *this); + } + else + { + err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_bracket, json_error_category()), *this); + } + break; + case ',': + begin_member_or_element(); + break; + case '/': + saved_state_ = state_stack_.back(); + state_stack_.back() = states::slash; + break; + default: + if (peek() == modes::array_element) + { + err_handler_->error(std::error_code(json_parser_errc::expected_comma_or_right_bracket, json_error_category()), *this); + } + else if (peek() == modes::object_member_value) + { + err_handler_->error(std::error_code(json_parser_errc::expected_comma_or_right_brace, json_error_category()), *this); + } + break; + } + } + ++p_; + ++column_; + break; + case states::object: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + break; + case '}': + if (!pop(modes::object_member_name)) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + } + handler_->end_object(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + break; + case '\"': + state_stack_.back() = states::string; + break; + case '/': + saved_state_ = state_stack_.back(); + state_stack_.back() = states::slash; + break; + case '\'': + err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_name, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::expect_member_name: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + break; + case '\"': + state_stack_.back() = states::string; + break; + case '/': + saved_state_ = state_stack_.back(); + state_stack_.back() = states::slash; + break; + case '}': + err_handler_->error(std::error_code(json_parser_errc::extra_comma, json_error_category()), *this); + break; + case '\'': + err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_name, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::expect_colon: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + break; + case ':': + begin_member_value(); + state_stack_.back() = states::expect_value; + break; + case '/': + saved_state_ = state_stack_.back(); + state_stack_.back() = states::slash; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_colon, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::expect_value: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + break; + case '{': + if (!push(modes::object_member_name)) + { + err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this); + } + state_stack_.back() = states::object; + handler_->begin_object(*this); + break; + case '[': + if (!push(modes::array_element)) + { + err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this); + } + state_stack_.back() = states::array; + handler_->begin_array(*this); + break; + case '/': + saved_state_ = state_stack_.back(); + state_stack_.back() = states::slash; + break; + + case '\"': + state_stack_.back() = states::string; + break; + case '-': + is_negative_ = true; + state_stack_.back() = states::minus; + break; + case '0': + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::zero; + break; + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::integer; + break; + case 'f': + state_stack_.back() = states::f; + literal_ = json_literals::false_literal(); + literal_index_ = 1; + /*if ((p_+4) < end_input_) + { + if ((*(p_+1) == 'a') & (*(p_+2) == 'l') & (*(p_+3) == 's') & (*(p_+4) == 'e')) + { + p_ += 4; + column_ += 4; + handler_->value(false, *this); + if (peek() == modes::start) + { + flip(modes::start,modes::done); + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + } + }*/ + break; + case 'n': + state_stack_.back() = states::n; + literal_ = json_literals::null_literal(); + literal_index_ = 1; + break; + case 't': + state_stack_.back() = states::t; + literal_ = json_literals::true_literal(); + literal_index_ = 1; + break; + case ']': + if (peek() == modes::array_element) + { + err_handler_->error(std::error_code(json_parser_errc::extra_comma, json_error_category()), *this); + } + else + { + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + } + break; + case '\'': + err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::array: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + break; + case '{': + if (!push(modes::object_member_name)) + { + err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this); + } + state_stack_.back() = states::object; + handler_->begin_object(*this); + break; + case '[': + if (!push(modes::array_element)) + { + err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this); + } + state_stack_.back() = states::array; + handler_->begin_array(*this); + break; + case ']': + if (!pop(modes::array_element)) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + } + handler_->end_array(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + break; + case '\"': + state_stack_.back() = states::string; + break; + case '/': + saved_state_ = state_stack_.back(); + state_stack_.back() = states::slash; + break; + case '-': + is_negative_ = true; + state_stack_.back() = states::minus; + break; + case '0': + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::zero; + break; + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::integer; + break; + case 'f': + state_stack_.back() = states::f; + literal_ = json_literals::false_literal(); + literal_index_ = 1; + /*if ((p_+4) < end_input_) + { + if ((*(p_+1) == 'a') & (*(p_+2) == 'l') & (*(p_+3) == 's') & (*(p_+4) == 'e')) + { + p_ += 4; + column_ += 4; + handler_->value(false, *this); + if (peek() == modes::start) + { + flip(modes::start,modes::done); + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + } + }*/ + break; + case 'n': + state_stack_.back() = states::n; + literal_ = json_literals::null_literal(); + literal_index_ = 1; + break; + case 't': + state_stack_.back() = states::t; + literal_ = json_literals::true_literal(); + literal_index_ = 1; + break; + case '\'': + err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::string: + { + const CharT* first; + const CharT* last; + if (parse_string(&first,&last)) + { + end_string_value(first,last-first); + string_buffer_.clear(); + } + } + break; + case states::escape: + { + escape_next_char(*p_); + } + ++p_; + ++column_; + break; + case states::u1: + { + append_codepoint(*p_); + state_stack_.back() = states::u2; + } + ++p_; + ++column_; + break; + case states::u2: + { + append_codepoint(*p_); + state_stack_.back() = states::u3; + } + ++p_; + ++column_; + break; + case states::u3: + { + append_codepoint(*p_); + state_stack_.back() = states::u4; + } + ++p_; + ++column_; + break; + case states::u4: + { + append_codepoint(*p_); + if (cp_ >= min_lead_surrogate && cp_ <= max_lead_surrogate) + { + state_stack_.back() = states::expect_surrogate_pair1; + } + else + { + json_char_traits::append_codepoint_to_string(cp_, string_buffer_); + state_stack_.back() = states::string; + } + } + ++p_; + ++column_; + break; + case states::expect_surrogate_pair1: + { + switch (*p_) + { + case '\\': + cp2_ = 0; + state_stack_.back() = states::expect_surrogate_pair2; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_codepoint_surrogate_pair, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::expect_surrogate_pair2: + { + switch (*p_) + { + case 'u': + state_stack_.back() = states::u6; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_codepoint_surrogate_pair, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::u6: + { + append_second_codepoint(*p_); + state_stack_.back() = states::u7; + } + ++p_; + ++column_; + break; + case states::u7: + { + append_second_codepoint(*p_); + state_stack_.back() = states::u8; + } + ++p_; + ++column_; + break; + case states::u8: + { + append_second_codepoint(*p_); + state_stack_.back() = states::u9; + } + ++p_; + ++column_; + break; + case states::u9: + { + append_second_codepoint(*p_); + uint32_t cp = 0x10000 + ((cp_ & 0x3FF) << 10) + (cp2_ & 0x3FF); + json_char_traits::append_codepoint_to_string(cp, string_buffer_); + state_stack_.back() = states::string; + } + ++p_; + ++column_; + break; + case states::minus: + { + switch (*p_) + { + case '0': + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::zero; + break; + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::integer; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::zero: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + end_integer_value(); + break; // No change + case '}': + end_integer_value(); + if (!pop(modes::object_member_value)) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + } + handler_->end_object(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + break; + case ']': + end_integer_value(); + if (!pop(modes::array_element)) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + } + handler_->end_array(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + break; + case '.': + precision_ = static_cast(number_buffer_.length()); + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::fraction; + break; + case ',': + end_integer_value(); + begin_member_or_element(); + break; + case '0': case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + err_handler_->error(std::error_code(json_parser_errc::leading_zero, json_error_category()), *this); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::integer: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + end_integer_value(); + break; + case '}': + end_integer_value(); + if (!pop(modes::object_member_value)) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + } + handler_->end_object(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + break; + case ']': + end_integer_value(); + if (!pop(modes::array_element)) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + } + handler_->end_array(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + break; + 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(*p_)); + state_stack_.back() = states::integer; + break; + case '.': + precision_ = static_cast(number_buffer_.length()); + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::fraction; + break; + case ',': + end_integer_value(); + begin_member_or_element(); + break; + case 'e':case 'E': + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::exp1; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::fraction: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + end_fraction_value(); + break; + case '}': + end_fraction_value(); + if (!pop(modes::object_member_value)) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + } + handler_->end_object(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + break; + case ']': + end_fraction_value(); + if (!pop(modes::array_element)) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + } + handler_->end_array(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + break; + case '0': + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9': + ++precision_; + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::fraction; + break; + case ',': + end_fraction_value(); + begin_member_or_element(); + break; + case 'e':case 'E': + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::exp1; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::exp1: + { + switch (*p_) + { + case '+': + state_stack_.back() = states::exp2; + break; + case '-': + number_buffer_.push_back(static_cast(*p_)); + state_stack_.back() = states::exp2; + break; + 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(*p_)); + state_stack_.back() = states::exp3; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::exp2: + { + switch (*p_) + { + 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(*p_)); + state_stack_.back() = states::exp3; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::exp3: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case ' ':case '\t': + { + bool done = false; + while (!done && (p_ + 1) < end_input_) + { + switch (*(p_ + 1)) + { + case ' ':case '\t': + ++p_; + ++column_; + break; + default: + done = true; + break; + } + } + } + end_fraction_value(); + break; + case '}': + end_fraction_value(); + if (!pop(modes::object_member_value)) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + } + handler_->end_object(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + break; + case ']': + end_fraction_value(); + if (!pop(modes::array_element)) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + } + handler_->end_array(*this); + if (peek() == modes::done) + { + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + break; + case ',': + end_fraction_value(); + begin_member_or_element(); + break; + 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(*p_)); + state_stack_.back() = states::exp3; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::t: + while (p_ < end_input_ && literal_index_ < literal_.second) + { + if (*p_ != literal_.first[literal_index_]) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_value, json_error_category()), *this); + } + ++p_; + ++literal_index_; + ++column_; + } + if (literal_index_ == literal_.second) + { + handler_->value(true, *this); + if (peek() == modes::start) + { + flip(modes::start,modes::done); + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + } + break; + case states::f: + while (p_ < end_input_ && literal_index_ < literal_.second) + { + if (*p_ != literal_.first[literal_index_]) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_value, json_error_category()), *this); + } + ++p_; + ++literal_index_; + ++column_; + } + if (literal_index_ == literal_.second) + { + handler_->value(false, *this); + if (peek() == modes::start) + { + flip(modes::start,modes::done); + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + } + break; + case states::n: + while (p_ < end_input_ && literal_index_ < literal_.second) + { + if (*p_ != literal_.first[literal_index_]) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_value, json_error_category()), *this); + } + ++p_; + ++literal_index_; + ++column_; + } + if (literal_index_ == literal_.second) + { + handler_->value(null_type(), *this); + if (peek() == modes::start) + { + flip(modes::start,modes::done); + state_stack_.back() = states::done; + handler_->end_json(); + } + else + { + state_stack_.back() = states::expect_comma_or_end; + } + } + break; + case states::slash: + { + switch (*p_) + { + case '*': + state_stack_.back() = states::slash_star; + break; + case '/': + state_stack_.back() = states::slash_slash; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + } + ++p_; + ++column_; + break; + case states::slash_star: + { + switch (*p_) + { + case '\r': +<<<<<<< HEAD + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = state_stack_.back(); + state_stack_.back() = states::lf; +======= + pre_line_break_state_ = state_; + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + case '*': + state_stack_.back() = states::slash_star_star; + break; + } + } + ++p_; + ++column_; + break; + case states::slash_slash: + { + switch (*p_) + { + case '\r': + pre_line_break_state_ = saved_state_; +<<<<<<< HEAD + state_stack_.back() = states::cr; + break; + case '\n': + pre_line_break_state_ = saved_state_; + state_stack_.back() = states::lf; +======= + state_ = states::cr; + stack2_.push_back(states::cr); + break; + case '\n': + pre_line_break_state_ = saved_state_; + state_ = states::lf; + stack2_.push_back(states::lf); +>>>>>>> 8522df40eb2e2c14a4b40274eedf44dd9d631bb8 + break; + } + } + ++p_; + ++column_; + break; + case states::slash_star_star: + { + switch (*p_) + { + case '/': + state_stack_.back() = saved_state_; + break; + default: + state_stack_.back() = states::slash_star; + break; + } + } + ++p_; + ++column_; + break; + default: + JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad parser state"); + break; + } + } + index_ += (p_-begin_input_); + } + + void end_parse() + { + if (peek() == modes::start) + { + switch (state_stack_.back()) + { + case states::zero: + case states::integer: + end_integer_value(); + break; + case states::fraction: + case states::exp3: + end_fraction_value(); + break; + default: + break; + } + } + if (!pop(modes::done)) + { + err_handler_->error(std::error_code(json_parser_errc::unexpected_eof, json_error_category()), *this); + } + } + + states state() const + { + return state_stack_.back(); + } + + size_t index() const + { + return index_; + } +private: + void end_fraction_value() + { + try + { + double d = float_reader_.read(number_buffer_.data(), precision_); + if (is_negative_) + d = -d; + handler_->value(d, static_cast(precision_), *this); + } + catch (...) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + handler_->value(null_type(), *this); // recovery + } + number_buffer_.clear(); + is_negative_ = false; + switch (stack_[top_]) + { + case modes::array_element: + case modes::object_member_value: + state_stack_.back() = states::expect_comma_or_end; + break; + case modes::start: + flip(modes::start,modes::done); + state_stack_.back() = states::done; + handler_->end_json(); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + } + + void end_integer_value() + { + if (is_negative_) + { + try + { + int64_t d = string_to_integer(is_negative_, number_buffer_.data(), number_buffer_.length()); + handler_->value(d, *this); + } + catch (const std::exception&) + { + try + { + double d = float_reader_.read(number_buffer_.data(), number_buffer_.length()); + handler_->value(-d, static_cast(number_buffer_.length()), *this); + } + catch (...) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + handler_->value(null_type(), *this); + } + } + } + else + { + try + { + uint64_t d = string_to_uinteger(number_buffer_.data(), number_buffer_.length()); + handler_->value(d, *this); + } + catch (const std::exception&) + { + try + { + double d = float_reader_.read(number_buffer_.data(),number_buffer_.length()); + handler_->value(d, static_cast(number_buffer_.length()), *this); + } + catch (...) + { + err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this); + handler_->value(null_type(), *this); + } + } + } + + switch (stack_[top_]) + { + case modes::array_element: + case modes::object_member_value: + state_stack_.back() = states::expect_comma_or_end; + break; + case modes::start: + flip(modes::start,modes::done); + state_stack_.back() = states::done; + handler_->end_json(); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + number_buffer_.clear(); + is_negative_ = false; + } + + void append_codepoint(int c) + { + 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); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + + void append_second_codepoint(int c) + { + 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); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this); + break; + } + } + + void escape_next_char(int next_input) + { + switch (next_input) + { + case '\"': + string_buffer_.push_back('\"'); + state_stack_.back() = states::string; + break; + case '\\': + string_buffer_.push_back('\\'); + state_stack_.back() = states::string; + break; + case '/': + string_buffer_.push_back('/'); + state_stack_.back() = states::string; + break; + case 'b': + string_buffer_.push_back('\b'); + state_stack_.back() = states::string; + break; + case 'f': + string_buffer_.push_back('\f'); + state_stack_.back() = states::string; + break; + case 'n': + string_buffer_.push_back('\n'); + state_stack_.back() = states::string; + break; + case 'r': + string_buffer_.push_back('\r'); + state_stack_.back() = states::string; + break; + case 't': + string_buffer_.push_back('\t'); + state_stack_.back() = states::string; + break; + case 'u': + cp_ = 0; + state_stack_.back() = states::u1; + break; + default: + err_handler_->error(std::error_code(json_parser_errc::illegal_escaped_character, json_error_category()), *this); + break; + } + } + + void end_string_value(const CharT* s, size_t length) + { + switch (stack_[top_]) + { + case modes::object_member_name: + handler_->name(s, length, *this); + state_stack_.back() = states::expect_colon; + break; + case modes::array_element: + case modes::object_member_value: + handler_->value(s, length, *this); + state_stack_.back() = states::expect_comma_or_end; + break; + case modes::start: + handler_->value(s, length, *this); + flip(modes::start,modes::done); + state_stack_.back() = states::done; + handler_->end_json(); + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + } + + void begin_member_or_element() + { + switch (stack_[top_]) + { + case modes::object_member_value: + // A comma causes a flip from object_member_value modes to object_member_name modes. + flip(modes::object_member_value, modes::object_member_name); + state_stack_.back() = states::expect_member_name; + break; + case modes::array_element: + state_stack_.back() = states::expect_value; + break; + case modes::done: + break; + default: + err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this); + break; + } + } + + void begin_member_value() + { + flip(modes::object_member_name, modes::object_member_value); + state_stack_.back() = states::expect_value; + } + + uint32_t append_to_codepoint(uint32_t cp, int c) + { + 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 + { + err_handler_->error(std::error_code(json_parser_errc::invalid_hex_escape_sequence, json_error_category()), *this); + } + return cp; + } + + size_t do_line_number() const override + { + return line_; + } + + size_t do_column_number() const override + { + return column_; + } + + CharT do_current_char() const override + { + return p_ < end_input_? *p_ : 0; + } + + bool push(modes mode) + { + ++top_; + if (top_ >= depth_) + { + if (top_ >= max_depth_) + { + return false; + } + depth_ *= 2; + stack_.resize(depth_); + } + stack_[top_] = mode; + return true; + } + + modes peek() + { + return stack_[top_]; + } + + bool peek(modes mode) + { + return stack_[top_] == mode; + } + + void flip(modes mode1, modes mode2) + { + JSONCONS_ASSERT((top_ >= 0) && (stack_[top_] == mode1)) + stack_[top_] = mode2; + } + + bool pop(modes mode) + { + if (top_ < 0 || stack_[top_] != mode) + { + return false; + } + --top_; + return true; + } +}; + +typedef basic_json_parser json_parser; +typedef basic_json_parser wjson_parser; + +} + +#endif + diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_reader.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_reader.hpp new file mode 100644 index 00000000..a0dd4641 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_reader.hpp @@ -0,0 +1,176 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/json_input_handler.hpp" +#include "jsoncons/parse_error_handler.hpp" +#include "jsoncons/json_parser.hpp" + +namespace jsoncons { + +template +class basic_json_reader +{ + static const size_t default_max_buffer_length = 16384; + + basic_json_parser parser_; + std::basic_istream *is_; + basic_parse_error_handler *err_handler_; + bool eof_; + std::vector buffer_; + size_t buffer_length_; + size_t buffer_capacity_; + size_t index_; +public: + basic_json_reader(std::basic_istream& is, + basic_json_input_handler& handler) + : parser_(handler), + is_(std::addressof(is)), + err_handler_(std::addressof(basic_default_parse_error_handler::instance())), + eof_(false), + buffer_length_(0), + buffer_capacity_(default_max_buffer_length), + index_(0) + { + buffer_.resize(buffer_capacity_); + } + + basic_json_reader(std::basic_istream& is, + basic_json_input_handler& handler, + basic_parse_error_handler& err_handler) + : parser_(handler,err_handler), + is_(std::addressof(is)), + err_handler_(std::addressof(err_handler)), + eof_(false), + buffer_length_(0), + buffer_capacity_(default_max_buffer_length), + index_(0) + { + buffer_.resize(buffer_capacity_); + } + + size_t buffer_capacity() const + { + return buffer_capacity_; + } + + void buffer_capacity(size_t capacity) + { + buffer_capacity_ = capacity; + buffer_.resize(buffer_capacity_); + } + + 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() + { + parser_.begin_parse(); + while (!eof_ && !parser_.done()) + { + if (!(index_ < buffer_length_)) + { + if (!is_->eof()) + { + is_->read(buffer_.data(), buffer_capacity_); + buffer_length_ = static_cast(is_->gcount()); + if (buffer_length_ == 0) + { + eof_ = true; + } + index_ = 0; + } + else + { + eof_ = true; + } + } + if (!eof_) + { + parser_.parse(buffer_.data(),index_,buffer_length_); + index_ = parser_.index(); + } + } + parser_.end_parse(); + } + + void check_done() + { + while (!eof_) + { + if (!(index_ < buffer_length_)) + { + if (!is_->eof()) + { + is_->read(buffer_.data(), buffer_capacity_); + buffer_length_ = static_cast(is_->gcount()); + if (buffer_length_ == 0) + { + eof_ = true; + } + index_ = 0; + } + else + { + eof_ = true; + } + } + if (!eof_) + { + parser_.check_done(buffer_.data(),index_,buffer_length_); + index_ = parser_.index(); + } + } + } + + bool eof() const + { + return eof_; + } + +#if !defined(JSONCONS_NO_DEPRECATED) + void read() + { + read_next(); + } + + size_t max_depth() const + { + return parser_.max_nesting_depth(); + } + + void max_depth(size_t depth) + { + parser_.max_nesting_depth(depth); + } +#endif +}; + +typedef basic_json_reader json_reader; +typedef basic_json_reader wjson_reader; + +} + +#endif + diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_serializer.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_serializer.hpp new file mode 100644 index 00000000..d9f3bf4f --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_serializer.hpp @@ -0,0 +1,435 @@ +// 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 +#include +#include +#include +#include +#include +#include // std::numeric_limits +#include +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/output_format.hpp" +#include "jsoncons/json_output_handler.hpp" + +namespace jsoncons { + +template +class basic_json_serializer : public basic_json_output_handler +{ + static const size_t default_buffer_length = 16384; + + struct stack_item + { + stack_item(bool is_object) + : is_object_(is_object), count_(0), option_(block_options::next_line), multiline_(false) + { + scalar_option_ = is_object ? block_options::next_line : block_options::same_line; + } + stack_item(bool is_object, block_options option) + : is_object_(is_object), count_(0), option_(option), multiline_(false) + { + scalar_option_ = is_object ? block_options::next_line : block_options::same_line; + } + bool is_multiline() const + { + return multiline_; + } + + bool is_object() const + { + return is_object_; + } + + bool is_same_line() const + { + return option_ = block_options::same_line; + } + + bool is_next_line() const + { + return option_ == block_options::next_line; + } + + bool scalar_next_line() const + { + return scalar_option_ == block_options::next_line; + } + + bool is_object_; + size_t count_; + block_options option_; + block_options scalar_option_; + bool multiline_; + }; + basic_output_format format_; + std::vector stack_; + int indent_; + std::streamsize original_precision_; + std::ios_base::fmtflags original_format_flags_; + bool indenting_; + float_printer fp_; + buffered_ostream bos_; +public: + basic_json_serializer(std::basic_ostream& os) + : indent_(0), + indenting_(false), + fp_(format_.precision()), + bos_(os) + { + } + + basic_json_serializer(std::basic_ostream& os, bool indenting) + : indent_(0), + indenting_(indenting), + fp_(format_.precision()), + bos_(os) + { + } + + basic_json_serializer(std::basic_ostream& os, const basic_output_format& format) + : format_(format), + indent_(0), + indenting_(false), + fp_(format_.precision()), + bos_(os) + { + } + basic_json_serializer(std::basic_ostream& os, const basic_output_format& format, bool indenting) + : format_(format), + indent_(0), + indenting_(indenting), + fp_(format_.precision()), + bos_(os) + { + } + + ~basic_json_serializer() + { + } + +private: + // Implementing methods + void do_begin_json() override + { + } + + void do_end_json() override + { + bos_.flush(); + } + + void do_begin_object() override + { + if (!stack_.empty() && !stack_.back().is_object()) + { + if (!stack_.empty()) + { + if (stack_.back().count_ > 0) + { + bos_. put(','); + } + } + } + + if (indenting_) + { + if (!stack_.empty() && stack_.back().is_object()) + { + if (format_.object_object_block_option() == block_options::next_line) + { + write_indent(); + } + stack_.push_back(stack_item(true,format_.object_object_block_option())); + } + else if (!stack_.empty()) + { + if (format_.array_object_block_option() == block_options::next_line) + { + write_indent(); + } + stack_.push_back(stack_item(true,format_.array_object_block_option())); + } + else + { + stack_.push_back(stack_item(true)); + } + indent(); + } + else + { + stack_.push_back(stack_item(true)); + } + bos_.put('{'); + } + + void do_end_object() override + { + JSONCONS_ASSERT(!stack_.empty()); + if (indenting_) + { + unindent(); + write_indent(); + } + stack_.pop_back(); + bos_.put('}'); + + end_value(); + } + + + void do_begin_array() override + { + if (!stack_.empty() && !stack_.back().is_object()) + { + if (!stack_.empty()) + { + if (stack_.back().count_ > 0) + { + bos_. put(','); + } + } + } + if (indenting_) + { + if (!stack_.empty() && stack_.back().is_object()) + { + if (format_.object_array_block_option() == block_options::next_line) + { + write_indent(); + } + stack_.push_back(stack_item(false,format_.object_array_block_option())); + } + else if (!stack_.empty()) + { + if (format_.array_array_block_option() == block_options::next_line) + { + write_indent(); + } + stack_.push_back(stack_item(false,format_.array_array_block_option())); + } + else + { + stack_.push_back(stack_item(false)); + } + indent(); + } + else + { + stack_.push_back(stack_item(false)); + } + bos_.put('['); + } + + void do_end_array() override + { + JSONCONS_ASSERT(!stack_.empty()); + if (indenting_) + { + unindent(); + if (stack_.back().is_multiline()) + { + write_indent(); + } + } + stack_.pop_back(); + bos_.put(']'); + end_value(); + } + + void do_name(const CharT* name, size_t length) override + { + if (!stack_.empty()) + { + if (stack_.back().count_ > 0) + { + bos_. put(','); + } + if (indenting_) + { + if (stack_.back().scalar_next_line()) + { + write_indent(); + } + } + } + + bos_.put('\"'); + escape_string(name, length, format_, bos_); + bos_.put('\"'); + bos_.put(':'); + bos_.put(' '); + } + + void do_null_value() override + { + if (!stack_.empty() && !stack_.back().is_object()) + { + begin_scalar_value(); + } + + auto buf = json_literals::null_literal(); + bos_.write(buf.first,buf.second); + + end_value(); + } + + void do_string_value(const CharT* value, size_t length) override + { + if (!stack_.empty() && !stack_.back().is_object()) + { + begin_scalar_value(); + } + + bos_. put('\"'); + escape_string(value, length, format_, bos_); + bos_. put('\"'); + + end_value(); + } + + void do_double_value(double value, uint8_t precision) override + { + if (!stack_.empty() && !stack_.back().is_object()) + { + begin_scalar_value(); + } + + if (is_nan(value) && format_.replace_nan()) + { + bos_.write(format_.nan_replacement()); + } + else if (is_pos_inf(value) && format_.replace_pos_inf()) + { + bos_.write(format_.pos_inf_replacement()); + } + else if (is_neg_inf(value) && format_.replace_neg_inf()) + { + bos_.write(format_.neg_inf_replacement()); + } + else + { + fp_.print(value,precision,bos_); + } + + end_value(); + } + + void do_integer_value(int64_t value) override + { + if (!stack_.empty() && !stack_.back().is_object()) + { + begin_scalar_value(); + } + print_integer(value,bos_); + end_value(); + } + + void do_uinteger_value(uint64_t value) override + { + if (!stack_.empty() && !stack_.back().is_object()) + { + begin_scalar_value(); + } + print_uinteger(value,bos_); + end_value(); + } + + void do_bool_value(bool value) override + { + if (!stack_.empty() && !stack_.back().is_object()) + { + begin_scalar_value(); + } + + if (value) + { + auto buf = json_literals::true_literal(); + bos_.write(buf.first,buf.second); + } + else + { + auto buf = json_literals::false_literal(); + bos_.write(buf.first,buf.second); + } + + end_value(); + } + + void begin_scalar_value() + { + if (!stack_.empty()) + { + if (stack_.back().count_ > 0) + { + bos_. put(','); + } + if (indenting_) + { + if (stack_.back().scalar_next_line()) + { + write_indent(); + } + } + } + } + + void begin_value() + { + if (!stack_.empty()) + { + if (stack_.back().count_ > 0) + { + bos_. put(','); + } + if (indenting_ && stack_.back().is_next_line()) + { + write_indent(); + } + } + } + + void end_value() + { + if (!stack_.empty()) + { + ++stack_.back().count_; + } + } + + void indent() + { + indent_ += static_cast(format_.indent()); + } + + void unindent() + { + indent_ -= static_cast(format_.indent()); + } + + void write_indent() + { + if (!stack_.empty()) + { + stack_.back().multiline_ = true; + } + bos_. put('\n'); + for (int i = 0; i < indent_; ++i) + { + bos_. put(' '); + } + } +}; + +typedef basic_json_serializer json_serializer; +typedef basic_json_serializer wjson_serializer; + +} +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_structures.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_structures.hpp new file mode 100644 index 00000000..ee8f75af --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_structures.hpp @@ -0,0 +1,860 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jsoncons/jsoncons.hpp" + +namespace jsoncons { + +template +class json_array +{ +public: + typedef Alloc allocator_type; + typedef JsonT value_type; + typedef typename std::allocator_traits:: template rebind_alloc vector_allocator_type; + typedef typename std::vector::reference reference; + typedef typename std::vector::const_reference const_reference; + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + + json_array() + : elements_() + { + } + + explicit json_array(const Alloc& allocator) + : elements_(allocator) + { + } + + explicit json_array(size_t n, const Alloc& allocator = Alloc()) + : elements_(n,JsonT(),allocator) + { + } + + explicit json_array(size_t n, const JsonT& value, const Alloc& allocator = Alloc()) + : elements_(n,value,allocator) + { + } + + template + json_array(InputIterator begin, InputIterator end, const Alloc& allocator = Alloc()) + : elements_(begin,end,allocator) + { + } + + json_array(const json_array& val) + : elements_(val.elements_) + { + } + + json_array(const json_array& val, const Alloc& allocator) + : elements_(val.elements_,allocator) + { + } + json_array(json_array&& val) + : elements_(std::move(val.elements_)) + { + } + json_array(json_array&& val, const Alloc& allocator) + : elements_(std::move(val.elements_),allocator) + { + } + + json_array(std::initializer_list init, + const Alloc& allocator = Alloc()) + : elements_(std::move(init),allocator) + { + } + + Alloc get_allocator() const + { + return elements_.get_allocator(); + } + + void swap(json_array& 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 JsonT& 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(iterator first, iterator last) + { + elements_.erase(first,last); + } + + JsonT& operator[](size_t i) {return elements_[i];} + + const JsonT& operator[](size_t i) const {return elements_[i];} + + void push_back(const JsonT& value) + { + elements_.push_back(value); + } + + void push_back(JsonT&& value) + { + elements_.push_back(std::move(value)); + } + + void add(size_t index, const JsonT& value) + { + auto position = index < elements_.size() ? elements_.begin() + index : elements_.end(); + elements_.insert(position, value); + } + + void add(size_t index, JsonT&& value) + { + auto it = index < elements_.size() ? elements_.begin() + index : elements_.end(); + elements_.insert(it, std::move(value)); + } + +#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 9 + // work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54577 + iterator add(const_iterator pos, const JsonT& value) + { + iterator it = elements_.begin() + (pos - elements_.begin()); + return elements_.insert(it, value); + } + + iterator add(const_iterator pos, JsonT&& value) + { + iterator it = elements_.begin() + (pos - elements_.begin()); + return elements_.insert(it, std::move(value)); + } +#else + iterator add(const_iterator pos, const JsonT& value) + { + return elements_.insert(pos, value); + } + + iterator add(const_iterator pos, JsonT&& value) + { + return elements_.insert(pos, std::move(value)); + } +#endif + + 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& 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: + json_array& operator=(const json_array&); + std::vector elements_; +}; + +template +class member_lt_string +{ + size_t length_; +public: + member_lt_string(size_t length) + : length_(length) + { + } + + bool operator()(const ValueT& a, const CharT* b) const + { + size_t len = std::min JSONCONS_NO_MACRO_EXP(a.name().length(),length_); + int result = std::char_traits::compare(a.name().data(),b,len); + if (result != 0) + { + return result < 0; + } + + return a.name().length() < length_; + } +}; + +template +bool name_le_string(const StringT& a, const CharT* b, size_t length) +{ + size_t min_len = std::min JSONCONS_NO_MACRO_EXP(a.length(),length); + int result = std::char_traits::compare(a.data(),b, min_len); + if (result != 0) + { + return result < 0; + } + + return a.length() <= length; +} + +template +bool name_eq_string(const StringT& a, const CharT* b, size_t length) +{ + return a.length() == length && std::char_traits::compare(a.data(),b,length) == 0; +} + +template +class member_lt_member +{ + typedef typename ValueT::char_type char_type; +public: + bool operator()(const ValueT& a, const ValueT& b) const + { + if (a.name().length() == b.name().length()) + { + return std::char_traits::compare(a.name().data(),b.name().data(),a.name().length()) < 0; + } + + size_t len = std::min JSONCONS_NO_MACRO_EXP(a.name().length(),b.name().length()); + int result = std::char_traits::compare(a.name().data(),b.name().data(),len); + if (result != 0) + { + return result < 0; + } + + return a.name().length() < b.name().length(); + } +}; + +template +class name_value_pair +{ +public: + typedef StringT string_type; + typedef typename StringT::value_type char_type; + + name_value_pair() + { + } + name_value_pair(const string_type& name) + : name_(name) + { + } + name_value_pair(string_type&& name) + : name_(std::move(name)) + { + } + + name_value_pair(const string_type& name, const ValueT& val) + : name_(name), value_(val) + { + } + name_value_pair(string_type&& name, const ValueT& val) + : name_(std::move(name)), value_(val) + { + } + name_value_pair(const string_type& name, ValueT&& val) + : name_(name), value_(std::move(val)) + { + } + name_value_pair(string_type&& name, ValueT&& val) + : name_(std::move(name)), value_(std::move(val)) + { + } + name_value_pair(const name_value_pair& member) + : name_(member.name_), value_(member.value_) + { + } + name_value_pair(name_value_pair&& member) + : name_(std::move(member.name_)), value_(std::move(member.value_)) + { + } + + const string_type& name() const + { + return name_; + } + + ValueT& value() + { + return value_; + } + + const ValueT& value() const + { + return value_; + } + + void value(const ValueT& value) + { + value_ = value; + } + + void value(ValueT&& value) + { + value_ = std::move(value); + } + + void swap(name_value_pair& member) + { + name_.swap(member.name_); + value_.swap(member.value_); + } + + name_value_pair& operator=(const name_value_pair& member) + { + if (this != & member) + { + name_ = member.name_; + value_ = member.value_; + } + return *this; + } + + name_value_pair& operator=(name_value_pair&& member) + { + if (this != &member) + { + name_.swap(member.name_); + value_.swap(member.value_); + } + return *this; + } + + void shrink_to_fit() + { + name_.shrink_to_fit(); + value_.shrink_to_fit(); + } +private: + string_type name_; + ValueT value_; +}; + +template +class json_object_iterator +{ +public: + typedef IteratorT iterator; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename std::iterator_traits::pointer pointer; + typedef typename std::iterator_traits::reference reference; + typedef std::bidirectional_iterator_tag iterator_category; + + json_object_iterator(bool empty = false) + : empty_(empty) + { + } + + json_object_iterator(iterator it) + : empty_(false), it_(it) + { + } + + json_object_iterator(const json_object_iterator& it) + : empty_(it.empty_), it_(it.it_) + { + } + + json_object_iterator& operator=(json_object_iterator rhs) + { + swap(*this,rhs); + return *this; + } + + json_object_iterator& operator++() + { + ++it_; + return *this; + } + + json_object_iterator operator++(int) // postfix increment + { + json_object_iterator temp(*this); + ++it_; + return temp; + } + + json_object_iterator& operator--() + { + --it_; + return *this; + } + + json_object_iterator operator--(int) + { + json_object_iterator temp(*this); + --it_; + return temp; + } + + reference operator*() const + { + return *it_; + } + + pointer operator->() const + { + return &(*it_); + } + + bool empty() const + { + return empty_; + } + + friend bool operator==(const json_object_iterator& it1, const json_object_iterator& it2) + { + return (it1.empty() && it2.empty()) || (it1.it_ == it2.it_); + } + friend bool operator!=(const json_object_iterator& it1, const json_object_iterator& it2) + { + return !(it1.it_ == it2.it_); + } + friend void swap(json_object_iterator& lhs, json_object_iterator& rhs) + { + using std::swap; + swap(lhs.it_,rhs.it_); + swap(lhs.empty_,rhs.empty_); + } + + iterator get() + { + return it_; + } + +//private: + bool empty_; + IteratorT it_; +}; + +template +class json_object +{ +public: + typedef Alloc allocator_type; + typedef typename JsonT::char_type char_type; + typedef StringT string_type; + typedef name_value_pair value_type; + typedef typename std::vector::iterator base_iterator; + typedef typename std::vector::const_iterator const_base_iterator; + + typedef json_object_iterator iterator; + typedef json_object_iterator const_iterator; +private: + std::vector members_; +public: + json_object(const allocator_type& allocator = allocator_type()) + : members_(allocator) + { + } + + json_object(const json_object& val) + : members_(val.members_) + { + } + + json_object(json_object&& val) + : members_(std::move(val.members_)) + { + } + + json_object(const json_object& val, const allocator_type& allocator) : + members_(val.members_,allocator) + { + } + + json_object(json_object&& val,const allocator_type& allocator) : + members_(std::move(val.members_),allocator) + { + } + + Alloc get_allocator() const + { + return members_.get_allocator(); + } + + iterator begin() + { + //return members_.begin(); + return iterator(members_.begin()); + } + + iterator end() + { + //return members_.end(); + return iterator(members_.end()); + } + + const_iterator begin() const + { + //return iterator(members.data()); + return const_iterator(members_.begin()); + } + + const_iterator end() const + { + //return members_.end(); + return const_iterator(members_.end()); + } +/* + const_iterator cbegin() const + { + return members_.begin(); + } + + const_iterator cend() const + { + return members_.end(); + } +*/ + void swap(json_object& val) + { + members_.swap(val.members_); + } + + size_t size() const {return members_.size();} + + size_t capacity() const {return members_.capacity();} + + void clear() {members_.clear();} + + void shrink_to_fit() + { + for (size_t i = 0; i < members_.size(); ++i) + { + members_[i].shrink_to_fit(); + } + members_.shrink_to_fit(); + } + + void reserve(size_t n) {members_.reserve(n);} + + iterator find(const char_type* name, size_t length) + { + member_lt_string comp(length); + auto it = std::lower_bound(members_.begin(),members_.end(), name, comp); + auto result = (it != members_.end() && name_eq_string(it->name(),name,length)) ? it : members_.end(); + return iterator(result); + } + + const_iterator find(const char_type* name, size_t length) const + { + member_lt_string comp(length); + auto it = std::lower_bound(members_.begin(),members_.end(), name, comp); + auto result = (it != members_.end() && name_eq_string(it->name(),name,length)) ? it : members_.end(); + return const_iterator(result); + } + + void erase(iterator first, iterator last) + { + members_.erase(first.get(),last.get()); + } + + void erase(const char_type* name, size_t length) + { + member_lt_string comp(length); + auto it = std::lower_bound(members_.begin(),members_.end(), name, comp); + if (it != members_.end() && name_eq_string(it->name(),name,length)) + { + members_.erase(it); + } + } + + template + void insert(InputIt first, InputIt last, UnaryPredicate pred) + { + size_t count = std::distance(first,last); + size_t pos = members_.size(); + members_.resize(pos+count); + auto d = members_.begin()+pos; + for (auto s = first; s != last; ++s, ++d) + { + *d = pred(*s); + } + std::sort(members_.begin(),members_.end(),member_lt_member()); + } + + void set(const char_type* s, size_t length, const JsonT& value) + { + auto it = std::lower_bound(members_.begin(),members_.end(),s,member_lt_string(length)); + if (it == members_.end()) + { + members_.push_back(value_type(string_type(s,length),value)); + } + else if (name_eq_string(it->name(),s,length)) + { + it->value(value); + } + else + { + members_.insert(it,value_type(string_type(s,length),value)); + } + } + + void set(const char_type* s, size_t length, JsonT&& value) + { + auto it = std::lower_bound(members_.begin(),members_.end(),s,member_lt_string(length)); + if (it == members_.end()) + { + members_.push_back(value_type(string_type(s,length),std::move(value))); + } + else if (name_eq_string(it->name(),s,length)) + { + it->value(std::move(value)); + } + else + { + members_.insert(it,value_type(string_type(s,length),std::move(value))); + } + } + + void set(string_type&& name, const JsonT& value) + { + auto it = std::lower_bound(members_.begin(),members_.end(),name.data() ,member_lt_string(name.length())); + if (it == members_.end()) + { + members_.push_back(value_type(std::move(name), value)); + } + else if (it->name() == name) + { + it->value(value); + } + else + { + members_.insert(it,value_type(std::move(name),value)); + } + } + + void set(const string_type& name, const JsonT& value) + { + set(name.data(),name.length(),value); + } + + void set(const string_type& name, JsonT&& value) + { + set(name.data(),name.length(),std::move(value)); + } + + void set(string_type&& name, JsonT&& value) + { + auto it = std::lower_bound(members_.begin(),members_.end(),name.data() ,member_lt_string(name.length())); + if (it == members_.end()) + { + members_.push_back(value_type(std::move(name), std::move(value))); + } + else if (it->name() == name) + { + it->value(std::move(value)); + } + else + { + members_.insert(it,value_type(std::move(name),std::move(value))); + } + } + + iterator set(iterator hint, const char_type* name, const JsonT& value) + { + return set(hint, name, std::char_traits::length(name), value); + } + + iterator set(iterator hint, const char_type* name, JsonT&& value) + { + return set(hint, name, std::char_traits::length(name), std::move(value)); + } + + iterator set(iterator hint, const char_type* s, size_t length, const JsonT& value) + { + base_iterator it; + if (hint.get() != members_.end() && name_le_string(hint.get()->name(), s, length)) + { + it = std::lower_bound(hint.get(),members_.end(),s,member_lt_string(length)); + } + else + { + it = std::lower_bound(members_.begin(),members_.end(),s, member_lt_string(length)); + } + + if (it == members_.end()) + { + members_.push_back(value_type(string_type(s, length), value)); + it = members_.begin() + (members_.size() - 1); + } + else if (name_eq_string(it->name(),s,length)) + { + it->value(value); + } + else + { + it = members_.insert(it,value_type(string_type(s,length),value)); + } + return iterator(it); + } + + iterator set(iterator hint, const char_type* s, size_t length, JsonT&& value) + { + base_iterator it; + if (hint.get() != members_.end() && name_le_string(hint.get()->name(), s, length)) + { + it = std::lower_bound(hint.get(),members_.end(),s,member_lt_string(length)); + } + else + { + it = std::lower_bound(members_.begin(),members_.end(),s, member_lt_string(length)); + } + + if (it == members_.end()) + { + members_.push_back(value_type(string_type(s, length), std::move(value))); + it = members_.begin() + (members_.size() - 1); + } + else if (name_eq_string(it->name(),s,length)) + { + it->value(std::move(value)); + } + else + { + it = members_.insert(it,value_type(string_type(s,length),std::move(value))); + } + return iterator(it); + } + + iterator set(iterator hint, const string_type& name, const JsonT& value) + { + return set(hint,name.data(),name.length(),value); + } + + iterator set(iterator hint, string_type&& name, const JsonT& value) + { + base_iterator it; + if (hint.get() != members_.end() && hint.get()->name() <= name) + { + it = std::lower_bound(hint.get(),members_.end(),name.data() ,member_lt_string(name.length())); + } + else + { + it = std::lower_bound(members_.begin(),members_.end(),name.data() ,member_lt_string(name.length())); + } + + if (it == members_.end()) + { + members_.push_back(value_type(std::move(name), value)); + it = members_.begin() + (members_.size() - 1); + } + else if (it->name() == name) + { + it->value(value); + } + else + { + it = members_.insert(it,value_type(std::move(name),value)); + } + return iterator(it); + } + + iterator set(iterator hint, const string_type& name, JsonT&& value) + { + return set(hint,name.data(),name.length(),std::move(value)); + } + + iterator set(iterator hint, string_type&& name, JsonT&& value) + { + typename std::vector::iterator it; + if (hint.get() != members_.end() && hint.get()->name() <= name) + { + it = std::lower_bound(hint.get(),members_.end(),name.data() ,member_lt_string(name.length())); + } + else + { + it = std::lower_bound(members_.begin(),members_.end(),name.data() ,member_lt_string(name.length())); + } + + if (it == members_.end()) + { + members_.push_back(value_type(std::move(name), std::move(value))); + it = members_.begin() + (members_.size() - 1); + } + else if (it->name() == name) + { + it->value(std::move(value)); + } + else + { + it = members_.insert(it,value_type(std::move(name),std::move(value))); + } + return iterator(it); + } + + bool operator==(const json_object& rhs) const + { + if (size() != rhs.size()) + { + return false; + } + for (auto it = members_.begin(); it != members_.end(); ++it) + { + + auto rhs_it = std::lower_bound(rhs.members_.begin(), rhs.members_.end(), *it, member_lt_member()); + // member_lt_member actually only compares keys, so we need to check the value separately + if (rhs_it == rhs.members_.end() || rhs_it->name() != it->name() || rhs_it->value() != it->value()) + { + return false; + } + } + return true; + } +private: + json_object& operator=(const json_object&); +}; + + + +} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_type_traits.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_type_traits.hpp new file mode 100644 index 00000000..aeda7a0b --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/json_type_traits.hpp @@ -0,0 +1,594 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "jsoncons/jsoncons.hpp" + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch" +#endif + +namespace jsoncons { + +template +class json_type_traits +{ +public: + static bool is(const JsonT&) + { + return false; + } +}; + +template +class json_type_traits +{ +public: + typedef typename JsonT::string_type string_type; + typedef typename string_type::allocator_type string_allocator; + + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_string(); + } + static string_type as(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.as_string(); + } + static string_type as(const JsonT& rhs, const string_allocator& allocator) JSONCONS_NOEXCEPT + { + return rhs.as_string(allocator); + } + static void assign(JsonT& lhs, const string_type& rhs) + { + lhs.assign_string(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& lhs) JSONCONS_NOEXCEPT + { + return lhs.is_any(); + } + static typename JsonT::any as(const JsonT& rhs) + { + return rhs.any_value(); + } + static void assign(JsonT& lhs, typename JsonT::any rhs) + { + lhs.assign_any(rhs); + } +}; + +template +class json_type_traits::const_pointer_type> +{ +public: + typedef typename JsonT::char_type char_type; + + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_string(); + } + static const char_type* as(const JsonT& rhs) + { + return rhs.as_cstring(); + } + static void assign(JsonT& lhs, const char_type *rhs) + { + size_t length = std::char_traits::length(rhs); + lhs.assign_string(rhs,length); + } +}; + +template +class json_type_traits::pointer_type> +{ +public: + typedef typename JsonT::char_type char_type; + + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_string(); + } + static const char_type* as(const JsonT& rhs) + { + return rhs.as_cstring(); + } + static void assign(JsonT& lhs, const char_type *rhs) + { + size_t length = std::char_traits::length(rhs); + lhs.assign_string(rhs,length); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + if (rhs.is_integer()) + { + return rhs.as_integer() >= std::numeric_limits::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else + { + return false; + } + } + static char as(const JsonT& rhs) + { + return static_cast(rhs.as_integer()); + } + static void assign(JsonT& lhs, char ch) + { + lhs.assign_integer(ch); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + if (rhs.is_integer()) + { + return rhs.as_integer() >= 0 && static_cast(rhs.as_integer()) <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else if (rhs.is_uinteger()) + { + return rhs.as_uinteger() <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else + { + return false; + } + } + static unsigned char as(const JsonT& rhs) + { + return static_cast(rhs.as_uinteger()); + } + static void assign(JsonT& lhs, unsigned char ch) + { + lhs.assign_uinteger(ch); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + if (rhs.is_integer()) + { + return rhs.as_integer() >= std::numeric_limits::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else if (rhs.is_uinteger()) + { + return rhs.as_uinteger() <= static_cast(std::numeric_limits::max JSONCONS_NO_MACRO_EXP()); + } + else + { + return false; + } + } + static signed char as(const JsonT& rhs) + { + return static_cast(rhs.as_integer()); + } + static void assign(JsonT& lhs, signed char ch) + { + lhs.assign_integer(ch); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + if (rhs.is_integer()) + { + return rhs.as_integer() >= std::numeric_limits::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else if (rhs.is_uinteger()) + { + return rhs.as_uinteger() <= static_cast(std::numeric_limits::max JSONCONS_NO_MACRO_EXP()); + } + else + { + return false; + } + } + static wchar_t as(const JsonT& rhs) + { + return static_cast(rhs.as_integer()); + } + static void assign(JsonT& lhs, wchar_t ch) + { + lhs.assign_integer(ch); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_object(); + } + static typename JsonT::object as(JsonT rhs) + { + JSONCONS_ASSERT(rhs.is_object()); + return rhs.object_value(); + } + static void assign(JsonT& lhs, typename JsonT::object rhs) + { + lhs.assign_object(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_array(); + } + static typename JsonT::array as(const JsonT& rhs) + { + JSONCONS_ASSERT(rhs.is_array()); + return rhs.array_value(); + } + static void assign(JsonT& lhs, typename JsonT::array rhs) + { + lhs.assign_array(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_null(); + } + static typename jsoncons::null_type as(const JsonT& rhs) + { + JSONCONS_ASSERT(rhs.is_null()); + return jsoncons::null_type(); + } + static void assign(JsonT& lhs, null_type) + { + lhs.assign_null(); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_bool(); + } + static bool as(const JsonT& rhs) + { + return rhs.as_bool(); + } + static void assign(JsonT& lhs, bool rhs) + { + lhs.assign_bool(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + if (rhs.is_integer()) + { + return rhs.as_integer() >= std::numeric_limits::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else if (rhs.is_uinteger()) + { + return rhs.as_uinteger() <= static_cast(std::numeric_limits::max JSONCONS_NO_MACRO_EXP()); + } + else + { + return false; + } + } + static short as(const JsonT& rhs) + { + return static_cast(rhs.as_integer()); + } + static void assign(JsonT& lhs, short rhs) + { + lhs.assign_integer(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + if (rhs.is_integer()) + { + return rhs.as_integer() >= 0 && static_cast(rhs.as_integer()) <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else if (rhs.is_uinteger()) + { + return rhs.as_uinteger() <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else + { + return false; + } + } + static unsigned short as(const JsonT& rhs) + { + return (unsigned short)rhs.as_uinteger(); + } + static void assign(JsonT& lhs, unsigned short rhs) + { + lhs.assign_uinteger(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + if (rhs.is_integer()) + { + return rhs.as_integer() >= std::numeric_limits::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else if (rhs.is_uinteger()) + { + return rhs.as_uinteger() <= static_cast(std::numeric_limits::max JSONCONS_NO_MACRO_EXP()); + } + else + { + return false; + } + } + static int as(const JsonT& rhs) + { + return static_cast(rhs.as_integer()); + } + static void assign(JsonT& lhs, int rhs) + { + lhs.assign_integer(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + if (rhs.is_integer()) + { + return rhs.as_integer() >= 0 && static_cast(rhs.as_integer()) <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else if (rhs.is_uinteger()) + { + return rhs.as_uinteger() <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else + { + return false; + } + } + static unsigned int as(const JsonT& rhs) + { + return static_cast(rhs.as_uinteger()); + } + static void assign(JsonT& lhs, unsigned int rhs) + { + lhs.assign_uinteger(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + if (rhs.is_integer()) + { + return rhs.as_integer() >= std::numeric_limits::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else if (rhs.is_uinteger()) + { + return rhs.as_uinteger() <= static_cast(std::numeric_limits::max JSONCONS_NO_MACRO_EXP()); + } + else + { + return false; + } + } + static long as(const JsonT& rhs) + { + return static_cast(rhs.as_integer()); + } + static void assign(JsonT& lhs, long rhs) + { + lhs.assign_integer(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + if (rhs.is_integer()) + { + return rhs.as_integer() >= 0 && static_cast(rhs.as_integer()) <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else if (rhs.is_uinteger()) + { + return rhs.as_uinteger() <= std::numeric_limits::max JSONCONS_NO_MACRO_EXP(); + } + else + { + return false; + } + } + static unsigned long as(const JsonT& rhs) + { + return static_cast(rhs.as_uinteger()); + } + static void assign(JsonT& lhs, unsigned long rhs) + { + lhs.assign_uinteger(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_integer(); + } + static long long as(const JsonT& rhs) + { + return rhs.as_integer(); + } + static void assign(JsonT& lhs, long long rhs) + { + lhs.assign_integer(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_uinteger(); + } + static unsigned long long as(const JsonT& rhs) + { + return rhs.as_uinteger(); + } + static void assign(JsonT& lhs, unsigned long long rhs) + { + lhs.assign_uinteger(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_double(); + } + + static double as(const JsonT& rhs) + { + return rhs.as_double(); + } + static void assign(JsonT& lhs, double rhs) + { + lhs.assign_double(rhs); + } +}; + +template +class json_type_traits +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + return rhs.is_double(); + } + static double as(const JsonT& rhs) + { + return static_cast(rhs.as_double()); + } + static void assign(JsonT& lhs, float rhs) + { + lhs.assign_double(static_cast(rhs)); + } +}; + +template +class json_type_traits> +{ +public: + static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT + { + bool result = rhs.is_array(); + for (size_t i = 0; result && i < rhs.size(); ++i) + { + if (!rhs[i].template is()) + { + result = false; + } + } + return result; + } + static std::vector as(const JsonT& rhs) + { + std::vector v(rhs.size()); + for (size_t i = 0; i < v.size(); ++i) + { + v[i] = rhs[i].template as(); + } + return v; + } + static void assign(JsonT& lhs, const std::vector& rhs) + { + lhs = JsonT(rhs.begin(), rhs.end()); + } +}; + +} + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/jsoncons.hpp b/vendor/jsoncons-0.99.2/jsoncons/jsoncons.hpp new file mode 100644 index 00000000..a45e4f8c --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/jsoncons.hpp @@ -0,0 +1,347 @@ +// 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_HPP +#define JSONCONS_JSONCONS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include "jsoncons/jsoncons_config.hpp" +#include "jsoncons/jsoncons_io.hpp" + +namespace jsoncons { + +// null_type + +struct null_type +{ +}; + +// json_exception + +class json_exception +{ +public: + virtual const char* what() const JSONCONS_NOEXCEPT = 0; +}; + +template +class json_exception_0 : public Base, public virtual json_exception +{ +public: + json_exception_0(std::string s) JSONCONS_NOEXCEPT + : Base(""), message_(s) + { + } + ~json_exception_0() JSONCONS_NOEXCEPT + { + } + const char* what() const JSONCONS_NOEXCEPT + { + return message_.c_str(); + } +private: + std::string message_; +}; + +template +class json_exception_1 : public Base, public virtual json_exception +{ +public: + json_exception_1(const std::string& format, const std::string& arg1) JSONCONS_NOEXCEPT + : Base(""), format_(format), arg1_(arg1) + { + } + json_exception_1(const std::string& format, const std::wstring& arg1) JSONCONS_NOEXCEPT + : Base(""), format_(format) + { + char buf[255]; + size_t retval; +#if defined(JSONCONS_HAS_WCSTOMBS_S) + wcstombs_s(&retval, buf, sizeof(buf), arg1.c_str(), arg1.size()); +#else + retval = wcstombs(buf, arg1.c_str(), sizeof(buf)); +#endif + if (retval != static_cast(-1)) + { + arg1_ = buf; + } + } + ~json_exception_1() JSONCONS_NOEXCEPT + { + } + const char* what() const JSONCONS_NOEXCEPT + { + c99_snprintf(const_cast(message_),255, format_.c_str(),arg1_.c_str()); + return message_; + } +private: + std::string format_; + std::string arg1_; + char message_[255]; +}; + +#define JSONCONS_STR2(x) #x +#define JSONCONS_STR(x) JSONCONS_STR2(x) + +#define JSONCONS_THROW_EXCEPTION(Base,x) throw jsoncons::json_exception_0((x)) +#define JSONCONS_THROW_EXCEPTION_1(Base,fmt,arg1) throw jsoncons::json_exception_1((fmt),(arg1)) +#define JSONCONS_ASSERT(x) if (!(x)) { \ + throw jsoncons::json_exception_0("assertion '" #x "' failed at " __FILE__ ":" \ + JSONCONS_STR(__LINE__)); } + +// json_char_traits + +const uint16_t min_lead_surrogate = 0xD800; +const uint16_t max_lead_surrogate = 0xDBFF; +const uint16_t min_trail_surrogate = 0xDC00; +const uint16_t max_trail_surrogate = 0xDFFF; + +template +struct json_literals +{ +}; + +template <> +struct json_literals +{ + static std::pair null_literal() + { + static const char* value = "null"; + return std::pair(value,4); + } + + static std::pair true_literal() + { + static const char* value = "true"; + return std::pair(value,4); + } + + static std::pair false_literal() + { + static const char* value = "false"; + return std::pair(value,5); + } +}; + +template <> +struct json_literals +{ + static std::pair null_literal() + { + static const wchar_t* value = L"null"; + return std::pair(value,4); + } + + static std::pair true_literal() + { + static const wchar_t* value = L"true"; + return std::pair(value,4); + } + + static std::pair false_literal() + { + static const wchar_t* value = L"false"; + return std::pair(value,5); + } +}; + +template +struct json_char_traits +{ +}; + +template <> +struct json_char_traits +{ + static uint32_t convert_char_to_codepoint(const char*& it, + const char*) + { + char c = *it; + uint32_t u(c >= 0 ? c : 256 + c ); + uint32_t cp = u; + if (u < 0x80) + { + } + else if ((u >> 5) == 0x6) + { + c = *(++it); + u = (c >= 0 ? c : 256 + c ); + cp = ((cp << 6) & 0x7ff) + (u & 0x3f); + } + else if ((u >> 4) == 0xe) + { + c = *(++it); + u = (c >= 0 ? c : 256 + c ); + cp = ((cp << 12) & 0xffff) + ((static_cast(0xff & u) << 6) & 0xfff); + c = *(++it); + u = (c >= 0 ? c : 256 + c ); + cp += (u) & 0x3f; + } + else if ((u >> 3) == 0x1e) + { + c = *(++it); + u = (c >= 0 ? c : 256 + c ); + cp = ((cp << 18) & 0x1fffff) + ((static_cast(0xff & u) << 12) & 0x3ffff); + c = *(++it); + u = (c >= 0 ? c : 256 + c ); + cp += (static_cast(0xff & u) << 6) & 0xfff; + c = *(++it); + u = (c >= 0 ? c : 256 + c ); + cp += (u) & 0x3f; + } + else + { + } + return cp; + } + + static void append_codepoint_to_string(uint32_t cp, std::string& s) + { + if (cp <= 0x7f) + { + s.push_back(static_cast(cp)); + } + else if (cp <= 0x7FF) + { + s.push_back(static_cast(0xC0 | (0x1f & (cp >> 6)))); + s.push_back(static_cast(0x80 | (0x3f & cp))); + } + else if (cp <= 0xFFFF) + { + s.push_back(0xE0 | static_cast((0xf & (cp >> 12)))); + s.push_back(0x80 | static_cast((0x3f & (cp >> 6)))); + s.push_back(static_cast(0x80 | (0x3f & cp))); + } + else if (cp <= 0x10FFFF) + { + s.push_back(static_cast(0xF0 | (0x7 & (cp >> 18)))); + s.push_back(static_cast(0x80 | (0x3f & (cp >> 12)))); + s.push_back(static_cast(0x80 | (0x3f & (cp >> 6)))); + s.push_back(static_cast(0x80 | (0x3f & cp))); + } + } + +}; + +template <> +struct json_char_traits // assume utf16 +{ + static void append_codepoint_to_string(uint32_t cp, std::wstring& s) + { + if (cp <= 0xFFFF) + { + s.push_back(static_cast(cp)); + } + else if (cp <= 0x10FFFF) + { + s.push_back(static_cast((cp >> 10) + min_lead_surrogate - (0x10000 >> 10))); + s.push_back(static_cast((cp & 0x3ff) + min_trail_surrogate)); + } + } + + static uint32_t convert_char_to_codepoint(const wchar_t*& it, const wchar_t*) + { + uint32_t cp = (0xffff & *it); + if ((cp >= min_lead_surrogate && cp <= max_lead_surrogate)) // surrogate pair + { + uint32_t trail_surrogate = 0xffff & *(++it); + cp = (cp << 10) + trail_surrogate + 0x10000u - (min_lead_surrogate << 10) - min_trail_surrogate; + } + return cp; + } +}; + +template <> +struct json_char_traits // assume utf32 +{ + static void append_codepoint_to_string(uint32_t cp, std::wstring& s) + { + if (cp <= 0xFFFF) + { + s.push_back(static_cast(cp)); + } + else if (cp <= 0x10FFFF) + { + s.push_back(static_cast(cp)); + } + } + + static uint32_t convert_char_to_codepoint(const wchar_t*& it, const wchar_t*) + { + uint32_t cp = static_cast(*it); + return cp; + } +}; + +inline +bool is_control_character(uint32_t c) +{ + return c <= 0x1F || c == 0x7f; +} + +inline +char to_hex_character(unsigned char c) +{ + JSONCONS_ASSERT(c <= 0xF); + + return (c < 10) ? ('0' + c) : ('A' - 10 + c); +} + +inline +bool is_non_ascii_character(uint32_t c) +{ + return c >= 0x80; +} + +template +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 +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 +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 +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; +}; + +} +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/jsoncons_config.hpp b/vendor/jsoncons-0.99.2/jsoncons/jsoncons_config.hpp new file mode 100644 index 00000000..7d261ec0 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/jsoncons_config.hpp @@ -0,0 +1,123 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // std::numeric_limits + +// Uncomment the following line to suppress deprecated names (recommended for new code) +// #define JSONCONS_NO_DEPRECATED + +#define JSONCONS_NO_MACRO_EXP + +namespace jsoncons +{ + +// Follow boost + +#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_FOPEN_S +#define JSONCONS_HAS_WCSTOMBS_S +#if _MSC_VER < 1800 // VS2013 +#define JSONCONS_NO_RAW_STRING_LITERALS +#define JSONCONS_NO_FOR_RANGE +#endif +#if _MSC_VER >= 1900 +#define JSONCONS_ALIGNOF alignof +#else +#define JSONCONS_ALIGNOF __alignof +#endif +#else +#define JSONCONS_ALIGNOF alignof +#endif + +#ifdef _MSC_VER +#pragma warning( disable : 4290 ) +inline bool is_nan(double x) { return _isnan(x) != 0; } +inline bool is_inf(double x) +{ + return !_finite(x) && !_isnan(x); +} +inline bool is_pos_inf(double x) +{ + return is_inf(x) && x > 0; +} +inline bool is_neg_inf(double x) +{ + return is_inf(x) && x < 0; +} + +inline +int c99_vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ + int count = -1; + + if (size != 0) count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); + if (count == -1) count = _vscprintf(format, ap); + + return count; +} + +inline +int c99_snprintf(char *str, size_t size, const char *format, ...) +{ + int count; + va_list ap; + + va_start(ap, format); + count = c99_vsnprintf(str, size, format, ap); + va_end(ap); + + return count; +} +#else +inline bool is_nan(double x) +{ return std::isnan( x ); } +inline bool is_pos_inf(double x) +{return std::isinf(x) && x > 0;} +inline bool is_neg_inf(double x) +{return std::isinf(x) && x > 0;} + +#if __cplusplus >= 201103L +#define c99_snprintf snprintf +#else +#define c99_snprintf std::snprintf +#endif + +#endif + +} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp b/vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp new file mode 100644 index 00000000..27c90fa1 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp @@ -0,0 +1,358 @@ +// 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_IO_HPP +#define JSONCONS_JSONCONS_IO_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // std::numeric_limits +#include "jsoncons_config.hpp" +#include "ovectorstream.hpp" + +namespace jsoncons +{ + +template +class buffered_ostream +{ + static const size_t default_buffer_length = 16384; + + std::basic_ostream* os_; + std::vector buffer_; + CharT * const begin_buffer_; + const CharT* const end_buffer_; + CharT* p_; +public: + buffered_ostream(std::basic_ostream& os) + : os_(std::addressof(os)), buffer_(default_buffer_length), begin_buffer_(buffer_.data()), end_buffer_(buffer_.data()+default_buffer_length), p_(buffer_.data()) + { + } + ~buffered_ostream() + { + os_->write(begin_buffer_, (p_ - begin_buffer_)); + os_->flush(); + } + + void flush() + { + os_->write(begin_buffer_, (p_ - begin_buffer_)); + p_ = begin_buffer_; + os_->flush(); + } + + 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_, (p_ - begin_buffer_)); + os_->write(s, length); + p_ = begin_buffer_; + } + } + + void write(const std::basic_string& s) + { + write(s.data(),s.length()); + } + + void put(CharT c) + { + if (p_ < end_buffer_) + { + *p_++ = c; + } + else + { + os_->write(begin_buffer_, (p_-begin_buffer_)); + p_ = begin_buffer_; + *p_++ = c; + } + } + +}; + +#ifdef _MSC_VER + +template +class float_printer +{ + uint8_t precision_; +public: + float_printer(int precision) + : precision_(precision) + { + } + + void print(double val, uint8_t precision, buffered_ostream& os) + { + char buf[_CVTBUFSIZE]; + int decimal_point = 0; + int sign = 0; + + int prec = (precision == 0) ? precision_ : precision; + + int err = _ecvt_s(buf, _CVTBUFSIZE, val, prec, &decimal_point, &sign); + if (err != 0) + { + throw std::runtime_error("Failed attempting double to string conversion"); + } + char* s = buf; + char* se = s + prec; + + int i, k; + int j; + + if (sign) + { + os.put('-'); + } + if (decimal_point <= -4 || decimal_point > se - s + 5) + { + os.put(*s++); + if (s < se) + { + os.put('.'); + while ((se-1) > s && *(se-1) == '0') + { + --se; + } + + while(s < se) + { + os.put(*s++); + } + } + os.put('e'); + /* sprintf(b, "%+.2d", decimal_point - 1); */ + if (--decimal_point < 0) { + os.put('-'); + decimal_point = -decimal_point; + } + else + os.put('+'); + for(j = 2, k = 10; 10*k <= decimal_point; j++, k *= 10); + for(;;) + { + i = decimal_point / k; + os.put(i + '0'); + if (--j <= 0) + break; + decimal_point -= i*k; + decimal_point *= 10; + } + } + else if (decimal_point <= 0) + { + os.put('0'); + os.put('.'); + while ((se-1) > s && *(se-1) == '0') + { + --se; + } + for(; decimal_point < 0; decimal_point++) + { + os.put('0'); + } + while(s < se) + { + os.put(*s++); + } + } + else { + while(s < se) + { + os.put(*s++); + if ((--decimal_point == 0) && s < se) + { + os.put('.'); + while ((se-1) > s && *(se-1) == '0') + { + --se; + } + } + } + for(; decimal_point > 0; decimal_point--) + { + os.put('0'); + } + } + } +}; + +#else + +template +class float_printer +{ + jsoncons::basic_ovectorstream vs_; + uint8_t precision_; +public: + float_printer(uint8_t precision) + : vs_(255), precision_(precision) + { + vs_.set_locale(std::locale::classic()); + vs_.precision(precision); + } + + void print(double val, uint8_t precision, buffered_ostream& os) + { + vs_.reset(); + vs_.precision(precision == 0 ? precision_ : precision); + vs_ << val; + + const CharT* s = vs_.data(); + const CharT* se = s + vs_.length(); + + bool dot = false; + while (s < se) + { + if (*s == '.') + { + dot = true; + } + else if (*s == 'e') + { + if (!dot) + { + os.put('.'); + os.put('0'); + dot = true; + } + } + os.put(*s); + ++s; + } + if (!dot) + { + os.put('.'); + os.put('0'); + } + } +}; + +#endif + +// string_to_float only requires narrow char +#ifdef _MSC_VER +class float_reader +{ +private: + _locale_t locale_; +public: + float_reader() + { + locale_ = _create_locale(LC_NUMERIC, "C"); + } + ~float_reader() + { + _free_locale(locale_); + } + + double read(const char* s, size_t length) + { + const char *begin = s; + char *end = nullptr; + double val = _strtod_l(begin, &end, locale_); + if (begin == end) + { + throw std::invalid_argument("Invalid float value"); + } + return val; + } + + float_reader(const float_reader& fr) = delete; + float_reader& operator=(const float_reader& fr) = delete; +}; + +#else +class float_reader +{ +private: + std::vector buffer_; + std::string decimal_point_; + bool is_dot_; +public: + float_reader() + : buffer_() + { + struct lconv * lc = localeconv(); + if (lc != nullptr) + { + decimal_point_ = std::string(lc->decimal_point); + } + else + { + decimal_point_ = std::string("."); + } + buffer_.reserve(100); + is_dot_ = decimal_point_ == "."; + } + + double read(const char* s, size_t length) + { + double val; + if (is_dot_) + { + const char *begin = s; + char *end = nullptr; + val = strtod(begin, &end); + if (begin == end) + { + throw std::invalid_argument("Invalid float value"); + } + } + else + { + buffer_.clear(); + size_t j = 0; + const char* pe = s + length; + for (const char* p = s; p < pe; ++p) + { + if (*p == '.') + { + buffer_.insert(buffer_.begin() + j, decimal_point_.begin(), decimal_point_.end()); + j += decimal_point_.length(); + } + else + { + buffer_.push_back(*p); + ++j; + } + } + const char *begin = buffer_.data(); + char *end = nullptr; + val = strtod(begin, &end); + if (begin == end) + { + throw std::invalid_argument("Invalid float value"); + } + } + return val; + } + + float_reader(const float_reader& fr) = delete; + float_reader& operator=(const float_reader& fr) = delete; +}; +#endif + +} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/output_format.hpp b/vendor/jsoncons-0.99.2/jsoncons/output_format.hpp new file mode 100644 index 00000000..54e74874 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/output_format.hpp @@ -0,0 +1,330 @@ +// 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_OUTPUT_FORMAT_HPP +#define JSONCONS_OUTPUT_FORMAT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace jsoncons { + +enum class block_options {next_line,same_line}; + +template +class buffered_ostream; + +template +class basic_output_format +{ + int indent_; + uint8_t precision_; + bool replace_nan_; + bool replace_pos_inf_; + bool replace_neg_inf_; + std::basic_string nan_replacement_; + std::basic_string pos_inf_replacement_; + std::basic_string neg_inf_replacement_; + bool escape_all_non_ascii_; + bool escape_solidus_; + block_options object_array_block_option_; + block_options array_array_block_option_; + block_options object_object_block_option_; + block_options array_object_block_option_; +public: + static const size_t default_indent = 4; + +// Constructors + + basic_output_format() + : + indent_(default_indent), + precision_(16), + replace_nan_(true), + replace_pos_inf_(true), + replace_neg_inf_(true), + nan_replacement_(json_literals::null_literal().first), + pos_inf_replacement_(json_literals::null_literal().first), + neg_inf_replacement_(json_literals::null_literal().first), + escape_all_non_ascii_(false), + escape_solidus_(false), + object_array_block_option_(block_options::same_line), + array_array_block_option_(block_options::next_line), + object_object_block_option_(block_options::same_line), + array_object_block_option_(block_options::next_line) + { + } + +// Accessors + + block_options object_array_block_option() + { + return object_array_block_option_; + } + + basic_output_format& object_array_block_option(block_options value) + { + object_array_block_option_ = value; + return *this; + } + + block_options object_object_block_option() + { + return object_object_block_option_; + } + + basic_output_format& object_object_block_option(block_options value) + { + object_object_block_option_ = value; + return *this; + } + + block_options array_array_block_option() + { + return array_array_block_option_; + } + + basic_output_format& array_array_block_option(block_options value) + { + array_array_block_option_ = value; + return *this; + } + + block_options array_object_block_option() + { + return array_object_block_option_; + } + + basic_output_format& array_object_block_option(block_options value) + { + array_object_block_option_ = value; + return *this; + } + + int indent() const + { + return indent_; + } + + uint8_t precision() const + { + return precision_; + } + + bool escape_all_non_ascii() const + { + return escape_all_non_ascii_; + } + + bool escape_solidus() const + { + return escape_solidus_; + } + + bool replace_nan() const {return replace_nan_;} + + bool replace_pos_inf() const {return replace_pos_inf_;} + + bool replace_neg_inf() const {return replace_neg_inf_;} + + std::basic_string nan_replacement() const + { + return nan_replacement_; + } + + std::basic_string pos_inf_replacement() const + { + return pos_inf_replacement_; + } + + std::basic_string neg_inf_replacement() const + { + return neg_inf_replacement_; + } + +// Modifiers + + basic_output_format& precision(uint8_t prec) + { + precision_ = prec; + return *this; + } + + basic_output_format& escape_all_non_ascii(bool value) + { + escape_all_non_ascii_ = value; + return *this; + } + + basic_output_format& escape_solidus(bool value) + { + escape_solidus_ = value; + return *this; + } + + basic_output_format& replace_nan(bool replace) + { + replace_nan_ = replace; + return *this; + } + + basic_output_format& replace_inf(bool replace) + { + replace_pos_inf_ = replace; + replace_neg_inf_ = replace; + return *this; + } + + basic_output_format& replace_pos_inf(bool replace) + { + replace_pos_inf_ = replace; + return *this; + } + + basic_output_format& replace_neg_inf(bool replace) + { + replace_neg_inf_ = replace; + return *this; + } + + basic_output_format& nan_replacement(const std::basic_string& replacement) + { + nan_replacement_ = replacement; + return *this; + } + + basic_output_format& pos_inf_replacement(const std::basic_string& replacement) + { + pos_inf_replacement_ = replacement; + return *this; + } + + basic_output_format& neg_inf_replacement(const std::basic_string& replacement) + { + neg_inf_replacement_ = replacement; + return *this; + } + + basic_output_format& indent(int value) + { + indent_ = value; + return *this; + } +}; + +template +void escape_string(const CharT* s, + size_t length, + const basic_output_format& format, + buffered_ostream& os) +{ + const CharT* begin = s; + const CharT* end = s + length; + for (const CharT* it = begin; it != end; ++it) + { + CharT c = *it; + switch (c) + { + case '\\': + os.put('\\'); + os.put('\\'); + break; + case '"': + os.put('\\'); + os.put('\"'); + break; + case '\b': + os.put('\\'); + os.put('b'); + break; + case '\f': + os.put('\\'); + os.put('f'); + break; + case '\n': + os.put('\\'); + os.put('n'); + break; + case '\r': + os.put('\\'); + os.put('r'); + break; + case '\t': + os.put('\\'); + os.put('t'); + break; + default: + uint32_t u(c >= 0 ? c : 256 + c); + if (format.escape_solidus() && c == '/') + { + os.put('\\'); + os.put('/'); + } + else if (is_control_character(u) || format.escape_all_non_ascii()) + { + // convert utf8 to codepoint + uint32_t cp = json_char_traits::convert_char_to_codepoint(it, end); + if (is_non_ascii_character(cp) || is_control_character(u)) + { + if (cp > 0xFFFF) + { + cp -= 0x10000; + uint32_t first = (cp >> 10) + 0xD800; + uint32_t second = ((cp & 0x03FF) + 0xDC00); + + os.put('\\'); + os.put('u'); + os.put(to_hex_character(first >> 12 & 0x000F)); + os.put(to_hex_character(first >> 8 & 0x000F)); + os.put(to_hex_character(first >> 4 & 0x000F)); + os.put(to_hex_character(first & 0x000F)); + os.put('\\'); + os.put('u'); + os.put(to_hex_character(second >> 12 & 0x000F)); + os.put(to_hex_character(second >> 8 & 0x000F)); + os.put(to_hex_character(second >> 4 & 0x000F)); + os.put(to_hex_character(second & 0x000F)); + } + else + { + os.put('\\'); + os.put('u'); + os.put(to_hex_character(cp >> 12 & 0x000F)); + os.put(to_hex_character(cp >> 8 & 0x000F)); + os.put(to_hex_character(cp >> 4 & 0x000F)); + os.put(to_hex_character(cp & 0x000F)); + } + } + else + { + os.put(c); + } + } + else if (format.escape_solidus() && c == '/') + { + os.put('\\'); + os.put('/'); + } + else + { + os.put(c); + } + break; + } + } +} + +typedef basic_output_format output_format; +typedef basic_output_format woutput_format; + +} +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/ovectorstream.hpp b/vendor/jsoncons-0.99.2/jsoncons/ovectorstream.hpp new file mode 100644 index 00000000..e19f5085 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/ovectorstream.hpp @@ -0,0 +1,227 @@ +// 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_OVECTORSTREAM_HPP +#define JSONCONS_OVECTORSTREAM_HPP + +#include +#include +#include +#include +#include +#include "jsoncons/jsoncons_config.hpp" + +namespace jsoncons { + +template< + class CharT, + class Traits = std::char_traits +> class basic_ovectorstream; + +template +class basic_ovectorbuf + : public std::basic_streambuf +{ +private: + std::ios_base::openmode mode_; + std::vector buf_; + +public: + typedef CharT char_type; + typedef typename CharTraits::int_type int_type; + typedef typename CharTraits::pos_type pos_type; + typedef typename CharTraits::off_type off_type; + typedef CharTraits traits_type; + typedef std::basic_streambuf base_streambuf; + +public: + + explicit basic_ovectorbuf(std::size_t length) JSONCONS_NOEXCEPT + : base_streambuf(), + 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()); + } + + virtual ~basic_ovectorbuf() {} + + const CharT* data() const + { + return buf_.data(); + } + +protected: + int_type underflow() override + { + return this->gptr() != this->egptr() ? + CharTraits::to_int_type(*this->gptr()) : CharTraits::eof(); + } + + int_type pbackfail(int_type c = CharTraits::eof()) override + { + if (this->gptr() != this->eback()) + { + if (!CharTraits::eq_int_type(c, CharTraits::eof())) + { + if (CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) + { + this->gbump(-1); + return c; + } + this->gbump(-1); + *this->gptr() = c; + return c; + } + else + { + this->gbump(-1); + return CharTraits::not_eof(c); + } + } + else + { + return CharTraits::eof(); + } + } + + int_type overflow(int_type c = CharTraits::eof()) override + { + if (!CharTraits::eq_int_type(c, CharTraits::eof())) + { + size_t pos = buf_.size(); + buf_.resize(pos*2); + this->setp(buf_.data(), buf_.data() + buf_.size()); + this->pubseekpos(pos, std::ios_base::out); + *this->pptr() = CharTraits::to_char_type(c); + this->pbump(1); + this->pubsync(); + return c; + } + else + { + return CharTraits::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(buf_.size()); + break; + case std::ios_base::cur: + newoff = static_cast(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(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(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 basic_ovectorstream : + private basic_ovectorbuf, + public std::basic_ostream +{ +public: + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + +private: + typedef basic_ovectorbuf base_ouputbuf; + typedef std::basic_ios base_ios; + typedef std::basic_ostream base_streambuf; + base_ouputbuf& get_buf() {return *this;} + const base_ouputbuf& get_buf() const {return *this;} + +public: + basic_ovectorstream(std::size_t length) JSONCONS_NOEXCEPT + : base_ouputbuf(length), + base_streambuf(&get_buf()) + {} + + ~basic_ovectorstream() {} + +public: + + size_t length() + { + return this->pptr() - this->pbase(); + } + + void set_locale(const std::locale& loc) + { + std::locale result = std::basic_ostream::imbue(loc); + this->pubimbue(loc); + } + + void reset() + { + this->clear(); + this->seekp(0, std::ios::beg); + } + + const CharT* data() const + { + return get_buf().data(); + } +}; + +} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons/parse_error_handler.hpp b/vendor/jsoncons-0.99.2/jsoncons/parse_error_handler.hpp new file mode 100644 index 00000000..9081fc95 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons/parse_error_handler.hpp @@ -0,0 +1,172 @@ +/// 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/jsoncons.hpp" +#include + +namespace jsoncons { + +class parse_exception : public std::exception, public virtual json_exception +{ +public: + parse_exception(std::error_code ec, + size_t line, + size_t column) + : error_code_(ec), + line_number_(line), + column_number_(column) + { + } + parse_exception(const parse_exception& other) + : error_code_(other.error_code_), + line_number_(other.line_number_), + column_number_(other.column_number_) + { + } + const char* what() const JSONCONS_NOEXCEPT + { + std::ostringstream os; + os << error_code_.message() << " at line " << line_number_ << " and column " << column_number_; + const_cast(buffer_) = os.str(); + return buffer_.c_str(); + } + + 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_; + } +private: + std::error_code error_code_; + std::string buffer_; + size_t line_number_; + size_t column_number_; +}; + +typedef parse_exception json_parse_exception; + +template +class basic_parsing_context +{ +public: + virtual ~basic_parsing_context() {} + + size_t line_number() const + { + return do_line_number(); + } + size_t column_number() const + { + return do_column_number(); + } + CharT current_char() const + { + return do_current_char(); + } + +#if !defined(JSONCONS_NO_DEPRECATED) + CharT last_char() const + { + return do_current_char(); + } +#endif + +private: + virtual size_t do_line_number() const = 0; + virtual size_t do_column_number() const = 0; + virtual CharT do_current_char() const = 0; +}; + +typedef basic_parsing_context parsing_context; +typedef basic_parsing_context wparsing_context; + +template +class basic_parse_error_handler +{ +public: + virtual ~basic_parse_error_handler() + { + } + + void warning(std::error_code ec, + const basic_parsing_context& context) throw (parse_exception) + { + do_warning(ec,context); + } + + void error(std::error_code ec, + const basic_parsing_context& context) throw (parse_exception) + { + do_error(ec,context); + } + + void fatal_error(std::error_code ec, + const basic_parsing_context& context) throw (parse_exception) + { + do_fatal_error(ec,context); + throw parse_exception(ec,context.line_number(),context.column_number()); + } + +private: + virtual void do_warning(std::error_code, + const basic_parsing_context& context) throw (parse_exception) = 0; + + virtual void do_error(std::error_code, + const basic_parsing_context& context) throw (parse_exception) = 0; + + virtual void do_fatal_error(std::error_code, + const basic_parsing_context& context) throw (parse_exception) + { + (void)context; + } +}; + +template +class basic_default_parse_error_handler : public basic_parse_error_handler +{ +public: + static basic_parse_error_handler& instance() + { + static basic_default_parse_error_handler instance; + return instance; + } +private: + virtual void do_warning(std::error_code, + const basic_parsing_context& context) throw (parse_exception) + { + (void)context; + } + + virtual void do_error(std::error_code ec, + const basic_parsing_context& context) throw (parse_exception) + { + throw parse_exception(ec,context.line_number(),context.column_number()); + } +}; + +typedef basic_parse_error_handler parse_error_handler; +typedef basic_parse_error_handler wparse_error_handler; + +typedef basic_default_parse_error_handler default_parse_error_handler; +typedef basic_default_parse_error_handler wdefault_parse_error_handler; + +typedef basic_parsing_context parsing_context; +typedef basic_parsing_context wparsing_context; + +} +#endif -- cgit v1.2.3