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) option(ENABLE_PROFILING "Enable asan" OFF)
mark_as_advanced(ENABLE_PROFILING) 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) if(ENABLE_SHARED)
set(RJP++_LIBFLAGS "-lrjp++ -lrjp") set(RJP++_LIBFLAGS "-lrjp++ -lrjp")
add_library(rjp++ SHARED ${SOURCE_LIST}) 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 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}/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}/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) if(ENABLE_PROFILING)

View File

@ -42,8 +42,8 @@ namespace rjp{
public: public:
using value::value; using value::value;
array(void); array(void);
array(const value& val); explicit array(const value& val);
array(value&& val); explicit array(value&& val);
array(const array&) = default; array(const array&) = default;
array(array&&) = default; array(array&&) = default;
@ -55,7 +55,7 @@ namespace rjp{
std::decay_t<Val> add(typename std::decay_t<Val>::underlying_type t){ std::decay_t<Val> add(typename std::decay_t<Val>::underlying_type t){
RJP_value* newelem = rjp_new_element(m_value); RJP_value* newelem = rjp_new_element(m_value);
detail::set_to_underlying<std::decay_t<Val>>(newelem, t); 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> template<class Val = null>
std::decay_t<Val> add(void){ std::decay_t<Val> add(void){
@ -68,7 +68,7 @@ namespace rjp{
rjp_set_null(newelem); rjp_set_null(newelem);
else else
detail::set_to_underlying<std::decay_t<Val>>(newelem, 0); 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(const RJP_string&);
string_val add(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; using value::value;
integer(underlying_type i); integer(underlying_type i);
integer(void); integer(void);
integer(const value& val); explicit integer(const value& val);
integer(value&& val); explicit integer(value&& val);
integer(const value& val, underlying_type i); integer(const value& val, underlying_type i);
integer(value&& val, underlying_type i); integer(value&& val, underlying_type i);
@ -37,8 +37,8 @@ namespace rjp{
using value::value; using value::value;
dfloat(underlying_type i); dfloat(underlying_type i);
dfloat(void); dfloat(void);
dfloat(const value& val); explicit dfloat(const value& val);
dfloat(value&& val); explicit dfloat(value&& val);
dfloat(const value& val, underlying_type i); dfloat(const value& val, underlying_type i);
dfloat(value&& val, underlying_type i); dfloat(value&& val, underlying_type i);
@ -59,8 +59,8 @@ namespace rjp{
using value::value; using value::value;
boolean(underlying_type i); boolean(underlying_type i);
boolean(void); boolean(void);
boolean(const value& val); explicit boolean(const value& val);
boolean(value&& val); explicit boolean(value&& val);
boolean(const value& val, underlying_type i); boolean(const value& val, underlying_type i);
boolean(value&& val, underlying_type i); boolean(value&& val, underlying_type i);
@ -80,8 +80,8 @@ namespace rjp{
public: public:
using value::value; using value::value;
null(void); null(void);
null(const value& val); explicit null(const value& val);
null(value&& val); explicit null(value&& val);
null(const null&) = default; null(const null&) = default;
null(null&&) = default; null(null&&) = default;

View File

@ -44,8 +44,8 @@ namespace rjp{
public: public:
using value::value; using value::value;
object(void); object(void);
object(const value& val); explicit object(const value& val);
object(value&& val); explicit object(value&& val);
object(const object&) = default; object(const object&) = default;
object(object&&) = default; object(object&&) = default;

View File

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

View File

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

View File

@ -17,8 +17,8 @@ namespace rjp{
string_val(const rexy::string_base& str); string_val(const rexy::string_base& str);
string_val(string&& str); string_val(string&& str);
string_val(void); string_val(void);
string_val(const value& val); explicit string_val(const value& val);
string_val(value&& val); explicit string_val(value&& val);
string_val(const value& val, const rexy::string_base& i); string_val(const value& val, const rexy::string_base& i);
string_val(value&& val, const rexy::string_base& i); string_val(value&& val, const rexy::string_base& i);
string_val(const value& val, string&& i); string_val(const value& val, string&& i);

View File

@ -6,6 +6,22 @@
namespace rjp{ 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 class value
{ {
protected: protected:
@ -30,6 +46,8 @@ namespace rjp{
RJP_data_type type(void)const; RJP_data_type type(void)const;
detail::vget_proxy get(void)const;
value parent(void)const; value parent(void)const;
bool is_child_of(const value&)const; bool is_child_of(const value&)const;

View File

@ -39,17 +39,17 @@ namespace rjp{
string_val array::add(const RJP_string& s){ string_val array::add(const RJP_string& s){
RJP_value* newelem = rjp_new_element(m_value); RJP_value* newelem = rjp_new_element(m_value);
rjp_set_string(newelem, s.value, s.length); 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){ string_val array::add(RJP_string&& s){
RJP_value* newelem = rjp_new_element(m_value); RJP_value* newelem = rjp_new_element(m_value);
rjp_set_string_steal(newelem, s.value, s.length); 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){ string_val array::add(const char* c, RJP_index len){
RJP_value* newelem = rjp_new_element(m_value); RJP_value* newelem = rjp_new_element(m_value);
rjp_set_string(newelem, c, len); 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){ string_val array::add(const rexy::string_base& s){
return add(s.get(), s.length()); return add(s.get(), s.length());
@ -58,7 +58,7 @@ namespace rjp{
RJP_value* newelem = rjp_new_element(m_value); RJP_value* newelem = rjp_new_element(m_value);
auto len = s.length(); auto len = s.length();
rjp_set_string_steal(newelem, s.release(), len); rjp_set_string_steal(newelem, s.release(), len);
return create_unmanaged(newelem); return string_val(create_unmanaged(newelem));
} }
value& array::remove(value& val){ value& array::remove(value& val){

View File

@ -66,6 +66,10 @@ namespace rjp{
RJP_data_type value::type(void)const{ RJP_data_type value::type(void)const{
return rjp_value_type(m_value); return rjp_value_type(m_value);
} }
detail::vget_proxy value::get(void)const{
return detail::vget_proxy(this);
}
value value::parent(void)const{ value value::parent(void)const{
return create_unmanaged(rjp_value_parent(m_value)); 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();
}
}