eina-cxx: Added interop containers.

efl-1.11
Savio Sena 9 years ago committed by Felipe Magno de Almeida
parent 34c3d4ded7
commit 256e21d939
  1. 2
      src/Makefile_Eet_Cxx.am
  2. 6
      src/Makefile_Eina_Cxx.am
  3. 337
      src/bindings/eina_cxx/eina_array.hh
  4. 40
      src/bindings/eina_cxx/eina_clone_allocators.hh
  5. 10
      src/bindings/eina_cxx/eina_eo_base_fwd.hh
  6. 330
      src/bindings/eina_cxx/eina_list.hh
  7. 18
      src/bindings/eina_cxx/eina_ptrarray.hh
  8. 34
      src/bindings/eina_cxx/eina_ptrlist.hh
  9. 24
      src/bindings/eo_cxx/eo_base.hh
  10. 2
      src/examples/eina_cxx/Makefile.am
  11. 584
      src/tests/eina_cxx/eina_cxx_test_ptrarray.cc
  12. 497
      src/tests/eina_cxx/eina_cxx_test_ptrlist.cc

@ -27,7 +27,7 @@ tests_eet_cxx_eet_cxx_suite_CPPFLAGS = \
-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eet_cxx\" \
-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)/src/tests/eet_cxx\" \
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eet_cxx\" \
@CHECK_CFLAGS@ @EET_CXX_CFLAGS@ @EINA_CXX_CFLAGS@ @EET_CFLAGS@ @EINA_CFLAGS@
@EO_CFLAGS@ @CHECK_CFLAGS@ @EET_CXX_CFLAGS@ @EINA_CXX_CFLAGS@ @EET_CFLAGS@ @EINA_CFLAGS@
tests_eet_cxx_eet_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EET_LIBS@
tests_eet_cxx_eet_cxx_suite_DEPENDENCIES = @USE_EET_INTERNAL_LIBS@
endif

@ -58,9 +58,11 @@ tests_eina_cxx_eina_cxx_suite_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)/src/tests/eina_cxx\" \
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eina_cxx\" \
@CHECK_CFLAGS@ \
@EO_CFLAGS@ \
@EO_CXX_CFLAGS@ \
@EINA_CXX_CFLAGS@
tests_eina_cxx_eina_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EINA_LIBS@
tests_eina_cxx_eina_cxx_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
tests_eina_cxx_eina_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EINA_LIBS@ @USE_EO_LIBS@
tests_eina_cxx_eina_cxx_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@
endif
endif

