#ifndef EINA_INARRAY_HH_ #define EINA_INARRAY_HH_ #include #include #include #include #include #include namespace efl { namespace eina { struct _inarray_access_traits { template struct const_iterator { typedef T const* type; }; template struct iterator { typedef T* type; }; template struct const_native_handle { typedef Eina_Inarray const* type; }; template struct native_handle { typedef Eina_Inarray* type; }; template static Eina_Inarray* native_handle_from_const(Eina_Inarray const* array) { return const_cast(array); } template static T& back(Eina_Inarray* raw) { assert(!_inarray_access_traits::empty(raw)); return *static_cast( ::eina_inarray_nth(raw, _inarray_access_traits::size(raw)-1u)); } template static T const& back(Eina_Inarray const* raw) { return _inarray_access_traits::back(const_cast(raw)); } template static T& front(Eina_Inarray* raw) { assert(!empty(raw)); return *static_cast( ::eina_inarray_nth(raw, 0u)); } template static T const& front(Eina_Inarray const* raw) { return _inarray_access_traits::front(const_cast(raw)); } template static T* begin(Eina_Inarray* raw) { return !raw->members ? 0 : static_cast( ::eina_inarray_nth(raw, 0u)); } template static T* end(Eina_Inarray* raw) { return !raw->members ? 0 : static_cast( ::eina_inarray_nth(raw, _inarray_access_traits::size(raw) -1)) + 1; } template static T const* begin(Eina_Inarray const* raw) { return _inarray_access_traits::begin(const_cast(raw)); } template static T const* end(Eina_Inarray const* raw) { return _inarray_access_traits::end(const_cast(raw)); } template static std::reverse_iterator rbegin(Eina_Inarray const* raw) { return std::reverse_iterator(_inarray_access_traits::begin(raw)); } template static std::reverse_iterator rend(Eina_Inarray const* raw) { return std::reverse_iterator(_inarray_access_traits::end(raw)); } template static std::reverse_iterator rbegin(Eina_Inarray* raw) { return std::reverse_iterator(_inarray_access_traits::begin(raw)); } template static std::reverse_iterator rend(Eina_Inarray* raw) { return std::reverse_iterator(_inarray_access_traits::end(raw)); } template static T const* cbegin(Eina_Inarray const* raw) { return _inarray_access_traits::begin(raw); } template static T const* cend(Eina_Inarray const* raw) { return _inarray_access_traits::end(raw); } template static std::reverse_iterator crbegin(Eina_Inarray const* raw) { return _inarray_access_traits::rbegin(raw); } template static std::reverse_iterator crend(Eina_Inarray const* raw) { return _inarray_access_traits::rend(raw); } template static inline bool empty(Eina_Inarray const* raw) { return _inarray_access_traits::size(raw) == 0; } template static inline std::size_t size(Eina_Inarray const* raw) { return ::eina_inarray_count(raw); } template static T const& index(Eina_Inarray const* raw, std::size_t i) { return *(_inarray_access_traits::begin(raw) + i); } template static T& index(Eina_Inarray* raw, std::size_t i) { return *(_inarray_access_traits::begin(raw) + i); } }; template class inarray; template struct range_inarray : _range_template { typedef _range_template _base_type; typedef typename std::remove_const::type value_type; range_inarray(Eina_Inarray* array) : _base_type(array) {} range_inarray(inarray& array) : _base_type(array.native_handle()) {} value_type& operator[](std::size_t index) const { return _inarray_access_traits::index(this->native_handle(), index); } }; struct _inarray_common_base { typedef std::size_t size_type; typedef Eina_Inarray* native_handle_type; typedef Eina_Inarray const* const_native_handle_type; explicit _inarray_common_base(Eina_Inarray* array) : _array(array) {} 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 _inarray_access_traits::size(_array); } bool empty() const { return _inarray_access_traits::empty(_array); } native_handle_type native_handle() { return _array; } const_native_handle_type native_handle() const { return _array; } 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 _base_type::native_handle_type native_handle_type; typedef _base_type::const_native_handle_type const_native_handle_type; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; using _base_type::size; using _base_type::empty; using _base_type::native_handle; _pod_inarray(Eina_Inarray* array) : _base_type(array) {} _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) { size_type s = size(); eina_inarray_push(_array, &value); assert(size() != s); assert(size() == s + 1u); } 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& operator[](size_type i) { return *(begin() + i); } value_type const& operator[](size_type i) const { return const_cast&>(*this)[i]; } value_type& back() { return _inarray_access_traits::back(_array); } value_type const& back() const { return _inarray_access_traits::back(_array); } value_type& front() { return _inarray_access_traits::front(_array); } value_type const& front() const { return _inarray_access_traits::front(_array); } iterator begin() { return _inarray_access_traits::begin(_array); } iterator end() { return _inarray_access_traits::end(_array); } const_iterator begin() const { return _inarray_access_traits::begin(_array); } const_iterator end() const { return _inarray_access_traits::end(_array); } const_reverse_iterator rbegin() const { return _inarray_access_traits::rbegin(_array); } const_reverse_iterator rend() const { return _inarray_access_traits::rend(_array); } reverse_iterator rbegin() { return _inarray_access_traits::rbegin(_array); } reverse_iterator rend() { return _inarray_access_traits::rend(_array); } const_iterator cbegin() const { return _inarray_access_traits::cbegin(_array); } const_iterator cend() const { return _inarray_access_traits::cend(_array); } const_reverse_iterator crbegin() const { return _inarray_access_traits::crbegin(_array); } const_reverse_iterator crend() const { return _inarray_access_traits::crend(_array); } 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(Eina_Inarray* array) : _base_type(array) {} _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& operator[](size_type i) { return *(begin() + i); } value_type const& operator[](size_type i) const { return const_cast&>(*this)[i]; } value_type& back() { return _inarray_access_traits::back(_array); } value_type const& back() const { return _inarray_access_traits::back(_array); } value_type& front() { return _inarray_access_traits::front(_array); } value_type const& front() const { return _inarray_access_traits::front(_array); } iterator begin() { return _inarray_access_traits::begin(_array); } iterator end() { return _inarray_access_traits::end(_array); } const_iterator begin() const { return _inarray_access_traits::begin(_array); } const_iterator end() const { return _inarray_access_traits::end(_array); } const_reverse_iterator rbegin() const { return _inarray_access_traits::rbegin(_array); } const_reverse_iterator rend() const { return _inarray_access_traits::rend(_array); } reverse_iterator rbegin() { return _inarray_access_traits::rbegin(_array); } reverse_iterator rend() { return _inarray_access_traits::rend(_array); } const_iterator cbegin() const { return _inarray_access_traits::cbegin(_array); } const_iterator cend() const { return _inarray_access_traits::cend(_array); } const_reverse_iterator crbegin() const { return _inarray_access_traits::crbegin(_array); } const_reverse_iterator crend() const { return _inarray_access_traits::crend(_array); } 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(Eina_Inarray* array) : _base_type(array) {} 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