A C++ wrapper for the basic C datatypes defined by the pEpEngine.
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.

190 lines
4.3 KiB

  1. // This file is under GNU General Public License 3.0
  2. // see LICENSE.txt
  3. #ifndef LIBPEPDATATYPES_WRAPPER_HH
  4. #define LIBPEPDATATYPES_WRAPPER_HH
  5. #include <initializer_list>
  6. #include <iterator>
  7. namespace pEp
  8. {
  9. template<class T>
  10. class Wrapper
  11. {
  12. public:
  13. typedef T c_type;
  14. template<class... Args>
  15. Wrapper(Args... args) : value{ this->_new(args...) } {}
  16. // no implicit copying... (yet?)
  17. Wrapper(const Wrapper<T>&) = delete;
  18. void operator=(const Wrapper<T>&) = delete;
  19. // must be implemented separately for each T
  20. Wrapper(Wrapper<T>&& victim);
  21. Wrapper<T>& operator=(Wrapper<T>&& victim);
  22. ~Wrapper();
  23. Wrapper<T> copy() const;
  24. bool operator==(const Wrapper<T>& b) const
  25. {
  26. return value==b.value;
  27. }
  28. bool operator!=(const Wrapper<T>& b) const
  29. {
  30. return value!=b.value;
  31. }
  32. private:
  33. // must be defined for each wrapped type:
  34. template<class... Args>
  35. T _new(Args...);
  36. T value;
  37. };
  38. // many wrapped datatypes are pointers, we can generalize a lot for them:
  39. template<class T>
  40. class Wrapper<T*>
  41. {
  42. public:
  43. typedef T* c_type;
  44. Wrapper() : value{nullptr} {}
  45. template<class... Args>
  46. Wrapper(Args... args) : value{ this->_new(args...) } {}
  47. // move is easy, efficient and generic:
  48. Wrapper(Wrapper<T*>&& victim) noexcept
  49. : value{ victim.value}
  50. {
  51. victim.value = nullptr;
  52. }
  53. Wrapper<T*>& operator=(Wrapper<T*>&& victim) noexcept
  54. {
  55. _free(value);
  56. value = victim.value;
  57. victim.value = nullptr;
  58. return *this;
  59. }
  60. Wrapper(const Wrapper<T*>& orig)
  61. : value{ orig.copy_out() }
  62. {}
  63. Wrapper<T*>& operator=(const Wrapper<T*>& orig)
  64. {
  65. if(&orig == this) return *this;
  66. _free(value);
  67. value = orig.copy_out();
  68. return *this;
  69. }
  70. ~Wrapper()
  71. {
  72. _free(value);
  73. }
  74. bool operator==(const Wrapper<T*>& b) const
  75. {
  76. return value==b.value;
  77. }
  78. bool operator!=(const Wrapper<T*>& b) const
  79. {
  80. return value!=b.value;
  81. }
  82. const T* operator->() const { return value; }
  83. const T* get() const { return value; }
  84. // dangerous!
  85. T* operator->() { return value; }
  86. T* get() { return value;}
  87. T* move_out() { T* r = value; value=nullptr; return r;}
  88. // only implemented for the datatypes where necessay.
  89. // other implementations can follow if necessary.
  90. T* copy_out() const;
  91. protected:
  92. Wrapper(T* _value) : value{_value} {}
  93. // must be defined for each wrapped type:
  94. template<class... Args>
  95. T* _new(Args...);
  96. void _free(T*);
  97. T* value;
  98. };
  99. // Wraps single-linked lists and provides an interface compatible
  100. // to std::forward_list
  101. template<class T, class Element>
  102. class ListWrapper;
  103. template<class T, class Element>
  104. class ListWrapper<T*, Element> : public Wrapper<T*>
  105. {
  106. public:
  107. typedef Wrapper<T*> Base;
  108. typedef ListWrapper<T*, Element> LW;
  109. static Element T::* const Value; // to access the current value
  110. // does not own the *value
  111. class iterator : public std::iterator< std::forward_iterator_tag, Element, ptrdiff_t>
  112. {
  113. public:
  114. iterator() = default;
  115. iterator operator++() { return (value ? value = value->next : value); }
  116. Element operator*() { return value->*LW::Value; }
  117. Element operator->() { return value->*LW::Value; }
  118. bool operator==(const iterator& other) const { return value == other.value; }
  119. bool operator!=(const iterator& other) const { return value != other.value; }
  120. private:
  121. iterator(T* _t) : value{_t} {}
  122. T* value = nullptr;
  123. friend class ListWrapper<T*, Element>;
  124. };
  125. using Base::value;
  126. ListWrapper() : Base() {}
  127. ListWrapper(const std::initializer_list<pEp::Wrapper<Element>>& i);
  128. ListWrapper(const std::initializer_list<Element>& i);
  129. iterator begin() { return iterator{value}; }
  130. iterator end() const { return iterator{}; }
  131. int size() const;
  132. bool empty() const;
  133. void erase(const iterator& it);
  134. void clear();
  135. void push_back(Element&&);
  136. void push_back(Wrapper<Element>&&);
  137. };
  138. } // end of namespace pEp
  139. #endif // LIBPEPDATATYPES_WRAPPER_HH