diff --git a/bazaar/ADT/ADT.cpp b/bazaar/ADT/ADT.cpp new file mode 100644 index 000000000..424680582 --- /dev/null +++ b/bazaar/ADT/ADT.cpp @@ -0,0 +1,60 @@ +// vi: noexpandtab:tabstop=4 + +#include +#include "ADT.h" + +using namespace Upp; + +#if 0 +CONSOLE_APP_MAIN +{ + // SList tests. + { + using ADT::SListNode; + using ADT::SList; + + struct Node : public SListNode { + Node(int i) : i(i) {} + const int i; + }; + + typedef SList List; + Node n0(0), n1(1), n2(2), n3(3), n4(4), n5(5); + List list; + + list.PushFront(&n0).PushFront(&n1).PushFront(&n2).PushFront(&n3).PushFront(&n4); + + for (SList::ForwardRange r = list.ForwardR(); !r.IsEmpty(); r.PopFront()) + r.Front(); + + for (SList::ForwardRange r = list.ForwardR(); !r.IsEmpty(); r.PopFront()) + Cout() << r.Front().i << " "; + Cout() << EOL; + } + + // DList tests. + { + using ADT::DListNode; + using ADT::DList; + + struct Node : public DListNode + { + Node(int i) : i(i) {} + const int i; + }; + + typedef DList List; + Node n0(0), n1(1), n2(2), n3(3), n4(4), n5(5); + List list; + + list << n0 << n1 << n2 << n3 << n4; + ASSERT(list.GetLast() == &n4); + + for (DList::ForwardRange r = list.ForwardR(); !r.IsEmpty(); r.PopFront()) + r.Front(); + + n1.ReplaceThisWith(&n5); + n0.RemoveThis(); + } +} +#endif diff --git a/bazaar/ADT/ADT.h b/bazaar/ADT/ADT.h new file mode 100644 index 000000000..7d075df67 --- /dev/null +++ b/bazaar/ADT/ADT.h @@ -0,0 +1,23 @@ +// vi: noexpandtab:tabstop=4 + +#ifndef _ADT_ADT_h +#define _ADT_ADT_h + +#ifdef flagNONAMESPACE +#define NAMESPACE_ADT +#define END_ADT_NAMESPACE +#define ADT +#else +#define NAMESPACE_ADT namespace adt { +#define END_ADT_NAMESPACE } +#define ADT adt +#endif + +NAMESPACE_ADT + +#include "List.h" + +END_ADT_NAMESPACE + + +#endif diff --git a/bazaar/ADT/ADT.upp b/bazaar/ADT/ADT.upp new file mode 100644 index 000000000..423ff291a --- /dev/null +++ b/bazaar/ADT/ADT.upp @@ -0,0 +1,13 @@ +description "Abstract Data Types\377"; + +uses + Core; + +file + List.h, + ADT.h, + ADT.cpp; + +mainconfig + "" = "SSE2"; + diff --git a/bazaar/ADT/List.h b/bazaar/ADT/List.h new file mode 100644 index 000000000..213b06101 --- /dev/null +++ b/bazaar/ADT/List.h @@ -0,0 +1,254 @@ +// vi: noexpandtab:tabstop=4 + +#ifndef _ADT_List_h +#define _ADT_List_h + +template +struct SListNode { + SListNode() : next(NULL) {} + + T* GetNext() const { return next; } + void SetNext(T* other) { next = other; } + + // Return removed node. + T* RemoveNext() const { + T* n = GetNext(); + SetNext(n->GetNext()); + return n; + } + + void InsertAfterThis(T* first, T* last) { + last->SetNext(next); + SetNext(first); + } + void InsertAfterThis(T* other) { + InsertAfterThis(other, other); + } + +private: + T* next; +}; + +template +struct DListNode { + DListNode() : prev(NULL), next(NULL) {} + + T* GetPrev() const { return prev; } + T* GetNext() const { return next; } + + void SetPrev(T* other) { prev = other; } + void SetNext(T* other) { next = other; } + + void RemoveThis() const { + GetPrev()->SetNext(next); + GetNext()->SetPrev(prev); + } + // Return removed node. + T* RemoveNext() { + T* n = GetNext(); + n->RemoveThis(); + return n; + } + // Return removed node. + T* RemovePrev() { + T* n = GetPrev(); + n->RemoveThis(); + return n; + } + + void ReplaceThisWith(T* first, T* last) const { + GetPrev()->SetNext(first); + GetNext()->SetPrev(last); + + first->SetPrev(prev); + last->SetNext(next); + } + void ReplaceThisWith(T* other) const { + ReplaceThisWith(other, other); + } + + void InsertAfterThis(T* first, T* last) { + first->SetPrev(next->prev); + GetNext()->SetPrev(last); + + // Code below is from SListNode::InsertAfterThis(). + last->SetNext(next); + SetNext(first); + } + void InsertAfterThis(T* other) { + InsertAfterThis(other, other); + } + + void InsertBeforeThis(T* first, T* last) { + last->SetNext(next->prev); + first->SetPrev(prev); + + GetPrev()->SetNext(first); + SetPrev(last); + } + void InsertBeforeThis(T* other) { + InsertBeforeThis(other, other); + } + +private: + T* prev; + T* next; +}; + +// Intrusive single-linked list with sentinel. +// Names PushFront and PopFront are kept for compatibility with DList. +template +struct SList { + typedef SList SelfType; + + SList() { + Clear(); + } + + void Clear() { + sentinel.SetNext((T*)&sentinel); + } + + T* GetFirst() const { return (T*)sentinel.GetNext(); } + T* GetEnd () const { return (T*)&sentinel; } + + bool IsEmpty() const { return sentinel.GetNext() == (const T*)&sentinel; } + bool IsFirst(const T* node) const { return node == sentinel.GetNext(); } + bool IsNull (const T* node) const { return node == (const T*)&sentinel; } + + SelfType& PushFront(T* first, T* last) { + sentinel.InsertAfterThis(first, last); + return *this; + } + + SelfType& PushFront(T* node) { + return PushFront(node, node); + } + + T* PopFront() const { + ASSERT(!IsEmpty()); + return sentinel.RemoveNext(); + } + /// + SelfType& operator <<(T& n) { return PushFront(&n); } + + /// + struct ForwardRange { + typedef T ValueType; + + ForwardRange(const SList& l) : list(&l), n(const_cast(l.GetFirst())) {} + + bool IsEmpty() const { return list->IsNull(n); } + void PopFront() { ASSERT(!IsEmpty()); n = n->GetNext(); } + T& Front() const { return *n; } + + protected: + const SList* list; + T* n; + }; + + ForwardRange ForwardR() const { return ForwardRange(*this); } + +private: + SListNode sentinel; +}; + +// Intrusive double-linked list with sentinel. +template +struct DList { + typedef DList SelfType; + + DList() { + Clear(); + } + + void Clear() { + sentinel.SetNext((T*)&sentinel); + sentinel.SetPrev((T*)&sentinel); + } + + T* GetFirst() const { return (T*)sentinel.GetNext(); } + T* GetLast () const { return (T*)sentinel.GetPrev(); } + T* GetEnd () const { return (T*)&sentinel; } + + bool IsEmpty() const { return sentinel.GetNext() == (const T*)&sentinel; } + bool IsFirst(const T* node) const { return node == sentinel.GetNext(); } + bool IsLast (const T* node) const { return node == sentinel.GetPrev(); } + bool IsNull (const T* node) const { return node == (const T*)&sentinel; } + + SelfType& PushFront(T* first, T* last) { + sentinel.InsertAfterThis(first, last); + return *this; + } + + SelfType& PushBack(T* first, T* last) { + sentinel.InsertBeforeThis(first, last); + return *this; + } + + SelfType& PushFront(T* node) { + return PushFront(node, node); + } + + SelfType& PushBack(T* node) { + return PushBack(node, node); + } + + T* PopFront() const { + return Remove(GetFirst()); + } + + T* PopBack() const { + return Remove(GetLast()); + } + + static T* Remove(T* node) { + node->Remove(); + return node; + } + + SelfType& PushFront(DList& other) { + if (!other.IsEmpty()) + PushFront(other.GetFirst(), other.GetLast()); + return *this; + } + void PickPushFront(DList& other) { + PushFront(other); + other.Clear(); + } + + SelfType& PushBack(DList& other) { + if (!other.IsEmpty()) + PushBack(other.GetFirst(), other.GetLast()); + return *this; + } + void PickPushBack(DList& other) { + PushBack(other); + other.Clear(); + } + + /// + SelfType& operator <<(T& n) { return PushBack(&n); } + + /// + struct ForwardRange { + typedef T ValueType; + + ForwardRange(const DList& l) : list(&l), n(const_cast(l.GetFirst())) {} + + bool IsEmpty() const { return list->IsNull(n); } + void PopFront() { ASSERT(!IsEmpty()); n = n->GetNext(); } + T& Front() const { return *n; } + + protected: + const DList* list; + T* n; + }; + + ForwardRange ForwardR() const { return ForwardRange(*this); } + +private: + DListNode sentinel; +}; + +#endif diff --git a/bazaar/ADT/init b/bazaar/ADT/init new file mode 100644 index 000000000..3ad10f655 --- /dev/null +++ b/bazaar/ADT/init @@ -0,0 +1,4 @@ +#ifndef _ADT_icpp_init_stub +#define _ADT_icpp_init_stub +#include "Core/init" +#endif