Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
json
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
json
Commits
250e5bf4
Commit
250e5bf4
authored
Jan 24, 2017
by
Niels Lohmann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
💄
overworked documentation and indentation
parent
030cf674
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
486 additions
and
436 deletions
+486
-436
src/json.hpp
src/json.hpp
+243
-218
src/json.hpp.re2c
src/json.hpp.re2c
+243
-218
No files found.
src/json.hpp
View file @
250e5bf4
...
@@ -107,12 +107,15 @@ SOFTWARE.
...
@@ -107,12 +107,15 @@ SOFTWARE.
*/
*/
namespace
nlohmann
namespace
nlohmann
{
{
// TODO update this doc
/*!
/*!
@brief unnamed namespace with internal helper functions
@brief unnamed namespace with internal helper functions
@since version 1.0.0
*/
This namespace collects some functions that could not be defined inside the
@ref basic_json class.
@since version 2.1.0
*/
namespace
detail
namespace
detail
{
{
///////////////////////////
///////////////////////////
...
@@ -122,22 +125,24 @@ namespace detail
...
@@ -122,22 +125,24 @@ namespace detail
/*!
/*!
@brief the JSON type enumeration
@brief the JSON type enumeration
This enumeration collects the different JSON types. It is internally used
This enumeration collects the different JSON types. It is internally used to
to distinguish the stored values, and the functions @ref basic_json::is_null(), @ref
distinguish the stored values, and the functions @ref basic_json::is_null(),
basic_json::is_object(), @ref basic_json::is_array(), @ref basic_json::is_string(), @ref basic_json::is_boolean(), @ref
@ref basic_json::is_object(), @ref basic_json::is_array(),
basic_json::is_number() (with @ref basic_json::is_number_integer(), @ref basic_json::is_number_unsigned(), and
@ref basic_json::is_string(), @ref basic_json::is_boolean(),
@ref basic_json::is_number_float()), @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
@ref basic_json::is_structured() rely on it.
@ref basic_json::is_structured() rely on it.
@note There are three enumeration entries (number_integer,
@note There are three enumeration entries (number_integer,
number_unsigned, and
number_
unsigned, and number_float), because the library distinguishes
number_
float), because the library distinguishes these three types for numbers:
these three types for numbers: @ref basic_json::number_unsigned_t is used for unsigned
@ref basic_json::number_unsigned_t is used for unsigned integers,
integers, @ref basic_json::number_integer_t is used for signed integers, and @ref
@ref basic_json::number_integer_t is used for signed integers, and
basic_json::number_float_t is used for floating-point numbers or to approximate
@ref basic_json::number_float_t is used for floating-point numbers or to
integers which do not fit in the limits of their respective type.
approximate
integers which do not fit in the limits of their respective type.
@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
value with
@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
the default value for a given type
value with
the default value for a given type
@since version 1.0.0
@since version 1.0.0
*/
*/
...
@@ -154,12 +159,6 @@ enum class value_t : uint8_t
...
@@ -154,12 +159,6 @@ enum class value_t : uint8_t
discarded
///< discarded by the the parser callback function
discarded
///< discarded by the the parser callback function
};
};
//////////////////////////////////////////
// lexicographical comparison operators //
//////////////////////////////////////////
/// @name lexicographical comparison operators
/// @{
/*!
/*!
@brief comparison operator for JSON types
@brief comparison operator for JSON types
...
@@ -193,51 +192,62 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
...
@@ -193,51 +192,62 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
order
[
static_cast
<
std
::
size_t
>
(
rhs
)];
order
[
static_cast
<
std
::
size_t
>
(
rhs
)];
}
}
/////////////
// helpers //
/////////////
// alias templates to reduce boilerplate
// alias templates to reduce boilerplate
template
<
bool
B
,
typename
T
=
void
>
template
<
bool
B
,
typename
T
=
void
>
using
enable_if_t
=
typename
std
::
enable_if
<
B
,
T
>::
type
;
using
enable_if_t
=
typename
std
::
enable_if
<
B
,
T
>::
type
;
template
<
typename
T
>
template
<
typename
T
>
using
uncvref_t
=
typename
std
::
remove_cv
<
typename
std
::
remove_reference
<
T
>::
type
>::
type
;
using
uncvref_t
=
typename
std
::
remove_cv
<
typename
std
::
remove_reference
<
T
>::
type
>::
type
;
// Taken from http://stackoverflow.com/questions/26936640/how-to-implement-is-enum-class-type-trait
// Taken from http://stackoverflow.com/questions/26936640/how-to-implement-is-enum-class-type-trait
template
<
typename
T
>
template
<
typename
T
>
using
is_unscoped_enum
=
using
is_unscoped_enum
=
std
::
integral_constant
<
bool
,
std
::
is_convertible
<
T
,
int
>::
value
and
std
::
integral_constant
<
bool
,
std
::
is_convertible
<
T
,
int
>::
value
and
std
::
is_enum
<
T
>::
value
>
;
std
::
is_enum
<
T
>::
value
>
;
// Implementation of 2 C++17 constructs: conjunction, negation.
/*
// This is needed to avoid evaluating all the traits in a condition
Implementation of 2 C++17 constructs: conjunction, negation. This is needed
//
to avoid evaluating all the traits in a condition
// For example: not std::is_same<void, T>::value and has_value_type<T>::value
// will not compile when T = void (on MSVC at least)
For example: not std::is_same<void, T>::value and has_value_type<T>::value
// Whereas conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value
will not compile when T = void (on MSVC at least). Whereas
// will stop evaluating if negation<...>::value == false
conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
//
stop evaluating if negation<...>::value == false
// Please note that those constructs must be used with caution, since symbols can
// become very long quickly (which can slow down compilation and cause MSVC internal compiler errors)
Please note that those constructs must be used with caution, since symbols can
// Only use it when you have too (see example ahead)
become very long quickly (which can slow down compilation and cause MSVC
template
<
class
...
>
struct
conjunction
:
std
::
true_type
{};
internal compiler errors). Only use it when you have to (see example ahead).
template
<
class
B1
>
struct
conjunction
<
B1
>
:
B1
{};
*/
template
<
class
B1
,
class
...
Bn
>
template
<
class
...
>
struct
conjunction
:
std
::
true_type
{};
struct
conjunction
<
B1
,
Bn
...
>
template
<
class
B1
>
struct
conjunction
<
B1
>
:
B1
{};
:
std
::
conditional
<
bool
(
B1
::
value
),
conjunction
<
Bn
...
>
,
B1
>::
type
{};
template
<
class
B1
,
class
...
Bn
>
struct
conjunction
<
B1
,
Bn
...
>
:
std
::
conditional
<
bool
(
B1
::
value
),
conjunction
<
Bn
...
>
,
B1
>::
type
{};
template
<
class
B
>
struct
negation
:
std
::
integral_constant
<
bool
,
!
B
::
value
>
{};
template
<
class
B
>
struct
negation
:
std
::
integral_constant
<
bool
,
!
B
::
value
>
{};
// dispatch utility (taken from ranges-v3)
// dispatch utility (taken from ranges-v3)
template
<
unsigned
N
>
struct
priority_tag
:
priority_tag
<
N
-
1
>
{};
template
<
unsigned
N
>
struct
priority_tag
:
priority_tag
<
N
-
1
>
{};
template
<
>
struct
priority_tag
<
0
>
{};
template
<
>
struct
priority_tag
<
0
>
{};
//////////////////
// constructors //
//////////////////
// This is an experiment. I need this to move constructors out of basic_json.
// This is an experiment. I need this to move constructors out of basic_json.
// I'm sure there is a better way, but this might need a big basic_json refactoring
// I'm sure there is a better way, but this might need a big basic_json
template
<
value_t
>
struct
external_constructor
;
// refactoring
template
<
value_t
>
struct
external_constructor
;
template
<
>
template
<
>
struct
external_constructor
<
value_t
::
boolean
>
struct
external_constructor
<
value_t
::
boolean
>
{
{
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
static
void
construct
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
boolean_t
b
)
noexcept
static
void
construct
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
boolean_t
b
)
noexcept
{
{
j
.
m_type
=
value_t
::
boolean
;
j
.
m_type
=
value_t
::
boolean
;
...
@@ -246,10 +256,10 @@ struct external_constructor<value_t::boolean>
...
@@ -246,10 +256,10 @@ struct external_constructor<value_t::boolean>
}
}
};
};
template
<
>
template
<
>
struct
external_constructor
<
value_t
::
string
>
struct
external_constructor
<
value_t
::
string
>
{
{
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
static
void
construct
(
BasicJsonType
&
j
,
const
typename
BasicJsonType
::
string_t
&
s
)
static
void
construct
(
BasicJsonType
&
j
,
const
typename
BasicJsonType
::
string_t
&
s
)
{
{
j
.
m_type
=
value_t
::
string
;
j
.
m_type
=
value_t
::
string
;
...
@@ -258,15 +268,17 @@ struct external_constructor<value_t::string>
...
@@ -258,15 +268,17 @@ struct external_constructor<value_t::string>
}
}
};
};
template
<
>
template
<
>
struct
external_constructor
<
value_t
::
number_float
>
struct
external_constructor
<
value_t
::
number_float
>
{
{
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
static
void
construct
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_float_t
val
)
noexcept
static
void
construct
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_float_t
val
)
noexcept
{
{
// replace infinity and NAN by null
// replace infinity and NAN by null
if
(
not
std
::
isfinite
(
val
))
if
(
not
std
::
isfinite
(
val
))
{
j
=
BasicJsonType
{};
j
=
BasicJsonType
{};
}
else
else
{
{
j
.
m_type
=
value_t
::
number_float
;
j
.
m_type
=
value_t
::
number_float
;
...
@@ -276,10 +288,10 @@ struct external_constructor<value_t::number_float>
...
@@ -276,10 +288,10 @@ struct external_constructor<value_t::number_float>
}
}
};
};
template
<
>
template
<
>
struct
external_constructor
<
value_t
::
number_unsigned
>
struct
external_constructor
<
value_t
::
number_unsigned
>
{
{
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
static
void
construct
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_unsigned_t
val
)
noexcept
static
void
construct
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_unsigned_t
val
)
noexcept
{
{
j
.
m_type
=
value_t
::
number_unsigned
;
j
.
m_type
=
value_t
::
number_unsigned
;
...
@@ -288,10 +300,10 @@ struct external_constructor<value_t::number_unsigned>
...
@@ -288,10 +300,10 @@ struct external_constructor<value_t::number_unsigned>
}
}
};
};
template
<
>
template
<
>
struct
external_constructor
<
value_t
::
number_integer
>
struct
external_constructor
<
value_t
::
number_integer
>
{
{
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
static
void
construct
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_integer_t
val
)
noexcept
static
void
construct
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_integer_t
val
)
noexcept
{
{
j
.
m_type
=
value_t
::
number_integer
;
j
.
m_type
=
value_t
::
number_integer
;
...
@@ -300,10 +312,10 @@ struct external_constructor<value_t::number_integer>
...
@@ -300,10 +312,10 @@ struct external_constructor<value_t::number_integer>
}
}
};
};
template
<
>
template
<
>
struct
external_constructor
<
value_t
::
array
>
struct
external_constructor
<
value_t
::
array
>
{
{
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
static
void
construct
(
BasicJsonType
&
j
,
const
typename
BasicJsonType
::
array_t
&
arr
)
static
void
construct
(
BasicJsonType
&
j
,
const
typename
BasicJsonType
::
array_t
&
arr
)
{
{
j
.
m_type
=
value_t
::
array
;
j
.
m_type
=
value_t
::
array
;
...
@@ -311,25 +323,24 @@ struct external_constructor<value_t::array>
...
@@ -311,25 +323,24 @@ struct external_constructor<value_t::array>
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
,
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
,
enable_if_t
<
not
std
::
is_same
<
CompatibleArrayType
,
enable_if_t
<
not
std
::
is_same
<
CompatibleArrayType
,
typename
BasicJsonType
::
array_t
>
::
value
,
typename
BasicJsonType
::
array_t
>
::
value
,
int
>
=
0
>
int
>
=
0
>
static
void
construct
(
BasicJsonType
&
j
,
const
CompatibleArrayType
&
arr
)
static
void
construct
(
BasicJsonType
&
j
,
const
CompatibleArrayType
&
arr
)
{
{
using
std
::
begin
;
using
std
::
begin
;
using
std
::
end
;
using
std
::
end
;
j
.
m_type
=
value_t
::
array
;
j
.
m_type
=
value_t
::
array
;
j
.
m_value
.
array
=
j
.
m_value
.
array
=
j
.
template
create
<
typename
BasicJsonType
::
array_t
>(
begin
(
arr
),
end
(
arr
));
j
.
template
create
<
typename
BasicJsonType
::
array_t
>(
begin
(
arr
),
end
(
arr
));
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
};
};
template
<
>
template
<
>
struct
external_constructor
<
value_t
::
object
>
struct
external_constructor
<
value_t
::
object
>
{
{
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
static
void
construct
(
BasicJsonType
&
j
,
const
typename
BasicJsonType
::
object_t
&
obj
)
static
void
construct
(
BasicJsonType
&
j
,
const
typename
BasicJsonType
::
object_t
&
obj
)
{
{
j
.
m_type
=
value_t
::
object
;
j
.
m_type
=
value_t
::
object
;
...
@@ -337,22 +348,26 @@ struct external_constructor<value_t::object>
...
@@ -337,22 +348,26 @@ struct external_constructor<value_t::object>
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
template
<
typename
BasicJsonType
,
typename
CompatibleObjectType
,
template
<
typename
BasicJsonType
,
typename
CompatibleObjectType
,
enable_if_t
<
not
std
::
is_same
<
CompatibleObjectType
,
enable_if_t
<
not
std
::
is_same
<
CompatibleObjectType
,
typename
BasicJsonType
::
object_t
>
::
value
,
typename
BasicJsonType
::
object_t
>
::
value
,
int
>
=
0
>
int
>
=
0
>
static
void
construct
(
BasicJsonType
&
j
,
const
CompatibleObjectType
&
obj
)
static
void
construct
(
BasicJsonType
&
j
,
const
CompatibleObjectType
&
obj
)
{
{
using
std
::
begin
;
using
std
::
begin
;
using
std
::
end
;
using
std
::
end
;
j
.
m_type
=
value_t
::
object
;
j
.
m_type
=
value_t
::
object
;
j
.
m_value
.
object
=
j
.
m_value
.
object
=
j
.
template
create
<
typename
BasicJsonType
::
object_t
>(
begin
(
obj
),
end
(
obj
));
j
.
template
create
<
typename
BasicJsonType
::
object_t
>(
begin
(
obj
),
end
(
obj
));
j
.
assert_invariant
();
j
.
assert_invariant
();
}
}
};
};
////////////////////////
// has_/is_ functions //
////////////////////////
/*!
/*!
@brief Helper to determine whether there's a key_type for T.
@brief Helper to determine whether there's a key_type for T.
...
@@ -364,9 +379,9 @@ contains a `mapped_type`, whereas `std::vector` fails the test.
...
@@ -364,9 +379,9 @@ contains a `mapped_type`, whereas `std::vector` fails the test.
@since version 1.0.0, overworked in version 2.0.6
@since version 1.0.0, overworked in version 2.0.6
*/
*/
#define NLOHMANN_JSON_HAS_HELPER(type) \
#define NLOHMANN_JSON_HAS_HELPER(type) \
template
<typename T> struct has_##type {
\
template
<typename T> struct has_##type {
\
private: \
private: \
template
<typename U, typename = typename U::type>
\
template
<typename U, typename = typename U::type>
\
static int detect(U &&); \
static int detect(U &&); \
static void detect(...); \
static void detect(...); \
public: \
public: \
...
@@ -381,10 +396,10 @@ NLOHMANN_JSON_HAS_HELPER(iterator);
...
@@ -381,10 +396,10 @@ NLOHMANN_JSON_HAS_HELPER(iterator);
#undef NLOHMANN_JSON_HAS_HELPER
#undef NLOHMANN_JSON_HAS_HELPER
template
<
bool
B
,
class
RealType
,
class
CompatibleObjectType
>
template
<
bool
B
,
class
RealType
,
class
CompatibleObjectType
>
struct
is_compatible_object_type_impl
:
std
::
false_type
{};
struct
is_compatible_object_type_impl
:
std
::
false_type
{};
template
<
class
RealType
,
class
CompatibleObjectType
>
template
<
class
RealType
,
class
CompatibleObjectType
>
struct
is_compatible_object_type_impl
<
true
,
RealType
,
CompatibleObjectType
>
struct
is_compatible_object_type_impl
<
true
,
RealType
,
CompatibleObjectType
>
{
{
static
constexpr
auto
value
=
static
constexpr
auto
value
=
...
@@ -404,7 +419,7 @@ struct is_compatible_object_type
...
@@ -404,7 +419,7 @@ struct is_compatible_object_type
typename
BasicJsonType
::
object_t
,
CompatibleObjectType
>::
value
;
typename
BasicJsonType
::
object_t
,
CompatibleObjectType
>::
value
;
};
};
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
struct
is_basic_json_nested_type
struct
is_basic_json_nested_type
{
{
static
auto
constexpr
value
=
std
::
is_same
<
T
,
typename
BasicJsonType
::
iterator
>::
value
or
static
auto
constexpr
value
=
std
::
is_same
<
T
,
typename
BasicJsonType
::
iterator
>::
value
or
...
@@ -414,11 +429,9 @@ struct is_basic_json_nested_type
...
@@ -414,11 +429,9 @@ struct is_basic_json_nested_type
std
::
is_same
<
T
,
typename
BasicJsonType
::
json_pointer
>::
value
;
std
::
is_same
<
T
,
typename
BasicJsonType
::
json_pointer
>::
value
;
};
};
template
<
class
BasicJsonType
,
class
CompatibleArrayType
>
template
<
class
BasicJsonType
,
class
CompatibleArrayType
>
struct
is_compatible_array_type
struct
is_compatible_array_type
{
{
// TODO concept Container?
// this might not make VS happy
static
auto
constexpr
value
=
static
auto
constexpr
value
=
conjunction
<
negation
<
std
::
is_same
<
void
,
CompatibleArrayType
>>
,
conjunction
<
negation
<
std
::
is_same
<
void
,
CompatibleArrayType
>>
,
negation
<
is_compatible_object_type
<
negation
<
is_compatible_object_type
<
...
@@ -430,10 +443,10 @@ struct is_compatible_array_type
...
@@ -430,10 +443,10 @@ struct is_compatible_array_type
has_iterator
<
CompatibleArrayType
>>::
value
;
has_iterator
<
CompatibleArrayType
>>::
value
;
};
};
template
<
bool
,
typename
,
typename
>
template
<
bool
,
typename
,
typename
>
struct
is_compatible_integer_type_impl
:
std
::
false_type
{};
struct
is_compatible_integer_type_impl
:
std
::
false_type
{};
template
<
typename
RealIntegerType
,
typename
CompatibleNumberIntegerType
>
template
<
typename
RealIntegerType
,
typename
CompatibleNumberIntegerType
>
struct
is_compatible_integer_type_impl
<
true
,
RealIntegerType
,
CompatibleNumberIntegerType
>
struct
is_compatible_integer_type_impl
<
true
,
RealIntegerType
,
CompatibleNumberIntegerType
>
{
{
// is there an assert somewhere on overflows?
// is there an assert somewhere on overflows?
...
@@ -447,24 +460,25 @@ struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIn
...
@@ -447,24 +460,25 @@ struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIn
RealLimits
::
is_signed
==
CompatibleLimits
::
is_signed
;
RealLimits
::
is_signed
==
CompatibleLimits
::
is_signed
;
};
};
template
<
typename
RealIntegerType
,
typename
CompatibleNumberIntegerType
>
template
<
typename
RealIntegerType
,
typename
CompatibleNumberIntegerType
>
struct
is_compatible_integer_type
struct
is_compatible_integer_type
{
{
static
constexpr
auto
static
constexpr
auto
value
=
value
=
is_compatible_integer_type_impl
<
is_compatible_integer_type_impl
<
std
::
is_integral
<
CompatibleNumberIntegerType
>::
value
and
std
::
is_integral
<
CompatibleNumberIntegerType
>::
value
and
not
std
::
is_same
<
bool
,
CompatibleNumberIntegerType
>::
value
,
not
std
::
is_same
<
bool
,
CompatibleNumberIntegerType
>::
value
,
RealIntegerType
,
CompatibleNumberIntegerType
>
::
value
;
RealIntegerType
,
CompatibleNumberIntegerType
>
::
value
;
};
};
// This trait checks if JSONSerializer<T>::from_json(json const&, udt&) exists
// This trait checks if JSONSerializer<T>::from_json(json const&, udt&) exists
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_from_json
struct
has_from_json
{
{
private:
private:
// also check the return type of from_json
// also check the return type of from_json
template
<
typename
U
,
typename
=
enable_if_t
<
std
::
is_same
<
void
,
decltype
(
uncvref_t
<
U
>
::
from_json
(
template
<
typename
U
,
typename
=
enable_if_t
<
std
::
is_same
<
void
,
decltype
(
uncvref_t
<
U
>
::
from_json
(
std
::
declval
<
BasicJsonType
>
(),
std
::
declval
<
T
&>
()))
>::
value
>>
std
::
declval
<
BasicJsonType
>
(),
std
::
declval
<
T
&>
()))
>::
value
>>
static
int
detect
(
U
&&
);
static
int
detect
(
U
&&
);
static
void
detect
(...);
static
void
detect
(...);
...
@@ -475,7 +489,7 @@ struct has_from_json
...
@@ -475,7 +489,7 @@ struct has_from_json
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
// this overload is used for non-default-constructible user-defined-types
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_non_default_from_json
struct
has_non_default_from_json
{
{
private:
private:
...
@@ -492,12 +506,12 @@ struct has_non_default_from_json
...
@@ -492,12 +506,12 @@ struct has_non_default_from_json
};
};
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_to_json
struct
has_to_json
{
{
private:
private:
template
<
typename
U
,
typename
=
decltype
(
uncvref_t
<
U
>
::
to_json
(
template
<
typename
U
,
typename
=
decltype
(
uncvref_t
<
U
>
::
to_json
(
std
::
declval
<
BasicJsonType
&>
(),
std
::
declval
<
T
>
()))
>
std
::
declval
<
BasicJsonType
&>
(),
std
::
declval
<
T
>
()))
>
static
int
detect
(
U
&&
);
static
int
detect
(
U
&&
);
static
void
detect
(...);
static
void
detect
(...);
...
@@ -506,58 +520,33 @@ struct has_to_json
...
@@ -506,58 +520,33 @@ struct has_to_json
std
::
declval
<
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>
>
()))
>::
value
;
std
::
declval
<
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>
>
()))
>::
value
;
};
};
// overloads for basic_json template parameters
template
<
typename
BasicJsonType
,
typename
ArithmeticType
,
/////////////
enable_if_t
<
std
::
is_arithmetic
<
ArithmeticType
>
::
value
and
// to_json //
not
std
::
is_same
<
ArithmeticType
,
/////////////
typename
BasicJsonType
::
boolean_t
>::
value
,
int
>
=
0
>
void
get_arithmetic_value
(
const
BasicJsonType
&
j
,
ArithmeticType
&
val
)
{
switch
(
static_cast
<
value_t
>
(
j
))
{
case
value_t
:
:
number_unsigned
:
val
=
static_cast
<
ArithmeticType
>
(
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_unsigned_t
*
>());
break
;
case
value_t
:
:
number_integer
:
val
=
static_cast
<
ArithmeticType
>
(
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_integer_t
*
>());
break
;
case
value_t
:
:
number_float
:
val
=
static_cast
<
ArithmeticType
>
(
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_float_t
*
>());
break
;
default:
JSON_THROW
(
std
::
domain_error
(
"type must be number, but is "
+
j
.
type_name
()));
}
}
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
void
to_json
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
boolean_t
b
)
noexcept
void
to_json
(
BasicJsonType
&
j
,
typename
BasicJsonType
::
boolean_t
b
)
noexcept
{
{
external_constructor
<
value_t
::
boolean
>::
construct
(
j
,
b
);
external_constructor
<
value_t
::
boolean
>::
construct
(
j
,
b
);
}
}
template
<
typename
BasicJsonType
,
typename
CompatibleString
,
template
<
typename
BasicJsonType
,
typename
CompatibleString
,
enable_if_t
<
std
::
is_constructible
<
typename
BasicJsonType
::
string_t
,
enable_if_t
<
std
::
is_constructible
<
typename
BasicJsonType
::
string_t
,
CompatibleString
>
::
value
,
CompatibleString
>
::
value
,
int
>
=
0
>
int
>
=
0
>
void
to_json
(
BasicJsonType
&
j
,
const
CompatibleString
&
s
)
void
to_json
(
BasicJsonType
&
j
,
const
CompatibleString
&
s
)
{
{
external_constructor
<
value_t
::
string
>::
construct
(
j
,
s
);
external_constructor
<
value_t
::
string
>::
construct
(
j
,
s
);
}
}
template
<
typename
BasicJsonType
,
typename
FloatType
,
template
<
typename
BasicJsonType
,
typename
FloatType
,
enable_if_t
<
std
::
is_floating_point
<
FloatType
>
::
value
,
int
>
=
0
>
enable_if_t
<
std
::
is_floating_point
<
FloatType
>
::
value
,
int
>
=
0
>
void
to_json
(
BasicJsonType
&
j
,
FloatType
val
)
noexcept
void
to_json
(
BasicJsonType
&
j
,
FloatType
val
)
noexcept
{
{
external_constructor
<
value_t
::
number_float
>::
construct
(
j
,
static_cast
<
typename
BasicJsonType
::
number_float_t
>
(
val
));
external_constructor
<
value_t
::
number_float
>::
construct
(
j
,
static_cast
<
typename
BasicJsonType
::
number_float_t
>
(
val
));
}
}
template
<
template
<
typename
BasicJsonType
,
typename
CompatibleNumberUnsignedType
,
typename
BasicJsonType
,
typename
CompatibleNumberUnsignedType
,
enable_if_t
<
is_compatible_integer_type
<
typename
BasicJsonType
::
number_unsigned_t
,
enable_if_t
<
is_compatible_integer_type
<
typename
BasicJsonType
::
number_unsigned_t
,
...
@@ -578,8 +567,8 @@ void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
...
@@ -578,8 +567,8 @@ void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
external_constructor
<
value_t
::
number_integer
>::
construct
(
j
,
static_cast
<
typename
BasicJsonType
::
number_integer_t
>
(
val
));
external_constructor
<
value_t
::
number_integer
>::
construct
(
j
,
static_cast
<
typename
BasicJsonType
::
number_integer_t
>
(
val
));
}
}
template
<
typename
BasicJsonType
,
typename
UnscopedEnumType
,
template
<
typename
BasicJsonType
,
typename
UnscopedEnumType
,
enable_if_t
<
is_unscoped_enum
<
UnscopedEnumType
>
::
value
,
int
>
=
0
>
enable_if_t
<
is_unscoped_enum
<
UnscopedEnumType
>
::
value
,
int
>
=
0
>
void
to_json
(
BasicJsonType
&
j
,
UnscopedEnumType
e
)
noexcept
void
to_json
(
BasicJsonType
&
j
,
UnscopedEnumType
e
)
noexcept
{
{
external_constructor
<
value_t
::
number_integer
>::
construct
(
j
,
e
);
external_constructor
<
value_t
::
number_integer
>::
construct
(
j
,
e
);
...
@@ -605,7 +594,48 @@ void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
...
@@ -605,7 +594,48 @@ void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
external_constructor
<
value_t
::
object
>::
construct
(
j
,
arr
);
external_constructor
<
value_t
::
object
>::
construct
(
j
,
arr
);
}
}
template
<
typename
BasicJsonType
>
///////////////
// from_json //
///////////////
// overloads for basic_json template parameters
template
<
typename
BasicJsonType
,
typename
ArithmeticType
,
enable_if_t
<
std
::
is_arithmetic
<
ArithmeticType
>
::
value
and
not
std
::
is_same
<
ArithmeticType
,
typename
BasicJsonType
::
boolean_t
>::
value
,
int
>
=
0
>
void
get_arithmetic_value
(
const
BasicJsonType
&
j
,
ArithmeticType
&
val
)
{
switch
(
static_cast
<
value_t
>
(
j
))
{
case
value_t
:
:
number_unsigned
:
{
val
=
static_cast
<
ArithmeticType
>
(
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_unsigned_t
*
>());
break
;
}
case
value_t
:
:
number_integer
:
{
val
=
static_cast
<
ArithmeticType
>
(
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_integer_t
*
>());
break
;
}
case
value_t
:
:
number_float
:
{
val
=
static_cast
<
ArithmeticType
>
(
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_float_t
*
>());
break
;
}
default:
{
JSON_THROW
(
std
::
domain_error
(
"type must be number, but is "
+
j
.
type_name
()));
}
}
}
template
<
typename
BasicJsonType
>
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
boolean_t
&
b
)
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
boolean_t
&
b
)
{
{
if
(
!
j
.
is_boolean
())
if
(
!
j
.
is_boolean
())
...
@@ -615,7 +645,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
...
@@ -615,7 +645,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
b
=
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
boolean_t
*
>();
b
=
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
boolean_t
*
>();
}
}
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
string_t
&
s
)
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
string_t
&
s
)
{
{
if
(
!
j
.
is_string
())
if
(
!
j
.
is_string
())
...
@@ -625,35 +655,35 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
...
@@ -625,35 +655,35 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
s
=
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
string_t
*
>();
s
=
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
string_t
*
>();
}
}
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_float_t
&
val
)
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_float_t
&
val
)
{
{
get_arithmetic_value
(
j
,
val
);
get_arithmetic_value
(
j
,
val
);
}
}
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_unsigned_t
&
val
)
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_unsigned_t
&
val
)
{
{
get_arithmetic_value
(
j
,
val
);
get_arithmetic_value
(
j
,
val
);
}
}
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_integer_t
&
val
)
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
number_integer_t
&
val
)
{
{
get_arithmetic_value
(
j
,
val
);
get_arithmetic_value
(
j
,
val
);
}
}
template
<
typename
BasicJsonType
,
typename
UnscopedEnumType
,
template
<
typename
BasicJsonType
,
typename
UnscopedEnumType
,
enable_if_t
<
is_unscoped_enum
<
UnscopedEnumType
>
::
value
,
int
>
=
0
>
enable_if_t
<
is_unscoped_enum
<
UnscopedEnumType
>
::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
UnscopedEnumType
&
e
)
void
from_json
(
const
BasicJsonType
&
j
,
UnscopedEnumType
&
e
)
{
{
typename
std
::
underlying_type
<
UnscopedEnumType
>::
type
val
=
e
;
typename
std
::
underlying_type
<
UnscopedEnumType
>::
type
val
=
e
;
get_arithmetic_value
(
j
,
val
);
get_arithmetic_value
(
j
,
val
);
e
=
static_cast
<
UnscopedEnumType
>
(
val
);
e
=
static_cast
<
UnscopedEnumType
>
(
val
);
}
}
template
<
typename
BasicJsonType
>
template
<
typename
BasicJsonType
>
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
array_t
&
arr
)
void
from_json
(
const
BasicJsonType
&
j
,
typename
BasicJsonType
::
array_t
&
arr
)
{
{
if
(
!
j
.
is_array
())
if
(
!
j
.
is_array
())
{
{
...
@@ -662,8 +692,9 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
...
@@ -662,8 +692,9 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
arr
=
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
array_t
*
>();
arr
=
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
array_t
*
>();
}
}
// forward_list doesn't have an insert method, TODO find a way to avoid including forward_list
// forward_list doesn't have an insert method
template
<
typename
BasicJsonType
,
typename
T
,
typename
Allocator
>
// TODO find a way to avoid including forward_list
template
<
typename
BasicJsonType
,
typename
T
,
typename
Allocator
>
void
from_json
(
const
BasicJsonType
&
j
,
std
::
forward_list
<
T
,
Allocator
>&
l
)
void
from_json
(
const
BasicJsonType
&
j
,
std
::
forward_list
<
T
,
Allocator
>&
l
)
{
{
// do not perform the check when user wants to retrieve jsons
// do not perform the check when user wants to retrieve jsons
...
@@ -685,23 +716,23 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
...
@@ -685,23 +716,23 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
}
}
}
}
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
>
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
>
void
from_json_array_impl
(
const
BasicJsonType
&
j
,
CompatibleArrayType
&
arr
,
priority_tag
<
0
>
)
void
from_json_array_impl
(
const
BasicJsonType
&
j
,
CompatibleArrayType
&
arr
,
priority_tag
<
0
>
)
{
{
using
std
::
begin
;
using
std
::
begin
;
using
std
::
end
;
using
std
::
end
;
std
::
transform
(
std
::
transform
(
j
.
begin
(),
j
.
end
(),
j
.
begin
(),
j
.
end
(),
std
::
inserter
(
arr
,
end
(
arr
)),
[](
const
BasicJsonType
&
i
)
std
::
inserter
(
arr
,
end
(
arr
)),
[](
const
BasicJsonType
&
i
)
{
{
// get<BasicJsonType>() returns *this, this won't call a from_json
method when
// get<BasicJsonType>() returns *this, this won't call a from_json
// value_type is BasicJsonType
//
method when
value_type is BasicJsonType
return
i
.
template
get
<
typename
CompatibleArrayType
::
value_type
>();
return
i
.
template
get
<
typename
CompatibleArrayType
::
value_type
>();
});
});
}
}
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
>
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
>
auto
from_json_array_impl
(
const
BasicJsonType
&
j
,
CompatibleArrayType
&
arr
,
priority_tag
<
1
>
)
auto
from_json_array_impl
(
const
BasicJsonType
&
j
,
CompatibleArrayType
&
arr
,
priority_tag
<
1
>
)
->
decltype
(
->
decltype
(
arr
.
reserve
(
std
::
declval
<
typename
CompatibleArrayType
::
size_type
>
()),
arr
.
reserve
(
std
::
declval
<
typename
CompatibleArrayType
::
size_type
>
()),
void
())
void
())
...
@@ -711,26 +742,24 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, pri
...
@@ -711,26 +742,24 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, pri
arr
.
reserve
(
j
.
size
());
arr
.
reserve
(
j
.
size
());
std
::
transform
(
std
::
transform
(
j
.
begin
(),
j
.
end
(),
std
::
inserter
(
arr
,
end
(
arr
)),
[](
const
BasicJsonType
&
i
)
j
.
begin
(),
j
.
end
(),
std
::
inserter
(
arr
,
end
(
arr
)),
[](
const
BasicJsonType
&
i
)
{
{
// get<BasicJsonType>() returns *this, this won't call a from_json
method when
// get<BasicJsonType>() returns *this, this won't call a from_json
// value_type is BasicJsonType
//
method when
value_type is BasicJsonType
return
i
.
template
get
<
typename
CompatibleArrayType
::
value_type
>();
return
i
.
template
get
<
typename
CompatibleArrayType
::
value_type
>();
});
});
}
}
template
<
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
,
typename
BasicJsonType
,
typename
CompatibleArrayType
,
enable_if_t
<
is_compatible_array_type
<
BasicJsonType
,
CompatibleArrayType
>
::
value
and
enable_if_t
<
is_compatible_array_type
<
BasicJsonType
,
CompatibleArrayType
>
::
value
and
not
std
::
is_same
<
typename
BasicJsonType
::
array_t
,
CompatibleArrayType
>::
value
,
int
>
=
0
>
not
std
::
is_same
<
typename
BasicJsonType
::
array_t
,
void
from_json
(
const
BasicJsonType
&
j
,
CompatibleArrayType
&
arr
)
CompatibleArrayType
>::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
CompatibleArrayType
&
arr
)
{
{
if
(
j
.
is_null
())
if
(
j
.
is_null
())
{
{
JSON_THROW
(
std
::
domain_error
(
"type must be array, but is "
+
j
.
type_name
()));
JSON_THROW
(
std
::
domain_error
(
"type must be array, but is "
+
j
.
type_name
()));
}
}
// when T == BasicJsonType, do not check if value_t is correct
// when T == BasicJsonType, do not check if value_t is correct
if
(
not
std
::
is_same
<
typename
CompatibleArrayType
::
value_type
,
BasicJsonType
>::
value
)
if
(
not
std
::
is_same
<
typename
CompatibleArrayType
::
value_type
,
BasicJsonType
>::
value
)
{
{
...
@@ -742,12 +771,9 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
...
@@ -742,12 +771,9 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
from_json_array_impl
(
j
,
arr
,
priority_tag
<
1
>
{});
from_json_array_impl
(
j
,
arr
,
priority_tag
<
1
>
{});
}
}
template
<
typename
BasicJsonType
,
typename
CompatibleObjectType
,
template
<
enable_if_t
<
is_compatible_object_type
<
BasicJsonType
,
CompatibleObjectType
>
::
value
,
int
>
=
0
>
typename
BasicJsonType
,
typename
CompatibleObjectType
,
void
from_json
(
const
BasicJsonType
&
j
,
CompatibleObjectType
&
obj
)
enable_if_t
<
is_compatible_object_type
<
BasicJsonType
,
CompatibleObjectType
>
::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
CompatibleObjectType
&
obj
)
{
{
if
(
!
j
.
is_object
())
if
(
!
j
.
is_object
())
{
{
...
@@ -766,63 +792,52 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
...
@@ -766,63 +792,52 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
//
//
// note: Is it really necessary to provide explicit overloads for boolean_t etc..
// note: Is it really necessary to provide explicit overloads for boolean_t etc..
// in case of a custom BooleanType which is not an arithmetic type?
// in case of a custom BooleanType which is not an arithmetic type?
template
<
template
<
typename
BasicJsonType
,
typename
ArithmeticType
,
typename
BasicJsonType
,
typename
ArithmeticType
,
enable_if_t
<
enable_if_t
<
std
::
is_arithmetic
<
ArithmeticType
>
::
value
and
std
::
is_arithmetic
<
ArithmeticType
>
::
value
and
not
std
::
is_same
<
ArithmeticType
,
typename
BasicJsonType
::
number_unsigned_t
>::
value
and
not
std
::
is_same
<
ArithmeticType
,
not
std
::
is_same
<
ArithmeticType
,
typename
BasicJsonType
::
number_integer_t
>::
value
and
typename
BasicJsonType
::
number_unsigned_t
>::
value
and
not
std
::
is_same
<
ArithmeticType
,
typename
BasicJsonType
::
number_float_t
>::
value
and
not
std
::
is_same
<
ArithmeticType
,
not
std
::
is_same
<
ArithmeticType
,
typename
BasicJsonType
::
boolean_t
>::
value
,
typename
BasicJsonType
::
number_integer_t
>::
value
and
int
>
=
0
>
not
std
::
is_same
<
ArithmeticType
,
typename
BasicJsonType
::
number_float_t
>::
value
and
not
std
::
is_same
<
ArithmeticType
,
typename
BasicJsonType
::
boolean_t
>::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
ArithmeticType
&
val
)
void
from_json
(
const
BasicJsonType
&
j
,
ArithmeticType
&
val
)
{
{
switch
(
static_cast
<
value_t
>
(
j
))
switch
(
static_cast
<
value_t
>
(
j
))
{
{
case
value_t
:
:
number_unsigned
:
case
value_t
:
:
number_unsigned
:
val
=
static_cast
<
ArithmeticType
>
(
val
=
static_cast
<
ArithmeticType
>
(
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_unsigned_t
*
>());
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_unsigned_t
*
>());
break
;
break
;
case
value_t
:
:
number_integer
:
case
value_t
:
:
number_integer
:
val
=
static_cast
<
ArithmeticType
>
(
val
=
static_cast
<
ArithmeticType
>
(
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_integer_t
*
>());
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_integer_t
*
>());
break
;
break
;
case
value_t
:
:
number_float
:
case
value_t
:
:
number_float
:
val
=
static_cast
<
ArithmeticType
>
(
val
=
static_cast
<
ArithmeticType
>
(
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_float_t
*
>());
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
number_float_t
*
>());
break
;
break
;
case
value_t
:
:
boolean
:
case
value_t
:
:
boolean
:
val
=
static_cast
<
ArithmeticType
>
(
val
=
static_cast
<
ArithmeticType
>
(
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
boolean_t
*
>());
*
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
boolean_t
*
>());
break
;
break
;
default:
default:
JSON_THROW
(
JSON_THROW
(
std
::
domain_error
(
"type must be number, but is "
+
j
.
type_name
()));
std
::
domain_error
(
"type must be number, but is "
+
j
.
type_name
()));
}
}
}
}
struct
to_json_fn
struct
to_json_fn
{
{
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
auto
call
(
BasicJsonType
&
j
,
T
&&
val
,
priority_tag
<
1
>
)
const
auto
call
(
BasicJsonType
&
j
,
T
&&
val
,
priority_tag
<
1
>
)
const
noexcept
(
noexcept
(
to_json
(
j
,
std
::
forward
<
T
>
(
val
))))
noexcept
(
noexcept
(
to_json
(
j
,
std
::
forward
<
T
>
(
val
))))
->
decltype
(
to_json
(
j
,
std
::
forward
<
T
>
(
val
)),
void
())
->
decltype
(
to_json
(
j
,
std
::
forward
<
T
>
(
val
)),
void
())
{
{
return
to_json
(
j
,
std
::
forward
<
T
>
(
val
));
return
to_json
(
j
,
std
::
forward
<
T
>
(
val
));
}
}
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
void
call
(
BasicJsonType
&
,
T
&&
,
priority_tag
<
0
>
)
const
noexcept
void
call
(
BasicJsonType
&
,
T
&&
,
priority_tag
<
0
>
)
const
noexcept
{
{
static_assert
(
sizeof
(
BasicJsonType
)
==
0
,
"to_json method in T's namespace can not be called"
);
static_assert
(
sizeof
(
BasicJsonType
)
==
0
,
"to_json method in T's namespace can not be called"
);
}
}
public:
public:
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
void
operator
()(
BasicJsonType
&
j
,
T
&&
val
)
const
void
operator
()(
BasicJsonType
&
j
,
T
&&
val
)
const
noexcept
(
noexcept
(
std
::
declval
<
to_json_fn
>
().
call
(
j
,
std
::
forward
<
T
>
(
val
),
priority_tag
<
1
>
{})))
noexcept
(
noexcept
(
std
::
declval
<
to_json_fn
>
().
call
(
j
,
std
::
forward
<
T
>
(
val
),
priority_tag
<
1
>
{})))
{
{
...
@@ -833,23 +848,23 @@ struct to_json_fn
...
@@ -833,23 +848,23 @@ struct to_json_fn
struct
from_json_fn
struct
from_json_fn
{
{
private:
private:
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
auto
call
(
const
BasicJsonType
&
j
,
T
&
val
,
priority_tag
<
1
>
)
const
auto
call
(
const
BasicJsonType
&
j
,
T
&
val
,
priority_tag
<
1
>
)
const
noexcept
(
noexcept
(
from_json
(
j
,
val
)))
noexcept
(
noexcept
(
from_json
(
j
,
val
)))
->
decltype
(
from_json
(
j
,
val
),
void
())
->
decltype
(
from_json
(
j
,
val
),
void
())
{
{
return
from_json
(
j
,
val
);
return
from_json
(
j
,
val
);
}
}
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
void
call
(
const
BasicJsonType
&
,
T
&
,
priority_tag
<
0
>
)
const
noexcept
void
call
(
const
BasicJsonType
&
,
T
&
,
priority_tag
<
0
>
)
const
noexcept
{
{
static_assert
(
sizeof
(
BasicJsonType
)
==
0
,
"from_json method in T's namespace can not be called"
);
static_assert
(
sizeof
(
BasicJsonType
)
==
0
,
"from_json method in T's namespace can not be called"
);
}
}
public:
public:
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
void
operator
()(
const
BasicJsonType
&
j
,
T
&
val
)
const
void
operator
()(
const
BasicJsonType
&
j
,
T
&
val
)
const
noexcept
(
noexcept
(
std
::
declval
<
from_json_fn
>
().
call
(
j
,
val
,
priority_tag
<
1
>
{})))
noexcept
(
noexcept
(
std
::
declval
<
from_json_fn
>
().
call
(
j
,
val
,
priority_tag
<
1
>
{})))
{
{
return
call
(
j
,
val
,
priority_tag
<
1
>
{});
return
call
(
j
,
val
,
priority_tag
<
1
>
{});
...
@@ -857,15 +872,16 @@ struct from_json_fn
...
@@ -857,15 +872,16 @@ struct from_json_fn
};
};
// taken from ranges-v3
// taken from ranges-v3
template
<
typename
T
>
template
<
typename
T
>
struct
static_const
struct
static_const
{
{
static
constexpr
T
value
{};
static
constexpr
T
value
{};
};
};
template
<
typename
T
>
template
<
typename
T
>
constexpr
T
static_const
<
T
>::
value
;
constexpr
T
static_const
<
T
>::
value
;
/*!
/*!
@brief helper class to create locales with decimal point
@brief helper class to create locales with decimal point
...
@@ -885,7 +901,8 @@ struct DecimalSeparator : std::numpunct<char>
...
@@ -885,7 +901,8 @@ struct DecimalSeparator : std::numpunct<char>
return
'.'
;
return
'.'
;
}
}
};
};
}
}
// namespace detail
namespace
namespace
{
{
...
@@ -895,16 +912,16 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va
...
@@ -895,16 +912,16 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va
// default JSONSerializer template argument, doesn't care about template argument
// default JSONSerializer template argument, doesn't care about template argument
// will use ADL for serialization
// will use ADL for serialization
template
<
typename
=
void
,
typename
=
void
>
template
<
typename
=
void
,
typename
=
void
>
struct
adl_serializer
struct
adl_serializer
{
{
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
static
void
from_json
(
BasicJsonType
&&
j
,
T
&
val
)
noexcept
(
noexcept
(
::
nlohmann
::
from_json
(
std
::
forward
<
BasicJsonType
>
(
j
),
val
)))
static
void
from_json
(
BasicJsonType
&&
j
,
T
&
val
)
noexcept
(
noexcept
(
::
nlohmann
::
from_json
(
std
::
forward
<
BasicJsonType
>
(
j
),
val
)))
{
{
::
nlohmann
::
from_json
(
std
::
forward
<
BasicJsonType
>
(
j
),
val
);
::
nlohmann
::
from_json
(
std
::
forward
<
BasicJsonType
>
(
j
),
val
);
}
}
template
<
typename
BasicJsonType
,
typename
T
>
template
<
typename
BasicJsonType
,
typename
T
>
static
void
to_json
(
BasicJsonType
&
j
,
T
&&
val
)
noexcept
(
static
void
to_json
(
BasicJsonType
&
j
,
T
&&
val
)
noexcept
(
noexcept
(
::
nlohmann
::
to_json
(
j
,
std
::
forward
<
T
>
(
val
))))
noexcept
(
::
nlohmann
::
to_json
(
j
,
std
::
forward
<
T
>
(
val
))))
{
{
...
@@ -912,6 +929,7 @@ struct adl_serializer
...
@@ -912,6 +929,7 @@ struct adl_serializer
}
}
};
};
/*!
/*!
@brief a class to store JSON values
@brief a class to store JSON values
...
@@ -1005,7 +1023,7 @@ template <
...
@@ -1005,7 +1023,7 @@ template <
class
basic_json
class
basic_json
{
{
private:
private:
template
<
detail
::
value_t
>
friend
struct
detail
::
external_constructor
;
template
<
detail
::
value_t
>
friend
struct
detail
::
external_constructor
;
/// workaround type for MSVC
/// workaround type for MSVC
using
basic_json_t
=
basic_json
<
ObjectType
,
ArrayType
,
StringType
,
using
basic_json_t
=
basic_json
<
ObjectType
,
ArrayType
,
StringType
,
BooleanType
,
NumberIntegerType
,
NumberUnsignedType
,
NumberFloatType
,
BooleanType
,
NumberIntegerType
,
NumberUnsignedType
,
NumberFloatType
,
...
@@ -1017,7 +1035,7 @@ class basic_json
...
@@ -1017,7 +1035,7 @@ class basic_json
template
<
typename
U
>
class
iter_impl
;
template
<
typename
U
>
class
iter_impl
;
template
<
typename
Base
>
class
json_reverse_iterator
;
template
<
typename
Base
>
class
json_reverse_iterator
;
class
json_pointer
;
class
json_pointer
;
template
<
typename
T
,
typename
SFINAE
>
template
<
typename
T
,
typename
SFINAE
>
using
json_serializer
=
JSONSerializer
<
T
,
SFINAE
>
;
using
json_serializer
=
JSONSerializer
<
T
,
SFINAE
>
;
/////////////////////
/////////////////////
...
@@ -1904,13 +1922,13 @@ class basic_json
...
@@ -1904,13 +1922,13 @@ class basic_json
@since version 2.1.0
@since version 2.1.0
*/
*/
template
<
typename
T
,
typename
U
=
detail
::
uncvref_t
<
T
>,
template
<
typename
T
,
typename
U
=
detail
::
uncvref_t
<
T
>,
detail
::
enable_if_t
<
not
std
::
is_base_of
<
std
::
istream
,
U
>::
value
and
detail
::
enable_if_t
<
not
std
::
is_base_of
<
std
::
istream
,
U
>::
value
and
not
std
::
is_same
<
U
,
basic_json_t
>::
value
and
not
std
::
is_same
<
U
,
basic_json_t
>::
value
and
not
detail
::
is_basic_json_nested_type
<
not
detail
::
is_basic_json_nested_type
<
basic_json_t
,
U
>::
value
and
basic_json_t
,
U
>::
value
and
detail
::
has_to_json
<
basic_json
,
U
>::
value
,
detail
::
has_to_json
<
basic_json
,
U
>::
value
,
int
>
=
0
>
int
>
=
0
>
basic_json
(
T
&&
val
)
noexcept
(
noexcept
(
JSONSerializer
<
U
>::
to_json
(
basic_json
(
T
&&
val
)
noexcept
(
noexcept
(
JSONSerializer
<
U
>::
to_json
(
std
::
declval
<
basic_json_t
&>
(),
std
::
forward
<
T
>
(
val
))))
std
::
declval
<
basic_json_t
&>
(),
std
::
forward
<
T
>
(
val
))))
{
{
...
@@ -5714,6 +5732,13 @@ class basic_json
...
@@ -5714,6 +5732,13 @@ class basic_json
/// @}
/// @}
public:
public:
//////////////////////////////////////////
// lexicographical comparison operators //
//////////////////////////////////////////
/// @name lexicographical comparison operators
/// @{
/*!
/*!
@brief comparison: equal
@brief comparison: equal
...
@@ -10795,7 +10820,7 @@ basic_json_parser_66:
...
@@ -10795,7 +10820,7 @@ basic_json_parser_66:
for
(;
curptr
<
m_cursor
;
curptr
++
)
for
(;
curptr
<
m_cursor
;
curptr
++
)
{
{
// quickly skip tests if a digit
// quickly skip tests if a digit
if
(
*
curptr
<
'0'
||
*
curptr
>
'9'
)
if
(
*
curptr
<
'0'
or
*
curptr
>
'9'
)
{
{
if
(
*
curptr
==
'.'
)
if
(
*
curptr
==
'.'
)
{
{
...
...
src/json.hpp.re2c
View file @
250e5bf4
...
@@ -107,12 +107,15 @@ SOFTWARE.
...
@@ -107,12 +107,15 @@ SOFTWARE.
*/
*/
namespace nlohmann
namespace nlohmann
{
{
// TODO update this doc
/*!
/*!
@brief unnamed namespace with internal helper functions
@brief unnamed namespace with internal helper functions
@since version 1.0.0
*/
This namespace collects some functions that could not be defined inside the
@ref basic_json class.
@since version 2.1.0
*/
namespace detail
namespace detail
{
{
///////////////////////////
///////////////////////////
...
@@ -122,22 +125,24 @@ namespace detail
...
@@ -122,22 +125,24 @@ namespace detail
/*!
/*!
@brief the JSON type enumeration
@brief the JSON type enumeration
This enumeration collects the different JSON types. It is internally used
This enumeration collects the different JSON types. It is internally used to
to distinguish the stored values, and the functions @ref basic_json::is_null(), @ref
distinguish the stored values, and the functions @ref basic_json::is_null(),
basic_json::is_object(), @ref basic_json::is_array(), @ref basic_json::is_string(), @ref basic_json::is_boolean(), @ref
@ref basic_json::is_object(), @ref basic_json::is_array(),
basic_json::is_number() (with @ref basic_json::is_number_integer(), @ref basic_json::is_number_unsigned(), and
@ref basic_json::is_string(), @ref basic_json::is_boolean(),
@ref basic_json::is_number_float()), @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
@ref basic_json::is_structured() rely on it.
@ref basic_json::is_structured() rely on it.
@note There are three enumeration entries (number_integer,
@note There are three enumeration entries (number_integer,
number_unsigned, and
number_
unsigned, and number_float), because the library distinguishes
number_
float), because the library distinguishes these three types for numbers:
these three types for numbers: @ref basic_json::number_unsigned_t is used for unsigned
@ref basic_json::number_unsigned_t is used for unsigned integers,
integers, @ref basic_json::number_integer_t is used for signed integers, and @ref
@ref basic_json::number_integer_t is used for signed integers, and
basic_json::number_float_t is used for floating-point numbers or to approximate
@ref basic_json::number_float_t is used for floating-point numbers or to
integers which do not fit in the limits of their respective type.
approximate
integers which do not fit in the limits of their respective type.
@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
value with
@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
the default value for a given type
value with
the default value for a given type
@since version 1.0.0
@since version 1.0.0
*/
*/
...
@@ -154,12 +159,6 @@ enum class value_t : uint8_t
...
@@ -154,12 +159,6 @@ enum class value_t : uint8_t
discarded ///< discarded by the the parser callback function
discarded ///< discarded by the the parser callback function
};
};
//////////////////////////////////////////
// lexicographical comparison operators //
//////////////////////////////////////////
/// @name lexicographical comparison operators
/// @{
/*!
/*!
@brief comparison operator for JSON types
@brief comparison operator for JSON types
...
@@ -193,51 +192,62 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
...
@@ -193,51 +192,62 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
order[static_cast<std::size_t>(rhs)];
order[static_cast<std::size_t>(rhs)];
}
}
/////////////
// helpers //
/////////////
// alias templates to reduce boilerplate
// alias templates to reduce boilerplate
template
<bool B, typename T = void>
template<bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
using enable_if_t = typename std::enable_if<B, T>::type;
template
<typename T>
template<typename T>
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
// Taken from http://stackoverflow.com/questions/26936640/how-to-implement-is-enum-class-type-trait
// Taken from http://stackoverflow.com/questions/26936640/how-to-implement-is-enum-class-type-trait
template
<typename T>
template<typename T>
using is_unscoped_enum =
using is_unscoped_enum =
std::integral_constant<bool, std::is_convertible<T, int>::value and
std::integral_constant<bool, std::is_convertible<T, int>::value and
std::is_enum<T>::value>;
std::is_enum<T>::value>;
// Implementation of 2 C++17 constructs: conjunction, negation.
/*
// This is needed to avoid evaluating all the traits in a condition
Implementation of 2 C++17 constructs: conjunction, negation. This is needed
//
to avoid evaluating all the traits in a condition
// For example: not std::is_same<void, T>::value and has_value_type<T>::value
// will not compile when T = void (on MSVC at least)
For example: not std::is_same<void, T>::value and has_value_type<T>::value
// Whereas conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value
will not compile when T = void (on MSVC at least). Whereas
// will stop evaluating if negation<...>::value == false
conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
//
stop evaluating if negation<...>::value == false
// Please note that those constructs must be used with caution, since symbols can
// become very long quickly (which can slow down compilation and cause MSVC internal compiler errors)
Please note that those constructs must be used with caution, since symbols can
// Only use it when you have too (see example ahead)
become very long quickly (which can slow down compilation and cause MSVC
template <class...> struct conjunction : std::true_type {};
internal compiler errors). Only use it when you have to (see example ahead).
template <class B1> struct conjunction<B1> : B1 {};
*/
template <class B1, class... Bn>
template<class...> struct conjunction : std::true_type {};
struct conjunction<B1, Bn...>
template<class B1> struct conjunction<B1> : B1 {};
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
template<class B1, class... Bn>
struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
template
<class B> struct negation : std::integral_constant < bool, !B::value > {};
template<class B> struct negation : std::integral_constant < bool, !B::value > {};
// dispatch utility (taken from ranges-v3)
// dispatch utility (taken from ranges-v3)
template <unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<> struct priority_tag<0> {};
template <> struct priority_tag<0> {};
//////////////////
// constructors //
//////////////////
// This is an experiment. I need this to move constructors out of basic_json.
// This is an experiment. I need this to move constructors out of basic_json.
// I'm sure there is a better way, but this might need a big basic_json refactoring
// I'm sure there is a better way, but this might need a big basic_json
template <value_t> struct external_constructor;
// refactoring
template<value_t> struct external_constructor;
template
<>
template<>
struct external_constructor<value_t::boolean>
struct external_constructor<value_t::boolean>
{
{
template
<typename BasicJsonType>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
{
{
j.m_type = value_t::boolean;
j.m_type = value_t::boolean;
...
@@ -246,10 +256,10 @@ struct external_constructor<value_t::boolean>
...
@@ -246,10 +256,10 @@ struct external_constructor<value_t::boolean>
}
}
};
};
template
<>
template<>
struct external_constructor<value_t::string>
struct external_constructor<value_t::string>
{
{
template
<typename BasicJsonType>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
{
{
j.m_type = value_t::string;
j.m_type = value_t::string;
...
@@ -258,15 +268,17 @@ struct external_constructor<value_t::string>
...
@@ -258,15 +268,17 @@ struct external_constructor<value_t::string>
}
}
};
};
template
<>
template<>
struct external_constructor<value_t::number_float>
struct external_constructor<value_t::number_float>
{
{
template
<typename BasicJsonType>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
{
{
// replace infinity and NAN by null
// replace infinity and NAN by null
if (not std::isfinite(val))
if (not std::isfinite(val))
{
j = BasicJsonType{};
j = BasicJsonType{};
}
else
else
{
{
j.m_type = value_t::number_float;
j.m_type = value_t::number_float;
...
@@ -276,10 +288,10 @@ struct external_constructor<value_t::number_float>
...
@@ -276,10 +288,10 @@ struct external_constructor<value_t::number_float>
}
}
};
};
template
<>
template<>
struct external_constructor<value_t::number_unsigned>
struct external_constructor<value_t::number_unsigned>
{
{
template
<typename BasicJsonType>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
{
{
j.m_type = value_t::number_unsigned;
j.m_type = value_t::number_unsigned;
...
@@ -288,10 +300,10 @@ struct external_constructor<value_t::number_unsigned>
...
@@ -288,10 +300,10 @@ struct external_constructor<value_t::number_unsigned>
}
}
};
};
template
<>
template<>
struct external_constructor<value_t::number_integer>
struct external_constructor<value_t::number_integer>
{
{
template
<typename BasicJsonType>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
{
{
j.m_type = value_t::number_integer;
j.m_type = value_t::number_integer;
...
@@ -300,10 +312,10 @@ struct external_constructor<value_t::number_integer>
...
@@ -300,10 +312,10 @@ struct external_constructor<value_t::number_integer>
}
}
};
};
template
<>
template<>
struct external_constructor<value_t::array>
struct external_constructor<value_t::array>
{
{
template
<typename BasicJsonType>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
{
{
j.m_type = value_t::array;
j.m_type = value_t::array;
...
@@ -311,25 +323,24 @@ struct external_constructor<value_t::array>
...
@@ -311,25 +323,24 @@ struct external_constructor<value_t::array>
j.assert_invariant();
j.assert_invariant();
}
}
template
<typename BasicJsonType, typename CompatibleArrayType,
template<typename BasicJsonType, typename CompatibleArrayType,
enable_if_t<not std::is_same<CompatibleArrayType,
enable_if_t<not std::is_same<CompatibleArrayType,
typename BasicJsonType::array_t>::value,
typename BasicJsonType::array_t>::value,
int> = 0>
int> = 0>
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
{
{
using std::begin;
using std::begin;
using std::end;
using std::end;
j.m_type = value_t::array;
j.m_type = value_t::array;
j.m_value.array =
j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
j.assert_invariant();
j.assert_invariant();
}
}
};
};
template
<>
template<>
struct external_constructor<value_t::object>
struct external_constructor<value_t::object>
{
{
template
<typename BasicJsonType>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
{
{
j.m_type = value_t::object;
j.m_type = value_t::object;
...
@@ -337,22 +348,26 @@ struct external_constructor<value_t::object>
...
@@ -337,22 +348,26 @@ struct external_constructor<value_t::object>
j.assert_invariant();
j.assert_invariant();
}
}
template
<typename BasicJsonType, typename CompatibleObjectType,
template<typename BasicJsonType, typename CompatibleObjectType,
enable_if_t<not std::is_same<CompatibleObjectType,
enable_if_t<not std::is_same<CompatibleObjectType,
typename BasicJsonType::object_t>::value,
typename BasicJsonType::object_t>::value,
int> = 0>
int> = 0>
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
{
{
using std::begin;
using std::begin;
using std::end;
using std::end;
j.m_type = value_t::object;
j.m_type = value_t::object;
j.m_value.object =
j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
j.assert_invariant();
j.assert_invariant();
}
}
};
};
////////////////////////
// has_/is_ functions //
////////////////////////
/*!
/*!
@brief Helper to determine whether there's a key_type for T.
@brief Helper to determine whether there's a key_type for T.
...
@@ -364,9 +379,9 @@ contains a `mapped_type`, whereas `std::vector` fails the test.
...
@@ -364,9 +379,9 @@ contains a `mapped_type`, whereas `std::vector` fails the test.
@since version 1.0.0, overworked in version 2.0.6
@since version 1.0.0, overworked in version 2.0.6
*/
*/
#define NLOHMANN_JSON_HAS_HELPER(type) \
#define NLOHMANN_JSON_HAS_HELPER(type) \
template
<typename T> struct has_##type {
\
template
<typename T> struct has_##type {
\
private: \
private: \
template
<typename U, typename = typename U::type>
\
template
<typename U, typename = typename U::type>
\
static int detect(U &&); \
static int detect(U &&); \
static void detect(...); \
static void detect(...); \
public: \
public: \
...
@@ -381,10 +396,10 @@ NLOHMANN_JSON_HAS_HELPER(iterator);
...
@@ -381,10 +396,10 @@ NLOHMANN_JSON_HAS_HELPER(iterator);
#undef NLOHMANN_JSON_HAS_HELPER
#undef NLOHMANN_JSON_HAS_HELPER
template
<bool B, class RealType, class CompatibleObjectType>
template<bool B, class RealType, class CompatibleObjectType>
struct is_compatible_object_type_impl : std::false_type {};
struct is_compatible_object_type_impl : std::false_type {};
template
<class RealType, class CompatibleObjectType>
template<class RealType, class CompatibleObjectType>
struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
{
{
static constexpr auto value =
static constexpr auto value =
...
@@ -404,7 +419,7 @@ struct is_compatible_object_type
...
@@ -404,7 +419,7 @@ struct is_compatible_object_type
typename BasicJsonType::object_t, CompatibleObjectType >::value;
typename BasicJsonType::object_t, CompatibleObjectType >::value;
};
};
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
struct is_basic_json_nested_type
struct is_basic_json_nested_type
{
{
static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
...
@@ -414,11 +429,9 @@ struct is_basic_json_nested_type
...
@@ -414,11 +429,9 @@ struct is_basic_json_nested_type
std::is_same<T, typename BasicJsonType::json_pointer>::value;
std::is_same<T, typename BasicJsonType::json_pointer>::value;
};
};
template
<class BasicJsonType, class CompatibleArrayType>
template<class BasicJsonType, class CompatibleArrayType>
struct is_compatible_array_type
struct is_compatible_array_type
{
{
// TODO concept Container?
// this might not make VS happy
static auto constexpr value =
static auto constexpr value =
conjunction<negation<std::is_same<void, CompatibleArrayType>>,
conjunction<negation<std::is_same<void, CompatibleArrayType>>,
negation<is_compatible_object_type<
negation<is_compatible_object_type<
...
@@ -430,10 +443,10 @@ struct is_compatible_array_type
...
@@ -430,10 +443,10 @@ struct is_compatible_array_type
has_iterator<CompatibleArrayType>>::value;
has_iterator<CompatibleArrayType>>::value;
};
};
template
<bool, typename, typename>
template<bool, typename, typename>
struct is_compatible_integer_type_impl : std::false_type {};
struct is_compatible_integer_type_impl : std::false_type {};
template
<typename RealIntegerType, typename CompatibleNumberIntegerType>
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
{
{
// is there an assert somewhere on overflows?
// is there an assert somewhere on overflows?
...
@@ -447,24 +460,25 @@ struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIn
...
@@ -447,24 +460,25 @@ struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIn
RealLimits::is_signed == CompatibleLimits::is_signed;
RealLimits::is_signed == CompatibleLimits::is_signed;
};
};
template
<typename RealIntegerType, typename CompatibleNumberIntegerType>
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type
struct is_compatible_integer_type
{
{
static constexpr auto
static constexpr auto
value =
value =
is_compatible_integer_type_impl <
is_compatible_integer_type_impl <
std::is_integral<CompatibleNumberIntegerType>::value and
std::is_integral<CompatibleNumberIntegerType>::value and
not std::is_same<bool, CompatibleNumberIntegerType>::value,
not std::is_same<bool, CompatibleNumberIntegerType>::value,
RealIntegerType, CompatibleNumberIntegerType > ::value;
RealIntegerType, CompatibleNumberIntegerType > ::value;
};
};
// This trait checks if JSONSerializer<T>::from_json(json const&, udt&) exists
// This trait checks if JSONSerializer<T>::from_json(json const&, udt&) exists
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
struct has_from_json
struct has_from_json
{
{
private:
private:
// also check the return type of from_json
// also check the return type of from_json
template
<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
static int detect(U&&);
static int detect(U&&);
static void detect(...);
static void detect(...);
...
@@ -475,7 +489,7 @@ struct has_from_json
...
@@ -475,7 +489,7 @@ struct has_from_json
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
// this overload is used for non-default-constructible user-defined-types
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
struct has_non_default_from_json
struct has_non_default_from_json
{
{
private:
private:
...
@@ -492,12 +506,12 @@ struct has_non_default_from_json
...
@@ -492,12 +506,12 @@ struct has_non_default_from_json
};
};
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
struct has_to_json
struct has_to_json
{
{
private:
private:
template
<typename U, typename = decltype(uncvref_t<U>::to_json(
template<typename U, typename = decltype(uncvref_t<U>::to_json(
std::declval<BasicJsonType&>(), std::declval<T>()))>
std::declval<BasicJsonType&>(), std::declval<T>()))>
static int detect(U&&);
static int detect(U&&);
static void detect(...);
static void detect(...);
...
@@ -506,58 +520,33 @@ struct has_to_json
...
@@ -506,58 +520,33 @@ struct has_to_json
std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
};
};
// overloads for basic_json template parameters
template <typename BasicJsonType, typename ArithmeticType,
/////////////
enable_if_t<std::is_arithmetic<ArithmeticType>::value and
// to_json //
not std::is_same<ArithmeticType,
/////////////
typename BasicJsonType::boolean_t>::value,
int> = 0>
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
{
switch (static_cast<value_t>(j))
{
case value_t::number_unsigned:
val = static_cast<ArithmeticType>(
*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
break;
case value_t::number_integer:
val = static_cast<ArithmeticType>(
*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
break;
case value_t::number_float:
val = static_cast<ArithmeticType>(
*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
break;
default:
JSON_THROW(
std::domain_error("type must be number, but is " + j.type_name()));
}
}
template
<typename BasicJsonType>
template<typename BasicJsonType>
void to_json(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
void to_json(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
{
{
external_constructor<value_t::boolean>::construct(j, b);
external_constructor<value_t::boolean>::construct(j, b);
}
}
template
<typename BasicJsonType, typename CompatibleString,
template<typename BasicJsonType, typename CompatibleString,
enable_if_t<std::is_constructible<typename BasicJsonType::string_t,
enable_if_t<std::is_constructible<typename BasicJsonType::string_t,
CompatibleString>::value,
CompatibleString>::value,
int> = 0>
int> = 0>
void to_json(BasicJsonType& j, const CompatibleString& s)
void to_json(BasicJsonType& j, const CompatibleString& s)
{
{
external_constructor<value_t::string>::construct(j, s);
external_constructor<value_t::string>::construct(j, s);
}
}
template
<typename BasicJsonType, typename FloatType,
template<typename BasicJsonType, typename FloatType,
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
void to_json(BasicJsonType& j, FloatType val) noexcept
void to_json(BasicJsonType& j, FloatType val) noexcept
{
{
external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
}
}
template <
template <
typename BasicJsonType, typename CompatibleNumberUnsignedType,
typename BasicJsonType, typename CompatibleNumberUnsignedType,
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t,
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t,
...
@@ -578,8 +567,8 @@ void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
...
@@ -578,8 +567,8 @@ void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
}
}
template
<typename BasicJsonType, typename UnscopedEnumType,
template<typename BasicJsonType, typename UnscopedEnumType,
enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>
enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>
void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept
void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept
{
{
external_constructor<value_t::number_integer>::construct(j, e);
external_constructor<value_t::number_integer>::construct(j, e);
...
@@ -605,7 +594,48 @@ void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
...
@@ -605,7 +594,48 @@ void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
external_constructor<value_t::object>::construct(j, arr);
external_constructor<value_t::object>::construct(j, arr);
}
}
template <typename BasicJsonType>
///////////////
// from_json //
///////////////
// overloads for basic_json template parameters
template<typename BasicJsonType, typename ArithmeticType,
enable_if_t<std::is_arithmetic<ArithmeticType>::value and
not std::is_same<ArithmeticType,
typename BasicJsonType::boolean_t>::value,
int> = 0>
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
{
switch (static_cast<value_t>(j))
{
case value_t::number_unsigned:
{
val = static_cast<ArithmeticType>(
*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
break;
}
case value_t::number_integer:
{
val = static_cast<ArithmeticType>(
*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
break;
}
case value_t::number_float:
{
val = static_cast<ArithmeticType>(
*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
break;
}
default:
{
JSON_THROW(
std::domain_error("type must be number, but is " + j.type_name()));
}
}
}
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
{
{
if (!j.is_boolean())
if (!j.is_boolean())
...
@@ -615,7 +645,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
...
@@ -615,7 +645,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
}
}
template
<typename BasicJsonType>
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{
{
if (!j.is_string())
if (!j.is_string())
...
@@ -625,35 +655,35 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
...
@@ -625,35 +655,35 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
}
template
<typename BasicJsonType>
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
{
{
get_arithmetic_value(j, val);
get_arithmetic_value(j, val);
}
}
template
<typename BasicJsonType>
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
{
{
get_arithmetic_value(j, val);
get_arithmetic_value(j, val);
}
}
template
<typename BasicJsonType>
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
{
{
get_arithmetic_value(j, val);
get_arithmetic_value(j, val);
}
}
template
<typename BasicJsonType, typename UnscopedEnumType,
template<typename BasicJsonType, typename UnscopedEnumType,
enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>
enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>
void from_json(const
BasicJsonType& j, UnscopedEnumType& e)
void from_json(const BasicJsonType& j, UnscopedEnumType& e)
{
{
typename std::underlying_type<UnscopedEnumType>::type val = e;
typename std::underlying_type<UnscopedEnumType>::type val = e;
get_arithmetic_value(j, val);
get_arithmetic_value(j, val);
e = static_cast<UnscopedEnumType>(val);
e = static_cast<UnscopedEnumType>(val);
}
}
template
<typename BasicJsonType>
template<typename BasicJsonType>
void from_json(const
BasicJsonType& j, typename BasicJsonType::array_t& arr)
void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
{
{
if (!j.is_array())
if (!j.is_array())
{
{
...
@@ -662,8 +692,9 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
...
@@ -662,8 +692,9 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
}
}
// forward_list doesn't have an insert method, TODO find a way to avoid including forward_list
// forward_list doesn't have an insert method
template <typename BasicJsonType, typename T, typename Allocator>
// TODO find a way to avoid including forward_list
template<typename BasicJsonType, typename T, typename Allocator>
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{
{
// do not perform the check when user wants to retrieve jsons
// do not perform the check when user wants to retrieve jsons
...
@@ -685,23 +716,23 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
...
@@ -685,23 +716,23 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
}
}
}
}
template
<typename BasicJsonType, typename CompatibleArrayType>
template<typename BasicJsonType, typename CompatibleArrayType>
void from_json_array_impl(const
BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>)
void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>)
{
{
using std::begin;
using std::begin;
using std::end;
using std::end;
std::transform(
std::transform(
j.begin(), j.end(),
j.begin(), j.end(), std::inserter(arr, end(arr)), [](const
BasicJsonType & i)
std::inserter(arr, end(arr)), [](const
BasicJsonType & i)
{
{
// get<BasicJsonType>() returns *this, this won't call a from_json
method when
// get<BasicJsonType>() returns *this, this won't call a from_json
// value_type is BasicJsonType
//
method when
value_type is BasicJsonType
return i.template get<typename CompatibleArrayType::value_type>();
return i.template get<typename CompatibleArrayType::value_type>();
});
});
}
}
template
<typename BasicJsonType, typename CompatibleArrayType>
template<typename BasicJsonType, typename CompatibleArrayType>
auto from_json_array_impl(const
BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>)
auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>)
-> decltype(
-> decltype(
arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
void())
void())
...
@@ -711,26 +742,24 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, pri
...
@@ -711,26 +742,24 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, pri
arr.reserve(j.size());
arr.reserve(j.size());
std::transform(
std::transform(
j.begin(), j.end(), std::inserter(arr, end(arr)), [](const
BasicJsonType & i)
j.begin(), j.end(), std::inserter(arr, end(arr)), [](const BasicJsonType & i)
{
{
// get<BasicJsonType>() returns *this, this won't call a from_json
method when
// get<BasicJsonType>() returns *this, this won't call a from_json
// value_type is BasicJsonType
//
method when
value_type is BasicJsonType
return i.template get<typename CompatibleArrayType::value_type>();
return i.template get<typename CompatibleArrayType::value_type>();
});
});
}
}
template <
template<typename BasicJsonType, typename CompatibleArrayType,
typename BasicJsonType, typename CompatibleArrayType,
enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>
not std::is_same<typename BasicJsonType::array_t,
void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
CompatibleArrayType>::value,
int> = 0 >
void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
{
{
if (j.is_null())
if (j.is_null())
{
{
JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
}
}
// when T == BasicJsonType, do not check if value_t is correct
// when T == BasicJsonType, do not check if value_t is correct
if (not std::is_same<typename CompatibleArrayType::value_type, BasicJsonType>::value)
if (not std::is_same<typename CompatibleArrayType::value_type, BasicJsonType>::value)
{
{
...
@@ -742,12 +771,9 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
...
@@ -742,12 +771,9 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
from_json_array_impl(j, arr, priority_tag<1> {});
from_json_array_impl(j, arr, priority_tag<1> {});
}
}
template<typename BasicJsonType, typename CompatibleObjectType,
template <
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
typename BasicJsonType, typename CompatibleObjectType,
void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
int> = 0 >
void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
{
{
if (!j.is_object())
if (!j.is_object())
{
{
...
@@ -766,63 +792,52 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
...
@@ -766,63 +792,52 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
//
//
// note: Is it really necessary to provide explicit overloads for boolean_t etc..
// note: Is it really necessary to provide explicit overloads for boolean_t etc..
// in case of a custom BooleanType which is not an arithmetic type?
// in case of a custom BooleanType which is not an arithmetic type?
template <
template<typename BasicJsonType, typename ArithmeticType,
typename BasicJsonType, typename ArithmeticType,
enable_if_t <
enable_if_t <
std::is_arithmetic<ArithmeticType>::value and
std::is_arithmetic<ArithmeticType>::value and
not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
not std::is_same<ArithmeticType,
not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
typename BasicJsonType::number_unsigned_t>::value and
not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
not std::is_same<ArithmeticType,
not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
typename BasicJsonType::number_integer_t>::value and
int> = 0>
not std::is_same<ArithmeticType,
typename BasicJsonType::number_float_t>::value and
not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
int > = 0 >
void from_json(const BasicJsonType& j, ArithmeticType& val)
void from_json(const BasicJsonType& j, ArithmeticType& val)
{
{
switch (static_cast<value_t>(j))
switch (static_cast<value_t>(j))
{
{
case value_t::number_unsigned:
case value_t::number_unsigned:
val = static_cast<ArithmeticType>(
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
break;
break;
case value_t::number_integer:
case value_t::number_integer:
val = static_cast<ArithmeticType>(
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
break;
break;
case value_t::number_float:
case value_t::number_float:
val = static_cast<ArithmeticType>(
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
break;
break;
case value_t::boolean:
case value_t::boolean:
val = static_cast<ArithmeticType>(
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
break;
break;
default:
default:
JSON_THROW(
JSON_THROW(std::domain_error("type must be number, but is " + j.type_name()));
std::domain_error("type must be number, but is " + j.type_name()));
}
}
}
}
struct to_json_fn
struct to_json_fn
{
{
template <typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
auto call(BasicJsonType& j, T&& val, priority_tag<1>) const
auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
noexcept(noexcept(to_json(j, std::forward<T>(val))))
-> decltype(to_json(j, std::forward<T>(val)), void())
-> decltype(to_json(j, std::forward<T>(val)),
void())
{
{
return to_json(j, std::forward<T>(val));
return to_json(j, std::forward<T>(val));
}
}
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept
void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept
{
{
static_assert(sizeof(BasicJsonType) == 0, "to_json method in T's namespace can not be called");
static_assert(sizeof(BasicJsonType) == 0, "to_json method in T's namespace can not be called");
}
}
public:
public:
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
void operator()(BasicJsonType& j, T&& val) const
void operator()(BasicJsonType& j, T&& val) const
noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
{
{
...
@@ -833,23 +848,23 @@ struct to_json_fn
...
@@ -833,23 +848,23 @@ struct to_json_fn
struct from_json_fn
struct from_json_fn
{
{
private:
private:
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
auto call(const
BasicJsonType& j, T& val, priority_tag<1>) const
auto call(const BasicJsonType& j, T& val, priority_tag<1>) const
noexcept(noexcept(from_json(j, val)))
noexcept(noexcept(from_json(j, val)))
-> decltype(from_json(j, val), void())
-> decltype(from_json(j, val), void())
{
{
return from_json(j, val);
return from_json(j, val);
}
}
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept
void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept
{
{
static_assert(sizeof(BasicJsonType) == 0, "from_json method in T's namespace can not be called");
static_assert(sizeof(BasicJsonType) == 0, "from_json method in T's namespace can not be called");
}
}
public:
public:
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
void operator()(const
BasicJsonType& j, T& val) const
void operator()(const BasicJsonType& j, T& val) const
noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
{
{
return call(j, val, priority_tag<1> {});
return call(j, val, priority_tag<1> {});
...
@@ -857,15 +872,16 @@ struct from_json_fn
...
@@ -857,15 +872,16 @@ struct from_json_fn
};
};
// taken from ranges-v3
// taken from ranges-v3
template
<typename T>
template<typename T>
struct static_const
struct static_const
{
{
static constexpr T value{};
static constexpr T value{};
};
};
template
<typename T>
template<typename T>
constexpr T static_const<T>::value;
constexpr T static_const<T>::value;
/*!
/*!
@brief helper class to create locales with decimal point
@brief helper class to create locales with decimal point
...
@@ -885,7 +901,8 @@ struct DecimalSeparator : std::numpunct<char>
...
@@ -885,7 +901,8 @@ struct DecimalSeparator : std::numpunct<char>
return '.';
return '.';
}
}
};
};
}
} // namespace detail
namespace
namespace
{
{
...
@@ -895,16 +912,16 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va
...
@@ -895,16 +912,16 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va
// default JSONSerializer template argument, doesn't care about template argument
// default JSONSerializer template argument, doesn't care about template argument
// will use ADL for serialization
// will use ADL for serialization
template
<typename = void, typename = void>
template<typename = void, typename = void>
struct adl_serializer
struct adl_serializer
{
{
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
static void from_json(BasicJsonType&& j, T& val) noexcept(noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
static void from_json(BasicJsonType&& j, T& val) noexcept(noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
{
{
::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
}
}
template
<typename BasicJsonType, typename T>
template<typename BasicJsonType, typename T>
static void to_json(BasicJsonType& j, T&& val) noexcept(
static void to_json(BasicJsonType& j, T&& val) noexcept(
noexcept(::nlohmann::to_json(j, std::forward<T>(val))))
noexcept(::nlohmann::to_json(j, std::forward<T>(val))))
{
{
...
@@ -912,6 +929,7 @@ struct adl_serializer
...
@@ -912,6 +929,7 @@ struct adl_serializer
}
}
};
};
/*!
/*!
@brief a class to store JSON values
@brief a class to store JSON values
...
@@ -1005,7 +1023,7 @@ template <
...
@@ -1005,7 +1023,7 @@ template <
class basic_json
class basic_json
{
{
private:
private:
template
<detail::value_t> friend struct detail::external_constructor;
template<detail::value_t> friend struct detail::external_constructor;
/// workaround type for MSVC
/// workaround type for MSVC
using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
...
@@ -1017,7 +1035,7 @@ class basic_json
...
@@ -1017,7 +1035,7 @@ class basic_json
template<typename U> class iter_impl;
template<typename U> class iter_impl;
template<typename Base> class json_reverse_iterator;
template<typename Base> class json_reverse_iterator;
class json_pointer;
class json_pointer;
template
<typename T, typename SFINAE>
template<typename T, typename SFINAE>
using json_serializer = JSONSerializer<T, SFINAE>;
using json_serializer = JSONSerializer<T, SFINAE>;
/////////////////////
/////////////////////
...
@@ -1904,13 +1922,13 @@ class basic_json
...
@@ -1904,13 +1922,13 @@ class basic_json
@since version 2.1.0
@since version 2.1.0
*/
*/
template
<typename T, typename U = detail::uncvref_t<T>,
template<typename T, typename U = detail::uncvref_t<T>,
detail::enable_if_t<not std::is_base_of<std::istream, U>::value and
detail::enable_if_t<not std::is_base_of<std::istream, U>::value and
not std::is_same<U, basic_json_t>::value and
not std::is_same<U, basic_json_t>::value and
not detail::is_basic_json_nested_type<
not detail::is_basic_json_nested_type<
basic_json_t, U>::value and
basic_json_t, U>::value and
detail::has_to_json<basic_json, U>::value,
detail::has_to_json<basic_json, U>::value,
int> = 0>
int> = 0>
basic_json(T && val) noexcept(noexcept(JSONSerializer<U>::to_json(
basic_json(T && val) noexcept(noexcept(JSONSerializer<U>::to_json(
std::declval<basic_json_t&>(), std::forward<T>(val))))
std::declval<basic_json_t&>(), std::forward<T>(val))))
{
{
...
@@ -5714,6 +5732,13 @@ class basic_json
...
@@ -5714,6 +5732,13 @@ class basic_json
/// @}
/// @}
public:
public:
//////////////////////////////////////////
// lexicographical comparison operators //
//////////////////////////////////////////
/// @name lexicographical comparison operators
/// @{
/*!
/*!
@brief comparison: equal
@brief comparison: equal
...
@@ -9945,7 +9970,7 @@ class basic_json
...
@@ -9945,7 +9970,7 @@ class basic_json
for (; curptr < m_cursor; curptr++)
for (; curptr < m_cursor; curptr++)
{
{
// quickly skip tests if a digit
// quickly skip tests if a digit
if (*curptr < '0'
|| *
curptr > '9')
if (*curptr < '0'
or*
curptr > '9')
{
{
if (*curptr == '.')
if (*curptr == '.')
{
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment