apply changes to json.hpp.re2c
This commit is contained in:
		
							parent
							
								
									68081cd112
								
							
						
					
					
						commit
						794dae8911
					
				
					 1 changed files with 125 additions and 66 deletions
				
			
		|  | @ -168,7 +168,7 @@ using is_unscoped_enum = | |||
| 
 | ||||
| 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) | ||||
|   { | ||||
|  | @ -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. | ||||
| // I'm sure there is a better way, but this might need a big basic_json refactoring | ||||
| template <value_t> struct external_constructor; | ||||
|  | @ -491,14 +496,15 @@ template <typename Json, typename ArithmeticType, | |||
|                           not std::is_same<ArithmeticType, | ||||
|                                            typename Json::boolean_t>::value, | ||||
|                       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()) | ||||
|     val = *const_cast<Json&>(j).template get_ptr<typename Json::number_integer_t*>(); | ||||
|   else if (j.is_number_unsigned()) | ||||
|     val = *const_cast<Json&>(j).template get_ptr<typename Json::number_unsigned_t*>(); | ||||
|   // unsigned must be checked first, since is_number_integer() == true for unsigned | ||||
|   if (j.is_number_unsigned()) | ||||
|     val = static_cast<ArithmeticType>(*j.template get_ptr<const 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()) | ||||
|     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 | ||||
|     throw std::domain_error("type must be number, but is " + type_name(j)); | ||||
| } | ||||
|  | @ -522,7 +528,7 @@ template <typename Json, typename FloatType, | |||
|           enable_if_t<std::is_floating_point<FloatType>::value, int> = 0> | ||||
| 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 < | |||
|                 int> = 0> | ||||
| 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 < | ||||
|  | @ -543,7 +549,7 @@ template < | |||
|                 int> = 0> | ||||
| 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, | ||||
|  | @ -559,7 +565,7 @@ template < | |||
|         is_compatible_array_type<Json, CompatibleArrayType>::value or | ||||
|             std::is_same<typename Json::array_t, CompatibleArrayType>::value, | ||||
|         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); | ||||
| } | ||||
|  | @ -568,48 +574,48 @@ template < | |||
|     typename Json, typename CompatibleObjectType, | ||||
|     enable_if_t<is_compatible_object_type<Json, CompatibleObjectType>::value, | ||||
|                 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); | ||||
| } | ||||
| 
 | ||||
| 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()) | ||||
|     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> | ||||
| 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()) | ||||
|     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> | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| template <typename Json, typename UnscopedEnumType, | ||||
|           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; | ||||
|   get_arithmetic_value(j, val); | ||||
|  | @ -617,16 +623,16 @@ void from_json(Json const &j, UnscopedEnumType& e) | |||
| } | ||||
| 
 | ||||
| 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()) | ||||
|     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 | ||||
| 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 | ||||
|   // (except when it's null.. ?) | ||||
|  | @ -641,13 +647,47 @@ void from_json(Json const&j, std::forward_list<T, Allocator>& l) | |||
|     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 < | ||||
|     typename Json, typename CompatibleArrayType, | ||||
|     enable_if_t<is_compatible_array_type<Json, CompatibleArrayType>::value and | ||||
|                     not std::is_same<typename Json::array_t, | ||||
|                                      CompatibleArrayType>::value, | ||||
|                 int> = 0> | ||||
| void from_json(Json const &j, CompatibleArrayType &arr) | ||||
| void from_json(const  Json &j, CompatibleArrayType &arr) | ||||
| { | ||||
|   if (j.is_null()) | ||||
|       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) | |||
|     if (!j.is_array()) | ||||
|       throw std::domain_error("type must be array, but is " + type_name(j)); | ||||
|   } | ||||
| 
 | ||||