@ -0,0 +1,337 @@
#ifndef EINA_ARRAY_HH_
#define EINA_ARRAY_HH_
#include <Eo.h>
#include <eina_ptrarray.hh>
#include <eina_eo_base_fwd.hh>
#include <iostream>
namespace efl { namespace eina {
template <typename T, typename CloneAllocator = default_clone_allocator_placeholder, typename Enable = void>
class array : ptr_array<T, typename std::conditional
<std::is_same<CloneAllocator, default_clone_allocator_placeholder>::value
, heap_no_copy_allocator, CloneAllocator>::type>
{
typedef ptr_array<T, typename std::conditional
<std::is_same<CloneAllocator, default_clone_allocator_placeholder>::value
, heap_no_copy_allocator, CloneAllocator>::type> _base_type;
public:
typedef typename _base_type::value_type value_type; /**< The type of each element. */
typedef typename _base_type::reference reference; /**< Type for a reference to an element. */
typedef typename _base_type::const_reference const_reference; /**< Type for a constant reference to an element. */
typedef typename _base_type::const_iterator const_iterator; /**< Type for a iterator for this container. */
typedef typename _base_type::iterator iterator; /**< Type for a constant iterator for this container. */
typedef typename _base_type::pointer pointer; /**< Type for a pointer to an element. */
typedef typename _base_type::const_pointer const_pointer; /**< Type for a constant pointer for an element. */
typedef typename _base_type::size_type size_type; /**< Type for size information used in the array. */
typedef typename _base_type::difference_type difference_type; /**< Type to represent the distance between two iterators. */
typedef typename _base_type::clone_allocator_type clone_allocator_type; /** Type for the clone allocator. */
typedef typename _base_type::reverse_iterator reverse_iterator; /**< Type for reverse iterator for this container. */
typedef typename _base_type::const_reverse_iterator const_reverse_iterator; /**< Type for reverse iterator for this container. */
using _base_type::_base_type;
using _base_type::clear;
using _base_type::size;
using _base_type::empty;
using _base_type::get_clone_allocator;
using _base_type::push_back;
using _base_type::pop_back;
using _base_type::insert;
using _base_type::erase;
using _base_type::assign;
using _base_type::back;
using _base_type::front;
using _base_type::operator[];
using _base_type::begin;
using _base_type::end;
using _base_type::rbegin;
using _base_type::rend;
using _base_type::cbegin;
using _base_type::cend;
using _base_type::crbegin;
using _base_type::crend;
using _base_type::ibegin;
using _base_type::iend;
using _base_type::cibegin;
using _base_type::ciend;
using _base_type::swap;
using _base_type::max_size;
using _base_type::native_handle;
friend bool operator==(array<T, CloneAllocator> const& lhs, array<T, CloneAllocator> const& rhs)
{
return static_cast<_base_type const&>(lhs) == static_cast<_base_type const&>(rhs);
}
};
/**
* @internal
*/
template <typename T>
struct _ptr_eo_array_iterator : _ptr_array_iterator<Eo>
{
typedef _ptr_array_iterator<Eo> _base_type;
typedef _ptr_eo_array_iterator<T> _self_type;
typedef typename remove_cv<T>::type value_type;
typedef value_type* pointer;
typedef value_type& reference;
_base_type& _base() { return *this; }
_base_type const& _base() const { return *this; }
_ptr_eo_array_iterator(_base_type const& base) : _base_type(base) {}
_ptr_eo_array_iterator() {}
explicit _ptr_eo_array_iterator(void** ptr)
: _base_type(ptr)
{
}
_ptr_eo_array_iterator(_ptr_eo_array_iterator<value_type> const& other)
: _base_type(static_cast<_base_type const&>(other))
{
}
_self_type& operator=(_self_type const& other)
{
this->_base_type::operator=(other);
return *this;
}
_self_type& operator++()
{
++_base();
return *this;
}
_self_type operator++(int)
{
_self_type tmp(*this);
++_base();
return tmp;
}
_self_type& operator--()
{
--_base();
return *this;
}
_self_type operator--(int)
{
_self_type tmp(*this);
--_base();
return tmp;
}
reference operator*() const
{
return *static_cast<pointer>(static_cast<void*>(native_handle()));
}
pointer operator->() const
{
return &**this;
}
using _base_type::native_handle;
};
template <typename T, typename CloneAllocator>
class array<T, CloneAllocator, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value>::type>
: ptr_array<Eo, typename std::conditional
<std::is_same<CloneAllocator, default_clone_allocator_placeholder>::value
, eo_clone_allocator, CloneAllocator>::type>
{
typedef ptr_array<Eo, typename std::conditional
<std::is_same<CloneAllocator, default_clone_allocator_placeholder>::value
, eo_clone_allocator, CloneAllocator>::type> _base_type;
typedef array<T, CloneAllocator> _self_type;
public:
typedef T value_type; /**< The type of each element. */
typedef T& reference; /**< Type for a reference to an element. */
typedef T const& const_reference; /**< Type for a constant reference to an element. */
typedef _ptr_eo_array_iterator<T const> const_iterator; /**< Type for a iterator for this container. */
typedef _ptr_eo_array_iterator<T> iterator; /**< Type for a constant iterator for this container. */
typedef T* pointer; /**< Type for a pointer to an element. */
typedef T const* const_pointer; /**< Type for a constant pointer for an element. */
typedef typename _base_type::size_type size_type; /**< Type for size information used in the array. */
typedef typename _base_type::difference_type difference_type; /**< Type to represent the distance between two iterators. */
typedef typename _base_type::clone_allocator_type clone_allocator_type; /** Type for the clone allocator. */
typedef std::reverse_iterator<iterator> reverse_iterator; /**< Type for reverse iterator for this container. */
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; /**< Type for reverse iterator for this container. */
explicit array(Eina_Array* handle)
: _base_type(handle) {}
array(clone_allocator_type alloc) : _base_type(alloc) {}
array() {}
array(size_type n, const_reference t)
{
while(n--)
push_back(t);
}
template <typename InputIterator>
array(InputIterator i, InputIterator const& j
, clone_allocator_type const& alloc = clone_allocator_type()
, typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
: _base_type(alloc)
{
while(i != j)
{
push_back(*i);
++i;
}
}
array(array<T, CloneAllocator> const& other)
: _base_type()
{
insert(end(), other.begin(), other.end());
}
template <typename CloneAllocator1>
array(array<T, CloneAllocator1>const& other)
: _base_type()
{
insert(end(), other.begin(), other.end());
}
array<T, CloneAllocator>& operator=(array<T, CloneAllocator>const& other)
{
clear();
insert(end(), other.begin(), other.end());
return *this;
}
using _base_type::clear;
using _base_type::size;
using _base_type::empty;
using _base_type::get_clone_allocator;
using _base_type::pop_back;
void push_back(const_reference w)
{
_base_type::push_back(this->_new_clone(*w._eo_ptr()));
}
iterator insert(iterator i, value_type const& t)
{
return _base_type::insert(i, this->_new_clone(*t._eo_ptr()));
}
iterator insert(iterator i, size_t n, value_type const& t)
{
return _base_type::insert(i, n, this->_new_clone(*t._eo_ptr()));
}
template <typename InputIterator>
iterator insert(iterator p, InputIterator i, InputIterator j
, typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
{
size_type index = p.native_handle() - this->_impl._array->data;
while(i != j)
{
p = insert(p, *i);
++p;
++i;
}
return iterator(this->_impl._array->data + index);
}
iterator erase(iterator p)
{
return _base_type::erase(p);
}
iterator erase(iterator i, iterator j)
{
return _base_type::erase(i, j);
}
template <typename InputIterator>
void assign(InputIterator i, InputIterator j
, typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
{
clear();
insert(end(), i, j);
}
void assign(size_type n, value_type const& t)
{
clear();
insert(end(), n, t);
}
reference front()
{
return *static_cast<pointer>(static_cast<void*>(&native_handle()->data[0]));
}
reference back()
{
return *static_cast<pointer>(static_cast<void*>(&native_handle()->data[eina_array_count(native_handle())-1]));
}
const_reference front() const { return const_cast<_self_type*>(this)->front(); }
const_reference back() const { return const_cast<_self_type*>(this)->back(); }
const_reference operator[](size_type n) const
{
return *static_cast<pointer>(static_cast<void*>(&native_handle()->data[n]));
}
reference operator[](size_type n)
{
return *static_cast<pointer>(static_cast<void*>(&native_handle()->data[n]));
}
iterator begin()
{
return iterator(&native_handle()->data[0]);
}
iterator end()
{
return iterator(&native_handle()->data[ ::eina_array_count(native_handle())]);
}
const_iterator begin() const
{
return const_cast< _self_type*>(this)->begin();
}
const_iterator end() const
{
return const_cast< _self_type*>(this)->end();
}
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
const_reverse_iterator rbegin() const
{
return reverse_iterator(end());
}
const_reverse_iterator rend() const
{
return reverse_iterator(begin());
}
const_iterator cbegin() const
{
return begin();
}
const_iterator cend() const
{
return cend();
}
const_reverse_iterator crbegin() const
{
return rbegin();
}
const_reverse_iterator crend() const
{
return rend();
}
using _base_type::swap;
using _base_type::max_size;
using _base_type::native_handle;
friend bool operator==(array<T, CloneAllocator> const& lhs, array<T, CloneAllocator> const& rhs)
{
return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
};
template <typename T, typename CloneAllocator>
bool operator!=(array<T, CloneAllocator> const& lhs, array<T, CloneAllocator> const& rhs)
{
return !(lhs == rhs);
}
} }
#endif

@ -1,6 +1,8 @@
#ifndef EINA_CLONE_ALLOCATORS_HH_
#define EINA_CLONE_ALLOCATORS_HH_
#include <Eo.h>
#include <memory>
#include <cstring>
#include <cstdlib>
@ -25,6 +27,11 @@ namespace efl { namespace eina {
* @{
*/
/*
* @internal
*/
struct default_clone_allocator_placeholder;
/**
* This allocator creates copies of objects on the heap, calling their
* copy constructor to make then equivalent to the given reference.
@ -50,6 +57,24 @@ struct heap_copy_allocator
}
};
/**
* This allocator creates copies of Eo classes through eo_ref
*
* The created objects are released using eo_unref
*/
struct eo_clone_allocator
{
static Eo* allocate_clone(Eo const& v)
{
return ::eo_ref(&v);
}
static void deallocate_clone(Eo const* p)
{
::eo_unref(const_cast<Eo*>(p));
}
};
/**
* This allocator allows users to create custom allocation schemes by
* overloading the <tt>new_clone(T const& v)</tt> and
@ -112,7 +137,7 @@ struct heap_no_copy_allocator
* Manages allocation and deallocation of memory using the function
* @c malloc and @c free. This allocator does not calls constructors,
* the content of the newly allocated objects are assigned using
* @c memcpy, so it is likely only plausible with types that have
* @c memcpy, so it has to be used with types that have
* <em>standard-layout</em>.
*/
struct malloc_clone_allocator
@ -134,6 +159,19 @@ struct malloc_clone_allocator
}
};
/**
* @internal
*/
template <typename A>
struct clone_allocator_deleter
{
template <typename T>
void operator()(T* object) const
{
A::deallocate_clone(object);
}
};
/**
* @}
*/

@ -0,0 +1,10 @@
#ifndef EINA_EO_BASE_FWD_HH
#define EINA_EO_BASE_FWD_HH
namespace efl { namespace eo {
struct base;
} }
#endif

@ -0,0 +1,330 @@
#ifndef EINA_LIST_HH_
#define EINA_LIST_HH_
#include <Eo.h>
#include <eina_ptrlist.hh>
namespace efl { namespace eina {
/**
* @internal
*/
template <typename T>
struct _ptr_eo_list_iterator : _ptr_list_iterator<Eo>
{
typedef _ptr_list_iterator<Eo> _base_type;
typedef _ptr_eo_list_iterator<T> _self_type;
typedef typename remove_cv<T>::type value_type;
typedef value_type* pointer;
typedef value_type& reference;
_base_type& _base() { return *this; }
_base_type const& _base() const { return *this; }
_ptr_eo_list_iterator(_base_type const& base) : _base_type(base) {}
_ptr_eo_list_iterator() {}
explicit _ptr_eo_list_iterator(Eina_List* list, Eina_List* node)
: _base_type(list, node)
{
}
_ptr_eo_list_iterator(_ptr_eo_list_iterator<value_type> const& other)
: _base_type(static_cast<_base_type const&>(other))
{
}
_self_type& operator=(_self_type const& other)
{
this->_base_type::operator=(other);
return *this;
}
_self_type& operator++()
{
++_base();
return *this;
}
_self_type operator++(int)
{
_self_type tmp(*this);
++_base();
return tmp;
}
_self_type& operator--()
{
--_base();
return *this;
}
_self_type operator--(int)
{
_self_type tmp(*this);
--_base();
return tmp;
}
reference operator*() const
{
void* data = reinterpret_cast<void*>(&this->_node->data);
return *static_cast<pointer>(data);
}
pointer operator->() const
{
return &**this;
}
using _base_type::native_handle;
};
template <typename T, typename CloneAllocator = default_clone_allocator_placeholder, typename Enable = void>
class list : ptr_list<T, typename std::conditional
<std::is_same<CloneAllocator, default_clone_allocator_placeholder>::value
, heap_no_copy_allocator, CloneAllocator>::type>
{
typedef ptr_list<T, typename std::conditional
<std::is_same<CloneAllocator, default_clone_allocator_placeholder>::value
, heap_no_copy_allocator, CloneAllocator>::type> _base_type;
public:
typedef typename _base_type::value_type value_type;
typedef typename _base_type::reference reference;
typedef typename _base_type::const_reference const_reference;
typedef typename _base_type::const_iterator const_iterator;
typedef typename _base_type::iterator iterator;
typedef typename _base_type::pointer pointer;
typedef typename _base_type::const_pointer const_pointer;
typedef typename _base_type::size_type size_type;
typedef typename _base_type::difference_type difference_type;
typedef typename _base_type::clone_allocator_type clone_allocator_type;
typedef typename _base_type::reverse_iterator reverse_iterator;
typedef typename _base_type::const_reverse_iterator const_reverse_iterator;
using _base_type::_base_type;
using _base_type::clear;
using _base_type::size;
using _base_type::empty;
using _base_type::get_clone_allocator;
using _base_type::push_back;
using _base_type::push_front;
using _base_type::pop_back;
using _base_type::pop_front;
using _base_type::insert;
using _base_type::erase;
using _base_type::assign;
using _base_type::back;
using _base_type::front;
using _base_type::begin;
using _base_type::end;
using _base_type::rbegin;
using _base_type::rend;
using _base_type::cbegin;
using _base_type::cend;
using _base_type::crbegin;
using _base_type::crend;
using _base_type::ibegin;
using _base_type::iend;
using _base_type::cibegin;
using _base_type::ciend;
using _base_type::swap;
using _base_type::max_size;
using _base_type::native_handle;
using _base_type::accessor;
};
template <typename T, typename CloneAllocator>
class list<T, CloneAllocator, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value>::type>
: ptr_list<Eo, typename std::conditional
<std::is_same<CloneAllocator, default_clone_allocator_placeholder>::value
, eo_clone_allocator, CloneAllocator>::type>
{
typedef ptr_list<Eo, typename std::conditional
<std::is_same<CloneAllocator, default_clone_allocator_placeholder>::value
, eo_clone_allocator, CloneAllocator>::type> _base_type;
typedef list<T, CloneAllocator> _self_type;
public:
typedef T value_type;
typedef value_type& reference;
typedef value_type const& const_reference;
typedef _ptr_eo_list_iterator<value_type const> const_iterator;
typedef _ptr_eo_list_iterator<value_type> iterator;
typedef value_type* pointer;
typedef value_type const* const_pointer;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef typename _base_type::clone_allocator_type clone_allocator_type;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
explicit list(Eina_List* handle)
: _base_type(handle) {}
list(clone_allocator_type alloc) : _base_type(alloc) {}
list() {}
list(size_type n, const_reference t)
{
while(n--)
push_back(t);
}
template <typename InputIterator>
list(InputIterator i, InputIterator const& j
, clone_allocator_type const& alloc = clone_allocator_type()
, typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
: _base_type(alloc)
{
while(i != j)
{
push_back(*i);
++i;
}
}
list(list<T, CloneAllocator> const& other)
: _base_type()
{
insert(end(), other.begin(), other.end());
}
~list()
{
}
list<T, CloneAllocator>& operator=(list<T, CloneAllocator>const& other)
{
clear();
insert(end(), other.begin(), other.end());
return *this;
}
using _base_type::clear;
using _base_type::size;
using _base_type::empty;
using _base_type::get_clone_allocator;
using _base_type::pop_back;
using _base_type::pop_front;
void push_back(const_reference w)
{
this->_base_type::push_back(* ::eo_ref(w._eo_ptr()));
}
void push_front(const_reference w)
{
this->_base_type::push_front(* ::eo_ref(w._eo_ptr()));
}
iterator insert(iterator i, const_reference v)
{
return this->_base_type::insert(i, * ::eo_ref(v._eo_ptr()));
}
iterator insert(iterator i, size_t n, const_reference v)
{
return this->_base_type::insert(i, n, * ::eo_ref(v._eo_ptr()));
}
template <typename InputIterator>
iterator insert(iterator p, InputIterator i, InputIterator j
, typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
{
iterator r = p;
if(i != j)
{
r = insert(p, *i);
++i;
}
while(i != j)
{
insert(p, *i);
++i;
}
return r;
}
iterator erase(iterator p)
{
return _base_type::erase(p);
}
iterator erase(iterator i, iterator j)
{
return _base_type::erase(i, j);
}
template <typename InputIterator>
void assign(InputIterator i, InputIterator j
, typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
{
clear();
insert(end(), i, j);
}
void assign(size_type n, value_type const& t)
{
clear();
insert(end(), n, t);
}
reference front()
{
return *static_cast<pointer>(static_cast<void*>(&native_handle()->data));
}
reference back()
{
return *static_cast<pointer>(static_cast<void*>(&eina_list_last(native_handle())->data));
}
const_reference front() const { return const_cast<_self_type*>(this)->front(); }
const_reference back() const { return const_cast<_self_type*>(this)->back(); }
iterator begin()
{
return iterator(native_handle(), native_handle());
}
iterator end()
{
return iterator(native_handle(), nullptr);
}
const_iterator begin() const
{
return const_cast<_self_type*>(this)->begin();
}
const_iterator end() const
{
return const_cast<_self_type*>(this)->end();
}
const_iterator cbegin() const
{
return begin();
}
const_iterator cend() const
{
return end();
}
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
const_reverse_iterator rbegin() const
{
return const_cast<_self_type*>(this)->rbegin();
}
const_reverse_iterator rend() const
{
return const_cast<_self_type*>(this)->rend();
}
const_reverse_iterator crbegin() const
{
return rbegin();
}
const_reverse_iterator crend() const
{
return rend();
}
using _base_type::swap;
using _base_type::max_size;
using _base_type::native_handle;
friend bool operator==(list<T, CloneAllocator> const& rhs, list<T, CloneAllocator> const& lhs)
{
return rhs.size() == lhs.size() && std::equal(rhs.begin(), rhs.end(), lhs.begin());
}
};
template <typename T, typename CloneAllocator>
bool operator!=(list<T, CloneAllocator> const& rhs, list<T, CloneAllocator> const& lhs)
{
return !(rhs == lhs);
}
} }
#endif

@ -445,6 +445,8 @@ public:
typedef std::reverse_iterator<iterator> reverse_iterator; /**< Type for reverse iterator for this container. */
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; /**< Type for reverse iterator for this container. */
typedef std::unique_ptr<value_type, clone_allocator_deleter<clone_allocator_type> > _unique_ptr;
/**
* @brief Default constructor. Create an empty array.
*
@ -452,6 +454,10 @@ public:
*/
ptr_array() {}
explicit ptr_array(Eina_Array* handle) : _base_type(handle) {}
explicit ptr_array(clone_allocator_type alloc) : _base_type(alloc) {}
/**
* @brief Construct an array object with @p n copies of @p t.
* @param n Number of elements.
@ -609,7 +615,7 @@ public:
*/
void push_back(pointer p)
{
std::unique_ptr<value_type> p1(p);
_unique_ptr p1(p);
push_back(p1);
}
@ -625,7 +631,8 @@ public:
* @warning The array gains ownership of the object managed by the
* given @c unique_ptr and will release it upon element destruction.
*/
void push_back(std::unique_ptr<T>& p)
template <typename Deleter>
void push_back(std::unique_ptr<T, Deleter>& p)
{
if(eina_array_push(this->_impl._array, p.get()))
p.release();
@ -678,7 +685,7 @@ public:
*/
iterator insert(iterator i, pointer pv)
{
std::unique_ptr<value_type> p(pv);
_unique_ptr p(pv);
return insert(i, p);
}
@ -699,7 +706,8 @@ public:
* @warning The array gains ownership of the object managed by the
* given @c unique_ptr and will release it upon element destruction.
*/
iterator insert(iterator i, std::unique_ptr<value_type>& p)
template <typename Deleter>
iterator insert(iterator i, std::unique_ptr<value_type, Deleter>& p)
{
std::size_t j
= i.native_handle() - this->_impl._array->data
@ -712,7 +720,7 @@ public:
this->_impl._array->data + j + 1
, this->_impl._array->data + j
, (size_ - j)*sizeof(void*));
// PRE: Q:[j, size) = [j+1, size+1)
// PRE: Q:[j, size_) = [j+1, size_+1)
pointer* data = static_cast<pointer*>
(static_cast<void*>(this->_impl._array->data));
data[j] = p.get();

@ -1,15 +1,17 @@
#ifndef EINA_LIST_HH_
#define EINA_LIST_HH_
#ifndef EINA_PTRLIST_HH_
#define EINA_PTRLIST_HH_
#include <Eina.h>
#include <eina_clone_allocators.hh>
#include <eina_lists_auxiliary.hh>
#include <eina_type_traits.hh>
#include <eina_accessor.hh>
#include <eina_eo_base_fwd.hh>
#include <eina_iterator.hh>
#include <memory>
#include <iterator>
#include <type_traits>
/**
* @addtogroup Eina_Cxx_Containers_Group
@ -560,6 +562,8 @@ public:
typedef std::reverse_iterator<iterator> reverse_iterator; /**< Type for reverse iterator for this container. */
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; /**< Type for reverse iterator for this container. */
typedef std::unique_ptr<value_type, clone_allocator_deleter<clone_allocator_type> > _unique_ptr;
/**
* @brief Default constructor. Create an empty list.
*
@ -567,6 +571,12 @@ public:
*/
ptr_list() {}
ptr_list(Eina_List* handle) : _base_type(handle) {}
ptr_list(clone_allocator_type alloc)
: _base_type(alloc)
{}
/**
* @brief Construct an list object with @p n copies of @p t.
* @param n Number of elements.
@ -725,7 +735,7 @@ public:
*/
void push_back(pointer p)
{
std::unique_ptr<value_type> p1(p);
_unique_ptr p1(p);
push_back(p1);
}
@ -740,7 +750,8 @@ public:
* @warning The list gains ownership of the object managed by the
* given @c unique_ptr and will release it upon element destruction.
*/
void push_back(std::unique_ptr<T>& p)
template <typename Deleter>
void push_back(std::unique_ptr<T, Deleter>& p)
{
Eina_List* new_list = eina_list_append(this->_impl._list, p.get());
if(new_list)
@ -761,7 +772,7 @@ public:
*/
void push_front(const_reference a)
{
push_front(this->new_clone(a));
push_front(this->_new_clone(a));
}
/**
@ -777,7 +788,7 @@ public:
*/
void push_front(pointer p)
{
std::unique_ptr<value_type> p1(p);
_unique_ptr p1(p);
push_front(p1);
}
@ -792,7 +803,8 @@ public:
* @warning The list gains ownership of the object managed by the
* given @c unique_ptr and will release it upon element destruction.
*/
void push_front(std::unique_ptr<T>& p)
template <typename Deleter>
void push_front(std::unique_ptr<T, Deleter>& p)
{
Eina_List* new_list = eina_list_prepend(this->_impl._list, p.get());
if(new_list)
@ -857,7 +869,7 @@ public:
*/
iterator insert(iterator i, pointer pv)
{
std::unique_ptr<value_type> p(pv);
_unique_ptr p(pv);
return insert(i, p);
}
@ -878,7 +890,8 @@ public:
* @warning The list gains ownership of the object managed by the
* given @c unique_ptr and will release it upon element destruction.
*/
iterator insert(iterator i, std::unique_ptr<value_type>& p)
template <typename Deleter>
iterator insert(iterator i, std::unique_ptr<value_type, Deleter>& p)
{
this->_impl._list = _eina_list_prepend_relative_list
(this->_impl._list, p.get(), i.native_handle());
@ -967,7 +980,7 @@ public:
iterator r = p;
if(i != j)
{
r = insert(p, *i);
r = insert(p, this->_new_clone(*i));
++i;
}
while(i != j)
@ -1442,7 +1455,6 @@ void swap(ptr_list<T, CloneAllocator>& lhs, ptr_list<T, CloneAllocator>& rhs)
{
lhs.swap(rhs);
}
/**
* @}
*/

@ -47,6 +47,11 @@ struct base
detail::unref(_eo_raw);
}
base(base const& other)
: _eo_raw( detail::ref(other._eo_ptr()) )
{
}
/// @brief Assignment operator.
///
base& operator=(base const& other)
@ -164,8 +169,19 @@ struct base
protected:
Eo* _eo_raw; ///< The opaque <em>EO Object</em>.
};
inline bool operator==(base const& lhs, base const& rhs)
{
return lhs._eo_ptr() == rhs._eo_ptr();
}
inline bool operator!=(base const& lhs, base const& rhs)
{
return !(lhs == rhs);
}
/// @brief Downcast @p U to @p T.
///
/// @param T An <em>EO C++ Class</em>.
@ -206,21 +222,21 @@ struct parent_type
///
struct parent_expr
{
parent_type operator=(efl::eo::base const& parent)
parent_type operator=(efl::eo::base const& parent) const
{
return { parent._eo_ptr() };
}
parent_type operator=(std::nullptr_t)
parent_type operator=(std::nullptr_t) const
{
return { NULL };
return { nullptr };
}
};
///
/// @brief Placeholder for the parent argument.
///
parent_expr parent = {};
parent_expr const parent = {};
/// @}

@ -3,7 +3,7 @@ MAINTAINERCLEANFILES = Makefile.in
AM_CXXFLAGS = \
-I$(top_builddir)/src/lib/efl \
-I. \
@EINA_CXX_CFLAGS@ @CHECK_CFLAGS@ @EINA_CFLAGS@
@EINA_CXX_CFLAGS@ @CHECK_CFLAGS@ @EINA_CFLAGS@ @EO_CFLAGS@
LDADD = $(top_builddir)/src/lib/eina/libeina.la @EINA_LDFLAGS@ @EFL_PTHREAD_LIBS@

@ -1,226 +1,479 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "Eina.hh"
#include "Eo.hh"
#include <eina_array.hh>
#include <algorithm>
#include <check.h>
const Eo_Class *simple_class_get(void);
#define MY_CLASS simple_class_get()
struct wrapper : efl::eo::base
{
explicit wrapper(Eo* o)
: base(o) {}
};
START_TEST(eina_cxx_ptrarray_push_back)
{
efl::eina::eina_init eina_init;
efl::eina::ptr_array<int> array;
array.push_back(new int(5));
array.push_back(new int(10));
array.push_back(new int(15));
efl::eo::eo_init eo_init;
int result[] = {5, 10, 15};
int rresult[] = {15, 10, 5};
ck_assert(array.size() == 3);
ck_assert(std::equal(array.begin(), array.end(), result));
ck_assert(std::equal(array.rbegin(), array.rend(), rresult));
wrapper const w1(eo_add(MY_CLASS, NULL));
wrapper const w2(eo_add(MY_CLASS, NULL));
wrapper const w3(eo_add(MY_CLASS, NULL));
{
efl::eina::ptr_array<int> array;
array.push_back(new int(5));
array.push_back(new int(10));
array.push_back(new int(15));
ck_assert(array.size() == 3);
ck_assert(std::equal(array.begin(), array.end(), result));
ck_assert(std::equal(array.rbegin(), array.rend(), rresult));
}
{
efl::eina::array<int> array;
array.push_back(new int(5));
array.push_back(new int(10));
array.push_back(new int(15));
ck_assert(array.size() == 3);
ck_assert(std::equal(array.begin(), array.end(), result));
ck_assert(std::equal(array.rbegin(), array.rend(), rresult));
}
{
wrapper result_[] = {w1, w2, w3};
wrapper rresult[] = {w3, w2, w1};
efl::eina::array<wrapper> array;
array.push_back(w1);
array.push_back(w2);
array.push_back(w3);
ck_assert(array.size() == 3);
ck_assert(std::equal(array.begin(), array.end(), result_));
ck_assert(std::equal(array.rbegin(), array.rend(), rresult));
}
}
END_TEST
START_TEST(eina_cxx_ptrarray_pop_back)
{
efl::eina::eina_init eina_init;
efl::eina::ptr_array<int> array;
array.push_back(new int(5));
array.push_back(new int(10));
array.push_back(new int(15));
array.pop_back();
efl::eo::eo_init eo_init;
int result[] = {5, 10};
int rresult[] = {10, 5};
ck_assert(array.size() == 2);
ck_assert(std::equal(array.begin(), array.end(), result));
ck_assert(std::equal(array.rbegin(), array.rend(), rresult));
{
efl::eina::ptr_array<int> array;
array.push_back(new int(5));
array.push_back(new int(10));
array.push_back(new int(15));
array.pop_back();
ck_assert(array.size() == 2);
ck_assert(std::equal(array.begin(), array.end(), result));
ck_assert(std::equal(array.rbegin(), array.rend(), rresult));
}
{
efl::eina::array<int> array;
array.push_back(new int(5));
array.push_back(new int(10));
array.push_back(new int(15));
array.pop_back();
ck_assert(array.size() == 2);
ck_assert(std::equal(array.begin(), array.end(), result));
ck_assert(std::equal(array.rbegin(), array.rend(), rresult));
}
{
wrapper const w1(eo_add(MY_CLASS, NULL));
wrapper const w2(eo_add(MY_CLASS, NULL));
wrapper const w3(eo_add(MY_CLASS, NULL));
efl::eina::array<wrapper> array;
array.push_back(w1);
array.push_back(w2);
array.push_back(w3);
array.pop_back();
wrapper result_[] = {w1, w2};
wrapper rresult[] = {w2, w1};
ck_assert(array.size() == 2);
ck_assert(std::equal(array.begin(), array.end(), result_));
ck_assert(std::equal(array.rbegin(), array.rend(), rresult));
}
}
END_TEST
START_TEST(eina_cxx_ptrarray_insert)
{
efl::eina::eina_init eina_init;
efl::eina::ptr_array<int> array;
ck_assert(std::distance(array.begin(), array.end()) == 0u);
ck_assert(std::distance(array.rbegin(), array.rend()) == 0u);
efl::eina::ptr_array<int>::iterator it;
it = array.insert(array.end(), new int(5)); // first element
ck_assert(it != array.end());
++it;
ck_assert(it == array.end());
ck_assert(array[0] == 5);
ck_assert(std::distance(array.begin(), array.end()) == 1u);
it = array.insert(array.end(), new int(10)); // equivalent to push_back
ck_assert(it != array.end());
++it;
ck_assert(it == array.end());
ck_assert(array[0] == 5);
ck_assert(array[1] == 10);
ck_assert(std::distance(array.begin(), array.end()) == 2u);
it = array.insert(array.begin(), new int(15)); // equivalent to push_front
ck_assert(it == array.begin());
ck_assert(array[1] == 5);
ck_assert(array[2] == 10);
ck_assert(array[0] == 15);
ck_assert(std::distance(array.begin(), array.end()) == 3u);
array.insert(array.end() - 1, new int(20)); // insert before the last element
ck_assert(array[0] == 15);
ck_assert(array[1] == 5);
ck_assert(array[2] == 20);
ck_assert(array[3] == 10);
ck_assert(std::distance(array.begin(), array.end()) == 4u);
int result[] = {15, 5, 20, 10};
int rresult[] = {10, 20, 5, 15};
ck_assert(array.size() == 4);
ck_assert(std::distance(array.begin(), array.end()) == 4u);
ck_assert(std::distance(array.rbegin(), array.rend()) == 4u);
ck_assert(std::equal(array.begin(), array.end(), result));
ck_assert(std::equal(array.rbegin(), array.rend(), rresult));
efl::eina::ptr_array<int, efl::eina::heap_copy_allocator> array2;
it = array2.insert(array2.end(), array.begin(), array.end());
ck_assert(it == array2.begin());
ck_assert(array == array2);
efl::eina::ptr_array<int, efl::eina::heap_copy_allocator> array3;
array3.push_back(1);
it = array3.insert(array3.end(), array.begin(), array.end());
ck_assert(array3.size() == 5);
ck_assert(array3.front() == 1);
it = array3.begin();
++it;
ck_assert(std::equal(it, array3.end(), array.begin()));
efl::eina::ptr_array<int, efl::eina::heap_copy_allocator> array4;
array4.push_back(1);
it = array4.insert(array4.begin(), array.begin(), array.end());
ck_assert(array4.size() == 5);
ck_assert(array4.back() == 1);
ck_assert(std::equal(array.begin(), array.end(), array4.begin()));
efl::eo::eo_init eo_init;
{
efl::eina::ptr_array<int> array;
ck_assert(std::distance(array.begin(), array.end()) == 0u);
ck_assert(std::distance(array.rbegin(), array.rend()) == 0u);
efl::eina::ptr_array<int>::iterator it;
it = array.insert(array.end(), new int(5)); // first element
ck_assert(it != array.end());
++it;
ck_assert(it == array.end());
ck_assert(array[0] == 5);
ck_assert(std::distance(array.begin(), array.end()) == 1u);
it = array.insert(array.end(), new int(10)); // equivalent to push_back
ck_assert(it != array.end());
++it;
ck_assert(it == array.end());
ck_assert(array[0] == 5);
ck_assert(array[1] == 10);
ck_assert(std::distance(array.begin(), array.end()) == 2u);
it = array.insert(array.begin(), new int(15)); // equivalent to push_front
ck_assert(it == array.begin());
ck_assert(array[1] == 5);