From 24f9f608a8e565df2b1a1b048a6d40a223c0aeaa Mon Sep 17 00:00:00 2001 From: rexy712 Date: Thu, 5 Mar 2020 17:23:30 -0800 Subject: [PATCH] Flesh out rjp++. Add conversion, parsing, type checking, key access, etc --- rjp++/include/rjp.hpp | 177 +++++++++++++++++++++++++++++++++------ rjp++/src/array.cpp | 53 +++++++++++- rjp++/src/integral.cpp | 24 +++--- rjp++/src/object.cpp | 78 ++++++++++++++--- rjp++/src/rjp.cpp | 7 +- rjp++/src/string_val.cpp | 8 +- rjp++/src/value.cpp | 15 ++-- 7 files changed, 300 insertions(+), 62 deletions(-) diff --git a/rjp++/include/rjp.hpp b/rjp++/include/rjp.hpp index 2099407..df28529 100644 --- a/rjp++/include/rjp.hpp +++ b/rjp++/include/rjp.hpp @@ -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 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::value,void>::type* = nullptr> - To cast(From&& from){ - return To(std::move(from)); + namespace detail{ + template,std::remove_reference_t>::value> + struct convert_helper; + template + struct convert_helper{ + static To perform(From&& t){ + return To(std::move(t)); + } + }; + template + struct convert_helper{ + static To perform(const From& t){ + return To(const_cast(t.raw()), false); + } + }; + template + struct convert_helper{ + static decltype(auto) perform(From&& t){ + return std::forward(t); + } + }; + } + + template + To convert(From&& from){ + return detail::convert_helper::perform(std::forward(from)); + } + + namespace detail{ + template + struct get_ref{ + using type = std::remove_reference_t; + }; + template + struct get_ref{ + using type = std::remove_reference_t&; + }; + template + struct get_ref{ + using type = std::remove_reference_t&&; + }; + } + + template + decltype(auto) cast(From&& from){ + return static_cast::type>(std::forward(from)); } } diff --git a/rjp++/src/array.cpp b/rjp++/src/array.cpp index e8e26f1..751f5a7 100644 --- a/rjp++/src/array.cpp +++ b/rjp++/src/array.cpp @@ -17,12 +17,12 @@ */ #include -#include //move +#include //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; + } } diff --git a/rjp++/src/integral.cpp b/rjp++/src/integral.cpp index e75e8f4..b4e776a 100644 --- a/rjp++/src/integral.cpp +++ b/rjp++/src/integral.cpp @@ -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) { diff --git a/rjp++/src/object.cpp b/rjp++/src/object.cpp index 0648b31..8a40e82 100644 --- a/rjp++/src/object.cpp +++ b/rjp++/src/object.cpp @@ -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; + } + } diff --git a/rjp++/src/rjp.cpp b/rjp++/src/rjp.cpp index fa70f7a..5d31517 100644 --- a/rjp++/src/rjp.cpp +++ b/rjp++/src/rjp.cpp @@ -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); + } } diff --git a/rjp++/src/string_val.cpp b/rjp++/src/string_val.cpp index 2721170..28d346b 100644 --- a/rjp++/src/string_val.cpp +++ b/rjp++/src/string_val.cpp @@ -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){ diff --git a/rjp++/src/value.cpp b/rjp++/src/value.cpp index 14a51a2..091e1cb 100644 --- a/rjp++/src/value.cpp +++ b/rjp++/src/value.cpp @@ -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;