// // Created by kikab on 06.05.2018. // #ifndef XOR_LIST_XORLIST_H #define XOR_LIST_XORLIST_H #include #include #include #include #include #include #include #include #include template struct XorListNode { public: XorListNode() = delete; explicit XorListNode(const T &val) { val_ = val; } explicit XorListNode(T &&val) { val_ = std::move(val);//std::forward(val); //std::cout << "move-constructor\n"; } XorListNode *right(const XorListNode *left) const { return reinterpret_cast(xor_ptr_ ^ reinterpret_cast(left)); } XorListNode *left(const XorListNode *right) const { return reinterpret_cast(xor_ptr_ ^ reinterpret_cast(right)); } void assign_leftright(const XorListNode *left, const XorListNode *right) { xor_ptr_ = (reinterpret_cast(left) ^ reinterpret_cast(right)); } T val_; private: uintptr_t xor_ptr_; }; template struct FwdXorListIterator { typedef FwdXorListIterator Self; typedef XorListNode Node; typedef ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; typedef T value_type; typedef T *pointer; typedef T &reference; FwdXorListIterator() = delete; FwdXorListIterator(Node *x, Node *prev) : node_(x), left_(prev) {} reference operator*() const { return node_->val_; } pointer operator->() const { return &node_->val_; } Self &operator++() { Node *future_left_ = node_; node_ = node_->right(left_); left_ = future_left_; return *this; } Self operator++(int) { Self __tmp = *this; Node *future_left_ = node_; node_ = node_->right(left_); left_ = future_left_; return __tmp; } Self &operator--() { Node *future_right = node_; node_ = node_->left(node_->right(left_)); left_ = node_->left(future_right); return *this; } Self operator--(int) { Self __tmp = *this; Node *future_right = node_; node_ = node_->left(node_->right(left_)); left_ = node_->left(future_right); return __tmp; } bool operator==(const Self &x) const { return left_ == x.left_; } bool operator!=(const Self &x) const { return left_ != x.left_; } Node *node_; Node *left_; }; template > class XorList { private: typedef typename __gnu_cxx::__alloc_traits::template rebind::other T_alloc_type; typedef __gnu_cxx::__alloc_traits T_alloc_traits; typedef typename T_alloc_traits::template rebind >::other Node_alloc_type; typedef __gnu_cxx::__alloc_traits Node_alloc_traits; public: // types: typedef T value_type; typedef typename T_alloc_traits::pointer pointer; typedef typename T_alloc_traits::const_pointer const_pointer; typedef value_type &reference; typedef const value_type &const_reference; typedef FwdXorListIterator iterator; typedef std::reverse_iterator reverse_iterator; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; //typedef Allocator allocator_type; explicit XorList(const Allocator &alloc = Allocator()) : front_(nullptr), back_(nullptr), size_(0), allocator_(Node_alloc_type(alloc)) {} explicit XorList(size_type count, const_reference value = T(), const Allocator &alloc = Allocator()) : front_(nullptr), back_(nullptr), size_(0), allocator_(Node_alloc_type(alloc)) { for (size_type i = 0; i < count; i++) push_back(value); } XorList &operator=(const XorList &other) { if (this == &other) return *this; clear(); allocator_ = Node_alloc_type(other.allocator_); front_ = back_ = nullptr; size_ = 0; for (const auto& i: other) push_back(i); std::cout << "Copy assignment\n"; return *this; } XorList &operator=(XorList &&other) noexcept { if (this == &other) return *this; clear(); this->front_ = other.front_; this->back_ = other.back_; this->size_ = other.size_; this->allocator_ = std::move(other.allocator_); other.front_ = other.back_ = nullptr; other.size_ = 0; std::cout << "Move assignment\n"; return *this; } ~XorList() { clear(); } template explicit XorList(xorlist_t &&other) noexcept : XorList() { *this = std::forward(other); } value_type front() const { return front_->val_; } value_type back() const { return back_->val_; } iterator begin() const { return iterator(front_, nullptr); } iterator end() const { if (!back_) return iterator(nullptr, nullptr); return ++iterator(back_, back_->left(nullptr)); } reverse_iterator rbegin() const { return reverse_iterator(front_, nullptr); } reverse_iterator rend() const { return ++reverse_iterator(back_, back_->left(nullptr)); } size_type size() const { return size_; } template void push_back(v_type &&val) { insert_after(iterator(back_, back_ ? back_->left(nullptr) : nullptr), std::forward(val)); } template void push_front(v_type &&val) { insert_before(iterator(front_, nullptr), std::forward(val)); } template void insert_before(iterator it, v_type &&val) { _m_insert(it, std::forward(val), BEFORE); } template void insert_after(iterator it, v_type &&val) { _m_insert(it, std::forward(val), AFTER); } void pop_back() { if (!back_) return; erase(iterator(back_, back_->left(nullptr))); } void pop_front() { if (!front_) return; erase(iterator(front_, nullptr)); } void erase(iterator it) { XorListNode *left = it.left_; XorListNode *cur = it.node_; XorListNode *right = it.node_->right(left); if (left) left->assign_leftright(left->left(cur), right); if (right) right->assign_leftright(left, right->right(cur)); if (cur) { size_--; if (front_ == cur) front_ = cur->right(nullptr); if (back_ == cur) back_ = cur->left(nullptr); } allocator_.destroy(cur); allocator_.deallocate(cur, 1); } void clear() { XorListNode *xleft = nullptr; XorListNode *x = front_; while (x != back_) { XorListNode *xnext = x->right(xleft); if (xnext) { allocator_.destroy(xleft); allocator_.deallocate(xleft, 1); } xleft = x; x = xnext; } if (xleft) { allocator_.destroy(xleft); allocator_.deallocate(xleft, 1); } if (x) { allocator_.destroy(x); allocator_.deallocate(x, 1); } size_ = 0; front_ = back_ = nullptr; } private: enum E_POSITION_TYPE { BEFORE, AFTER }; template void _m_insert(iterator it, v_type &&val, E_POSITION_TYPE pos) { XorListNode *cur = it.node_; XorListNode *left = it.left_; XorListNode *new_node = reinterpret_cast *>(allocator_.allocate(1)); Node_alloc_traits::construct(allocator_, new_node, std::forward(val)); new_node->assign_leftright(nullptr, nullptr); if (!front_ || !back_) { front_ = back_ = new_node; size_ = 1; return; } XorListNode *right = it.node_->right(left); if (pos == BEFORE) { new_node->assign_leftright(left, cur); cur->assign_leftright(new_node, right); if (left) left->assign_leftright(left->left(cur), new_node); if (cur == front_) front_ = new_node; } if (pos == AFTER) { new_node->assign_leftright(cur, right); cur->assign_leftright(left, new_node); if (right) right->assign_leftright(new_node, right->right(cur)); if (cur == back_) back_ = new_node; } size_++; } private: XorListNode *front_; XorListNode *back_; // Pointer to the LAST element size_type size_; Node_alloc_type allocator_; }; #endif //XOR_LIST_XORLIST_H