#ifndef EINA_LIST_HH_ #define EINA_LIST_HH_ #include #include #include #include #include #include #include namespace efl { namespace eina { struct _ptr_list_iterator_base { typedef std::ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; _ptr_list_iterator_base() : _list(0) {} _ptr_list_iterator_base(Eina_List* list, Eina_List* node) : _list(list), _node(node) {} protected: Eina_List *_list, *_node; }; template struct _ptr_list_iterator : _ptr_list_iterator_base { typedef T value_type; typedef value_type* pointer; typedef value_type& reference; _ptr_list_iterator() {} explicit _ptr_list_iterator(Eina_List* list, Eina_List* node) : _ptr_list_iterator_base(list, node) { } _ptr_list_iterator(_ptr_list_iterator::type> const& other) : _ptr_list_iterator_base(static_cast<_ptr_list_iterator_base const&>(other)) { } _ptr_list_iterator& operator++() { _node = eina_list_next(_node); return *this; } _ptr_list_iterator operator++(int) { _ptr_list_iterator tmp(*this); ++*this; return tmp; } _ptr_list_iterator& operator--() { if(_node) _node = eina_list_prev(_node); else _node = eina_list_last(_list); return *this; } _ptr_list_iterator operator--(int) { _ptr_list_iterator tmp(*this); --*this; return tmp; } reference operator*() const { void* data = eina_list_data_get(_node); return *static_cast(data); } pointer operator->() const { return &**this; } Eina_List* native_handle() { return _node; } Eina_List const* native_handle() const { return _node; } friend inline bool operator==(_ptr_list_iterator lhs, _ptr_list_iterator rhs) { return lhs._node == rhs._node; } friend inline bool operator!=(_ptr_list_iterator lhs, _ptr_list_iterator rhs) { return !(lhs == rhs); } }; template struct _ptr_list_common_base { typedef CloneAllocator clone_allocator_type; _ptr_list_common_base(CloneAllocator clone_allocator) : _impl(clone_allocator) {} _ptr_list_common_base(Eina_List* _list) : _impl(_list) {} _ptr_list_common_base() {} CloneAllocator& _get_clone_allocator() { return _impl; } CloneAllocator const& _get_clone_allocator() const { return _impl; } void _delete_clone(T const* p) { _get_clone_allocator().deallocate_clone(p); } T* _new_clone(T const& a) { return _get_clone_allocator().allocate_clone(a); } struct _ptr_list_impl : CloneAllocator { _ptr_list_impl() : _list(0) {} _ptr_list_impl(CloneAllocator allocator) : clone_allocator_type(allocator), _list(0) {} Eina_List* _list; }; _ptr_list_impl _impl; private: _ptr_list_common_base(_ptr_list_common_base const& other); _ptr_list_common_base& operator=(_ptr_list_common_base const& other); }; template class ptr_list : protected _ptr_list_common_base { typedef _ptr_list_common_base _base_type; public: typedef T value_type; typedef T& reference; typedef T const& const_reference; typedef _ptr_list_iterator const_iterator; typedef _ptr_list_iterator iterator; typedef T* pointer; typedef T const* const_pointer; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef CloneAllocator clone_allocator_type; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; ptr_list() {} ptr_list(size_type n, const_reference t) { while(n--) push_back(t); } template ptr_list(InputIterator i, InputIterator const& j , clone_allocator_type const& alloc = clone_allocator_type() , typename eina::enable_if::value>::type* = 0) : _base_type(alloc) { while(i != j) { push_back(*i); ++i; } } ptr_list(ptr_list const& other) : _base_type() { insert(end(), other.begin(), other.end()); } template ptr_list(ptr_listconst& other) : _base_type() { insert(end(), other.begin(), other.end()); } ~ptr_list() { clear(); } ptr_list& operator=(ptr_listconst& other) { clear(); insert(end(), other.begin(), other.end()); return *this; } void clear() { for(iterator first = begin(), last = end(); first != last; ++first) this->_delete_clone(&*first); eina_list_free(this->_impl._list); this->_impl._list = 0; } std::size_t size() const { return eina_list_count(this->_impl._list); } bool empty() const { return size() == 0u; } clone_allocator_type get_clone_allocator() const { return clone_allocator_type(this->_get_clone_allocator()); } void push_back(const_reference a) { push_back(this->_new_clone(a)); } void push_back(pointer p) { std::unique_ptr p1(p); push_back(p1); } void push_back(std::unique_ptr& p) { Eina_List* new_list = eina_list_append(this->_impl._list, p.get()); if(new_list) { this->_impl._list = new_list; p.release(); } else throw std::bad_alloc(); } void push_front(const_reference a) { push_front(this->new_clone(a)); } void push_front(pointer p) { std::unique_ptr p1(p); push_front(p1); } void push_front(std::unique_ptr& p) { Eina_List* new_list = eina_list_prepend(this->_impl._list, p.get()); if(new_list) { this->_impl._list = new_list; p.release(); } else throw std::bad_alloc(); } void pop_back() { this->_impl._list = eina_list_remove_list(this->_impl._list, eina_list_last(this->_impl._list)); } void pop_front() { this->_impl._list = eina_list_remove_list(this->_impl._list, this->_impl._list); } iterator insert(iterator i, value_type const& t) { return insert(i, this->_new_clone(t)); } iterator insert(iterator i, pointer pv) { std::unique_ptr p(pv); return insert(i, p); } iterator insert(iterator i, std::unique_ptr& p) { this->_impl._list = _eina_list_prepend_relative_list (this->_impl._list, p.get(), i.native_handle()); if(this->_impl._list) p.release(); else throw std::bad_alloc(); return iterator(this->_impl._list , i.native_handle() ? ::eina_list_prev(i.native_handle()) : ::eina_list_last(this->_impl._list) ); } iterator insert(iterator i, size_t n, value_type const& t) { iterator r = i; if(n--) r = insert(i, t); while(n--) insert(i, t); return r; } iterator insert(iterator i, size_t n, pointer p) { iterator r = i; if(n--) r = insert(i, p); while(n--) insert(i, this->_new_clone(p)); return r; } template iterator insert(iterator p, InputIterator i, InputIterator j , typename eina::enable_if::value>::type* = 0) { iterator r = p; if(i != j) { r = insert(p, *i); ++i; } while(i != j) { insert(p, this->_new_clone(*i)); ++i; } return r; } iterator erase(iterator q) { if(q.native_handle()) { iterator r(this->_impl._list, eina_list_next(q.native_handle())); this->_impl._list = eina_list_remove_list(this->_impl._list, q.native_handle()); return r; } else return q; } iterator erase(iterator i, iterator j) { while(i != j) i = erase(i); if(j.native_handle()) return j; else return end(); } template void assign(InputIterator i, InputIterator j , typename eina::enable_if::value>::type* = 0) { clear(); insert(end(), i, j); } void assign(size_type n, value_type const& t) { clear(); insert(end(), n, t); } value_type& back() { return *static_cast(eina_list_data_get(eina_list_last(this->_impl._list))); } value_type const& back() const { return const_cast&>(*this).back(); } value_type& front() { return *static_cast(eina_list_data_get(this->_impl._list)); } value_type const& front() const { return const_cast&>(*this).front(); } const_iterator begin() const { return const_iterator(this->_impl._list, this->_impl._list); } const_iterator end() const { return const_iterator(this->_impl._list, 0); } iterator begin() { return iterator(this->_impl._list, this->_impl._list); } iterator end() { return iterator(this->_impl._list, 0); } 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(); } eina::iterator ibegin() { return eina::iterator( ::eina_list_iterator_new(this->_impl._list) ); } eina::iterator iend() { return eina::iterator(); } eina::iterator ibegin() const { return eina::iterator( ::eina_list_iterator_new(this->_impl._list) ); } eina::iterator iend() const { return eina::iterator(); } eina::iterator cibegin() const { return ibegin(); } eina::iterator ciend() const { return iend(); } void swap(ptr_list& other) { std::swap(this->_impl._list, other._impl._list); } size_type max_size() const { return -1; } Eina_List* native_handle() { return this->_impl._list; } Eina_List const* native_handle() const { return this->_impl._list; } eina::accessor accessor() const { return eina::accessor(eina_list_accessor_new(this->_impl._list)); } eina::accessor accessor() { return eina::accessor(eina_list_accessor_new(this->_impl._list)); } }; template bool operator==(ptr_list const& lhs, ptr_list const& rhs) { return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); } template bool operator!=(ptr_list const& lhs, ptr_list const& rhs) { return !(lhs == rhs); } template void swap(ptr_list& lhs, ptr_list& rhs) { lhs.swap(rhs); } } } #endif