From da9debda673cad9b156d7ba414f34f31bfa66ec7 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 29 Aug 2013 11:45:28 -0700 Subject: [PATCH] Sync AMTL. --- public/amtl/am-inlinelist.h | 55 ++++++++++++++++------ public/amtl/am-linkedlist.h | 91 ++++++++++++++++++++++--------------- public/amtl/am-moveable.h | 7 +++ public/amtl/am-string.h | 3 ++ public/amtl/am-vector.h | 34 +++++++++----- 5 files changed, 128 insertions(+), 62 deletions(-) diff --git a/public/amtl/am-inlinelist.h b/public/amtl/am-inlinelist.h index 4e9e1ee7..c0d052ba 100644 --- a/public/amtl/am-inlinelist.h +++ b/public/amtl/am-inlinelist.h @@ -31,11 +31,14 @@ #define _include_amtl_inline_list_h_ #include +#include namespace ke { template class InlineList; +// Objects can recursively inherit from InlineListNode in order to have +// membership in an InlineList. template class InlineListNode { @@ -43,14 +46,14 @@ class InlineListNode public: InlineListNode() - : next_(NULL), - prev_(NULL) + : next_(NULL), + prev_(NULL) { } InlineListNode(InlineListNode *next, InlineListNode *prev) - : next_(next), - prev_(prev) + : next_(next), + prev_(prev) { } @@ -59,6 +62,14 @@ class InlineListNode InlineListNode *prev_; }; +// An InlineList is a linked list that threads link pointers through objects, +// rather than allocating node memory. A node can be in at most one list at +// any time. +// +// Since InlineLists are designed to be very cheap, there is no requirement +// that elements be removed from a list once the list is destructed. However, +// for as long as the list is alive, all of its contained nodes must also +// be alive. template class InlineList { @@ -66,12 +77,26 @@ class InlineList Node head_; + // Work around a clang bug where we can't initialize with &head_ in the ctor. + inline Node *head() { + return &head_; + } + public: InlineList() - : head_(&head_, &head_) + : head_(head(), head()) { } + ~InlineList() + { +#if !defined(NDEBUG) + // Remove all items to clear their next/prev fields. + while (begin() != end()) + remove(*begin()); +#endif + } + public: class iterator { @@ -86,7 +111,7 @@ class InlineList iterator & operator ++() { iter_ = iter_->next; - return *iter_; + return *this; } iterator operator ++(int) { iterator old(*this); @@ -105,14 +130,6 @@ class InlineList bool operator ==(const iterator &where) const { return iter_ == where.iter_; } - iterator prev() const { - iterator p(iter_->prev_); - return p; - } - iterator next() const { - iterator p(iter_->next_); - return p; - } }; iterator begin() { @@ -126,9 +143,17 @@ class InlineList void remove(Node *t) { t->prev_->next_ = t->next_; t->next_->prev_ = t->prev_; + +#if !defined(NDEBUG) + t->next_ = NULL; + t->prev_ = NULL; +#endif } - void insert(Node *t) { + void append(Node *t) { + assert(!t->next_); + assert(!t->prev_); + t->prev_ = head_.prev_; t->next_ = &head_; head_.prev_->next_ = t; diff --git a/public/amtl/am-linkedlist.h b/public/amtl/am-linkedlist.h index 5c06930b..488e97a2 100644 --- a/public/amtl/am-linkedlist.h +++ b/public/amtl/am-linkedlist.h @@ -34,6 +34,7 @@ #include #include #include +#include namespace ke { @@ -58,6 +59,10 @@ class LinkedList : public AllocPolicy : obj(o) { } + Node(Moveable o) + : obj(o) + { + } T obj; Node *next; @@ -68,29 +73,28 @@ public: LinkedList(AllocPolicy = AllocPolicy()) : length_(0) { + head()->prev = head(); + head()->next = head(); } ~LinkedList() { clear(); } bool append(const T &obj) { - Node *node = allocNode(obj); - if (!node) - return false; - - node->prev = head()->prev; - node->next = head(); - head()->prev->next = node; - head()->prev = node; - - length_++; + return insertBefore(end(), obj) != end(); + } + bool append(Moveable obj) { + return insertBefore(end(), obj) != end(); } bool prepend(const T &obj) { - return insert(begin(), obj); + return insertBefore(begin(), obj) != begin(); + } + bool prepend(Moveable obj) { + return insertBefore(begin(), obj) != begin(); } - size_t size() const { + size_t length() const { return length_; } @@ -137,6 +141,13 @@ public: new (node) Node(obj); return node; } + Node *allocNode(Moveable obj) { + Node *node = (Node *)this->malloc(sizeof(Node)); + if (!node) + return NULL; + new (node) Node(obj); + return node; + } void freeNode(Node *node) { node->obj.~T(); @@ -221,29 +232,9 @@ public: Node *this_; }; - public: - iterator begin() const { - return iterator(head()->next); - } - iterator end() const { - return iterator(head()); - } - iterator erase(iterator &where) { - Node *pNode = where.this_; - iterator iter(where); - iter++; - - pNode->prev->next = pNode->next; - pNode->next->prev = pNode->prev; - - freeNode(pNode); - length_--; - - return iter; - } - iterator insert(iterator where, const T &obj) { - // Insert obj right before where - Node *node = allocNode(obj); + private: + // Insert obj right before where. + iterator insert(iterator where, Node *node) { if (!node) return where; @@ -259,6 +250,34 @@ public: } public: + iterator begin() { + return iterator(head()->next); + } + iterator end() { + return iterator(head()); + } + iterator erase(iterator where) { + Node *pNode = where.this_; + iterator iter(where); + iter++; + + pNode->prev->next = pNode->next; + pNode->next->prev = pNode->prev; + + freeNode(pNode); + length_--; + + return iter; + } + iterator insertBefore(iterator where, const T &obj) { + return insert(where, allocNode(obj)); + } + iterator insertBefore(iterator where, Moveable obj) { + return insert(where, allocNode(obj)); + } + + public: + // Removes one instance of |obj| from the list, if found. void remove(const T &obj) { for (iterator b = begin(); b != end(); b++) { if (*b == obj) { @@ -269,7 +288,7 @@ public: } template - iterator find(const U &equ) const { + iterator find(const U &equ) { for (iterator iter = begin(); iter != end(); iter++) { if (*iter == equ) return iter; diff --git a/public/amtl/am-moveable.h b/public/amtl/am-moveable.h index 448fd652..e500dbc7 100644 --- a/public/amtl/am-moveable.h +++ b/public/amtl/am-moveable.h @@ -61,6 +61,13 @@ struct Moveable T &t_; }; +template +static inline Moveable +Move(T &t) +{ + return Moveable(t); +} + } // namespace ke #endif // _include_amtl_moveable_h_ diff --git a/public/amtl/am-string.h b/public/amtl/am-string.h index 7be795f9..665e7bb8 100644 --- a/public/amtl/am-string.h +++ b/public/amtl/am-string.h @@ -81,6 +81,9 @@ class AString return *this; } + int compare(const char *str) const { + return strcmp(chars(), str); + } int compare(const AString &other) const { return strcmp(chars(), other.chars()); } diff --git a/public/amtl/am-vector.h b/public/amtl/am-vector.h index d6b6fc13..937f7a09 100644 --- a/public/amtl/am-vector.h +++ b/public/amtl/am-vector.h @@ -43,24 +43,23 @@ class Vector : public AllocPolicy { public: Vector(AllocPolicy = AllocPolicy()) - : data_(NULL), - nitems_(0), - maxsize_(0) + : data_(NULL), + nitems_(0), + maxsize_(0) { } + Vector(Moveable > other) { + data_ = other->data_; + nitems_ = other->nitems_; + maxsize_ = other->maxsize_; + other->reset(); + } + ~Vector() { zap(); } - void steal(Vector &other) { - zap(); - data_ = other.data_; - nitems_ = other.nitems_; - maxsize_ = other.maxsize_; - other.reset(); - } - bool append(const T &item) { if (!growIfNeeded(1)) return false; @@ -68,11 +67,24 @@ class Vector : public AllocPolicy nitems_++; return true; } + bool append(Moveable item) { + if (!growIfNeeded(1)) + return false; + new (&data_[nitems_]) T(item); + nitems_++; + return true; + } void infallibleAppend(const T &item) { assert(growIfNeeded(1)); new (&data_[nitems_]) T(item); nitems_++; } + void infallibleAppend(Moveable item) { + assert(growIfNeeded(1)); + new (&data_[nitems_]) T(item); + nitems_++; + } + T popCopy() { T t = at(length() - 1); pop();