Add callback based parsing to rjp++
This commit is contained in:
parent
32db7680d7
commit
caaf29842d
@ -24,12 +24,59 @@
|
||||
#include "value.hpp"
|
||||
|
||||
#include <utility> //move
|
||||
#include <tuple>
|
||||
|
||||
namespace rjp{
|
||||
|
||||
string to_json(const value& val, int format = RJP_FORMAT_PRETTY);
|
||||
value parse_json(const rexy::string_base& str, RJP_parse_flag = RJP_PARSE_NONE);
|
||||
value parse_json(const char* str, RJP_parse_flag = RJP_PARSE_NONE);
|
||||
namespace detail{
|
||||
template<int... Indexes>
|
||||
struct sequence_tup{};
|
||||
template<int N, int... Indexes>
|
||||
struct sequence_gen : public sequence_gen<N-1, Indexes..., sizeof...(Indexes)>{};
|
||||
template<int... Indexes>
|
||||
struct sequence_gen<0, Indexes...>{
|
||||
using type = sequence_tup<Indexes...>;
|
||||
};
|
||||
|
||||
template<class Func, class... Args>
|
||||
struct parse_helper{
|
||||
Func&& func;
|
||||
std::tuple<Args...> tup;
|
||||
|
||||
template<int... Indexes>
|
||||
int operator()(char* c, int size, sequence_tup<Indexes...>)const{
|
||||
return std::forward<Func>(func)(c, size, std::get<Indexes>(tup)...);
|
||||
}
|
||||
};
|
||||
struct invoker{
|
||||
virtual ~invoker(void){}
|
||||
virtual int run(char*, int)const = 0;
|
||||
};
|
||||
template<class Func, class... Args>
|
||||
struct invoker_impl : public invoker{
|
||||
parse_helper<Func,Args...> ph;
|
||||
|
||||
template<class Fn, class... Ts>
|
||||
invoker_impl(Fn&& fn, Ts&&... ts):
|
||||
ph{std::forward<Fn>(fn), {std::forward<Ts>(ts)...}}{}
|
||||
int run(char* c, int size)const override{
|
||||
return ph(c, size, typename sequence_gen<sizeof...(Args)>::type{});
|
||||
}
|
||||
};
|
||||
|
||||
int irjp_parse_callback(char* dest, int size, void* userdata);
|
||||
}
|
||||
template<class Func, class... Args>
|
||||
value parse_json(RJP_parse_flag f, Func&& func, Args&&... args){
|
||||
RJP_parse_callback cb;
|
||||
detail::invoker_impl<Func,Args...> inv(std::forward<Func>(func), std::forward<Args>(args)...);
|
||||
cb.data = static_cast<void*>(&inv);
|
||||
cb.read = detail::irjp_parse_callback;
|
||||
return value(rjp_parse_cback(f, &cb), true);
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
template<class To, class From, bool = std::is_same<std::remove_reference_t<To>,std::remove_reference_t<From>>::value>
|
||||
|
||||
@ -22,6 +22,9 @@ namespace rjp{
|
||||
value& operator=(const value& val);
|
||||
value& operator=(value&& val);
|
||||
|
||||
operator bool(void)const;
|
||||
bool valid(void)const;
|
||||
|
||||
const RJP_value* raw(void)const;
|
||||
RJP_value* raw(void);
|
||||
|
||||
|
||||
@ -32,4 +32,10 @@ namespace rjp{
|
||||
value parse_json(const char* str, RJP_parse_flag flags){
|
||||
return value(rjp_parse(str, flags), true);
|
||||
}
|
||||
namespace detail{
|
||||
int irjp_parse_callback(char* dest, int size, void* userdata){
|
||||
invoker* inv = static_cast<invoker*>(userdata);
|
||||
return inv->run(dest, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,6 +49,12 @@ namespace rjp{
|
||||
std::swap(val.m_managed, m_managed);
|
||||
return *this;
|
||||
}
|
||||
value::operator bool(void)const{
|
||||
return m_value != nullptr;
|
||||
}
|
||||
bool value::valid(void)const{
|
||||
return m_value != nullptr;
|
||||
}
|
||||
|
||||
const RJP_value* value::raw(void)const{
|
||||
return m_value;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user