|   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>(); | ||||
|       }); | ||||
|   from_json_array_impl(j, arr, priority_tag<1>{}); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -674,12 +705,12 @@ template < | |||
|     typename Json, typename CompatibleObjectType, | ||||
|     enable_if_t<is_compatible_object_type<Json, CompatibleObjectType>::value, | ||||
|                 int> = 0> | ||||
| void from_json(Json const &j, CompatibleObjectType &obj) | ||||
| void from_json(const  Json &j, CompatibleObjectType &obj) | ||||
| { | ||||
|   if (!j.is_object()) | ||||
|     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::end; | ||||
|   // we could avoid the assignment, but this might require a for loop, which | ||||
|  | @ -700,16 +731,16 @@ template < | |||
|             not std::is_same<ArithmeticType, typename Json::number_float_t>::value and | ||||
|             not std::is_same<ArithmeticType, typename Json::boolean_t>::value, | ||||
|         int> = 0> | ||||
| void from_json(Json const &j, ArithmeticType &val) | ||||
| void from_json(const  Json &j, ArithmeticType &val) | ||||
| { | ||||
|   if (j.is_number_integer()) | ||||
|     val = *const_cast<Json&>(j).template get_ptr<typename Json::number_integer_t*>(); | ||||
|   else if (j.is_number_unsigned()) | ||||
|     val = *const_cast<Json&>(j).template get_ptr<typename Json::number_unsigned_t*>(); | ||||
|   if (j.is_number_unsigned()) | ||||
|     val = static_cast<ArithmeticType>(*j.template get_ptr<const 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()) | ||||
|     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()) | ||||
|     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 | ||||
|     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) | |||
| struct to_json_fn | ||||
| { | ||||
|     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)), | ||||
|     auto call(Json& j, T&& val, priority_tag<1>) const | ||||
|     noexcept(noexcept(to_json(j, std::forward<T>(val)))) | ||||
|     -> decltype(to_json(j, std::forward<T>(val)), | ||||
|                 void()) | ||||
|     { | ||||
|         return to_json(std::forward<Json>(j), std::forward<T>(val)); | ||||
|         return to_json(j, std::forward<T>(val)); | ||||
|     } | ||||
| 
 | ||||
|     template <typename Json, typename T> | ||||
|     void call(Json&, T&&, priority_tag<0>) const noexcept | ||||
|     { | ||||
|         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 | ||||
| { | ||||
|     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); | ||||
|     } | ||||
| 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> | |||
|         return '.'; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| // taken from ranges-v3 | ||||
|  | @ -772,8 +831,8 @@ 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; | ||||
| constexpr const auto & to_json = static_const<detail::to_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 | ||||
|  | @ -788,9 +847,10 @@ struct adl_serializer | |||
|     } | ||||
| 
 | ||||
|     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 | |||
| { | ||||
|   private: | ||||
|     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 | ||||
|     using basic_json_t = basic_json<ObjectType, ArrayType, StringType, | ||||
|           BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, | ||||
|  | @ -2967,16 +3027,16 @@ class basic_json | |||
|                                                       uncvref_t<T>>::value, | ||||
|             int> = 0> | ||||
|     // 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 ? | ||||
|     // i know there is a special behaviour for boolean_t* and such | ||||
|     auto get() const noexcept(noexcept(JSONSerializer<uncvref_t<T>>::from_json( | ||||
|         std::declval<basic_json_t const &>(), std::declval<uncvref_t<T> &>()))) | ||||
|         std::declval<const basic_json_t &>(), std::declval<uncvref_t<T> &>()))) | ||||
|         -> 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, | ||||
|                     "user-defined types must be DefaultConstructible and " | ||||
|                     "Types must be DefaultConstructible and " | ||||
|                     "CopyConstructible when used with get"); | ||||
|       type ret; | ||||
|       JSONSerializer<type>::from_json(*this, ret); | ||||
|  | @ -2992,12 +3052,11 @@ class basic_json | |||
|                         detail::has_non_default_from_json<basic_json_t, | ||||
|                                                           uncvref_t<T>>::value, | ||||
|                     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); | ||||
|     } | ||||
| 
 | ||||
|     // TODO what to do with those... | ||||
|     /*! | ||||
|     @brief get a pointer value (explicit) | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue