diff --git a/libdvbtee/value/Makefile.am b/libdvbtee/value/Makefile.am index bf792f22..fc7caa36 100644 --- a/libdvbtee/value/Makefile.am +++ b/libdvbtee/value/Makefile.am @@ -1,12 +1,12 @@ lib_LTLIBRARIES = libvalueobj.la -libvalueobj_la_SOURCES = value.cpp object.cpp array.cpp +libvalueobj_la_SOURCES = value.cpp object.cpp array.cpp handle.cpp -EXTRA_DIST=value.h object.h array.h +EXTRA_DIST=value.h object.h array.h handle.h VALOBJ_LIBRARY_VERSION=1:0:0 libvalueobj_la_LDFLAGS = -version-info $(VALOBJ_LIBRARY_VERSION) library_includedir=$(includedir)/value -library_include_HEADERS = value.h object.h array.h +library_include_HEADERS = value.h object.h array.h handle.h diff --git a/libdvbtee/value/array.cpp b/libdvbtee/value/array.cpp index e99330e9..bb1fb36e 100644 --- a/libdvbtee/value/array.cpp +++ b/libdvbtee/value/array.cpp @@ -32,48 +32,11 @@ using namespace valueobj; namespace valueobj { -template -const ValueBase* Array::push(T val) -{ - return push(val, ""); -} - -template -const ValueBase* Array::set(std::string key, T val) -{ - if (!key.length()) return NULL; - const ValueBase* v = push(val, key); - if (v) updateIndex(key, v); - return v; -} - -template -const ValueBase* Array::set(int key, T val) -{ - return set(intToStr(key), val); -} - -template -const ValueBase* Array::pushByRef(T& val, std::string idx) -{ - Value *v = new Value(idx, val); - vector.push_back(v); - ++(*v); // increment refcount - return v; -} - -template -const ValueBase* Array::push(T val, std::string idx) -{ - return pushByRef(val, idx); -} - - template const T& Array::get(unsigned int &idx, T& def) const { if (idx <= vector.size()) { - Value *val = (Value*)vector[idx]; + Value *val = vector.at(idx); if (val->checkType(typeid(T))) return val->get(); } @@ -82,11 +45,9 @@ const T& Array::get(unsigned int &idx, T& def) const } #define IMPL_ARRAY_TMPL(T) \ -template const ValueBase* Array::push(T val); \ -template const ValueBase* Array::set(std::string key, T val); \ -template const ValueBase* Array::set(int key, T val); \ -template const ValueBase* Array::pushByRef(T& val, std::string idx); \ -template const ValueBase* Array::push(T val, std::string idx); \ +template Handle& Array::push(T val); \ +template bool Array::set(std::string key, T val); \ +template bool Array::set(int key, T val); \ template const T& Array::get(unsigned int &idx, T& def) const IMPL_ARRAY_TMPL(int); @@ -106,6 +67,7 @@ IMPL_ARRAY_TMPL(Array); IMPL_ARRAY_TMPL(Object); static ReferencedValueUndefined& valueUndefined = ReferencedValueUndefined::instance(); +static Handle valueUndefinedHdl = Handle((ValueBase*)&valueUndefined); Array::Array(std::string idx) : idxField(idx) @@ -126,16 +88,30 @@ Array::~Array() Array::Array(const Array &obj) { for (KeyValueVector::const_iterator it = obj.vector.begin(); it != obj.vector.end(); ++it) { - ValueBase *v = *it; - push(v); - const std::string& n = v->getName(); - if (n.length()) updateIndex(n, v); + Handle& hdl = push(*it); + const std::string& n = hdl.get()->getName(); + if (n.length()) updateIndex(n, hdl); } #if DBG fprintf(stderr, "%s(copy) %lu\n", __func__, vector.size()); #endif } +Handle& Array::push(Handle hdl) +{ + vector.push_back(hdl); + return vector.back(); +} + +bool Array::set(std::string key, Handle hdl) +{ + if (!key.length()) return false; + + Handle& h = push(hdl); + updateIndex(key, h); + return true; +} + const std::string Array::toJson() const { std::stringstream s; @@ -147,7 +123,7 @@ const std::string Array::toJson() const for (KeyValueVector::const_iterator it = vector.begin(); it != vector.end(); ++it) { if (it != vector.begin()) s << ", "; - s << (*it)->toJson(); + s << it->toJson(); } s << " ]"; @@ -165,17 +141,17 @@ const std::string &Array::getIndex() const return idxField; } -const ValueBase* Array::get(unsigned int idx) const +Handle& Array::get(unsigned int idx) const { if (idx <= vector.size()) - return vector[idx]; + return (Handle&)vector.at(idx); - return &valueUndefined; + return valueUndefinedHdl; } -void Array::updateIndex(std::string key, const ValueBase *val) +void Array::updateIndex(std::string key, Handle& val) { - if (key.length()) indices[key] = val; + if (key.length()) indices[key] = &val; } std::string &Array::assignIndex(Object &obj, std::string &index) @@ -189,27 +165,22 @@ std::string &Array::assignIndex(Object &obj, std::string &index) return index; } -const ValueBase* Array::getByName(std::string idx) const +Handle& Array::getByName(std::string idx) const { - std::map::const_iterator it = indices.find(idx); + std::map::const_iterator it = indices.find(idx); if (it == indices.end()) - return &valueUndefined; + return valueUndefinedHdl; - return it->second; + return *(it->second); } -const ValueBase* Array::getByName(unsigned int idx) const +Handle& Array::getByName(unsigned int idx) const { return getByName(intToStr(idx)); } void Array::clear() { - for (KeyValueVector::iterator it = vector.begin(); it != vector.end(); ++it) - { - // decrement refcount. if refcount becomes zero, delete - if (0 == (--(**it)).getRefCnt()) delete *it; - } vector.clear(); indices.clear(); } @@ -221,91 +192,32 @@ const std::string Array::intToStr(int i) const return s.str(); } -const ValueBase* Array::pushObject(Object &val, std::string idx) +Handle& Array::pushObject(Object &val, std::string idx) { bool extractIndex = (!idx.length()); if (extractIndex) assignIndex(val, idx); - const ValueBase *v = pushByRef(val, idx); + Handle& v = push(Handle(val, idx)); if (extractIndex) updateIndex(idx, v); return v; } -#ifndef USING_INLINE_PUSH -const ValueBase *Array::push(char *val, std::string idx) -{ - return push(std::string(val), idx); -} - -const ValueBase *Array::push(const char *val, std::string idx) -{ - return push(std::string(val), idx); -} - -const ValueBase *Array::push(std::string &val, std::string idx) -{ - return pushByRef(val, idx); -} - -const ValueBase *Array::push(Array &val, std::string idx) -{ - return pushByRef(val, idx); -} - -const ValueBase *Array::push(Array *val, std::string idx) -{ - return pushByRef(*val, idx); -} -#endif - -const ValueBase* Array::push(Object &o) +Handle& Array::push(Object &o) { return pushObject(o, ""); } -const ValueBase *Array::push(Object *o) +Handle& Array::push(Object *o) { return push(*o); } -const ValueBase* Array::push(char *val) -{ - return push(std::string(val)); -} - -const ValueBase* Array::push(const char *val) -{ - return push(std::string(val)); -} - -const ValueBase *Array::set(std::string key, char *val) -{ - return set(key, std::string(val)); -} - -const ValueBase *Array::set(std::string key, const char *val) -{ - return set(key, std::string(val)); -} - -const ValueBase *Array::set(int key, char *val) -{ - return set(intToStr(key), val); -} - -const ValueBase *Array::set(int key, const char *val) -{ - return set(intToStr(key), val); -} - -const ValueBase* Array::push(ValueBase *val) +Handle& Array::push(ValueBase *val) { - vector.push_back(val); - ++(*val); - return val; + return push(Handle(val)); } DEFINE_DEFAULT_GETTERS(Array, unsigned int) diff --git a/libdvbtee/value/array.h b/libdvbtee/value/array.h index 61503d01..c99b2545 100644 --- a/libdvbtee/value/array.h +++ b/libdvbtee/value/array.h @@ -28,10 +28,11 @@ #include "value.h" #include "object.h" +#include "handle.h" namespace valueobj { -typedef std::vector KeyValueVector; +typedef std::vector KeyValueVector; class Object; @@ -42,33 +43,38 @@ class Array { Array(const Array&); - const ValueBase* push(ValueBase*); + Handle& push(Handle hdl); - const ValueBase* push(Object&); - const ValueBase* push(Object*); + Handle& push(ValueBase*); + + Handle& push(Object&); + Handle& push(Object*); template - const ValueBase* push(T val); + Handle& push(T val) + { + return push(Handle(val, "")); + } - const ValueBase* push( char* val); - const ValueBase* push(const char* val); + bool set(std::string key, Handle hdl); template - const ValueBase* set(std::string key, T val); - - const ValueBase* set(std::string key, char* val); - const ValueBase* set(std::string key, const char* val); + bool set(std::string key, T val) + { + return set(key, Handle(val, key)); + } template - const ValueBase* set(int key, T val); + bool set(int key, T val) + { + return set(intToStr(key), val); + } - const ValueBase* set(int key, char* val); - const ValueBase* set(int key, const char* val); - const ValueBase* getByName(std::string idx) const; - const ValueBase* getByName(unsigned int idx) const; + Handle& getByName(std::string idx) const; + Handle& getByName(unsigned int idx) const; - const ValueBase* get(unsigned int idx) const; + Handle& get(unsigned int idx) const; template const T& get(unsigned int idx) const; @@ -82,36 +88,15 @@ class Array { private: KeyValueVector vector; - std::map indices; + std::map indices; std::string idxField; - template - const ValueBase* pushByRef(T& val, std::string idx); - - const ValueBase* pushObject(Object& val, std::string idx); - - template - const ValueBase* push(T val, std::string idx); - -#define USING_INLINE_PUSH -#ifdef USING_INLINE_PUSH - inline const ValueBase* push( char* val, std::string idx) { return push(std::string(val), idx); } - inline const ValueBase* push(const char* val, std::string idx) { return push(std::string(val), idx); } - inline const ValueBase* push(std::string& val, std::string idx) { return pushByRef(val, idx); } - inline const ValueBase* push(Array& val, std::string idx) { return pushByRef(val, idx); } - inline const ValueBase* push(Array* val, std::string idx) { return pushByRef(*val, idx); } -#else - const ValueBase* push( char* val, std::string idx); - const ValueBase* push(const char* val, std::string idx); - const ValueBase* push(std::string& val, std::string idx); - const ValueBase* push(Array& val, std::string idx); - const ValueBase* push(Array* val, std::string idx); -#endif + Handle& pushObject(Object& val, std::string idx); template const T& get(unsigned int &idx, T& def) const; - void updateIndex(std::string, const ValueBase*); + void updateIndex(std::string, Handle&); std::string& assignIndex(Object&, std::string&); const std::string intToStr(int) const; diff --git a/libdvbtee/value/handle.cpp b/libdvbtee/value/handle.cpp new file mode 100644 index 00000000..5c1cf5a3 --- /dev/null +++ b/libdvbtee/value/handle.cpp @@ -0,0 +1,139 @@ +/***************************************************************************** + * Copyright (C) 2011-2016 Michael Ira Krufky + * + * Author: Michael Ira Krufky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include "handle.h" + +using namespace valueobj; + +static ReferencedValueUndefined& valueUndefined = ReferencedValueUndefined::instance(); + +Handle::Handle() + : m_value(NULL) {} + +Handle::~Handle() +{ + clear(); +} + +Handle::Handle(const Handle &hdl) + : m_value(hdl.m_value) +{ + incRefCnt(); +} + +Handle::Handle(const ValueBase *v) + : m_value((ValueBase*)v) +{ + incRefCnt(); +} + +Handle::Handle(ValueBase *v) + : m_value(v) +{ + incRefCnt(); +} + +const ValueBase *Handle::set(const char *s, std::string name) +{ + std::string val(s); + return set((ValueBase*)new Value(name, val)); +} + +const ValueBase *Handle::set(char *s, std::string name) +{ + std::string val(s); + return set((ValueBase*)new Value(name, val)); +} + +const ValueBase *Handle::set(Handle &hdl) +{ + return set(hdl.m_value); +} + +const ValueBase *Handle::set(ValueBase *val) +{ + clear(); + m_value = val; + incRefCnt(); + return m_value; +} + +const ValueBase *Handle::set(const ValueBase *val) +{ + return set((ValueBase*)val); +} + +ValueBase *Handle::get() const +{ + return m_value; +} + +Handle::operator ValueBase *() const +{ + return m_value; +} + +Handle::operator const ValueBase *() const +{ + return m_value; +} + +void Handle::clear() +{ + decRefCnt(); + m_value = NULL; +} + +size_t Handle::size() const +{ + return (m_value == NULL) ? 0 : 1; +} + +const std::string Handle::toJson() const +{ + if (m_value) return m_value->toJson(); + return ""; +} + +void Handle::incRefCnt() { + if (m_value) ++(*m_value); +} + +void Handle::decRefCnt() +{ + if (m_value) { + if (!((--(*m_value)).getRefCnt())) { + delete m_value; + } + } +} + +Handle &Handle::operator=(ValueBase *v) +{ + set(v); + return *this; +} + +Handle &Handle::operator=(Handle &hdl) +{ + set(hdl); + return *this; +} diff --git a/libdvbtee/value/handle.h b/libdvbtee/value/handle.h new file mode 100644 index 00000000..3258955c --- /dev/null +++ b/libdvbtee/value/handle.h @@ -0,0 +1,157 @@ +/***************************************************************************** + * Copyright (C) 2011-2016 Michael Ira Krufky + * + * Author: Michael Ira Krufky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef __HANDLE_H__ +#define __HANDLE_H__ + +#include +#include + +#include "value.h" + +namespace valueobj { + +class Handle { +public: + Handle(); + ~Handle(); + + Handle(const Handle& hdl); +#if 0 + template + Handle(T& o, std::string name = "") : m_value(NULL) { set(o, name); } +#endif + template + Handle(T o, std::string name = "") : m_value(NULL) + { + /* we assign m_value to the return value of set + * to satisfy the coverity checker, + * avoiding Resource Leak false positive */ + m_value = (ValueBase*)set(o, name); + } + + template + Handle(Value v) : m_value(&v) { incRefCnt(); } + + template + Handle(Value& v) : m_value(&v) { incRefCnt(); } + + template + Handle(Value* v) : m_value(v) { incRefCnt(); } + + Handle(const ValueBase* v); + Handle(ValueBase* v); + + Handle& operator=(Handle& hdl); +#if 1 + template + Handle& operator=(T& v) + { + set(v); + return *this; + } +#else + template + Handle& operator=(T v) + { + set(v); + return *this; + } +#endif + template + Handle& operator=(Value& v) + { + set(v); + return *this; + } + + template + Handle& operator=(Value* v) + { + set(v); + return *this; + } + + Handle& operator=(ValueBase* v); + + const ValueBase* set(char* s, std::string name = ""); + + const ValueBase* set(const char* s, std::string name = ""); +#if 0 + template + const ValueBase* set(T& val, std::string name = "") + { + return set((ValueBase*)new Value(name, val)); + } +#endif + template + const ValueBase* set(T val, std::string name = "") + { + return set((ValueBase*)new Value(name, val)); + } + + template + const ValueBase* set(Value& val) + { + return set((ValueBase*)&val); + } + + const ValueBase* set(Handle& hdl); + + const ValueBase* set(const ValueBase* val); + + const ValueBase* set(ValueBase* val); + + ValueBase* get() const; + + template const T& get() const + { + if (m_value) return ((Value*)m_value)->get(); + //FIXME: return &valueobj::ReferencedValueUndefined::instance(); + static T zero(0); + return zero; + } + + template + operator T() const { return get(); } + + template + operator Value*() const { return (Value*)m_value; } + + operator ValueBase*() const; + operator const ValueBase*() const; + + void clear(); + + size_t size() const; + + const std::string toJson() const; + +private: + ValueBase* m_value; + + void incRefCnt(); + void decRefCnt(); +}; + +} + +#endif /* __HANDLE_H__ */ diff --git a/libdvbtee/value/object.cpp b/libdvbtee/value/object.cpp index 4e9f20f7..b18de462 100644 --- a/libdvbtee/value/object.cpp +++ b/libdvbtee/value/object.cpp @@ -34,22 +34,6 @@ DEFINE_DEFAULT_GETTERS(Object, std::string) namespace valueobj { -template -const ValueBase* Object::setByRef(std::string& key, T& val) -{ - if (map.count(key)) { - if (0 == (--(*map[key])).getRefCnt()) delete map[key]; - } - - Value *v = new Value(key, val); - - map[key] = v; - //map.insert( std::pair(key, v) ); - - ++(*v); // increment refcount - return v; -} - template const T& Object::get(std::string& key, T& def) const { @@ -64,7 +48,6 @@ const T& Object::get(std::string& key, T& def) const } #define IMPL_OBJECT_TMPL(T) \ -template const ValueBase* Object::setByRef(std::string& key, T& val); \ template const T& Object::get(std::string& key, T& def) const IMPL_OBJECT_TMPL(int); @@ -85,6 +68,7 @@ IMPL_OBJECT_TMPL(Object); static ReferencedValueUndefined& valueUndefined = ReferencedValueUndefined::instance(); +static Handle valueUndefinedHdl = Handle((ValueBase*)&valueUndefined); Object::Object() { @@ -112,51 +96,22 @@ Object::Object(const Object &obj) #endif } -const ValueBase *Object::set(std::string key, char *val) +Handle& Object::setByRef(std::string& key, Handle& hdl) { - return set(key, std::string(val)); + return map[key] = hdl; } -const ValueBase *Object::set(std::string key, const char *val) -{ - return set(key, std::string(val)); -} - -const ValueBase *Object::set(std::string key, std::string &val) -{ - return setByRef(key, val); -} - -const ValueBase *Object::set(std::string key, Array &val) -{ - return setByRef(key, val); -} - -const ValueBase *Object::set(std::string key, Object &val) -{ - return setByRef(key, val); -} - -const ValueBase *Object::set(std::string key, Array *val) -{ - return setByRef(key, *val); -} - -const ValueBase *Object::set(std::string key, Object *val) -{ - return setByRef(key, *val); -} - -const ValueBase* Object::get(std::string key) const +Handle& Object::get(std::string key) const { KeyValueMap::const_iterator it = map.find(key); - if (it != map.end()) - return it->second; + if (it != map.end()) { + return (Handle&)it->second; + } - return &valueUndefined; + return valueUndefinedHdl; } -const ValueBase* Object::get(int key) const +Handle& Object::get(int key) const { return get(intToStr(key)); } @@ -164,7 +119,6 @@ const ValueBase* Object::get(int key) const void Object::unSet(std::string key) { if (map.count(key)) { - if (0 == (--(*map[key])).getRefCnt()) delete map[key]; map.erase(key); } } @@ -176,11 +130,6 @@ void Object::unSet(int key) void Object::clear() { - for (KeyValueMap::iterator it = map.begin(); it != map.end(); ++it) - { - // decrement refcount. if refcount becomes zero, delete - if (0 == (--(*it->second)).getRefCnt()) delete it->second; - } map.clear(); } @@ -192,12 +141,9 @@ const std::string Object::toJson() const s << "{ "; for (KeyValueMap::const_iterator it = map.begin(); it != map.end(); ++it) { - ValueBase *val = it->second; - if (it != map.begin()) s << ", "; - s << "\"" << it->first << "\": "; - s << val->toJson(); + s << "\"" << it->first << "\": " << it->second.toJson(); } s << " }"; @@ -211,18 +157,25 @@ const std::string Object::intToStr(int i) const return s.str(); } +Handle& Object::set(std::string key, Handle hdl) +{ + return setByRef(key, hdl); +} + +Handle& Object::set(int key, Handle hdl) +{ + return set(intToStr(key), hdl); +} + // deprecated: -const ValueBase *Object::set(ValueBase *val) +Handle& Object::set(ValueBase *val) { return set(val->getName(), val); } -const ValueBase *Object::set(std::string key, ValueBase *val) +Handle& Object::set(std::string key, ValueBase *val) { - unSet(key); - map[key] = val; - ++(*val); - return val; + return set(key, Handle(val)); } TO_JSON_TPL(Object, VALUE.toJson().c_str()) diff --git a/libdvbtee/value/object.h b/libdvbtee/value/object.h index 4eb38e2e..90bf77a6 100644 --- a/libdvbtee/value/object.h +++ b/libdvbtee/value/object.h @@ -28,10 +28,11 @@ #include "value.h" #include "array.h" +#include "handle.h" namespace valueobj { -typedef std::map KeyValueMap; +typedef std::map KeyValueMap; class Array; @@ -42,39 +43,34 @@ class Object { Object(const Object&); + Handle& set(std::string key, Handle); + Handle& set(int key, Handle); + template - const ValueBase* set(std::string key, T val) + Handle& set(std::string key, T val) { - return setByRef(key, val); + return set(key, Handle(val, key)); } - const ValueBase* set(std::string key, char* val); - const ValueBase* set(std::string key, const char* val); - const ValueBase* set(std::string key, std::string& val); - const ValueBase* set(std::string key, Array& val); - const ValueBase* set(std::string key, Object& val); - const ValueBase* set(std::string key, Array* val); - const ValueBase* set(std::string key, Object* val); - template - const ValueBase* set(int key, T val) + Handle& set(int key, T val) { return set(intToStr(key), val); } - const ValueBase* set(std::string key, ValueBase*); + Handle& set(std::string key, ValueBase*); // deprecated: - const ValueBase* set(ValueBase*); + Handle& set(ValueBase*); void unSet(std::string key); void unSet(int key); void clear(); - const ValueBase* get(std::string key) const; - const ValueBase* get(int key) const; + Handle& get(std::string key) const; + Handle& get(int key) const; template const T& get(std::string key) const; @@ -89,8 +85,7 @@ class Object { private: KeyValueMap map; - template - const ValueBase* setByRef(std::string& key, T& val); + Handle& setByRef(std::string&, Handle&); template const T& get(std::string& key, T& def) const; diff --git a/libdvbtee/value/value.pri b/libdvbtee/value/value.pri index 99eaaa9f..e6f9ed4b 100644 --- a/libdvbtee/value/value.pri +++ b/libdvbtee/value/value.pri @@ -1,11 +1,13 @@ INCLUDEPATH += $$PWD VALOBJ_SOURCES = \ + $$PWD/handle.cpp \ $$PWD/array.cpp \ $$PWD/object.cpp \ $$PWD/value.cpp HEADERS += \ + $$PWD/handle.h \ $$PWD/array.h \ $$PWD/object.h \ $$PWD/value-macros.h \