worked on #91
- implemented `get_ptr` function to return pointer to value member - overworked `get` function to support pointer types - added test cases - added documentation (see http://nlohmann.github.io/json/classnlohmann_1_1basic__json.html) with examples
This commit is contained in:
parent
457572184c
commit
40312fb07b
11 changed files with 698 additions and 18 deletions
20
doc/examples/get__PointerType.cpp
Normal file
20
doc/examples/get__PointerType.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
|
using namespace nlohmann;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// create a JSON boolean
|
||||||
|
json value = 17;
|
||||||
|
|
||||||
|
// explicitly getting pointers
|
||||||
|
auto p1 = value.get<const json::number_integer_t*>();
|
||||||
|
auto p2 = value.get<json::number_integer_t*>();
|
||||||
|
auto p3 = value.get<json::number_integer_t* const>();
|
||||||
|
auto p4 = value.get<const json::number_integer_t* const>();
|
||||||
|
auto p5 = value.get<json::number_float_t*>();
|
||||||
|
|
||||||
|
// print the pointees
|
||||||
|
std::cout << *p1 << ' ' << *p2 << ' ' << *p3 << ' ' << *p4 << '\n';
|
||||||
|
std::cout << std::boolalpha << (p5 == nullptr) << '\n';
|
||||||
|
}
|
2
doc/examples/get__PointerType.output
Normal file
2
doc/examples/get__PointerType.output
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
17 17 17 17
|
||||||
|
true
|
49
doc/examples/get__ValueType_const.cpp
Normal file
49
doc/examples/get__ValueType_const.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include <json.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
using namespace nlohmann;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// create a JSON value with different types
|
||||||
|
json json_types =
|
||||||
|
{
|
||||||
|
{"boolean", true},
|
||||||
|
{
|
||||||
|
"number", {
|
||||||
|
{"integer", 42},
|
||||||
|
{"floating-point", 17.23}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{"string", "Hello, world!"},
|
||||||
|
{"array", {1, 2, 3, 4, 5}},
|
||||||
|
{"null", nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
// use explicit conversions
|
||||||
|
auto v1 = json_types["boolean"].get<bool>();
|
||||||
|
auto v2 = json_types["number"]["integer"].get<int>();
|
||||||
|
auto v3 = json_types["number"]["integer"].get<short>();
|
||||||
|
auto v4 = json_types["number"]["floating-point"].get<float>();
|
||||||
|
auto v5 = json_types["number"]["floating-point"].get<int>();
|
||||||
|
auto v6 = json_types["string"].get<std::string>();
|
||||||
|
auto v7 = json_types["array"].get<std::vector<short>>();
|
||||||
|
auto v8 = json_types.get<std::unordered_map<std::string, json>>();
|
||||||
|
|
||||||
|
// print the conversion results
|
||||||
|
std::cout << v1 << '\n';
|
||||||
|
std::cout << v2 << ' ' << v3 << '\n';
|
||||||
|
std::cout << v4 << ' ' << v5 << '\n';
|
||||||
|
std::cout << v6 << '\n';
|
||||||
|
|
||||||
|
for (auto i : v7)
|
||||||
|
{
|
||||||
|
std::cout << i << ' ';
|
||||||
|
}
|
||||||
|
std::cout << "\n\n";
|
||||||
|
|
||||||
|
for (auto i : v8)
|
||||||
|
{
|
||||||
|
std::cout << i.first << ": " << i.second << '\n';
|
||||||
|
}
|
||||||
|
}
|
11
doc/examples/get__ValueType_const.output
Normal file
11
doc/examples/get__ValueType_const.output
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
1
|
||||||
|
42 42
|
||||||
|
17.23 17
|
||||||
|
Hello, world!
|
||||||
|
1 2 3 4 5
|
||||||
|
|
||||||
|
string: "Hello, world!"
|
||||||
|
number: {"floating-point":17.23,"integer":42}
|
||||||
|
null: null
|
||||||
|
boolean: true
|
||||||
|
array: [1,2,3,4,5]
|
20
doc/examples/get_ptr.cpp
Normal file
20
doc/examples/get_ptr.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
|
using namespace nlohmann;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// create a JSON boolean
|
||||||
|
json value = 17;
|
||||||
|
|
||||||
|
// explicitly getting pointers
|
||||||
|
auto p1 = value.get_ptr<const json::number_integer_t*>();
|
||||||
|
auto p2 = value.get_ptr<json::number_integer_t*>();
|
||||||
|
auto p3 = value.get_ptr<json::number_integer_t* const>();
|
||||||
|
auto p4 = value.get_ptr<const json::number_integer_t* const>();
|
||||||
|
auto p5 = value.get_ptr<json::number_float_t*>();
|
||||||
|
|
||||||
|
// print the pointees
|
||||||
|
std::cout << *p1 << ' ' << *p2 << ' ' << *p3 << ' ' << *p4 << '\n';
|
||||||
|
std::cout << std::boolalpha << (p5 == nullptr) << '\n';
|
||||||
|
}
|
2
doc/examples/get_ptr.output
Normal file
2
doc/examples/get_ptr.output
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
17 17 17 17
|
||||||
|
true
|
49
doc/examples/operator__ValueType.cpp
Normal file
49
doc/examples/operator__ValueType.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include <json.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
using namespace nlohmann;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// create a JSON value with different types
|
||||||
|
json json_types =
|
||||||
|
{
|
||||||
|
{"boolean", true},
|
||||||
|
{
|
||||||
|
"number", {
|
||||||
|
{"integer", 42},
|
||||||
|
{"floating-point", 17.23}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{"string", "Hello, world!"},
|
||||||
|
{"array", {1, 2, 3, 4, 5}},
|
||||||
|
{"null", nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
// use implicit conversions
|
||||||
|
bool v1 = json_types["boolean"];
|
||||||
|
int v2 = json_types["number"]["integer"];
|
||||||
|
short v3 = json_types["number"]["integer"];
|
||||||
|
float v4 = json_types["number"]["floating-point"];
|
||||||
|
int v5 = json_types["number"]["floating-point"];
|
||||||
|
std::string v6 = json_types["string"];
|
||||||
|
std::vector<short> v7 = json_types["array"];
|
||||||
|
std::unordered_map<std::string, json> v8 = json_types;
|
||||||
|
|
||||||
|
// print the conversion results
|
||||||
|
std::cout << v1 << '\n';
|
||||||
|
std::cout << v2 << ' ' << v3 << '\n';
|
||||||
|
std::cout << v4 << ' ' << v5 << '\n';
|
||||||
|
std::cout << v6 << '\n';
|
||||||
|
|
||||||
|
for (auto i : v7)
|
||||||
|
{
|
||||||
|
std::cout << i << ' ';
|
||||||
|
}
|
||||||
|
std::cout << "\n\n";
|
||||||
|
|
||||||
|
for (auto i : v8)
|
||||||
|
{
|
||||||
|
std::cout << i.first << ": " << i.second << '\n';
|
||||||
|
}
|
||||||
|
}
|
11
doc/examples/operator__ValueType.output
Normal file
11
doc/examples/operator__ValueType.output
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
1
|
||||||
|
42 42
|
||||||
|
17.23 17
|
||||||
|
Hello, world!
|
||||||
|
1 2 3 4 5
|
||||||
|
|
||||||
|
string: "Hello, world!"
|
||||||
|
number: {"floating-point":17.23,"integer":42}
|
||||||
|
null: null
|
||||||
|
boolean: true
|
||||||
|
array: [1,2,3,4,5]
|
186
src/json.hpp
186
src/json.hpp
|
@ -1787,24 +1787,192 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (object)
|
||||||
|
const object_t* get_impl_ptr(object_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_object() ? m_value.object : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (array)
|
||||||
|
const array_t* get_impl_ptr(array_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_array() ? m_value.array : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (string)
|
||||||
|
const string_t* get_impl_ptr(string_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_string() ? m_value.string : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (boolean)
|
||||||
|
const boolean_t* get_impl_ptr(boolean_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_boolean() ? &m_value.boolean : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (integer number)
|
||||||
|
const number_integer_t* get_impl_ptr(number_integer_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_number_integer() ? &m_value.number_integer : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (floating-point number)
|
||||||
|
const number_float_t* get_impl_ptr(number_float_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_number_float() ? &m_value.number_float : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// @name value access
|
/// @name value access
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
/// get a value (explicit)
|
/*!
|
||||||
// <http://stackoverflow.com/a/8315197/266378>
|
@brief get a value (explicit)
|
||||||
template<typename T>
|
|
||||||
T get() const
|
Explicit type conversion between the JSON value and a compatible value.
|
||||||
|
|
||||||
|
@tparam ValueType non-pointer type compatible to the JSON value, for
|
||||||
|
instance `int` for JSON integer numbers, `bool` for JSON booleans, or
|
||||||
|
`std::vector` types for JSON arrays
|
||||||
|
|
||||||
|
@return copy of the JSON value, converted to type @a ValueType
|
||||||
|
|
||||||
|
@throw std::domain_error in case passed type @a ValueType is incompatible
|
||||||
|
to JSON
|
||||||
|
|
||||||
|
@complexity Linear in the size of the JSON value.
|
||||||
|
|
||||||
|
@liveexample{The example below shows serveral conversions from JSON values
|
||||||
|
to other types. There a few things to note: (1) Floating-point numbers can
|
||||||
|
be converted to integers\, (2) A JSON array can be converted to a standard
|
||||||
|
`std::vector<short>`\, (3) A JSON object can be converted to C++
|
||||||
|
assiciative containers such as `std::unordered_map<std::string\,
|
||||||
|
json>`.,get__ValueType_const}
|
||||||
|
|
||||||
|
@internal
|
||||||
|
The idea of using a casted null pointer to choose the correct
|
||||||
|
implementation is from <http://stackoverflow.com/a/8315197/266378>.
|
||||||
|
@endinternal
|
||||||
|
|
||||||
|
@sa @ref operator ValueType() const for implicit conversion
|
||||||
|
@sa @ref get() for pointer-member access
|
||||||
|
*/
|
||||||
|
template<typename ValueType, typename
|
||||||
|
std::enable_if<
|
||||||
|
not std::is_pointer<ValueType>::value
|
||||||
|
, int>::type = 0>
|
||||||
|
ValueType get() const
|
||||||
{
|
{
|
||||||
return get_impl(static_cast<T*>(nullptr));
|
return get_impl(static_cast<ValueType*>(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get a value (implicit)
|
/*!
|
||||||
template<typename T>
|
@brief get a pointer value (explicit)
|
||||||
operator T() const
|
|
||||||
|
Explicit pointer access to the internally stored JSON value. No copies are
|
||||||
|
made.
|
||||||
|
|
||||||
|
@warning Writing data to the pointee of the result yields an undefined
|
||||||
|
state.
|
||||||
|
|
||||||
|
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
|
||||||
|
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
|
||||||
|
number_float_t.
|
||||||
|
|
||||||
|
@return pointer to the internally stored JSON value if the requested pointer
|
||||||
|
type @a PointerType fits to the JSON value; `nullptr` otherwise
|
||||||
|
|
||||||
|
@complexity Constant.
|
||||||
|
|
||||||
|
@liveexample{The example below shows how pointers to internal values of a
|
||||||
|
JSON value can be requested. Note that no type conversions are made and a
|
||||||
|
`nullptr` is returned if the value and the requested pointer type does not
|
||||||
|
match.,get__PointerType}
|
||||||
|
|
||||||
|
@sa @ref get_ptr() for explicit pointer-member access
|
||||||
|
*/
|
||||||
|
template<typename PointerType, typename
|
||||||
|
std::enable_if<
|
||||||
|
std::is_pointer<PointerType>::value
|
||||||
|
, int>::type = 0>
|
||||||
|
PointerType get() const noexcept
|
||||||
{
|
{
|
||||||
return get<T>();
|
// delegate the call to get_ptr
|
||||||
|
return get_ptr<PointerType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief get a pointer value (implicit)
|
||||||
|
|
||||||
|
Implict pointer access to the internally stored JSON value. No copies are
|
||||||
|
made.
|
||||||
|
|
||||||
|
@warning Writing data to the pointee of the result yields an undefined
|
||||||
|
state.
|
||||||
|
|
||||||
|
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
|
||||||
|
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
|
||||||
|
number_float_t.
|
||||||
|
|
||||||
|
@return pointer to the internally stored JSON value if the requested pointer
|
||||||
|
type @a PointerType fits to the JSON value; `nullptr` otherwise
|
||||||
|
|
||||||
|
@complexity Constant.
|
||||||
|
|
||||||
|
@liveexample{The example below shows how pointers to internal values of a
|
||||||
|
JSON value can be requested. Note that no type conversions are made and a
|
||||||
|
`nullptr` is returned if the value and the requested pointer type does not
|
||||||
|
match.,get_ptr}
|
||||||
|
*/
|
||||||
|
template<typename PointerType, typename
|
||||||
|
std::enable_if<
|
||||||
|
std::is_pointer<PointerType>::value
|
||||||
|
, int>::type = 0>
|
||||||
|
PointerType get_ptr() const noexcept
|
||||||
|
{
|
||||||
|
// get_impl_ptr will only work with non-const and non-volatile pointer
|
||||||
|
// types. Therefore, we case away all cv properties to be able to
|
||||||
|
// select the correct function. The cv properties will then be added
|
||||||
|
// again by the const const cast to PointerType.
|
||||||
|
return const_cast<PointerType>(get_impl_ptr(
|
||||||
|
static_cast<typename std::add_pointer<typename std::remove_cv<typename std::remove_pointer<PointerType>::type>::type>::type>
|
||||||
|
(nullptr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief get a value (implicit)
|
||||||
|
|
||||||
|
Implict type conversion between the JSON value and a compatible value. The
|
||||||
|
call is realized by calling @ref get() const.
|
||||||
|
|
||||||
|
@tparam ValueType non-pointer type compatible to the JSON value, for
|
||||||
|
instance `int` for JSON integer numbers, `bool` for JSON booleans, or
|
||||||
|
`std::vector` types for JSON arrays
|
||||||
|
|
||||||
|
@return copy of the JSON value, converted to type @a ValueType
|
||||||
|
|
||||||
|
@throw std::domain_error in case passed type @a ValueType is incompatible
|
||||||
|
to JSON, thrown by @ref get() const
|
||||||
|
|
||||||
|
@complexity Linear in the size of the JSON value.
|
||||||
|
|
||||||
|
@liveexample{The example below shows serveral conversions from JSON values
|
||||||
|
to other types. There a few things to note: (1) Floating-point numbers can
|
||||||
|
be converted to integers\, (2) A JSON array can be converted to a standard
|
||||||
|
`std::vector<short>`\, (3) A JSON object can be converted to C++
|
||||||
|
assiciative containers such as `std::unordered_map<std::string\,
|
||||||
|
json>`.,operator__ValueType}
|
||||||
|
*/
|
||||||
|
template<typename ValueType, typename
|
||||||
|
std::enable_if<
|
||||||
|
not std::is_pointer<ValueType>::value
|
||||||
|
, int>::type = 0>
|
||||||
|
operator ValueType() const
|
||||||
|
{
|
||||||
|
// delegate the call to get<>() const
|
||||||
|
return get<ValueType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
@ -1787,24 +1787,192 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (object)
|
||||||
|
const object_t* get_impl_ptr(object_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_object() ? m_value.object : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (array)
|
||||||
|
const array_t* get_impl_ptr(array_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_array() ? m_value.array : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (string)
|
||||||
|
const string_t* get_impl_ptr(string_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_string() ? m_value.string : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (boolean)
|
||||||
|
const boolean_t* get_impl_ptr(boolean_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_boolean() ? &m_value.boolean : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (integer number)
|
||||||
|
const number_integer_t* get_impl_ptr(number_integer_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_number_integer() ? &m_value.number_integer : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get a pointer to the value (floating-point number)
|
||||||
|
const number_float_t* get_impl_ptr(number_float_t*) const noexcept
|
||||||
|
{
|
||||||
|
return is_number_float() ? &m_value.number_float : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// @name value access
|
/// @name value access
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
/// get a value (explicit)
|
/*!
|
||||||
// <http://stackoverflow.com/a/8315197/266378>
|
@brief get a value (explicit)
|
||||||
template<typename T>
|
|
||||||
T get() const
|
Explicit type conversion between the JSON value and a compatible value.
|
||||||
|
|
||||||
|
@tparam ValueType non-pointer type compatible to the JSON value, for
|
||||||
|
instance `int` for JSON integer numbers, `bool` for JSON booleans, or
|
||||||
|
`std::vector` types for JSON arrays
|
||||||
|
|
||||||
|
@return copy of the JSON value, converted to type @a ValueType
|
||||||
|
|
||||||
|
@throw std::domain_error in case passed type @a ValueType is incompatible
|
||||||
|
to JSON
|
||||||
|
|
||||||
|
@complexity Linear in the size of the JSON value.
|
||||||
|
|
||||||
|
@liveexample{The example below shows serveral conversions from JSON values
|
||||||
|
to other types. There a few things to note: (1) Floating-point numbers can
|
||||||
|
be converted to integers\, (2) A JSON array can be converted to a standard
|
||||||
|
`std::vector<short>`\, (3) A JSON object can be converted to C++
|
||||||
|
assiciative containers such as `std::unordered_map<std::string\,
|
||||||
|
json>`.,get__ValueType_const}
|
||||||
|
|
||||||
|
@internal
|
||||||
|
The idea of using a casted null pointer to choose the correct
|
||||||
|
implementation is from <http://stackoverflow.com/a/8315197/266378>.
|
||||||
|
@endinternal
|
||||||
|
|
||||||
|
@sa @ref operator ValueType() const for implicit conversion
|
||||||
|
@sa @ref get() for pointer-member access
|
||||||
|
*/
|
||||||
|
template<typename ValueType, typename
|
||||||
|
std::enable_if<
|
||||||
|
not std::is_pointer<ValueType>::value
|
||||||
|
, int>::type = 0>
|
||||||
|
ValueType get() const
|
||||||
{
|
{
|
||||||
return get_impl(static_cast<T*>(nullptr));
|
return get_impl(static_cast<ValueType*>(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get a value (implicit)
|
/*!
|
||||||
template<typename T>
|
@brief get a pointer value (explicit)
|
||||||
operator T() const
|
|
||||||
|
Explicit pointer access to the internally stored JSON value. No copies are
|
||||||
|
made.
|
||||||
|
|
||||||
|
@warning Writing data to the pointee of the result yields an undefined
|
||||||
|
state.
|
||||||
|
|
||||||
|
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
|
||||||
|
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
|
||||||
|
number_float_t.
|
||||||
|
|
||||||
|
@return pointer to the internally stored JSON value if the requested pointer
|
||||||
|
type @a PointerType fits to the JSON value; `nullptr` otherwise
|
||||||
|
|
||||||
|
@complexity Constant.
|
||||||
|
|
||||||
|
@liveexample{The example below shows how pointers to internal values of a
|
||||||
|
JSON value can be requested. Note that no type conversions are made and a
|
||||||
|
`nullptr` is returned if the value and the requested pointer type does not
|
||||||
|
match.,get__PointerType}
|
||||||
|
|
||||||
|
@sa @ref get_ptr() for explicit pointer-member access
|
||||||
|
*/
|
||||||
|
template<typename PointerType, typename
|
||||||
|
std::enable_if<
|
||||||
|
std::is_pointer<PointerType>::value
|
||||||
|
, int>::type = 0>
|
||||||
|
PointerType get() const noexcept
|
||||||
{
|
{
|
||||||
return get<T>();
|
// delegate the call to get_ptr
|
||||||
|
return get_ptr<PointerType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief get a pointer value (implicit)
|
||||||
|
|
||||||
|
Implict pointer access to the internally stored JSON value. No copies are
|
||||||
|
made.
|
||||||
|
|
||||||
|
@warning Writing data to the pointee of the result yields an undefined
|
||||||
|
state.
|
||||||
|
|
||||||
|
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
|
||||||
|
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
|
||||||
|
number_float_t.
|
||||||
|
|
||||||
|
@return pointer to the internally stored JSON value if the requested pointer
|
||||||
|
type @a PointerType fits to the JSON value; `nullptr` otherwise
|
||||||
|
|
||||||
|
@complexity Constant.
|
||||||
|
|
||||||
|
@liveexample{The example below shows how pointers to internal values of a
|
||||||
|
JSON value can be requested. Note that no type conversions are made and a
|
||||||
|
`nullptr` is returned if the value and the requested pointer type does not
|
||||||
|
match.,get_ptr}
|
||||||
|
*/
|
||||||
|
template<typename PointerType, typename
|
||||||
|
std::enable_if<
|
||||||
|
std::is_pointer<PointerType>::value
|
||||||
|
, int>::type = 0>
|
||||||
|
PointerType get_ptr() const noexcept
|
||||||
|
{
|
||||||
|
// get_impl_ptr will only work with non-const and non-volatile pointer
|
||||||
|
// types. Therefore, we case away all cv properties to be able to
|
||||||
|
// select the correct function. The cv properties will then be added
|
||||||
|
// again by the const const cast to PointerType.
|
||||||
|
return const_cast<PointerType>(get_impl_ptr(
|
||||||
|
static_cast<typename std::add_pointer<typename std::remove_cv<typename std::remove_pointer<PointerType>::type>::type>::type>
|
||||||
|
(nullptr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief get a value (implicit)
|
||||||
|
|
||||||
|
Implict type conversion between the JSON value and a compatible value. The
|
||||||
|
call is realized by calling @ref get() const.
|
||||||
|
|
||||||
|
@tparam ValueType non-pointer type compatible to the JSON value, for
|
||||||
|
instance `int` for JSON integer numbers, `bool` for JSON booleans, or
|
||||||
|
`std::vector` types for JSON arrays
|
||||||
|
|
||||||
|
@return copy of the JSON value, converted to type @a ValueType
|
||||||
|
|
||||||
|
@throw std::domain_error in case passed type @a ValueType is incompatible
|
||||||
|
to JSON, thrown by @ref get() const
|
||||||
|
|
||||||
|
@complexity Linear in the size of the JSON value.
|
||||||
|
|
||||||
|
@liveexample{The example below shows serveral conversions from JSON values
|
||||||
|
to other types. There a few things to note: (1) Floating-point numbers can
|
||||||
|
be converted to integers\, (2) A JSON array can be converted to a standard
|
||||||
|
`std::vector<short>`\, (3) A JSON object can be converted to C++
|
||||||
|
assiciative containers such as `std::unordered_map<std::string\,
|
||||||
|
json>`.,operator__ValueType}
|
||||||
|
*/
|
||||||
|
template<typename ValueType, typename
|
||||||
|
std::enable_if<
|
||||||
|
not std::is_pointer<ValueType>::value
|
||||||
|
, int>::type = 0>
|
||||||
|
operator ValueType() const
|
||||||
|
{
|
||||||
|
// delegate the call to get<>() const
|
||||||
|
return get<ValueType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
180
test/unit.cpp
180
test/unit.cpp
|
@ -2434,6 +2434,186 @@ TEST_CASE("value conversion")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("pointer access")
|
||||||
|
{
|
||||||
|
// create a JSON value with different types
|
||||||
|
json json_types =
|
||||||
|
{
|
||||||
|
{"boolean", true},
|
||||||
|
{
|
||||||
|
"number", {
|
||||||
|
{"integer", 42},
|
||||||
|
{"floating-point", 17.23}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{"string", "Hello, world!"},
|
||||||
|
{"array", {1, 2, 3, 4, 5}},
|
||||||
|
{"null", nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
SECTION("pointer access to object_t")
|
||||||
|
{
|
||||||
|
using test_type = json::object_t;
|
||||||
|
json value = {{"one", 1}, {"two", 2}};
|
||||||
|
|
||||||
|
// check if pointers are returned correctly
|
||||||
|
test_type* p1 = value.get_ptr<test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<test_type*>());
|
||||||
|
CHECK(*p1 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||||
|
CHECK(*p2 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||||
|
CHECK(*p3 == value.get<test_type>());
|
||||||
|
|
||||||
|
// check if null pointers are returned correctly
|
||||||
|
CHECK(value.get_ptr<json::object_t*>() != nullptr);
|
||||||
|
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("pointer access to array_t")
|
||||||
|
{
|
||||||
|
using test_type = json::array_t;
|
||||||
|
json value = {1, 2, 3, 4};
|
||||||
|
|
||||||
|
// check if pointers are returned correctly
|
||||||
|
test_type* p1 = value.get_ptr<test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<test_type*>());
|
||||||
|
CHECK(*p1 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||||
|
CHECK(*p2 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||||
|
CHECK(*p3 == value.get<test_type>());
|
||||||
|
|
||||||
|
// check if null pointers are returned correctly
|
||||||
|
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::array_t*>() != nullptr);
|
||||||
|
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("pointer access to string_t")
|
||||||
|
{
|
||||||
|
using test_type = json::string_t;
|
||||||
|
json value = "hello";
|
||||||
|
|
||||||
|
// check if pointers are returned correctly
|
||||||
|
test_type* p1 = value.get_ptr<test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<test_type*>());
|
||||||
|
CHECK(*p1 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||||
|
CHECK(*p2 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||||
|
CHECK(*p3 == value.get<test_type>());
|
||||||
|
|
||||||
|
// check if null pointers are returned correctly
|
||||||
|
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::string_t*>() != nullptr);
|
||||||
|
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("pointer access to boolean_t")
|
||||||
|
{
|
||||||
|
using test_type = json::boolean_t;
|
||||||
|
json value = false;
|
||||||
|
|
||||||
|
// check if pointers are returned correctly
|
||||||
|
test_type* p1 = value.get_ptr<test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<test_type*>());
|
||||||
|
CHECK(*p1 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||||
|
CHECK(*p2 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||||
|
CHECK(*p3 == value.get<test_type>());
|
||||||
|
|
||||||
|
// check if null pointers are returned correctly
|
||||||
|
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::boolean_t*>() != nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("pointer access to number_integer_t")
|
||||||
|
{
|
||||||
|
using test_type = json::number_integer_t;
|
||||||
|
json value = 23;
|
||||||
|
|
||||||
|
// check if pointers are returned correctly
|
||||||
|
test_type* p1 = value.get_ptr<test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<test_type*>());
|
||||||
|
CHECK(*p1 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||||
|
CHECK(*p2 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||||
|
CHECK(*p3 == value.get<test_type>());
|
||||||
|
|
||||||
|
// check if null pointers are returned correctly
|
||||||
|
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_integer_t*>() != nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("pointer access to number_float_t")
|
||||||
|
{
|
||||||
|
using test_type = json::number_float_t;
|
||||||
|
json value = 42.23;
|
||||||
|
|
||||||
|
// check if pointers are returned correctly
|
||||||
|
test_type* p1 = value.get_ptr<test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<test_type*>());
|
||||||
|
CHECK(*p1 == Approx(value.get<test_type>()));
|
||||||
|
|
||||||
|
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type*>());
|
||||||
|
CHECK(*p2 == Approx(value.get<test_type>()));
|
||||||
|
|
||||||
|
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||||
|
CHECK(p1 == value.get_ptr<const test_type* const>());
|
||||||
|
CHECK(*p3 == Approx(value.get<test_type>()));
|
||||||
|
|
||||||
|
// check if null pointers are returned correctly
|
||||||
|
CHECK(value.get_ptr<json::object_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::array_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::string_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<json::number_float_t*>() != nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("element access")
|
TEST_CASE("element access")
|
||||||
{
|
{
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
|
|
Loading…
Reference in a new issue