You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

238 lines
5.6 KiB

// This file is under GNU General Public License 3.0
// see LICENSE.txt
#ifndef LIBPEPDATATYPES_WRAPPER_HH
#define LIBPEPDATATYPES_WRAPPER_HH
#include <initializer_list>
#include <iterator>
namespace pEp {
/// A generalized wrapper around pEpEngine's datatypes.
template<class T>
class Wrapper {
public:
typedef T c_type;
template<class... Args>
Wrapper(Args... args) : value{ this->_new(args...) }
{
}
// no implicit copying... (yet?)
Wrapper(const Wrapper<T>&) = delete;
void operator=(const Wrapper<T>&) = delete;
// must be implemented separately for each T
Wrapper(Wrapper<T>&& victim);
Wrapper<T>& operator=(Wrapper<T>&& victim);
~Wrapper();
Wrapper<T> copy() const;
bool operator==(const Wrapper<T>& b) const
{
return value == b.value;
}
bool operator!=(const Wrapper<T>& b) const
{
return value != b.value;
}
private:
// must be defined for each wrapped type:
template<class... Args>
T _new(Args...);
T value;
};
// many wrapped datatypes are pointers, we can generalize a lot for them:
template<class T>
class Wrapper<T*> {
public:
typedef T* c_type;
Wrapper() : value{ nullptr } {}
template<class... Args>
Wrapper(Args... args) : value{ this->_new(args...) }
{
}
// move is easy, efficient and generic:
Wrapper(Wrapper<T*>&& victim) noexcept : value{ victim.value }
{
victim.value = nullptr;
}
Wrapper<T*>& operator=(Wrapper<T*>&& victim) noexcept
{
_free(value);
value = victim.value;
victim.value = nullptr;
return *this;
}
Wrapper(const Wrapper<T*>& orig) : value{ orig.copy_out() } {}
Wrapper<T*>& operator=(const Wrapper<T*>& orig)
{
if (&orig == this)
return *this;
_free(value);
value = orig.copy_out();
return *this;
}
~Wrapper()
{
_free(value);
}
bool operator==(const Wrapper<T*>& b) const
{
return value == b.value;
}
bool operator!=(const Wrapper<T*>& 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<class... Args>
T* _new(Args...);
void _free(T*);
T* value;
};
// Wraps single-linked lists and provides an interface compatible
// to std::forward_list
template<class T, class Element>
class ListWrapper;
template<class T, class Element>
class ListWrapper<T*, Element> : public Wrapper<T*> {
public:
typedef Wrapper<T*> Base;
typedef ListWrapper<T*, Element> 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<T*, Element>;
};
typedef const iterator const_iterator;
using Base::value;
ListWrapper() : Base() {}
ListWrapper(const std::initializer_list<pEp::Wrapper<Element>>& i);
ListWrapper(const std::initializer_list<Element>& 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<Element>&&);
};
} // end of namespace pEp
#endif // LIBPEPDATATYPES_WRAPPER_HH