Flesh out rjp++. Add conversion, parsing, type checking, key access, etc

This commit is contained in:
rexy712
2020-03-05 17:23:30 -08:00
parent 5c7be8fb66
commit 24f9f608a8
7 changed files with 300 additions and 62 deletions

View File

@@ -55,10 +55,9 @@ namespace rjp{
RJP_value* m_value;
bool m_managed = true;
protected:
value(RJP_value* val);
public:
value(void);
explicit value(RJP_value* val, bool managed);
value(const value& val);
value(value&& val);
~value(void);
@@ -69,6 +68,8 @@ namespace rjp{
const RJP_value* raw(void)const;
RJP_value* raw(void);
RJP_data_type type(void)const;
value parent(void)const;
bool is_child_of(const value&)const;
@@ -85,6 +86,7 @@ namespace rjp{
public:
using underlying_type = RJP_int;
public:
using value::value;
integer(underlying_type i);
integer(void);
integer(const value& val);
@@ -107,6 +109,7 @@ namespace rjp{
public:
using underlying_type = RJP_float;
public:
using value::value;
dfloat(underlying_type i);
dfloat(void);
dfloat(const value& val);
@@ -128,6 +131,7 @@ namespace rjp{
public:
using underlying_type = RJP_bool;
public:
using value::value;
boolean(underlying_type i);
boolean(void);
boolean(const value& val);
@@ -141,12 +145,13 @@ namespace rjp{
boolean& operator=(const boolean&) = default;
boolean& operator=(boolean&&) = default;
underlying_type get(void)const;
void set(underlying_type i);
bool get(void)const;
void set(bool i);
};
class null : public value
{
public:
using value::value;
null(void);
null(const value& val);
null(value&& val);
@@ -164,6 +169,7 @@ namespace rjp{
public:
using underlying_type = RJP_string;
public:
using value::value;
string_val(const rexy::string_base& str);
string_val(string&& str);
string_val(void);
@@ -180,8 +186,8 @@ namespace rjp{
string_val& operator=(const string_val&) = default;
string_val& operator=(string_val&&) = default;
rexy::static_string get(void)const&;
string get(void)&&;
rexy::static_string get(void)const;
string steal(void);
void set(const rexy::string_base& str);
void set(string&& str);
@@ -193,18 +199,63 @@ namespace rjp{
member(void) = default;
member(const member&) = default;
member(member&&) = default;
member(const value& val):
value(val){}
member(value&& val):
value(std::move(val)){}
using value::value;
~member(void) = default;
member& operator=(const member&) = default;
member& operator=(member&&) = default;
rexy::static_string key(void)const;
string steal_key(void);
rexy::static_string key(void)const{return rexy::static_string(rjp_member_key(m_value)->value, rjp_member_key(m_value)->length);}
string steal_key(void){return string(m_value);}
};
class iterator_base
{
protected:
class value_wrapper
{
private:
member m_value;
public:
value_wrapper(RJP_value* value, bool managed):
m_value(value, managed){}
member* operator->(void){
return &m_value;
}
};
};
class object_iterator : protected iterator_base
{
protected:
RJP_object_iterator m_it;
public:
object_iterator(void);
object_iterator(RJP_value* v);
object_iterator(const object_iterator&) = delete;
object_iterator(object_iterator&& o);
~object_iterator(void);
object_iterator& operator=(const object_iterator&) = delete;
object_iterator& operator=(object_iterator&& o);
bool operator==(const object_iterator& o)const;
bool operator!=(const object_iterator& o)const;
member operator*(void)const;
value_wrapper operator->(void)const;
object_iterator& operator++(void);
};
class object : public value
{
public:
using iterator = object_iterator;
using const_iterator = const iterator;
public:
using value::value;
object(void);
object(const value& val);
object(value&& val);
@@ -221,11 +272,11 @@ namespace rjp{
key.release();
return T(create_unmanaged(newmemb), i);
}
value add(const rexy::string_base& key);
string_val add(const rexy::string_base& key, const rexy::string_base& val);
string_val add(const rexy::string_base& key, string&& val);
string_val add(string&& key, const rexy::string_base& val);
string_val add(string&& key, string&& val);
member add(const rexy::string_base& key);
member add(const rexy::string_base& key, const rexy::string_base& val);
member add(const rexy::string_base& key, string&& val);
member add(string&& key, const rexy::string_base& val);
member add(string&& key, string&& val);
value remove(const rexy::string_base& key);
value& remove(value& val);
@@ -235,16 +286,42 @@ namespace rjp{
bool has_child(const value&);
value search(const rexy::string_base& key){
RJP_value* result = rjp_search_member(m_value, key.get());
return create_unmanaged(result);
}
iterator begin(void);
const_iterator begin(void)const;
iterator end(void)const;
value search(const rexy::string_base& key);
};
class array_iterator : protected iterator_base
{
protected:
RJP_array_iterator m_it;
public:
array_iterator(void) = default;
array_iterator(RJP_value* v);
array_iterator(const array_iterator&) = delete;
array_iterator(array_iterator&& a);
~array_iterator(void);
array_iterator& operator=(const array_iterator&) = delete;
array_iterator& operator=(array_iterator&& o);
bool operator==(const array_iterator& o)const;
bool operator!=(const array_iterator& o)const;
value operator*(void)const;
value_wrapper operator->(void)const;
array_iterator& operator++(void);
};
class array : public value
{
public:
using iterator = array_iterator;
using const_iterator = const iterator;
public:
using value::value;
array(void);
array(const value& val);
array(value&& val);
@@ -255,29 +332,75 @@ namespace rjp{
array& operator=(const array&) = default;
array& operator=(array&&) = default;
value add(void){
RJP_value* newelem = rjp_add_element(m_value);
return create_unmanaged(newelem);
}
value add(void);
string_val add(const rexy::string_base& val);
string_val add(string&& val);
template<class T = value>
T add(typename T::underlying_type i){
RJP_value* newelem = rjp_add_element(m_value);
return T(create_unmanaged(newelem), i);
}
string_val add(const rexy::string_base& val);
string_val add(string&& val);
value& remove(value& val);
void destroy(value&& val);
iterator begin(void);
iterator end(void);
const_iterator begin(void)const;
const_iterator end(void)const;
};
string to_json(const value& val, int format = RJP_FORMAT_PRETTY);
value parse_json(const rexy::string_base& str);
value parse_json(const char* str);
template<class To, class From, typename std::enable_if<!std::is_lvalue_reference<From>::value,void>::type* = nullptr>
To cast(From&& from){
return To(std::move(from));
namespace detail{
template<class To, class From, bool = std::is_same<std::remove_reference_t<To>,std::remove_reference_t<From>>::value>
struct convert_helper;
template<class To, class From>
struct convert_helper<To,From,false>{
static To perform(From&& t){
return To(std::move(t));
}
};
template<class To, class From>
struct convert_helper<To,From&,false>{
static To perform(const From& t){
return To(const_cast<RJP_value*>(t.raw()), false);
}
};
template<class To, class From>
struct convert_helper<To,From,true>{
static decltype(auto) perform(From&& t){
return std::forward<From>(t);
}
};
}
template<class To, class From>
To convert(From&& from){
return detail::convert_helper<To,From>::perform(std::forward<From>(from));
}
namespace detail{
template<class To, class From>
struct get_ref{
using type = std::remove_reference_t<To>;
};
template<class To, class From>
struct get_ref<To, From&>{
using type = std::remove_reference_t<To>&;
};
template<class To, class From>
struct get_ref<To, From&&>{
using type = std::remove_reference_t<To>&&;
};
}
template<class To, class From>
decltype(auto) cast(From&& from){
return static_cast<typename detail::get_ref<To,From>::type>(std::forward<From>(from));
}
}

View File

@@ -17,12 +17,12 @@
*/
#include <rjp.hpp>
#include <utility> //move
#include <utility> //move, swap
namespace rjp{
array::array(void):
value(rjp_new_array()){}
value(rjp_new_array(), true){}
array::array(const value& val):
value(val)
{
@@ -35,6 +35,10 @@ namespace rjp{
if(rjp_value_type(m_value) != rjp_json_array)
rjp_set_array(m_value);
}
value array::add(void){
RJP_value* newelem = rjp_add_element(m_value);
return create_unmanaged(newelem);
}
string_val array::add(const rexy::string_base& val){
RJP_value* newelem = rjp_add_element(m_value);
return string_val(create_unmanaged(newelem), val);
@@ -52,5 +56,50 @@ namespace rjp{
void array::destroy(value&& val){
rjp_free_element(m_value, val.raw());
}
array::iterator array::begin(void){
return iterator(m_value);
}
array::const_iterator array::begin(void)const{
return const_iterator(m_value);
}
array::iterator array::end(void){
return iterator();
}
array_iterator::array_iterator(RJP_value* v){
rjp_init_array_iterator(&m_it, v);
}
array_iterator::array_iterator(array_iterator&& a):
m_it(a.m_it)
{
a.m_it = RJP_array_iterator{};
}
array_iterator::~array_iterator(void){
rjp_delete_array_iterator(&m_it);
}
array_iterator& array_iterator::operator=(array_iterator&& o){
std::swap(m_it, o.m_it);
return *this;
}
bool array_iterator::operator==(const array_iterator& o)const{
return rjp_array_iterator_current(&m_it) == rjp_array_iterator_current(&o.m_it);
}
bool array_iterator::operator!=(const array_iterator& o)const{
return !(*this == o);
}
value array_iterator::operator*(void)const{
return value(rjp_array_iterator_current(&m_it), false);
}
auto array_iterator::operator->(void)const -> value_wrapper{
return value_wrapper(rjp_array_iterator_current(&m_it), false);
}
array_iterator& array_iterator::operator++(void){
rjp_array_iterator_next(&m_it);
return *this;
}
}

View File

@@ -22,20 +22,20 @@
namespace rjp{
integer::integer(underlying_type i):
value(rjp_new_int(i)){}
value(rjp_new_int(i), true){}
integer::integer(void):
integer(0){}
integer::integer(const value& val):
value(val)
{
if(rjp_value_type(m_value) != rjp_json_integer)
rjp_set_int(m_value, 0);
rjp_set_int(m_value, rjp_get_int(val.raw()));
}
integer::integer(value&& val):
value(std::move(val))
{
if(rjp_value_type(m_value) != rjp_json_integer)
rjp_set_int(m_value, 0);
rjp_set_int(m_value, rjp_get_int(m_value));
}
integer::integer(const value& val, underlying_type i):
value(val)
@@ -55,20 +55,20 @@ namespace rjp{
}
dfloat::dfloat(underlying_type i):
value(rjp_new_float(i)){}
value(rjp_new_float(i), true){}
dfloat::dfloat(void):
dfloat(0){}
dfloat::dfloat(const value& val):
value(val)
{
if(rjp_value_type(m_value) != rjp_json_dfloat)
rjp_set_float(m_value, 0);
rjp_set_float(m_value, rjp_get_float(val.raw()));
}
dfloat::dfloat(value&& val):
value(std::move(val))
{
if(rjp_value_type(m_value) != rjp_json_dfloat)
rjp_set_float(m_value, 0);
rjp_set_float(m_value, rjp_get_float(m_value));
}
dfloat::dfloat(const value& val, underlying_type i):
value(val)
@@ -89,20 +89,20 @@ namespace rjp{
}
boolean::boolean(underlying_type i):
value(rjp_new_bool(i)){}
value(rjp_new_bool(i), true){}
boolean::boolean(void):
boolean(0){}
boolean::boolean(const value& val):
value(val)
{
if(rjp_value_type(m_value) != rjp_json_boolean)
rjp_set_bool(m_value, 0);
rjp_set_bool(m_value, rjp_get_bool(val.raw()));
}
boolean::boolean(value&& val):
value(std::move(val))
{
if(rjp_value_type(m_value) != rjp_json_boolean)
rjp_set_bool(m_value, 0);
rjp_set_bool(m_value, rjp_get_bool(m_value));
}
boolean::boolean(const value& val, underlying_type i):
value(val)
@@ -115,15 +115,15 @@ namespace rjp{
rjp_set_bool(m_value, i);
}
boolean::underlying_type boolean::get(void)const{
bool boolean::get(void)const{
return rjp_get_bool(m_value);
}
void boolean::set(underlying_type i){
void boolean::set(bool i){
rjp_set_bool(m_value, i);
}
null::null(void):
value(rjp_new_null()){}
value(rjp_new_null(), true){}
null::null(const value& val):
value(val)
{

View File

@@ -22,7 +22,7 @@
namespace rjp{
object::object(void):
value(rjp_new_object()){}
value(rjp_new_object(), true){}
object::object(const value& val):
value(val)
{
@@ -35,27 +35,33 @@ namespace rjp{
if(rjp_value_type(m_value) != rjp_json_object)
rjp_set_object(m_value);
}
value object::add(const rexy::string_base& key){
member object::add(const rexy::string_base& key){
RJP_value* newmemb = rjp_add_member_key_copy(m_value, key.get(), key.length());
return create_unmanaged(newmemb);
}
string_val object::add(const rexy::string_base& key, const rexy::string_base& val){
member object::add(const rexy::string_base& key, const rexy::string_base& val){
RJP_value* newmemb = rjp_add_member_key_copy(m_value, key.get(), key.length());
return string_val(create_unmanaged(newmemb), val);
rjp_set_string_copy(newmemb, val.get(), val.length());
return create_unmanaged(newmemb);
}
string_val object::add(const rexy::string_base& key, string&& val){
member object::add(const rexy::string_base& key, string&& val){
RJP_value* newmemb = rjp_add_member_key_copy(m_value, key.get(), key.length());
return string_val(create_unmanaged(newmemb), std::move(val));
auto len = val.length();
rjp_set_string(newmemb, val.release(), len);
return create_unmanaged(newmemb);
}
string_val object::add(string&& key, const rexy::string_base& val){
member object::add(string&& key, const rexy::string_base& val){
auto keylen = key.length();
RJP_value* newmemb = rjp_add_member(m_value, key.release(), keylen);
return string_val(create_unmanaged(newmemb), val);
rjp_set_string_copy(newmemb, val.get(), val.length());
return create_unmanaged(newmemb);
}
string_val object::add(string&& key, string&& val){
member object::add(string&& key, string&& val){
auto keylen = key.length();
auto len = val.length();
RJP_value* newmemb = rjp_add_member(m_value, key.release(), keylen);
return string_val(create_unmanaged(newmemb), std::move(val));
rjp_set_string(newmemb, val.release(), len);
return create_unmanaged(newmemb);
}
value object::remove(const rexy::string_base& key){
@@ -78,4 +84,56 @@ namespace rjp{
bool object::has_child(const value& val){
return val.parent().raw() == m_value;
}
object::iterator object::begin(void){
return iterator(m_value);
}
object::const_iterator object::begin(void)const{
return const_iterator(m_value);
}
object::iterator object::end(void)const{
return iterator();
}
value object::search(const rexy::string_base& key){
RJP_value* result = rjp_search_member(m_value, key.get());
return create_unmanaged(result);
}
object_iterator::object_iterator(void):
m_it(){}
object_iterator::object_iterator(RJP_value* v){
rjp_init_object_iterator(&m_it, v);
}
object_iterator::object_iterator(object_iterator&& o):
m_it(o.m_it)
{
o.m_it = RJP_object_iterator{};
}
object_iterator::~object_iterator(void){
rjp_delete_object_iterator(&m_it);
}
object_iterator& object_iterator::operator=(object_iterator&& o){
std::swap(m_it, o.m_it);
return *this;
}
bool object_iterator::operator==(const object_iterator& o)const{
return rjp_object_iterator_current(&m_it) == rjp_object_iterator_current(&o.m_it);
}
bool object_iterator::operator!=(const object_iterator& o)const{
return !(*this == o);
}
member object_iterator::operator*(void)const{
return member(rjp_object_iterator_current(&m_it), false);
}
auto object_iterator::operator->(void)const -> value_wrapper{
return value_wrapper(rjp_object_iterator_current(&m_it), false);
}
object_iterator& object_iterator::operator++(void){
rjp_object_iterator_next(&m_it);
return *this;
}
}

View File

@@ -25,5 +25,10 @@ namespace rjp{
s.reset(rjp_to_json(val.raw(), format));
return s;
}
value parse_json(const rexy::string_base& str){
return value(rjp_parse(str.get()), true);
}
value parse_json(const char* str){
return value(rjp_parse(str), true);
}
}

View File

@@ -23,9 +23,9 @@
namespace rjp{
string_val::string_val(const rexy::string_base& str):
value(rjp_new_string_copy(str.get(), str.length())){}
value(rjp_new_string_copy(str.get(), str.length()), true){}
string_val::string_val(string&& str):
value(rjp_new_string(str.get(), str.length()))
value(rjp_new_string(str.get(), str.length()), true)
{
str.release();
}
@@ -66,11 +66,11 @@ namespace rjp{
rjp_set_string(m_value, i.release(), length);
}
rexy::static_string string_val::get(void)const&{
rexy::static_string string_val::get(void)const{
const RJP_string* str = rjp_get_cstring(m_value);
return rexy::static_string(str->value, str->length);
}
string string_val::get(void)&&{
string string_val::steal(void){
return string(m_value);
}
void string_val::set(const rexy::string_base& str){

View File

@@ -21,8 +21,9 @@
namespace rjp{
value::value(RJP_value* val):
m_value(val){}
value::value(RJP_value* val, bool managed):
m_value(val),
m_managed(managed){}
value::value(void):
m_value(rjp_new_null()){}
value::value(const value& val):
@@ -55,6 +56,10 @@ namespace rjp{
return m_value;
}
RJP_data_type value::type(void)const{
return rjp_value_type(m_value);
}
value value::parent(void)const{
return create_unmanaged(rjp_value_parent(m_value));
}
@@ -69,15 +74,13 @@ namespace rjp{
}
value value::create_unmanaged(RJP_value* val){
value retval(val);
retval.m_managed = false;
return retval;
return value(val, false);
}
void value::remove_management(value& val){
val.m_managed = false;
}
value value::create_managed(RJP_value* val){
return value(val);
return value(val, true);
}
void value::add_management(value& val){
val.m_managed = true;