// This file is under GNU General Public License 3.0 // see LICENSE.txt #ifndef LIBPEPDATATYPES_WRAPPER_HH #define LIBPEPDATATYPES_WRAPPER_HH #include #include namespace pEp { /// A generalized wrapper around pEpEngine's datatypes. template class Wrapper { public: typedef T c_type; template Wrapper(Args... args) : value{ this->_new(args...) } {} // no implicit copying... (yet?) Wrapper(const Wrapper&) = delete; void operator=(const Wrapper&) = delete; // must be implemented separately for each T Wrapper(Wrapper&& victim); Wrapper& operator=(Wrapper&& victim); ~Wrapper(); Wrapper copy() const; bool operator==(const Wrapper& b) const { return value==b.value; } bool operator!=(const Wrapper& b) const { return value!=b.value; } private: // must be defined for each wrapped type: template T _new(Args...); T value; }; // many wrapped datatypes are pointers, we can generalize a lot for them: template class Wrapper { public: typedef T* c_type; Wrapper() : value{nullptr} {} template Wrapper(Args... args) : value{ this->_new(args...) } {} // move is easy, efficient and generic: Wrapper(Wrapper&& victim) noexcept : value{ victim.value} { victim.value = nullptr; } Wrapper& operator=(Wrapper&& victim) noexcept { _free(value); value = victim.value; victim.value = nullptr; return *this; } Wrapper(const Wrapper& orig) : value{ orig.copy_out() } {} Wrapper& operator=(const Wrapper& orig) { if(&orig == this) return *this; _free(value); value = orig.copy_out(); return *this; } ~Wrapper() { _free(value); } bool operator==(const Wrapper& b) const { return value==b.value; } bool operator!=(const Wrapper& b) const { return value!=b.value; } // Get read-only access to the value itself // Beware: 'const' is not transitive in C, so the 2nd indirect data // allows r/w access! const T* operator->() const { return value; } const T* get() const { return value; } // Dangerous: Get R/W access to the value! T* operator->() { return value; } T* get() { return value;} // Releases ownership of the value. Wrapper becomes valueless. T* move_out() { T* r = value; value=nullptr; return r;} // only implemented for the datatypes where necessay. // other implementations can follow if necessary. T* copy_out() const; protected: Wrapper(T* _value) : value{_value} {} // must be defined for each wrapped type: template T* _new(Args...); void _free(T*); T* value; }; // Wraps single-linked lists and provides an interface compatible // to std::forward_list template class ListWrapper; template class ListWrapper : public Wrapper { public: typedef Wrapper Base; typedef ListWrapper LW; static Element T::* const Value; // to access the current value // does not own the *value class iterator : public std::iterator< std::forward_iterator_tag, Element, ptrdiff_t> { public: iterator() = default; iterator operator++() { return (value ? value = value->next : value); } Element operator*() { return value->*LW::Value; } Element operator->() { return value->*LW::Value; } bool operator==(const iterator& other) const { return value == other.value; } bool operator!=(const iterator& other) const { return value != other.value; } private: iterator(T* _t) : value{_t} {} T* value = nullptr; friend class ListWrapper; }; typedef const iterator const_iterator; using Base::value; ListWrapper() : Base() {} ListWrapper(const std::initializer_list>& i); ListWrapper(const std::initializer_list& i); iterator begin() { return iterator{value}; } iterator end() const { return iterator{}; } const_iterator cbegin() const { return const_iterator{value}; } const_iterator cend() const { return const_iterator{}; } int size() const; bool empty() const; void erase(const iterator& it); void clear(); void push_back(Element&&); void push_back(Wrapper&&); }; } // end of namespace pEp #endif // LIBPEPDATATYPES_WRAPPER_HH