perf improvement for DfLinkedList::end(), erase/insert/insert_after/push_front implementations

develop
Ben Lubar 2018-06-18 13:36:57 -05:00
parent 0b9d46712f
commit 1606483e7e
No known key found for this signature in database
GPG Key ID: 018BAB45DB2D2B24
1 changed files with 134 additions and 155 deletions

@ -241,133 +241,49 @@ namespace DFHack
class iterator; class iterator;
class const_iterator; class const_iterator;
class proxy
{
L *root;
L *prev;
friend class iterator;
proxy(L *root, L *prev) : root(root), prev(prev)
{
CHECK_NULL_POINTER(root);
CHECK_NULL_POINTER(prev);
}
public:
operator I * & ()
{
CHECK_NULL_POINTER(prev->next);
return prev->next->item;
}
operator I *() const
{
CHECK_NULL_POINTER(prev->next);
return prev->next->item;
}
I *operator->() const
{
CHECK_NULL_POINTER(prev->next);
return prev->next->item;
}
proxy & operator=(I *item)
{
if (!prev->next)
{
prev->next = new L();
if (prev != root)
prev->next->prev = prev;
}
prev->next->item = item;
return *this;
}
};
class iterator class iterator
{ {
L *root; L *root;
L *prev; L *cur;
bool next;
friend struct DfLinkedList<L, I>; friend struct DfLinkedList<L, I>;
friend class const_iterator; friend class const_iterator;
void ensure_prev() iterator(L *root, L *cur) : root(root), cur(cur) {}
{
CHECK_NULL_POINTER(root);
if (!prev && !next)
{
for (prev = root; prev->next && prev->next->next; prev = prev->next)
{
next = true;
}
}
}
iterator() : root(nullptr), prev(nullptr), next(false) {}
public: public:
using difference_type = void; using difference_type = void;
using value_type = I *; using value_type = I *;
using pointer = I **; using pointer = I **;
using reference = proxy; using reference = I * &;
using iterator_category = std::output_iterator_tag; using iterator_category = std::bidirectional_iterator_tag;
iterator(L *root, L *prev, bool next = false) : root(root), prev(prev), next(next) {} iterator() : root(nullptr), cur(nullptr) {}
iterator(const iterator & other) : root(other.root), prev(other.prev), next(other.next) {} iterator(const iterator & other) : root(other.root), cur(other.cur) {}
iterator & operator++() iterator & operator++()
{ {
CHECK_NULL_POINTER(root); CHECK_NULL_POINTER(root);
CHECK_NULL_POINTER(cur);
CHECK_NULL_POINTER(prev); cur = cur->next;
CHECK_NULL_POINTER(prev->next);
if (!next && !prev->next->next)
{
next = true;
return *this;
}
CHECK_NULL_POINTER(prev->next->next);
prev = prev->next;
return *this; return *this;
} }
iterator & operator--() iterator & operator--()
{ {
CHECK_NULL_POINTER(root); CHECK_NULL_POINTER(root);
ensure_prev(); if (!cur)
if (next)
{ {
next = false; // find end() - 1
return *this; for (cur = root->next; cur && cur->next; cur = cur->next)
}
CHECK_NULL_POINTER(prev);
if (prev == root)
{
throw DFHack::Error::NullPointer("prev->prev", DFHACK_FUNCTION_SIG);
}
if (root->next == prev)
{
prev = root;
return *this;
}
if (prev->prev)
{
prev = prev->prev;
return *this;
}
for (L *it = root; it->next; it = it->next)
{
if (it->next == prev)
{ {
prev = it;
return *this;
} }
return *this;
} }
throw DFHack::Error::NullPointer("prev->prev", DFHACK_FUNCTION_SIG); CHECK_NULL_POINTER(cur);
CHECK_NULL_POINTER(cur->prev);
cur = cur->prev;
return *this;
} }
iterator operator++(int) iterator operator++(int)
{ {
@ -384,36 +300,24 @@ namespace DFHack
iterator & operator=(const iterator & other) iterator & operator=(const iterator & other)
{ {
root = other.root; root = other.root;
prev = other.prev; cur = other.cur;
next = other.next;
return *this; return *this;
} }
proxy operator*() I * & operator*()
{ {
CHECK_NULL_POINTER(prev); CHECK_NULL_POINTER(root);
CHECK_NULL_POINTER(prev->next); CHECK_NULL_POINTER(cur);
if (next)
return proxy(root, prev->next);
return proxy(root, prev); return cur->item;
} }
const proxy operator*() const I * const & operator*() const
{ {
CHECK_NULL_POINTER(prev); CHECK_NULL_POINTER(root);
CHECK_NULL_POINTER(prev->next); CHECK_NULL_POINTER(cur);
if (next)
return proxy(root, prev->next);
return proxy(root, prev);
}
I * operator->() const return cur->item;
{
return **this;
} }
operator const_iterator() const operator const_iterator() const
@ -422,26 +326,7 @@ namespace DFHack
} }
bool operator==(const iterator & other) const bool operator==(const iterator & other) const
{ {
if (root != other.root) return root == other.root && cur == other.cur;
return false;
if (!next && !prev && !other.next && !other.prev)
return true;
if ((!next && !prev) || (!other.next && !other.prev))
{
iterator this_copy = *this;
this_copy.ensure_prev();
iterator other_copy = other;
other_copy.ensure_prev();
return this_copy == other_copy;
}
if (other.next && !next)
return prev && other.prev && prev->next == other.prev;
if (next && !other.next)
return prev && other.prev && other.prev->next == prev;
return other.prev == prev;
} }
bool operator!=(const iterator & other) const bool operator!=(const iterator & other) const
{ {
@ -454,9 +339,9 @@ namespace DFHack
friend struct DfLinkedList<L, I>; friend struct DfLinkedList<L, I>;
public: public:
using difference_type = void; using difference_type = void;
using value_type = I * ; using value_type = I *;
using pointer = I * const *; using pointer = I * const *;
using reference = const proxy; using reference = I * const &;
using iterator_category = std::bidirectional_iterator_tag; using iterator_category = std::bidirectional_iterator_tag;
const_iterator(const iterator & iter) : iter(iter) {} const_iterator(const iterator & iter) : iter(iter) {}
@ -475,13 +360,13 @@ namespace DFHack
const_iterator operator++(int) const_iterator operator++(int)
{ {
const_iterator copy(*this); const_iterator copy(*this);
++*this; ++iter;
return copy; return copy;
} }
const_iterator operator--(int) const_iterator operator--(int)
{ {
const_iterator copy(*this); const_iterator copy(*this);
--*this; --iter;
return copy; return copy;
} }
const_iterator & operator=(const const_iterator & other) const_iterator & operator=(const const_iterator & other)
@ -489,11 +374,7 @@ namespace DFHack
iter = other.iter; iter = other.iter;
return *this; return *this;
} }
const proxy operator*() const I * const & operator*() const
{
return *iter;
}
I *operator->() const
{ {
return *iter; return *iter;
} }
@ -526,11 +407,11 @@ namespace DFHack
iterator begin() iterator begin()
{ {
return iterator(static_cast<L *>(this), static_cast<L *>(this)); return iterator(static_cast<L *>(this), static_cast<L *>(this)->next);
} }
const_iterator begin() const const_iterator begin() const
{ {
return const_iterator(static_cast<L *>(this), static_cast<L *>(this)); return const_iterator(static_cast<L *>(this), static_cast<L *>(this)->next);
} }
const_iterator cbegin() const const_iterator cbegin() const
{ {
@ -538,15 +419,113 @@ namespace DFHack
} }
iterator end() iterator end()
{ {
return iterator(static_cast<L *>(this), nullptr, false); return iterator(static_cast<L *>(this), nullptr);
} }
const_iterator end() const const_iterator end() const
{ {
return const_iterator(static_cast<L *>(this), nullptr, false); return const_iterator(static_cast<L *>(this), nullptr);
} }
const_iterator cend() const const_iterator cend() const
{ {
return end(); return end();
} }
iterator erase(const_iterator pos)
{
auto root = static_cast<L *>(this);
CHECK_INVALID_ARGUMENT(pos.iter.root == root);
CHECK_NULL_POINTER(pos.iter.cur);
auto link = pos.iter.cur;
auto next = link->next;
if (link->next && link->prev)
{
link->next->prev = link->prev;
link->prev->next = link->next;
}
else if (link->next)
{
link->next->prev = nullptr;
}
else if (link->prev)
{
link->prev->next = nullptr;
}
if (root->next == link)
{
root->next = next;
}
delete link;
return iterator(root, next);
}
iterator insert(const_iterator pos, I * const & item)
{
auto root = static_cast<L *>(this);
CHECK_INVALID_ARGUMENT(pos.iter.root == root);
auto link = pos.iter.cur;
if (!link || !link->prev)
{
if (!link && root->next)
{
pos--;
return insert_after(pos, item);
}
CHECK_INVALID_ARGUMENT(root->next == link);
push_front(item);
return begin();
}
auto newlink = new L();
newlink->prev = link->prev;
newlink->next = link;
link->prev = newlink;
if (newlink->prev)
{
newlink->prev->next = newlink;
}
else if (link == root->next)
{
root->next = newlink;
}
newlink->item = item;
return iterator(root, newlink);
}
iterator insert_after(const_iterator pos, I * const & item)
{
auto root = static_cast<L *>(this);
CHECK_INVALID_ARGUMENT(pos.iter.root == root);
CHECK_NULL_POINTER(pos.iter.cur);
auto link = pos.iter.cur;
auto next = link->next;
auto newlink = new L();
newlink->prev = link;
newlink->next = next;
link->next = newlink;
if (next)
{
next->prev = newlink;
}
newlink->item = item;
return iterator(root, newlink);
}
void push_front(I * const & item)
{
auto root = static_cast<L *>(this);
auto link = new L();
link->prev = nullptr;
if (root->next)
{
root->next->prev = link;
link->next = root->next;
}
link->item = item;
root->next = link;
}
}; };
} }