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