Added rjp++ dispatcher and proxy type for get operations. Makes it easier to make generic programs around.

This commit is contained in:
rexy712 2020-03-27 12:40:37 -07:00
parent ee0a1d48da
commit 5bebbe1d33
12 changed files with 178 additions and 22 deletions

View File

@ -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)

View File

@ -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<Val> add(typename std::decay_t<Val>::underlying_type t){
RJP_value* newelem = rjp_new_element(m_value);
detail::set_to_underlying<std::decay_t<Val>>(newelem, t);
return create_unmanaged(newelem);
return std::decay_t<Val>(create_unmanaged(newelem));
}
template<class Val = null>
std::decay_t<Val> add(void){
@ -68,7 +68,7 @@ namespace rjp{
rjp_set_null(newelem);
else
detail::set_to_underlying<std::decay_t<Val>>(newelem, 0);
return create_unmanaged(newelem);
return std::decay_t<Val>(create_unmanaged(newelem));
}
string_val add(const RJP_string&);
string_val add(RJP_string&&);

108
rjp++/include/dispatch.hpp Normal file
View File

@ -0,0 +1,108 @@
#ifndef RJP_DISPATCH_HPP
#define RJP_DISPATCH_HPP
#include "rjp_internal.hpp"
#include <type_traits> //is_same, true_type, false_type
#include <utility> //forward
namespace rjp{
namespace detail{
template<RJP_data_type T>
struct to_value_type;
template<>
struct to_value_type<rjp_json_object>{
using type = rjp::object;
};
template<>
struct to_value_type<rjp_json_string>{
using type = rjp::string_val;
};
template<>
struct to_value_type<rjp_json_integer>{
using type = rjp::integer;
};
template<>
struct to_value_type<rjp_json_dfloat>{
using type = rjp::dfloat;
};
template<>
struct to_value_type<rjp_json_boolean>{
using type = rjp::boolean;
};
template<>
struct to_value_type<rjp_json_array>{
using type = rjp::array;
};
template<>
struct to_value_type<rjp_json_null>{
using type = rjp::null;
};
template<RJP_data_type T>
using to_value_type_t = typename to_value_type<T>::type;
template<RJP_data_type T>
struct next_data_type;
template<>
struct next_data_type<rjp_json_object>{
static constexpr RJP_data_type value = rjp_json_string;
};
template<>
struct next_data_type<rjp_json_string>{
static constexpr RJP_data_type value = rjp_json_integer;
};
template<>
struct next_data_type<rjp_json_integer>{
static constexpr RJP_data_type value = rjp_json_dfloat;
};
template<>
struct next_data_type<rjp_json_dfloat>{
static constexpr RJP_data_type value = rjp_json_boolean;
};
template<>
struct next_data_type<rjp_json_boolean>{
static constexpr RJP_data_type value = rjp_json_array;
};
template<>
struct next_data_type<rjp_json_array>{
static constexpr RJP_data_type value = rjp_json_null;
};
template<RJP_data_type T>
struct has_next_data_type_helper{
template<class U, bool = (sizeof(U) == sizeof(U))>
static std::true_type check(U*);
static std::false_type check(...);
static constexpr bool value = std::is_same<std::true_type,decltype(check((next_data_type<T>*)0))>::value;
};
template<RJP_data_type T>
struct has_next_data_type{
static constexpr bool value = has_next_data_type_helper<T>::value;
};
template<class Func, class Val, RJP_data_type T>
decltype(auto) dispatch_helper(Func&& fun, Val&& v){
if(v.type() == T){
return std::forward<Func>(fun)(static_cast<detail::to_value_type_t<T>>(std::forward<Val>(v)));
}
if constexpr(detail::has_next_data_type<T>::value){
return dispatch_helper<Func,Val,detail::next_data_type<T>::value>(std::forward<Func>(fun), std::forward<Val>(v));
}
}
}
template<class Func, class Val>
decltype(auto) dispatch(Func&& fun, Val&& v){
return detail::dispatch_helper<Func,Val,rjp_json_object>(std::forward<Func>(fun), std::forward<Val>(v));
}
template<class... Ts>
struct dispatcher : public Ts...
{
using Ts::operator()...;
};
template<class... Ts>
dispatcher(Ts&&...) -> dispatcher<Ts...>;
}
#endif

View File

@ -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;

View File

@ -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;

View File

@ -10,5 +10,6 @@
#include <rjp++/string.hpp>
#include <rjp++/string_val.hpp>
#include <rjp++/value.hpp>
#include <rjp++/dispatch.hpp>
#endif

View File

@ -29,5 +29,6 @@
#include "string_val.hpp"
#include "value.hpp"
#include "parse.hpp"
#include "dispatch.hpp"
#endif

View File

@ -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);

View File

@ -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;

View File

@ -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){

View File

@ -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));

24
rjp++/src/vget_proxy.cpp Normal file
View File

@ -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<const rjp::integer>(*m_value).get();
}
vget_proxy::operator bool(void)const{
return rjp::cast<const rjp::boolean>(*m_value).get();
}
vget_proxy::operator rexy::static_string(void)const{
return rjp::cast<const rjp::string_val>(*m_value).get();
}
vget_proxy::operator double(void)const{
return rjp::cast<const rjp::dfloat>(*m_value).get();
}
}