Added rjp++ dispatcher and proxy type for get operations. Makes it easier to make generic programs around.
This commit is contained in:
parent
ee0a1d48da
commit
5bebbe1d33
@ -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)
|
||||
|
||||
@ -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
108
rjp++/include/dispatch.hpp
Normal 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
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -10,5 +10,6 @@
|
||||
#include <rjp++/string.hpp>
|
||||
#include <rjp++/string_val.hpp>
|
||||
#include <rjp++/value.hpp>
|
||||
#include <rjp++/dispatch.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@ -29,5 +29,6 @@
|
||||
#include "string_val.hpp"
|
||||
#include "value.hpp"
|
||||
#include "parse.hpp"
|
||||
#include "dispatch.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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){
|
||||
|
||||
@ -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
24
rjp++/src/vget_proxy.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user