+ more adjustments toward a real container
This commit is contained in:
parent
3c780f0f57
commit
76be1ae1f6
5 changed files with 630 additions and 488 deletions
|
@ -184,7 +184,7 @@ bool foo = j.at(2);
|
||||||
// other stuff
|
// other stuff
|
||||||
j.size(); // 3 entries
|
j.size(); // 3 entries
|
||||||
j.empty(); // false
|
j.empty(); // false
|
||||||
j.type(); // json::value_type::array
|
j.type(); // json::value_t::array
|
||||||
j.clear(); // the array is empty again
|
j.clear(); // the array is empty again
|
||||||
|
|
||||||
// comparison
|
// comparison
|
||||||
|
|
File diff suppressed because it is too large
Load diff
329
src/json.cc
329
src/json.cc
|
@ -2,7 +2,7 @@
|
||||||
@file
|
@file
|
||||||
@copyright The code is licensed under the MIT License
|
@copyright The code is licensed under the MIT License
|
||||||
<http://opensource.org/licenses/MIT>,
|
<http://opensource.org/licenses/MIT>,
|
||||||
Copyright (c) 2013-2014 Niels Lohmann.
|
Copyright (c) 2013-2015 Niels Lohmann.
|
||||||
|
|
||||||
@author Niels Lohmann <http://nlohmann.me>
|
@author Niels Lohmann <http://nlohmann.me>
|
||||||
|
|
||||||
|
@ -42,37 +42,37 @@ Construct an empty JSON given the type.
|
||||||
|
|
||||||
@post Memory for array, object, and string are allocated.
|
@post Memory for array, object, and string are allocated.
|
||||||
*/
|
*/
|
||||||
json::json(const value_type t)
|
json::json(const value_t t)
|
||||||
: type_(t)
|
: type_(t)
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::array):
|
case (value_t::array):
|
||||||
{
|
{
|
||||||
value_.array = new array_t();
|
value_.array = new array_t();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::object):
|
case (value_t::object):
|
||||||
{
|
{
|
||||||
value_.object = new object_t();
|
value_.object = new object_t();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::string):
|
case (value_t::string):
|
||||||
{
|
{
|
||||||
value_.string = new string_t();
|
value_.string = new string_t();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::boolean):
|
case (value_t::boolean):
|
||||||
{
|
{
|
||||||
value_.boolean = boolean_t();
|
value_.boolean = boolean_t();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::number):
|
case (value_t::number):
|
||||||
{
|
{
|
||||||
value_.number = number_t();
|
value_.number = number_t();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::number_float):
|
case (value_t::number_float):
|
||||||
{
|
{
|
||||||
value_.number_float = number_float_t();
|
value_.number_float = number_float_t();
|
||||||
break;
|
break;
|
||||||
|
@ -96,35 +96,35 @@ Construct a string JSON object.
|
||||||
@param s a string to initialize the JSON object with
|
@param s a string to initialize the JSON object with
|
||||||
*/
|
*/
|
||||||
json::json(const std::string& s)
|
json::json(const std::string& s)
|
||||||
: type_(value_type::string), value_(new string_t(s))
|
: type_(value_t::string), value_(new string_t(s))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json::json(std::string&& s)
|
json::json(std::string&& s)
|
||||||
: type_(value_type::string), value_(new string_t(std::move(s)))
|
: type_(value_t::string), value_(new string_t(std::move(s)))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json::json(const char* s)
|
json::json(const char* s)
|
||||||
: type_(value_type::string), value_(new string_t(s))
|
: type_(value_t::string), value_(new string_t(s))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json::json(const bool b) noexcept
|
json::json(const bool b) noexcept
|
||||||
: type_(value_type::boolean), value_(b)
|
: type_(value_t::boolean), value_(b)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json::json(const array_t& a)
|
json::json(const array_t& a)
|
||||||
: type_(value_type::array), value_(new array_t(a))
|
: type_(value_t::array), value_(new array_t(a))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json::json(array_t&& a)
|
json::json(array_t&& a)
|
||||||
: type_(value_type::array), value_(new array_t(std::move(a)))
|
: type_(value_t::array), value_(new array_t(std::move(a)))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json::json(const object_t& o)
|
json::json(const object_t& o)
|
||||||
: type_(value_type::object), value_(new object_t(o))
|
: type_(value_t::object), value_(new object_t(o))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json::json(object_t&& o)
|
json::json(object_t&& o)
|
||||||
: type_(value_type::object), value_(new object_t(std::move(o)))
|
: type_(value_t::object), value_(new object_t(std::move(o)))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -148,20 +148,20 @@ json::json(list_init_t a)
|
||||||
// is a string
|
// is a string
|
||||||
for (const auto& element : a)
|
for (const auto& element : a)
|
||||||
{
|
{
|
||||||
if (element.type_ != value_type::array or
|
if (element.type_ != value_t::array or
|
||||||
element.size() != 2 or
|
element.size() != 2 or
|
||||||
element[0].type_ != value_type::string)
|
element[0].type_ != value_t::string)
|
||||||
{
|
{
|
||||||
|
|
||||||
// the initializer list describes an array
|
// the initializer list describes an array
|
||||||
type_ = value_type::array;
|
type_ = value_t::array;
|
||||||
value_ = new array_t(a);
|
value_ = new array_t(a);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the initializer list is a list of pairs
|
// the initializer list is a list of pairs
|
||||||
type_ = value_type::object;
|
type_ = value_t::object;
|
||||||
value_ = new object_t();
|
value_ = new object_t();
|
||||||
for (const json& element : a)
|
for (const json& element : a)
|
||||||
{
|
{
|
||||||
|
@ -181,32 +181,32 @@ json::json(const json& o)
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::array):
|
case (value_t::array):
|
||||||
{
|
{
|
||||||
value_.array = new array_t(*o.value_.array);
|
value_.array = new array_t(*o.value_.array);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::object):
|
case (value_t::object):
|
||||||
{
|
{
|
||||||
value_.object = new object_t(*o.value_.object);
|
value_.object = new object_t(*o.value_.object);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::string):
|
case (value_t::string):
|
||||||
{
|
{
|
||||||
value_.string = new string_t(*o.value_.string);
|
value_.string = new string_t(*o.value_.string);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::boolean):
|
case (value_t::boolean):
|
||||||
{
|
{
|
||||||
value_.boolean = o.value_.boolean;
|
value_.boolean = o.value_.boolean;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::number):
|
case (value_t::number):
|
||||||
{
|
{
|
||||||
value_.number = o.value_.number;
|
value_.number = o.value_.number;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::number_float):
|
case (value_t::number_float):
|
||||||
{
|
{
|
||||||
value_.number_float = o.value_.number_float;
|
value_.number_float = o.value_.number_float;
|
||||||
break;
|
break;
|
||||||
|
@ -229,7 +229,7 @@ json::json(json&& o) noexcept
|
||||||
: type_(std::move(o.type_)), value_(std::move(o.value_))
|
: type_(std::move(o.type_)), value_(std::move(o.value_))
|
||||||
{
|
{
|
||||||
// invalidate payload
|
// invalidate payload
|
||||||
o.type_ = value_type::null;
|
o.type_ = value_t::null;
|
||||||
o.value_ = {};
|
o.value_ = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,17 +250,17 @@ json::~json() noexcept
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::array):
|
case (value_t::array):
|
||||||
{
|
{
|
||||||
delete value_.array;
|
delete value_.array;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::object):
|
case (value_t::object):
|
||||||
{
|
{
|
||||||
delete value_.object;
|
delete value_.object;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::string):
|
case (value_t::string):
|
||||||
{
|
{
|
||||||
delete value_.string;
|
delete value_.string;
|
||||||
break;
|
break;
|
||||||
|
@ -296,23 +296,23 @@ std::string json::type_name() const noexcept
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::array):
|
case (value_t::array):
|
||||||
{
|
{
|
||||||
return "array";
|
return "array";
|
||||||
}
|
}
|
||||||
case (value_type::object):
|
case (value_t::object):
|
||||||
{
|
{
|
||||||
return "object";
|
return "object";
|
||||||
}
|
}
|
||||||
case (value_type::null):
|
case (value_t::null):
|
||||||
{
|
{
|
||||||
return "null";
|
return "null";
|
||||||
}
|
}
|
||||||
case (value_type::string):
|
case (value_t::string):
|
||||||
{
|
{
|
||||||
return "string";
|
return "string";
|
||||||
}
|
}
|
||||||
case (value_type::boolean):
|
case (value_t::boolean):
|
||||||
{
|
{
|
||||||
return "boolean";
|
return "boolean";
|
||||||
}
|
}
|
||||||
|
@ -337,7 +337,7 @@ std::string json::get() const
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::string):
|
case (value_t::string):
|
||||||
return *value_.string;
|
return *value_.string;
|
||||||
default:
|
default:
|
||||||
throw std::logic_error("cannot cast " + type_name() + " to JSON string");
|
throw std::logic_error("cannot cast " + type_name() + " to JSON string");
|
||||||
|
@ -353,9 +353,9 @@ int json::get() const
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::number):
|
case (value_t::number):
|
||||||
return value_.number;
|
return value_.number;
|
||||||
case (value_type::number_float):
|
case (value_t::number_float):
|
||||||
return static_cast<int>(value_.number_float);
|
return static_cast<int>(value_.number_float);
|
||||||
default:
|
default:
|
||||||
throw std::logic_error("cannot cast " + type_name() + " to JSON number");
|
throw std::logic_error("cannot cast " + type_name() + " to JSON number");
|
||||||
|
@ -371,9 +371,9 @@ int64_t json::get() const
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::number):
|
case (value_t::number):
|
||||||
return value_.number;
|
return value_.number;
|
||||||
case (value_type::number_float):
|
case (value_t::number_float):
|
||||||
return static_cast<number_t>(value_.number_float);
|
return static_cast<number_t>(value_.number_float);
|
||||||
default:
|
default:
|
||||||
throw std::logic_error("cannot cast " + type_name() + " to JSON number");
|
throw std::logic_error("cannot cast " + type_name() + " to JSON number");
|
||||||
|
@ -389,9 +389,9 @@ double json::get() const
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::number):
|
case (value_t::number):
|
||||||
return static_cast<number_float_t>(value_.number);
|
return static_cast<number_float_t>(value_.number);
|
||||||
case (value_type::number_float):
|
case (value_t::number_float):
|
||||||
return value_.number_float;
|
return value_.number_float;
|
||||||
default:
|
default:
|
||||||
throw std::logic_error("cannot cast " + type_name() + " to JSON number");
|
throw std::logic_error("cannot cast " + type_name() + " to JSON number");
|
||||||
|
@ -407,7 +407,7 @@ bool json::get() const
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::boolean):
|
case (value_t::boolean):
|
||||||
return value_.boolean;
|
return value_.boolean;
|
||||||
default:
|
default:
|
||||||
throw std::logic_error("cannot cast " + type_name() + " to JSON Boolean");
|
throw std::logic_error("cannot cast " + type_name() + " to JSON Boolean");
|
||||||
|
@ -421,11 +421,11 @@ bool json::get() const
|
||||||
template<>
|
template<>
|
||||||
json::array_t json::get() const
|
json::array_t json::get() const
|
||||||
{
|
{
|
||||||
if (type_ == value_type::array)
|
if (type_ == value_t::array)
|
||||||
{
|
{
|
||||||
return *value_.array;
|
return *value_.array;
|
||||||
}
|
}
|
||||||
if (type_ == value_type::object)
|
if (type_ == value_t::object)
|
||||||
{
|
{
|
||||||
throw std::logic_error("cannot cast " + type_name() + " to JSON array");
|
throw std::logic_error("cannot cast " + type_name() + " to JSON array");
|
||||||
}
|
}
|
||||||
|
@ -442,7 +442,7 @@ json::array_t json::get() const
|
||||||
template<>
|
template<>
|
||||||
json::object_t json::get() const
|
json::object_t json::get() const
|
||||||
{
|
{
|
||||||
if (type_ == value_type::object)
|
if (type_ == value_t::object)
|
||||||
{
|
{
|
||||||
return *value_.object;
|
return *value_.object;
|
||||||
}
|
}
|
||||||
|
@ -505,27 +505,27 @@ std::string json::dump(const bool prettyPrint, const unsigned int indentStep,
|
||||||
|
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::string):
|
case (value_t::string):
|
||||||
{
|
{
|
||||||
return std::string("\"") + escapeString(*value_.string) + "\"";
|
return std::string("\"") + escapeString(*value_.string) + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
case (value_type::boolean):
|
case (value_t::boolean):
|
||||||
{
|
{
|
||||||
return value_.boolean ? "true" : "false";
|
return value_.boolean ? "true" : "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
case (value_type::number):
|
case (value_t::number):
|
||||||
{
|
{
|
||||||
return std::to_string(value_.number);
|
return std::to_string(value_.number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case (value_type::number_float):
|
case (value_t::number_float):
|
||||||
{
|
{
|
||||||
return std::to_string(value_.number_float);
|
return std::to_string(value_.number_float);
|
||||||
}
|
}
|
||||||
|
|
||||||
case (value_type::array):
|
case (value_t::array):
|
||||||
{
|
{
|
||||||
if (value_.array->empty())
|
if (value_.array->empty())
|
||||||
{
|
{
|
||||||
|
@ -560,7 +560,7 @@ std::string json::dump(const bool prettyPrint, const unsigned int indentStep,
|
||||||
return result + indent() + "]";
|
return result + indent() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
case (value_type::object):
|
case (value_t::object):
|
||||||
{
|
{
|
||||||
if (value_.object->empty())
|
if (value_.object->empty())
|
||||||
{
|
{
|
||||||
|
@ -597,7 +597,7 @@ std::string json::dump(const bool prettyPrint, const unsigned int indentStep,
|
||||||
return result + indent() + "}";
|
return result + indent() + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
// actually only value_type::null - but making the compiler happy
|
// actually only value_t::null - but making the compiler happy
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return "null";
|
return "null";
|
||||||
|
@ -717,15 +717,15 @@ an array, the passed element is added to the array.
|
||||||
void json::push_back(const json& o)
|
void json::push_back(const json& o)
|
||||||
{
|
{
|
||||||
// push_back only works for null objects or arrays
|
// push_back only works for null objects or arrays
|
||||||
if (not(type_ == value_type::null or type_ == value_type::array))
|
if (not(type_ == value_t::null or type_ == value_t::array))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("cannot add element to " + type_name());
|
throw std::runtime_error("cannot add element to " + type_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
// transform null object into an array
|
// transform null object into an array
|
||||||
if (type_ == value_type::null)
|
if (type_ == value_t::null)
|
||||||
{
|
{
|
||||||
type_ = value_type::array;
|
type_ = value_t::array;
|
||||||
value_.array = new array_t;
|
value_.array = new array_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,22 +752,22 @@ an array, the passed element is added to the array using move semantics.
|
||||||
void json::push_back(json&& o)
|
void json::push_back(json&& o)
|
||||||
{
|
{
|
||||||
// push_back only works for null objects or arrays
|
// push_back only works for null objects or arrays
|
||||||
if (not(type_ == value_type::null or type_ == value_type::array))
|
if (not(type_ == value_t::null or type_ == value_t::array))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("cannot add element to " + type_name());
|
throw std::runtime_error("cannot add element to " + type_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
// transform null object into an array
|
// transform null object into an array
|
||||||
if (type_ == value_type::null)
|
if (type_ == value_t::null)
|
||||||
{
|
{
|
||||||
type_ = value_type::array;
|
type_ = value_t::array;
|
||||||
value_.array = new array_t;
|
value_.array = new array_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add element to array (move semantics)
|
// add element to array (move semantics)
|
||||||
value_.array->emplace_back(std::move(o));
|
value_.array->emplace_back(std::move(o));
|
||||||
// invalidate object
|
// invalidate object
|
||||||
o.type_ = value_type::null;
|
o.type_ = value_t::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -789,9 +789,9 @@ void json::push_back(list_init_t a)
|
||||||
// is a string
|
// is a string
|
||||||
for (const auto& element : a)
|
for (const auto& element : a)
|
||||||
{
|
{
|
||||||
if (element.type_ != value_type::array or
|
if (element.type_ != value_t::array or
|
||||||
element.size() != 2 or
|
element.size() != 2 or
|
||||||
element[0].type_ != value_type::string)
|
element[0].type_ != value_t::string)
|
||||||
{
|
{
|
||||||
// the initializer list describes an array
|
// the initializer list describes an array
|
||||||
is_array = true;
|
is_array = true;
|
||||||
|
@ -832,10 +832,10 @@ index. Bounds will not be checked.
|
||||||
@pre Object is an array.
|
@pre Object is an array.
|
||||||
@exception std::domain_error if object is not an array
|
@exception std::domain_error if object is not an array
|
||||||
*/
|
*/
|
||||||
json& json::operator[](const int index)
|
json::reference json::operator[](const int index)
|
||||||
{
|
{
|
||||||
// this [] operator only works for arrays
|
// this [] operator only works for arrays
|
||||||
if (type_ != value_type::array)
|
if (type_ != value_t::array)
|
||||||
{
|
{
|
||||||
throw std::domain_error("cannot add entry with index " +
|
throw std::domain_error("cannot add entry with index " +
|
||||||
std::to_string(index) + " to " + type_name());
|
std::to_string(index) + " to " + type_name());
|
||||||
|
@ -861,10 +861,10 @@ index. Bounds will not be checked.
|
||||||
@pre Object is an array.
|
@pre Object is an array.
|
||||||
@exception std::domain_error if object is not an array
|
@exception std::domain_error if object is not an array
|
||||||
*/
|
*/
|
||||||
const json& json::operator[](const int index) const
|
json::const_reference json::operator[](const int index) const
|
||||||
{
|
{
|
||||||
// this [] operator only works for arrays
|
// this [] operator only works for arrays
|
||||||
if (type_ != value_type::array)
|
if (type_ != value_t::array)
|
||||||
{
|
{
|
||||||
throw std::domain_error("cannot get entry with index " +
|
throw std::domain_error("cannot get entry with index " +
|
||||||
std::to_string(index) + " from " + type_name());
|
std::to_string(index) + " from " + type_name());
|
||||||
|
@ -891,10 +891,10 @@ index. Bounds will be checked.
|
||||||
@exception std::domain_error if object is not an array
|
@exception std::domain_error if object is not an array
|
||||||
@exception std::out_of_range if index is out of range (via std::vector::at)
|
@exception std::out_of_range if index is out of range (via std::vector::at)
|
||||||
*/
|
*/
|
||||||
json& json::at(const int index)
|
json::reference json::at(const int index)
|
||||||
{
|
{
|
||||||
// this function only works for arrays
|
// this function only works for arrays
|
||||||
if (type_ != value_type::array)
|
if (type_ != value_t::array)
|
||||||
{
|
{
|
||||||
throw std::domain_error("cannot add entry with index " +
|
throw std::domain_error("cannot add entry with index " +
|
||||||
std::to_string(index) + " to " + type_name());
|
std::to_string(index) + " to " + type_name());
|
||||||
|
@ -921,10 +921,10 @@ index. Bounds will be checked.
|
||||||
@exception std::domain_error if object is not an array
|
@exception std::domain_error if object is not an array
|
||||||
@exception std::out_of_range if index is out of range (via std::vector::at)
|
@exception std::out_of_range if index is out of range (via std::vector::at)
|
||||||
*/
|
*/
|
||||||
const json& json::at(const int index) const
|
json::const_reference json::at(const int index) const
|
||||||
{
|
{
|
||||||
// this function only works for arrays
|
// this function only works for arrays
|
||||||
if (type_ != value_type::array)
|
if (type_ != value_t::array)
|
||||||
{
|
{
|
||||||
throw std::domain_error("cannot get entry with index " +
|
throw std::domain_error("cannot get entry with index " +
|
||||||
std::to_string(index) + " from " + type_name());
|
std::to_string(index) + " from " + type_name());
|
||||||
|
@ -937,7 +937,7 @@ const json& json::at(const int index) const
|
||||||
/*!
|
/*!
|
||||||
@copydoc json::operator[](const char* key)
|
@copydoc json::operator[](const char* key)
|
||||||
*/
|
*/
|
||||||
json& json::operator[](const std::string& key)
|
json::reference json::operator[](const std::string& key)
|
||||||
{
|
{
|
||||||
return operator[](key.c_str());
|
return operator[](key.c_str());
|
||||||
}
|
}
|
||||||
|
@ -955,17 +955,17 @@ key.
|
||||||
|
|
||||||
@exception std::domain_error if object is not an object (or null)
|
@exception std::domain_error if object is not an object (or null)
|
||||||
*/
|
*/
|
||||||
json& json::operator[](const char* key)
|
json::reference json::operator[](const char* key)
|
||||||
{
|
{
|
||||||
// implicitly convert null to object
|
// implicitly convert null to object
|
||||||
if (type_ == value_type::null)
|
if (type_ == value_t::null)
|
||||||
{
|
{
|
||||||
type_ = value_type::object;
|
type_ = value_t::object;
|
||||||
value_.object = new object_t;
|
value_.object = new object_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this [] operator only works for objects
|
// this [] operator only works for objects
|
||||||
if (type_ != value_type::object)
|
if (type_ != value_t::object)
|
||||||
{
|
{
|
||||||
throw std::domain_error("cannot add entry with key " +
|
throw std::domain_error("cannot add entry with key " +
|
||||||
std::string(key) + " to " + type_name());
|
std::string(key) + " to " + type_name());
|
||||||
|
@ -992,10 +992,10 @@ key.
|
||||||
@exception std::domain_error if object is not an object
|
@exception std::domain_error if object is not an object
|
||||||
@exception std::out_of_range if key is not found in object
|
@exception std::out_of_range if key is not found in object
|
||||||
*/
|
*/
|
||||||
const json& json::operator[](const std::string& key) const
|
json::const_reference json::operator[](const std::string& key) const
|
||||||
{
|
{
|
||||||
// this [] operator only works for objects
|
// this [] operator only works for objects
|
||||||
if (type_ != value_type::object)
|
if (type_ != value_t::object)
|
||||||
{
|
{
|
||||||
throw std::domain_error("cannot get entry with key " +
|
throw std::domain_error("cannot get entry with key " +
|
||||||
std::string(key) + " from " + type_name());
|
std::string(key) + " from " + type_name());
|
||||||
|
@ -1017,7 +1017,7 @@ const json& json::operator[](const std::string& key) const
|
||||||
/*!
|
/*!
|
||||||
@copydoc json::at(const char* key)
|
@copydoc json::at(const char* key)
|
||||||
*/
|
*/
|
||||||
json& json::at(const std::string& key)
|
json::reference json::at(const std::string& key)
|
||||||
{
|
{
|
||||||
return at(key.c_str());
|
return at(key.c_str());
|
||||||
}
|
}
|
||||||
|
@ -1035,10 +1035,10 @@ key.
|
||||||
@exception std::domain_error if object is not an object
|
@exception std::domain_error if object is not an object
|
||||||
@exception std::out_of_range if key was not found (via std::map::at)
|
@exception std::out_of_range if key was not found (via std::map::at)
|
||||||
*/
|
*/
|
||||||
json& json::at(const char* key)
|
json::reference json::at(const char* key)
|
||||||
{
|
{
|
||||||
// this function operator only works for objects
|
// this function operator only works for objects
|
||||||
if (type_ != value_type::object)
|
if (type_ != value_t::object)
|
||||||
{
|
{
|
||||||
throw std::domain_error("cannot add entry with key " +
|
throw std::domain_error("cannot add entry with key " +
|
||||||
std::string(key) + " to " + type_name());
|
std::string(key) + " to " + type_name());
|
||||||
|
@ -1051,7 +1051,7 @@ json& json::at(const char* key)
|
||||||
/*!
|
/*!
|
||||||
@copydoc json::at(const char *key) const
|
@copydoc json::at(const char *key) const
|
||||||
*/
|
*/
|
||||||
const json& json::at(const std::string& key) const
|
json::const_reference json::at(const std::string& key) const
|
||||||
{
|
{
|
||||||
return at(key.c_str());
|
return at(key.c_str());
|
||||||
}
|
}
|
||||||
|
@ -1067,10 +1067,10 @@ key.
|
||||||
@exception std::domain_error if object is not an object
|
@exception std::domain_error if object is not an object
|
||||||
@exception std::out_of_range if key is not found (via std::map::at)
|
@exception std::out_of_range if key is not found (via std::map::at)
|
||||||
*/
|
*/
|
||||||
const json& json::at(const char* key) const
|
json::const_reference json::at(const char* key) const
|
||||||
{
|
{
|
||||||
// this [] operator only works for objects
|
// this [] operator only works for objects
|
||||||
if (type_ != value_type::object)
|
if (type_ != value_t::object)
|
||||||
{
|
{
|
||||||
throw std::domain_error("cannot get entry with key " +
|
throw std::domain_error("cannot get entry with key " +
|
||||||
std::string(key) + " from " + type_name());
|
std::string(key) + " from " + type_name());
|
||||||
|
@ -1080,7 +1080,6 @@ const json& json::at(const char* key) const
|
||||||
return value_.object->at(key);
|
return value_.object->at(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the size of the JSON object.
|
Returns the size of the JSON object.
|
||||||
|
|
||||||
|
@ -1090,19 +1089,49 @@ Returns the size of the JSON object.
|
||||||
|
|
||||||
@invariant The size is reported as 0 if and only if empty() would return true.
|
@invariant The size is reported as 0 if and only if empty() would return true.
|
||||||
*/
|
*/
|
||||||
std::size_t json::size() const noexcept
|
json::size_type json::size() const noexcept
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::array):
|
case (value_t::array):
|
||||||
{
|
{
|
||||||
return value_.array->size();
|
return value_.array->size();
|
||||||
}
|
}
|
||||||
case (value_type::object):
|
case (value_t::object):
|
||||||
{
|
{
|
||||||
return value_.object->size();
|
return value_.object->size();
|
||||||
}
|
}
|
||||||
case (value_type::null):
|
case (value_t::null):
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the maximal size of the JSON object.
|
||||||
|
|
||||||
|
@return the maximal size of the JSON object; the maximal size is the maximal
|
||||||
|
number of elements in compounds (array and object), 1 for value types
|
||||||
|
(true, false, number, string), and 0 for null.
|
||||||
|
*/
|
||||||
|
json::size_type json::max_size() const noexcept
|
||||||
|
{
|
||||||
|
switch (type_)
|
||||||
|
{
|
||||||
|
case (value_t::array):
|
||||||
|
{
|
||||||
|
return value_.array->max_size();
|
||||||
|
}
|
||||||
|
case (value_t::object):
|
||||||
|
{
|
||||||
|
return value_.object->max_size();
|
||||||
|
}
|
||||||
|
case (value_t::null):
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1126,15 +1155,15 @@ bool json::empty() const noexcept
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::array):
|
case (value_t::array):
|
||||||
{
|
{
|
||||||
return value_.array->empty();
|
return value_.array->empty();
|
||||||
}
|
}
|
||||||
case (value_type::object):
|
case (value_t::object):
|
||||||
{
|
{
|
||||||
return value_.object->empty();
|
return value_.object->empty();
|
||||||
}
|
}
|
||||||
case (value_type::null):
|
case (value_t::null):
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1156,32 +1185,32 @@ void json::clear() noexcept
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::array):
|
case (value_t::array):
|
||||||
{
|
{
|
||||||
value_.array->clear();
|
value_.array->clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::object):
|
case (value_t::object):
|
||||||
{
|
{
|
||||||
value_.object->clear();
|
value_.object->clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::string):
|
case (value_t::string):
|
||||||
{
|
{
|
||||||
value_.string->clear();
|
value_.string->clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::boolean):
|
case (value_t::boolean):
|
||||||
{
|
{
|
||||||
value_.boolean = {};
|
value_.boolean = {};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::number):
|
case (value_t::number):
|
||||||
{
|
{
|
||||||
value_.number = {};
|
value_.number = {};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::number_float):
|
case (value_t::number_float):
|
||||||
{
|
{
|
||||||
value_.number_float = {};
|
value_.number_float = {};
|
||||||
break;
|
break;
|
||||||
|
@ -1199,7 +1228,7 @@ void json::swap(json& o) noexcept
|
||||||
std::swap(value_, o.value_);
|
std::swap(value_, o.value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
json::value_type json::type() const noexcept
|
json::value_t json::type() const noexcept
|
||||||
{
|
{
|
||||||
return type_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
@ -1216,7 +1245,7 @@ json::const_iterator json::find(const std::string& key) const
|
||||||
|
|
||||||
json::iterator json::find(const char* key)
|
json::iterator json::find(const char* key)
|
||||||
{
|
{
|
||||||
if (type_ != value_type::object)
|
if (type_ != value_t::object)
|
||||||
{
|
{
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
|
@ -1240,7 +1269,7 @@ json::iterator json::find(const char* key)
|
||||||
|
|
||||||
json::const_iterator json::find(const char* key) const
|
json::const_iterator json::find(const char* key) const
|
||||||
{
|
{
|
||||||
if (type_ != value_type::object)
|
if (type_ != value_t::object)
|
||||||
{
|
{
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
|
@ -1266,65 +1295,65 @@ bool json::operator==(const json& o) const noexcept
|
||||||
{
|
{
|
||||||
switch (type_)
|
switch (type_)
|
||||||
{
|
{
|
||||||
case (value_type::array):
|
case (value_t::array):
|
||||||
{
|
{
|
||||||
if (o.type_ == value_type::array)
|
if (o.type_ == value_t::array)
|
||||||
{
|
{
|
||||||
return *value_.array == *o.value_.array;
|
return *value_.array == *o.value_.array;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::object):
|
case (value_t::object):
|
||||||
{
|
{
|
||||||
if (o.type_ == value_type::object)
|
if (o.type_ == value_t::object)
|
||||||
{
|
{
|
||||||
return *value_.object == *o.value_.object;
|
return *value_.object == *o.value_.object;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::null):
|
case (value_t::null):
|
||||||
{
|
{
|
||||||
if (o.type_ == value_type::null)
|
if (o.type_ == value_t::null)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::string):
|
case (value_t::string):
|
||||||
{
|
{
|
||||||
if (o.type_ == value_type::string)
|
if (o.type_ == value_t::string)
|
||||||
{
|
{
|
||||||
return *value_.string == *o.value_.string;
|
return *value_.string == *o.value_.string;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::boolean):
|
case (value_t::boolean):
|
||||||
{
|
{
|
||||||
if (o.type_ == value_type::boolean)
|
if (o.type_ == value_t::boolean)
|
||||||
{
|
{
|
||||||
return value_.boolean == o.value_.boolean;
|
return value_.boolean == o.value_.boolean;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::number):
|
case (value_t::number):
|
||||||
{
|
{
|
||||||
if (o.type_ == value_type::number)
|
if (o.type_ == value_t::number)
|
||||||
{
|
{
|
||||||
return value_.number == o.value_.number;
|
return value_.number == o.value_.number;
|
||||||
}
|
}
|
||||||
if (o.type_ == value_type::number_float)
|
if (o.type_ == value_t::number_float)
|
||||||
{
|
{
|
||||||
return value_.number == static_cast<number_t>(o.value_.number_float);
|
return value_.number == static_cast<number_t>(o.value_.number_float);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (value_type::number_float):
|
case (value_t::number_float):
|
||||||
{
|
{
|
||||||
if (o.type_ == value_type::number)
|
if (o.type_ == value_t::number)
|
||||||
{
|
{
|
||||||
return value_.number_float == static_cast<number_float_t>(o.value_.number);
|
return value_.number_float == static_cast<number_float_t>(o.value_.number);
|
||||||
}
|
}
|
||||||
if (o.type_ == value_type::number_float)
|
if (o.type_ == value_t::number_float)
|
||||||
{
|
{
|
||||||
return value_.number_float == o.value_.number_float;
|
return value_.number_float == o.value_.number_float;
|
||||||
}
|
}
|
||||||
|
@ -1376,7 +1405,7 @@ json::iterator::iterator(json* j) : object_(j)
|
||||||
{
|
{
|
||||||
if (object_ != nullptr)
|
if (object_ != nullptr)
|
||||||
{
|
{
|
||||||
if (object_->type_ == json::value_type::array)
|
if (object_->type_ == json::value_t::array)
|
||||||
{
|
{
|
||||||
if (object_->empty())
|
if (object_->empty())
|
||||||
{
|
{
|
||||||
|
@ -1387,7 +1416,7 @@ json::iterator::iterator(json* j) : object_(j)
|
||||||
vi_ = new array_t::iterator(object_->value_.array->begin());
|
vi_ = new array_t::iterator(object_->value_.array->begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (object_->type_ == json::value_type::object)
|
else if (object_->type_ == json::value_t::object)
|
||||||
{
|
{
|
||||||
if (object_->empty())
|
if (object_->empty())
|
||||||
{
|
{
|
||||||
|
@ -1405,7 +1434,7 @@ json::iterator::iterator(const json::iterator& o) : object_(o.object_)
|
||||||
{
|
{
|
||||||
if (object_ != nullptr)
|
if (object_ != nullptr)
|
||||||
{
|
{
|
||||||
if (object_->type_ == json::value_type::array)
|
if (object_->type_ == json::value_t::array)
|
||||||
{
|
{
|
||||||
if (object_->empty())
|
if (object_->empty())
|
||||||
{
|
{
|
||||||
|
@ -1416,7 +1445,7 @@ json::iterator::iterator(const json::iterator& o) : object_(o.object_)
|
||||||
vi_ = new array_t::iterator(object_->value_.array->begin());
|
vi_ = new array_t::iterator(object_->value_.array->begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (object_->type_ == json::value_type::object)
|
else if (object_->type_ == json::value_t::object)
|
||||||
{
|
{
|
||||||
if (object_->empty())
|
if (object_->empty())
|
||||||
{
|
{
|
||||||
|
@ -1453,11 +1482,11 @@ bool json::iterator::operator==(const json::iterator& o) const
|
||||||
|
|
||||||
if (object_ != nullptr)
|
if (object_ != nullptr)
|
||||||
{
|
{
|
||||||
if (object_->type_ == json::value_type::array)
|
if (object_->type_ == json::value_t::array)
|
||||||
{
|
{
|
||||||
return (vi_ == o.vi_);
|
return (vi_ == o.vi_);
|
||||||
}
|
}
|
||||||
if (object_->type_ == json::value_type::object)
|
if (object_->type_ == json::value_t::object)
|
||||||
{
|
{
|
||||||
return (oi_ == o.oi_);
|
return (oi_ == o.oi_);
|
||||||
}
|
}
|
||||||
|
@ -1481,7 +1510,7 @@ json::iterator& json::iterator::operator++()
|
||||||
|
|
||||||
switch (object_->type_)
|
switch (object_->type_)
|
||||||
{
|
{
|
||||||
case (json::value_type::array):
|
case (json::value_t::array):
|
||||||
{
|
{
|
||||||
if (++(*vi_) == object_->value_.array->end())
|
if (++(*vi_) == object_->value_.array->end())
|
||||||
{
|
{
|
||||||
|
@ -1489,7 +1518,7 @@ json::iterator& json::iterator::operator++()
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (json::value_type::object):
|
case (json::value_t::object):
|
||||||
{
|
{
|
||||||
if (++(*oi_) == object_->value_.object->end())
|
if (++(*oi_) == object_->value_.object->end())
|
||||||
{
|
{
|
||||||
|
@ -1515,11 +1544,11 @@ json& json::iterator::operator*() const
|
||||||
|
|
||||||
switch (object_->type_)
|
switch (object_->type_)
|
||||||
{
|
{
|
||||||
case (json::value_type::array):
|
case (json::value_t::array):
|
||||||
{
|
{
|
||||||
return **vi_;
|
return **vi_;
|
||||||
}
|
}
|
||||||
case (json::value_type::object):
|
case (json::value_t::object):
|
||||||
{
|
{
|
||||||
return (*oi_)->second;
|
return (*oi_)->second;
|
||||||
}
|
}
|
||||||
|
@ -1540,11 +1569,11 @@ json* json::iterator::operator->() const
|
||||||
|
|
||||||
switch (object_->type_)
|
switch (object_->type_)
|
||||||
{
|
{
|
||||||
case (json::value_type::array):
|
case (json::value_t::array):
|
||||||
{
|
{
|
||||||
return &(**vi_);
|
return &(**vi_);
|
||||||
}
|
}
|
||||||
case (json::value_type::object):
|
case (json::value_t::object):
|
||||||
{
|
{
|
||||||
return &((*oi_)->second);
|
return &((*oi_)->second);
|
||||||
}
|
}
|
||||||
|
@ -1557,7 +1586,7 @@ json* json::iterator::operator->() const
|
||||||
|
|
||||||
std::string json::iterator::key() const
|
std::string json::iterator::key() const
|
||||||
{
|
{
|
||||||
if (object_ != nullptr and object_->type_ == json::value_type::object)
|
if (object_ != nullptr and object_->type_ == json::value_t::object)
|
||||||
{
|
{
|
||||||
return (*oi_)->first;
|
return (*oi_)->first;
|
||||||
}
|
}
|
||||||
|
@ -1577,11 +1606,11 @@ json& json::iterator::value() const
|
||||||
|
|
||||||
switch (object_->type_)
|
switch (object_->type_)
|
||||||
{
|
{
|
||||||
case (json::value_type::array):
|
case (json::value_t::array):
|
||||||
{
|
{
|
||||||
return **vi_;
|
return **vi_;
|
||||||
}
|
}
|
||||||
case (json::value_type::object):
|
case (json::value_t::object):
|
||||||
{
|
{
|
||||||
return (*oi_)->second;
|
return (*oi_)->second;
|
||||||
}
|
}
|
||||||
|
@ -1597,7 +1626,7 @@ json::const_iterator::const_iterator(const json* j) : object_(j)
|
||||||
{
|
{
|
||||||
if (object_ != nullptr)
|
if (object_ != nullptr)
|
||||||
{
|
{
|
||||||
if (object_->type_ == json::value_type::array)
|
if (object_->type_ == json::value_t::array)
|
||||||
{
|
{
|
||||||
if (object_->empty())
|
if (object_->empty())
|
||||||
{
|
{
|
||||||
|
@ -1608,7 +1637,7 @@ json::const_iterator::const_iterator(const json* j) : object_(j)
|
||||||
vi_ = new array_t::const_iterator(object_->value_.array->begin());
|
vi_ = new array_t::const_iterator(object_->value_.array->begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (object_->type_ == json::value_type::object)
|
else if (object_->type_ == json::value_t::object)
|
||||||
{
|
{
|
||||||
if (object_->empty())
|
if (object_->empty())
|
||||||
{
|
{
|
||||||
|
@ -1626,7 +1655,7 @@ json::const_iterator::const_iterator(const json::const_iterator& o) : object_(o.
|
||||||
{
|
{
|
||||||
if (object_ != nullptr)
|
if (object_ != nullptr)
|
||||||
{
|
{
|
||||||
if (object_->type_ == json::value_type::array)
|
if (object_->type_ == json::value_t::array)
|
||||||
{
|
{
|
||||||
if (object_->empty())
|
if (object_->empty())
|
||||||
{
|
{
|
||||||
|
@ -1637,7 +1666,7 @@ json::const_iterator::const_iterator(const json::const_iterator& o) : object_(o.
|
||||||
vi_ = new array_t::const_iterator(object_->value_.array->begin());
|
vi_ = new array_t::const_iterator(object_->value_.array->begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (object_->type_ == json::value_type::object)
|
else if (object_->type_ == json::value_t::object)
|
||||||
{
|
{
|
||||||
if (object_->empty())
|
if (object_->empty())
|
||||||
{
|
{
|
||||||
|
@ -1655,7 +1684,7 @@ json::const_iterator::const_iterator(const json::iterator& o) : object_(o.object
|
||||||
{
|
{
|
||||||
if (object_ != nullptr)
|
if (object_ != nullptr)
|
||||||
{
|
{
|
||||||
if (object_->type_ == json::value_type::array)
|
if (object_->type_ == json::value_t::array)
|
||||||
{
|
{
|
||||||
if (object_->empty())
|
if (object_->empty())
|
||||||
{
|
{
|
||||||
|
@ -1666,7 +1695,7 @@ json::const_iterator::const_iterator(const json::iterator& o) : object_(o.object
|
||||||
vi_ = new array_t::const_iterator(object_->value_.array->begin());
|
vi_ = new array_t::const_iterator(object_->value_.array->begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (object_->type_ == json::value_type::object)
|
else if (object_->type_ == json::value_t::object)
|
||||||
{
|
{
|
||||||
if (object_->empty())
|
if (object_->empty())
|
||||||
{
|
{
|
||||||
|
@ -1703,11 +1732,11 @@ bool json::const_iterator::operator==(const json::const_iterator& o) const
|
||||||
|
|
||||||
if (object_ != nullptr)
|
if (object_ != nullptr)
|
||||||
{
|
{
|
||||||
if (object_->type_ == json::value_type::array)
|
if (object_->type_ == json::value_t::array)
|
||||||
{
|
{
|
||||||
return (vi_ == o.vi_);
|
return (vi_ == o.vi_);
|
||||||
}
|
}
|
||||||
if (object_->type_ == json::value_type::object)
|
if (object_->type_ == json::value_t::object)
|
||||||
{
|
{
|
||||||
return (oi_ == o.oi_);
|
return (oi_ == o.oi_);
|
||||||
}
|
}
|
||||||
|
@ -1731,7 +1760,7 @@ json::const_iterator& json::const_iterator::operator++()
|
||||||
|
|
||||||
switch (object_->type_)
|
switch (object_->type_)
|
||||||
{
|
{
|
||||||
case (json::value_type::array):
|
case (json::value_t::array):
|
||||||
{
|
{
|
||||||
if (++(*vi_) == object_->value_.array->end())
|
if (++(*vi_) == object_->value_.array->end())
|
||||||
{
|
{
|
||||||
|
@ -1739,7 +1768,7 @@ json::const_iterator& json::const_iterator::operator++()
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (json::value_type::object):
|
case (json::value_t::object):
|
||||||
{
|
{
|
||||||
if (++(*oi_) == object_->value_.object->end())
|
if (++(*oi_) == object_->value_.object->end())
|
||||||
{
|
{
|
||||||
|
@ -1765,11 +1794,11 @@ const json& json::const_iterator::operator*() const
|
||||||
|
|
||||||
switch (object_->type_)
|
switch (object_->type_)
|
||||||
{
|
{
|
||||||
case (json::value_type::array):
|
case (json::value_t::array):
|
||||||
{
|
{
|
||||||
return **vi_;
|
return **vi_;
|
||||||
}
|
}
|
||||||
case (json::value_type::object):
|
case (json::value_t::object):
|
||||||
{
|
{
|
||||||
return (*oi_)->second;
|
return (*oi_)->second;
|
||||||
}
|
}
|
||||||
|
@ -1790,11 +1819,11 @@ const json* json::const_iterator::operator->() const
|
||||||
|
|
||||||
switch (object_->type_)
|
switch (object_->type_)
|
||||||
{
|
{
|
||||||
case (json::value_type::array):
|
case (json::value_t::array):
|
||||||
{
|
{
|
||||||
return &(**vi_);
|
return &(**vi_);
|
||||||
}
|
}
|
||||||
case (json::value_type::object):
|
case (json::value_t::object):
|
||||||
{
|
{
|
||||||
return &((*oi_)->second);
|
return &((*oi_)->second);
|
||||||
}
|
}
|
||||||
|
@ -1807,7 +1836,7 @@ const json* json::const_iterator::operator->() const
|
||||||
|
|
||||||
std::string json::const_iterator::key() const
|
std::string json::const_iterator::key() const
|
||||||
{
|
{
|
||||||
if (object_ != nullptr and object_->type_ == json::value_type::object)
|
if (object_ != nullptr and object_->type_ == json::value_t::object)
|
||||||
{
|
{
|
||||||
return (*oi_)->first;
|
return (*oi_)->first;
|
||||||
}
|
}
|
||||||
|
@ -1827,11 +1856,11 @@ const json& json::const_iterator::value() const
|
||||||
|
|
||||||
switch (object_->type_)
|
switch (object_->type_)
|
||||||
{
|
{
|
||||||
case (json::value_type::array):
|
case (json::value_t::array):
|
||||||
{
|
{
|
||||||
return **vi_;
|
return **vi_;
|
||||||
}
|
}
|
||||||
case (json::value_type::object):
|
case (json::value_t::object):
|
||||||
{
|
{
|
||||||
return (*oi_)->second;
|
return (*oi_)->second;
|
||||||
}
|
}
|
||||||
|
@ -1901,7 +1930,7 @@ json json::parser::parse()
|
||||||
case ('{'):
|
case ('{'):
|
||||||
{
|
{
|
||||||
// explicitly set result to object to cope with {}
|
// explicitly set result to object to cope with {}
|
||||||
json result(value_type::object);
|
json result(value_t::object);
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
|
||||||
|
@ -1932,7 +1961,7 @@ json json::parser::parse()
|
||||||
case ('['):
|
case ('['):
|
||||||
{
|
{
|
||||||
// explicitly set result to array to cope with []
|
// explicitly set result to array to cope with []
|
||||||
json result(value_type::array);
|
json result(value_t::array);
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
|
||||||
|
|
117
src/json.h
117
src/json.h
|
@ -2,7 +2,7 @@
|
||||||
@file
|
@file
|
||||||
@copyright The code is licensed under the MIT License
|
@copyright The code is licensed under the MIT License
|
||||||
<http://opensource.org/licenses/MIT>,
|
<http://opensource.org/licenses/MIT>,
|
||||||
Copyright (c) 2013-2014 Niels Lohmann.
|
Copyright (c) 2013-2015 Niels Lohmann.
|
||||||
|
|
||||||
@author Niels Lohmann <http://nlohmann.me>
|
@author Niels Lohmann <http://nlohmann.me>
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
||||||
#include <vector> // std::vector
|
#include <vector> // std::vector
|
||||||
#include <iterator> // std::iterator
|
#include <iterator> // std::iterator
|
||||||
#include <limits> // std::numeric_limits
|
#include <limits> // std::numeric_limits
|
||||||
|
#include <functional> // std::hash
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
{
|
{
|
||||||
|
@ -41,30 +42,21 @@ due to alignment.
|
||||||
*/
|
*/
|
||||||
class json
|
class json
|
||||||
{
|
{
|
||||||
// forward declaration to friend this class
|
|
||||||
public:
|
public:
|
||||||
|
// forward declaration to friend this class
|
||||||
class iterator;
|
class iterator;
|
||||||
class const_iterator;
|
class const_iterator;
|
||||||
|
|
||||||
public:
|
// container types
|
||||||
/// possible types of a JSON object
|
using value_type = json;
|
||||||
enum class value_type : uint8_t
|
using reference = json&;
|
||||||
{
|
using const_reference = const json&;
|
||||||
/// ordered collection of values
|
using pointer = json*;
|
||||||
array = 0,
|
using const_pointer = const json*;
|
||||||
/// unordered set of name/value pairs
|
using iterator = json::iterator;
|
||||||
object,
|
using const_iterator = json::const_iterator;
|
||||||
/// null value
|
using difference_type = std::ptrdiff_t;
|
||||||
null,
|
using size_type = std::size_t;
|
||||||
/// string value
|
|
||||||
string,
|
|
||||||
/// Boolean value
|
|
||||||
boolean,
|
|
||||||
/// number value (integer)
|
|
||||||
number,
|
|
||||||
/// number value (float)
|
|
||||||
number_float
|
|
||||||
};
|
|
||||||
|
|
||||||
/// a type for an object
|
/// a type for an object
|
||||||
using object_t = std::map<std::string, json>;
|
using object_t = std::map<std::string, json>;
|
||||||
|
@ -113,9 +105,28 @@ class json
|
||||||
value(number_float_t);
|
value(number_float_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// possible types of a JSON object
|
||||||
|
enum class value_t : uint8_t
|
||||||
|
{
|
||||||
|
/// ordered collection of values
|
||||||
|
array = 0,
|
||||||
|
/// unordered set of name/value pairs
|
||||||
|
object,
|
||||||
|
/// null value
|
||||||
|
null,
|
||||||
|
/// string value
|
||||||
|
string,
|
||||||
|
/// Boolean value
|
||||||
|
boolean,
|
||||||
|
/// number value (integer)
|
||||||
|
number,
|
||||||
|
/// number value (float)
|
||||||
|
number_float
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// create an object according to given type
|
/// create an object according to given type
|
||||||
json(const value_type);
|
json(const value_t);
|
||||||
/// create a null object
|
/// create a null object
|
||||||
json() = default;
|
json() = default;
|
||||||
/// create a null object
|
/// create a null object
|
||||||
|
@ -140,15 +151,23 @@ class json
|
||||||
json(list_init_t);
|
json(list_init_t);
|
||||||
|
|
||||||
/// create a number object (integer)
|
/// create a number object (integer)
|
||||||
template<typename T, typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type = 0>
|
template<typename T, typename
|
||||||
|
std::enable_if<
|
||||||
|
std::numeric_limits<T>::is_integer, T>::type
|
||||||
|
= 0>
|
||||||
json(const T n) noexcept
|
json(const T n) noexcept
|
||||||
: type_(value_type::number), value_(static_cast<number_t>(n))
|
: type_(value_t::number),
|
||||||
|
value_(static_cast<number_t>(n))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// create a number object (float)
|
/// create a number object (float)
|
||||||
template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
|
template<typename T, typename = typename
|
||||||
|
std::enable_if<
|
||||||
|
std::is_floating_point<T>::value>::type
|
||||||
|
>
|
||||||
json(const T n) noexcept
|
json(const T n) noexcept
|
||||||
: type_(value_type::number_float), value_(static_cast<number_float_t>(n))
|
: type_(value_t::number_float),
|
||||||
|
value_(static_cast<number_float_t>(n))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// create an array object
|
/// create an array object
|
||||||
|
@ -284,27 +303,29 @@ class json
|
||||||
/// operator to get an element in an array
|
/// operator to get an element in an array
|
||||||
const json& operator[](const int) const;
|
const json& operator[](const int) const;
|
||||||
/// operator to get an element in an array
|
/// operator to get an element in an array
|
||||||
json& at(const int);
|
reference at(const int);
|
||||||
/// operator to get an element in an array
|
/// operator to get an element in an array
|
||||||
const json& at(const int) const;
|
const_reference at(const int) const;
|
||||||
|
|
||||||
/// operator to set an element in an object
|
/// operator to set an element in an object
|
||||||
json& operator[](const std::string&);
|
reference operator[](const std::string&);
|
||||||
/// operator to set an element in an object
|
/// operator to set an element in an object
|
||||||
json& operator[](const char*);
|
reference operator[](const char*);
|
||||||
/// operator to get an element in an object
|
/// operator to get an element in an object
|
||||||
const json& operator[](const std::string&) const;
|
const_reference operator[](const std::string&) const;
|
||||||
/// operator to set an element in an object
|
/// operator to set an element in an object
|
||||||
json& at(const std::string&);
|
reference at(const std::string&);
|
||||||
/// operator to set an element in an object
|
/// operator to set an element in an object
|
||||||
json& at(const char*);
|
reference at(const char*);
|
||||||
/// operator to get an element in an object
|
/// operator to get an element in an object
|
||||||
const json& at(const std::string&) const;
|
const_reference at(const std::string&) const;
|
||||||
/// operator to get an element in an object
|
/// operator to get an element in an object
|
||||||
const json& at(const char*) const;
|
const_reference at(const char*) const;
|
||||||
|
|
||||||
/// return the number of stored values
|
/// return the number of stored values
|
||||||
std::size_t size() const noexcept;
|
size_type size() const noexcept;
|
||||||
|
/// return the maximal number of values that can be stored
|
||||||
|
size_type max_size() const noexcept;
|
||||||
/// checks whether object is empty
|
/// checks whether object is empty
|
||||||
bool empty() const noexcept;
|
bool empty() const noexcept;
|
||||||
/// removes all elements from compounds and resets values to default
|
/// removes all elements from compounds and resets values to default
|
||||||
|
@ -314,7 +335,7 @@ class json
|
||||||
void swap(json&) noexcept;
|
void swap(json&) noexcept;
|
||||||
|
|
||||||
/// return the type of the object
|
/// return the type of the object
|
||||||
value_type type() const noexcept;
|
value_t type() const noexcept;
|
||||||
|
|
||||||
/// find an element in an object (returns end() iterator otherwise)
|
/// find an element in an object (returns end() iterator otherwise)
|
||||||
iterator find(const std::string&);
|
iterator find(const std::string&);
|
||||||
|
@ -345,7 +366,7 @@ class json
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// the type of this object
|
/// the type of this object
|
||||||
value_type type_ = value_type::null;
|
value_t type_ = value_t::null;
|
||||||
|
|
||||||
/// the payload
|
/// the payload
|
||||||
value value_ {};
|
value value_ {};
|
||||||
|
@ -475,15 +496,29 @@ class json
|
||||||
/// user-defined literal operator to create JSON objects from strings
|
/// user-defined literal operator to create JSON objects from strings
|
||||||
nlohmann::json operator "" _json(const char*, std::size_t);
|
nlohmann::json operator "" _json(const char*, std::size_t);
|
||||||
|
|
||||||
// specialization of std::swap
|
// specialization of std::swap, and std::hash
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
template <>
|
template <>
|
||||||
/// swaps the values of two JSON objects
|
/// swaps the values of two JSON objects
|
||||||
inline void swap(nlohmann::json& j1,
|
inline void swap(nlohmann::json& j1,
|
||||||
nlohmann::json& j2) noexcept(is_nothrow_move_constructible<nlohmann::json>::value and
|
nlohmann::json& j2) noexcept(
|
||||||
is_nothrow_move_assignable<nlohmann::json>::value)
|
is_nothrow_move_constructible<nlohmann::json>::value and
|
||||||
|
is_nothrow_move_assignable<nlohmann::json>::value
|
||||||
|
)
|
||||||
{
|
{
|
||||||
j1.swap(j2);
|
j1.swap(j2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
/// hash value for JSON objects
|
||||||
|
struct hash<nlohmann::json>
|
||||||
|
{
|
||||||
|
size_t operator()(const nlohmann::json& j) const
|
||||||
|
{
|
||||||
|
// a naive hashing via the string representation
|
||||||
|
return hash<std::string>()(j.dump());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ TEST_CASE("array")
|
||||||
SECTION("Basics")
|
SECTION("Basics")
|
||||||
{
|
{
|
||||||
// construction with given type
|
// construction with given type
|
||||||
json j(json::value_type::array);
|
json j(json::value_t::array);
|
||||||
CHECK(j.type() == json::value_type::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
|
|
||||||
// const object
|
// const object
|
||||||
const json j_const (j);
|
const json j_const (j);
|
||||||
|
@ -34,7 +34,9 @@ TEST_CASE("array")
|
||||||
|
|
||||||
// container members
|
// container members
|
||||||
CHECK(j.size() == 0);
|
CHECK(j.size() == 0);
|
||||||
|
CHECK(j.max_size() > 0);
|
||||||
CHECK(j.empty() == true);
|
CHECK(j.empty() == true);
|
||||||
|
CHECK_NOTHROW(size_t h = std::hash<json>()(j));
|
||||||
|
|
||||||
// implicit conversions
|
// implicit conversions
|
||||||
CHECK_NOTHROW(json::array_t v = j);
|
CHECK_NOTHROW(json::array_t v = j);
|
||||||
|
@ -88,21 +90,21 @@ TEST_CASE("array")
|
||||||
|
|
||||||
// case 1: there is an element that is not an array
|
// case 1: there is an element that is not an array
|
||||||
json j3 = { {"foo", "bar"}, 3 };
|
json j3 = { {"foo", "bar"}, 3 };
|
||||||
CHECK(j3.type() == json::value_type::array);
|
CHECK(j3.type() == json::value_t::array);
|
||||||
|
|
||||||
// case 2: there is an element with more than two elements
|
// case 2: there is an element with more than two elements
|
||||||
json j4 = { {"foo", "bar"}, {"one", "two", "three"} };
|
json j4 = { {"foo", "bar"}, {"one", "two", "three"} };
|
||||||
CHECK(j4.type() == json::value_type::array);
|
CHECK(j4.type() == json::value_t::array);
|
||||||
|
|
||||||
// case 3: there is an element whose first element is not a string
|
// case 3: there is an element whose first element is not a string
|
||||||
json j5 = { {"foo", "bar"}, {true, "baz"} };
|
json j5 = { {"foo", "bar"}, {true, "baz"} };
|
||||||
CHECK(j5.type() == json::value_type::array);
|
CHECK(j5.type() == json::value_t::array);
|
||||||
|
|
||||||
// check if nested arrays work and are recognized as arrays
|
// check if nested arrays work and are recognized as arrays
|
||||||
json j6 = { {{"foo", "bar"}} };
|
json j6 = { {{"foo", "bar"}} };
|
||||||
CHECK(j6.type() == json::value_type::array);
|
CHECK(j6.type() == json::value_t::array);
|
||||||
CHECK(j6.size() == 1);
|
CHECK(j6.size() == 1);
|
||||||
CHECK(j6[0].type() == json::value_type::object);
|
CHECK(j6[0].type() == json::value_t::object);
|
||||||
|
|
||||||
// move constructor
|
// move constructor
|
||||||
json j7(std::move(v1));
|
json j7(std::move(v1));
|
||||||
|
@ -152,8 +154,8 @@ TEST_CASE("array")
|
||||||
json empty1, empty2;
|
json empty1, empty2;
|
||||||
empty1 += "foo";
|
empty1 += "foo";
|
||||||
empty2.push_back("foo");
|
empty2.push_back("foo");
|
||||||
CHECK(empty1.type() == json::value_type::array);
|
CHECK(empty1.type() == json::value_t::array);
|
||||||
CHECK(empty2.type() == json::value_type::array);
|
CHECK(empty2.type() == json::value_t::array);
|
||||||
CHECK(empty1 == empty2);
|
CHECK(empty1 == empty2);
|
||||||
|
|
||||||
// exceptions
|
// exceptions
|
||||||
|
@ -182,7 +184,7 @@ TEST_CASE("array")
|
||||||
CHECK_THROWS_AS(nonarray2.push_back(nonarray3), std::runtime_error);
|
CHECK_THROWS_AS(nonarray2.push_back(nonarray3), std::runtime_error);
|
||||||
CHECK_THROWS_AS(nonarray2.push_back(3), std::runtime_error);
|
CHECK_THROWS_AS(nonarray2.push_back(3), std::runtime_error);
|
||||||
CHECK_NOTHROW(empty3.push_back(nonarray3));
|
CHECK_NOTHROW(empty3.push_back(nonarray3));
|
||||||
CHECK(empty3.type() == json::value_type::array);
|
CHECK(empty3.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
const json k = j;
|
const json k = j;
|
||||||
|
@ -300,12 +302,12 @@ TEST_CASE("array")
|
||||||
// turn arrays with two strings. However, this is treated like the
|
// turn arrays with two strings. However, this is treated like the
|
||||||
// initializer list of an object.
|
// initializer list of an object.
|
||||||
json j_should_be_an_array = { {"foo", "bar"}, {"baz", "bat"} };
|
json j_should_be_an_array = { {"foo", "bar"}, {"baz", "bat"} };
|
||||||
CHECK(j_should_be_an_array.type() == json::value_type::object);
|
CHECK(j_should_be_an_array.type() == json::value_t::object);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Iterators and empty arrays")
|
SECTION("Iterators and empty arrays")
|
||||||
{
|
{
|
||||||
json empty_array(json::value_type::array);
|
json empty_array(json::value_t::array);
|
||||||
for (json::iterator it = empty_array.begin(); it != empty_array.end(); ++it) {}
|
for (json::iterator it = empty_array.begin(); it != empty_array.end(); ++it) {}
|
||||||
for (json::const_iterator it = empty_array.begin(); it != empty_array.end(); ++it) {}
|
for (json::const_iterator it = empty_array.begin(); it != empty_array.end(); ++it) {}
|
||||||
for (json::const_iterator it = empty_array.cbegin(); it != empty_array.cend(); ++it) {}
|
for (json::const_iterator it = empty_array.cbegin(); it != empty_array.cend(); ++it) {}
|
||||||
|
@ -338,47 +340,47 @@ TEST_CASE("array")
|
||||||
{
|
{
|
||||||
std::vector<int> c_vector {1, 2, 3, 4};
|
std::vector<int> c_vector {1, 2, 3, 4};
|
||||||
json j_vec(c_vector);
|
json j_vec(c_vector);
|
||||||
CHECK(j_vec.type() == json::value_type::array);
|
CHECK(j_vec.type() == json::value_t::array);
|
||||||
CHECK(j_vec.size() == 4);
|
CHECK(j_vec.size() == 4);
|
||||||
|
|
||||||
std::set<std::string> c_set {"one", "two", "three", "four", "one"};
|
std::set<std::string> c_set {"one", "two", "three", "four", "one"};
|
||||||
json j_set(c_set);
|
json j_set(c_set);
|
||||||
CHECK(j_set.type() == json::value_type::array);
|
CHECK(j_set.type() == json::value_t::array);
|
||||||
CHECK(j_set.size() == 4);
|
CHECK(j_set.size() == 4);
|
||||||
|
|
||||||
std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};
|
std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};
|
||||||
json j_uset(c_uset);
|
json j_uset(c_uset);
|
||||||
CHECK(j_uset.type() == json::value_type::array);
|
CHECK(j_uset.type() == json::value_t::array);
|
||||||
CHECK(j_uset.size() == 4);
|
CHECK(j_uset.size() == 4);
|
||||||
|
|
||||||
std::multiset<std::string> c_mset {"one", "two", "one", "four"};
|
std::multiset<std::string> c_mset {"one", "two", "one", "four"};
|
||||||
json j_mset(c_mset);
|
json j_mset(c_mset);
|
||||||
CHECK(j_mset.type() == json::value_type::array);
|
CHECK(j_mset.type() == json::value_t::array);
|
||||||
CHECK(j_mset.size() == 4);
|
CHECK(j_mset.size() == 4);
|
||||||
|
|
||||||
std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
|
std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
|
||||||
json j_umset(c_umset);
|
json j_umset(c_umset);
|
||||||
CHECK(j_umset.type() == json::value_type::array);
|
CHECK(j_umset.type() == json::value_t::array);
|
||||||
CHECK(j_umset.size() == 4);
|
CHECK(j_umset.size() == 4);
|
||||||
|
|
||||||
std::deque<float> c_deque {1.2, 2.3, 3.4, 5.6};
|
std::deque<float> c_deque {1.2, 2.3, 3.4, 5.6};
|
||||||
json j_deque(c_deque);
|
json j_deque(c_deque);
|
||||||
CHECK(j_deque.type() == json::value_type::array);
|
CHECK(j_deque.type() == json::value_t::array);
|
||||||
CHECK(j_deque.size() == 4);
|
CHECK(j_deque.size() == 4);
|
||||||
|
|
||||||
std::list<bool> c_list {true, true, false, true};
|
std::list<bool> c_list {true, true, false, true};
|
||||||
json j_list(c_list);
|
json j_list(c_list);
|
||||||
CHECK(j_list.type() == json::value_type::array);
|
CHECK(j_list.type() == json::value_t::array);
|
||||||
CHECK(j_list.size() == 4);
|
CHECK(j_list.size() == 4);
|
||||||
|
|
||||||
std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543};
|
std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543};
|
||||||
json j_flist(c_flist);
|
json j_flist(c_flist);
|
||||||
CHECK(j_flist.type() == json::value_type::array);
|
CHECK(j_flist.type() == json::value_t::array);
|
||||||
CHECK(j_flist.size() == 4);
|
CHECK(j_flist.size() == 4);
|
||||||
|
|
||||||
std::array<unsigned long, 4> c_array {{1, 2, 3, 4}};
|
std::array<unsigned long, 4> c_array {{1, 2, 3, 4}};
|
||||||
json j_array(c_array);
|
json j_array(c_array);
|
||||||
CHECK(j_array.type() == json::value_type::array);
|
CHECK(j_array.type() == json::value_t::array);
|
||||||
CHECK(j_array.size() == 4);
|
CHECK(j_array.size() == 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,8 +390,8 @@ TEST_CASE("object")
|
||||||
SECTION("Basics")
|
SECTION("Basics")
|
||||||
{
|
{
|
||||||
// construction with given type
|
// construction with given type
|
||||||
json j(json::value_type::object);
|
json j(json::value_t::object);
|
||||||
CHECK(j.type() == json::value_type::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
|
|
||||||
// const object
|
// const object
|
||||||
const json j_const = j;
|
const json j_const = j;
|
||||||
|
@ -403,7 +405,9 @@ TEST_CASE("object")
|
||||||
|
|
||||||
// container members
|
// container members
|
||||||
CHECK(j.size() == 0);
|
CHECK(j.size() == 0);
|
||||||
|
CHECK(j.max_size() > 0);
|
||||||
CHECK(j.empty() == true);
|
CHECK(j.empty() == true);
|
||||||
|
CHECK_NOTHROW(size_t h = std::hash<json>()(j));
|
||||||
|
|
||||||
// implicit conversions
|
// implicit conversions
|
||||||
CHECK_THROWS_AS(json::array_t v = j, std::logic_error);
|
CHECK_THROWS_AS(json::array_t v = j, std::logic_error);
|
||||||
|
@ -604,7 +608,7 @@ TEST_CASE("object")
|
||||||
// implicit transformation into an object
|
// implicit transformation into an object
|
||||||
json empty;
|
json empty;
|
||||||
empty["foo"] = "bar";
|
empty["foo"] = "bar";
|
||||||
CHECK(empty.type() == json::value_type::object);
|
CHECK(empty.type() == json::value_t::object);
|
||||||
CHECK(empty["foo"] == "bar");
|
CHECK(empty["foo"] == "bar");
|
||||||
|
|
||||||
// exceptions
|
// exceptions
|
||||||
|
@ -649,8 +653,8 @@ TEST_CASE("object")
|
||||||
CHECK(false);
|
CHECK(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK((*it).type() == json::value_type::number);
|
CHECK((*it).type() == json::value_t::number);
|
||||||
CHECK(it->type() == json::value_type::number);
|
CHECK(it->type() == json::value_t::number);
|
||||||
}
|
}
|
||||||
|
|
||||||
// range-based for
|
// range-based for
|
||||||
|
@ -680,8 +684,8 @@ TEST_CASE("object")
|
||||||
CHECK(false);
|
CHECK(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK((*it).type() == json::value_type::number);
|
CHECK((*it).type() == json::value_t::number);
|
||||||
CHECK(it->type() == json::value_type::number);
|
CHECK(it->type() == json::value_t::number);
|
||||||
}
|
}
|
||||||
|
|
||||||
// const_iterator using cbegin/cend
|
// const_iterator using cbegin/cend
|
||||||
|
@ -705,8 +709,8 @@ TEST_CASE("object")
|
||||||
CHECK(false);
|
CHECK(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK((*it).type() == json::value_type::number);
|
CHECK((*it).type() == json::value_t::number);
|
||||||
CHECK(it->type() == json::value_type::number);
|
CHECK(it->type() == json::value_t::number);
|
||||||
}
|
}
|
||||||
|
|
||||||
// const_iterator (on const object)
|
// const_iterator (on const object)
|
||||||
|
@ -730,8 +734,8 @@ TEST_CASE("object")
|
||||||
CHECK(false);
|
CHECK(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK((*it).type() == json::value_type::number);
|
CHECK((*it).type() == json::value_t::number);
|
||||||
CHECK(it->type() == json::value_type::number);
|
CHECK(it->type() == json::value_t::number);
|
||||||
}
|
}
|
||||||
|
|
||||||
// const_iterator using cbegin/cend (on const object)
|
// const_iterator using cbegin/cend (on const object)
|
||||||
|
@ -755,8 +759,8 @@ TEST_CASE("object")
|
||||||
CHECK(false);
|
CHECK(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK((*it).type() == json::value_type::number);
|
CHECK((*it).type() == json::value_t::number);
|
||||||
CHECK(it->type() == json::value_type::number);
|
CHECK(it->type() == json::value_t::number);
|
||||||
}
|
}
|
||||||
|
|
||||||
// range-based for (on const object)
|
// range-based for (on const object)
|
||||||
|
@ -768,7 +772,7 @@ TEST_CASE("object")
|
||||||
|
|
||||||
SECTION("Iterators and empty objects")
|
SECTION("Iterators and empty objects")
|
||||||
{
|
{
|
||||||
json empty_object(json::value_type::object);
|
json empty_object(json::value_t::object);
|
||||||
for (json::iterator it = empty_object.begin(); it != empty_object.end(); ++it) {}
|
for (json::iterator it = empty_object.begin(); it != empty_object.end(); ++it) {}
|
||||||
for (json::const_iterator it = empty_object.begin(); it != empty_object.end(); ++it) {}
|
for (json::const_iterator it = empty_object.begin(); it != empty_object.end(); ++it) {}
|
||||||
for (json::const_iterator it = empty_object.cbegin(); it != empty_object.cend(); ++it) {}
|
for (json::const_iterator it = empty_object.cbegin(); it != empty_object.cend(); ++it) {}
|
||||||
|
@ -806,22 +810,22 @@ TEST_CASE("object")
|
||||||
{
|
{
|
||||||
std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };
|
std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };
|
||||||
json j_map(c_map);
|
json j_map(c_map);
|
||||||
CHECK(j_map.type() == json::value_type::object);
|
CHECK(j_map.type() == json::value_t::object);
|
||||||
CHECK(j_map.size() == 3);
|
CHECK(j_map.size() == 3);
|
||||||
|
|
||||||
std::unordered_map<const char*, float> c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} };
|
std::unordered_map<const char*, float> c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} };
|
||||||
json j_umap(c_umap);
|
json j_umap(c_umap);
|
||||||
CHECK(j_umap.type() == json::value_type::object);
|
CHECK(j_umap.type() == json::value_t::object);
|
||||||
CHECK(j_umap.size() == 3);
|
CHECK(j_umap.size() == 3);
|
||||||
|
|
||||||
std::multimap<std::string, bool> c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
|
std::multimap<std::string, bool> c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
|
||||||
json j_mmap(c_mmap);
|
json j_mmap(c_mmap);
|
||||||
CHECK(j_mmap.type() == json::value_type::object);
|
CHECK(j_mmap.type() == json::value_t::object);
|
||||||
CHECK(j_mmap.size() == 3);
|
CHECK(j_mmap.size() == 3);
|
||||||
|
|
||||||
std::unordered_multimap<std::string, bool> c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
|
std::unordered_multimap<std::string, bool> c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
|
||||||
json j_ummap(c_ummap);
|
json j_ummap(c_ummap);
|
||||||
CHECK(j_ummap.type() == json::value_type::object);
|
CHECK(j_ummap.type() == json::value_t::object);
|
||||||
CHECK(j_ummap.size() == 3);
|
CHECK(j_ummap.size() == 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -832,7 +836,7 @@ TEST_CASE("null")
|
||||||
{
|
{
|
||||||
// construction with given type
|
// construction with given type
|
||||||
json j;
|
json j;
|
||||||
CHECK(j.type() == json::value_type::null);
|
CHECK(j.type() == json::value_t::null);
|
||||||
|
|
||||||
// string representation of default value
|
// string representation of default value
|
||||||
CHECK(j.dump() == "null");
|
CHECK(j.dump() == "null");
|
||||||
|
@ -843,7 +847,9 @@ TEST_CASE("null")
|
||||||
|
|
||||||
// container members
|
// container members
|
||||||
CHECK(j.size() == 0);
|
CHECK(j.size() == 0);
|
||||||
|
CHECK(j.max_size() == 0);
|
||||||
CHECK(j.empty() == true);
|
CHECK(j.empty() == true);
|
||||||
|
CHECK_NOTHROW(size_t h = std::hash<json>()(j));
|
||||||
|
|
||||||
// implicit conversions
|
// implicit conversions
|
||||||
CHECK_NOTHROW(json::array_t v = j);
|
CHECK_NOTHROW(json::array_t v = j);
|
||||||
|
@ -878,7 +884,7 @@ TEST_CASE("null")
|
||||||
SECTION("Create from value")
|
SECTION("Create from value")
|
||||||
{
|
{
|
||||||
json j1 = nullptr;
|
json j1 = nullptr;
|
||||||
CHECK(j1.type() == json::value_type::null);
|
CHECK(j1.type() == json::value_t::null);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Operators")
|
SECTION("Operators")
|
||||||
|
@ -911,8 +917,8 @@ TEST_CASE("string")
|
||||||
SECTION("Basics")
|
SECTION("Basics")
|
||||||
{
|
{
|
||||||
// construction with given type
|
// construction with given type
|
||||||
json j(json::value_type::string);
|
json j(json::value_t::string);
|
||||||
CHECK(j.type() == json::value_type::string);
|
CHECK(j.type() == json::value_t::string);
|
||||||
|
|
||||||
// const object
|
// const object
|
||||||
const json j_const = j;
|
const json j_const = j;
|
||||||
|
@ -926,7 +932,9 @@ TEST_CASE("string")
|
||||||
|
|
||||||
// container members
|
// container members
|
||||||
CHECK(j.size() == 1);
|
CHECK(j.size() == 1);
|
||||||
|
CHECK(j.max_size() == 1);
|
||||||
CHECK(j.empty() == false);
|
CHECK(j.empty() == false);
|
||||||
|
CHECK_NOTHROW(size_t h = std::hash<json>()(j));
|
||||||
|
|
||||||
// implicit conversions
|
// implicit conversions
|
||||||
CHECK_NOTHROW(json::array_t v = j);
|
CHECK_NOTHROW(json::array_t v = j);
|
||||||
|
@ -1022,8 +1030,8 @@ TEST_CASE("boolean")
|
||||||
SECTION("Basics")
|
SECTION("Basics")
|
||||||
{
|
{
|
||||||
// construction with given type
|
// construction with given type
|
||||||
json j(json::value_type::boolean);
|
json j(json::value_t::boolean);
|
||||||
CHECK(j.type() == json::value_type::boolean);
|
CHECK(j.type() == json::value_t::boolean);
|
||||||
|
|
||||||
// const object
|
// const object
|
||||||
const json j_const = j;
|
const json j_const = j;
|
||||||
|
@ -1037,7 +1045,9 @@ TEST_CASE("boolean")
|
||||||
|
|
||||||
// container members
|
// container members
|
||||||
CHECK(j.size() == 1);
|
CHECK(j.size() == 1);
|
||||||
|
CHECK(j.max_size() == 1);
|
||||||
CHECK(j.empty() == false);
|
CHECK(j.empty() == false);
|
||||||
|
CHECK_NOTHROW(size_t h = std::hash<json>()(j));
|
||||||
|
|
||||||
// implicit conversions
|
// implicit conversions
|
||||||
CHECK_NOTHROW(json::array_t v = j);
|
CHECK_NOTHROW(json::array_t v = j);
|
||||||
|
@ -1118,8 +1128,8 @@ TEST_CASE("number (int)")
|
||||||
SECTION("Basics")
|
SECTION("Basics")
|
||||||
{
|
{
|
||||||
// construction with given type
|
// construction with given type
|
||||||
json j(json::value_type::number);
|
json j(json::value_t::number);
|
||||||
CHECK(j.type() == json::value_type::number);
|
CHECK(j.type() == json::value_t::number);
|
||||||
|
|
||||||
// const object
|
// const object
|
||||||
const json j_const = j;
|
const json j_const = j;
|
||||||
|
@ -1133,7 +1143,9 @@ TEST_CASE("number (int)")
|
||||||
|
|
||||||
// container members
|
// container members
|
||||||
CHECK(j.size() == 1);
|
CHECK(j.size() == 1);
|
||||||
|
CHECK(j.max_size() == 1);
|
||||||
CHECK(j.empty() == false);
|
CHECK(j.empty() == false);
|
||||||
|
CHECK_NOTHROW(size_t h = std::hash<json>()(j));
|
||||||
|
|
||||||
// implicit conversions
|
// implicit conversions
|
||||||
CHECK_NOTHROW(json::array_t v = j);
|
CHECK_NOTHROW(json::array_t v = j);
|
||||||
|
@ -1229,8 +1241,8 @@ TEST_CASE("number (float)")
|
||||||
SECTION("Basics")
|
SECTION("Basics")
|
||||||
{
|
{
|
||||||
// construction with given type
|
// construction with given type
|
||||||
json j(json::value_type::number_float);
|
json j(json::value_t::number_float);
|
||||||
CHECK(j.type() == json::value_type::number_float);
|
CHECK(j.type() == json::value_t::number_float);
|
||||||
|
|
||||||
// const object
|
// const object
|
||||||
const json j_const = j;
|
const json j_const = j;
|
||||||
|
@ -1244,7 +1256,9 @@ TEST_CASE("number (float)")
|
||||||
|
|
||||||
// container members
|
// container members
|
||||||
CHECK(j.size() == 1);
|
CHECK(j.size() == 1);
|
||||||
|
CHECK(j.max_size() == 1);
|
||||||
CHECK(j.empty() == false);
|
CHECK(j.empty() == false);
|
||||||
|
CHECK_NOTHROW(size_t h = std::hash<json>()(j));
|
||||||
|
|
||||||
// implicit conversions
|
// implicit conversions
|
||||||
CHECK_NOTHROW(json::array_t v = j);
|
CHECK_NOTHROW(json::array_t v = j);
|
||||||
|
@ -1388,35 +1402,35 @@ TEST_CASE("Iterators")
|
||||||
CHECK_THROWS_AS(* j7_const.cend(), std::runtime_error);
|
CHECK_THROWS_AS(* j7_const.cend(), std::runtime_error);
|
||||||
|
|
||||||
// operator ->
|
// operator ->
|
||||||
CHECK(j1.begin()->type() == json::value_type::number);
|
CHECK(j1.begin()->type() == json::value_t::number);
|
||||||
CHECK(j1.cbegin()->type() == json::value_type::number);
|
CHECK(j1.cbegin()->type() == json::value_t::number);
|
||||||
CHECK(j2.begin()->type() == json::value_type::string);
|
CHECK(j2.begin()->type() == json::value_t::string);
|
||||||
CHECK(j2.cbegin()->type() == json::value_type::string);
|
CHECK(j2.cbegin()->type() == json::value_t::string);
|
||||||
CHECK(j3.begin()->type() == json::value_type::boolean);
|
CHECK(j3.begin()->type() == json::value_t::boolean);
|
||||||
CHECK(j3.cbegin()->type() == json::value_type::boolean);
|
CHECK(j3.cbegin()->type() == json::value_t::boolean);
|
||||||
CHECK(j4.begin()->type() == json::value_type::null);
|
CHECK(j4.begin()->type() == json::value_t::null);
|
||||||
CHECK(j4.cbegin()->type() == json::value_type::null);
|
CHECK(j4.cbegin()->type() == json::value_t::null);
|
||||||
CHECK(j5.begin()->type() == json::value_type::number);
|
CHECK(j5.begin()->type() == json::value_t::number);
|
||||||
CHECK(j5.cbegin()->type() == json::value_type::number);
|
CHECK(j5.cbegin()->type() == json::value_t::number);
|
||||||
CHECK(j6.begin()->type() == json::value_type::number_float);
|
CHECK(j6.begin()->type() == json::value_t::number_float);
|
||||||
CHECK(j6.cbegin()->type() == json::value_type::number_float);
|
CHECK(j6.cbegin()->type() == json::value_t::number_float);
|
||||||
CHECK(j7.begin()->type() == json::value_type::string);
|
CHECK(j7.begin()->type() == json::value_t::string);
|
||||||
CHECK(j7.cbegin()->type() == json::value_type::string);
|
CHECK(j7.cbegin()->type() == json::value_t::string);
|
||||||
|
|
||||||
CHECK(j1_const.begin()->type() == json::value_type::number);
|
CHECK(j1_const.begin()->type() == json::value_t::number);
|
||||||
CHECK(j1_const.cbegin()->type() == json::value_type::number);
|
CHECK(j1_const.cbegin()->type() == json::value_t::number);
|
||||||
CHECK(j2_const.begin()->type() == json::value_type::string);
|
CHECK(j2_const.begin()->type() == json::value_t::string);
|
||||||
CHECK(j2_const.cbegin()->type() == json::value_type::string);
|
CHECK(j2_const.cbegin()->type() == json::value_t::string);
|
||||||
CHECK(j3_const.begin()->type() == json::value_type::boolean);
|
CHECK(j3_const.begin()->type() == json::value_t::boolean);
|
||||||
CHECK(j3_const.cbegin()->type() == json::value_type::boolean);
|
CHECK(j3_const.cbegin()->type() == json::value_t::boolean);
|
||||||
CHECK(j4_const.begin()->type() == json::value_type::null);
|
CHECK(j4_const.begin()->type() == json::value_t::null);
|
||||||
CHECK(j4_const.cbegin()->type() == json::value_type::null);
|
CHECK(j4_const.cbegin()->type() == json::value_t::null);
|
||||||
CHECK(j5_const.begin()->type() == json::value_type::number);
|
CHECK(j5_const.begin()->type() == json::value_t::number);
|
||||||
CHECK(j5_const.cbegin()->type() == json::value_type::number);
|
CHECK(j5_const.cbegin()->type() == json::value_t::number);
|
||||||
CHECK(j6_const.begin()->type() == json::value_type::number_float);
|
CHECK(j6_const.begin()->type() == json::value_t::number_float);
|
||||||
CHECK(j6_const.cbegin()->type() == json::value_type::number_float);
|
CHECK(j6_const.cbegin()->type() == json::value_t::number_float);
|
||||||
CHECK(j7_const.begin()->type() == json::value_type::string);
|
CHECK(j7_const.begin()->type() == json::value_t::string);
|
||||||
CHECK(j7_const.cbegin()->type() == json::value_type::string);
|
CHECK(j7_const.cbegin()->type() == json::value_t::string);
|
||||||
|
|
||||||
CHECK_THROWS_AS(j1.end()->type(), std::runtime_error);
|
CHECK_THROWS_AS(j1.end()->type(), std::runtime_error);
|
||||||
CHECK_THROWS_AS(j1.cend()->type(), std::runtime_error);
|
CHECK_THROWS_AS(j1.cend()->type(), std::runtime_error);
|
||||||
|
@ -1449,35 +1463,35 @@ TEST_CASE("Iterators")
|
||||||
CHECK_THROWS_AS(j7_const.cend()->type(), std::runtime_error);
|
CHECK_THROWS_AS(j7_const.cend()->type(), std::runtime_error);
|
||||||
|
|
||||||
// value
|
// value
|
||||||
CHECK(j1.begin().value().type() == json::value_type::number);
|
CHECK(j1.begin().value().type() == json::value_t::number);
|
||||||
CHECK(j1.cbegin().value().type() == json::value_type::number);
|
CHECK(j1.cbegin().value().type() == json::value_t::number);
|
||||||
CHECK(j2.begin().value().type() == json::value_type::string);
|
CHECK(j2.begin().value().type() == json::value_t::string);
|
||||||
CHECK(j2.cbegin().value().type() == json::value_type::string);
|
CHECK(j2.cbegin().value().type() == json::value_t::string);
|
||||||
CHECK(j3.begin().value().type() == json::value_type::boolean);
|
CHECK(j3.begin().value().type() == json::value_t::boolean);
|
||||||
CHECK(j3.cbegin().value().type() == json::value_type::boolean);
|
CHECK(j3.cbegin().value().type() == json::value_t::boolean);
|
||||||
CHECK(j4.begin().value().type() == json::value_type::null);
|
CHECK(j4.begin().value().type() == json::value_t::null);
|
||||||
CHECK(j4.cbegin().value().type() == json::value_type::null);
|
CHECK(j4.cbegin().value().type() == json::value_t::null);
|
||||||
CHECK(j5.begin().value().type() == json::value_type::number);
|
CHECK(j5.begin().value().type() == json::value_t::number);
|
||||||
CHECK(j5.cbegin().value().type() == json::value_type::number);
|
CHECK(j5.cbegin().value().type() == json::value_t::number);
|
||||||
CHECK(j6.begin().value().type() == json::value_type::number_float);
|
CHECK(j6.begin().value().type() == json::value_t::number_float);
|
||||||
CHECK(j6.cbegin().value().type() == json::value_type::number_float);
|
CHECK(j6.cbegin().value().type() == json::value_t::number_float);
|
||||||
CHECK(j7.begin().value().type() == json::value_type::string);
|
CHECK(j7.begin().value().type() == json::value_t::string);
|
||||||
CHECK(j7.cbegin().value().type() == json::value_type::string);
|
CHECK(j7.cbegin().value().type() == json::value_t::string);
|
||||||
|
|
||||||
CHECK(j1_const.begin().value().type() == json::value_type::number);
|
CHECK(j1_const.begin().value().type() == json::value_t::number);
|
||||||
CHECK(j1_const.cbegin().value().type() == json::value_type::number);
|
CHECK(j1_const.cbegin().value().type() == json::value_t::number);
|
||||||
CHECK(j2_const.begin().value().type() == json::value_type::string);
|
CHECK(j2_const.begin().value().type() == json::value_t::string);
|
||||||
CHECK(j2_const.cbegin().value().type() == json::value_type::string);
|
CHECK(j2_const.cbegin().value().type() == json::value_t::string);
|
||||||
CHECK(j3_const.begin().value().type() == json::value_type::boolean);
|
CHECK(j3_const.begin().value().type() == json::value_t::boolean);
|
||||||
CHECK(j3_const.cbegin().value().type() == json::value_type::boolean);
|
CHECK(j3_const.cbegin().value().type() == json::value_t::boolean);
|
||||||
CHECK(j4_const.begin().value().type() == json::value_type::null);
|
CHECK(j4_const.begin().value().type() == json::value_t::null);
|
||||||
CHECK(j4_const.cbegin().value().type() == json::value_type::null);
|
CHECK(j4_const.cbegin().value().type() == json::value_t::null);
|
||||||
CHECK(j5_const.begin().value().type() == json::value_type::number);
|
CHECK(j5_const.begin().value().type() == json::value_t::number);
|
||||||
CHECK(j5_const.cbegin().value().type() == json::value_type::number);
|
CHECK(j5_const.cbegin().value().type() == json::value_t::number);
|
||||||
CHECK(j6_const.begin().value().type() == json::value_type::number_float);
|
CHECK(j6_const.begin().value().type() == json::value_t::number_float);
|
||||||
CHECK(j6_const.cbegin().value().type() == json::value_type::number_float);
|
CHECK(j6_const.cbegin().value().type() == json::value_t::number_float);
|
||||||
CHECK(j7_const.begin().value().type() == json::value_type::string);
|
CHECK(j7_const.begin().value().type() == json::value_t::string);
|
||||||
CHECK(j7_const.cbegin().value().type() == json::value_type::string);
|
CHECK(j7_const.cbegin().value().type() == json::value_t::string);
|
||||||
|
|
||||||
CHECK_THROWS_AS(j1.end().value(), std::out_of_range);
|
CHECK_THROWS_AS(j1.end().value(), std::out_of_range);
|
||||||
CHECK_THROWS_AS(j1.cend().value(), std::out_of_range);
|
CHECK_THROWS_AS(j1.cend().value(), std::out_of_range);
|
||||||
|
|
Loading…
Reference in a new issue