summaryrefslogtreecommitdiff
path: root/vendor/jsoncons-0.99.2/jsoncons/json.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/jsoncons-0.99.2/jsoncons/json.hpp')
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json.hpp3574
1 files changed, 3574 insertions, 0 deletions
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