Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
json
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
json
Commits
be1d3de4
Commit
be1d3de4
authored
Dec 18, 2016
by
Niels Lohmann
Committed by
Théo DELRIEU
Jan 21, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
💄
moved changes to re2c file and ran `make pretty`
parent
aa2679a8
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
731 additions
and
233 deletions
+731
-233
json.hpp
src/json.hpp
+75
-64
json.hpp.re2c
src/json.hpp.re2c
+533
-69
unit-class_lexer.cpp
test/src/unit-class_lexer.cpp
+0
-0
unit-udt.cpp
test/src/unit-udt.cpp
+123
-100
No files found.
src/json.hpp
View file @
be1d3de4
...
@@ -142,7 +142,10 @@ using is_unscoped_enum =
...
@@ -142,7 +142,10 @@ using is_unscoped_enum =
namespace
detail
namespace
detail
{
{
// Very useful construct against boilerplate (more boilerplate needed than in C++17: http://en.cppreference.com/w/cpp/types/void_t)
// Very useful construct against boilerplate (more boilerplate needed than in C++17: http://en.cppreference.com/w/cpp/types/void_t)
template
<
typename
...
>
struct
make_void
{
using
type
=
void
;
};
template
<
typename
...
>
struct
make_void
{
using
type
=
void
;
};
template
<
typename
...
Ts
>
using
void_t
=
typename
make_void
<
Ts
...
>::
type
;
template
<
typename
...
Ts
>
using
void_t
=
typename
make_void
<
Ts
...
>::
type
;
// Implementation of 3 C++17 constructs: conjunction, disjunction, negation.
// Implementation of 3 C++17 constructs: conjunction, disjunction, negation.
...
@@ -160,14 +163,14 @@ template <class...> struct conjunction : std::true_type {};
...
@@ -160,14 +163,14 @@ template <class...> struct conjunction : std::true_type {};
template
<
class
B1
>
struct
conjunction
<
B1
>
:
B1
{};
template
<
class
B1
>
struct
conjunction
<
B1
>
:
B1
{};
template
<
class
B1
,
class
...
Bn
>
template
<
class
B1
,
class
...
Bn
>
struct
conjunction
<
B1
,
Bn
...
>
struct
conjunction
<
B1
,
Bn
...
>
:
conditional_t
<
bool
(
B1
::
value
),
conjunction
<
Bn
...
>
,
B1
>
{};
:
conditional_t
<
bool
(
B1
::
value
),
conjunction
<
Bn
...
>
,
B1
>
{};
template
<
class
B
>
struct
negation
:
std
::
integral_constant
<
bool
,
!
B
::
value
>
{};
template
<
class
B
>
struct
negation
:
std
::
integral_constant
<
bool
,
!
B
::
value
>
{};
template
<
class
...
>
struct
disjunction
:
std
::
false_type
{};
template
<
class
...
>
struct
disjunction
:
std
::
false_type
{};
template
<
class
B1
>
struct
disjunction
<
B1
>
:
B1
{};
template
<
class
B1
>
struct
disjunction
<
B1
>
:
B1
{};
template
<
class
B1
,
class
...
Bn
>
template
<
class
B1
,
class
...
Bn
>
struct
disjunction
<
B1
,
Bn
...
>
struct
disjunction
<
B1
,
Bn
...
>
:
conditional_t
<
bool
(
B1
::
value
),
B1
,
disjunction
<
Bn
...
>>
{};
:
conditional_t
<
bool
(
B1
::
value
),
B1
,
disjunction
<
Bn
...
>>
{};
/*!
/*!
@brief Helper to determine whether there's a key_type for T.
@brief Helper to determine whether there's a key_type for T.
...
@@ -198,7 +201,7 @@ NLOHMANN_JSON_HAS_HELPER(iterator)
...
@@ -198,7 +201,7 @@ 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
>
...
@@ -215,15 +218,15 @@ struct is_compatible_object_type
...
@@ -215,15 +218,15 @@ struct is_compatible_object_type
{
{
// As noted ahead, we need to stop evaluating traits if CompatibleObjectType = void
// As noted ahead, we need to stop evaluating traits if CompatibleObjectType = void
// hence the conjunction
// hence the conjunction
static
auto
constexpr
value
=
is_compatible_object_type_impl
<
static
auto
constexpr
value
=
is_compatible_object_type_impl
<
conjunction
<
negation
<
std
::
is_same
<
void
,
CompatibleObjectType
>>
,
conjunction
<
negation
<
std
::
is_same
<
void
,
CompatibleObjectType
>>
,
has_mapped_type
<
CompatibleObjectType
>
,
has_mapped_type
<
CompatibleObjectType
>
,
has_key_type
<
CompatibleObjectType
>>::
value
,
has_key_type
<
CompatibleObjectType
>>::
value
,
RealType
,
CompatibleObjectType
>::
value
;
RealType
,
CompatibleObjectType
>::
value
;
};
};
template
<
bool
B
,
class
BasicJson
,
class
CompatibleArrayType
>
template
<
bool
B
,
class
BasicJson
,
class
CompatibleArrayType
>
struct
is_compatible_array_type_impl
:
std
::
false_type
{};
struct
is_compatible_array_type_impl
:
std
::
false_type
{};
template
<
class
BasicJson
,
class
CompatibleArrayType
>
template
<
class
BasicJson
,
class
CompatibleArrayType
>
struct
is_compatible_array_type_impl
<
true
,
BasicJson
,
CompatibleArrayType
>
struct
is_compatible_array_type_impl
<
true
,
BasicJson
,
CompatibleArrayType
>
...
@@ -248,16 +251,16 @@ struct is_compatible_array_type
...
@@ -248,16 +251,16 @@ struct is_compatible_array_type
{
{
// the check for CompatibleArrayType = void is done in is_compatible_object_type
// the check for CompatibleArrayType = void is done in is_compatible_object_type
// but we need the conjunction here as well
// but we need the conjunction here as well
static
auto
constexpr
value
=
is_compatible_array_type_impl
<
static
auto
constexpr
value
=
is_compatible_array_type_impl
<
conjunction
<
negation
<
is_compatible_object_type
<
conjunction
<
negation
<
is_compatible_object_type
<
typename
BasicJson
::
object_t
,
CompatibleArrayType
>>
,
typename
BasicJson
::
object_t
,
CompatibleArrayType
>>
,
has_value_type
<
CompatibleArrayType
>
,
has_value_type
<
CompatibleArrayType
>
,
has_iterator
<
CompatibleArrayType
>>::
value
,
has_iterator
<
CompatibleArrayType
>>::
value
,
BasicJson
,
CompatibleArrayType
>::
value
;
BasicJson
,
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
>
...
@@ -275,9 +278,9 @@ struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIn
...
@@ -275,9 +278,9 @@ struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIn
template
<
typename
RealIntegerType
,
typename
CompatibleNumberIntegerType
>
template
<
typename
RealIntegerType
,
typename
CompatibleNumberIntegerType
>
struct
is_compatible_integer_type
struct
is_compatible_integer_type
{
{
static
constexpr
auto
value
=
is_compatible_integer_type_impl
<
static
constexpr
auto
value
=
is_compatible_integer_type_impl
<
std
::
is_arithmetic
<
CompatibleNumberIntegerType
>::
value
,
RealIntegerType
,
std
::
is_arithmetic
<
CompatibleNumberIntegerType
>::
value
,
RealIntegerType
,
CompatibleNumberIntegerType
>::
value
;
CompatibleNumberIntegerType
>::
value
;
};
};
template
<
typename
RealFloat
,
typename
CompatibleFloat
>
template
<
typename
RealFloat
,
typename
CompatibleFloat
>
...
@@ -321,15 +324,15 @@ template <template <typename, typename> class JSONSerializer, typename Json,
...
@@ -321,15 +324,15 @@ template <template <typename, typename> class JSONSerializer, typename Json,
typename
T
>
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
<
Json
>
(),
std
::
declval
<
T
&>
()))
>::
value
>>
std
::
declval
<
Json
>
(),
std
::
declval
<
T
&>
()))
>::
value
>>
static
int
detect
(
U
&&
);
static
int
detect
(
U
&&
);
static
void
detect
(...);
static
void
detect
(...);
public
:
public
:
static
constexpr
bool
value
=
std
::
is_integral
<
decltype
(
static
constexpr
bool
value
=
std
::
is_integral
<
decltype
(
detect
(
std
::
declval
<
JSONSerializer
<
T
,
void
>>
()))
>::
value
;
detect
(
std
::
declval
<
JSONSerializer
<
T
,
void
>>
()))
>::
value
;
};
};
...
@@ -340,13 +343,13 @@ template <template <typename, typename> class JSONSerializer, typename Json,
...
@@ -340,13 +343,13 @@ template <template <typename, typename> class JSONSerializer, typename Json,
typename
T
>
typename
T
>
struct
has_non_default_from_json
struct
has_non_default_from_json
{
{
private
:
private
:
template
<
typename
U
,
typename
=
enable_if_t
<
std
::
is_same
<
T
,
decltype
(
uncvref_t
<
U
>::
from_json
(
std
::
declval
<
Json
>
()))
>::
value
>>
template
<
typename
U
,
typename
=
enable_if_t
<
std
::
is_same
<
T
,
decltype
(
uncvref_t
<
U
>::
from_json
(
std
::
declval
<
Json
>
()))
>::
value
>>
static
int
detect
(
U
&&
);
static
int
detect
(
U
&&
);
static
void
detect
(...);
static
void
detect
(...);
public
:
public
:
static
constexpr
bool
value
=
std
::
is_integral
<
decltype
(
static
constexpr
bool
value
=
std
::
is_integral
<
decltype
(
detect
(
std
::
declval
<
JSONSerializer
<
T
,
void
>>
()))
>::
value
;
detect
(
std
::
declval
<
JSONSerializer
<
T
,
void
>>
()))
>::
value
;
};
};
...
@@ -356,14 +359,14 @@ template <template <typename, typename> class JSONSerializer, typename Json,
...
@@ -356,14 +359,14 @@ template <template <typename, typename> class JSONSerializer, typename Json,
typename
T
>
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
<
Json
&>
(),
std
::
declval
<
T
>
()))
>
std
::
declval
<
Json
&>
(),
std
::
declval
<
T
>
()))
>
static
int
detect
(
U
&&
);
static
int
detect
(
U
&&
);
static
void
detect
(...);
static
void
detect
(...);
public
:
public
:
static
constexpr
bool
value
=
std
::
is_integral
<
decltype
(
static
constexpr
bool
value
=
std
::
is_integral
<
decltype
(
detect
(
std
::
declval
<
JSONSerializer
<
T
,
void
>>
()))
>::
value
;
detect
(
std
::
declval
<
JSONSerializer
<
T
,
void
>>
()))
>::
value
;
};
};
...
@@ -377,7 +380,7 @@ struct to_json_fn
...
@@ -377,7 +380,7 @@ struct to_json_fn
{
{
// is it really useful to mark those as constexpr?
// is it really useful to mark those as constexpr?
template
<
typename
Json
,
typename
T
>
template
<
typename
Json
,
typename
T
>
constexpr
auto
operator
()(
Json
&&
j
,
T
&&
val
)
const
constexpr
auto
operator
()(
Json
&&
j
,
T
&&
val
)
const
noexcept
(
noexcept
(
to_json
(
std
::
forward
<
Json
>
(
j
),
std
::
forward
<
T
>
(
val
))))
noexcept
(
noexcept
(
to_json
(
std
::
forward
<
Json
>
(
j
),
std
::
forward
<
T
>
(
val
))))
->
decltype
(
to_json
(
std
::
forward
<
Json
>
(
j
),
std
::
forward
<
T
>
(
val
)),
->
decltype
(
to_json
(
std
::
forward
<
Json
>
(
j
),
std
::
forward
<
T
>
(
val
)),
void
())
void
())
...
@@ -389,7 +392,7 @@ struct to_json_fn
...
@@ -389,7 +392,7 @@ struct to_json_fn
struct
from_json_fn
struct
from_json_fn
{
{
template
<
typename
Json
,
typename
T
>
template
<
typename
Json
,
typename
T
>
constexpr
auto
operator
()(
Json
&&
j
,
T
&
val
)
const
constexpr
auto
operator
()(
Json
&&
j
,
T
&
val
)
const
noexcept
(
noexcept
(
from_json
(
std
::
forward
<
Json
>
(
j
),
val
)))
noexcept
(
noexcept
(
from_json
(
std
::
forward
<
Json
>
(
j
),
val
)))
->
decltype
(
from_json
(
std
::
forward
<
Json
>
(
j
),
val
),
void
())
->
decltype
(
from_json
(
std
::
forward
<
Json
>
(
j
),
val
),
void
())
{
{
...
@@ -431,8 +434,8 @@ constexpr T static_const<T>::value;
...
@@ -431,8 +434,8 @@ constexpr T static_const<T>::value;
inline
namespace
inline
namespace
{
{
constexpr
auto
const
&
to_json
=
static_const
<
detail
::
to_json_fn
>::
value
;
constexpr
auto
const
&
to_json
=
static_const
<
detail
::
to_json_fn
>::
value
;
constexpr
auto
const
&
from_json
=
static_const
<
detail
::
from_json_fn
>::
value
;
constexpr
auto
const
&
from_json
=
static_const
<
detail
::
from_json_fn
>::
value
;
}
}
// default JSONSerializer template argument, doesn't care about template argument
// default JSONSerializer template argument, doesn't care about template argument
...
@@ -1535,7 +1538,7 @@ class basic_json
...
@@ -1535,7 +1538,7 @@ class basic_json
enable_if_t
<
detail
::
is_compatible_object_type
<
enable_if_t
<
detail
::
is_compatible_object_type
<
object_t
,
CompatibleObjectType
>::
value
,
object_t
,
CompatibleObjectType
>::
value
,
int
>
=
0
>
int
>
=
0
>
basic_json
(
const
CompatibleObjectType
&
val
)
:
m_type
(
value_t
::
object
)
basic_json
(
const
CompatibleObjectType
&
val
)
:
m_type
(
value_t
::
object
)
{
{
using
std
::
begin
;
using
std
::
begin
;
using
std
::
end
;
using
std
::
end
;
...
@@ -1598,7 +1601,7 @@ class basic_json
...
@@ -1598,7 +1601,7 @@ class basic_json
enable_if_t
<
detail
::
is_compatible_array_type
<
enable_if_t
<
detail
::
is_compatible_array_type
<
basic_json_t
,
CompatibleArrayType
>::
value
,
basic_json_t
,
CompatibleArrayType
>::
value
,
int
>
=
0
>
int
>
=
0
>
basic_json
(
const
CompatibleArrayType
&
val
)
:
m_type
(
value_t
::
array
)
basic_json
(
const
CompatibleArrayType
&
val
)
:
m_type
(
value_t
::
array
)
{
{
using
std
::
begin
;
using
std
::
begin
;
using
std
::
end
;
using
std
::
end
;
...
@@ -1622,8 +1625,8 @@ class basic_json
...
@@ -1622,8 +1625,8 @@ class basic_json
uncvref_t
<
T
>
,
basic_json_t
>>
,
uncvref_t
<
T
>
,
basic_json_t
>>
,
detail
::
has_to_json
<
JSONSerializer
,
basic_json
,
detail
::
has_to_json
<
JSONSerializer
,
basic_json
,
uncvref_t
<
T
>>>::
value
,
uncvref_t
<
T
>>>::
value
,
int
>
=
0
>
int
>
=
0
>
basic_json
(
T
&&
val
)
basic_json
(
T
&&
val
)
{
{
JSONSerializer
<
uncvref_t
<
T
>>::
to_json
(
*
this
,
std
::
forward
<
T
>
(
val
));
JSONSerializer
<
uncvref_t
<
T
>>::
to_json
(
*
this
,
std
::
forward
<
T
>
(
val
));
}
}
...
@@ -1828,10 +1831,11 @@ class basic_json
...
@@ -1828,10 +1831,11 @@ class basic_json
typename
CompatibleNumberIntegerType
,
typename
CompatibleNumberIntegerType
,
enable_if_t
<
detail
::
is_compatible_integer_type
<
enable_if_t
<
detail
::
is_compatible_integer_type
<
number_integer_t
,
CompatibleNumberIntegerType
>::
value
,
number_integer_t
,
CompatibleNumberIntegerType
>::
value
,
int
>
=
0
>
int
>
=
0
>
basic_json
(
const
CompatibleNumberIntegerType
val
)
noexcept
basic_json
(
const
CompatibleNumberIntegerType
val
)
noexcept
:
m_type
(
value_t
::
number_integer
),
:
m_type
(
value_t
::
number_integer
),
m_value
(
static_cast
<
number_integer_t
>
(
val
))
{
m_value
(
static_cast
<
number_integer_t
>
(
val
))
{
assert_invariant
();
assert_invariant
();
}
}
...
@@ -1885,10 +1889,11 @@ class basic_json
...
@@ -1885,10 +1889,11 @@ class basic_json
typename
CompatibleNumberUnsignedType
,
typename
CompatibleNumberUnsignedType
,
enable_if_t
<
detail
::
is_compatible_integer_type
<
enable_if_t
<
detail
::
is_compatible_integer_type
<
number_unsigned_t
,
CompatibleNumberUnsignedType
>::
value
,
number_unsigned_t
,
CompatibleNumberUnsignedType
>::
value
,
int
>
=
0
>
int
>
=
0
>
basic_json
(
const
CompatibleNumberUnsignedType
val
)
noexcept
basic_json
(
const
CompatibleNumberUnsignedType
val
)
noexcept
:
m_type
(
value_t
::
number_unsigned
),
:
m_type
(
value_t
::
number_unsigned
),
m_value
(
static_cast
<
number_unsigned_t
>
(
val
))
{
m_value
(
static_cast
<
number_unsigned_t
>
(
val
))
{
assert_invariant
();
assert_invariant
();
}
}
...
@@ -2521,7 +2526,7 @@ class basic_json
...
@@ -2521,7 +2526,7 @@ class basic_json
template
<
typename
T
,
enable_if_t
<
not
detail
::
is_compatible_basic_json_type
<
template
<
typename
T
,
enable_if_t
<
not
detail
::
is_compatible_basic_json_type
<
uncvref_t
<
T
>
,
basic_json_t
>::
value
and
uncvref_t
<
T
>
,
basic_json_t
>::
value
and
detail
::
has_to_json
<
JSONSerializer
,
basic_json_t
,
uncvref_t
<
T
>>::
value
>>
detail
::
has_to_json
<
JSONSerializer
,
basic_json_t
,
uncvref_t
<
T
>>::
value
>>
reference
&
operator
=
(
T
&&
val
)
noexcept
(
std
::
is_nothrow_constructible
<
basic_json_t
,
uncvref_t
<
T
>>::
value
and
reference
&
operator
=
(
T
&&
val
)
noexcept
(
std
::
is_nothrow_constructible
<
basic_json_t
,
uncvref_t
<
T
>>::
value
and
std
::
is_nothrow_move_assignable
<
uncvref_t
<
T
>>::
value
)
std
::
is_nothrow_move_assignable
<
uncvref_t
<
T
>>::
value
)
{
{
static_assert
(
sizeof
(
T
)
==
0
,
""
);
static_assert
(
sizeof
(
T
)
==
0
,
""
);
...
@@ -2544,32 +2549,38 @@ class basic_json
...
@@ -2544,32 +2549,38 @@ class basic_json
@since version 1.0.0
@since version 1.0.0
*/
*/
~
basic_json
()
{
~
basic_json
()
{
assert_invariant
();
assert_invariant
();
switch
(
m_type
)
{
switch
(
m_type
)
case
value_t
:
:
object
:
{
{
case
value_t
:
:
object
:
{
AllocatorType
<
object_t
>
alloc
;
AllocatorType
<
object_t
>
alloc
;
alloc
.
destroy
(
m_value
.
object
);
alloc
.
destroy
(
m_value
.
object
);
alloc
.
deallocate
(
m_value
.
object
,
1
);
alloc
.
deallocate
(
m_value
.
object
,
1
);
break
;
break
;
}
}
case
value_t
:
:
array
:
{
case
value_t
:
:
array
:
{
AllocatorType
<
array_t
>
alloc
;
AllocatorType
<
array_t
>
alloc
;
alloc
.
destroy
(
m_value
.
array
);
alloc
.
destroy
(
m_value
.
array
);
alloc
.
deallocate
(
m_value
.
array
,
1
);
alloc
.
deallocate
(
m_value
.
array
,
1
);
break
;
break
;
}
}
case
value_t
:
:
string
:
{
case
value_t
:
:
string
:
{
AllocatorType
<
string_t
>
alloc
;
AllocatorType
<
string_t
>
alloc
;
alloc
.
destroy
(
m_value
.
string
);
alloc
.
destroy
(
m_value
.
string
);
alloc
.
deallocate
(
m_value
.
string
,
1
);
alloc
.
deallocate
(
m_value
.
string
,
1
);
break
;
break
;
}
}
default
:
{
default
:
{
// all other types need no specific destructor
// all other types need no specific destructor
break
;
break
;
}
}
...
@@ -3025,15 +3036,15 @@ class basic_json
...
@@ -3025,15 +3036,15 @@ class basic_json
/// get an array (explicit)
/// get an array (explicit)
template
<
template
<
class
T
,
class
T
,
typename
std
::
enable_if
<
typename
std
::
enable_if
<
std
::
is_convertible
<
basic_json_t
,
typename
T
::
value_type
>::
value
and
std
::
is_convertible
<
basic_json_t
,
typename
T
::
value_type
>::
value
and
not
std
::
is_same
<
basic_json_t
,
not
std
::
is_same
<
basic_json_t
,
typename
T
::
value_type
>::
value
and
typename
T
::
value_type
>::
value
and
not
std
::
is_arithmetic
<
T
>::
value
and
not
std
::
is_arithmetic
<
T
>::
value
and
not
std
::
is_convertible
<
std
::
string
,
T
>::
value
and
not
std
::
is_convertible
<
std
::
string
,
T
>::
value
and
not
detail
::
has_mapped_type
<
T
>::
value
,
not
detail
::
has_mapped_type
<
T
>::
value
,
int
>::
type
=
0
>
int
>::
type
=
0
>
T
get_impl
(
T
*
)
const
T
get_impl
(
T
*
)
const
{
{
if
(
is_array
())
if
(
is_array
())
{
{
...
@@ -3305,9 +3316,9 @@ class basic_json
...
@@ -3305,9 +3316,9 @@ class basic_json
template
<
typename
ValueType
,
template
<
typename
ValueType
,
enable_if_t
<
not
std
::
is_pointer
<
ValueType
>::
value
,
int
>
=
0
>
enable_if_t
<
not
std
::
is_pointer
<
ValueType
>::
value
,
int
>
=
0
>
auto
get
()
const
auto
get
()
const
->
decltype
(
this
->
get_impl
(
static_cast
<
ValueType
*>
(
nullptr
)))
->
decltype
(
this
->
get_impl
(
static_cast
<
ValueType
*>
(
nullptr
)))
{
{
return
get_impl
(
static_cast
<
ValueType
*>
(
nullptr
));
return
get_impl
(
static_cast
<
ValueType
*>
(
nullptr
));
}
}
template
<
template
<
...
@@ -3316,11 +3327,11 @@ class basic_json
...
@@ -3316,11 +3327,11 @@ class basic_json
uncvref_t
<
T
>
,
basic_json_t
>>
,
uncvref_t
<
T
>
,
basic_json_t
>>
,
detail
::
has_from_json
<
JSONSerializer
,
basic_json_t
,
detail
::
has_from_json
<
JSONSerializer
,
basic_json_t
,
uncvref_t
<
T
>>>::
value
,
uncvref_t
<
T
>>>::
value
,
int
>
=
0
>
int
>
=
0
>
auto
get
()
const
->
uncvref_t
<
T
>
auto
get
()
const
->
uncvref_t
<
T
>
{
{
using
type
=
uncvref_t
<
T
>
;
using
type
=
uncvref_t
<
T
>
;
static_assert
(
std
::
is_default_constructible
<
type
>::
value
&&
static_assert
(
std
::
is_default_constructible
<
type
>::
value
&&
std
::
is_copy_constructible
<
type
>::
value
,
std
::
is_copy_constructible
<
type
>::
value
,
"user-defined types must be DefaultConstructible and "
"user-defined types must be DefaultConstructible and "
"CopyConstructible when used with get"
);
"CopyConstructible when used with get"
);
...
@@ -3336,7 +3347,7 @@ class basic_json
...
@@ -3336,7 +3347,7 @@ class basic_json
uncvref_t
<
T
>
,
basic_json_t
>>
,
uncvref_t
<
T
>
,
basic_json_t
>>
,
detail
::
has_non_default_from_json
<
JSONSerializer
,
basic_json_t
,
detail
::
has_non_default_from_json
<
JSONSerializer
,
basic_json_t
,
uncvref_t
<
T
>>>::
value
,
uncvref_t
<
T
>>>::
value
,
short
>
=
0
>
short
>
=
0
>
T
get
()
const
T
get
()
const
{
{
return
JSONSerializer
<
T
>::
from_json
(
*
this
);
return
JSONSerializer
<
T
>::
from_json
(
*
this
);
...
@@ -12685,25 +12696,25 @@ using json = basic_json<>;
...
@@ -12685,25 +12696,25 @@ using json = basic_json<>;
// specialization of std::swap, and std::hash
// specialization of std::swap, and std::hash
namespace
std
namespace
std
{
{
/*!
/*!
@brief exchanges the values of two JSON objects
@brief exchanges the values of two JSON objects
@since version 1.0.0
@since version 1.0.0
*/
*/
template
<>
template
<>
inline
void
swap
(
nlohmann
::
json
&
j1
,
inline
void
swap
(
nlohmann
::
json
&
j1
,
nlohmann
::
json
&
j2
)
noexcept
(
nlohmann
::
json
&
j2
)
noexcept
(
is_nothrow_move_constructible
<
nlohmann
::
json
>::
value
and
is_nothrow_move_constructible
<
nlohmann
::
json
>::
value
and
is_nothrow_move_assignable
<
nlohmann
::
json
>::
value
is_nothrow_move_assignable
<
nlohmann
::
json
>::
value
)
)
{
{
j1
.
swap
(
j2
);
j1
.
swap
(
j2
);
}
}
/// hash value for JSON objects
/// hash value for JSON objects
template
<>
template
<>
struct
hash
<
nlohmann
::
json
>
struct
hash
<
nlohmann
::
json
>
{
{
/*!
/*!
@brief return a hash value for a JSON object
@brief return a hash value for a JSON object
...
@@ -12715,7 +12726,7 @@ struct hash<nlohmann::json>
...
@@ -12715,7 +12726,7 @@ struct hash<nlohmann::json>
const
auto
&
h
=
hash
<
nlohmann
::
json
::
string_t
>
();
const
auto
&
h
=
hash
<
nlohmann
::
json
::
string_t
>
();
return
h
(
j
.
dump
());
return
h
(
j
.
dump
());
}
}
};
};
}
// namespace std
}
// namespace std
/*!
/*!
...
...
src/json.hpp.re2c
View file @
be1d3de4
...
@@ -106,38 +106,356 @@ SOFTWARE.
...
@@ -106,38 +106,356 @@ SOFTWARE.
*/
*/
namespace nlohmann
namespace nlohmann
{
{
// alias templates to reduce boilerplate
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
template <typename T>
using remove_cv_t = typename std::remove_cv<T>::type;
template <typename T>
using remove_reference_t = typename std::remove_reference<T>::type;
template <typename T>
using uncvref_t = remove_cv_t<remove_reference_t<T>>;
template <bool If, typename Then, typename Else>
using conditional_t = typename std::conditional<If, Then, Else>::type;
// Taken from http://stackoverflow.com/questions/26936640/how-to-implement-is-enum-class-type-trait
template <typename T>
using is_scoped_enum =
std::integral_constant<bool, not std::is_convertible<T, int>::value and
std::is_enum<T>::value>;
template <typename T>
using is_unscoped_enum =
std::integral_constant<bool, std::is_convertible<T, int>::value and
std::is_enum<T>::value>;
// TODO update this doc
/*!
/*!
@brief unnamed namespace with internal helper functions
@brief unnamed namespace with internal helper functions
@since version 1.0.0
@since version 1.0.0
*/
*/
namespace
namespace detail
{
{
// Very useful construct against boilerplate (more boilerplate needed than in C++17: http://en.cppreference.com/w/cpp/types/void_t)
template <typename...> struct make_void
{
using type = void;
};
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
// Implementation of 3 C++17 constructs: conjunction, disjunction, 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)
// Whereas 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)
// Only use it when you have too (see example ahead)
template <class...> struct conjunction : std::true_type {};
template <class B1> struct conjunction<B1> : B1 {};
template <class B1, class... Bn>
struct conjunction<B1, Bn...>
: conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
template <class B> struct negation : std::integral_constant < bool, !B::value > {};
template <class...> struct disjunction : std::false_type {};
template <class B1> struct disjunction<B1> : B1 {};
template <class B1, class... Bn>
struct disjunction<B1, Bn...>
: conditional_t<bool(B1::value), B1, disjunction<Bn...>> {};
/*!
/*!
@brief Helper to determine whether there's a key_type for T.
@brief Helper to determine whether there's a key_type for T.
Thus helper is used to tell associative containers apart from other containers
Thus helper is used to tell associative containers apart from other containers
such as sequence containers. For instance, `std::map` passes the test as it
such as sequence containers. For instance, `std::map` passes the test as it
contains a `mapped_type`, whereas `std::vector` fails the test.
contains a `mapped_type`, whereas `std::vector` fails the test.
@sa http://stackoverflow.com/a/7728728/266378
@sa http://stackoverflow.com/a/7728728/266378
@since version 1.0.0, overworked in version 2.0.6
@since version 1.0.0, overworked in version 2.0.6
*/
*/
template<typename T>
#define NLOHMANN_JSON_HAS_HELPER(type) \
struct has_mapped_type
template <typename T> struct has_##type { \
private: \
template <typename U, typename = typename U::type> \
static int detect(U &&); \
\
static void detect(...); \
\
public: \
static constexpr bool value = \
std::is_integral<decltype(detect(std::declval<T>()))>::value; \
};
NLOHMANN_JSON_HAS_HELPER(mapped_type)
NLOHMANN_JSON_HAS_HELPER(key_type)
NLOHMANN_JSON_HAS_HELPER(value_type)
NLOHMANN_JSON_HAS_HELPER(iterator)
#undef NLOHMANN_JSON_HAS_HELPER
template <bool B, class RealType, class CompatibleObjectType>
struct is_compatible_object_type_impl : std::false_type {};
template <class RealType, class CompatibleObjectType>
struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
{
static constexpr auto value =
std::is_constructible<typename RealType::key_type,
typename CompatibleObjectType::key_type>::value and
std::is_constructible<typename RealType::mapped_type,
typename CompatibleObjectType::mapped_type>::value;
};
template<class RealType, class CompatibleObjectType>
struct is_compatible_object_type
{
// As noted ahead, we need to stop evaluating traits if CompatibleObjectType = void
// hence the conjunction
static auto constexpr value = is_compatible_object_type_impl <
conjunction<negation<std::is_same<void, CompatibleObjectType>>,
has_mapped_type<CompatibleObjectType>,
has_key_type<CompatibleObjectType>>::value,
RealType, CompatibleObjectType >::value;
};
template <bool B, class BasicJson, class CompatibleArrayType>
struct is_compatible_array_type_impl : std::false_type {};
template <class BasicJson, class CompatibleArrayType>
struct is_compatible_array_type_impl<true, BasicJson, CompatibleArrayType>
{
static constexpr auto value =
not std::is_same<CompatibleArrayType,
typename BasicJson::iterator>::value and
not std::is_same<CompatibleArrayType,
typename BasicJson::const_iterator>::value and
not std::is_same<CompatibleArrayType,
typename BasicJson::reverse_iterator>::value and
not std::is_same<CompatibleArrayType,
typename BasicJson::const_reverse_iterator>::value and
not std::is_same<CompatibleArrayType,
typename BasicJson::array_t::iterator>::value and
not std::is_same<CompatibleArrayType,
typename BasicJson::array_t::const_iterator>::value;
};
template <class BasicJson, class CompatibleArrayType>
struct is_compatible_array_type
{
// the check for CompatibleArrayType = void is done in is_compatible_object_type
// but we need the conjunction here as well
static auto constexpr value = is_compatible_array_type_impl <
conjunction<negation<is_compatible_object_type<
typename BasicJson::object_t, CompatibleArrayType>>,
has_value_type<CompatibleArrayType>,
has_iterator<CompatibleArrayType>>::value,
BasicJson, CompatibleArrayType >::value;
};
template <bool, typename, typename>
struct is_compatible_integer_type_impl : std::false_type {};
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
{
using RealLimits = std::numeric_limits<RealIntegerType>;
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
static constexpr auto value =
std::is_constructible<RealIntegerType,
CompatibleNumberIntegerType>::value and
CompatibleLimits::is_integer and
RealLimits::is_signed == CompatibleLimits::is_signed;
};
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type
{
static constexpr auto value = is_compatible_integer_type_impl <
std::is_arithmetic<CompatibleNumberIntegerType>::value, RealIntegerType,
CompatibleNumberIntegerType >::value;
};
template <typename RealFloat, typename CompatibleFloat>
struct is_compatible_float_type
{
static constexpr auto value =
std::is_constructible<RealFloat, CompatibleFloat>::value and
std::is_floating_point<CompatibleFloat>::value;
};
template <typename T, typename BasicJson>
struct is_compatible_basic_json_type
{
static auto constexpr value =
is_unscoped_enum<T>::value or
std::is_same<T, BasicJson>::value or
std::is_constructible<typename BasicJson::string_t, T>::value or
std::is_same<typename BasicJson::boolean_t, T>::value or
is_compatible_array_type<BasicJson, T>::value or
is_compatible_object_type<typename BasicJson::object_t, T>::value or
is_compatible_float_type<typename BasicJson::number_float_t, T>::value or
is_compatible_integer_type<typename BasicJson::number_integer_t,
T>::value or
is_compatible_integer_type<typename BasicJson::number_unsigned_t,
T>::value;
};
template <typename T, typename BasicJson, typename PrimitiveIterator>
struct is_basic_json_nested_class
{
static auto constexpr value = std::is_same<T, typename BasicJson::iterator>::value or
std::is_same<T, typename BasicJson::const_iterator>::value or
std::is_same<T, typename BasicJson::reverse_iterator>::value or
std::is_same<T, typename BasicJson::const_reverse_iterator>::value or
std::is_same<T, PrimitiveIterator>::value or
std::is_same<T, typename BasicJson::json_pointer>::value;
};
// This trait checks if JSONSerializer<T>::from_json(json const&, udt&) exists
template <template <typename, typename> class JSONSerializer, typename Json,
typename T>
struct has_from_json
{
private:
// 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(
std::declval<Json>(), std::declval<T&>()))>::value>>
static int detect(U&&);
static void detect(...);
public:
static constexpr bool value = std::is_integral<decltype(
detect(std::declval<JSONSerializer<T, void>>()))>::value;
};
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
template <template <typename, typename> class JSONSerializer, typename Json,
typename T>
struct has_non_default_from_json
{
private:
template <typename U, typename = enable_if_t<std::is_same<T, decltype(uncvref_t<U>::from_json(std::declval<Json>()))>::value>>
static int detect(U&&);
static void detect(...);
public:
static constexpr bool value = std::is_integral<decltype(
detect(std::declval<JSONSerializer<T, void>>()))>::value;
};
// This trait checks if JSONSerializer<T>::to_json exists
template <template <typename, typename> class JSONSerializer, typename Json,
typename T>
struct has_to_json
{
{
private:
private:
template <typename U, typename = typename U::mapped_type>
template <typename U, typename = decltype(uncvref_t<U>::to_json(
std::declval<Json&>(), std::declval<T>()))>
static int detect(U&&);
static int detect(U&&);
static void detect(...);
static void detect(...);
public:
public:
static constexpr bool value =
static constexpr bool value = std::is_integral<decltype(
std::is_integral<decltype(detect(std::declval<T>()))>::value;
detect(std::declval<JSONSerializer<T, void>>()))>::value;
};
// those declarations are needed to workaround a MSVC bug related to ADL
// (taken from MSVC-Ranges implementation)
void to_json();
void from_json();
struct to_json_fn
{
// is it really useful to mark those as constexpr?
template <typename Json, typename T>
constexpr auto operator()(Json&& j, T&& val) const
noexcept(noexcept(to_json(std::forward<Json>(j), std::forward<T>(val))))
-> decltype(to_json(std::forward<Json>(j), std::forward<T>(val)),
void())
{
return to_json(std::forward<Json>(j), std::forward<T>(val));
}
};
};
} // namespace
struct from_json_fn
{
template <typename Json, typename T>
constexpr auto operator()(Json&& j, T& val) const
noexcept(noexcept(from_json(std::forward<Json>(j), val)))
-> decltype(from_json(std::forward<Json>(j), val), void())
{
return from_json(std::forward<Json>(j), val);
}
};
/*!
@brief helper class to create locales with decimal point
This struct is used a default locale during the JSON serialization. JSON
requires the decimal point to be `.`, so this function overloads the
`do_decimal_point()` function to return `.`. This function is called by
float-to-string conversions to retrieve the decimal separator between integer
and fractional parts.
@sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315
@since version 2.0.0
*/
struct DecimalSeparator : std::numpunct<char>
{
char do_decimal_point() const
{
return '.';
}
};
}
// taken from ranges-v3
// TODO add doc
template <typename T>
struct static_const
{
static constexpr T value{};
};
template <typename T>
constexpr T static_const<T>::value;
inline namespace
{
constexpr auto const& to_json = static_const<detail::to_json_fn>::value;
constexpr auto const& from_json = static_const<detail::from_json_fn>::value;
}
// default JSONSerializer template argument, doesn't care about template argument
// will use ADL for serialization
template <typename = void, typename = void>
struct adl_serializer
{
template <typename Json, typename T>
static void from_json(Json&& j, T& val)
{
::nlohmann::from_json(std::forward<Json>(j), val);
}
template <typename Json, typename T>
static void to_json(Json& j, T&& val)
{
::nlohmann::to_json(j, std::forward<T>(val));
}
};
/*!
/*!
@brief a class to store JSON values
@brief a class to store JSON values
...
@@ -226,7 +544,8 @@ template <
...
@@ -226,7 +544,8 @@ template <
class NumberIntegerType = std::int64_t,
class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t,
class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double,
class NumberFloatType = double,
template<typename U> class AllocatorType = std::allocator
template<typename U> class AllocatorType = std::allocator,
template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer
>
>
class basic_json
class basic_json
{
{
...
@@ -234,7 +553,8 @@ class basic_json
...
@@ -234,7 +553,8 @@ class basic_json
/// 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,
AllocatorType>;
AllocatorType, JSONSerializer>;
class primitive_iterator_t;
public:
public:
// forward declarations
// forward declarations
...
@@ -1215,11 +1535,11 @@ class basic_json
...
@@ -1215,11 +1535,11 @@ class basic_json
@since version 1.0.0
@since version 1.0.0
*/
*/
template
<class CompatibleObjectType, typename std::enable_if<
template
<class CompatibleObjectType,
std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
enable_if_t<detail::is_compatible_object_type<
std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
object_t, CompatibleObjectType>::value,
basic_json(const CompatibleObjectType& val)
int> = 0>
: m_type(value_t::object)
basic_json(const CompatibleObjectType& val)
: m_type(value_t::object)
{
{
using std::begin;
using std::begin;
using std::end;
using std::end;
...
@@ -1278,16 +1598,11 @@ class basic_json
...
@@ -1278,16 +1598,11 @@ class basic_json
@since version 1.0.0
@since version 1.0.0
*/
*/
template<class CompatibleArrayType, typename std::enable_if<
template <class CompatibleArrayType,
not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
enable_if_t<detail::is_compatible_array_type<
not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
basic_json_t, CompatibleArrayType>::value,
not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
int> = 0>
not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
basic_json(const CompatibleArrayType& val) : m_type(value_t::array)
not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
basic_json(const CompatibleArrayType& val)
: m_type(value_t::array)
{
{
using std::begin;
using std::begin;
using std::end;
using std::end;
...
@@ -1295,6 +1610,28 @@ class basic_json
...
@@ -1295,6 +1610,28 @@ class basic_json
assert_invariant();
assert_invariant();
}
}
// constructor chosen when:
// - JSONSerializer::to_json exists for type T
// - T is not a istream, nor convertible to basic_json (float, vectors, etc)
// is_compatible_basic_json_type == not is_user_defined_type
template <
typename T,
enable_if_t<not std::is_base_of<std::istream, uncvref_t<T>>::value and
not detail::is_basic_json_nested_class<uncvref_t<T>, basic_json_t, primitive_iterator_t>::value and
not std::is_same<uncvref_t<T>, typename basic_json_t::array_t::iterator>::value and
not std::is_same<uncvref_t<T>, typename basic_json_t::object_t::iterator>::value and
detail::conjunction<detail::negation<detail::is_compatible_basic_json_type<
uncvref_t<T>, basic_json_t>>,
detail::has_to_json<JSONSerializer, basic_json,
uncvref_t<T>>>::value,
int> = 0 >
basic_json(T && val)
{
JSONSerializer<uncvref_t<T>>::to_json(*this, std::forward<T>(val));
}
/*!
/*!
@brief create a string (explicit)
@brief create a string (explicit)
...
@@ -1456,7 +1793,10 @@ class basic_json
...
@@ -1456,7 +1793,10 @@ class basic_json
@since version 1.0.0
@since version 1.0.0
*/
*/
basic_json(const int val) noexcept
// Constructor for unscoped enums (not enum classes)
template <typename T, enable_if_t<is_unscoped_enum<T>::value, int> = 0>
basic_json(T val) noexcept
: m_type(value_t::number_integer),
: m_type(value_t::number_integer),
m_value(static_cast<number_integer_t>(val))
m_value(static_cast<number_integer_t>(val))
{
{
...
@@ -1488,11 +1828,11 @@ class basic_json
...
@@ -1488,11 +1828,11 @@ class basic_json
@since version 1.0.0
@since version 1.0.0
*/
*/
template
<typename CompatibleNumberIntegerType, typename std::enable_if
<
template
<
std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
typename CompatibleNumberIntegerType,
std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
enable_if_t<detail::is_compatible_integer_type<
std::numeric_limits<CompatibleNumberIntegerType>::is_signed
,
number_integer_t, CompatibleNumberIntegerType>::value
,
CompatibleNumberIntegerType>::type = 0
>
int> = 0
>
basic_json(const CompatibleNumberIntegerType val) noexcept
basic_json(const CompatibleNumberIntegerType val) noexcept
: m_type(value_t::number_integer),
: m_type(value_t::number_integer),
m_value(static_cast<number_integer_t>(val))
m_value(static_cast<number_integer_t>(val))
...
@@ -1546,11 +1886,11 @@ class basic_json
...
@@ -1546,11 +1886,11 @@ class basic_json
@since version 2.0.0
@since version 2.0.0
*/
*/
template
<typename CompatibleNumberUnsignedType, typename std::enable_if
<
template <
std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
typename CompatibleNumberUnsignedType,
std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
enable_if_t<detail::is_compatible_integer_type<
not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed
,
number_unsigned_t, CompatibleNumberUnsignedType>::value
,
CompatibleNumberUnsignedType>::type = 0
>
int> = 0
>
basic_json(const CompatibleNumberUnsignedType val) noexcept
basic_json(const CompatibleNumberUnsignedType val) noexcept
: m_type(value_t::number_unsigned),
: m_type(value_t::number_unsigned),
m_value(static_cast<number_unsigned_t>(val))
m_value(static_cast<number_unsigned_t>(val))
...
@@ -1626,9 +1966,10 @@ class basic_json
...
@@ -1626,9 +1966,10 @@ class basic_json
@since version 1.0.0
@since version 1.0.0
*/
*/
template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
template <typename CompatibleNumberFloatType,
std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
enable_if_t<detail::is_compatible_float_type<
std::is_floating_point<CompatibleNumberFloatType>::value>::type>
number_float_t, CompatibleNumberFloatType>::value,
int> = 0>
basic_json(const CompatibleNumberFloatType val) noexcept
basic_json(const CompatibleNumberFloatType val) noexcept
: basic_json(number_float_t(val))
: basic_json(number_float_t(val))
{
{
...
@@ -2182,6 +2523,18 @@ class basic_json
...
@@ -2182,6 +2523,18 @@ class basic_json
return *this;
return *this;
}
}
// this overload is needed, since constructor for udt is explicit
template <typename T, enable_if_t<not detail::is_compatible_basic_json_type<
uncvref_t<T>, basic_json_t>::value and
detail::has_to_json<JSONSerializer, basic_json_t, uncvref_t<T>>::value>>
reference& operator=(T&& val) noexcept(std::is_nothrow_constructible<basic_json_t, uncvref_t<T>>::value and
std::is_nothrow_move_assignable<uncvref_t<T>>::value)
{
static_assert(sizeof(T) == 0 , "");
// I'm not sure this a is good practice...
return *this = basic_json_t{std::forward<T>(val)};
}
/*!
/*!
@brief destructor
@brief destructor
...
@@ -2655,7 +3008,6 @@ class basic_json
...
@@ -2655,7 +3008,6 @@ class basic_json
// value access //
// value access //
//////////////////
//////////////////
/// get an object (explicit)
template<class T, typename std::enable_if<
template<class T, typename std::enable_if<
std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
...
@@ -2681,13 +3033,16 @@ class basic_json
...
@@ -2681,13 +3033,16 @@ class basic_json
}
}
/// get an array (explicit)
/// get an array (explicit)
template<class T, typename std::enable_if<
template <
class T,
typename std::enable_if <
std::is_convertible<basic_json_t, typename T::value_type>::value and
std::is_convertible<basic_json_t, typename T::value_type>::value and
not std::is_same<basic_json_t, typename T::value_type>::value and
not std::is_same<basic_json_t,
typename T::value_type>::value and
not std::is_arithmetic<T>::value and
not std::is_arithmetic<T>::value and
not std::is_convertible<std::string, T>::value and
not std::is_convertible<std::string, T>::value and
not has_mapped_type<T>::value, int>::type = 0>
not detail::has_mapped_type<T>::value,
T get_impl(T* /*unused*/) const
int >::type = 0 >
{
{
if (is_array())
if (is_array())
{
{
...
@@ -2727,7 +3082,7 @@ class basic_json
...
@@ -2727,7 +3082,7 @@ class basic_json
/// get an array (explicit)
/// get an array (explicit)
template<class T, typename std::enable_if<
template<class T, typename std::enable_if<
std::is_same<basic_json, typename T::value_type>::value and
std::is_same<basic_json, typename T::value_type>::value and
not has_mapped_type<T>::value, int>::type = 0>
not
detail::
has_mapped_type<T>::value, int>::type = 0>
T get_impl(T* /*unused*/) const
T get_impl(T* /*unused*/) const
{
{
if (is_array())
if (is_array())
...
@@ -2956,13 +3311,46 @@ class basic_json
...
@@ -2956,13 +3311,46 @@ class basic_json
@since version 1.0.0
@since version 1.0.0
*/
*/
template<typename ValueType, typename std::enable_if<
template <typename ValueType,
not std::is_pointer<ValueType>::value, int>::type = 0>
enable_if_t<not std::is_pointer<ValueType>::value, int> = 0>
ValueType get() const
auto get() const
-> decltype(this->get_impl(static_cast<ValueType*>(nullptr)))
{
{
return get_impl(static_cast<ValueType*>(nullptr));
return get_impl(static_cast<ValueType*>(nullptr));
}
}
template <
typename T,
enable_if_t<detail::conjunction<detail::negation<detail::is_compatible_basic_json_type<
uncvref_t<T>, basic_json_t>>,
detail::has_from_json<JSONSerializer, basic_json_t,
uncvref_t<T>>>::value,
int> = 0 >
auto get() const -> uncvref_t<T>
{
using type = uncvref_t<T>;
static_assert(std::is_default_constructible<type>::value&&
std::is_copy_constructible<type>::value,
"user-defined types must be DefaultConstructible and "
"CopyConstructible when used with get");
type ret;
JSONSerializer<type>::from_json(*this, ret);
return ret;
}
// This overload is chosen for non-default constructible user-defined-types
template <
typename T,
enable_if_t<detail::conjunction<detail::negation<detail::is_compatible_basic_json_type<
uncvref_t<T>, basic_json_t>>,
detail::has_non_default_from_json<JSONSerializer, basic_json_t,
uncvref_t<T>>>::value,
short> = 0 >
T get() const
{
return JSONSerializer<T>::from_json(*this);
}
/*!
/*!
@brief get a pointer value (explicit)
@brief get a pointer value (explicit)
...
@@ -8155,6 +8543,11 @@ class basic_json
...
@@ -8155,6 +8543,11 @@ class basic_json
class primitive_iterator_t
class primitive_iterator_t
{
{
public:
public:
difference_type get_value() const noexcept
{
return m_it;
}
/// set iterator to a defined beginning
/// set iterator to a defined beginning
void set_begin() noexcept
void set_begin() noexcept
{
{
...
@@ -8179,16 +8572,87 @@ class basic_json
...
@@ -8179,16 +8572,87 @@ class basic_json
return (m_it == end_value);
return (m_it == end_value);
}
}
/// return reference to the value to change and compare
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
operator difference_type& () noexcept
{
{
return
m_it;
return lhs.m_it == rhs.
m_it;
}
}
/// return value to compare
friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
constexpr operator difference_type () const noexcept
{
{
return m_it;
return !(lhs == rhs);
}
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
{
return lhs.m_it < rhs.m_it;
}
friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
{
return lhs.m_it <= rhs.m_it;
}
friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
{
return lhs.m_it > rhs.m_it;
}
friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
{
return lhs.m_it >= rhs.m_it;
}
primitive_iterator_t operator+(difference_type i)
{
auto result = *this;
result += i;
return result;
}
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
{
return lhs.m_it - rhs.m_it;
}
friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)
{
return os << it.m_it;
}
primitive_iterator_t& operator++()
{
++m_it;
return *this;
}
primitive_iterator_t& operator++(int)
{
m_it++;
return *this;
}
primitive_iterator_t& operator--()
{
--m_it;
return *this;
}
primitive_iterator_t& operator--(int)
{
m_it--;
return *this;
}
primitive_iterator_t& operator+=(difference_type n)
{
m_it += n;
return *this;
}
primitive_iterator_t& operator-=(difference_type n)
{
m_it -= n;
return *this;
}
}
private:
private:
...
@@ -8893,7 +9357,7 @@ class basic_json
...
@@ -8893,7 +9357,7 @@ class basic_json
default:
default:
{
{
if (m_it.primitive_iterator
== -n)
if (m_it.primitive_iterator.get_value()
== -n)
{
{
return *m_object;
return *m_object;
}
}
...
@@ -11380,25 +11844,25 @@ using json = basic_json<>;
...
@@ -11380,25 +11844,25 @@ using json = basic_json<>;
// specialization of std::swap, and std::hash
// specialization of std::swap, and std::hash
namespace std
namespace std
{
{
/*!
/*!
@brief exchanges the values of two JSON objects
@brief exchanges the values of two JSON objects
@since version 1.0.0
@since version 1.0.0
*/
*/
template<>
template<>
inline void swap(nlohmann::json& j1,
inline void swap(nlohmann::json& j1,
nlohmann::json& j2) noexcept(
nlohmann::json& j2) noexcept(
is_nothrow_move_constructible<nlohmann::json>::value and
is_nothrow_move_constructible<nlohmann::json>::value and
is_nothrow_move_assignable<nlohmann::json>::value
is_nothrow_move_assignable<nlohmann::json>::value
)
)
{
{
j1.swap(j2);
j1.swap(j2);
}
}
/// hash value for JSON objects
/// hash value for JSON objects
template<>
template<>
struct hash<nlohmann::json>
struct hash<nlohmann::json>
{
{
/*!
/*!
@brief return a hash value for a JSON object
@brief return a hash value for a JSON object
...
@@ -11410,7 +11874,7 @@ struct hash<nlohmann::json>
...
@@ -11410,7 +11874,7 @@ struct hash<nlohmann::json>
const auto& h = hash<nlohmann::json::string_t>();
const auto& h = hash<nlohmann::json::string_t>();
return h(j.dump());
return h(j.dump());
}
}
};
};
} // namespace std
} // namespace std
/*!
/*!
...
...
test/src/unit-class_lexer.cpp
View file @
be1d3de4
test/src/unit-udt.cpp
View file @
be1d3de4
...
@@ -38,67 +38,67 @@ using nlohmann::json;
...
@@ -38,67 +38,67 @@ using nlohmann::json;
namespace
udt
namespace
udt
{
{
enum
class
country
enum
class
country
{
{
china
,
china
,
france
,
france
,
russia
russia
};
};
struct
age
struct
age
{
{
int
m_val
;
int
m_val
;
};
};
struct
name
struct
name
{
{
std
::
string
m_val
;
std
::
string
m_val
;
};
};
struct
address
struct
address
{
{
std
::
string
m_val
;
std
::
string
m_val
;
};
};
struct
person
struct
person
{
{
age
m_age
;
age
m_age
;
name
m_name
;
name
m_name
;
country
m_country
;
country
m_country
;
};
};
struct
contact
struct
contact
{
{
person
m_person
;
person
m_person
;
address
m_address
;
address
m_address
;
};
};
struct
contact_book
struct
contact_book
{
{
name
m_book_name
;
name
m_book_name
;
std
::
vector
<
contact
>
m_contacts
;
std
::
vector
<
contact
>
m_contacts
;
};
};
}
}
// to_json methods
// to_json methods
namespace
udt
namespace
udt
{
{
// templates because of the custom_json tests (see below)
// templates because of the custom_json tests (see below)
template
<
typename
Json
>
template
<
typename
Json
>
void
to_json
(
Json
&
j
,
age
a
)
void
to_json
(
Json
&
j
,
age
a
)
{
{
j
=
a
.
m_val
;
j
=
a
.
m_val
;
}
}
template
<
typename
Json
>
template
<
typename
Json
>
void
to_json
(
Json
&
j
,
name
const
&
n
)
void
to_json
(
Json
&
j
,
name
const
&
n
)
{
{
j
=
n
.
m_val
;
j
=
n
.
m_val
;
}
}
template
<
typename
Json
>
template
<
typename
Json
>
void
to_json
(
Json
&
j
,
country
c
)
void
to_json
(
Json
&
j
,
country
c
)
{
{
switch
(
c
)
switch
(
c
)
{
{
case
country
:
:
china
:
case
country
:
:
china
:
...
@@ -111,123 +111,128 @@ namespace udt
...
@@ -111,123 +111,128 @@ namespace udt
j
=
u8"Российская Федерация"
;
j
=
u8"Российская Федерация"
;
return
;
return
;
}
}
}
}
template
<
typename
Json
>
template
<
typename
Json
>
void
to_json
(
Json
&
j
,
person
const
&
p
)
void
to_json
(
Json
&
j
,
person
const
&
p
)
{
{
j
=
Json
{{
"age"
,
p
.
m_age
},
{
"name"
,
p
.
m_name
},
{
"country"
,
p
.
m_country
}};
j
=
Json
{{
"age"
,
p
.
m_age
},
{
"name"
,
p
.
m_name
},
{
"country"
,
p
.
m_country
}};
}
}
void
to_json
(
nlohmann
::
json
&
j
,
address
const
&
a
)
void
to_json
(
nlohmann
::
json
&
j
,
address
const
&
a
)
{
{
j
=
a
.
m_val
;
j
=
a
.
m_val
;
}
}
void
to_json
(
nlohmann
::
json
&
j
,
contact
const
&
c
)
void
to_json
(
nlohmann
::
json
&
j
,
contact
const
&
c
)
{
{
j
=
json
{{
"person"
,
c
.
m_person
},
{
"address"
,
c
.
m_address
}};
j
=
json
{{
"person"
,
c
.
m_person
},
{
"address"
,
c
.
m_address
}};
}
}
void
to_json
(
nlohmann
::
json
&
j
,
contact_book
const
&
cb
)
void
to_json
(
nlohmann
::
json
&
j
,
contact_book
const
&
cb
)
{
{
j
=
json
{{
"name"
,
cb
.
m_book_name
},
{
"contacts"
,
cb
.
m_contacts
}};
j
=
json
{{
"name"
,
cb
.
m_book_name
},
{
"contacts"
,
cb
.
m_contacts
}};
}
}
// operators
// operators
bool
operator
==
(
age
lhs
,
age
rhs
)
bool
operator
==
(
age
lhs
,
age
rhs
)
{
{
return
lhs
.
m_val
==
rhs
.
m_val
;
return
lhs
.
m_val
==
rhs
.
m_val
;
}
}
bool
operator
==
(
address
const
&
lhs
,
address
const
&
rhs
)
bool
operator
==
(
address
const
&
lhs
,
address
const
&
rhs
)
{
{
return
lhs
.
m_val
==
rhs
.
m_val
;
return
lhs
.
m_val
==
rhs
.
m_val
;
}
}
bool
operator
==
(
name
const
&
lhs
,
name
const
&
rhs
)
bool
operator
==
(
name
const
&
lhs
,
name
const
&
rhs
)
{
{
return
lhs
.
m_val
==
rhs
.
m_val
;
return
lhs
.
m_val
==
rhs
.
m_val
;
}
}
bool
operator
==
(
person
const
&
lhs
,
person
const
&
rhs
)
bool
operator
==
(
person
const
&
lhs
,
person
const
&
rhs
)
{
{
return
std
::
tie
(
lhs
.
m_name
,
lhs
.
m_age
)
==
std
::
tie
(
rhs
.
m_name
,
rhs
.
m_age
);
return
std
::
tie
(
lhs
.
m_name
,
lhs
.
m_age
)
==
std
::
tie
(
rhs
.
m_name
,
rhs
.
m_age
);
}
}
bool
operator
==
(
contact
const
&
lhs
,
contact
const
&
rhs
)
bool
operator
==
(
contact
const
&
lhs
,
contact
const
&
rhs
)
{
{
return
std
::
tie
(
lhs
.
m_person
,
lhs
.
m_address
)
==
return
std
::
tie
(
lhs
.
m_person
,
lhs
.
m_address
)
==
std
::
tie
(
rhs
.
m_person
,
rhs
.
m_address
);
std
::
tie
(
rhs
.
m_person
,
rhs
.
m_address
);
}
}
bool
operator
==
(
contact_book
const
&
lhs
,
contact_book
const
&
rhs
)
bool
operator
==
(
contact_book
const
&
lhs
,
contact_book
const
&
rhs
)
{
{
return
std
::
tie
(
lhs
.
m_book_name
,
lhs
.
m_contacts
)
==
return
std
::
tie
(
lhs
.
m_book_name
,
lhs
.
m_contacts
)
==
std
::
tie
(
rhs
.
m_book_name
,
rhs
.
m_contacts
);
std
::
tie
(
rhs
.
m_book_name
,
rhs
.
m_contacts
);
}
}
}
}
// from_json methods
// from_json methods
namespace
udt
namespace
udt
{
{
template
<
typename
Json
>
template
<
typename
Json
>
void
from_json
(
Json
const
&
j
,
age
&
a
)
void
from_json
(
Json
const
&
j
,
age
&
a
)
{
{
a
.
m_val
=
j
.
template
get
<
int
>
();
a
.
m_val
=
j
.
template
get
<
int
>
();
}
}
template
<
typename
Json
>
template
<
typename
Json
>
void
from_json
(
Json
const
&
j
,
name
&
n
)
void
from_json
(
Json
const
&
j
,
name
&
n
)
{
{
n
.
m_val
=
j
.
template
get
<
std
::
string
>
();
n
.
m_val
=
j
.
template
get
<
std
::
string
>
();
}
}
template
<
typename
Json
>
template
<
typename
Json
>
void
from_json
(
Json
const
&
j
,
country
&
c
)
void
from_json
(
Json
const
&
j
,
country
&
c
)
{
{
const
auto
str
=
j
.
template
get
<
std
::
string
>
();
const
auto
str
=
j
.
template
get
<
std
::
string
>
();
static
const
std
::
map
<
std
::
string
,
country
>
m
=
{
static
const
std
::
map
<
std
::
string
,
country
>
m
=
{
{
u8"中华人民共和国"
,
country
::
china
},
{
u8"中华人民共和国"
,
country
::
china
},
{
"France"
,
country
::
france
},
{
"France"
,
country
::
france
},
{
"Российская Федерация"
,
country
::
russia
}};
{
"Российская Федерация"
,
country
::
russia
}
};
const
auto
it
=
m
.
find
(
str
);
const
auto
it
=
m
.
find
(
str
);
// TODO test exceptions
// TODO test exceptions
c
=
it
->
second
;
c
=
it
->
second
;
}
}
template
<
typename
Json
>
template
<
typename
Json
>
void
from_json
(
Json
const
&
j
,
person
&
p
)
void
from_json
(
Json
const
&
j
,
person
&
p
)
{
{
p
.
m_age
=
j
[
"age"
].
template
get
<
age
>
();
p
.
m_age
=
j
[
"age"
].
template
get
<
age
>
();
p
.
m_name
=
j
[
"name"
].
template
get
<
name
>
();
p
.
m_name
=
j
[
"name"
].
template
get
<
name
>
();
p
.
m_country
=
j
[
"country"
].
template
get
<
country
>
();
p
.
m_country
=
j
[
"country"
].
template
get
<
country
>
();
}
}
void
from_json
(
nlohmann
::
json
const
&
j
,
address
&
a
)
void
from_json
(
nlohmann
::
json
const
&
j
,
address
&
a
)
{
{
a
.
m_val
=
j
.
get
<
std
::
string
>
();
a
.
m_val
=
j
.
get
<
std
::
string
>
();
}
}
void
from_json
(
nlohmann
::
json
const
&
j
,
contact
&
c
)
void
from_json
(
nlohmann
::
json
const
&
j
,
contact
&
c
)
{
{
c
.
m_person
=
j
[
"person"
].
get
<
person
>
();
c
.
m_person
=
j
[
"person"
].
get
<
person
>
();
c
.
m_address
=
j
[
"address"
].
get
<
address
>
();
c
.
m_address
=
j
[
"address"
].
get
<
address
>
();
}
}
void
from_json
(
nlohmann
::
json
const
&
j
,
contact_book
&
cb
)
void
from_json
(
nlohmann
::
json
const
&
j
,
contact_book
&
cb
)
{
{
cb
.
m_book_name
=
j
[
"name"
].
get
<
name
>
();
cb
.
m_book_name
=
j
[
"name"
].
get
<
name
>
();
cb
.
m_contacts
=
j
[
"contacts"
].
get
<
std
::
vector
<
contact
>>
();
cb
.
m_contacts
=
j
[
"contacts"
].
get
<
std
::
vector
<
contact
>>
();
}
}
}
}
TEST_CASE
(
"basic usage"
,
"[udt]"
)
TEST_CASE
(
"basic usage"
,
"[udt]"
)
{
{
// a bit narcissic maybe :) ?
// a bit narcissic maybe :) ?
const
udt
::
age
a
{
23
};
const
udt
::
age
a
{
23
};
const
udt
::
name
n
{
"theo"
};
const
udt
::
name
n
{
"theo"
};
const
udt
::
country
c
{
udt
::
country
::
france
};
const
udt
::
country
c
{
udt
::
country
::
france
};
const
udt
::
person
sfinae_addict
{
a
,
n
,
c
};
const
udt
::
person
sfinae_addict
{
a
,
n
,
c
};
...
@@ -295,18 +300,26 @@ struct adl_serializer<std::shared_ptr<T>>
...
@@ -295,18 +300,26 @@ struct adl_serializer<std::shared_ptr<T>>
static
void
to_json
(
json
&
j
,
std
::
shared_ptr
<
T
>
const
&
opt
)
static
void
to_json
(
json
&
j
,
std
::
shared_ptr
<
T
>
const
&
opt
)
{
{
if
(
opt
)
if
(
opt
)
{
j
=
*
opt
;
j
=
*
opt
;
}
else
else
{
j
=
nullptr
;
j
=
nullptr
;
}
}
}
static
void
from_json
(
json
const
&
j
,
std
::
shared_ptr
<
T
>
&
opt
)
static
void
from_json
(
json
const
&
j
,
std
::
shared_ptr
<
T
>&
opt
)
{
{
if
(
j
.
is_null
())
if
(
j
.
is_null
())
{
opt
=
nullptr
;
opt
=
nullptr
;
}
else
else
{
opt
.
reset
(
new
T
(
j
.
get
<
T
>
()));
opt
.
reset
(
new
T
(
j
.
get
<
T
>
()));
}
}
}
};
};
template
<>
template
<>
...
@@ -387,7 +400,7 @@ struct adl_serializer<std::vector<T>>
...
@@ -387,7 +400,7 @@ struct adl_serializer<std::vector<T>>
{
{
}
}
static
void
from_json
(
json
const
&
j
,
std
::
vector
<
T
>
&
opt
)
static
void
from_json
(
json
const
&
j
,
std
::
vector
<
T
>&
opt
)
{
{
}
}
};
};
...
@@ -396,9 +409,9 @@ struct adl_serializer<std::vector<T>>
...
@@ -396,9 +409,9 @@ struct adl_serializer<std::vector<T>>
TEST_CASE
(
"current supported types are preferred over specializations"
,
"[udt]"
)
TEST_CASE
(
"current supported types are preferred over specializations"
,
"[udt]"
)
{
{
json
j
=
std
::
vector
<
int
>
{
1
,
2
,
3
};
json
j
=
std
::
vector
<
int
>
{
1
,
2
,
3
};
auto
f
=
j
.
get
<
std
::
vector
<
int
>>
();
auto
f
=
j
.
get
<
std
::
vector
<
int
>>
();
CHECK
((
f
==
std
::
vector
<
int
>
{
1
,
2
,
3
}));
CHECK
((
f
==
std
::
vector
<
int
>
{
1
,
2
,
3
}));
}
}
namespace
nlohmann
namespace
nlohmann
...
@@ -409,20 +422,28 @@ struct adl_serializer<std::unique_ptr<T>>
...
@@ -409,20 +422,28 @@ struct adl_serializer<std::unique_ptr<T>>
static
void
to_json
(
json
&
j
,
std
::
unique_ptr
<
T
>
const
&
opt
)
static
void
to_json
(
json
&
j
,
std
::
unique_ptr
<
T
>
const
&
opt
)
{
{
if
(
opt
)
if
(
opt
)
{
j
=
*
opt
;
j
=
*
opt
;
}
else
else
{
j
=
nullptr
;
j
=
nullptr
;
}
}
}
// this is the overload needed for non-copyable types,
// this is the overload needed for non-copyable types,
// should we add a priority tag in the implementation to prefer this overload if it exists?
// should we add a priority tag in the implementation to prefer this overload if it exists?
static
std
::
unique_ptr
<
T
>
from_json
(
json
const
&
j
)
static
std
::
unique_ptr
<
T
>
from_json
(
json
const
&
j
)
{
{
if
(
j
.
is_null
())
if
(
j
.
is_null
())
{
return
nullptr
;
return
nullptr
;
}
else
else
{
return
std
::
unique_ptr
<
T
>
(
new
T
(
j
.
get
<
T
>
()));
return
std
::
unique_ptr
<
T
>
(
new
T
(
j
.
get
<
T
>
()));
}
}
}
};
};
}
}
...
@@ -477,7 +498,9 @@ struct pod_serializer
...
@@ -477,7 +498,9 @@ struct pod_serializer
auto
bytes
=
static_cast
<
char
const
*>
(
static_cast
<
void
const
*>
(
&
t
));
auto
bytes
=
static_cast
<
char
const
*>
(
static_cast
<
void
const
*>
(
&
t
));
std
::
uint64_t
value
=
bytes
[
0
];
std
::
uint64_t
value
=
bytes
[
0
];
for
(
auto
i
=
1
;
i
<
8
;
++
i
)
for
(
auto
i
=
1
;
i
<
8
;
++
i
)
{
value
|=
bytes
[
i
]
<<
8
*
i
;
value
|=
bytes
[
i
]
<<
8
*
i
;
}
j
=
value
;
j
=
value
;
}
}
...
@@ -514,7 +537,7 @@ TEST_CASE("custom serializer for pods", "[udt]")
...
@@ -514,7 +537,7 @@ TEST_CASE("custom serializer for pods", "[udt]")
template
<
typename
T
,
typename
>
template
<
typename
T
,
typename
>
struct
another_adl_serializer
;
struct
another_adl_serializer
;
using
custom_json
=
nlohmann
::
basic_json
<
std
::
map
,
std
::
vector
,
std
::
string
,
bool
,
std
::
int64_t
,
std
::
uint64_t
,
double
,
std
::
allocator
,
another_adl_serializer
>
;
using
custom_json
=
nlohmann
::
basic_json
<
std
::
map
,
std
::
vector
,
std
::
string
,
bool
,
std
::
int64_t
,
std
::
uint64_t
,
double
,
std
::
allocator
,
another_adl_serializer
>
;
template
<
typename
T
,
typename
>
template
<
typename
T
,
typename
>
struct
another_adl_serializer
struct
another_adl_serializer
...
...
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