diff --git a/include/rstl/map.hpp b/include/rstl/map.hpp index c2617d82..1aed7dc1 100644 --- a/include/rstl/map.hpp +++ b/include/rstl/map.hpp @@ -14,12 +14,17 @@ public: typedef pair< K, V > value_type; private: - typedef red_black_tree< K, value_type, 1, select1st< value_type >, Cmp, Alloc > rep_type; + // TODO: some things use a 0, others use a 1 + typedef red_black_tree< K, value_type, 0, select1st< value_type >, Cmp, Alloc > rep_type; public: // typedef typename rep_type::iterator iterator; typedef typename rep_type::const_iterator const_iterator; + void insert(const value_type& item) { + inner.insert(item); + } + private: rep_type inner; }; diff --git a/include/rstl/red_black_tree.hpp b/include/rstl/red_black_tree.hpp index 0ecb2a25..6c3316fb 100644 --- a/include/rstl/red_black_tree.hpp +++ b/include/rstl/red_black_tree.hpp @@ -3,20 +3,31 @@ #include "types.h" +#include "rstl/pair.hpp" #include "rstl/rmemory_allocator.hpp" namespace rstl { template < typename P > -struct select1st {}; +struct select1st { + const P& operator()(const P& it) const { return it; } +}; + +template < typename K, typename V > +struct select1st< pair< K, V > > { + const K& operator()(const pair< K, V >& it) const { return it.first; } +}; template < typename T > -struct less {}; +struct less { + bool operator()(const T& a, const T& b) const { return a < b; } +}; enum node_color { kNC_Red, kNC_Black, }; +void rbtree_rebalance(void*, void*); void* rbtree_traverse_forward(const void*, void*); template < typename T, typename P, int U, typename S = select1st< P >, typename Cmp = less< T >, @@ -24,16 +35,35 @@ template < typename T, typename P, int U, typename S = select1st< P >, typename class red_black_tree { private: struct node { - node_color mColor; - node* mParent; node* mLeft; node* mRight; - P mValue; + node* mParent; + node_color mColor; + uchar mValue[sizeof(P)]; - P& get_value() { return mValue; } + node(const P& value, node_color color = kNC_Red) + : mLeft(nullptr), mRight(nullptr), mColor(color), mParent(nullptr) { + construct(get_value(), value); + } + + P* get_value() { return reinterpret_cast< P* >(&mValue); } + const P* get_value() const { return reinterpret_cast< const P* >(&mValue); } + + node* get_left() { return mLeft; } + void set_left(node* n) { mLeft = n; } + node* get_right() { return mRight; } + void set_right(node* n) { mRight = n; } }; struct header {}; + struct unknown { + node* x0_nodeA; + node** x4_nodeB; + bool x8_; + + unknown(node* a, node** b, bool flag) : x0_nodeA(a), x4_nodeB(b), x8_(flag) {} + }; + public: struct const_iterator { node* mNode; @@ -49,25 +79,85 @@ public: } const_iterator& operator++() { - mNode = static_cast(rbtree_traverse_forward(static_cast(mHeader), static_cast(mNode))); + mNode = static_cast< node* >(rbtree_traverse_forward(static_cast< const void* >(mHeader), + static_cast< void* >(mNode))); return *this; } const_iterator operator++(int) { const_iterator result = *this; - mNode = static_cast(rbtree_traverse_forward(static_cast(mHeader), static_cast(mNode))); + mNode = static_cast< node* >(rbtree_traverse_forward(static_cast< const void* >(mHeader), + static_cast< void* >(mNode))); return result; } }; + unknown insert_into(node* n, const P& item); + unknown insert(const P& item) { return insert_into(x10_rootNode, item); } + private: - uchar x0_; - uchar x1_; - uint x4_; - uint x8_; - uint xc_; - uint x10_; + Alloc x0_allocator; + Cmp x1_cmp; + S x2_selector; + int x4_count; + node* x8_nodeA; + node* xc_nodeB; + node* x10_rootNode; }; + +static bool kUnknownValueNewRoot = true; +static bool kUnknownValueEqualKey = false; +static bool kUnknownValueNewItem = true; + +template < typename T, typename P, int U, typename S, typename Cmp, typename Alloc > +typename red_black_tree< T, P, U, S, Cmp, Alloc >::unknown +red_black_tree< T, P, U, S, Cmp, Alloc >::insert_into(node* n, const P& item) { + if (n == nullptr) { + x0_allocator.allocate(n, 1); + new (n) node(item); + x10_rootNode = n; + x4_count += 1; + x8_nodeA = x10_rootNode; + xc_nodeB = x10_rootNode; + return unknown(x10_rootNode, &x8_nodeA, kUnknownValueNewRoot); + + } else { + node* newNode = nullptr; + while (newNode == nullptr) { + bool firstComp = x1_cmp(x2_selector(*n->get_value()), x2_selector(item)); + if (!firstComp && !x1_cmp(x2_selector(item), x2_selector(*n->get_value()))) { + return unknown(n, &x8_nodeA, kUnknownValueEqualKey); + } + if (firstComp) { + if (n->get_left() == nullptr) { + x0_allocator.allocate(newNode, 1); + new (newNode) node(item, kNC_Black); + n->set_left(newNode); + if (n == x8_nodeA) { + x8_nodeA = newNode; + } + } else { + n = n->get_left(); + } + } else { + if (n->get_right() == nullptr) { + x0_allocator.allocate(newNode, 1); + new (newNode) node(item, kNC_Black); + n->set_right(newNode); + if (n == xc_nodeB) { + xc_nodeB = newNode; + } + } else { + n = n->get_right(); + } + } + } + x4_count += 1; + rbtree_rebalance(&x8_nodeA, newNode); + return unknown(newNode, &x8_nodeA, kUnknownValueNewItem); + } +} + }; // namespace rstl #endif // _RSTL_RED_BLACK_TREE