summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBardur Arantsson <bardur@scientician.net>2016-10-05 18:45:08 +0200
committerBardur Arantsson <bardur@scientician.net>2016-10-05 18:45:08 +0200
commit0f36ab53cbac06b61d1b4b6509590759ed8c6703 (patch)
treef37b74c04cbf6bda79d543c941f72e4db12ddd0d
parent0e91eb9e205508daf5de1234e7ac3e59fa809982 (diff)
Introduce jsoncons as replacement for jansson
-rw-r--r--src/CMakeLists.txt1
l---------vendor/jsoncons1
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json.hpp3574
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_deserializer.hpp267
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_error_category.hpp111
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_filter.hpp324
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_input_handler.hpp282
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_output_handler.hpp262
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp1587
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp.orig2157
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_reader.hpp176
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_serializer.hpp435
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_structures.hpp860
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_type_traits.hpp594
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/jsoncons.hpp347
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/jsoncons_config.hpp123
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp358
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/output_format.hpp330
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/ovectorstream.hpp227
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/parse_error_handler.hpp172
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/boost/type_extensions.hpp59
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp55
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp341
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp903
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp175
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp445
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/json_query.hpp921
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_error_category.hpp75
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_filter.hpp1495
29 files changed, 16657 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5f06bcec..035c42d1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,6 +3,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../vendor/bandit)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../vendor/fmt)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../vendor/pcg-cpp/include)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../vendor/jsoncons)
# Add subdirectories
ADD_SUBDIRECTORY (squelch)
diff --git a/vendor/jsoncons b/vendor/jsoncons
new file mode 120000
index 00000000..0f3415d8
--- /dev/null
+++ b/vendor/jsoncons
@@ -0,0 +1 @@
+jsoncons-0.99.2 \ No newline at end of file
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 <limits>
+#include <string>
+#include <vector>
+#include <exception>
+#include <cstdlib>
+#include <cstring>
+#include <ostream>
+#include <memory>
+#include <typeinfo>
+#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 <class T, class Alloc, typename... Args>
+T* create_impl(const Alloc& allocator, Args&& ... args)
+{
+ typename std::allocator_traits<Alloc>:: template rebind_alloc<T> alloc(allocator);
+ T* storage = alloc.allocate(1);
+ try
+ {
+ std::allocator_traits<Alloc>:: template rebind_traits<T>::construct(alloc, storage, std::forward<Args>(args)...);
+ }
+ catch (...)
+ {
+ alloc.deallocate(storage,1);
+ throw;
+ }
+ return storage;
+}
+
+template <class T, class Alloc>
+void destroy_impl(const Alloc& allocator, T* p)
+{
+ typename std::allocator_traits<Alloc>:: template rebind_alloc<T> alloc(allocator);
+ std::allocator_traits<Alloc>:: template rebind_traits<T>::destroy(alloc, p);
+ alloc.deallocate(p,1);
+}
+
+template <typename CharT, class Alloc>
+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<allocator_type>::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<typename T>
+ explicit serializable_any(T val)
+ {
+ impl_ = create_impl<any_handle_impl<typename type_wrapper<T>::value_type>>(allocator_,val);
+ }
+
+ Alloc get_allocator() const
+ {
+ return allocator_;
+ }
+
+ template <typename T>
+ typename type_wrapper<T>::reference cast()
+ {
+ if (typeid(*impl_) != typeid(any_handle_impl<typename type_wrapper<T>::value_type>))
+ {
+ JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad serializable_any cast");
+ }
+ return static_cast<any_handle_impl<typename type_wrapper<T>::value_type>&>(*impl_).value_;
+ }
+
+ template <typename T>
+ typename type_wrapper<T>::const_reference cast() const
+ {
+ if (typeid(*impl_) != typeid(any_handle_impl<typename type_wrapper<T>::value_type>))
+ {
+ JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad serializable_any cast");
+ }
+ return static_cast<any_handle_impl<typename type_wrapper<T>::value_type>&>(*impl_).value_;
+ }
+
+ serializable_any& operator=(serializable_any rhs)
+ {
+ std::swap(impl_,rhs.impl_);
+ return *this;
+ }
+
+ void to_stream(basic_json_output_handler<CharT>& 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<CharT>& os) const = 0;
+ };
+
+ template <class T>
+ 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<any_handle_impl<T>>(allocator, value_);
+ }
+
+ virtual void to_stream(basic_json_output_handler<CharT>& os) const
+ {
+ serialize(os,value_);
+ }
+
+ T value_;
+ };
+
+ Alloc allocator_;
+ any_handle* impl_;
+};
+
+template <typename CharT,class T> inline
+void serialize(basic_json_output_handler<CharT>& os, const T&)
+{
+ os.value(null_type());
+}
+
+template <typename CharT>
+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 <typename CharT, typename Alloc = std::allocator<CharT>>
+class basic_json
+{
+public:
+
+ typedef Alloc allocator_type;
+
+ typedef CharT char_type;
+ typedef typename std::char_traits<CharT> char_traits_type;
+
+ typedef typename std::allocator_traits<Alloc>:: template rebind_alloc<CharT> string_allocator;
+ typedef std::basic_string<CharT,char_traits_type,string_allocator> string_type;
+ typedef basic_json<CharT,Alloc> value_type;
+ typedef name_value_pair<string_type,value_type> member_type;
+
+ typedef typename std::allocator_traits<Alloc>:: template rebind_alloc<basic_json<CharT,Alloc>> array_allocator;
+
+ typedef typename std::allocator_traits<Alloc>:: template rebind_alloc<member_type> object_allocator;
+
+ typedef json_array<basic_json<CharT,Alloc>,array_allocator> array;
+ typedef json_object<string_type,basic_json<CharT,Alloc>,object_allocator> object;
+ typedef serializable_any<char_type,Alloc> 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 <typename IteratorT>
+ class range
+ {
+ IteratorT first_;
+ IteratorT last_;
+ public:
+ range(const IteratorT& first, const IteratorT& last)
+ : first_(first), last_(last)
+ {
+ }
+
+ public:
+ friend class basic_json<CharT, Alloc>;
+
+ IteratorT begin()
+ {
+ return first_;
+ }
+ IteratorT end()
+ {
+ return last_;
+ }
+ };
+
+ typedef range<object_iterator> object_range;
+ typedef range<const_object_iterator> const_object_range;
+ typedef range<array_iterator> array_range;
+ typedef range<const_array_iterator> 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<char_type>::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<sizeof(string_dataA), JSONCONS_ALIGNOF(string_dataA)>::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<string_allocator>:: template rebind_alloc<char> alloc(allocator);
+
+ char* storage = alloc.allocate(mem_size);
+ string_data* ps = new(storage)string_data(allocator);
+ auto psa = reinterpret_cast<string_dataA*>(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<string_allocator>:: template rebind_alloc<char> alloc(allocator);
+ alloc.deallocate(reinterpret_cast<char*>(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<object>(a, object_allocator(a));
+ }
+
+ variant(std::initializer_list<value_type> init,
+ const Alloc& a)
+ : type_(value_types::array_t)
+ {
+ value_.array_val_ = create_impl<array>(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<object>(val.get_allocator(), val) ;
+ }
+
+ variant(const object & val, const Alloc& a)
+ : type_(value_types::object_t)
+ {
+ value_.object_val_ = create_impl<object>(a, val, object_allocator(a)) ;
+ }
+
+ variant(object&& val)
+ : type_(value_types::object_t)
+ {
+ value_.object_val_ = create_impl<object>(val.get_allocator(), std::move(val));
+ }
+
+ variant(object&& val, const Alloc& a)
+ : type_(value_types::object_t)
+ {
+ value_.object_val_ = create_impl<object>(a, std::move(val), object_allocator(a));
+ }
+
+ variant(const array& val)
+ : type_(value_types::array_t)
+ {
+ value_.array_val_ = create_impl<array>(val.get_allocator(), val);
+ }
+
+ variant(const array& val, const Alloc& a)
+ : type_(value_types::array_t)
+ {
+ value_.array_val_ = create_impl<array>(a, val, array_allocator(a));
+ }
+
+ variant(array&& val)
+ : type_(value_types::array_t)
+ {
+ value_.array_val_ = create_impl<array>(val.get_allocator(), std::move(val));
+ }
+
+ variant(array&& val, const Alloc& a)
+ : type_(value_types::array_t)
+ {
+ value_.array_val_ = create_impl<array>(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<any>(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<string_type>(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<uint8_t>(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<char_type>::length(s);
+ if (length > variant::small_string_capacity)
+ {
+ type_ = value_types::string_t;
+ //value_.string_val_ = create_impl<string_type>(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<uint8_t>(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<string_type>(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<uint8_t>(length);
+ std::memcpy(value_.small_string_val_,s,length*sizeof(char_type));
+ value_.small_string_val_[length_or_precision_] = 0;
+ }
+ }
+
+ template<class InputIterator>
+ variant(InputIterator first, InputIterator last, const Alloc& a)
+ : type_(value_types::array_t)
+ {
+ value_.array_val_ = create_impl<array>(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<string_type>(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<array>(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<object>(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<any>(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<object>(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<object>(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<array>(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<array>(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<string_type>(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<uint8_t>(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<string_type>(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<uint8_t>(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<any>(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<char_type>::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 ParentT>
+ class json_proxy
+ {
+ private:
+ typedef json_proxy<ParentT> 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<CharT,Alloc>& evaluate()
+ {
+ return parent_.evaluate(name_);
+ }
+
+ const basic_json<CharT,Alloc>& evaluate() const
+ {
+ return parent_.evaluate(name_);
+ }
+
+ basic_json<CharT,Alloc>& evaluate_with_default()
+ {
+ basic_json<CharT,Alloc>& 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<CharT,Alloc>& evaluate(size_t index)
+ {
+ return parent_.evaluate(name_).at(index);
+ }
+
+ const basic_json<CharT,Alloc>& evaluate(size_t index) const
+ {
+ return parent_.evaluate(name_).at(index);
+ }
+
+ basic_json<CharT,Alloc>& evaluate(const string_type& index)
+ {
+ return parent_.evaluate(name_).at(index);
+ }
+
+ const basic_json<CharT,Alloc>& evaluate(const string_type& index) const
+ {
+ return parent_.evaluate(name_).at(index);
+ }
+ public:
+
+ friend class basic_json<CharT,Alloc>;
+
+ 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 <typename T>
+ void resize(size_t n, T val)
+ {
+ evaluate().resize(n,val);
+ }
+
+ template<typename T>
+ bool is() const
+ {
+ return evaluate().template is<T>();
+ }
+
+ 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<char_type>& format) const
+ {
+ return evaluate().as_string(format);
+ }
+
+ string_type as_string(const basic_output_format<char_type>& format,
+ const string_allocator& allocator) const
+ {
+ return evaluate().as_string(format,allocator);
+ }
+
+ template<typename T>
+ T as() const
+ {
+ return evaluate().template as<T>();
+ }
+
+ template<typename T>
+ typename std::enable_if<std::is_same<string_type,T>::value>::type as(const string_allocator& allocator) const
+ {
+ return evaluate().template as<T>(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 <class T>
+ std::vector<T> as_vector() const
+ {
+ return evaluate().template as_vector<T>();
+ }
+
+ double as_double() const
+ {
+ return evaluate().as_double();
+ }
+
+ int64_t as_integer() const
+ {
+ return evaluate().as_integer();
+ }
+
+ unsigned long long as_ulonglong() const
+ {
+ return evaluate().as_ulonglong();
+ }
+
+ uint64_t as_uinteger() const
+ {
+ return evaluate().as_uinteger();
+ }
+
+ template <class T>
+ const T& any_cast() const
+ {
+ return evaluate().template any_cast<T>();
+ }
+ // Returns a const reference to the custom data associated with name
+
+ template <class T>
+ T& any_cast()
+ {
+ return evaluate().template any_cast<T>();
+ }
+ // Returns a reference to the custom data associated with name
+
+ operator basic_json&()
+ {
+ return evaluate();
+ }
+
+ operator const basic_json&() const
+ {
+ return evaluate();
+ }
+
+ template <typename T>
+ 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<CharT,Alloc>& operator[](size_t i)
+ {
+ return evaluate_with_default().at(i);
+ }
+
+ const basic_json<CharT,Alloc>& operator[](size_t i) const
+ {
+ return evaluate().at(i);
+ }
+
+ json_proxy<proxy_type> operator[](const string_type& name)
+ {
+ return json_proxy<proxy_type>(*this,name);
+ }
+
+ const json_proxy<proxy_type> operator[](const string_type& name) const
+ {
+ return json_proxy<proxy_type>(*this,name);
+ }
+
+ basic_json<CharT,Alloc>& at(const string_type& name)
+ {
+ return evaluate().at(name);
+ }
+
+ const basic_json<CharT,Alloc>& at(const string_type& name) const
+ {
+ return evaluate().at(name);
+ }
+
+ const basic_json<CharT,Alloc>& at(size_t index)
+ {
+ return evaluate().at(index);
+ }
+
+ const basic_json<CharT,Alloc>& 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 <typename T>
+ basic_json<CharT,Alloc> get(const string_type& name, T&& default_val) const
+ {
+ return evaluate().get(name,std::forward<T>(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<CharT,Alloc>& value)
+ {
+ evaluate().set(name,value);
+ }
+
+ void set(string_type&& name, const basic_json<CharT,Alloc>& value)
+
+ {
+ evaluate().set(std::move(name),value);
+ }
+
+ void set(const string_type& name, basic_json<CharT,Alloc>&& value)
+
+ {
+ evaluate().set(name,std::move(value));
+ }
+
+ void set(string_type&& name, basic_json<CharT,Alloc>&& value)
+
+ {
+ evaluate().set(std::move(name),std::move(value));
+ }
+
+ object_iterator set(object_iterator hint, const string_type& name, const basic_json<CharT,Alloc>& value)
+ {
+ return evaluate().set(hint, name,value);
+ }
+
+ object_iterator set(object_iterator hint, string_type&& name, const basic_json<CharT,Alloc>& value)
+
+ {
+ return evaluate().set(hint, std::move(name),value);
+ }
+
+ object_iterator set(object_iterator hint, const string_type& name, basic_json<CharT,Alloc>&& value)
+
+ {
+ return evaluate().set(hint, name,std::move(value));
+ }
+
+ object_iterator set(object_iterator hint, string_type&& name, basic_json<CharT,Alloc>&& value)
+
+ {
+ return evaluate().set(hint, std::move(name),std::move(value));
+ }
+
+ void add(basic_json<CharT,Alloc>&& value)
+ {
+ evaluate_with_default().add(std::move(value));
+ }
+
+ void add(const basic_json<CharT,Alloc>& value)
+ {
+ evaluate_with_default().add(value);
+ }
+
+ array_iterator add(const_array_iterator pos, const basic_json<CharT,Alloc>& value)
+ {
+ return evaluate_with_default().add(pos, value);
+ }
+
+ array_iterator add(const_array_iterator pos, basic_json<CharT,Alloc>&& 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<char_type>& format, string_allocator& allocator = string_allocator()) const
+ {
+ return evaluate().to_string(format,allocator);
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os) const
+ {
+ evaluate().to_stream(os);
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os, const basic_output_format<char_type>& format) const
+ {
+ evaluate().to_stream(os,format);
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os, const basic_output_format<char_type>& format, bool indenting) const
+ {
+ evaluate().to_stream(os,format,indenting);
+ }
+
+ void swap(basic_json<CharT,Alloc>& val)
+ {
+ evaluate_with_default().swap(val);
+ }
+
+ friend std::basic_ostream<char_type>& operator<<(std::basic_ostream<char_type>& 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 <typename T>
+ void resize_array(size_t n, T val)
+ {
+ evaluate().resize_array(n,val);
+ }
+
+ object_iterator begin_members()
+ {
+ return evaluate().begin_members();
+ }
+
+ const_object_iterator begin_members() const
+ {
+ return evaluate().begin_members();
+ }
+
+ object_iterator end_members()
+ {
+ return evaluate().end_members();
+ }
+
+ const_object_iterator end_members() const
+ {
+ return evaluate().end_members();
+ }
+
+ array_iterator begin_elements()
+ {
+ return evaluate().begin_elements();
+ }
+
+ const_array_iterator begin_elements() const
+ {
+ return evaluate().begin_elements();
+ }
+
+ array_iterator end_elements()
+ {
+ return evaluate().end_elements();
+ }
+
+ const_array_iterator end_elements() const
+ {
+ return evaluate().end_elements();
+ }
+
+ const basic_json<CharT,Alloc>& 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<CharT,Alloc>& value)
+ {
+ evaluate_with_default().add(index, value);
+ }
+
+ void add(size_t index, basic_json<CharT,Alloc>&& 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<char_type>& is);
+ static basic_json parse_stream(std::basic_istream<char_type>& is, basic_parse_error_handler<char_type>& err_handler);
+
+ static basic_json parse(const string_type& s)
+ {
+ basic_json_deserializer<basic_json<CharT, Alloc>> handler;
+ basic_json_parser<char_type> 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<char_type>& err_handler)
+ {
+ basic_json_deserializer<basic_json<CharT, Alloc>> handler;
+ basic_json_parser<char_type> 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<char_type>& 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 <class T>
+ 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 <size_t dim>
+ static typename std::enable_if<dim==1,basic_json>::type make_array(size_t n)
+ {
+ return array(n);
+ }
+
+ template <size_t dim, class T>
+ static typename std::enable_if<dim==1,basic_json>::type make_array(size_t n, const T& val, const Alloc& allocator = Alloc())
+ {
+ return array(n,val,allocator);
+ }
+
+ template <size_t dim, typename... Args>
+ static typename std::enable_if<(dim>1),basic_json>::type make_array(size_t n, Args... args)
+ {
+ const size_t dim1 = dim - 1;
+
+ basic_json val = make_array<dim1>(args...);
+ val.resize(n);
+ for (size_t i = 0; i < n; ++i)
+ {
+ val[i] = make_array<dim1>(args...);
+ }
+ return val;
+ }
+
+ variant var_;
+
+ basic_json()
+ : var_()
+ {
+ }
+
+ basic_json(const Alloc& allocator)
+ : var_(allocator)
+ {
+ }
+
+ basic_json(std::initializer_list<value_type> init,
+ const Alloc& allocator = Alloc())
+ : var_(std::move(init), allocator)
+ {
+ }
+
+ basic_json(const basic_json<CharT, Alloc>& val)
+ : var_(val.var_)
+ {
+ }
+
+ basic_json(const basic_json<CharT, Alloc>& val, const Alloc& allocator)
+ : var_(val.var_,allocator)
+ {
+ }
+
+ basic_json(basic_json<CharT,Alloc>&& other)
+ : var_(std::move(other.var_))
+ {
+ }
+
+ basic_json(basic_json<CharT,Alloc>&& 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 <class ParentT>
+ basic_json(const json_proxy<ParentT>& proxy, const Alloc& allocator = Alloc())
+ : var_(proxy.evaluate().var_,allocator)
+ {
+ }
+
+ template <typename T>
+ basic_json(T val)
+ : var_(null_type())
+ {
+ json_type_traits<value_type,T>::assign(*this,val);
+ }
+
+ basic_json(double val, uint8_t precision)
+ : var_(val,precision)
+ {
+ }
+
+ template <typename T>
+ basic_json(T val, const Alloc& allocator)
+ : var_(allocator)
+ {
+ json_type_traits<value_type,T>::assign(*this,val);
+ }
+
+ basic_json(const char_type *s, size_t length, const Alloc& allocator = Alloc())
+ : var_(s, length, allocator)
+ {
+ }
+ template<class InputIterator>
+ basic_json(InputIterator first, InputIterator last, const Alloc& allocator = Alloc())
+ : var_(first,last,allocator)
+ {
+ }
+
+ ~basic_json()
+ {
+ }
+
+ basic_json& operator=(const basic_json<CharT,Alloc>& rhs)
+ {
+ var_ = rhs.var_;
+ return *this;
+ }
+
+ basic_json& operator=(basic_json<CharT,Alloc>&& rhs)
+ {
+ if (this != &rhs)
+ {
+ var_ = std::move(rhs.var_);
+ }
+ return *this;
+ }
+
+ basic_json& operator=(std::initializer_list<value_type> init)
+ {
+ basic_json<CharT,Alloc> val(init);
+ swap(val);
+ return *this;
+ }
+
+ template <class T>
+ basic_json<CharT, Alloc>& operator=(T val)
+ {
+ json_type_traits<value_type,T>::assign(*this,val);
+ return *this;
+ }
+
+ bool operator!=(const basic_json<CharT,Alloc>& rhs) const;
+
+ bool operator==(const basic_json<CharT,Alloc>& 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<CharT,Alloc>& operator[](size_t i)
+ {
+ return at(i);
+ }
+
+ const basic_json<CharT,Alloc>& operator[](size_t i) const
+ {
+ return at(i);
+ }
+
+ json_proxy<basic_json<CharT, Alloc>> 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<basic_json<CharT,Alloc>>(*this, name);
+ break;
+ default:
+ JSONCONS_THROW_EXCEPTION(std::runtime_error,"Not an object");
+ break;
+ }
+ }
+
+ const basic_json<CharT,Alloc>& 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<char_type,char_traits_type,string_allocator> os(s);
+ {
+ basic_json_serializer<char_type> serializer(os);
+ to_stream(serializer);
+ }
+ return os.str();
+ }
+
+ string_type to_string(const basic_output_format<char_type>& format,
+ const string_allocator& allocator=string_allocator()) const
+ {
+ string_type s(allocator);
+ std::basic_ostringstream<char_type> os(s);
+ {
+ basic_json_serializer<char_type> serializer(os, format);
+ to_stream(serializer);
+ }
+ return os.str();
+ }
+
+ void to_stream(basic_json_output_handler<char_type>& 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<char_type>& os) const
+ {
+ basic_json_serializer<char_type> serializer(os);
+ to_stream(serializer);
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os, const basic_output_format<char_type>& format) const
+ {
+ basic_json_serializer<char_type> serializer(os, format);
+ to_stream(serializer);
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os, const basic_output_format<char_type>& format, bool indenting) const
+ {
+ basic_json_serializer<char_type> 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<typename T>
+ bool is() const
+ {
+ return json_type_traits<value_type,T>::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<unsigned long long>(std::numeric_limits<long long>::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<class U=Alloc,
+ typename std::enable_if<std::is_default_constructible<U>::value
+ >::type* = nullptr>
+ void create_object_implicitly()
+ {
+ var_.type_ = value_types::object_t;
+ var_.value_.object_val_ = create_impl<object>(Alloc(),object_allocator(Alloc()));
+ }
+
+ template<class U=Alloc,
+ typename std::enable_if<!std::is_default_constructible<U>::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 <typename T>
+ 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<typename T>
+ T as() const
+ {
+ return json_type_traits<value_type,T>::as(*this);
+ }
+
+ template<typename T>
+ typename std::enable_if<std::is_same<string_type,T>::value>::type as(const string_allocator& allocator) const
+ {
+ return json_type_traits<value_type,T>::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<int64_t>(var_.value_.double_val_);
+ case value_types::integer_t:
+ return static_cast<int64_t>(var_.value_.integer_val_);
+ case value_types::uinteger_t:
+ return static_cast<int64_t>(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<uint64_t>(var_.value_.double_val_);
+ case value_types::integer_t:
+ return static_cast<uint64_t>(var_.value_.integer_val_);
+ case value_types::uinteger_t:
+ return static_cast<uint64_t>(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<double>(var_.value_.integer_val_);
+ case value_types::uinteger_t:
+ return static_cast<double>(var_.value_.uinteger_val_);
+ case value_types::null_t:
+ return std::numeric_limits<double>::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<char_type>& 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<char_type>& 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<CharT, Alloc>& 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<CharT, Alloc>& evaluate()
+ {
+ return *this;
+ }
+
+ basic_json<CharT, Alloc>& evaluate_with_default()
+ {
+ return *this;
+ }
+
+ const basic_json<CharT, Alloc>& evaluate() const
+ {
+ return *this;
+ }
+
+ basic_json<CharT, Alloc>& evaluate(size_t i)
+ {
+ return at(i);
+ }
+
+ const basic_json<CharT, Alloc>& evaluate(size_t i) const
+ {
+ return at(i);
+ }
+
+ basic_json<CharT, Alloc>& evaluate(const string_type& name)
+ {
+ return at(name);
+ }
+
+ const basic_json<CharT, Alloc>& evaluate(const string_type& name) const
+ {
+ return at(name);
+ }
+
+ const basic_json<CharT, Alloc>& 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<CharT, Alloc>& 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<CharT, Alloc>& 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<char_type>::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<char_type>::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<typename T>
+ basic_json<CharT, Alloc> get(const string_type& name, T&& default_val) const
+ {
+ switch (var_.type_)
+ {
+ case value_types::empty_object_t:
+ {
+ return basic_json<CharT,Alloc>(std::forward<T>(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<CharT,Alloc>(std::forward<T>(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<CharT, Alloc>& 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<CharT, Alloc>& 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<CharT, Alloc>&& 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<CharT, Alloc>&& 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<CharT, Alloc>& 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<CharT, Alloc>& 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<CharT, Alloc>&& 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<CharT, Alloc>&& 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<CharT, Alloc>& 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<CharT, Alloc>&& 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<CharT, Alloc>& 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<CharT, Alloc>&& 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<CharT,Alloc>& b)
+ {
+ var_.swap(b.var_);
+ }
+
+ template <class T>
+ std::vector<T> as_vector() const
+ {
+ std::vector<T> v(size());
+ for (size_t i = 0; i < v.size(); ++i)
+ {
+ v[i] = json_type_traits<value_type,T>::as(at(i));
+ }
+ return v;
+ }
+
+ friend void swap(basic_json<CharT,Alloc>& a, basic_json<CharT,Alloc>& b)
+ {
+ a.swap(b);
+ }
+
+ void assign_any(const typename basic_json<CharT,Alloc>::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 <typename T>
+ 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<T>();
+ }
+ template <typename T>
+ 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<T>();
+ }
+
+ 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 <typename T>
+ 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 <typename T>
+ 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<char_type>& is)
+ {
+ return parse_stream(is);
+ }
+ static basic_json parse(std::basic_istream<char_type>& is, basic_parse_error_handler<char_type>& 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<char_type>& err_handler)
+ {
+ return parse(s,err_handler);
+ }
+
+ void resize_array(size_t n)
+ {
+ resize(n);
+ }
+
+ template <typename T>
+ 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<CharT,Alloc>& get(const string_type& name) const
+ {
+ static const basic_json<CharT, Alloc> 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<int>(var_.value_.double_val_);
+ case value_types::integer_t:
+ return static_cast<int>(var_.value_.integer_val_);
+ case value_types::uinteger_t:
+ return static_cast<int>(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<unsigned int>(var_.value_.double_val_);
+ case value_types::integer_t:
+ return static_cast<unsigned int>(var_.value_.integer_val_);
+ case value_types::uinteger_t:
+ return static_cast<unsigned int>(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<long>(var_.value_.double_val_);
+ case value_types::integer_t:
+ return static_cast<long>(var_.value_.integer_val_);
+ case value_types::uinteger_t:
+ return static_cast<long>(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<unsigned long>(var_.value_.double_val_);
+ case value_types::integer_t:
+ return static_cast<unsigned long>(var_.value_.integer_val_);
+ case value_types::uinteger_t:
+ return static_cast<unsigned long>(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<CharT, Alloc>& 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<CharT, Alloc>&& 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<int size>
+ static typename std::enable_if<size==1,basic_json>::type make_multi_array()
+ {
+ return make_array();
+ }
+ template<size_t size>
+ static typename std::enable_if<size==1,basic_json>::type make_multi_array(size_t n)
+ {
+ return make_array(n);
+ }
+ template<size_t size,typename T>
+ static typename std::enable_if<size==1,basic_json>::type make_multi_array(size_t n, T val)
+ {
+ return make_array(n,val);
+ }
+ template<size_t size>
+ static typename std::enable_if<size==2,basic_json>::type make_multi_array(size_t m, size_t n)
+ {
+ return make_array<2>(m, n);
+ }
+ template<size_t size,typename T>
+ static typename std::enable_if<size==2,basic_json>::type make_multi_array(size_t m, size_t n, T val)
+ {
+ return make_array<2>(m, n, val);
+ }
+ template<size_t size>
+ static typename std::enable_if<size==3,basic_json>::type make_multi_array(size_t m, size_t n, size_t k)
+ {
+ return make_array<3>(m, n, k);
+ }
+ template<size_t size,typename T>
+ static typename std::enable_if<size==3,basic_json>::type make_multi_array(size_t m, size_t n, size_t k, T val)
+ {
+ return make_array<3>(m, n, k, val);
+ }
+#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<value_type*>(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<typename string_type::value_type>& operator<<(std::basic_ostream<typename string_type::value_type>& os, const basic_json<CharT, Alloc>& o)
+ {
+ o.to_stream(os);
+ return os;
+ }
+
+ friend std::basic_istream<typename string_type::value_type>& operator<<(std::basic_istream<typename string_type::value_type>& is, basic_json<CharT, Alloc>& o)
+ {
+ basic_json_deserializer<basic_json<CharT, Alloc>> handler;
+ basic_json_reader<typename string_type::value_type> 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 JsonT>
+void swap(typename JsonT::member_type& a, typename JsonT::member_type& b)
+{
+ a.swap(b);
+}
+
+template<typename CharT, typename Alloc>
+bool basic_json<CharT, Alloc>::operator!=(const basic_json<CharT, Alloc>& rhs) const
+{
+ return !(*this == rhs);
+}
+
+template<typename CharT, typename Alloc>
+bool basic_json<CharT, Alloc>::operator==(const basic_json<CharT, Alloc>& rhs) const
+{
+ return var_ == rhs.var_;
+}
+
+template<typename CharT, typename Alloc>
+basic_json<CharT, Alloc> basic_json<CharT, Alloc>::make_2d_array(size_t m, size_t n)
+{
+ basic_json<CharT, Alloc> a = basic_json<CharT, Alloc>::array();
+ a.resize(m);
+ for (size_t i = 0; i < a.size(); ++i)
+ {
+ a[i] = basic_json<CharT, Alloc>::make_array(n);
+ }
+ return a;
+}
+
+template<typename CharT, typename Alloc>
+template<typename T>
+basic_json<CharT, Alloc> basic_json<CharT, Alloc>::make_2d_array(size_t m, size_t n, T val)
+{
+ basic_json<CharT, Alloc> v;
+ v = val;
+ basic_json<CharT, Alloc> a = make_array(m);
+ for (size_t i = 0; i < a.size(); ++i)
+ {
+ a[i] = basic_json<CharT, Alloc>::make_array(n, v);
+ }
+ return a;
+}
+
+template<typename CharT, typename Alloc>
+basic_json<CharT, Alloc> basic_json<CharT, Alloc>::make_3d_array(size_t m, size_t n, size_t k)
+{
+ basic_json<CharT, Alloc> a = basic_json<CharT, Alloc>::array();
+ a.resize(m);
+ for (size_t i = 0; i < a.size(); ++i)
+ {
+ a[i] = basic_json<CharT, Alloc>::make_2d_array(n, k);
+ }
+ return a;
+}
+
+template<typename CharT, typename Alloc>
+template<typename T>
+basic_json<CharT, Alloc> basic_json<CharT, Alloc>::make_3d_array(size_t m, size_t n, size_t k, T val)
+{
+ basic_json<CharT, Alloc> v;
+ v = val;
+ basic_json<CharT, Alloc> a = make_array(m);
+ for (size_t i = 0; i < a.size(); ++i)
+ {
+ a[i] = basic_json<CharT, Alloc>::make_2d_array(n, k, v);
+ }
+ return a;
+}
+
+template<typename CharT, typename Alloc>
+basic_json<CharT, Alloc> basic_json<CharT, Alloc>::parse_stream(std::basic_istream<char_type>& is)
+{
+ basic_json_deserializer<basic_json<CharT, Alloc>> handler;
+ basic_json_reader<char_type> 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<typename CharT, typename Alloc>
+basic_json<CharT, Alloc> basic_json<CharT, Alloc>::parse_stream(std::basic_istream<char_type>& is,
+ basic_parse_error_handler<char_type>& err_handler)
+{
+ basic_json_deserializer<basic_json<CharT, Alloc>> handler;
+ basic_json_reader<char_type> 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<typename CharT, typename Alloc>
+basic_json<CharT, Alloc> basic_json<CharT, Alloc>::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<basic_json<CharT, Alloc>> handler;
+ try
+ {
+ // obtain file size:
+ std::fseek (fp , 0 , SEEK_END);
+ long size = std::ftell (fp);
+ std::rewind(fp);
+
+ if (size > 0)
+ {
+ std::vector<char_type> buffer(size);
+
+ // copy the file into the buffer:
+ size_t result = std::fread (buffer.data(),1,size,fp);
+ if (result != static_cast<unsigned long long>(size))
+ {
+ JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Error reading file %s", filename);
+ }
+
+ basic_json_parser<char_type> 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<typename CharT, typename Alloc>
+basic_json<CharT, Alloc> basic_json<CharT, Alloc>::parse_file(const std::string& filename,
+ basic_parse_error_handler<char_type>& 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<basic_json<CharT, Alloc>> handler;
+ try
+ {
+ // obtain file size:
+ std::fseek (fp , 0 , SEEK_END);
+ long size = std::ftell (fp);
+ std::rewind(fp);
+
+ if (size > 0)
+ {
+ std::vector<char_type> buffer(size);
+
+ // copy the file into the buffer:
+ size_t result = std::fread (buffer.data(),1,size,fp);
+ if (result != static_cast<unsigned long long>(size))
+ {
+ JSONCONS_THROW_EXCEPTION_1(std::runtime_error,"Error reading file %s", filename);
+ }
+
+ basic_json_parser<char_type> 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 CharT, typename Alloc>
+typename basic_json<CharT, Alloc>::any& basic_json<CharT, Alloc>::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<typename CharT, typename Alloc>
+const typename basic_json<CharT, Alloc>::any& basic_json<CharT, Alloc>::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 <typename JsonT>
+std::basic_istream<typename JsonT::char_type>& operator>>(std::basic_istream<typename JsonT::char_type>& is, JsonT& o)
+{
+ basic_json_deserializer<JsonT> handler;
+ basic_json_reader<typename JsonT::char_type> 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<typename JsonT>
+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<char_type>& format)
+ : o_(&o), is_pretty_print_(is_pretty_print), format_(format)
+ {
+ ;
+ }
+
+ void to_stream(std::basic_ostream<char_type>& os) const
+ {
+ o_->to_stream(os, format_, is_pretty_print_);
+ }
+
+ friend std::basic_ostream<char_type>& operator<<(std::basic_ostream<char_type>& os, const json_printable<JsonT>& o)
+ {
+ o.to_stream(os);
+ return os;
+ }
+
+ const JsonT *o_;
+ bool is_pretty_print_;
+ basic_output_format<char_type> format_;
+private:
+ json_printable();
+};
+
+template<typename JsonT>
+json_printable<JsonT> print(const JsonT& val)
+{
+ return json_printable<JsonT>(val,false);
+}
+
+template<class JsonT>
+json_printable<JsonT> print(const JsonT& val,
+ const basic_output_format<typename JsonT::char_type>& format)
+{
+ return json_printable<JsonT>(val, false, format);
+}
+
+template<class JsonT>
+json_printable<JsonT> pretty_print(const JsonT& val)
+{
+ return json_printable<JsonT>(val,true);
+}
+
+template<typename JsonT>
+json_printable<JsonT> pretty_print(const JsonT& val,
+ const basic_output_format<typename JsonT::char_type>& format)
+{
+ return json_printable<JsonT>(val, true, format);
+}
+
+typedef basic_json<char,std::allocator<char>> json;
+typedef basic_json<wchar_t,std::allocator<wchar_t>> wjson;
+
+typedef basic_json_deserializer<json> json_deserializer;
+typedef basic_json_deserializer<wjson> 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 <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <memory>
+#include "jsoncons/jsoncons.hpp"
+#include "jsoncons/json_input_handler.hpp"
+
+namespace jsoncons {
+
+template <class JsonT>
+class basic_json_deserializer : public basic_json_input_handler<typename JsonT::char_type>
+{
+ 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_item> stack_;
+ std::vector<size_t> 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<char_type>&) override
+ {
+ push_object();
+ }
+
+ void do_end_object(const basic_parsing_context<char_type>&) override
+ {
+ end_structure();
+ pop_object();
+ }
+
+ void do_begin_array(const basic_parsing_context<char_type>&) override
+ {
+ push_array();
+ }
+
+ void do_end_array(const basic_parsing_context<char_type>&) 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<char_type>&) override
+ {
+ stack_[top_].name_ = string_type(p,length,sa_);
+ }
+
+ void do_string_value(const char_type* p, size_t length, const basic_parsing_context<char_type>&) 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<char_type>&) override
+ {
+ stack_[top_].value_ = value;
+ if (++top_ >= stack_.size())
+ {
+ stack_.resize(top_*2);
+ }
+ }
+
+ void do_uinteger_value(uint64_t value, const basic_parsing_context<char_type>&) 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<char_type>&) 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<char_type>&) override
+ {
+ stack_[top_].value_ = value;
+ if (++top_ >= stack_.size())
+ {
+ stack_.resize(top_*2);
+ }
+ }
+
+ void do_null_value(const basic_parsing_context<char_type>&) 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 <system_error>
+
+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 <string>
+
+#include "jsoncons/json_input_handler.hpp"
+#include "jsoncons/json_output_handler.hpp"
+#include "jsoncons/parse_error_handler.hpp"
+
+namespace jsoncons {
+
+template <typename CharT>
+class basic_json_input_output_adapter : public basic_json_input_handler<CharT>
+{
+public:
+ basic_json_input_output_adapter()
+ : writer_(std::addressof(null_json_output_handler<CharT>()))
+ {
+ }
+
+ basic_json_input_output_adapter(basic_json_output_handler<CharT>& 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<CharT>& context) override
+ {
+ writer_->begin_object();
+ }
+
+ void do_end_object(const basic_parsing_context<CharT>& context) override
+ {
+ writer_->end_object();
+ }
+
+ void do_begin_array(const basic_parsing_context<CharT>& context) override
+ {
+ writer_->begin_array();
+ }
+
+ void do_end_array(const basic_parsing_context<CharT>& context) override
+ {
+ writer_->end_array();
+ }
+
+ void do_name(const CharT* name, size_t length,
+ const basic_parsing_context<CharT>& context) override
+ {
+ writer_->name(name, length);
+ }
+
+ void do_string_value(const CharT* value, size_t length,
+ const basic_parsing_context<CharT>& context) override
+ {
+ writer_->value(value, length);
+ }
+
+ void do_integer_value(int64_t value, const basic_parsing_context<CharT>& context) override
+ {
+ writer_->value(value);
+ }
+
+ void do_uinteger_value(uint64_t value,
+ const basic_parsing_context<CharT>& context) override
+ {
+ writer_->value(value);
+ }
+
+ void do_double_value(double value, uint8_t precision, const basic_parsing_context<CharT>& context) override
+ {
+ writer_->value(value, precision);
+ }
+
+ void do_bool_value(bool value, const basic_parsing_context<CharT>& context) override
+ {
+ writer_->value(value);
+ }
+
+ void do_null_value(const basic_parsing_context<CharT>& context) override
+ {
+ writer_->value(null_type());
+ }
+
+ basic_json_output_handler<CharT>* writer_;
+};
+
+template <typename CharT>
+class basic_json_filter : public basic_json_input_handler<CharT>
+{
+public:
+ basic_json_filter(basic_json_input_handler<CharT>& handler)
+ : handler_(std::addressof(handler)),
+ err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance()))
+ {
+ }
+
+ basic_json_filter(basic_json_input_handler<CharT>& handler,
+ basic_parse_error_handler<CharT>& err_handler)
+ : handler_(std::addressof(handler)),
+ err_handler_(std::addressof(err_handler))
+ {
+ }
+
+ basic_json_filter(basic_json_output_handler<CharT>& output_handler)
+ : input_output_adapter_(output_handler), handler_(std::addressof(input_output_adapter_)),
+ err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance()))
+ {
+ }
+
+ basic_json_filter(basic_json_output_handler<CharT>& output_handler,
+ basic_parse_error_handler<CharT>& err_handler)
+ : input_output_adapter_(output_handler), handler_(std::addressof(input_output_adapter_)),
+ err_handler_(std::addressof(err_handler))
+ {
+ }
+
+ basic_json_input_handler<CharT>& input_handler()
+ {
+ return *handler_;
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+ basic_json_input_handler<CharT>& 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<CharT>& context) override
+ {
+ handler_->begin_object(context);
+ }
+
+ void do_end_object(const basic_parsing_context<CharT>& context) override
+ {
+ handler_->end_object(context);
+ }
+
+ void do_begin_array(const basic_parsing_context<CharT>& context) override
+ {
+ handler_->begin_array(context);
+ }
+
+ void do_end_array(const basic_parsing_context<CharT>& context) override
+ {
+ handler_->end_array(context);
+ }
+
+ void do_name(const CharT* name, size_t length, const basic_parsing_context<CharT>& context) override
+ {
+ handler_->name(name, length, context);
+ }
+
+ void do_string_value(const CharT* value, size_t length, const basic_parsing_context<CharT>& context) override
+ {
+ handler_->value(value,length,context);
+ }
+
+ void do_double_value(double value, uint8_t precision, const basic_parsing_context<CharT>& context) override
+ {
+ handler_->value(value,precision,context);
+ }
+
+ void do_integer_value(int64_t value, const basic_parsing_context<CharT>& context) override
+ {
+ handler_->value(value,context);
+ }
+
+ void do_uinteger_value(uint64_t value, const basic_parsing_context<CharT>& context) override
+ {
+ handler_->value(value,context);
+ }
+
+ void do_bool_value(bool value, const basic_parsing_context<CharT>& context) override
+ {
+ handler_->value(value,context);
+ }
+
+ void do_null_value(const basic_parsing_context<CharT>& context) override
+ {
+ handler_->value(null_type(),context);
+ }
+
+ basic_json_input_output_adapter<CharT> input_output_adapter_;
+ basic_json_input_handler<CharT>* handler_;
+ basic_parse_error_handler<CharT>* err_handler_;
+};
+
+// Filters out begin_json and end_json events
+template <typename CharT>
+class basic_begin_end_json_filter : public basic_json_filter<CharT>
+{
+public:
+ basic_begin_end_json_filter(basic_json_input_handler<CharT>& handler)
+ : basic_json_filter<CharT>(handler)
+ {
+ }
+private:
+ void do_begin_json() override
+ {
+ }
+
+ void do_end_json() override
+ {
+ }
+};
+
+template <typename CharT>
+class basic_json_output_input_adapter : public basic_json_output_handler<CharT>
+{
+public:
+ basic_json_output_input_adapter(basic_json_input_handler<CharT>& input_handler,
+ const basic_parsing_context<CharT>& 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<CharT>* input_handler_;
+ const basic_parsing_context<CharT>* context_;
+};
+
+typedef basic_json_filter<char> json_filter;
+typedef basic_json_filter<wchar_t> 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 <string>
+#include "jsoncons/jsoncons.hpp"
+
+namespace jsoncons {
+
+template<typename CharT>
+uint64_t string_to_uinteger(const CharT *s, size_t length) throw(std::overflow_error)
+{
+ static const uint64_t max_value = std::numeric_limits<uint64_t>::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<typename CharT>
+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<int64_t>::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 <typename CharT>
+class basic_parsing_context;
+
+template <typename CharT>
+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<CharT>& context)
+ {
+ do_begin_object(context);
+ }
+
+ void end_object(const basic_parsing_context<CharT>& context)
+ {
+ do_end_object(context);
+ }
+
+ void begin_array(const basic_parsing_context<CharT>& context)
+ {
+ do_begin_array(context);
+ }
+
+ void end_array(const basic_parsing_context<CharT>& context)
+ {
+ do_end_array(context);
+ }
+
+ void name(const std::basic_string<CharT>& name, const basic_parsing_context<CharT>& context)
+ {
+ do_name(name.data(), name.length(), context);
+ }
+
+ void name(const CharT* p, size_t length, const basic_parsing_context<CharT>& context)
+ {
+ do_name(p, length, context);
+ }
+
+ void value(const std::basic_string<CharT>& value, const basic_parsing_context<CharT>& context)
+ {
+ do_string_value(value.data(), value.length(), context);
+ }
+
+ void value(const CharT* p, size_t length, const basic_parsing_context<CharT>& context)
+ {
+ do_string_value(p, length, context);
+ }
+
+ void value(const CharT* p, const basic_parsing_context<CharT>& context)
+ {
+ do_string_value(p, std::char_traits<CharT>::length(p), context);
+ }
+
+ void value(int value, const basic_parsing_context<CharT>& context)
+ {
+ do_integer_value(value,context);
+ }
+
+ void value(long value, const basic_parsing_context<CharT>& context)
+ {
+ do_integer_value(value,context);
+ }
+
+ void value(long long value, const basic_parsing_context<CharT>& context)
+ {
+ do_integer_value(value,context);
+ }
+
+ void value(unsigned int value, const basic_parsing_context<CharT>& context)
+ {
+ do_uinteger_value(value,context);
+ }
+
+ void value(unsigned long value, const basic_parsing_context<CharT>& context)
+ {
+ do_uinteger_value(value,context);
+ }
+
+ void value(unsigned long long value, const basic_parsing_context<CharT>& context)
+ {
+ do_uinteger_value(value,context);
+ }
+
+ void value(float value, uint8_t precision, const basic_parsing_context<CharT>& context)
+ {
+ do_double_value(value, precision, context);
+ }
+
+ void value(double value, uint8_t precision, const basic_parsing_context<CharT>& context)
+ {
+ do_double_value(value, precision, context);
+ }
+
+ void value(bool value, const basic_parsing_context<CharT>& context)
+ {
+ do_bool_value(value,context);
+ }
+
+ void value(null_type, const basic_parsing_context<CharT>& 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<CharT>& context) = 0;
+
+ virtual void do_end_object(const basic_parsing_context<CharT>& context) = 0;
+
+ virtual void do_begin_array(const basic_parsing_context<CharT>& context) = 0;
+
+ virtual void do_end_array(const basic_parsing_context<CharT>& context) = 0;
+
+ virtual void do_name(const CharT* name, size_t length, const basic_parsing_context<CharT>& context) = 0;
+
+ virtual void do_null_value(const basic_parsing_context<CharT>& context) = 0;
+
+ virtual void do_string_value(const CharT* value, size_t length, const basic_parsing_context<CharT>& context) = 0;
+
+ virtual void do_double_value(double value, uint8_t precision, const basic_parsing_context<CharT>& context) = 0;
+
+ virtual void do_integer_value(int64_t value, const basic_parsing_context<CharT>& context) = 0;
+
+ virtual void do_uinteger_value(uint64_t value, const basic_parsing_context<CharT>& context) = 0;
+
+ virtual void do_bool_value(bool value, const basic_parsing_context<CharT>& context) = 0;
+};
+
+
+template <typename CharT>
+class basic_empty_json_input_handler : public basic_json_input_handler<CharT>
+{
+public:
+ static basic_json_input_handler<CharT>& instance()
+ {
+ static basic_empty_json_input_handler<CharT> instance;
+ return instance;
+ }
+private:
+ void do_begin_json() override
+ {
+ }
+
+ void do_end_json() override
+ {
+ }
+
+ void do_begin_object(const basic_parsing_context<CharT>&) override
+ {
+ }
+
+ void do_end_object(const basic_parsing_context<CharT>&) override
+ {
+ }
+
+ void do_begin_array(const basic_parsing_context<CharT>&) override
+ {
+ }
+
+ void do_end_array(const basic_parsing_context<CharT>&) override
+ {
+ }
+
+ void do_name(const CharT* p, size_t length, const basic_parsing_context<CharT>&) override
+ {
+ (void)p;
+ (void)length;
+ }
+
+ void do_null_value(const basic_parsing_context<CharT>&) override
+ {
+ }
+
+ void do_string_value(const CharT* p, size_t length, const basic_parsing_context<CharT>&) override
+ {
+ (void)p;
+ (void)length;
+ }
+
+ void do_double_value(double, uint8_t, const basic_parsing_context<CharT>&) override
+ {
+ }
+
+ void do_integer_value(int64_t, const basic_parsing_context<CharT>&) override
+ {
+ }
+
+ void do_uinteger_value(uint64_t, const basic_parsing_context<CharT>&) override
+ {
+ }
+
+ void do_bool_value(bool, const basic_parsing_context<CharT>&) override
+ {
+ }
+};
+
+typedef basic_json_input_handler<char> json_input_handler;
+typedef basic_json_input_handler<wchar_t> wjson_input_handler;
+
+typedef basic_empty_json_input_handler<char> empty_json_input_handler;
+typedef basic_empty_json_input_handler<wchar_t> 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 <string>
+#include "jsoncons/jsoncons.hpp"
+
+namespace jsoncons {
+
+template<typename CharT>
+void print_integer(int64_t value, buffered_ostream<CharT>& os)
+{
+ CharT buf[255];
+ uint64_t u = (value < 0) ? static_cast<uint64_t>(-value) : static_cast<uint64_t>(value);
+ CharT* p = buf;
+ do
+ {
+ *p++ = static_cast<CharT>(48 + u%10);
+ }
+ while (u /= 10);
+ if (value < 0)
+ {
+ os.put('-');
+ }
+ while (--p >= buf)
+ {
+ os.put(*p);
+ }
+}
+
+template<typename CharT>
+void print_uinteger(uint64_t value, buffered_ostream<CharT>& os)
+{
+ CharT buf[255];
+ CharT* p = buf;
+ do
+ {
+ *p++ = static_cast<CharT>(48 + value % 10);
+ } while (value /= 10);
+ while (--p >= buf)
+ {
+ os.put(*p);
+ }
+}
+
+template <typename CharT>
+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<CharT>& 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<CharT>& 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<CharT>::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 <typename CharT>
+class null_json_output_handler_impl : public basic_json_output_handler<CharT>
+{
+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<typename CharT>
+basic_json_output_handler<CharT>& null_json_output_handler()
+{
+ static null_json_output_handler_impl<CharT> instance;
+ return instance;
+}
+
+typedef basic_json_output_handler<char> json_output_handler;
+typedef basic_json_output_handler<wchar_t> wjson_output_handler;
+
+}
+#endif
diff --git a/vendor/jsoncons-0.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 <memory>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <stdexcept>
+#include <system_error>
+#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<typename CharT>
+class basic_json_parser : private basic_parsing_context<CharT>
+{
+ static const int default_initial_stack_capacity_ = 100;
+
+ std::vector<states> stack_;
+ basic_json_input_handler<CharT> *handler_;
+ basic_parse_error_handler<CharT> *err_handler_;
+ size_t column_;
+ size_t line_;
+ uint32_t cp_;
+ uint32_t cp2_;
+ std::basic_string<CharT> string_buffer_;
+ std::basic_string<char> 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<const CharT*,size_t> literal_;
+ size_t literal_index_;
+
+public:
+ basic_json_parser(basic_json_input_handler<CharT>& handler)
+ : handler_(std::addressof(handler)),
+ err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance())),
+ column_(0),
+ line_(0),
+ cp_(0),
+ is_negative_(false),
+ index_(0),
+ initial_stack_capacity_(default_initial_stack_capacity_)
+ {
+ max_depth_ = std::numeric_limits<int>::max JSONCONS_NO_MACRO_EXP();
+ }
+
+ basic_json_parser(basic_json_input_handler<CharT>& handler,
+ basic_parse_error_handler<CharT>& 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<int>::max JSONCONS_NO_MACRO_EXP();
+ }
+
+ const basic_parsing_context<CharT>& parsing_context() const
+ {
+ return *this;
+ }
+
+ ~basic_json_parser()
+ {
+ }
+
+ size_t max_nesting_depth() const
+ {
+ return static_cast<size_t>(max_depth_);
+ }
+
+ void max_nesting_depth(size_t max_nesting_depth)
+ {
+ max_depth_ = static_cast<int>(std::min(max_nesting_depth,static_cast<size_t>(std::numeric_limits<int>::max 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<char>(*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<char>(*p_));
+ stack_.back() = states::integer;
+ break;
+ case 'f':
+ handler_->begin_json();
+ stack_.back() = states::f;
+ literal_ = json_literals<CharT>::false_literal();
+ literal_index_ = 1;
+ break;
+ case 'n':
+ handler_->begin_json();
+ stack_.back() = states::n;
+ literal_ = json_literals<CharT>::null_literal();
+ literal_index_ = 1;
+ break;
+ case 't':
+ handler_->begin_json();
+ stack_.back() = states::t;
+ literal_ = json_literals<CharT>::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<char>(*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<char>(*p_));
+ stack_.back() = states::integer;
+ break;
+ case 'f':
+ stack_.back() = states::f;
+ literal_ = json_literals<CharT>::false_literal();
+ literal_index_ = 1;
+ break;
+ case 'n':
+ stack_.back() = states::n;
+ literal_ = json_literals<CharT>::null_literal();
+ literal_index_ = 1;
+ break;
+ case 't':
+ stack_.back() = states::t;
+ literal_ = json_literals<CharT>::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<char>(*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<char>(*p_));
+ stack_.back() = states::integer;
+ break;
+ case 'f':
+ stack_.back() = states::f;
+ literal_ = json_literals<CharT>::false_literal();
+ literal_index_ = 1;
+ break;
+ case 'n':
+ stack_.back() = states::n;
+ literal_ = json_literals<CharT>::null_literal();
+ literal_index_ = 1;
+ break;
+ case 't':
+ stack_.back() = states::t;
+ literal_ = json_literals<CharT>::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<CharT, sizeof(CharT)>::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<CharT, sizeof(CharT)>::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<char>(*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<char>(*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<uint8_t>(number_buffer_.length());
+ number_buffer_.push_back(static_cast<char>(*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<char>(*p_));
+ stack_.back() = states::integer;
+ break;
+ case '.':
+ precision_ = static_cast<uint8_t>(number_buffer_.length());
+ number_buffer_.push_back(static_cast<char>(*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<char>(*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<char>(*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<char>(*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<char>(*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<char>(*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<char>(*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<char>(*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<uint8_t>(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<uint8_t>(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<uint8_t>(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<char> json_parser;
+typedef basic_json_parser<wchar_t> 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 <memory>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <stdexcept>
+#include <system_error>
+#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<typename CharT>
+class basic_json_parser : private basic_parsing_context<CharT>
+{
+ static const int default_depth = 100;
+
+ std::vector<states> state_stack_;
+ int top_;
+ std::vector<modes> stack_;
+ basic_json_input_handler<CharT> *handler_;
+ basic_parse_error_handler<CharT> *err_handler_;
+ size_t column_;
+ size_t line_;
+ uint32_t cp_;
+ uint32_t cp2_;
+ std::basic_string<CharT> string_buffer_;
+ std::basic_string<char> 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<const CharT*,size_t> literal_;
+ size_t literal_index_;
+
+ std::vector<states> stack2_;
+
+public:
+ basic_json_parser(basic_json_input_handler<CharT>& handler)
+ : top_(-1),
+ stack_(default_depth),
+ handler_(std::addressof(handler)),
+ err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance())),
+ column_(0),
+ line_(0),
+ cp_(0),
+ is_negative_(false),
+ index_(0),
+ depth_(default_depth)
+ {
+ max_depth_ = std::numeric_limits<int>::max JSONCONS_NO_MACRO_EXP();
+ }
+
+ basic_json_parser(basic_json_input_handler<CharT>& handler,
+ basic_parse_error_handler<CharT>& 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<int>::max JSONCONS_NO_MACRO_EXP();
+ }
+
+ const basic_parsing_context<CharT>& parsing_context() const
+ {
+ return *this;
+ }
+
+ ~basic_json_parser()
+ {
+ }
+
+ size_t max_nesting_depth() const
+ {
+ return static_cast<size_t>(max_depth_);
+ }
+
+ void max_nesting_depth(size_t max_nesting_depth)
+ {
+ max_depth_ = static_cast<int>(std::min(max_nesting_depth,static_cast<size_t>(std::numeric_limits<int>::max 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<char>(*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<char>(*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<CharT>::false_literal();
+ literal_index_ = 1;
+ break;
+ case 'n':
+ handler_->begin_json();
+ flip(modes::done, modes::start);
+ state_stack_.back() = states::n;
+ literal_ = json_literals<CharT>::null_literal();
+ literal_index_ = 1;
+ break;
+ case 't':
+ handler_->begin_json();
+ flip(modes::done, modes::start);
+ state_stack_.back() = states::t;
+ literal_ = json_literals<CharT>::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<char>(*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<char>(*p_));
+ state_stack_.back() = states::integer;
+ break;
+ case 'f':
+ state_stack_.back() = states::f;
+ literal_ = json_literals<CharT>::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<CharT>::null_literal();
+ literal_index_ = 1;
+ break;
+ case 't':
+ state_stack_.back() = states::t;
+ literal_ = json_literals<CharT>::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<char>(*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<char>(*p_));
+ state_stack_.back() = states::integer;
+ break;
+ case 'f':
+ state_stack_.back() = states::f;
+ literal_ = json_literals<CharT>::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<CharT>::null_literal();
+ literal_index_ = 1;
+ break;
+ case 't':
+ state_stack_.back() = states::t;
+ literal_ = json_literals<CharT>::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<CharT, sizeof(CharT)>::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<CharT, sizeof(CharT)>::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<char>(*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<char>(*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<uint8_t>(number_buffer_.length());
+ number_buffer_.push_back(static_cast<char>(*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<char>(*p_));
+ state_stack_.back() = states::integer;
+ break;
+ case '.':
+ precision_ = static_cast<uint8_t>(number_buffer_.length());
+ number_buffer_.push_back(static_cast<char>(*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<char>(*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<char>(*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<char>(*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<char>(*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<char>(*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<char>(*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<char>(*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<uint8_t>(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<uint8_t>(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<uint8_t>(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<char> json_parser;
+typedef basic_json_parser<wchar_t> 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 <memory>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <stdexcept>
+#include <system_error>
+#include "jsoncons/jsoncons.hpp"
+#include "jsoncons/json_input_handler.hpp"
+#include "jsoncons/parse_error_handler.hpp"
+#include "jsoncons/json_parser.hpp"
+
+namespace jsoncons {
+
+template<typename CharT>
+class basic_json_reader
+{
+ static const size_t default_max_buffer_length = 16384;
+
+ basic_json_parser<CharT> parser_;
+ std::basic_istream<CharT> *is_;
+ basic_parse_error_handler<CharT> *err_handler_;
+ bool eof_;
+ std::vector<CharT> buffer_;
+ size_t buffer_length_;
+ size_t buffer_capacity_;
+ size_t index_;
+public:
+ basic_json_reader(std::basic_istream<CharT>& is,
+ basic_json_input_handler<CharT>& handler)
+ : parser_(handler),
+ is_(std::addressof(is)),
+ err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance())),
+ eof_(false),
+ buffer_length_(0),
+ buffer_capacity_(default_max_buffer_length),
+ index_(0)
+ {
+ buffer_.resize(buffer_capacity_);
+ }
+
+ basic_json_reader(std::basic_istream<CharT>& is,
+ basic_json_input_handler<CharT>& handler,
+ basic_parse_error_handler<CharT>& 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<size_t>(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<size_t>(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<char> json_reader;
+typedef basic_json_reader<wchar_t> 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 <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <cstdlib>
+#include <limits> // std::numeric_limits
+#include <fstream>
+#include "jsoncons/jsoncons.hpp"
+#include "jsoncons/output_format.hpp"
+#include "jsoncons/json_output_handler.hpp"
+
+namespace jsoncons {
+
+template<typename CharT>
+class basic_json_serializer : public basic_json_output_handler<CharT>
+{
+ 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<CharT> format_;
+ std::vector<stack_item> stack_;
+ int indent_;
+ std::streamsize original_precision_;
+ std::ios_base::fmtflags original_format_flags_;
+ bool indenting_;
+ float_printer<CharT> fp_;
+ buffered_ostream<CharT> bos_;
+public:
+ basic_json_serializer(std::basic_ostream<CharT>& os)
+ : indent_(0),
+ indenting_(false),
+ fp_(format_.precision()),
+ bos_(os)
+ {
+ }
+
+ basic_json_serializer(std::basic_ostream<CharT>& os, bool indenting)
+ : indent_(0),
+ indenting_(indenting),
+ fp_(format_.precision()),
+ bos_(os)
+ {
+ }
+
+ basic_json_serializer(std::basic_ostream<CharT>& os, const basic_output_format<CharT>& format)
+ : format_(format),
+ indent_(0),
+ indenting_(false),
+ fp_(format_.precision()),
+ bos_(os)
+ {
+ }
+ basic_json_serializer(std::basic_ostream<CharT>& os, const basic_output_format<CharT>& 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<CharT>(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<CharT>::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<CharT>(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<CharT>::true_literal();
+ bos_.write(buf.first,buf.second);
+ }
+ else
+ {
+ auto buf = json_literals<CharT>::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<int>(format_.indent());
+ }
+
+ void unindent()
+ {
+ indent_ -= static_cast<int>(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<char> json_serializer;
+typedef basic_json_serializer<wchar_t> 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 <string>
+#include <vector>
+#include <exception>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <algorithm>
+#include <sstream>
+#include <iomanip>
+#include <utility>
+#include <initializer_list>
+#include "jsoncons/jsoncons.hpp"
+
+namespace jsoncons {
+
+template <class JsonT, class Alloc>
+class json_array
+{
+public:
+ typedef Alloc allocator_type;
+ typedef JsonT value_type;
+ typedef typename std::allocator_traits<Alloc>:: template rebind_alloc<JsonT> vector_allocator_type;
+ typedef typename std::vector<JsonT,Alloc>::reference reference;
+ typedef typename std::vector<JsonT,Alloc>::const_reference const_reference;
+ typedef typename std::vector<JsonT,Alloc>::iterator iterator;
+ typedef typename std::vector<JsonT,Alloc>::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 <class InputIterator>
+ 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<JsonT> init,
+ const Alloc& allocator = Alloc())
+ : elements_(std::move(init),allocator)
+ {
+ }
+
+ Alloc get_allocator() const
+ {
+ return elements_.get_allocator();
+ }
+
+ void swap(json_array<JsonT,Alloc>& 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<JsonT,Alloc>& 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<JsonT,Alloc>&);
+ std::vector<JsonT,Alloc> elements_;
+};
+
+template <class ValueT,typename CharT>
+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<CharT>::compare(a.name().data(),b,len);
+ if (result != 0)
+ {
+ return result < 0;
+ }
+
+ return a.name().length() < length_;
+ }
+};
+
+template <class StringT,typename CharT>
+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<CharT>::compare(a.data(),b, min_len);
+ if (result != 0)
+ {
+ return result < 0;
+ }
+
+ return a.length() <= length;
+}
+
+template <class StringT,typename CharT>
+bool name_eq_string(const StringT& a, const CharT* b, size_t length)
+{
+ return a.length() == length && std::char_traits<CharT>::compare(a.data(),b,length) == 0;
+}
+
+template <class ValueT>
+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<char_type>::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<char_type>::compare(a.name().data(),b.name().data(),len);
+ if (result != 0)
+ {
+ return result < 0;
+ }
+
+ return a.name().length() < b.name().length();
+ }
+};
+
+template <class StringT, class ValueT>
+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 IteratorT,class NonConstIteratorT>
+class json_object_iterator
+{
+public:
+ typedef IteratorT iterator;
+ typedef typename std::iterator_traits<IteratorT>::value_type value_type;
+ typedef typename std::iterator_traits<IteratorT>::difference_type difference_type;
+ typedef typename std::iterator_traits<IteratorT>::pointer pointer;
+ typedef typename std::iterator_traits<IteratorT>::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<NonConstIteratorT,NonConstIteratorT>& 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 StringT,class JsonT,class Alloc>
+class json_object
+{
+public:
+ typedef Alloc allocator_type;
+ typedef typename JsonT::char_type char_type;
+ typedef StringT string_type;
+ typedef name_value_pair<StringT,JsonT> value_type;
+ typedef typename std::vector<value_type, allocator_type>::iterator base_iterator;
+ typedef typename std::vector<value_type, allocator_type>::const_iterator const_base_iterator;
+
+ typedef json_object_iterator<base_iterator,base_iterator> iterator;
+ typedef json_object_iterator<const_base_iterator,base_iterator> const_iterator;
+private:
+ std::vector<value_type,allocator_type> members_;
+public:
+ json_object(const allocator_type& allocator = allocator_type())
+ : members_(allocator)
+ {
+ }
+
+ json_object(const json_object<StringT,JsonT,Alloc>& val)
+ : members_(val.members_)
+ {
+ }
+
+ json_object(json_object&& val)
+ : members_(std::move(val.members_))
+ {
+ }
+
+ json_object(const json_object<StringT,JsonT,Alloc>& 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<value_type,char_type> 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<value_type,char_type> 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<value_type,char_type> 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<class InputIt, class UnaryPredicate>
+ 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<value_type>());
+ }
+
+ 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<value_type,char_type>(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<value_type,char_type>(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<value_type,char_type>(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<value_type,char_type>(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<char_type>::length(name), value);
+ }
+
+ iterator set(iterator hint, const char_type* name, JsonT&& value)
+ {
+ return set(hint, name, std::char_traits<char_type>::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<value_type,char_type>(length));
+ }
+ else
+ {
+ it = std::lower_bound(members_.begin(),members_.end(),s, member_lt_string<value_type,char_type>(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<value_type,char_type>(length));
+ }
+ else
+ {
+ it = std::lower_bound(members_.begin(),members_.end(),s, member_lt_string<value_type,char_type>(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<value_type,char_type>(name.length()));
+ }
+ else
+ {
+ it = std::lower_bound(members_.begin(),members_.end(),name.data() ,member_lt_string<value_type,char_type>(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<value_type,allocator_type>::iterator it;
+ if (hint.get() != members_.end() && hint.get()->name() <= name)
+ {
+ it = std::lower_bound(hint.get(),members_.end(),name.data() ,member_lt_string<value_type,char_type>(name.length()));
+ }
+ else
+ {
+ it = std::lower_bound(members_.begin(),members_.end(),name.data() ,member_lt_string<value_type,char_type>(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<StringT,JsonT,Alloc>& 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<value_type>());
+ // 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<StringT,JsonT,Alloc>& operator=(const json_object<StringT,JsonT,Alloc>&);
+};
+
+
+
+}
+
+#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 <string>
+#include <vector>
+#include <exception>
+#include <cstdlib>
+#include <cstring>
+#include <utility>
+#include <algorithm>
+#include <fstream>
+#include <limits>
+#include "jsoncons/jsoncons.hpp"
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+#endif
+
+namespace jsoncons {
+
+template <class JsonT, typename T>
+class json_type_traits
+{
+public:
+ static bool is(const JsonT&)
+ {
+ return false;
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, typename JsonT::string_type>
+{
+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 JsonT>
+class json_type_traits<JsonT, typename JsonT::any>
+{
+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 JsonT>
+class json_type_traits<JsonT, typename type_wrapper<typename JsonT::char_type>::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<char_type>::length(rhs);
+ lhs.assign_string(rhs,length);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, typename type_wrapper<typename JsonT::char_type>::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<char_type>::length(rhs);
+ lhs.assign_string(rhs,length);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, char>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ if (rhs.is_integer())
+ {
+ return rhs.as_integer() >= std::numeric_limits<char>::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits<char>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static char as(const JsonT& rhs)
+ {
+ return static_cast<char>(rhs.as_integer());
+ }
+ static void assign(JsonT& lhs, char ch)
+ {
+ lhs.assign_integer(ch);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, unsigned char>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ if (rhs.is_integer())
+ {
+ return rhs.as_integer() >= 0 && static_cast<unsigned long long>(rhs.as_integer()) <= std::numeric_limits<unsigned char>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else if (rhs.is_uinteger())
+ {
+ return rhs.as_uinteger() <= std::numeric_limits<unsigned char>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static unsigned char as(const JsonT& rhs)
+ {
+ return static_cast<unsigned char>(rhs.as_uinteger());
+ }
+ static void assign(JsonT& lhs, unsigned char ch)
+ {
+ lhs.assign_uinteger(ch);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, signed char>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ if (rhs.is_integer())
+ {
+ return rhs.as_integer() >= std::numeric_limits<char>::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits<char>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else if (rhs.is_uinteger())
+ {
+ return rhs.as_uinteger() <= static_cast<unsigned long long>(std::numeric_limits<char>::max JSONCONS_NO_MACRO_EXP());
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static signed char as(const JsonT& rhs)
+ {
+ return static_cast<signed char>(rhs.as_integer());
+ }
+ static void assign(JsonT& lhs, signed char ch)
+ {
+ lhs.assign_integer(ch);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, wchar_t>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ if (rhs.is_integer())
+ {
+ return rhs.as_integer() >= std::numeric_limits<wchar_t>::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits<wchar_t>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else if (rhs.is_uinteger())
+ {
+ return rhs.as_uinteger() <= static_cast<unsigned long long>(std::numeric_limits<wchar_t>::max JSONCONS_NO_MACRO_EXP());
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static wchar_t as(const JsonT& rhs)
+ {
+ return static_cast<wchar_t>(rhs.as_integer());
+ }
+ static void assign(JsonT& lhs, wchar_t ch)
+ {
+ lhs.assign_integer(ch);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, typename JsonT::object>
+{
+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 JsonT>
+class json_type_traits<JsonT, typename JsonT::array>
+{
+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 JsonT>
+class json_type_traits<JsonT, jsoncons::null_type>
+{
+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 JsonT>
+class json_type_traits<JsonT, bool>
+{
+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 JsonT>
+class json_type_traits<JsonT, short>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ if (rhs.is_integer())
+ {
+ return rhs.as_integer() >= std::numeric_limits<short>::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits<short>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else if (rhs.is_uinteger())
+ {
+ return rhs.as_uinteger() <= static_cast<unsigned long long>(std::numeric_limits<short>::max JSONCONS_NO_MACRO_EXP());
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static short as(const JsonT& rhs)
+ {
+ return static_cast<short>(rhs.as_integer());
+ }
+ static void assign(JsonT& lhs, short rhs)
+ {
+ lhs.assign_integer(rhs);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, unsigned short>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ if (rhs.is_integer())
+ {
+ return rhs.as_integer() >= 0 && static_cast<unsigned long long>(rhs.as_integer()) <= std::numeric_limits<unsigned short>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else if (rhs.is_uinteger())
+ {
+ return rhs.as_uinteger() <= std::numeric_limits<unsigned short>::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 JsonT>
+class json_type_traits<JsonT, int>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ if (rhs.is_integer())
+ {
+ return rhs.as_integer() >= std::numeric_limits<int>::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits<int>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else if (rhs.is_uinteger())
+ {
+ return rhs.as_uinteger() <= static_cast<unsigned long long>(std::numeric_limits<int>::max JSONCONS_NO_MACRO_EXP());
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static int as(const JsonT& rhs)
+ {
+ return static_cast<int>(rhs.as_integer());
+ }
+ static void assign(JsonT& lhs, int rhs)
+ {
+ lhs.assign_integer(rhs);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, unsigned int>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ if (rhs.is_integer())
+ {
+ return rhs.as_integer() >= 0 && static_cast<unsigned long long>(rhs.as_integer()) <= std::numeric_limits<unsigned int>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else if (rhs.is_uinteger())
+ {
+ return rhs.as_uinteger() <= std::numeric_limits<unsigned int>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static unsigned int as(const JsonT& rhs)
+ {
+ return static_cast<unsigned int>(rhs.as_uinteger());
+ }
+ static void assign(JsonT& lhs, unsigned int rhs)
+ {
+ lhs.assign_uinteger(rhs);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, long>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ if (rhs.is_integer())
+ {
+ return rhs.as_integer() >= std::numeric_limits<long>::min JSONCONS_NO_MACRO_EXP() && rhs.as_integer() <= std::numeric_limits<long>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else if (rhs.is_uinteger())
+ {
+ return rhs.as_uinteger() <= static_cast<unsigned long long>(std::numeric_limits<long>::max JSONCONS_NO_MACRO_EXP());
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static long as(const JsonT& rhs)
+ {
+ return static_cast<long>(rhs.as_integer());
+ }
+ static void assign(JsonT& lhs, long rhs)
+ {
+ lhs.assign_integer(rhs);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, unsigned long>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ if (rhs.is_integer())
+ {
+ return rhs.as_integer() >= 0 && static_cast<unsigned long long>(rhs.as_integer()) <= std::numeric_limits<unsigned long>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else if (rhs.is_uinteger())
+ {
+ return rhs.as_uinteger() <= std::numeric_limits<unsigned long>::max JSONCONS_NO_MACRO_EXP();
+ }
+ else
+ {
+ return false;
+ }
+ }
+ static unsigned long as(const JsonT& rhs)
+ {
+ return static_cast<unsigned long>(rhs.as_uinteger());
+ }
+ static void assign(JsonT& lhs, unsigned long rhs)
+ {
+ lhs.assign_uinteger(rhs);
+ }
+};
+
+template<class JsonT>
+class json_type_traits<JsonT, long long>
+{
+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 JsonT>
+class json_type_traits<JsonT, unsigned long long>
+{
+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 JsonT>
+class json_type_traits<JsonT, double>
+{
+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 JsonT>
+class json_type_traits<JsonT, float>
+{
+public:
+ static bool is(const JsonT& rhs) JSONCONS_NOEXCEPT
+ {
+ return rhs.is_double();
+ }
+ static double as(const JsonT& rhs)
+ {
+ return static_cast<float>(rhs.as_double());
+ }
+ static void assign(JsonT& lhs, float rhs)
+ {
+ lhs.assign_double(static_cast<double>(rhs));
+ }
+};
+
+template<class JsonT, typename T>
+class json_type_traits<JsonT, std::vector<T>>
+{
+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<T>())
+ {
+ result = false;
+ }
+ }
+ return result;
+ }
+ static std::vector<T> as(const JsonT& rhs)
+ {
+ std::vector<T> v(rhs.size());
+ for (size_t i = 0; i < v.size(); ++i)
+ {
+ v[i] = rhs[i].template as<T>();
+ }
+ return v;
+ }
+ static void assign(JsonT& lhs, const std::vector<T>& 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 <locale>
+#include <string>
+#include <vector>
+#include <cstdlib>
+#include <cwchar>
+#include <cstdint>
+#include <iostream>
+#include <vector>
+#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 <typename Base>
+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 <typename Base>
+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<std::size_t>(-1))
+ {
+ arg1_ = buf;
+ }
+ }
+ ~json_exception_1() JSONCONS_NOEXCEPT
+ {
+ }
+ const char* what() const JSONCONS_NOEXCEPT
+ {
+ c99_snprintf(const_cast<char*>(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<Base>((x))
+#define JSONCONS_THROW_EXCEPTION_1(Base,fmt,arg1) throw jsoncons::json_exception_1<Base>((fmt),(arg1))
+#define JSONCONS_ASSERT(x) if (!(x)) { \
+ throw jsoncons::json_exception_0<std::runtime_error>("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 <typename CharT>
+struct json_literals
+{
+};
+
+template <>
+struct json_literals<char>
+{
+ static std::pair<const char*,size_t> null_literal()
+ {
+ static const char* value = "null";
+ return std::pair<const char*,size_t>(value,4);
+ }
+
+ static std::pair<const char*,size_t> true_literal()
+ {
+ static const char* value = "true";
+ return std::pair<const char*,size_t>(value,4);
+ }
+
+ static std::pair<const char*,size_t> false_literal()
+ {
+ static const char* value = "false";
+ return std::pair<const char*,size_t>(value,5);
+ }
+};
+
+template <>
+struct json_literals<wchar_t>
+{
+ static std::pair<const wchar_t*,size_t> null_literal()
+ {
+ static const wchar_t* value = L"null";
+ return std::pair<const wchar_t*,size_t>(value,4);
+ }
+
+ static std::pair<const wchar_t*,size_t> true_literal()
+ {
+ static const wchar_t* value = L"true";
+ return std::pair<const wchar_t*,size_t>(value,4);
+ }
+
+ static std::pair<const wchar_t*,size_t> false_literal()
+ {
+ static const wchar_t* value = L"false";
+ return std::pair<const wchar_t*,size_t>(value,5);
+ }
+};
+
+template <typename CharT,size_t Size>
+struct json_char_traits
+{
+};
+
+template <>
+struct json_char_traits<char,1>
+{
+ 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<uint32_t>(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<uint32_t>(0xff & u) << 12) & 0x3ffff);
+ c = *(++it);
+ u = (c >= 0 ? c : 256 + c );
+ cp += (static_cast<uint32_t>(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<char>(cp));
+ }
+ else if (cp <= 0x7FF)
+ {
+ s.push_back(static_cast<char>(0xC0 | (0x1f & (cp >> 6))));
+ s.push_back(static_cast<char>(0x80 | (0x3f & cp)));
+ }
+ else if (cp <= 0xFFFF)
+ {
+ s.push_back(0xE0 | static_cast<char>((0xf & (cp >> 12))));
+ s.push_back(0x80 | static_cast<char>((0x3f & (cp >> 6))));
+ s.push_back(static_cast<char>(0x80 | (0x3f & cp)));
+ }
+ else if (cp <= 0x10FFFF)
+ {
+ s.push_back(static_cast<char>(0xF0 | (0x7 & (cp >> 18))));
+ s.push_back(static_cast<char>(0x80 | (0x3f & (cp >> 12))));
+ s.push_back(static_cast<char>(0x80 | (0x3f & (cp >> 6))));
+ s.push_back(static_cast<char>(0x80 | (0x3f & cp)));
+ }
+ }
+
+};
+
+template <>
+struct json_char_traits<wchar_t,2> // assume utf16
+{
+ static void append_codepoint_to_string(uint32_t cp, std::wstring& s)
+ {
+ if (cp <= 0xFFFF)
+ {
+ s.push_back(static_cast<wchar_t>(cp));
+ }
+ else if (cp <= 0x10FFFF)
+ {
+ s.push_back(static_cast<wchar_t>((cp >> 10) + min_lead_surrogate - (0x10000 >> 10)));
+ s.push_back(static_cast<wchar_t>((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<wchar_t,4> // assume utf32
+{
+ static void append_codepoint_to_string(uint32_t cp, std::wstring& s)
+ {
+ if (cp <= 0xFFFF)
+ {
+ s.push_back(static_cast<wchar_t>(cp));
+ }
+ else if (cp <= 0x10FFFF)
+ {
+ s.push_back(static_cast<wchar_t>(cp));
+ }
+ }
+
+ static uint32_t convert_char_to_codepoint(const wchar_t*& it, const wchar_t*)
+ {
+ uint32_t cp = static_cast<uint32_t>(*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 <typename T>
+struct type_wrapper
+{
+ typedef T* pointer_type;
+ typedef const T* const_pointer_type;
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+};
+
+template <typename T>
+struct type_wrapper<const T>
+{
+ typedef T* pointer_type;
+ typedef const T* const_pointer_type;
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+};
+
+template <typename T>
+struct type_wrapper<T&>
+{
+ typedef T* pointer_type;
+ typedef const T* const_pointer_type;
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+};
+
+template <typename T>
+struct type_wrapper<const T&>
+{
+ typedef T* pointer_type;
+ typedef const T* const_pointer_type;
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+};
+
+}
+#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 <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+#include <cstdarg>
+#include <limits> // 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 <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+#include <cstdarg>
+#include <limits> // std::numeric_limits
+#include "jsoncons_config.hpp"
+#include "ovectorstream.hpp"
+
+namespace jsoncons
+{
+
+template <typename CharT>
+class buffered_ostream
+{
+ static const size_t default_buffer_length = 16384;
+
+ std::basic_ostream<CharT>* os_;
+ std::vector<CharT> buffer_;
+ CharT * const begin_buffer_;
+ const CharT* const end_buffer_;
+ CharT* p_;
+public:
+ buffered_ostream(std::basic_ostream<CharT>& 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<CharT>& 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 <typename CharT>
+class float_printer
+{
+ uint8_t precision_;
+public:
+ float_printer(int precision)
+ : precision_(precision)
+ {
+ }
+
+ void print(double val, uint8_t precision, buffered_ostream<CharT>& 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 <typename CharT>
+class float_printer
+{
+ jsoncons::basic_ovectorstream<CharT> 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<CharT>& 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<char> 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 <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <cstdlib>
+#include <limits>
+#include <cwchar>
+
+namespace jsoncons {
+
+enum class block_options {next_line,same_line};
+
+template <typename CharT>
+class buffered_ostream;
+
+template <typename CharT>
+class basic_output_format
+{
+ int indent_;
+ uint8_t precision_;
+ bool replace_nan_;
+ bool replace_pos_inf_;
+ bool replace_neg_inf_;
+ std::basic_string<CharT> nan_replacement_;
+ std::basic_string<CharT> pos_inf_replacement_;
+ std::basic_string<CharT> 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<CharT>::null_literal().first),
+ pos_inf_replacement_(json_literals<CharT>::null_literal().first),
+ neg_inf_replacement_(json_literals<CharT>::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<CharT>& 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<CharT>& 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<CharT>& 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<CharT>& 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<CharT> nan_replacement() const
+ {
+ return nan_replacement_;
+ }
+
+ std::basic_string<CharT> pos_inf_replacement() const
+ {
+ return pos_inf_replacement_;
+ }
+
+ std::basic_string<CharT> neg_inf_replacement() const
+ {
+ return neg_inf_replacement_;
+ }
+
+// Modifiers
+
+ basic_output_format<CharT>& precision(uint8_t prec)
+ {
+ precision_ = prec;
+ return *this;
+ }
+
+ basic_output_format<CharT>& escape_all_non_ascii(bool value)
+ {
+ escape_all_non_ascii_ = value;
+ return *this;
+ }
+
+ basic_output_format<CharT>& escape_solidus(bool value)
+ {
+ escape_solidus_ = value;
+ return *this;
+ }
+
+ basic_output_format<CharT>& replace_nan(bool replace)
+ {
+ replace_nan_ = replace;
+ return *this;
+ }
+
+ basic_output_format<CharT>& replace_inf(bool replace)
+ {
+ replace_pos_inf_ = replace;
+ replace_neg_inf_ = replace;
+ return *this;
+ }
+
+ basic_output_format<CharT>& replace_pos_inf(bool replace)
+ {
+ replace_pos_inf_ = replace;
+ return *this;
+ }
+
+ basic_output_format<CharT>& replace_neg_inf(bool replace)
+ {
+ replace_neg_inf_ = replace;
+ return *this;
+ }
+
+ basic_output_format<CharT>& nan_replacement(const std::basic_string<CharT>& replacement)
+ {
+ nan_replacement_ = replacement;
+ return *this;
+ }
+
+ basic_output_format<CharT>& pos_inf_replacement(const std::basic_string<CharT>& replacement)
+ {
+ pos_inf_replacement_ = replacement;
+ return *this;
+ }
+
+ basic_output_format<CharT>& neg_inf_replacement(const std::basic_string<CharT>& replacement)
+ {
+ neg_inf_replacement_ = replacement;
+ return *this;
+ }
+
+ basic_output_format<CharT>& indent(int value)
+ {
+ indent_ = value;
+ return *this;
+ }
+};
+
+template<typename CharT>
+void escape_string(const CharT* s,
+ size_t length,
+ const basic_output_format<CharT>& format,
+ buffered_ostream<CharT>& 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<CharT, sizeof(CharT)>::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<char> output_format;
+typedef basic_output_format<wchar_t> 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 <ios>
+#include <ostream>
+#include <string>
+#include <cstddef>
+#include <vector>
+#include "jsoncons/jsoncons_config.hpp"
+
+namespace jsoncons {
+
+template<
+ class CharT,
+ class Traits = std::char_traits<CharT>
+> class basic_ovectorstream;
+
+template<class CharT, class CharTraits>
+class basic_ovectorbuf
+ : public std::basic_streambuf<CharT, CharTraits>
+{
+private:
+ std::ios_base::openmode mode_;
+ std::vector<CharT> 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<char_type, traits_type> 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<std::streamoff>(buf_.size());
+ break;
+ case std::ios_base::cur:
+ newoff = static_cast<std::streamoff>(this->pptr() - this->pbase());
+ break;
+ default:
+ return pos_type(off_type(-1));
+ }
+
+ off += newoff;
+
+ std::ptrdiff_t n = this->epptr() - this->pbase();
+
+ if (off < 0 || off > n) return pos_type(off_type(-1));
+ else
+ {
+ this->setp(this->pbase(), this->pbase() + n);
+ this->pbump(static_cast<int>(off));
+ }
+
+ return pos_type(off);
+ }
+
+ pos_type seekoff_beg(off_type off)
+ {
+ std::ptrdiff_t n = this->epptr() - this->pbase();
+
+ if (off < 0 || off > n)
+ {
+ return pos_type(off_type(-1));
+ }
+ else
+ {
+ this->setp(this->pbase(), this->pbase() + n);
+ this->pbump(static_cast<int>(off));
+ }
+
+ return pos_type(off);
+ }
+
+ pos_type seekpos(pos_type pos, std::ios_base::openmode mode
+ = std::ios_base::out) override
+ {
+ (void)mode; // Always out
+
+ return seekoff_beg(pos - pos_type(off_type(0)));
+ }
+};
+
+template<class CharT, class CharTraits>
+class basic_ovectorstream :
+ private basic_ovectorbuf<CharT, CharTraits>,
+ public std::basic_ostream<CharT, CharTraits>
+{
+public:
+ typedef typename std::basic_ios
+ <CharT, CharTraits>::char_type char_type;
+ typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
+ typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
+ typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
+ typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
+
+private:
+ typedef basic_ovectorbuf<CharT, CharTraits> base_ouputbuf;
+ typedef std::basic_ios<char_type, CharTraits> base_ios;
+ typedef std::basic_ostream<char_type, CharTraits> 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<CharT, CharTraits>::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 <system_error>
+
+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<std::string&>(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<typename CharT>
+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<char> parsing_context;
+typedef basic_parsing_context<wchar_t> wparsing_context;
+
+template <typename CharT>
+class basic_parse_error_handler
+{
+public:
+ virtual ~basic_parse_error_handler()
+ {
+ }
+
+ void warning(std::error_code ec,
+ const basic_parsing_context<CharT>& context) throw (parse_exception)
+ {
+ do_warning(ec,context);
+ }
+
+ void error(std::error_code ec,
+ const basic_parsing_context<CharT>& context) throw (parse_exception)
+ {
+ do_error(ec,context);
+ }
+
+ void fatal_error(std::error_code ec,
+ const basic_parsing_context<CharT>& 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<CharT>& context) throw (parse_exception) = 0;
+
+ virtual void do_error(std::error_code,
+ const basic_parsing_context<CharT>& context) throw (parse_exception) = 0;
+
+ virtual void do_fatal_error(std::error_code,
+ const basic_parsing_context<CharT>& context) throw (parse_exception)
+ {
+ (void)context;
+ }
+};
+
+template <typename CharT>
+class basic_default_parse_error_handler : public basic_parse_error_handler<CharT>
+{
+public:
+ static basic_parse_error_handler<CharT>& instance()
+ {
+ static basic_default_parse_error_handler<CharT> instance;
+ return instance;
+ }
+private:
+ virtual void do_warning(std::error_code,
+ const basic_parsing_context<CharT>& context) throw (parse_exception)
+ {
+ (void)context;
+ }
+
+ virtual void do_error(std::error_code ec,
+ const basic_parsing_context<CharT>& context) throw (parse_exception)
+ {
+ throw parse_exception(ec,context.line_number(),context.column_number());
+ }
+};
+
+typedef basic_parse_error_handler<char> parse_error_handler;
+typedef basic_parse_error_handler<wchar_t> wparse_error_handler;
+
+typedef basic_default_parse_error_handler<char> default_parse_error_handler;
+typedef basic_default_parse_error_handler<wchar_t> wdefault_parse_error_handler;
+
+typedef basic_parsing_context<char> parsing_context;
+typedef basic_parsing_context<wchar_t> wparsing_context;
+
+}
+#endif
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/boost/type_extensions.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/boost/type_extensions.hpp
new file mode 100644
index 00000000..59936cd7
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons_ext/boost/type_extensions.hpp
@@ -0,0 +1,59 @@
+// 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_EXT_TYPE_EXTENSIONS_HPP
+#define JSONCONS_EXT_TYPE_EXTENSIONS_HPP
+
+#include "jsoncons/json.hpp"
+#include "boost/date_time/gregorian/gregorian.hpp"
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+#endif
+
+namespace jsoncons
+{
+ template <typename JsonT>
+ class json_type_traits<JsonT,boost::gregorian::date>
+ {
+ public:
+ static bool is(const JsonT& val) JSONCONS_NOEXCEPT
+ {
+ if (!val.is_string())
+ {
+ return false;
+ }
+ std::string s = val.template as<std::string>();
+ try
+ {
+ boost::gregorian::date_from_iso_string(s);
+ return true;
+ }
+ catch (...)
+ {
+ return false;
+ }
+ }
+
+ static boost::gregorian::date as(const JsonT& val)
+ {
+ std::string s = val.template as<std::string>();
+ return boost::gregorian::from_simple_string(s);
+ }
+
+ static void assign(JsonT& lhs, boost::gregorian::date val)
+ {
+ lhs = to_iso_extended_string(val);
+ }
+ };
+}
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp
new file mode 100644
index 00000000..5056d380
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp
@@ -0,0 +1,55 @@
+/// 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_CSV_CSV_TEXT_ERROR_CATEGORY_HPP
+#define JSONCONS_CSV_CSV_TEXT_ERROR_CATEGORY_HPP
+
+#include "jsoncons/jsoncons.hpp"
+#include <system_error>
+
+namespace jsoncons { namespace csv {
+
+namespace csv_parser_errc
+{
+ const int unexpected_eof = 1;
+ const int expected_quote = 2;
+ const int invalid_csv_text = 3;
+ const int invalid_state = 4;
+}
+
+class csv_error_category_impl
+ : public std::error_category
+{
+public:
+ virtual const char* name() const JSONCONS_NOEXCEPT
+ {
+ return "csv";
+ }
+ virtual std::string message(int ev) const
+ {
+ switch (ev)
+ {
+ case csv_parser_errc::unexpected_eof:
+ return "Unexpected end of file";
+ case csv_parser_errc::expected_quote:
+ return "Expected quote character";
+ case csv_parser_errc::invalid_csv_text:
+ return "Invalid CSV text";
+ default:
+ return "Unknown JSON parser error";
+ }
+ }
+};
+
+inline
+const std::error_category& csv_error_category()
+{
+ static csv_error_category_impl instance;
+ return instance;
+}
+
+}}
+#endif
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp
new file mode 100644
index 00000000..099a154f
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp
@@ -0,0 +1,341 @@
+// 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_CSV_CSV_PARAMETERS_HPP
+#define JSONCONS_CSV_CSV_PARAMETERS_HPP
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <cstdlib>
+#include <limits>
+#include <cwchar>
+
+namespace jsoncons { namespace csv {
+
+enum class quote_styles
+{
+ all,minimal,none,nonnumeric
+};
+
+template <typename CharT>
+class basic_csv_parameters
+{
+public:
+ static const size_t default_indent = 4;
+
+// Constructors
+
+ basic_csv_parameters()
+ :
+ assume_header_(false),
+ ignore_empty_values_(false),
+ trim_leading_(false),
+ trim_trailing_(false),
+ trim_leading_inside_quotes_(false),
+ trim_trailing_inside_quotes_(false),
+ unquoted_empty_value_is_null_(false),
+ field_delimiter_(','),
+ quote_char_('\"'),
+ quote_escape_char_('\"'),
+ comment_starter_('\0'),
+ quote_style_(quote_styles::minimal),
+ max_lines_(std::numeric_limits<unsigned long>::max JSONCONS_NO_MACRO_EXP()),
+ header_lines_(0)
+ {
+ line_delimiter_.push_back('\n');
+ }
+
+// Properties
+
+ size_t header_lines() const
+ {
+ return (assume_header_ && header_lines_ <= 1) ? 1 : header_lines_;
+ }
+
+ basic_csv_parameters<CharT>& header_lines(size_t value)
+ {
+ header_lines_ = value;
+ return *this;
+ }
+
+ bool assume_header() const
+ {
+ return assume_header_;
+ }
+
+ basic_csv_parameters<CharT>& assume_header(bool value)
+ {
+ assume_header_ = value;
+ return *this;
+ }
+
+ bool ignore_empty_values() const
+ {
+ return ignore_empty_values_;
+ }
+
+ basic_csv_parameters<CharT>& ignore_empty_values(bool value)
+ {
+ ignore_empty_values_ = value;
+ return *this;
+ }
+
+ bool trim_leading() const
+ {
+ return trim_leading_;
+ }
+
+ basic_csv_parameters<CharT>& trim_leading(bool value)
+ {
+ trim_leading_ = value;
+ return *this;
+ }
+
+ bool trim_trailing() const
+ {
+ return trim_trailing_;
+ }
+
+ basic_csv_parameters<CharT>& trim_trailing(bool value)
+ {
+ trim_trailing_ = value;
+ return *this;
+ }
+
+ bool trim_leading_inside_quotes() const
+ {
+ return trim_leading_inside_quotes_;
+ }
+
+ basic_csv_parameters<CharT>& trim_leading_inside_quotes(bool value)
+ {
+ trim_leading_inside_quotes_ = value;
+ return *this;
+ }
+
+ bool trim_trailing_inside_quotes() const
+ {
+ return trim_trailing_inside_quotes_;
+ }
+
+ basic_csv_parameters<CharT>& trim_trailing_inside_quotes(bool value)
+ {
+ trim_trailing_inside_quotes_ = value;
+ return *this;
+ }
+
+ bool trim() const
+ {
+ return trim_leading_ && trim_trailing_;
+ }
+
+ basic_csv_parameters<CharT>& trim(bool value)
+ {
+ trim_leading_ = value;
+ trim_trailing_ = value;
+ return *this;
+ }
+
+ bool trim_inside_quotes() const
+ {
+ return trim_leading_inside_quotes_ && trim_trailing_inside_quotes_;
+ }
+
+ basic_csv_parameters<CharT>& trim_inside_quotes(bool value)
+ {
+ trim_leading_inside_quotes_ = value;
+ trim_trailing_inside_quotes_ = value;
+ return *this;
+ }
+
+ bool unquoted_empty_value_is_null() const
+ {
+ return unquoted_empty_value_is_null_;
+ }
+
+ basic_csv_parameters<CharT>& unquoted_empty_value_is_null(bool value)
+ {
+ unquoted_empty_value_is_null_ = value;
+ return *this;
+ }
+
+ std::vector<std::basic_string<CharT>> column_names() const
+ {
+ return column_names_;
+ }
+
+ basic_csv_parameters<CharT>& column_names(const std::vector<std::basic_string<CharT>>& value)
+ {
+ column_names_ = value;
+ return *this;
+ }
+
+ std::vector<std::basic_string<CharT>> column_types() const
+ {
+ return column_types_;
+ }
+
+ basic_csv_parameters<CharT>& column_types(const std::vector<std::basic_string<CharT>>& value)
+ {
+ column_types_ = value;
+ return *this;
+ }
+
+ std::vector<std::basic_string<CharT>> column_defaults() const
+ {
+ return column_defaults_;
+ }
+
+ basic_csv_parameters<CharT>& column_defaults(const std::vector<std::basic_string<CharT>>& value)
+ {
+ column_defaults_ = value;
+ return *this;
+ }
+
+ CharT field_delimiter() const
+ {
+ return field_delimiter_;
+ }
+
+ basic_csv_parameters<CharT>& field_delimiter(CharT value)
+ {
+ field_delimiter_ = value;
+ return *this;
+ }
+
+ std::basic_string<CharT> line_delimiter() const
+ {
+ return line_delimiter_;
+ }
+
+ basic_csv_parameters<CharT>& line_delimiter(std::basic_string<CharT> value)
+ {
+ line_delimiter_ = value;
+ return *this;
+ }
+
+ CharT quote_char() const
+ {
+ return quote_char_;
+ }
+
+ basic_csv_parameters<CharT>& quote_char(CharT value)
+ {
+ quote_char_ = value;
+ return *this;
+ }
+
+ CharT quote_escape_char() const
+ {
+ return quote_escape_char_;
+ }
+
+ basic_csv_parameters<CharT>& quote_escape_char(CharT value)
+ {
+ quote_escape_char_ = value;
+ return *this;
+ }
+
+ CharT comment_starter() const
+ {
+ return comment_starter_;
+ }
+
+ basic_csv_parameters<CharT>& comment_starter(CharT value)
+ {
+ comment_starter_ = value;
+ return *this;
+ }
+
+ quote_styles quote_style() const
+ {
+ return quote_style_;
+ }
+
+ basic_csv_parameters<CharT>& assume_header(quote_styles value)
+ {
+ quote_style_ = value;
+ return *this;
+ }
+
+ unsigned long max_lines() const
+ {
+ return max_lines_;
+ }
+
+ basic_csv_parameters<CharT>& max_lines(unsigned long value)
+ {
+ max_lines_ = value;
+ return *this;
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+
+ std::basic_string<CharT> header() const
+ {
+ return header_;
+ }
+
+ basic_csv_parameters<CharT>& header(const std::basic_string<CharT>& value)
+ {
+ header_ = value;
+ return *this;
+ }
+
+ std::basic_string<CharT> data_types() const
+ {
+ return data_types_;
+ }
+
+ basic_csv_parameters<CharT>& data_types(const std::basic_string<CharT>& value)
+ {
+ data_types_ = value;
+ return *this;
+ }
+
+ std::basic_string<CharT> default_values() const
+ {
+ return default_values_;
+ }
+
+ basic_csv_parameters<CharT>& default_values(const std::basic_string<CharT>& value)
+ {
+ default_values_ = value;
+ return *this;
+ }
+#endif
+private:
+ bool assume_header_;
+ bool ignore_empty_values_;
+ bool trim_leading_;
+ bool trim_trailing_;
+ bool trim_leading_inside_quotes_;
+ bool trim_trailing_inside_quotes_;
+ bool unquoted_empty_value_is_null_;
+ CharT field_delimiter_;
+ CharT quote_char_;
+ CharT quote_escape_char_;
+ CharT comment_starter_;
+ quote_styles quote_style_;
+ unsigned long max_lines_;
+ size_t header_lines_;
+ std::basic_string<CharT> line_delimiter_;
+ std::basic_string<CharT> header_;
+ std::basic_string<CharT> data_types_;
+ std::basic_string<CharT> default_values_;
+ std::vector<std::basic_string<CharT>> column_names_;
+ std::vector<std::basic_string<CharT>> column_types_;
+ std::vector<std::basic_string<CharT>> column_defaults_;
+};
+
+typedef basic_csv_parameters<char> csv_parameters;
+typedef basic_csv_parameters<wchar_t> wcsv_parameters;
+
+}}
+#endif
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp
new file mode 100644
index 00000000..14323666
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp
@@ -0,0 +1,903 @@
+// 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_CSV_CSV_PARSER_HPP
+#define JSONCONS_CSV_CSV_PARSER_HPP
+
+#include <memory>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <stdexcept>
+#include <system_error>
+#include <cctype>
+#include "jsoncons/jsoncons.hpp"
+#include "jsoncons/json_input_handler.hpp"
+#include "jsoncons/parse_error_handler.hpp"
+#include "jsoncons/json_parser.hpp"
+#include "jsoncons/json_filter.hpp"
+#include "jsoncons_ext/csv/csv_error_category.hpp"
+#include "jsoncons_ext/csv/csv_parameters.hpp"
+
+namespace jsoncons { namespace csv {
+
+template <typename CharT>
+struct json_csv_parser_traits
+{
+};
+
+template <>
+struct json_csv_parser_traits<char>
+{
+ static const std::string string_literal() {return "string";};
+
+ static const std::string integer_literal() {return "integer";};
+
+ static const std::string float_literal() {return "float";};
+
+ static const std::string boolean_literal() {return "boolean";};
+};
+
+template <>
+struct json_csv_parser_traits<wchar_t> // assume utf16
+{
+ static const std::wstring string_literal() {return L"string";};
+
+ static const std::wstring integer_literal() {return L"integer";};
+
+ static const std::wstring float_literal() {return L"float";};
+
+ static const std::wstring boolean_literal() {return L"boolean";};
+};
+
+enum class csv_modes {
+ done,
+ header,
+ array,
+ object
+};
+
+enum class csv_states
+{
+ start,
+ comment,
+ expect_value,
+ between_fields,
+ quoted_string,
+ unquoted_string,
+ escaped_value,
+ minus,
+ zero,
+ integer,
+ fraction,
+ exp1,
+ exp2,
+ exp3,
+ done
+};
+
+enum class data_types
+{
+ string_t,integer_t,float_t,boolean_t
+};
+
+template<typename CharT>
+class basic_csv_parser : private basic_parsing_context<CharT>
+{
+ static const int default_depth = 3;
+
+ csv_states state_;
+ int top_;
+ std::vector<csv_modes> stack_;
+ basic_json_input_handler<CharT> *handler_;
+ basic_parse_error_handler<CharT> *err_handler_;
+ bool is_negative_;
+ uint32_t cp_;
+ size_t index_;
+ unsigned long column_;
+ unsigned long line_;
+ int curr_char_;
+ int prev_char_;
+ std::basic_string<CharT> string_buffer_;
+ csv_states saved_state_;
+ int depth_;
+ basic_csv_parameters<CharT> parameters_;
+ std::vector<std::basic_string<CharT>> column_names_;
+ std::vector<data_types> column_types_;
+ std::vector<std::basic_string<CharT>> column_defaults_;
+ size_t column_index_;
+ basic_begin_end_json_filter<CharT> filter_;
+ basic_json_parser<CharT> parser_;
+
+public:
+ basic_csv_parser(basic_json_input_handler<CharT>& handler)
+ : top_(-1),
+ stack_(default_depth),
+ handler_(std::addressof(handler)),
+ err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance())),
+ is_negative_(false),
+ cp_(0),
+ index_(0),
+ filter_(handler),
+ parser_(filter_)
+ {
+ depth_ = default_depth;
+ state_ = csv_states::start;
+ top_ = -1;
+ line_ = 1;
+ column_ = 0;
+ column_index_ = 0;
+ }
+
+ basic_csv_parser(basic_json_input_handler<CharT>& handler,
+ basic_csv_parameters<CharT> params)
+ : top_(-1),
+ stack_(default_depth),
+ handler_(std::addressof(handler)),
+ err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance())),
+ is_negative_(false),
+ cp_(0),
+ index_(0),
+ parameters_(params),
+ filter_(handler),
+ parser_(filter_)
+ {
+ depth_ = default_depth;
+ state_ = csv_states::start;
+ top_ = -1;
+ line_ = 1;
+ column_ = 0;
+ column_index_ = 0;
+ }
+
+ basic_csv_parser(basic_json_input_handler<CharT>& handler,
+ basic_parse_error_handler<CharT>& err_handler)
+ : top_(-1),
+ stack_(default_depth),
+ handler_(std::addressof(handler)),
+ err_handler_(std::addressof(err_handler)),
+ is_negative_(false),
+ cp_(0),
+ index_(0),
+ filter_(handler),
+ parser_(filter_)
+ {
+ depth_ = default_depth;
+ state_ = csv_states::start;
+ top_ = -1;
+ line_ = 1;
+ column_ = 0;
+ column_index_ = 0;
+ }
+
+ basic_csv_parser(basic_json_input_handler<CharT>& handler,
+ basic_parse_error_handler<CharT>& err_handler,
+ basic_csv_parameters<CharT> params)
+ : top_(-1),
+ stack_(default_depth),
+ handler_(std::addressof(handler)),
+ err_handler_(std::addressof(err_handler)),
+ is_negative_(false),
+ cp_(0),
+ index_(0),
+ parameters_(params),
+ filter_(handler),
+ parser_(filter_)
+ {
+ depth_ = default_depth;
+ state_ = csv_states::start;
+ top_ = -1;
+ line_ = 1;
+ column_ = 0;
+ column_index_ = 0;
+ }
+
+ ~basic_csv_parser()
+ {
+ }
+
+ const basic_parsing_context<CharT>& parsing_context() const
+ {
+ return *this;
+ }
+
+ bool done() const
+ {
+ return state_ == csv_states::done;
+ }
+
+ const std::vector<std::basic_string<CharT>>& column_labels() const
+ {
+ return column_names_;
+ }
+
+ void after_field()
+ {
+ ++column_index_;
+ }
+
+ void before_record()
+ {
+ if (column_index_ == 0)
+ {
+ switch (stack_[top_])
+ {
+ case csv_modes::array:
+ handler_->begin_array(*this);
+ break;
+ case csv_modes::object:
+ handler_->begin_object(*this);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void after_record()
+ {
+ switch (stack_[top_])
+ {
+ case csv_modes::array:
+ handler_->end_array(*this);
+ break;
+ case csv_modes::object:
+ handler_->end_object(*this);
+ break;
+ case csv_modes::header:
+ if (line_ >= parameters_.header_lines())
+ {
+ if (column_names_.size() > 0)
+ {
+ flip(csv_modes::header, csv_modes::object);
+ }
+ else
+ {
+ flip(csv_modes::header, csv_modes::array);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ column_index_ = 0;
+ }
+
+ void begin_parse()
+ {
+ push(csv_modes::done);
+ handler_->begin_json();
+
+ if (parameters_.column_names().size() > 0)
+ {
+ column_names_ = parameters_.column_names();
+ }
+#if !defined(JSONCONS_NO_DEPRECATED)
+ else if (parameters_.header().length() > 0)
+ {
+ basic_empty_json_input_handler<CharT> ih;
+ basic_csv_parameters<CharT> params;
+ params.field_delimiter(parameters_.field_delimiter());
+ params.quote_char(parameters_.quote_char());
+ params.quote_escape_char(parameters_.quote_escape_char());
+ params.assume_header(true);
+ basic_csv_parser<CharT> p(ih,params);
+ p.begin_parse();
+ p.parse(parameters_.header().data(),0,parameters_.header().length());
+ p.end_parse();
+ column_names_ = p.column_labels();
+ }
+#endif
+ if (parameters_.column_types().size() > 0)
+ {
+ column_types_.resize(parameters_.column_types().size());
+ for (size_t i = 0; i < parameters_.column_types().size(); ++i)
+ {
+ if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::string_literal())
+ {
+ column_types_[i] = data_types::string_t;
+ }
+ else if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::integer_literal())
+ {
+ column_types_[i] = data_types::integer_t;
+ }
+ else if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::float_literal())
+ {
+ column_types_[i] = data_types::float_t;
+ }
+ else if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::boolean_literal())
+ {
+ column_types_[i] = data_types::boolean_t;
+ }
+ }
+ }
+#if !defined(JSONCONS_NO_DEPRECATED)
+ else if (parameters_.data_types().length() > 0)
+ {
+ basic_empty_json_input_handler<CharT> ih;
+ basic_csv_parameters<CharT> params;
+ params.field_delimiter(parameters_.field_delimiter());
+ params.assume_header(true);
+ basic_csv_parser<CharT> p(ih,params);
+ p.begin_parse();
+ p.parse(parameters_.data_types().data(),0,parameters_.data_types().length());
+ p.end_parse();
+ column_types_.resize(p.column_labels().size());
+ for (size_t i = 0; i < p.column_labels().size(); ++i)
+ {
+ if (p.column_labels()[i] == json_csv_parser_traits<CharT>::string_literal())
+ {
+ column_types_[i] = data_types::string_t;
+ }
+ else if (p.column_labels()[i] == json_csv_parser_traits<CharT>::integer_literal())
+ {
+ column_types_[i] = data_types::integer_t;
+ }
+ else if (p.column_labels()[i] == json_csv_parser_traits<CharT>::float_literal())
+ {
+ column_types_[i] = data_types::float_t;
+ }
+ else if (p.column_labels()[i] == json_csv_parser_traits<CharT>::boolean_literal())
+ {
+ column_types_[i] = data_types::boolean_t;
+ }
+ }
+ }
+#endif
+ if (parameters_.column_defaults().size() > 0)
+ {
+ column_defaults_ = parameters_.column_defaults();
+ }
+#if !defined(JSONCONS_NO_DEPRECATED)
+ else if (parameters_.default_values().length() > 0)
+ {
+ basic_empty_json_input_handler<CharT> ih;
+ basic_csv_parameters<CharT> params;
+ params.field_delimiter(parameters_.field_delimiter());
+ params.assume_header(true);
+ basic_csv_parser<CharT> p(ih,params);
+ p.begin_parse();
+ p.parse(parameters_.default_values().data(),0,parameters_.default_values().length());
+ p.end_parse();
+ column_defaults_.resize(p.column_labels().size());
+ for (size_t i = 0; i < p.column_labels().size(); ++i)
+ {
+ column_defaults_[i] = p.column_labels()[i];
+ }
+ }
+#endif
+ if (parameters_.header_lines() > 0)
+ {
+ push(csv_modes::header);
+ }
+ else
+ {
+ push(csv_modes::array);
+ }
+ handler_->begin_array(*this);
+ state_ = csv_states::expect_value;
+ column_index_ = 0;
+ prev_char_ = 0;
+ curr_char_ = 0;
+ column_ = 1;
+ }
+
+ void parse(const CharT* p, size_t start, size_t length)
+ {
+ index_ = start;
+ for (; index_ < length && state_ != csv_states::done; ++index_)
+ {
+ curr_char_ = p[index_];
+all_csv_states:
+ switch (state_)
+ {
+ case csv_states::comment:
+ if (curr_char_ == '\n')
+ {
+ state_ = csv_states::expect_value;
+ }
+ else if (prev_char_ == '\r')
+ {
+ state_ = csv_states::expect_value;
+ goto all_csv_states;
+ }
+ break;
+ case csv_states::expect_value:
+ if (column_ == 1 && curr_char_ == parameters_.comment_starter())
+ {
+ state_ = csv_states::comment;
+ }
+ else
+ {
+ state_ = csv_states::unquoted_string;
+ goto all_csv_states;
+ }
+ break;
+ case csv_states::between_fields:
+ if (curr_char_ == '\r' || (prev_char_ != '\r' && curr_char_ == '\n'))
+ {
+ after_record();
+ state_ = csv_states::expect_value;
+ }
+ else if (curr_char_ == parameters_.field_delimiter())
+ {
+ state_ = csv_states::expect_value;
+ }
+ break;
+ case csv_states::escaped_value:
+ {
+ if (curr_char_ == parameters_.quote_char())
+ {
+ string_buffer_.push_back(curr_char_);
+ state_ = csv_states::quoted_string;
+ }
+ else if (parameters_.quote_escape_char() == parameters_.quote_char())
+ {
+ before_record();
+ end_quoted_string_value();
+ after_field();
+ state_ = csv_states::between_fields;
+ goto all_csv_states;
+ }
+ }
+ break;
+ case csv_states::quoted_string:
+ {
+ if (curr_char_ == parameters_.quote_escape_char())
+ {
+ state_ = csv_states::escaped_value;
+ }
+ else if (curr_char_ == parameters_.quote_char())
+ {
+ before_record();
+ end_quoted_string_value();
+ after_field();
+ state_ = csv_states::between_fields;
+ }
+ else
+ {
+ string_buffer_.push_back(curr_char_);
+ }
+ }
+ break;
+ case csv_states::unquoted_string:
+ {
+ if (curr_char_ == '\r' || (prev_char_ != '\r' && curr_char_ == '\n'))
+ {
+ before_record();
+ end_unquoted_string_value();
+ after_field();
+ after_record();
+ state_ = csv_states::expect_value;
+ }
+ else if (curr_char_ == '\n')
+ {
+ if (prev_char_ != '\r')
+ {
+ before_record();
+ end_unquoted_string_value();
+ after_field();
+ after_record();
+ state_ = csv_states::expect_value;
+ }
+ }
+ else if (curr_char_ == parameters_.field_delimiter())
+ {
+ before_record();
+ end_unquoted_string_value();
+ after_field();
+ state_ = csv_states::expect_value;
+ }
+ else if (curr_char_ == parameters_.quote_char())
+ {
+ string_buffer_.clear();
+ state_ = csv_states::quoted_string;
+ }
+ else
+ {
+ string_buffer_.push_back(curr_char_);
+ }
+ }
+ break;
+ default:
+ err_handler_->error(std::error_code(csv_parser_errc::invalid_state, csv_error_category()), *this);
+ break;
+ }
+ if (line_ > parameters_.max_lines())
+ {
+ state_ = csv_states::done;
+ }
+ switch (curr_char_)
+ {
+ case '\r':
+ ++line_;
+ column_ = 1;
+ break;
+ case '\n':
+ if (prev_char_ != '\r')
+ {
+ ++line_;
+ }
+ column_ = 1;
+ break;
+ default:
+ ++column_;
+ break;
+ }
+ prev_char_ = curr_char_;
+ }
+ }
+
+ void end_parse()
+ {
+ switch (state_)
+ {
+ case csv_states::unquoted_string:
+ before_record();
+ end_unquoted_string_value();
+ after_field();
+ break;
+ case csv_states::escaped_value:
+ if (parameters_.quote_escape_char() == parameters_.quote_char())
+ {
+ before_record();
+ end_quoted_string_value();
+ after_field();
+ }
+ break;
+ default:
+ break;
+ }
+ if (column_index_ > 0)
+ {
+ after_record();
+ }
+ switch (stack_[top_])
+ {
+ case csv_modes::array:
+ if (!pop(csv_modes::array))
+ {
+ err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this);
+ }
+ break;
+ case csv_modes::object:
+ if (!pop(csv_modes::object))
+ {
+ err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this);
+ }
+ break;
+ case csv_modes::header:
+ if (!pop(csv_modes::header))
+ {
+ err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this);
+ }
+ break;
+ default:
+ break;
+ }
+ handler_->end_array(*this);
+ if (!pop(csv_modes::done))
+ {
+ err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this);
+ }
+ handler_->end_json();
+ }
+
+ csv_states state() const
+ {
+ return state_;
+ }
+
+ size_t index() const
+ {
+ return index_;
+ }
+private:
+
+ void trim_string_buffer(bool trim_leading, bool trim_trailing)
+ {
+ size_t start = 0;
+ size_t length = string_buffer_.length();
+ if (trim_leading)
+ {
+ bool done = false;
+ while (!done && start < string_buffer_.length())
+ {
+ if ((string_buffer_[start] < 256) && std::isspace(string_buffer_[start]))
+ {
+ ++start;
+ }
+ else
+ {
+ done = true;
+ }
+ }
+ }
+ if (trim_trailing)
+ {
+ bool done = false;
+ while (!done && length > 0)
+ {
+ if ((string_buffer_[length-1] < 256) && std::isspace(string_buffer_[length-1]))
+ {
+ --length;
+ }
+ else
+ {
+ done = true;
+ }
+ }
+ }
+ if (start != 0 || length != string_buffer_.size())
+ {
+ string_buffer_ = string_buffer_.substr(start,length-start);
+ }
+ }
+
+ void end_unquoted_string_value()
+ {
+ if (parameters_.trim_leading() | parameters_.trim_trailing())
+ {
+ trim_string_buffer(parameters_.trim_leading(),parameters_.trim_trailing());
+ }
+ switch (stack_[top_])
+ {
+ case csv_modes::header:
+ if (parameters_.assume_header() && line_ == 1)
+ {
+ column_names_.push_back(string_buffer_);
+ }
+ break;
+ case csv_modes::object:
+ if (!(parameters_.ignore_empty_values() && string_buffer_.size() == 0))
+ {
+ if (column_index_ < column_names_.size())
+ {
+ handler_->name(column_names_[column_index_].data(), column_names_[column_index_].length(), *this);
+ if (parameters_.unquoted_empty_value_is_null() && string_buffer_.length() == 0)
+ {
+ handler_->value(jsoncons::null_type(),*this);
+ }
+ else
+ {
+ end_value();
+ }
+ }
+ }
+ break;
+ case csv_modes::array:
+ if (parameters_.unquoted_empty_value_is_null() && string_buffer_.length() == 0)
+ {
+ handler_->value(jsoncons::null_type(),*this);
+ }
+ else
+ {
+ end_value();
+ }
+ break;
+ default:
+ err_handler_->error(std::error_code(csv_parser_errc::invalid_csv_text, csv_error_category()), *this);
+ break;
+ }
+ state_ = csv_states::expect_value;
+ string_buffer_.clear();
+ }
+
+ void end_quoted_string_value()
+ {
+ if (parameters_.trim_leading_inside_quotes() | parameters_.trim_trailing_inside_quotes())
+ {
+ trim_string_buffer(parameters_.trim_leading_inside_quotes(),parameters_.trim_trailing_inside_quotes());
+ }
+ switch (stack_[top_])
+ {
+ case csv_modes::header:
+ if (parameters_.assume_header() && line_ == 1)
+ {
+ column_names_.push_back(string_buffer_);
+ }
+ break;
+ case csv_modes::object:
+ if (!(parameters_.ignore_empty_values() && string_buffer_.size() == 0))
+ {
+ if (column_index_ < column_names_.size())
+ {
+ handler_->name(column_names_[column_index_].data(), column_names_[column_index_].length(), *this);
+ end_value();
+ }
+ }
+ break;
+ case csv_modes::array:
+ end_value();
+ break;
+ default:
+ err_handler_->error(std::error_code(csv_parser_errc::invalid_csv_text, csv_error_category()), *this);
+ break;
+ }
+ state_ = csv_states::expect_value;
+ string_buffer_.clear();
+ }
+
+ void end_value()
+ {
+ if (column_index_ < column_types_.size())
+ {
+ switch (column_types_[column_index_])
+ {
+ case data_types::integer_t:
+ {
+ std::istringstream iss(string_buffer_);
+ long long val;
+ iss >> val;
+ if (!iss.fail())
+ {
+ handler_->value(val, *this);
+ }
+ else
+ {
+ if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0)
+ {
+ parser_.begin_parse();
+ parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length());
+ parser_.end_parse();
+ }
+ else
+ {
+ handler_->value(null_type(), *this);
+ }
+ }
+ }
+ break;
+ case data_types::float_t:
+ {
+ std::istringstream iss(string_buffer_);
+ double val;
+ iss >> val;
+ if (!iss.fail())
+ {
+ handler_->value(val, 0, *this);
+ }
+ else
+ {
+ if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0)
+ {
+ parser_.begin_parse();
+ parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length());
+ parser_.end_parse();
+ }
+ else
+ {
+ handler_->value(null_type(), *this);
+ }
+ }
+ }
+ break;
+ case data_types::boolean_t:
+ {
+ if (string_buffer_.length() == 1 && string_buffer_[0] == '0')
+ {
+ handler_->value(false, *this);
+ }
+ else if (string_buffer_.length() == 1 && string_buffer_[0] == '1')
+ {
+ handler_->value(true, *this);
+ }
+ else if (string_buffer_.length() == 5 && ((string_buffer_[0] == 'f' || string_buffer_[0] == 'F') && (string_buffer_[1] == 'a' || string_buffer_[1] == 'A') && (string_buffer_[2] == 'l' || string_buffer_[2] == 'L') && (string_buffer_[3] == 's' || string_buffer_[3] == 'S') && (string_buffer_[4] == 'e' || string_buffer_[4] == 'E')))
+ {
+ handler_->value(false, *this);
+ }
+ else if (string_buffer_.length() == 4 && ((string_buffer_[0] == 't' || string_buffer_[0] == 'T') && (string_buffer_[1] == 'r' || string_buffer_[1] == 'R') && (string_buffer_[2] == 'u' || string_buffer_[2] == 'U') && (string_buffer_[3] == 'e' || string_buffer_[3] == 'E')))
+ {
+ handler_->value(true, *this);
+ }
+ else
+ {
+ if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0)
+ {
+ parser_.begin_parse();
+ parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length());
+ parser_.end_parse();
+ }
+ else
+ {
+ handler_->value(null_type(), *this);
+ }
+ }
+ }
+ break;
+ default:
+ if (string_buffer_.length() > 0)
+ {
+ handler_->value(string_buffer_.data(), string_buffer_.length(), *this);
+ }
+ else
+ {
+ if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0)
+ {
+ parser_.begin_parse();
+ parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length());
+ parser_.end_parse();
+ }
+ else
+ {
+ handler_->value("", *this);
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ handler_->value(string_buffer_.data(), string_buffer_.length(), *this);
+ }
+ }
+
+ 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 (CharT)prev_char_;
+ }
+
+ void push(csv_modes mode)
+ {
+ ++top_;
+ if (top_ >= depth_)
+ {
+ depth_ *= 2;
+ stack_.resize(depth_);
+ }
+ stack_[top_] = mode;
+ }
+
+ int peek()
+ {
+ return stack_[top_];
+ }
+
+ bool peek(csv_modes mode)
+ {
+ return stack_[top_] == mode;
+ }
+
+ bool flip(csv_modes mode1, csv_modes mode2)
+ {
+ if (top_ < 0 || stack_[top_] != mode1)
+ {
+ return false;
+ }
+ stack_[top_] = mode2;
+ return true;
+ }
+
+ bool pop(csv_modes mode)
+ {
+ if (top_ < 0 || stack_[top_] != mode)
+ {
+ return false;
+ }
+ --top_;
+ return true;
+ }
+};
+
+typedef basic_csv_parser<char> csv_parser;
+typedef basic_csv_parser<wchar_t> wcsv_parser;
+
+}}
+
+#endif
+
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp
new file mode 100644
index 00000000..38213e25
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp
@@ -0,0 +1,175 @@
+// 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_CSV_CSV_READER_HPP
+#define JSONCONS_CSV_CSV_READER_HPP
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <stdexcept>
+#include "jsoncons/jsoncons.hpp"
+#include "jsoncons/json_input_handler.hpp"
+#include "jsoncons/parse_error_handler.hpp"
+#include "jsoncons_ext/csv/csv_error_category.hpp"
+#include "jsoncons_ext/csv/csv_parser.hpp"
+#include "jsoncons/json.hpp"
+
+namespace jsoncons { namespace csv {
+
+template<typename CharT>
+class basic_csv_reader
+{
+ struct stack_item
+ {
+ stack_item()
+ : array_begun_(false)
+ {
+ }
+
+ bool array_begun_;
+ };
+public:
+ // Structural characters
+ static const size_t default_max_buffer_length = 16384;
+ //! Parse an input stream of CSV text into a json object
+ /*!
+ \param is The input stream to read from
+ */
+
+ basic_csv_reader(std::basic_istream<CharT>& is,
+ basic_json_input_handler<CharT>& handler)
+
+ : parser_(handler),
+ is_(std::addressof(is)),
+ buffer_(default_max_buffer_length),
+ buffer_capacity_(default_max_buffer_length),
+ buffer_position_(0),
+ buffer_length_(0),
+ eof_(false),
+ index_(0)
+ {
+ }
+
+ basic_csv_reader(std::basic_istream<CharT>& is,
+ basic_json_input_handler<CharT>& handler,
+ basic_csv_parameters<CharT> params)
+
+ : parser_(handler,params),
+ is_(std::addressof(is)),
+ buffer_(default_max_buffer_length),
+ buffer_capacity_(default_max_buffer_length),
+ buffer_position_(0),
+ buffer_length_(0),
+ eof_(false),
+ index_(0)
+ {
+ }
+
+ basic_csv_reader(std::basic_istream<CharT>& is,
+ basic_json_input_handler<CharT>& handler,
+ basic_parse_error_handler<CharT>& err_handler)
+ :
+ parser_(handler,err_handler),
+ is_(std::addressof(is)),
+ buffer_(),
+ buffer_capacity_(default_max_buffer_length),
+ buffer_position_(0),
+ buffer_length_(0),
+ eof_(false),
+ index_(0)
+
+
+ {
+ }
+
+ basic_csv_reader(std::basic_istream<CharT>& is,
+ basic_json_input_handler<CharT>& handler,
+ basic_parse_error_handler<CharT>& err_handler,
+ basic_csv_parameters<CharT> params)
+ :
+ parser_(handler,err_handler,params),
+ is_(std::addressof(is)),
+ buffer_(),
+ buffer_capacity_(default_max_buffer_length),
+ buffer_position_(0),
+ buffer_length_(0),
+ eof_(false),
+ index_(0)
+ {
+ }
+
+ ~basic_csv_reader()
+ {
+ }
+
+ void read()
+ {
+ parser_.begin_parse();
+ while (!eof_ && !parser_.done())
+ {
+ if (!(index_ < buffer_length_))
+ {
+ if (!is_->eof())
+ {
+ is_->read(buffer_.data(), buffer_capacity_);
+ buffer_length_ = static_cast<size_t>(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();
+ }
+
+ bool eof() const
+ {
+ return eof_;
+ }
+
+ size_t buffer_capacity() const
+ {
+ return buffer_capacity_;
+ }
+
+ void buffer_capacity(size_t buffer_capacity)
+ {
+ buffer_capacity_ = buffer_capacity;
+ }
+
+private:
+ basic_csv_reader(const basic_csv_reader&) = delete;
+ basic_csv_reader& operator = (const basic_csv_reader&) = delete;
+
+ basic_csv_parser<CharT> parser_;
+ std::basic_istream<CharT>* is_;
+ std::vector<CharT> buffer_;
+ size_t buffer_capacity_;
+ size_t buffer_position_;
+ size_t buffer_length_;
+ bool eof_;
+ size_t index_;
+};
+
+typedef basic_csv_reader<char> csv_reader;
+
+}}
+
+#endif
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp
new file mode 100644
index 00000000..f331b629
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp
@@ -0,0 +1,445 @@
+// 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_CSV_CSV_SERIALIZER_HPP
+#define JSONCONS_CSV_CSV_SERIALIZER_HPP
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <ostream>
+#include <cstdlib>
+#include <map>
+#include "jsoncons/jsoncons.hpp"
+#include "jsoncons/output_format.hpp"
+#include "jsoncons/json_output_handler.hpp"
+#include <limits> // std::numeric_limits
+
+namespace jsoncons { namespace csv {
+
+template <typename CharT>
+struct csv_char_traits
+{
+};
+
+template <>
+struct csv_char_traits<char>
+{
+ static const std::string all_literal() {return "all";};
+
+ static const std::string minimal_literal() {return "minimal";};
+
+ static const std::string none_literal() {return "none";};
+
+ static const std::string nonnumeric_literal() {return "nonumeric";};
+};
+
+template <>
+struct csv_char_traits<wchar_t>
+{
+ static const std::wstring all_literal() {return L"all";};
+
+ static const std::wstring minimal_literal() {return L"minimal";};
+
+ static const std::wstring none_literal() {return L"none";};
+
+ static const std::wstring nonnumeric_literal() {return L"nonumeric";};
+};
+
+template <typename CharT>
+void escape_string(const CharT* s,
+ size_t length,
+ CharT quote_char, CharT quote_escape_char,
+ buffered_ostream<CharT>& os)
+{
+ const CharT* begin = s;
+ const CharT* end = s + length;
+ for (const CharT* it = begin; it != end; ++it)
+ {
+ CharT c = *it;
+ if (c == quote_char)
+ {
+ os.put(quote_escape_char);
+ os.put(quote_char);
+ }
+ else
+ {
+ os.put(c);
+ }
+ }
+}
+
+template<typename CharT>
+class basic_csv_serializer : public basic_json_output_handler<CharT>
+{
+ struct stack_item
+ {
+ stack_item(bool is_object)
+ : is_object_(is_object), count_(0), skip_(false)
+ {
+ }
+ bool is_object() const
+ {
+ return is_object_;
+ }
+
+ bool is_object_;
+ size_t count_;
+ bool skip_;
+ };
+ buffered_ostream<CharT> os_;
+ basic_csv_parameters<CharT> parameters_;
+ basic_output_format<CharT> format_;
+ std::vector<stack_item> stack_;
+ std::streamsize original_precision_;
+ std::ios_base::fmtflags original_format_flags_;
+ std::basic_ostringstream<CharT> header_oss_;
+ buffered_ostream<CharT> header_os_;
+ std::map<std::basic_string<CharT>,size_t> header_;
+ float_printer<CharT> fp_;
+public:
+ basic_csv_serializer(std::basic_ostream<CharT>& os)
+ :
+ os_(os),
+ format_(),
+ stack_(),
+ original_precision_(),
+ original_format_flags_(),
+ header_os_(header_oss_),
+ header_(),
+ fp_(format_.precision())
+ {
+ }
+
+ basic_csv_serializer(std::basic_ostream<CharT>& os,
+ basic_csv_parameters<CharT> params)
+ :
+ os_(os),
+ parameters_(params),
+ format_(),
+ stack_(),
+ original_precision_(),
+ original_format_flags_(),
+ header_os_(header_oss_),
+ header_(),
+ fp_(format_.precision())
+ {
+ }
+
+ ~basic_csv_serializer()
+ {
+ }
+
+private:
+
+ void do_begin_json() override
+ {
+ }
+
+ void do_end_json() override
+ {
+ }
+
+ void do_begin_object() override
+ {
+ stack_.push_back(stack_item(true));
+ }
+
+ void do_end_object() override
+ {
+ if (stack_.size() == 2)
+ {
+ os_.write(parameters_.line_delimiter());
+ if (stack_[0].count_ == 0)
+ {
+ os_.write(header_oss_.str());
+ os_.write(parameters_.line_delimiter());
+ }
+ }
+ stack_.pop_back();
+
+ end_value();
+ }
+
+ void do_begin_array() override
+ {
+ stack_.push_back(stack_item(false));
+ }
+
+ void do_end_array() override
+ {
+ if (stack_.size() == 2)
+ {
+ os_.write(parameters_.line_delimiter());
+ }
+ stack_.pop_back();
+
+ end_value();
+ }
+
+ void do_name(const CharT* name, size_t length) override
+ {
+ if (stack_.size() == 2)
+ {
+ if (stack_[0].count_ == 0)
+ {
+ if (stack_.back().count_ > 0)
+ {
+ os_.put(parameters_.field_delimiter());
+ }
+ bool quote = false;
+ if (parameters_.quote_style() == quote_styles::all || parameters_.quote_style() == quote_styles::nonnumeric ||
+ (parameters_.quote_style() == quote_styles::minimal && std::char_traits<CharT>::find(name,length,parameters_.field_delimiter()) != nullptr))
+ {
+ quote = true;
+ os_.put(parameters_.quote_char());
+ }
+ jsoncons::csv::escape_string<CharT>(name, length, parameters_.quote_char(), parameters_.quote_escape_char(), os_);
+ if (quote)
+ {
+ os_.put(parameters_.quote_char());
+ }
+ header_[name] = stack_.back().count_;
+ }
+ else
+ {
+ typename std::map<std::basic_string<CharT>,size_t>::iterator it = header_.find(std::basic_string<CharT>(name,length));
+ if (it == header_.end())
+ {
+ stack_.back().skip_ = true;
+ //std::cout << " Not found ";
+ }
+ else
+ {
+ stack_.back().skip_ = false;
+ while (stack_.back().count_ < it->second)
+ {
+ os_.put(parameters_.field_delimiter());
+ ++stack_.back().count_;
+ }
+ // std::cout << " (" << it->value() << " " << stack_.back().count_ << ") ";
+ }
+ }
+ }
+ }
+
+ void do_null_value() override
+ {
+ if (stack_.size() == 2 && !stack_.back().skip_)
+ {
+ if (stack_.back().is_object() && stack_[0].count_ == 0)
+ {
+ do_null_value(header_os_);
+ }
+ else
+ {
+ do_null_value(os_);
+ }
+ }
+ }
+
+ void do_string_value(const CharT* val, size_t length) override
+ {
+ if (stack_.size() == 2 && !stack_.back().skip_)
+ {
+ if (stack_.back().is_object() && stack_[0].count_ == 0)
+ {
+ value(val,length,header_os_);
+ }
+ else
+ {
+ value(val,length,os_);
+ }
+ }
+ }
+
+ void do_double_value(double val, uint8_t precision) override
+ {
+ if (stack_.size() == 2 && !stack_.back().skip_)
+ {
+ if (stack_.back().is_object() && stack_[0].count_ == 0)
+ {
+ value(val,header_os_);
+ }
+ else
+ {
+ value(val,os_);
+ }
+ }
+ }
+
+ void do_integer_value(int64_t val) override
+ {
+ if (stack_.size() == 2 && !stack_.back().skip_)
+ {
+ if (stack_.back().is_object() && stack_[0].count_ == 0)
+ {
+ value(val,header_os_);
+ }
+ else
+ {
+ value(val,os_);
+ }
+ }
+ }
+
+ void do_uinteger_value(uint64_t val) override
+ {
+ if (stack_.size() == 2 && !stack_.back().skip_)
+ {
+ if (stack_.back().is_object() && stack_[0].count_ == 0)
+ {
+ value(val,header_os_);
+ }
+ else
+ {
+ value(val,os_);
+ }
+ }
+ }
+
+ void do_bool_value(bool val) override
+ {
+ if (stack_.size() == 2 && !stack_.back().skip_)
+ {
+ if (stack_.back().is_object() && stack_[0].count_ == 0)
+ {
+ value(val,header_os_);
+ }
+ else
+ {
+ value(val,os_);
+ }
+ }
+ }
+
+ void value(const CharT* val, size_t length, buffered_ostream<CharT>& os)
+ {
+ begin_value(os);
+
+ bool quote = false;
+ if (parameters_.quote_style() == quote_styles::all || parameters_.quote_style() == quote_styles::nonnumeric ||
+ (parameters_.quote_style() == quote_styles::minimal && std::char_traits<CharT>::find(val, length, parameters_.field_delimiter()) != nullptr))
+ {
+ quote = true;
+ os.put(parameters_.quote_char());
+ }
+ jsoncons::csv::escape_string<CharT>(val, length, parameters_.quote_char(), parameters_.quote_escape_char(), os);
+ if (quote)
+ {
+ os.put(parameters_.quote_char());
+ }
+
+ end_value();
+ }
+
+ void value(double val, buffered_ostream<CharT>& os)
+ {
+ begin_value(os);
+
+ if (is_nan(val) && format_.replace_nan())
+ {
+ os.write(format_.nan_replacement());
+ }
+ else if (is_pos_inf(val) && format_.replace_pos_inf())
+ {
+ os.write(format_.pos_inf_replacement());
+ }
+ else if (is_neg_inf(val) && format_.replace_neg_inf())
+ {
+ os.write(format_.neg_inf_replacement());
+ }
+ //else if (format_.floatfield() != 0)
+ //{
+ // std::basic_ostringstream<CharT> ss;
+ // ss.imbue(std::locale::classic());
+ // ss.setf(format_.floatfield(), std::ios::floatfield);
+ // ss << std::showpoint << std::setprecision(format_.precision()) << val;
+ // os.write(ss.str());
+ //}
+ else
+ {
+ fp_.print(val,format_.precision(),os);
+ }
+
+ end_value();
+
+ }
+
+ void value(int64_t val, buffered_ostream<CharT>& os)
+ {
+ begin_value(os);
+
+ std::basic_ostringstream<CharT> ss;
+ ss << val;
+ os.write(ss.str());
+
+ end_value();
+ }
+
+ void value(uint64_t val, buffered_ostream<CharT>& os)
+ {
+ begin_value(os);
+
+ std::basic_ostringstream<CharT> ss;
+ ss << val;
+ os.write(ss.str());
+
+ end_value();
+ }
+
+ void value(bool val, buffered_ostream<CharT>& os)
+ {
+ begin_value(os);
+
+ if (val)
+ {
+ auto buf = json_literals<CharT>::true_literal();
+ os.write(buf.first,buf.second);
+ }
+ else
+ {
+ auto buf = json_literals<CharT>::false_literal();
+ os.write(buf.first,buf.second);
+ }
+
+ end_value();
+ }
+
+ void do_null_value(buffered_ostream<CharT>& os)
+ {
+ begin_value(os);
+ auto buf = json_literals<CharT>::null_literal();
+ os.write(buf.first,buf.second);
+ end_value();
+
+ }
+
+ void begin_value(buffered_ostream<CharT>& os)
+ {
+ if (!stack_.empty())
+ {
+ if (stack_.back().count_ > 0)
+ {
+ os.put(parameters_.field_delimiter());
+ }
+ }
+ }
+
+ void end_value()
+ {
+ if (!stack_.empty())
+ {
+ ++stack_.back().count_;
+ }
+ }
+};
+
+typedef basic_csv_serializer<char> csv_serializer;
+
+}}
+
+#endif
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/json_query.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/json_query.hpp
new file mode 100644
index 00000000..7e530abd
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/json_query.hpp
@@ -0,0 +1,921 @@
+// 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_JSONPATH_JSONQUERY_HPP
+#define JSONCONS_JSONPATH_JSONQUERY_HPP
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <memory>
+#include "jsoncons/json.hpp"
+#include "jsonpath_filter.hpp"
+#include "jsonpath_error_category.hpp"
+
+namespace jsoncons { namespace jsonpath {
+
+ template<typename CharT>
+ bool try_string_to_index(const CharT *s, size_t length, size_t* value)
+ {
+ static const size_t max_value = std::numeric_limits<size_t>::max JSONCONS_NO_MACRO_EXP();
+ static const size_t max_value_div_10 = max_value / 10;
+
+ size_t n = 0;
+ for (size_t i = 0; i < length; ++i)
+ {
+ CharT c = s[i];
+ switch (c)
+ {
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
+ {
+ size_t x = c - '0';
+ if (n > max_value_div_10)
+ {
+ return false;
+ }
+ n = n * 10;
+ if (n > max_value - x)
+ {
+ return false;
+ }
+
+ n += x;
+ }
+ break;
+ default:
+ return false;
+ break;
+ }
+ }
+ *value = n;
+ return true;
+ }
+
+ template <typename CharT>
+ struct json_jsonpath_traits
+ {
+ };
+
+ template <>
+ struct json_jsonpath_traits<char>
+ {
+ static const std::string length_literal() {return "length";};
+ };
+
+ template <>
+ struct json_jsonpath_traits<wchar_t> // assume utf16
+ {
+ static const std::wstring length_literal() {return L"length";};
+ };
+
+// here
+
+template<class JsonT>
+JsonT json_query(const JsonT& root, const typename JsonT::char_type* path, size_t length)
+{
+ jsonpath_evaluator<JsonT> evaluator;
+ evaluator.evaluate(root,path,length);
+ return evaluator.get_values();
+}
+
+template<class JsonT>
+JsonT json_query(const JsonT& root, const typename JsonT::string_type& path)
+{
+ return json_query(root,path.data(),path.length());
+}
+
+template<class JsonT>
+JsonT json_query(const JsonT& root, const typename JsonT::char_type* path)
+{
+ return json_query(root,path,std::char_traits<typename JsonT::char_type>::length(path));
+}
+
+enum class states
+{
+ start,
+ cr,
+ lf,
+ expect_separator,
+ expect_unquoted_name,
+ unquoted_name,
+ single_quoted_name,
+ double_quoted_name,
+ left_bracket,
+ left_bracket_start,
+ left_bracket_end,
+ left_bracket_end2,
+ left_bracket_step,
+ left_bracket_step2,
+ expect_right_bracket,
+ dot
+};
+
+template<class JsonT>
+class jsonpath_evaluator : private basic_parsing_context<typename JsonT::char_type>
+{
+private:
+ typedef typename JsonT::char_type char_type;
+ typedef typename JsonT::string_type string_type;
+ typedef const JsonT* cjson_ptr;
+ typedef std::vector<cjson_ptr> node_set;
+
+ basic_parse_error_handler<char_type> *err_handler_;
+ states state_;
+ string_type buffer_;
+ size_t start_;
+ size_t end_;
+ size_t step_;
+ bool positive_start_;
+ bool positive_end_;
+ bool positive_step_;
+ bool end_undefined_;
+ std::vector<node_set> stack_;
+ bool recursive_descent_;
+ std::vector<cjson_ptr> nodes_;
+ std::vector<std::shared_ptr<JsonT>> temp_;
+ size_t line_;
+ size_t column_;
+ const char_type* begin_input_;
+ const char_type* end_input_;
+ const char_type* p_;
+ states pre_line_break_state_;
+
+ void transfer_nodes()
+ {
+ stack_.push_back(nodes_);
+ nodes_.clear();
+ }
+
+public:
+ jsonpath_evaluator()
+ : err_handler_(std::addressof(basic_default_parse_error_handler<char_type>::instance()))
+ {
+ }
+
+ JsonT get_values() const
+ {
+ JsonT result = JsonT::make_array();
+
+ if (stack_.size() > 0)
+ {
+ for (size_t i = 0; i < stack_.back().size(); ++i)
+ {
+ cjson_ptr p = stack_.back()[i];
+ result.add(*p);
+ }
+ }
+ return result;
+ }
+
+ void evaluate(const JsonT& root, const string_type& path)
+ {
+ evaluate(root,path.data(),path.length());
+ }
+ void evaluate(const JsonT& root, const char_type* path)
+ {
+ evaluate(root,path,std::char_traits<char_type>::length(path));
+ }
+
+ void evaluate(const JsonT& root, const char_type* path, size_t length)
+ {
+ begin_input_ = path;
+ end_input_ = path + length;
+ p_ = begin_input_;
+
+ line_ = 1;
+ column_ = 1;
+ state_ = states::start;
+ buffer_.clear();
+ start_ = 0;
+ end_ = 0;
+ step_ = 1;
+ recursive_descent_ = false;
+ positive_start_ = true;
+ positive_end_ = true;
+ positive_step_ = true;
+ end_undefined_ = false;
+
+ while (p_ < end_input_)
+ {
+ switch (state_)
+ {
+ case states::cr:
+ ++line_;
+ column_ = 1;
+ switch (*p_)
+ {
+ case '\n':
+ state_ = pre_line_break_state_;
+ ++p_;
+ ++column_;
+ break;
+ default:
+ state_ = pre_line_break_state_;
+ break;
+ }
+ break;
+ case states::lf:
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case states::start:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case ' ':case '\t':
+ ++p_;
+ ++column_;
+ break;
+ case '$':
+ case '@':
+ {
+ node_set v;
+ v.push_back(std::addressof(root));
+ stack_.push_back(v);
+ state_ = states::expect_separator;
+ }
+ break;
+ default:
+ err_handler_->fatal_error(std::error_code(jsonpath_parser_errc::expected_root, jsonpath_error_category()), *this);
+ break;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case states::dot:
+ switch (*p_)
+ {
+ case '.':
+ recursive_descent_ = true;
+ ++p_;
+ ++column_;
+ state_ = states::expect_unquoted_name;
+ break;
+ default:
+ state_ = states::expect_unquoted_name;
+ break;
+ }
+ break;
+ case states::expect_unquoted_name:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case '.':
+ err_handler_->fatal_error(std::error_code(jsonpath_parser_errc::expected_name, jsonpath_error_category()), *this);
+ ++p_;
+ ++column_;
+ break;
+ case '*':
+ end_all();
+ transfer_nodes();
+ state_ = states::expect_separator;
+ ++p_;
+ ++column_;
+ break;
+ default:
+ state_ = states::unquoted_name;
+ break;
+ }
+ break;
+ case states::expect_separator:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case ' ':case '\t':
+ ++p_;
+ ++column_;
+ break;
+ case '.':
+ state_ = states::dot;
+ break;
+ case '[':
+ state_ = states::left_bracket;
+ break;
+ default:
+ err_handler_->fatal_error(std::error_code(jsonpath_parser_errc::expected_separator, jsonpath_error_category()), *this);
+ break;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case states::expect_right_bracket:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case ',':
+ state_ = states::left_bracket;
+ break;
+ case ']':
+ transfer_nodes();
+ state_ = states::expect_separator;
+ break;
+ case ' ':case '\t':
+ break;
+ default:
+ err_handler_->fatal_error(std::error_code(jsonpath_parser_errc::expected_right_bracket, jsonpath_error_category()), *this);
+ break;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::left_bracket_step:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case '-':
+ positive_step_ = false;
+ state_ = states::left_bracket_step2;
+ break;
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
+ step_ = static_cast<size_t>(*p_-'0');
+ state_ = states::left_bracket_step2;
+ break;
+ case ']':
+ end_array_slice();
+ transfer_nodes();
+ state_ = states::expect_separator;
+ break;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::left_bracket_step2:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
+ step_ = step_*10 + static_cast<size_t>(*p_-'0');
+ break;
+ case ']':
+ end_array_slice();
+ transfer_nodes();
+ state_ = states::expect_separator;
+ break;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::left_bracket_end:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case '-':
+ positive_end_ = false;
+ state_ = states::left_bracket_end2;
+ break;
+ case ':':
+ step_ = 0;
+ state_ = states::left_bracket_step;
+ break;
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
+ end_undefined_ = false;
+ end_ = static_cast<size_t>(*p_-'0');
+ state_ = states::left_bracket_end2;
+ break;
+ case ']':
+ end_array_slice();
+ transfer_nodes();
+ state_ = states::expect_separator;
+ break;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::left_bracket_end2:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case ':':
+ step_ = 0;
+ state_ = states::left_bracket_step;
+ break;
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
+ end_undefined_ = false;
+ end_ = end_*10 + static_cast<size_t>(*p_-'0');
+ break;
+ case ']':
+ end_array_slice();
+ transfer_nodes();
+ state_ = states::expect_separator;
+ break;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::left_bracket_start:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case ':':
+ step_ = 1;
+ end_undefined_ = true;
+ state_ = states::left_bracket_end;
+ break;
+ case ',':
+ find_elements();
+ break;
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
+ start_ = start_*10 + static_cast<size_t>(*p_-'0');
+ break;
+ case ']':
+ find_elements();
+ transfer_nodes();
+ state_ = states::expect_separator;
+ break;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::left_bracket:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case ' ':case '\t':
+ ++p_;
+ ++column_;
+ break;
+ case '(':
+ {
+ if (stack_.back().size() == 1)
+ {
+ jsonpath_filter_parser<JsonT> parser(&p_,&line_,&column_);
+ parser.parse(p_,end_input_);
+ auto index = parser.eval(*(stack_.back()[0]));
+ if (index.template is<size_t>())
+ {
+ start_ = index. template as<size_t>();
+ find_elements();
+ }
+ else if (index.is_string())
+ {
+ find(index.as_string());
+ }
+ }
+ else
+ {
+ ++p_;
+ ++column_;
+ }
+ }
+ break;
+ case '?':
+ {
+ jsonpath_filter_parser<JsonT> parser(&p_,&line_,&column_);
+ parser.parse(p_,end_input_);
+ nodes_.clear();
+ for (size_t j = 0; j < stack_.back().size(); ++j)
+ {
+ accept(*(stack_.back()[j]),parser);
+ }
+ }
+ break;
+
+ case ':':
+ step_ = 1;
+ end_undefined_ = true;
+ state_ = states::left_bracket_end;
+ ++p_;
+ ++column_;
+ break;
+ case ',':
+ find_elements();
+ ++p_;
+ ++column_;
+ break;
+ case '-':
+ positive_start_ = false;
+ state_ = states::left_bracket_start;
+ ++p_;
+ ++column_;
+ break;
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
+ start_ = static_cast<size_t>(*p_-'0');
+ state_ = states::left_bracket_start;
+ ++p_;
+ ++column_;
+ break;
+ case ']':
+ //find_elements();
+ transfer_nodes();
+ state_ = states::expect_separator;
+ ++p_;
+ ++column_;
+ break;
+ case '*':
+ end_all();
+ //transfer_nodes();
+ state_ = states::expect_right_bracket;
+ ++p_;
+ ++column_;
+ break;
+ case '\'':
+ state_ = states::single_quoted_name;
+ ++p_;
+ ++column_;
+ break;
+ case '\"':
+ state_ = states::double_quoted_name;
+ ++p_;
+ ++column_;
+ break;
+ default:
+ ++p_;
+ ++column_;
+ break;
+ }
+ break;
+ case states::unquoted_name:
+ switch (*p_)
+ {
+ case '\r':
+ pre_line_break_state_ = state_;
+ state_ = states::cr;
+ break;
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = states::lf;
+ break;
+ case '[':
+ find(buffer_);
+ buffer_.clear();
+ transfer_nodes();
+ start_ = 0;
+ state_ = states::left_bracket;
+ break;
+ case '.':
+ find(buffer_);
+ buffer_.clear();
+ transfer_nodes();
+ state_ = states::dot;
+ break;
+ case ' ':case '\t':
+ break;
+ default:
+ buffer_.push_back(*p_);
+ break;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case states::single_quoted_name:
+ switch (*p_)
+ {
+ case '\'':
+ find(buffer_);
+ buffer_.clear();
+ state_ = states::expect_right_bracket;
+ break;
+ case '\\':
+ buffer_.push_back(*p_);
+ if (p_+1 < end_input_)
+ {
+ ++p_;
+ ++column_;
+ buffer_.push_back(*p_);
+ }
+ break;
+ default:
+ buffer_.push_back(*p_);
+ break;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case states::double_quoted_name:
+ switch (*p_)
+ {
+ case '\"':
+ find(buffer_);
+ buffer_.clear();
+ state_ = states::expect_right_bracket;
+ break;
+ case '\\':
+ buffer_.push_back(*p_);
+ if (p_+1 < end_input_)
+ {
+ ++p_;
+ ++column_;
+ buffer_.push_back(*p_);
+ }
+ break;
+ default:
+ buffer_.push_back(*p_);
+ break;
+ };
+ ++p_;
+ ++column_;
+ break;
+ default:
+ ++p_;
+ ++column_;
+ break;
+ }
+ }
+ switch (state_)
+ {
+ case states::unquoted_name:
+ {
+ find(buffer_);
+ buffer_.clear();
+ transfer_nodes();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ void accept(const JsonT& val,
+ jsonpath_filter_parser<JsonT>& filter)
+ {
+ if (val.is_object())
+ {
+ if (recursive_descent_ && val.is_object())
+ {
+ for (auto it = val.members().begin(); it != val.members().end(); ++it)
+ {
+ accept(it->value(),filter);
+ }
+ }
+ if (filter.exists(val))
+ {
+ nodes_.push_back(std::addressof(val));
+ }
+ }
+ else if (val.is_array())
+ {
+ for (auto it = val.elements().begin(); it != val.elements().end(); ++it)
+ {
+ accept(*it,filter);
+ }
+ }
+ }
+
+
+
+ void end_all()
+ {
+ for (size_t i = 0; i < stack_.back().size(); ++i)
+ {
+ cjson_ptr p = stack_.back()[i];
+ if (p->is_array())
+ {
+ for (auto it = p->elements().begin(); it != p->elements().end(); ++it)
+ {
+ nodes_.push_back(std::addressof(*it));
+ }
+ }
+ else if (p->is_object())
+ {
+ for (auto it = p->members().begin(); it != p->members().end(); ++it)
+ {
+ nodes_.push_back(std::addressof(it->value()));
+ }
+ }
+
+ }
+ start_ = 0;
+ }
+
+ void find_elements()
+ {
+ for (size_t i = 0; i < stack_.back().size(); ++i)
+ {
+ cjson_ptr p = stack_.back()[i];
+ if (p->is_array() && start_ < p->size())
+ {
+ nodes_.push_back(std::addressof((*p)[start_]));
+ }
+ }
+ start_ = 0;
+ }
+
+ void end_array_slice()
+ {
+ if (positive_step_)
+ {
+ end_array_slice1();
+ }
+ else
+ {
+ end_array_slice2();
+ }
+ start_ = 0;
+ end_ = 0;
+ step_ = 1;
+ positive_start_ = positive_end_ = positive_step_ = true;
+ end_undefined_ = true;
+ }
+
+ void end_array_slice1()
+ {
+ for (size_t i = 0; i < stack_.back().size(); ++i)
+ {
+ cjson_ptr p = stack_.back()[i];
+ if (p->is_array())
+ {
+ size_t start = positive_start_ ? start_ : p->size() - start_;
+ size_t end;
+ if (!end_undefined_)
+ {
+ end = positive_end_ ? end_ : p->size() - end_;
+ }
+ else
+ {
+ end = p->size();
+ }
+ for (size_t j = start; j < end; j += step_)
+ {
+ if (p->is_array() && j < p->size())
+ {
+ nodes_.push_back(std::addressof((*p)[j]));
+ }
+ }
+ }
+ }
+ }
+
+ void end_array_slice2()
+ {
+ for (size_t i = 0; i < stack_.back().size(); ++i)
+ {
+ cjson_ptr p = stack_.back()[i];
+ size_t start = positive_start_ ? start_ : p->size() - start_;
+ size_t end;
+ if (!end_undefined_)
+ {
+ end = positive_end_ ? end_ : p->size() - end_;
+ }
+ else
+ {
+ end = p->size();
+ }
+
+ size_t j = end + step_ - 1;
+ while (j > (start+step_-1))
+ {
+ j -= step_;
+ if (p->is_array() && j < p->size())
+ {
+ nodes_.push_back(std::addressof((*p)[j]));
+ }
+ }
+ }
+ }
+
+ void find(const string_type& name)
+ {
+ if (name.length() > 0)
+ {
+ for (size_t i = 0; i < stack_.back().size(); ++i)
+ {
+ find1(*(stack_.back()[i]), name);
+ }
+ recursive_descent_ = false;
+ }
+ }
+
+ void find1(const JsonT& context_val, const string_type& name)
+ {
+ if (context_val.is_object())
+ {
+ if (context_val.count(name) > 0)
+ {
+ nodes_.push_back(std::addressof(context_val.at(name)));
+ }
+ if (recursive_descent_)
+ {
+ for (auto it = context_val.members().begin(); it != context_val.members().end(); ++it)
+ {
+ if (it->value().is_object() || it->value().is_array())
+ {
+ find1(it->value(), name);
+ }
+ }
+ }
+ }
+ else if (context_val.is_array())
+ {
+ size_t index = 0;
+ if (try_string_to_index(name.data(),name.size(),&index))
+ {
+ if (index < context_val.size())
+ {
+ nodes_.push_back(std::addressof(context_val[index]));
+ }
+ }
+ else if (name == json_jsonpath_traits<char_type>::length_literal() && context_val.size() > 0)
+ {
+ auto q = std::make_shared<JsonT>(context_val.size());
+ temp_.push_back(q);
+ nodes_.push_back(q.get());
+ }
+ if (recursive_descent_)
+ {
+ for (auto it = context_val.elements().begin(); it != context_val.elements().end(); ++it)
+ {
+ if (it->is_object() || it->is_array())
+ {
+ find1(*it, name);
+ }
+ }
+ }
+ }
+ }
+
+ size_t do_line_number() const override
+ {
+ return line_;
+ }
+
+ size_t do_column_number() const override
+ {
+ return column_;
+ }
+
+ char_type do_current_char() const override
+ {
+ return 0; //p_ < end_input_? *p_ : 0;
+ }
+
+};
+
+}}
+
+#endif
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_error_category.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_error_category.hpp
new file mode 100644
index 00000000..7f6b6a12
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_error_category.hpp
@@ -0,0 +1,75 @@
+/// 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_JSONPATH_JSONPATH_ERROR_CATEGORY_HPP
+#define JSONCONS_JSONPATH_JSONPATH_ERROR_CATEGORY_HPP
+
+#include "jsoncons/jsoncons.hpp"
+#include <system_error>
+
+namespace jsoncons { namespace jsonpath {
+
+namespace jsonpath_parser_errc
+{
+ const int expected_root = 1;
+ const int expected_right_bracket = 2;
+ const int expected_name = 3;
+ const int expected_separator = 4;
+ const int invalid_filter = 5;
+ const int invalid_filter_expected_slash = 6;
+ const int invalid_filter_unbalanced_paren = 7;
+ const int invalid_filter_unsupported_operator = 8;
+ const int invalid_filter_expected_right_brace = 9;
+ const int invalid_filter_expected_primary = 10;
+}
+
+class jsonpath_error_category_impl
+ : public std::error_category
+{
+public:
+ virtual const char* name() const JSONCONS_NOEXCEPT
+ {
+ return "jsonpath";
+ }
+ virtual std::string message(int ev) const
+ {
+ switch (ev)
+ {
+ case jsonpath_parser_errc::expected_root:
+ return "Expected $";
+ case jsonpath_parser_errc::expected_right_bracket:
+ return "Expected ]";
+ case jsonpath_parser_errc::expected_name:
+ return "Expected a name following a dot";
+ case jsonpath_parser_errc::expected_separator:
+ return "Expected dot or left bracket separator";
+ case jsonpath_parser_errc::invalid_filter:
+ return "Invalid path filter";
+ case jsonpath_parser_errc::invalid_filter_expected_slash:
+ return "Invalid path filter, expected '/'";
+ case jsonpath_parser_errc::invalid_filter_unbalanced_paren:
+ return "Invalid path filter, unbalanced parenthesis";
+ case jsonpath_parser_errc::invalid_filter_unsupported_operator:
+ return "Unsupported operator";
+ case jsonpath_parser_errc::invalid_filter_expected_right_brace:
+ return "Invalid path filter, expected right brace }";
+ case jsonpath_parser_errc::invalid_filter_expected_primary:
+ return "Invalid path filter, expected primary expression.";
+ default:
+ return "Unknown jsonpath parser error";
+ }
+ }
+};
+
+inline
+const std::error_category& jsonpath_error_category()
+{
+ static jsonpath_error_category_impl instance;
+ return instance;
+}
+
+}}
+#endif
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_filter.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_filter.hpp
new file mode 100644
index 00000000..b0ac51c6
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_filter.hpp
@@ -0,0 +1,1495 @@
+// 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_JSONPATH_FILTER_HPP
+#define JSONCONS_JSONPATH_FILTER_HPP
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <memory>
+#include <regex>
+#include "jsoncons/json.hpp"
+#include "jsonpath_error_category.hpp"
+
+namespace jsoncons { namespace jsonpath {
+
+template <class JsonT>
+class jsonpath_evaluator;
+
+enum class filter_states
+{
+ start,
+ cr,
+ lf,
+ expect_right_round_bracket,
+ expect_oper_or_right_round_bracket,
+ expect_path_or_value,
+ expect_regex,
+ regex,
+ single_quoted_text,
+ double_quoted_text,
+ unquoted_text,
+ path,
+ value,
+ oper
+};
+
+enum class token_types
+{
+ left_paren,
+ right_paren,
+ term,
+ eq,
+ ne,
+ regex,
+ ampamp,
+ pipepipe,
+ lt,
+ gt,
+ lte,
+ gte,
+ plus,
+ minus,
+ exclaim,
+ done
+};
+
+template <class JsonT>
+class term
+{
+public:
+ typedef typename JsonT::string_type string_type;
+ typedef typename JsonT::char_type char_type;
+
+ virtual void initialize(const JsonT& context_node)
+ {
+ }
+ virtual bool accept_single_node() const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual JsonT evaluate_single_node() const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool exclaim() const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool eq(const term& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool eq(const JsonT& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool ne(const term& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool ne(const JsonT& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool regex(const term& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool regex2(const string_type& subject) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool ampamp(const term& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool ampamp(const JsonT& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool pipepipe(const term& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool pipepipe(const JsonT& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool lt(const term& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool lt(const JsonT& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool gt(const term& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual bool gt(const JsonT& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual JsonT minus(const term& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual JsonT minus(const JsonT& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual JsonT unary_minus() const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual JsonT plus(const term& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+ virtual JsonT plus(const JsonT& rhs) const
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1);
+ }
+};
+
+template <class JsonT>
+class token
+{
+ token_types type_;
+ std::shared_ptr<term<JsonT>> term_ptr_;
+public:
+ token(token_types type)
+ : type_(type)
+ {
+ }
+ token(token_types type, std::shared_ptr<term<JsonT>> term_ptr)
+ : type_(type), term_ptr_(term_ptr)
+ {
+ }
+ token(const token& t)
+ : type_(t.type_), term_ptr_(t.term_ptr_)
+ {
+ }
+
+ token_types type() const
+ {
+ return type_;
+ }
+
+ std::shared_ptr<term<JsonT>> term_ptr()
+ {
+ return term_ptr_;
+ }
+
+ void initialize(const JsonT& context_node)
+ {
+ if (term_ptr_.get() != nullptr)
+ {
+ term_ptr_->initialize(context_node);
+ }
+ }
+};
+
+template <class JsonT>
+class token_stream
+{
+ std::vector<token<JsonT>>& tokens_;
+ size_t index_;
+public:
+ token_stream(std::vector<token<JsonT>>& tokens)
+ : tokens_(tokens), index_(0)
+ {
+ }
+
+ token<JsonT> get()
+ {
+ static token<JsonT> done = token<JsonT>(token_types::done);
+ return index_ < tokens_.size() ? tokens_[index_++] : done;
+ }
+ void putback()
+ {
+ --index_;
+ }
+};
+
+template <class JsonT>
+bool ampamp(const JsonT& lhs, const JsonT& rhs)
+{
+ return lhs.as_bool() && rhs.as_bool();
+}
+
+template <class JsonT>
+bool pipepipe(const JsonT& lhs, const JsonT& rhs)
+{
+ return lhs.as_bool() || rhs.as_bool();
+}
+
+template <class JsonT>
+bool lt(const JsonT& lhs, const JsonT& rhs)
+{
+ bool result = false;
+ if (lhs. template is<unsigned long long>() && rhs. template is<unsigned long long>())
+ {
+ result = lhs. template as<unsigned long long>() < rhs. template as<unsigned long long>();
+ }
+ else if (lhs. template is<long long>() && rhs. template is<long long>())
+ {
+ result = lhs. template as<long long>() < rhs. template as<long long>();
+ }
+ else if ((lhs.is_number() && rhs.is_double()) || (lhs.is_double() && rhs.is_number()))
+ {
+ result = lhs.as_double() < rhs.as_double();
+ }
+ else if (lhs.is_string() && rhs.is_string())
+ {
+ result = lhs.as_string() < rhs.as_string();
+ }
+ return result;
+}
+
+template <class JsonT>
+bool gt(const JsonT& lhs, const JsonT& rhs)
+{
+ return lt(rhs,lhs);
+}
+
+template <class JsonT>
+JsonT plus(const JsonT& lhs, const JsonT& rhs)
+{
+ JsonT result = jsoncons::null_type();
+ if (lhs.is_integer() && rhs.is_integer())
+ {
+ result = ((lhs.as_integer() + rhs.as_integer()));
+ }
+ else if ((lhs.is_number() && rhs.is_double()) || (lhs.is_double() && rhs.is_number()))
+ {
+ result = (lhs.as_double() + rhs.as_double());
+ }
+ else if (lhs.is_uinteger() && rhs.is_uinteger())
+ {
+ result = (lhs.as_uinteger() + rhs.as_uinteger());
+ }
+ return result;
+}
+
+template <class JsonT>
+JsonT unary_minus(const JsonT& lhs)
+{
+ JsonT result = jsoncons::null_type();
+ if (lhs.is_integer())
+ {
+ result = -lhs.as_integer();
+ }
+ else if (lhs.is_double())
+ {
+ result = -lhs.as_double();
+ }
+ return result;
+}
+
+template <class JsonT>
+JsonT minus(const JsonT& lhs, const JsonT& rhs)
+{
+ JsonT result = jsoncons::null_type();
+ if (lhs.is_integer() && rhs.is_integer())
+ {
+ result = ((lhs.as_integer() - rhs.as_integer()));
+ }
+ else if ((lhs.is_number() && rhs.is_double()) || (lhs.is_double() && rhs.is_number()))
+ {
+ result = (lhs.as_double() - rhs.as_double());
+ }
+ else if (lhs.is_uinteger() && rhs.is_uinteger() && lt(rhs,lhs))
+ {
+ result = (lhs.as_uinteger() - rhs.as_uinteger());
+ }
+ return result;
+}
+
+template <class JsonT>
+class value_term : public term<JsonT>
+{
+ JsonT value_;
+public:
+ template <class T>
+ value_term(const T& value)
+ : value_(value)
+ {
+ }
+
+ bool accept_single_node() const override
+ {
+ return value_.as_bool();
+ }
+
+ JsonT evaluate_single_node() const override
+ {
+ return value_;
+ }
+
+ bool exclaim() const override
+ {
+ return !value_.as_bool();
+ }
+
+ bool eq(const term<JsonT>& rhs) const override
+ {
+ return rhs.eq(value_);
+ }
+
+ bool eq(const JsonT& rhs) const override
+ {
+ return value_ == rhs;
+ }
+
+ bool ne(const term<JsonT>& rhs) const override
+ {
+ return rhs.ne(value_);
+ }
+ bool ne(const JsonT& rhs) const override
+ {
+ return value_ != rhs;
+ }
+ bool regex(const term<JsonT>& rhs) const override
+ {
+ return rhs.regex2(value_.as_string());
+ }
+ bool ampamp(const term<JsonT>& rhs) const override
+ {
+ return rhs.ampamp(value_);
+ }
+ bool ampamp(const JsonT& rhs) const override
+ {
+ return jsoncons::jsonpath::ampamp(value_,rhs);
+ }
+ bool pipepipe(const term<JsonT>& rhs) const override
+ {
+ return rhs.pipepipe(value_);
+ }
+ bool pipepipe(const JsonT& rhs) const override
+ {
+ return jsoncons::jsonpath::pipepipe(value_,rhs);
+ }
+
+ bool lt(const term<JsonT>& rhs) const override
+ {
+ return rhs.gt(value_);
+ }
+
+ bool lt(const JsonT& rhs) const override
+ {
+ return jsoncons::jsonpath::lt(value_,rhs);
+ }
+
+ bool gt(const term<JsonT>& rhs) const override
+ {
+ return rhs.lt(value_);
+ }
+
+ bool gt(const JsonT& rhs) const override
+ {
+ return jsoncons::jsonpath::gt(value_,rhs);
+ }
+
+ JsonT minus(const term<JsonT>& rhs) const override
+ {
+ return jsoncons::jsonpath::plus(rhs.unary_minus(),value_);
+ }
+
+ JsonT minus(const JsonT& rhs) const override
+ {
+ return jsoncons::jsonpath::minus(value_,rhs);
+ }
+
+ JsonT unary_minus() const override
+ {
+ return jsoncons::jsonpath::unary_minus(value_);
+ }
+
+ JsonT plus(const term<JsonT>& rhs) const override
+ {
+ return rhs.plus(value_);
+ }
+
+ JsonT plus(const JsonT& rhs) const override
+ {
+ return jsoncons::jsonpath::plus(value_,rhs);
+ }
+};
+
+template <class JsonT>
+class regex_term : public term<JsonT>
+{
+ typedef typename JsonT::char_type char_type;
+ typedef typename JsonT::string_type string_type;
+ string_type pattern_;
+ std::regex::flag_type flags_;
+public:
+ regex_term(const string_type& pattern, std::regex::flag_type flags)
+ : pattern_(pattern), flags_(flags)
+ {
+ }
+
+ bool regex2(const string_type& subject) const override
+ {
+ std::basic_regex<char_type> pattern(pattern_,
+ flags_);
+ return std::regex_match(subject, pattern);
+ }
+};
+
+template <class JsonT>
+class path_term : public term<JsonT>
+{
+ typedef typename JsonT::string_type string_type;
+
+ string_type path_;
+ JsonT nodes_;
+public:
+ path_term(const string_type& path)
+ : path_(path)
+ {
+ }
+
+ void initialize(const JsonT& context_node) override
+ {
+ jsonpath_evaluator<JsonT> evaluator;
+ evaluator.evaluate(context_node,path_);
+ nodes_ = evaluator.get_values();
+ }
+
+ bool accept_single_node() const override
+ {
+ return nodes_.size() != 0;
+ }
+
+ JsonT evaluate_single_node() const override
+ {
+ return nodes_.size() == 1 ? nodes_[0] : nodes_;
+ }
+
+ bool exclaim() const override
+ {
+ return nodes_.size() == 0;
+ }
+
+ bool eq(const term<JsonT>& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = rhs.eq(nodes_[i]);
+ }
+ }
+ return result;
+ }
+
+ bool eq(const JsonT& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = nodes_[i] == rhs;
+ }
+ }
+ return result;
+ }
+
+ bool ne(const term<JsonT>& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = rhs.ne(nodes_[i]);
+ }
+ }
+ return result;
+
+ }
+ bool ne(const JsonT& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = nodes_[i] != rhs;
+ }
+ }
+ return result;
+ }
+ bool regex(const term<JsonT>& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = rhs.regex2(nodes_[i].as_string());
+ }
+ }
+ return result;
+ }
+ bool ampamp(const term<JsonT>& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = rhs.ampamp(nodes_[i]);
+ }
+ }
+ return result;
+ }
+ bool ampamp(const JsonT& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = jsoncons::jsonpath::ampamp(nodes_[i],rhs);
+ }
+ }
+ return result;
+ }
+ bool pipepipe(const term<JsonT>& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = rhs.pipepipe(nodes_[i]);
+ }
+ }
+ return result;
+ }
+ bool pipepipe(const JsonT& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = jsoncons::jsonpath::pipepipe(nodes_[i],rhs);
+ }
+ }
+ return result;
+ }
+
+ bool lt(const JsonT& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = jsoncons::jsonpath::lt(nodes_[i],rhs);
+ }
+ }
+ return result;
+ }
+
+ bool lt(const term<JsonT>& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = rhs.gt(nodes_[i]);
+ }
+ }
+ return result;
+ }
+
+ bool gt(const JsonT& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = jsoncons::jsonpath::gt(nodes_[i],rhs);
+ }
+ }
+ return result;
+ }
+
+ bool gt(const term<JsonT>& rhs) const override
+ {
+ bool result = false;
+ if (nodes_.size() > 0)
+ {
+ result = true;
+ for (size_t i = 0; result && i < nodes_.size(); ++i)
+ {
+ result = rhs.lt(nodes_[i]);
+ }
+ }
+ return result;
+ }
+
+ JsonT minus(const JsonT& rhs) const override
+ {
+ return nodes_.size() == 1 ? jsoncons::jsonpath::minus(nodes_[0],rhs) : jsoncons::null_type();
+ }
+
+ JsonT minus(const term<JsonT>& rhs) const override
+ {
+
+ return nodes_.size() == 1 ? jsoncons::jsonpath::plus(rhs.unary_minus(),nodes_[0]) : jsoncons::null_type();
+ }
+
+ JsonT unary_minus() const override
+ {
+ return nodes_.size() == 1 ? jsoncons::jsonpath::unary_minus(nodes_[0]) : jsoncons::null_type();
+ }
+
+ JsonT plus(const JsonT& rhs) const override
+ {
+ static auto a_null = jsoncons::null_type();
+ return nodes_.size() == 1 ? jsoncons::jsonpath::plus(nodes_[0],rhs) : a_null;
+ }
+
+ JsonT plus(const term<JsonT>& rhs) const override
+ {
+ static auto a_null = jsoncons::null_type();
+ return nodes_.size() == 1 ? rhs.plus(nodes_[0]) : a_null;
+ }
+};
+
+template <class JsonT>
+class jsonpath_filter_parser
+{
+ typedef typename JsonT::string_type string_type;
+ typedef typename JsonT::char_type char_type;
+
+ size_t& line_;
+ size_t& column_;
+ filter_states state_;
+ string_type buffer_;
+ std::vector<token<JsonT>> tokens_;
+ int depth_;
+ const char_type* begin_input_;
+ const char_type* end_input_;
+ const char_type*& p_;
+ filter_states pre_line_break_state_;
+public:
+ jsonpath_filter_parser(const char_type** expr, size_t* line,size_t* column)
+ : line_(*line), column_(*column),p_(*expr)
+ {
+ }
+
+ bool exists(const JsonT& context_node)
+ {
+ for (auto it=tokens_.begin(); it != tokens_.end(); ++it)
+ {
+ it->initialize(context_node);
+ }
+ bool result = false;
+
+ token_stream<JsonT> ts(tokens_);
+ auto e = expression(ts);
+ result = e->accept_single_node();
+
+ return result;
+ }
+
+ JsonT eval(const JsonT& context_node)
+ {
+ try
+ {
+ for (auto it=tokens_.begin(); it != tokens_.end(); ++it)
+ {
+ it->initialize(context_node);
+ }
+
+ token_stream<JsonT> ts(tokens_);
+ auto e = expression(ts);
+ JsonT result = e->evaluate_single_node();
+
+ return result;
+ }
+ catch (const parse_exception& e)
+ {
+ throw parse_exception(e.code(),line_,column_);
+ }
+ }
+
+ std::shared_ptr<term<JsonT>> primary(token_stream<JsonT>& ts)
+ {
+ auto t = ts.get();
+
+ switch (t.type())
+ {
+ case token_types::left_paren:
+ {
+ auto expr = expression(ts);
+ t = ts.get();
+ if (t.type() != token_types::right_paren)
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_expected_right_brace, jsonpath_error_category()),line_,column_);
+ }
+ return expr;
+ }
+ case token_types::term:
+ return t.term_ptr();
+ case token_types::exclaim:
+ {
+ JsonT val = primary(ts)->exclaim();
+ auto expr = std::make_shared<value_term<JsonT>>(val);
+ return expr;
+ }
+ case token_types::minus:
+ {
+ JsonT val = primary(ts)->unary_minus();
+ auto expr = std::make_shared<value_term<JsonT>>(val);
+ return expr;
+ }
+ default:
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_expected_primary, jsonpath_error_category()),line_,column_);
+ }
+ }
+
+ std::shared_ptr<term<JsonT>> expression(token_stream<JsonT>& ts)
+ {
+ auto left = make_term(ts);
+ auto t = ts.get();
+ while (true)
+ {
+ switch (t.type())
+ {
+ case token_types::plus:
+ {
+ JsonT val = left->plus(*(make_term(ts)));
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ case token_types::minus:
+ {
+ JsonT val = left->minus(*(make_term(ts)));
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ default:
+ ts.putback();
+ return left;
+ }
+ }
+ return left;
+ }
+
+ std::shared_ptr<term<JsonT>> make_term(token_stream<JsonT>& ts)
+ {
+ auto left = primary(ts);
+ auto t = ts.get();
+ while (true)
+ {
+ switch (t.type())
+ {
+ case token_types::eq:
+ {
+ bool e = left->eq(*(primary(ts)));
+ JsonT val(e);
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ case token_types::ne:
+ {
+ bool e = left->ne(*(primary(ts)));
+ JsonT val(e);
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ case token_types::regex:
+ {
+ bool e = left->regex(*(primary(ts)));
+ JsonT val(e);
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ case token_types::ampamp:
+ {
+ bool e = left->ampamp(*(primary(ts)));
+ JsonT val(e);
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ case token_types::pipepipe:
+ {
+ bool e = left->pipepipe(*(primary(ts)));
+ JsonT val(e);
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ case token_types::lt:
+ {
+ bool e = left->lt(*(primary(ts)));
+ JsonT val(e);
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ case token_types::gt:
+ {
+ bool e = left->gt(*(primary(ts)));
+ JsonT val(e);
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ case token_types::lte:
+ {
+ bool e = left->lt(*(primary(ts))) || left->eq(*(primary(ts)));
+ JsonT val(e);
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ case token_types::gte:
+ {
+ bool e = left->gt(*(primary(ts))) || left->eq(*(primary(ts)));
+ JsonT val(e);
+ left = std::make_shared<value_term<JsonT>>(val);
+ t = ts.get();
+ }
+ break;
+ default:
+ ts.putback();
+ return left;
+ }
+ }
+ }
+
+ void parse(const char_type* expr, size_t length)
+ {
+ parse(expr,expr+length);
+ }
+
+ void parse(const char_type* expr, const char_type* end_expr)
+ {
+ p_ = expr;
+ end_input_ = end_expr;
+ depth_ = 0;
+ tokens_.clear();
+ state_ = filter_states::start;
+ bool done = false;
+ while (!done && p_ < end_input_)
+ {
+ switch (state_)
+ {
+ case filter_states::cr:
+ ++line_;
+ column_ = 1;
+ switch (*p_)
+ {
+ case '\n':
+ state_ = pre_line_break_state_;
+ ++p_;
+ ++column_;
+ break;
+ default:
+ state_ = pre_line_break_state_;
+ break;
+ }
+ break;
+ case filter_states::lf:
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case filter_states::start:
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ pre_line_break_state_ = state_;
+ state_ = filter_states::lf;
+ break;
+ case '(':
+ state_ = filter_states::expect_path_or_value;
+ ++depth_;
+ tokens_.push_back(token<JsonT>(token_types::left_paren));
+ break;
+ case ')':
+ tokens_.push_back(token<JsonT>(token_types::right_paren));
+ if (--depth_ == 0)
+ {
+ done = true;
+ }
+ break;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case filter_states::oper:
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case '!':
+ if (p_+1 < end_input_ && *(p_+1) == '=')
+ {
+ ++p_;
+ ++column_;
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::ne));
+ }
+ else
+ {
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::exclaim));
+ }
+ break;
+ case '&':
+ if (p_+1 < end_input_ && *(p_+1) == '&')
+ {
+ ++p_;
+ ++column_;
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::ampamp));
+ }
+ break;
+ case '|':
+ if (p_+1 < end_input_ && *(p_+1) == '|')
+ {
+ ++p_;
+ ++column_;
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::pipepipe));
+ }
+ break;
+ case '=':
+ if (p_+1 < end_input_ && *(p_+1) == '=')
+ {
+ ++p_;
+ ++column_;
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::eq));
+ }
+ else if (p_+1 < end_input_ && *(p_+1) == '~')
+ {
+ ++p_;
+ ++column_;
+ state_ = filter_states::expect_regex;
+ tokens_.push_back(token<JsonT>(token_types::regex));
+ }
+ break;
+ case '>':
+ if (p_+1 < end_input_ && *(p_+1) == '=')
+ {
+ ++p_;
+ ++column_;
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::gte));
+ }
+ else
+ {
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::gt));
+ }
+ break;
+ case '<':
+ if (p_+1 < end_input_ && *(p_+1) == '=')
+ {
+ ++p_;
+ ++column_;
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::lte));
+ }
+ else
+ {
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::lt));
+ }
+ break;
+ case '+':
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::plus));
+ break;
+ case '-':
+ state_ = filter_states::expect_path_or_value;
+ tokens_.push_back(token<JsonT>(token_types::minus));
+ break;
+ case ' ':case '\t':
+ break;
+ default:
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter, jsonpath_error_category()),line_,column_);
+ break;
+
+ }
+ ++p_;
+ ++column_;
+ break;
+ case filter_states::unquoted_text:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case '<':
+ case '>':
+ case '!':
+ case '=':
+ case '&':
+ case '|':
+ case '+':
+ case '-':
+ {
+ if (buffer_.length() > 0)
+ {
+ try
+ {
+ auto val = JsonT::parse(buffer_);
+ tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<value_term<JsonT>>(val)));
+ }
+ catch (const parse_exception& e)
+ {
+ throw parse_exception(e.code(),line_,column_);
+ }
+ buffer_.clear();
+ }
+ state_ = filter_states::oper;
+ }
+ break;
+ case ')':
+ if (buffer_.length() > 0)
+ {
+ try
+ {
+ auto val = JsonT::parse(buffer_);
+ tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<value_term<JsonT>>(val)));
+ }
+ catch (const parse_exception& e)
+ {
+ throw parse_exception(e.code(),line_,column_);
+ }
+ buffer_.clear();
+ }
+ tokens_.push_back(token<JsonT>(token_types::right_paren));
+ if (--depth_ == 0)
+ {
+ state_ = filter_states::start;
+ done = true;
+ }
+ else
+ {
+ state_ = filter_states::expect_path_or_value;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case ' ':case '\t':
+ if (buffer_.length() > 0)
+ {
+ try
+ {
+ auto val = JsonT::parse(buffer_);
+ tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<value_term<JsonT>>(val)));
+ }
+ catch (const parse_exception& e)
+ {
+ throw parse_exception(e.code(),line_,column_);
+ }
+ buffer_.clear();
+ }
+ ++p_;
+ ++column_;
+ break;
+ default:
+ buffer_.push_back(*p_);
+ ++p_;
+ ++column_;
+ break;
+ }
+ }
+ break;
+ case filter_states::single_quoted_text:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case '\\':
+ buffer_.push_back(*p_);
+ if (p_+1 < end_input_)
+ {
+ ++p_;
+ ++column_;
+ buffer_.push_back(*p_);
+ }
+ break;
+ case '\'':
+ buffer_.push_back('\"');
+ //if (buffer_.length() > 0)
+ {
+ try
+ {
+ auto val = JsonT::parse(buffer_);
+ tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<value_term<JsonT>>(val)));
+ }
+ catch (const parse_exception& e)
+ {
+ throw parse_exception(e.code(),line_,column_);
+ }
+ buffer_.clear();
+ }
+ state_ = filter_states::expect_path_or_value;
+ break;
+
+ default:
+ buffer_.push_back(*p_);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case filter_states::double_quoted_text:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case '\\':
+ buffer_.push_back(*p_);
+ if (p_+1 < end_input_)
+ {
+ ++p_;
+ ++column_;
+ buffer_.push_back(*p_);
+ }
+ break;
+ case '\"':
+ buffer_.push_back(*p_);
+ //if (buffer_.length() > 0)
+ {
+ try
+ {
+ auto val = JsonT::parse(buffer_);
+ tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<value_term<JsonT>>(val)));
+ }
+ catch (const parse_exception& e)
+ {
+ throw parse_exception(e.code(),line_,column_);
+ }
+ buffer_.clear();
+ }
+ state_ = filter_states::expect_path_or_value;
+ break;
+
+ default:
+ buffer_.push_back(*p_);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case filter_states::expect_path_or_value:
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case '<':
+ case '>':
+ case '!':
+ case '=':
+ case '&':
+ case '|':
+ case '+':
+ case '-':
+ state_ = filter_states::oper;
+ // don't increment
+ break;
+ case '@':
+ buffer_.push_back(*p_);
+ state_ = filter_states::path;
+ ++p_;
+ ++column_;
+ break;
+ case ' ':case '\t':
+ ++p_;
+ ++column_;
+ break;
+ case '\'':
+ buffer_.push_back('\"');
+ state_ = filter_states::single_quoted_text;
+ ++p_;
+ ++column_;
+ break;
+ case '\"':
+ buffer_.push_back(*p_);
+ state_ = filter_states::double_quoted_text;
+ ++p_;
+ ++column_;
+ break;
+ case '(':
+ ++depth_;
+ tokens_.push_back(token<JsonT>(token_types::left_paren));
+ ++p_;
+ ++column_;
+ break;
+ case ')':
+ tokens_.push_back(token<JsonT>(token_types::right_paren));
+ if (--depth_ == 0)
+ {
+ done = true;
+ state_ = filter_states::start;
+ }
+ ++p_;
+ ++column_;
+ break;
+ default:
+ // don't increment
+ state_ = filter_states::unquoted_text;
+ break;
+ };
+ break;
+ case filter_states::expect_oper_or_right_round_bracket:
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case ' ':case '\t':
+ break;
+ case ')':
+ tokens_.push_back(token<JsonT>(token_types::right_paren));
+ if (--depth_ == 0)
+ {
+ done = true;
+ state_ = filter_states::start;
+ }
+ break;
+ case '<':
+ case '>':
+ case '!':
+ case '=':
+ case '&':
+ case '|':
+ case '+':
+ case '-':
+ {
+ state_ = filter_states::oper;
+ // don't increment p
+ }
+ break;
+ default:
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter, jsonpath_error_category()),line_,column_);
+ break;
+ };
+ break;
+ case filter_states::expect_right_round_bracket:
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case ' ':case '\t':
+ break;
+ case ')':
+ tokens_.push_back(token<JsonT>(token_types::right_paren));
+ if (--depth_ == 0)
+ {
+ done = true;
+ state_ = filter_states::start;
+ }
+ else
+ {
+ state_ = filter_states::expect_oper_or_right_round_bracket;
+ }
+ break;
+ default:
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter, jsonpath_error_category()),line_,column_);
+ break;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case filter_states::path:
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case '<':
+ case '>':
+ case '!':
+ case '=':
+ case '&':
+ case '|':
+ case '+':
+ case '-':
+ {
+ if (buffer_.length() > 0)
+ {
+ tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<path_term<JsonT>>(buffer_)));
+ buffer_.clear();
+ }
+ state_ = filter_states::oper;
+ // don't increment
+ }
+ break;
+ case ')':
+ if (buffer_.length() > 0)
+ {
+ tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<path_term<JsonT>>(buffer_)));
+ tokens_.push_back(token<JsonT>(token_types::right_paren));
+ buffer_.clear();
+ }
+ if (--depth_ == 0)
+ {
+ state_ = filter_states::start;
+ done = true;
+ }
+ else
+ {
+ state_ = filter_states::expect_path_or_value;
+ }
+ ++p_;
+ ++column_;
+ break;
+ default:
+ buffer_.push_back(*p_);
+ ++p_;
+ ++column_;
+ break;
+ };
+ break;
+ case filter_states::expect_regex:
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case '/':
+ state_ = filter_states::regex;
+ break;
+ case ' ':case '\t':
+ break;
+ default:
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_expected_slash, jsonpath_error_category()),line_,column_);
+ break;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case filter_states::regex:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ case '\n':
+ ++line_;
+ column_ = 1;
+ state_ = pre_line_break_state_;
+ break;
+ case '/':
+ //if (buffer_.length() > 0)
+ {
+ std::regex::flag_type flags = std::regex_constants::ECMAScript;
+ if (p_+1 < end_input_ && *(p_+1) == 'i')
+ {
+ ++p_;
+ ++column_;
+ flags |= std::regex_constants::icase;
+ }
+ tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<regex_term<JsonT>>(buffer_,flags)));
+ buffer_.clear();
+ }
+ state_ = filter_states::expect_path_or_value;
+ break;
+
+ default:
+ buffer_.push_back(*p_);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ default:
+ ++p_;
+ ++column_;
+ break;
+ }
+ }
+ if (depth_ != 0)
+ {
+ throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unbalanced_paren, jsonpath_error_category()),line_,column_);
+ }
+ }
+};
+
+
+}}
+#endif \ No newline at end of file