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
794dae89
Commit
794dae89
authored
Jan 15, 2017
by
Théo DELRIEU
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
apply changes to json.hpp.re2c
parent
68081cd1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
125 additions
and
66 deletions
+125
-66
json.hpp.re2c
src/json.hpp.re2c
+125
-66
No files found.
src/json.hpp.re2c
View file @
794dae89
...
@@ -168,7 +168,7 @@ using is_unscoped_enum =
...
@@ -168,7 +168,7 @@ using is_unscoped_enum =
namespace detail
namespace detail
{
{
template <typename Json> std::string type_name(
Json const
&j)
template <typename Json> std::string type_name(
const Json
&j)
{
{
switch (j.m_type)
switch (j.m_type)
{
{
...
@@ -189,6 +189,11 @@ template <typename Json> std::string type_name(Json const &j)
...
@@ -189,6 +189,11 @@ template <typename Json> std::string type_name(Json const &j)
}
}
}
}
// dispatch utility (taken from ranges-v3)
template <unsigned N> struct priority_tag : priority_tag<N - 1> {};
template <> struct priority_tag<0> {};
// 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 refactoring
template <value_t> struct external_constructor;
template <value_t> struct external_constructor;
...
@@ -491,14 +496,15 @@ template <typename Json, typename ArithmeticType,
...
@@ -491,14 +496,15 @@ template <typename Json, typename ArithmeticType,
not std::is_same<ArithmeticType,
not std::is_same<ArithmeticType,
typename Json::boolean_t>::value,
typename Json::boolean_t>::value,
int> = 0>
int> = 0>
void get_arithmetic_value(
Json const
&j, ArithmeticType &val)
void get_arithmetic_value(
const Json
&j, ArithmeticType &val)
{
{
if (j.is_number_integer())
// unsigned must be checked first, since is_number_integer() == true for unsigned
val = *const_cast<Json&>(j).template get_ptr<typename Json::number_integer_t*>();
if (j.is_number_unsigned())
else if (j.is_number_unsigned())
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename Json::number_unsigned_t*>());
val = *const_cast<Json&>(j).template get_ptr<typename Json::number_unsigned_t*>();
else if (j.is_number_integer())
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename Json::number_integer_t*>());
else if (j.is_number_float())
else if (j.is_number_float())
val =
*const_cast<Json&>(j).template get_ptr<typename Json::number_float_t*>(
);
val =
static_cast<ArithmeticType>(*j.template get_ptr<const typename Json::number_float_t*>()
);
else
else
throw std::domain_error("type must be number, but is " + type_name(j));
throw std::domain_error("type must be number, but is " + type_name(j));
}
}
...
@@ -522,7 +528,7 @@ template <typename Json, typename FloatType,
...
@@ -522,7 +528,7 @@ template <typename Json, 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(Json &j, FloatType val) noexcept
void to_json(Json &j, FloatType val) noexcept
{
{
external_constructor<value_t::number_float>::construct(j,
val
);
external_constructor<value_t::number_float>::construct(j,
static_cast<typename Json::number_float_t>(val)
);
}
}
...
@@ -533,7 +539,7 @@ template <
...
@@ -533,7 +539,7 @@ template <
int> = 0>
int> = 0>
void to_json(Json &j, CompatibleNumberUnsignedType val) noexcept
void to_json(Json &j, CompatibleNumberUnsignedType val) noexcept
{
{
external_constructor<value_t::number_unsigned>::construct(j,
val
);
external_constructor<value_t::number_unsigned>::construct(j,
static_cast<typename Json::number_unsigned_t>(val)
);
}
}
template <
template <
...
@@ -543,7 +549,7 @@ template <
...
@@ -543,7 +549,7 @@ template <
int> = 0>
int> = 0>
void to_json(Json &j, CompatibleNumberIntegerType val) noexcept
void to_json(Json &j, CompatibleNumberIntegerType val) noexcept
{
{
external_constructor<value_t::number_integer>::construct(j,
val
);
external_constructor<value_t::number_integer>::construct(j,
static_cast<typename Json::number_integer_t>(val)
);
}
}
template <typename Json, typename UnscopedEnumType,
template <typename Json, typename UnscopedEnumType,
...
@@ -559,7 +565,7 @@ template <
...
@@ -559,7 +565,7 @@ template <
is_compatible_array_type<Json, CompatibleArrayType>::value or
is_compatible_array_type<Json, CompatibleArrayType>::value or
std::is_same<typename Json::array_t, CompatibleArrayType>::value,
std::is_same<typename Json::array_t, CompatibleArrayType>::value,
int> = 0>
int> = 0>
void to_json(Json &j,
CompatibleArrayType const
&arr)
void to_json(Json &j,
const CompatibleArrayType
&arr)
{
{
external_constructor<value_t::array>::construct(j, arr);
external_constructor<value_t::array>::construct(j, arr);
}
}
...
@@ -568,48 +574,48 @@ template <
...
@@ -568,48 +574,48 @@ template <
typename Json, typename CompatibleObjectType,
typename Json, typename CompatibleObjectType,
enable_if_t<is_compatible_object_type<Json, CompatibleObjectType>::value,
enable_if_t<is_compatible_object_type<Json, CompatibleObjectType>::value,
int> = 0>
int> = 0>
void to_json(Json &j,
CompatibleObjectType const
&arr)
void to_json(Json &j,
const CompatibleObjectType
&arr)
{
{
external_constructor<value_t::object>::construct(j, arr);
external_constructor<value_t::object>::construct(j, arr);
}
}
template <typename Json>
template <typename Json>
void from_json(
Json const
& j, typename Json::boolean_t& b)
void from_json(
const Json
& j, typename Json::boolean_t& b)
{
{
if (!j.is_boolean())
if (!j.is_boolean())
throw std::domain_error("type must be boolean, but is " + type_name(j));
throw std::domain_error("type must be boolean, but is " + type_name(j));
b = *
const_cast<Json&>(j).template get_ptr<
typename Json::boolean_t*>();
b = *
j.template get_ptr<const
typename Json::boolean_t*>();
}
}
template <typename Json>
template <typename Json>
void from_json(
Json const
& j, typename Json::string_t& s)
void from_json(
const Json
& j, typename Json::string_t& s)
{
{
if (!j.is_string())
if (!j.is_string())
throw std::domain_error("type must be string, but is " + type_name(j));
throw std::domain_error("type must be string, but is " + type_name(j));
s = *
const_cast<Json&>(j).template get_ptr<
typename Json::string_t*>();
s = *
j.template get_ptr<const
typename Json::string_t*>();
}
}
template <typename Json>
template <typename Json>
void from_json(
Json const
& j, typename Json::number_float_t& val)
void from_json(
const Json
& j, typename Json::number_float_t& val)
{
{
get_arithmetic_value(j, val);
get_arithmetic_value(j, val);
}
}
template <typename Json>
template <typename Json>
void from_json(
Json const
& j, typename Json::number_unsigned_t& val)
void from_json(
const Json
& j, typename Json::number_unsigned_t& val)
{
{
get_arithmetic_value(j, val);
get_arithmetic_value(j, val);
}
}
template <typename Json>
template <typename Json>
void from_json(
Json const
& j, typename Json::number_integer_t& val)
void from_json(
const Json
& j, typename Json::number_integer_t& val)
{
{
get_arithmetic_value(j, val);
get_arithmetic_value(j, val);
}
}
template <typename Json, typename UnscopedEnumType,
template <typename Json, 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(
Json const
&j, UnscopedEnumType& e)
void from_json(
const Json
&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);
...
@@ -617,16 +623,16 @@ void from_json(Json const &j, UnscopedEnumType& e)
...
@@ -617,16 +623,16 @@ void from_json(Json const &j, UnscopedEnumType& e)
}
}
template <typename Json>
template <typename Json>
void from_json(
Json const
&j, typename Json::array_t &arr)
void from_json(
const Json
&j, typename Json::array_t &arr)
{
{
if (!j.is_array())
if (!j.is_array())
throw std::domain_error("type must be array, but is " + type_name(j));
throw std::domain_error("type must be array, but is " + type_name(j));
arr = *
const_cast<Json&>(j).template get_ptr<
typename Json::array_t*>();
arr = *
j.template get_ptr<const
typename Json::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, TODO find a way to avoid including forward_list
template <typename Json, typename T, typename Allocator>
template <typename Json, typename T, typename Allocator>
void from_json(
Json const
&j, std::forward_list<T, Allocator>& l)
void from_json(
const Json
&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
// (except when it's null.. ?)
// (except when it's null.. ?)
...
@@ -641,13 +647,47 @@ void from_json(Json const&j, std::forward_list<T, Allocator>& l)
...
@@ -641,13 +647,47 @@ void from_json(Json const&j, std::forward_list<T, Allocator>& l)
l.push_front(it->template get<T>());
l.push_front(it->template get<T>());
}
}
template <typename Json, typename CompatibleArrayType>
void from_json_array_impl(const Json &j, CompatibleArrayType &arr, priority_tag<0>)
{
using std::begin;
using std::end;
std::transform(
j.begin(), j.end(), std::inserter(arr, end(arr)), [](const Json &i)
{
// get<Json>() returns *this, this won't call a from_json method when
// value_type is Json
return i.template get<typename CompatibleArrayType::value_type>();
});
}
template <typename Json, typename CompatibleArrayType>
auto from_json_array_impl(const Json &j, CompatibleArrayType &arr, priority_tag<1>)
-> decltype(
arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
void())
{
using std::begin;
using std::end;
arr.reserve(j.size());
std::transform(
j.begin(), j.end(), std::inserter(arr, end(arr)), [](const Json &i)
{
// get<Json>() returns *this, this won't call a from_json method when
// value_type is Json
return i.template get<typename CompatibleArrayType::value_type>();
});
}
template <
template <
typename Json, typename CompatibleArrayType,
typename Json, typename CompatibleArrayType,
enable_if_t<is_compatible_array_type<Json, CompatibleArrayType>::value and
enable_if_t<is_compatible_array_type<Json, CompatibleArrayType>::value and
not std::is_same<typename Json::array_t,
not std::is_same<typename Json::array_t,
CompatibleArrayType>::value,
CompatibleArrayType>::value,
int> = 0>
int> = 0>
void from_json(
Json const
&j, CompatibleArrayType &arr)
void from_json(
const Json
&j, CompatibleArrayType &arr)
{
{
if (j.is_null())
if (j.is_null())
throw std::domain_error("type must be array, but is " + type_name(j));
throw std::domain_error("type must be array, but is " + type_name(j));
...
@@ -657,16 +697,7 @@ void from_json(Json const &j, CompatibleArrayType &arr)
...
@@ -657,16 +697,7 @@ void from_json(Json const &j, CompatibleArrayType &arr)
if (!j.is_array())
if (!j.is_array())
throw std::domain_error("type must be array, but is " + type_name(j));
throw std::domain_error("type must be array, but is " + type_name(j));
}
}
from_json_array_impl(j, arr, priority_tag<1>{});
using std::begin;
using std::end;
std::transform(
j.begin(), j.end(), std::inserter(arr, end(arr)), [](Json const &i)
{
// get<Json>() returns *this, this won't call a from_json method when
// value_type is Json
return i.template get<typename CompatibleArrayType::value_type>();
});
}
}
...
@@ -674,12 +705,12 @@ template <
...
@@ -674,12 +705,12 @@ template <
typename Json, typename CompatibleObjectType,
typename Json, typename CompatibleObjectType,
enable_if_t<is_compatible_object_type<Json, CompatibleObjectType>::value,
enable_if_t<is_compatible_object_type<Json, CompatibleObjectType>::value,
int> = 0>
int> = 0>
void from_json(
Json const
&j, CompatibleObjectType &obj)
void from_json(
const Json
&j, CompatibleObjectType &obj)
{
{
if (!j.is_object())
if (!j.is_object())
throw std::domain_error("type must be object, but is " + type_name(j));
throw std::domain_error("type must be object, but is " + type_name(j));
auto inner_object =
const_cast<Json&>(j).template get_ptr<
typename Json::object_t*>();
auto inner_object =
j.template get_ptr<const
typename Json::object_t*>();
using std::begin;
using std::begin;
using std::end;
using std::end;
// we could avoid the assignment, but this might require a for loop, which
// we could avoid the assignment, but this might require a for loop, which
...
@@ -700,16 +731,16 @@ template <
...
@@ -700,16 +731,16 @@ template <
not std::is_same<ArithmeticType, typename Json::number_float_t>::value and
not std::is_same<ArithmeticType, typename Json::number_float_t>::value and
not std::is_same<ArithmeticType, typename Json::boolean_t>::value,
not std::is_same<ArithmeticType, typename Json::boolean_t>::value,
int> = 0>
int> = 0>
void from_json(
Json const
&j, ArithmeticType &val)
void from_json(
const Json
&j, ArithmeticType &val)
{
{
if (j.is_number_
integer
())
if (j.is_number_
unsigned
())
val =
*const_cast<Json&>(j).template get_ptr<typename Json::number_integer_t*>(
);
val =
static_cast<ArithmeticType>(*j.template get_ptr<const typename Json::number_unsigned_t*>()
);
else if (j.is_number_
unsigned
())
else if (j.is_number_
integer
())
val =
*const_cast<Json&>(j).template get_ptr<typename Json::number_unsigned_t*>(
);
val =
static_cast<ArithmeticType>(*j.template get_ptr<const typename Json::number_integer_t*>()
);
else if (j.is_number_float())
else if (j.is_number_float())
val =
*const_cast<Json&>(j).template get_ptr<typename Json::number_float_t*>(
);
val =
static_cast<ArithmeticType>(*j.template get_ptr<const typename Json::number_float_t*>()
);
else if (j.is_boolean())
else if (j.is_boolean())
val =
*const_cast<Json&>(j).template get_ptr<typename Json::boolean_t*>(
);
val =
static_cast<ArithmeticType>(*j.template get_ptr<const typename Json::boolean_t*>()
);
else
else
throw std::domain_error("type must be number, but is " + type_name(j));
throw std::domain_error("type must be number, but is " + type_name(j));
}
}
...
@@ -717,24 +748,53 @@ void from_json(Json const &j, ArithmeticType &val)
...
@@ -717,24 +748,53 @@ void from_json(Json const &j, ArithmeticType &val)
struct to_json_fn
struct to_json_fn
{
{
template <typename Json, typename T>
template <typename Json, typename T>
constexpr auto operator()(Json&& j, T&& val
) const
auto call(Json& j, T&& val, priority_tag<1>
) const
noexcept(noexcept(to_json(
std::forward<Json>(j)
, std::forward<T>(val))))
noexcept(noexcept(to_json(
j
, std::forward<T>(val))))
-> decltype(to_json(
std::forward<Json>(j)
, std::forward<T>(val)),
-> decltype(to_json(
j
, std::forward<T>(val)),
void())
void())
{
{
return to_json(
std::forward<Json>(j)
, std::forward<T>(val));
return to_json(
j
, std::forward<T>(val));
}
}
};
struct from_json_fn
{
template <typename Json, typename T>
template <typename Json, typename T>
constexpr auto operator()(Json&& j, T& val) const
void call(Json&, T&&, priority_tag<0>) const noexcept
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
);
static_assert(sizeof(Json) == 0, "to_json method in T's namespace can not be called"
);
}
}
public:
template <typename Json, typename T>
void operator()(Json &j, T &&val) const
noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1>{})))
{
return call(j, std::forward<T>(val), priority_tag<1>{});
}
};
struct from_json_fn
{
private:
template <typename Json, typename T>
auto call(const Json &j, T &val, priority_tag<1>) const
noexcept(noexcept(from_json(j, val)))
-> decltype(from_json(j, val), void())
{
return from_json(j, val);
}
template <typename Json, typename T>
void call(const Json &, T&, priority_tag<0>) const noexcept
{
static_assert(sizeof(Json) == 0, "from_json method in T's namespace can not be called");
}
public:
template <typename Json, typename T>
void operator()(const Json &j, T &val) const
noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1>{})))
{
return call(j, val, priority_tag<1>{});
}
};
};
/*!
/*!
...
@@ -756,7 +816,6 @@ struct DecimalSeparator : std::numpunct<char>
...
@@ -756,7 +816,6 @@ struct DecimalSeparator : std::numpunct<char>
return '.';
return '.';
}
}
};
};
}
}
// taken from ranges-v3
// taken from ranges-v3
...
@@ -772,8 +831,8 @@ constexpr T static_const<T>::value;
...
@@ -772,8 +831,8 @@ constexpr T static_const<T>::value;
inline namespace
inline namespace
{
{
constexpr
auto const
& to_json = static_const<detail::to_json_fn>::value;
constexpr
const auto
& to_json = static_const<detail::to_json_fn>::value;
constexpr
auto const
& from_json = static_const<detail::from_json_fn>::value;
constexpr
const auto
& 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
...
@@ -788,9 +847,10 @@ struct adl_serializer
...
@@ -788,9 +847,10 @@ struct adl_serializer
}
}
template <typename Json, typename T>
template <typename Json, typename T>
static void to_json(Json& j, T&& val)
static void to_json(Json &j, T &&val) noexcept(
noexcept(::nlohmann::to_json(j, std::forward<T>(val))))
{
{
::nlohmann::to_json(j, std::forward<T>(val));
::nlohmann::to_json(j, std::forward<T>(val));
}
}
};
};
...
@@ -888,7 +948,7 @@ class basic_json
...
@@ -888,7 +948,7 @@ class basic_json
{
{
private:
private:
template <::nlohmann::value_t> friend struct detail::external_constructor;
template <::nlohmann::value_t> friend struct detail::external_constructor;
template <typename Json> friend std::string detail::type_name(
Json const
&);
template <typename Json> friend std::string detail::type_name(
const 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,
...
@@ -2967,16 +3027,16 @@ class basic_json
...
@@ -2967,16 +3027,16 @@ class basic_json
uncvref_t<T>>::value,
uncvref_t<T>>::value,
int> = 0>
int> = 0>
// do we really want the uncvref ? if a user call get<int &>, shouldn't we
// do we really want the uncvref ? if a user call get<int &>, shouldn't we
// i know there is a special behaviour for boolean_t* and such
// static assert ?
// static assert ?
// i know there is a special behaviour for boolean_t* and such
auto get() const noexcept(noexcept(JSONSerializer<uncvref_t<T>>::from_json(
auto get() const noexcept(noexcept(JSONSerializer<uncvref_t<T>>::from_json(
std::declval<
basic_json_t cons
t &>(), std::declval<uncvref_t<T> &>())))
std::declval<
const basic_json_
t &>(), std::declval<uncvref_t<T> &>())))
-> uncvref_t<T>
-> 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
and
std::is_copy_constructible<type>::value,
std::is_copy_constructible<type>::value,
"
user-defined t
ypes must be DefaultConstructible and "
"
T
ypes must be DefaultConstructible and "
"CopyConstructible when used with get");
"CopyConstructible when used with get");
type ret;
type ret;
JSONSerializer<type>::from_json(*this, ret);
JSONSerializer<type>::from_json(*this, ret);
...
@@ -2992,12 +3052,11 @@ class basic_json
...
@@ -2992,12 +3052,11 @@ class basic_json
detail::has_non_default_from_json<basic_json_t,
detail::has_non_default_from_json<basic_json_t,
uncvref_t<T>>::value,
uncvref_t<T>>::value,
int> = 0>
int> = 0>
constexpr uncvref_t<T> get() const noexcept(noexcept(JSONSerializer<T>::from_json(std::declval<basic_json_t const
&>())))
uncvref_t<T> get() const noexcept(noexcept(JSONSerializer<T>::from_json(std::declval<const basic_json_t
&>())))
{
{
return JSONSerializer<T>::from_json(*this);
return JSONSerializer<T>::from_json(*this);
}
}
// TODO what to do with those...
/*!
/*!
@brief get a pointer value (explicit)
@brief get a pointer value (explicit)
...
...
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