From 5bebbe1d3365367de644ad15697962db07f9dca2 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Fri, 27 Mar 2020 12:40:37 -0700 Subject: [PATCH] Added rjp++ dispatcher and proxy type for get operations. Makes it easier to make generic programs around. --- rjp++/CMakeLists.txt | 4 +- rjp++/include/array.hpp | 8 +-- rjp++/include/dispatch.hpp | 108 +++++++++++++++++++++++++++++++++ rjp++/include/integral.hpp | 16 ++--- rjp++/include/object.hpp | 4 +- rjp++/include/rjp.hpp | 1 + rjp++/include/rjp_internal.hpp | 1 + rjp++/include/string_val.hpp | 4 +- rjp++/include/value.hpp | 18 ++++++ rjp++/src/array.cpp | 8 +-- rjp++/src/value.cpp | 4 ++ rjp++/src/vget_proxy.cpp | 24 ++++++++ 12 files changed, 178 insertions(+), 22 deletions(-) create mode 100644 rjp++/include/dispatch.hpp create mode 100644 rjp++/src/vget_proxy.cpp diff --git a/rjp++/CMakeLists.txt b/rjp++/CMakeLists.txt index 4714571..290b5d4 100644 --- a/rjp++/CMakeLists.txt +++ b/rjp++/CMakeLists.txt @@ -13,7 +13,7 @@ option(BUILD_TESTS "Build test programs" OFF) option(ENABLE_PROFILING "Enable asan" OFF) mark_as_advanced(ENABLE_PROFILING) -set(SOURCE_LIST "src/allocator.cpp" "src/array.cpp" "src/integral.cpp" "src/object.cpp" "src/rjp.cpp" "src/string.cpp" "src/string_val.cpp" "src/value.cpp") +set(SOURCE_LIST "src/allocator.cpp" "src/array.cpp" "src/integral.cpp" "src/object.cpp" "src/rjp.cpp" "src/string.cpp" "src/string_val.cpp" "src/value.cpp" "src/vget_proxy.cpp") if(ENABLE_SHARED) set(RJP++_LIBFLAGS "-lrjp++ -lrjp") add_library(rjp++ SHARED ${SOURCE_LIST}) @@ -32,7 +32,7 @@ set_target_properties(rjp++ PROPERTIES PUBLIC_HEADER ${INCLUDE_PATH}/rjp.hpp) set(CPP_HEADERS ${INCLUDE_PATH}/array.hpp ${INCLUDE_PATH}/integral.hpp ${INCLUDE_PATH}/iterator.hpp ${INCLUDE_PATH}/member.hpp ${INCLUDE_PATH}/object.hpp ${INCLUDE_PATH}/parse.hpp ${INCLUDE_PATH}/string.hpp ${INCLUDE_PATH}/string_val.hpp ${INCLUDE_PATH}/value.hpp - ${INCLUDE_PATH}/rjp_util.hpp) + ${INCLUDE_PATH}/rjp_util.hpp ${INCLUDE_PATH}/dispatch.hpp) if(ENABLE_PROFILING) diff --git a/rjp++/include/array.hpp b/rjp++/include/array.hpp index f55f6f5..5cde4f2 100644 --- a/rjp++/include/array.hpp +++ b/rjp++/include/array.hpp @@ -42,8 +42,8 @@ namespace rjp{ public: using value::value; array(void); - array(const value& val); - array(value&& val); + explicit array(const value& val); + explicit array(value&& val); array(const array&) = default; array(array&&) = default; @@ -55,7 +55,7 @@ namespace rjp{ std::decay_t add(typename std::decay_t::underlying_type t){ RJP_value* newelem = rjp_new_element(m_value); detail::set_to_underlying>(newelem, t); - return create_unmanaged(newelem); + return std::decay_t(create_unmanaged(newelem)); } template std::decay_t add(void){ @@ -68,7 +68,7 @@ namespace rjp{ rjp_set_null(newelem); else detail::set_to_underlying>(newelem, 0); - return create_unmanaged(newelem); + return std::decay_t(create_unmanaged(newelem)); } string_val add(const RJP_string&); string_val add(RJP_string&&); diff --git a/rjp++/include/dispatch.hpp b/rjp++/include/dispatch.hpp new file mode 100644 index 0000000..0ece839 --- /dev/null +++ b/rjp++/include/dispatch.hpp @@ -0,0 +1,108 @@ +#ifndef RJP_DISPATCH_HPP +#define RJP_DISPATCH_HPP + +#include "rjp_internal.hpp" +#include //is_same, true_type, false_type +#include //forward + +namespace rjp{ + + namespace detail{ + template + struct to_value_type; + + template<> + struct to_value_type{ + using type = rjp::object; + }; + template<> + struct to_value_type{ + using type = rjp::string_val; + }; + template<> + struct to_value_type{ + using type = rjp::integer; + }; + template<> + struct to_value_type{ + using type = rjp::dfloat; + }; + template<> + struct to_value_type{ + using type = rjp::boolean; + }; + template<> + struct to_value_type{ + using type = rjp::array; + }; + template<> + struct to_value_type{ + using type = rjp::null; + }; + template + using to_value_type_t = typename to_value_type::type; + + template + struct next_data_type; + template<> + struct next_data_type{ + static constexpr RJP_data_type value = rjp_json_string; + }; + template<> + struct next_data_type{ + static constexpr RJP_data_type value = rjp_json_integer; + }; + template<> + struct next_data_type{ + static constexpr RJP_data_type value = rjp_json_dfloat; + }; + template<> + struct next_data_type{ + static constexpr RJP_data_type value = rjp_json_boolean; + }; + template<> + struct next_data_type{ + static constexpr RJP_data_type value = rjp_json_array; + }; + template<> + struct next_data_type{ + static constexpr RJP_data_type value = rjp_json_null; + }; + + template + struct has_next_data_type_helper{ + template + static std::true_type check(U*); + static std::false_type check(...); + + static constexpr bool value = std::is_same*)0))>::value; + }; + template + struct has_next_data_type{ + static constexpr bool value = has_next_data_type_helper::value; + }; + template + decltype(auto) dispatch_helper(Func&& fun, Val&& v){ + if(v.type() == T){ + return std::forward(fun)(static_cast>(std::forward(v))); + } + if constexpr(detail::has_next_data_type::value){ + return dispatch_helper::value>(std::forward(fun), std::forward(v)); + } + } + } + template + decltype(auto) dispatch(Func&& fun, Val&& v){ + return detail::dispatch_helper(std::forward(fun), std::forward(v)); + } + template + struct dispatcher : public Ts... + { + using Ts::operator()...; + }; + + template + dispatcher(Ts&&...) -> dispatcher; +} + +#endif diff --git a/rjp++/include/integral.hpp b/rjp++/include/integral.hpp index 281a34c..2cd9806 100644 --- a/rjp++/include/integral.hpp +++ b/rjp++/include/integral.hpp @@ -14,8 +14,8 @@ namespace rjp{ using value::value; integer(underlying_type i); integer(void); - integer(const value& val); - integer(value&& val); + explicit integer(const value& val); + explicit integer(value&& val); integer(const value& val, underlying_type i); integer(value&& val, underlying_type i); @@ -37,8 +37,8 @@ namespace rjp{ using value::value; dfloat(underlying_type i); dfloat(void); - dfloat(const value& val); - dfloat(value&& val); + explicit dfloat(const value& val); + explicit dfloat(value&& val); dfloat(const value& val, underlying_type i); dfloat(value&& val, underlying_type i); @@ -59,8 +59,8 @@ namespace rjp{ using value::value; boolean(underlying_type i); boolean(void); - boolean(const value& val); - boolean(value&& val); + explicit boolean(const value& val); + explicit boolean(value&& val); boolean(const value& val, underlying_type i); boolean(value&& val, underlying_type i); @@ -80,8 +80,8 @@ namespace rjp{ public: using value::value; null(void); - null(const value& val); - null(value&& val); + explicit null(const value& val); + explicit null(value&& val); null(const null&) = default; null(null&&) = default; diff --git a/rjp++/include/object.hpp b/rjp++/include/object.hpp index 7f8e614..64abd5d 100644 --- a/rjp++/include/object.hpp +++ b/rjp++/include/object.hpp @@ -44,8 +44,8 @@ namespace rjp{ public: using value::value; object(void); - object(const value& val); - object(value&& val); + explicit object(const value& val); + explicit object(value&& val); object(const object&) = default; object(object&&) = default; diff --git a/rjp++/include/rjp.hpp b/rjp++/include/rjp.hpp index 841dc16..8480830 100644 --- a/rjp++/include/rjp.hpp +++ b/rjp++/include/rjp.hpp @@ -10,5 +10,6 @@ #include #include #include +#include #endif diff --git a/rjp++/include/rjp_internal.hpp b/rjp++/include/rjp_internal.hpp index a203f0e..a3eff2e 100644 --- a/rjp++/include/rjp_internal.hpp +++ b/rjp++/include/rjp_internal.hpp @@ -29,5 +29,6 @@ #include "string_val.hpp" #include "value.hpp" #include "parse.hpp" +#include "dispatch.hpp" #endif diff --git a/rjp++/include/string_val.hpp b/rjp++/include/string_val.hpp index a6fc085..c2c60c0 100644 --- a/rjp++/include/string_val.hpp +++ b/rjp++/include/string_val.hpp @@ -17,8 +17,8 @@ namespace rjp{ string_val(const rexy::string_base& str); string_val(string&& str); string_val(void); - string_val(const value& val); - string_val(value&& val); + explicit string_val(const value& val); + explicit string_val(value&& val); string_val(const value& val, const rexy::string_base& i); string_val(value&& val, const rexy::string_base& i); string_val(const value& val, string&& i); diff --git a/rjp++/include/value.hpp b/rjp++/include/value.hpp index 0cad6f0..c32531b 100644 --- a/rjp++/include/value.hpp +++ b/rjp++/include/value.hpp @@ -6,6 +6,22 @@ namespace rjp{ + class value; + + namespace detail{ + class vget_proxy + { + private: + const rjp::value* m_value; + public: + vget_proxy(const rjp::value* v); + operator int(void)const; + operator bool(void)const; + operator rexy::static_string(void)const; + operator double(void)const; + }; + } + class value { protected: @@ -30,6 +46,8 @@ namespace rjp{ RJP_data_type type(void)const; + detail::vget_proxy get(void)const; + value parent(void)const; bool is_child_of(const value&)const; diff --git a/rjp++/src/array.cpp b/rjp++/src/array.cpp index 2df45f9..9b94f4d 100644 --- a/rjp++/src/array.cpp +++ b/rjp++/src/array.cpp @@ -39,17 +39,17 @@ namespace rjp{ string_val array::add(const RJP_string& s){ RJP_value* newelem = rjp_new_element(m_value); rjp_set_string(newelem, s.value, s.length); - return create_unmanaged(newelem); + return string_val(create_unmanaged(newelem)); } string_val array::add(RJP_string&& s){ RJP_value* newelem = rjp_new_element(m_value); rjp_set_string_steal(newelem, s.value, s.length); - return create_unmanaged(newelem); + return string_val(create_unmanaged(newelem)); } string_val array::add(const char* c, RJP_index len){ RJP_value* newelem = rjp_new_element(m_value); rjp_set_string(newelem, c, len); - return create_unmanaged(newelem); + return string_val(create_unmanaged(newelem)); } string_val array::add(const rexy::string_base& s){ return add(s.get(), s.length()); @@ -58,7 +58,7 @@ namespace rjp{ RJP_value* newelem = rjp_new_element(m_value); auto len = s.length(); rjp_set_string_steal(newelem, s.release(), len); - return create_unmanaged(newelem); + return string_val(create_unmanaged(newelem)); } value& array::remove(value& val){ diff --git a/rjp++/src/value.cpp b/rjp++/src/value.cpp index e043866..4f1b1a7 100644 --- a/rjp++/src/value.cpp +++ b/rjp++/src/value.cpp @@ -66,6 +66,10 @@ namespace rjp{ RJP_data_type value::type(void)const{ return rjp_value_type(m_value); } + detail::vget_proxy value::get(void)const{ + return detail::vget_proxy(this); + } + value value::parent(void)const{ return create_unmanaged(rjp_value_parent(m_value)); diff --git a/rjp++/src/vget_proxy.cpp b/rjp++/src/vget_proxy.cpp new file mode 100644 index 0000000..b3bf793 --- /dev/null +++ b/rjp++/src/vget_proxy.cpp @@ -0,0 +1,24 @@ +#include "value.hpp" +#include "integral.hpp" +#include "string_val.hpp" +#include "string.hpp" +#include "rjp_util.hpp" + +namespace rjp::detail{ + + vget_proxy::vget_proxy(const rjp::value* v): + m_value(v){} + vget_proxy::operator int(void)const{ + return rjp::cast(*m_value).get(); + } + vget_proxy::operator bool(void)const{ + return rjp::cast(*m_value).get(); + } + vget_proxy::operator rexy::static_string(void)const{ + return rjp::cast(*m_value).get(); + } + vget_proxy::operator double(void)const{ + return rjp::cast(*m_value).get(); + } + +}