#ifndef EINA_INARRAY_HH_ #define EINA_INARRAY_HH_ #include #include #include #include #include namespace efl { namespace eina { struct _inarray_common_base { typedef std::size_t size_type; explicit _inarray_common_base(size_type member_size) : _array( ::eina_inarray_new(member_size, 0) ) { } ~_inarray_common_base() { ::eina_inarray_free(_array); } size_type size() const { return ::eina_inarray_count(_array); } bool empty() const { return size() == 0u; } Eina_Inarray* _array; private: _inarray_common_base(_inarray_common_base const& other); _inarray_common_base& operator=(_inarray_common_base const& other); }; template class _pod_inarray : _inarray_common_base { typedef _inarray_common_base _base_type; public: typedef T value_type; typedef T& reference; typedef T const& const_reference; typedef T* pointer; typedef T const* const_pointer; typedef pointer iterator; typedef const_pointer const_iterator; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; using _base_type::size; using _base_type::empty; _pod_inarray() : _base_type(sizeof(T)) { } _pod_inarray(size_type n, value_type const& t) : _base_type(sizeof(T)) { while(n--) push_back(t); } template _pod_inarray(InputIterator i, InputIterator const& j , typename eina::enable_if::value>::type* = 0) : _base_type(sizeof(T)) { while(i != j) { push_back(*i); ++i; } } _pod_inarray(_pod_inarrayconst& other) : _base_type(sizeof(T)) { insert(end(), other.begin(), other.end()); } ~_pod_inarray() { } _pod_inarray& operator=(_pod_inarrayconst& other) { clear(); insert(end(), other.begin(), other.end()); return *this; } void clear() { ::eina_inarray_flush(_array); } void push_back(T const& value) { eina_inarray_push(_array, &value); } void pop_back() { eina_inarray_pop(_array); } iterator insert(iterator i, value_type const& t) { if(i != end()) { T* q = static_cast ( ::eina_inarray_alloc_at(_array, i - begin(), 1u)); std::memcpy(q, &t, sizeof(t)); return q; } else { push_back(t); return end()-1; } } iterator insert(iterator i, size_t n, value_type const& t) { T* q; if(i != end()) { q = static_cast ( ::eina_inarray_alloc_at(_array, i - &_array->members, n)); } else { q = eina_inarray_grow(_array, n); } for(T* p = q; n; --n, ++p) std::memcpy(p, &t, sizeof(t)); return q; } template iterator insert(iterator p, InputIterator i, InputIterator j , typename eina::enable_if::value>::type* = 0) { size_type n = 0; while(i != j) { p = insert(p, *i); ++p; ++i; ++n; } return p - n; } iterator erase(iterator q) { ::eina_inarray_remove_at(_array, q - begin()); return q; } iterator erase(iterator i, iterator j) { while(i != j) { erase(--j); } return i; } template void assign(InputIterator i, InputIterator j , typename eina::enable_if::value>::type* = 0); void assign(size_type n, value_type const& t); value_type& back() { assert(!empty()); return *static_cast(eina_inarray_nth(_array, size()-1u)); } value_type const& back() const { return const_cast<_pod_inarray&>(*this).back(); } value_type& front() { assert(!empty()); return *static_cast(eina_inarray_nth(_array, 0u)); } value_type const& front() const { return const_cast<_pod_inarray&>(*this).front(); } iterator begin() { return !_array->members ? 0 : static_cast(::eina_inarray_nth(_array, 0u)); } iterator end() { return !_array->members ? 0 : static_cast(::eina_inarray_nth(_array, size()-1)) + 1; } const_iterator begin() const { return const_cast< _pod_inarray&>(*this).begin(); } const_iterator end() const { return const_cast< _pod_inarray&>(*this).end(); } const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(end()); } reverse_iterator rbegin() { return reverse_iterator(begin()); } reverse_iterator rend() { return reverse_iterator(end()); } const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } const_reverse_iterator crbegin() const { return rbegin(); } const_reverse_iterator crend() const { return rend(); } void swap(_pod_inarray& other) { std::swap(_array, other._array); } size_type max_size() const { return -1; } Eina_Inarray* native_handle() { return this->_array; } Eina_Inarray const* native_handle() const { return this->_array; } }; template class _nonpod_inarray : _inarray_common_base { typedef _inarray_common_base _base_type; public: typedef T value_type; typedef T& reference; typedef T const& const_reference; typedef T* pointer; typedef T const* const_pointer; typedef pointer iterator; typedef const_pointer const_iterator; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; using _base_type::size; using _base_type::empty; _nonpod_inarray() : _base_type(sizeof(T)) { } _nonpod_inarray(size_type n, value_type const& t) : _base_type(sizeof(T)) { while(n--) push_back(t); } template _nonpod_inarray(InputIterator i, InputIterator const& j , typename eina::enable_if::value>::type* = 0) : _base_type(sizeof(T)) { while(i != j) { push_back(*i); ++i; } } _nonpod_inarray(_nonpod_inarrayconst& other) : _base_type(sizeof(T)) { insert(end(), other.begin(), other.end()); } ~_nonpod_inarray() { for(T* first = static_cast(_array->members) , *last = first + _array->len; first != last; ++first) first->~T(); } _nonpod_inarray& operator=(_nonpod_inarrayconst& other) { clear(); insert(end(), other.begin(), other.end()); return *this; } void clear() { for(T* first = static_cast(_array->members) , *last = first + _array->len; first != last; ++first) first->~T(); ::eina_inarray_flush(_array); } void push_back(T const& value) { insert(end(), 1u, value); } void pop_back() { T* elem = static_cast(_array->members) + _array->len - 1; elem->~T(); eina_inarray_pop(_array); } iterator insert(iterator i, value_type const& t) { return insert(i, 1u, t); } iterator insert(iterator i, size_t n, value_type const& t) { if(_array->max - _array->len >= n) { iterator end = static_cast(_array->members) + _array->len , last = end + n; _array->len += n; std::reverse_iterator dest(last), src(end), src_end(i); for(;src != src_end; ++src) { if(dest.base() <= end) *dest++ = *src; else new (&*dest++) T(*src); } iterator j = i; for(size_type i = 0;i != n;++i) { if(j < end) *j = t; else new (&*j++) T(t); } } else { size_type index = i - static_cast(_array->members); Eina_Inarray* old_array = eina_inarray_new(_array->member_size, 0); *old_array = *_array; _array->len = _array->max = 0; _array->members = 0; eina_inarray_resize(_array, old_array->len+n); _array->len = old_array->len+n; iterator old_first = static_cast(old_array->members) , first = begin() , last = first + _array->len; i = index + begin(); while(first != i) { new (&*first++) T(*old_first); old_first++->~T(); } for(size_type i = 0;i != n;++i) new (&*first++) T(t); std::size_t diff = last - first; assert(diff == _array->len - index - n); while(first != last) { new (&*first++) T(*old_first); old_first++->~T(); } } return i; } template iterator insert(iterator p, InputIterator i, InputIterator j , typename eina::enable_if::value>::type* = 0) { size_type n = 0; while(i != j) { p = insert(p, *i); ++p; ++i; ++n; } return p - n; } iterator erase(iterator q) { return erase(q, q+1); } iterator erase(iterator i, iterator j) { iterator last = end(); iterator k = i, l = j; while(l != last) *k++ = *l++; while(k != last) k++->~T(); _array->len -= j - i; return i; } template void assign(InputIterator i, InputIterator j , typename eina::enable_if::value>::type* = 0); void assign(size_type n, value_type const& t); value_type& back() { assert(!empty()); return *static_cast(eina_inarray_nth(_array, size()-1u)); } value_type const& back() const { return const_cast<_nonpod_inarray&>(*this).back(); } value_type& front() { assert(!empty()); return *static_cast(eina_inarray_nth(_array, 0u)); } value_type const& front() const { return const_cast<_nonpod_inarray&>(*this).front(); } iterator begin() { return static_cast(_array->members); } iterator end() { return static_cast(_array->members) + _array->len; } const_iterator begin() const { return const_cast< _nonpod_inarray&>(*this).begin(); } const_iterator end() const { return const_cast< _nonpod_inarray&>(*this).end(); } const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(end()); } reverse_iterator rbegin() { return reverse_iterator(begin()); } reverse_iterator rend() { return reverse_iterator(end()); } const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } const_reverse_iterator crbegin() const { return rbegin(); } const_reverse_iterator crend() const { return rend(); } void swap(_nonpod_inarray& other) { std::swap(_array, other._array); } size_type max_size() const { return -1; } Eina_Inarray* native_handle() { return this->_array; } Eina_Inarray const* native_handle() const { return this->_array; } }; template class inarray : public eina::if_, _pod_inarray , _nonpod_inarray >::type { typedef typename eina::if_, _pod_inarray , _nonpod_inarray >::type _base_type; public: inarray() : _base_type() {} inarray(typename _base_type::size_type n, typename _base_type::value_type const& t) : _base_type(n, t) {} template inarray(InputIterator i, InputIterator const& j , typename eina::enable_if::value>::type* = 0) : _base_type(i, j) {} }; template bool operator==(inarray const& lhs, inarray const& rhs) { return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); } template bool operator!=(inarray const& lhs, inarray const& rhs) { return !(lhs == rhs); } template void swap(inarray& lhs, inarray& rhs) { lhs.swap(rhs); } } } #endif