/* =========================================================================== Copyright (C) 2000 - 2013, Raven Software, Inc. Copyright (C) 2001 - 2013, Activision, Inc. Copyright (C) 2013 - 2015, OpenJK contributors This file is part of the OpenJK source code. OpenJK is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . =========================================================================== */ //////////////////////////////////////////////////////////////////////////////////////// // RAVEN STANDARD TEMPLATE LIBRARY // (c) 2002 Activision // // // Map // --- // This map is based on a red black tree, which guarentees balanced data, no mater what // order elements are added. The map uses a memory pool for storage of node data. // // //////////////////////////////////////////////////////////////////////////////////////// #if !defined(RATL_MAP_VS_INC) #define RATL_MAP_VS_INC //////////////////////////////////////////////////////////////////////////////////////// // Includes //////////////////////////////////////////////////////////////////////////////////////// #if defined(RA_DEBUG_LINKING) #pragma message("...including map_vs.h") #endif #if !defined(RATL_COMMON_INC) #include "ratl_common.h" #endif #if !defined(RATL_POOL_VS_INC) #include "pool_vs.h" #endif namespace ratl { // this is private to the set, but you have no access to it, soooo.. class tree_node { int mParent; int mLeft; int mRight; public: enum { RED_BIT = 0x40000000, // to save space we are putting the red bool in a high bit // this is in the parent only NULL_NODE = 0x3fffffff, // this must not have the red bit set }; void init() { mLeft = NULL_NODE; mRight = NULL_NODE; mParent = NULL_NODE | RED_BIT; } int left() const { return mLeft; } int right() const { return mRight; } int parent() const { return mParent & (~RED_BIT); } bool red() const { return !!(mParent & RED_BIT); } void set_left(int l) { mLeft = l; } void set_right(int r) { mRight = r; } void set_parent(int p) { mParent &= RED_BIT; mParent |= p; } void set_red(bool isRed) { if (isRed) { mParent |= RED_BIT; } else { mParent &= ~RED_BIT; } } }; //fixme void *, comparison function pointer-ize this for code bloat. template class tree_base { public: typedef T TStorageTraits; typedef typename T::TValue TTValue; //////////////////////////////////////////////////////////////////////////////////// // Capacity Enum //////////////////////////////////////////////////////////////////////////////////// static const int CAPACITY = T::CAPACITY; private: pool_base mPool; // The Allocation Data Pool int mRoot; int mLastAdd; void link_left(int node,int left) { T::node(mPool[node]).set_left(left); if (left!=tree_node::NULL_NODE) { T::node(mPool[left]).set_parent(node); } } void link_right(int node,int right) { T::node(mPool[node]).set_right(right); if (right!=tree_node::NULL_NODE) { T::node(mPool[right]).set_parent(node); } } //////////////////////////////////////////////////////////////////////////////////// // This is the map internal recursive find function - do not use externally //////////////////////////////////////////////////////////////////////////////////// int find_internal(const TTValue &key, int at) const { // FAIL TO FIND? //--------------- if (at==tree_node::NULL_NODE) { return tree_node::NULL_NODE; } // Should We Search Left? //------------------------ if (key CAST_TO *verify_alloc_key(CAST_TO *p) const { return mPool.verify_alloc(p); } void insert_alloced_key() { assert(mLastAdd>=0&&mLastAdd=0&&mLastAdd=0&&i=0&&i class set_base : public tree_base { public: typedef T TStorageTraits; typedef typename T::TValue TTValue; //////////////////////////////////////////////////////////////////////////////////// // Capacity Enum //////////////////////////////////////////////////////////////////////////////////// static const int CAPACITY = T::CAPACITY; //////////////////////////////////////////////////////////////////////////////////// // Adds Element Value At Location Key - O(log n) //////////////////////////////////////////////////////////////////////////////////// void insert(const TTValue &key) { assert(!IS_MULTI || find_index(key)==tree_node::NULL_NODE); //fixme handle duplicates more sensibly? alloc_key(key); tree_base::insert_alloced_key(); } //////////////////////////////////////////////////////////////////////////////////// // Allocs an item, when filled, call insert_alloced //////////////////////////////////////////////////////////////////////////////////// TTValue & alloc() { return tree_base::alloc_key(); } //////////////////////////////////////////////////////////////////////////////////// // Allocs an item (raw), when constucted, call insert_alloced //////////////////////////////////////////////////////////////////////////////////// TRatlNew *alloc_raw() { return tree_base::alloc_key_raw(); } template CAST_TO *verify_alloc(CAST_TO *p) const { return verify_alloc_key(p); } void insert_alloced() { tree_base::insert_alloced_key(); } //////////////////////////////////////////////////////////////////////////////////// // Removes The First Element With Key (key) - O(log n) //////////////////////////////////////////////////////////////////////////////////// void erase(const TTValue &key) { //fixme this is a double search currently int i=find_index(key); if (i!=tree_node::NULL_NODE) { tree_base::erase_index(i); } } //////////////////////////////////////////////////////////////////////////////////// // Iterator // // A map is sorted in ascending order on the KEY type. ++ and -- are both // O((log n)^2) operations // //////////////////////////////////////////////////////////////////////////////////// class iterator { friend class set_base; friend class const_iterator; int mLoc; set_base* mOwner; public: iterator(set_base *owner=0, int loc=tree_node::NULL_NODE) : mOwner(owner), mLoc(loc) { } iterator(const iterator &o) : mOwner(o.mOwner), mLoc(o.mLoc) { } void operator=(const iterator &o) { mOwner=o.mOwner; mLoc=o.mLoc; } iterator operator++() //prefix { assert(mOwner); mLoc=mOwner->next(mLoc); return *this; } iterator operator++(int) //postfix { assert(mOwner); iterator old(*this); mLoc=mOwner->next(mLoc); return old; } iterator operator--() //prefix { assert(mOwner); mLoc=mOwner->previous(mLoc); return *this; } iterator operator--(int) //postfix { assert(mOwner); iterator old(*this); mLoc=mOwner->previous(mLoc); return old; } bool operator!=(const iterator p) const {return (mLoc!=p.mLoc || mOwner!=p.mOwner);} bool operator==(const iterator p) const {return (mLoc==p.mLoc && mOwner==p.mOwner);} const TTValue & operator*() const { assert(mOwner); assert(mLoc>=0&&mLocindex_to_key(mLoc); } const TTValue * operator->() const { assert(mOwner); assert(mLoc>=0&&mLocindex_to_key(mLoc); } }; class const_iterator { friend class set_base; int mLoc; const set_base* mOwner; public: const_iterator(const set_base *owner=0, int loc=tree_node::NULL_NODE) : mOwner(owner), mLoc(loc) { } const_iterator(const const_iterator &o) : mOwner(o.mOwner), mLoc(o.mLoc) { } const_iterator(const iterator &o) : mOwner(o.mOwner), mLoc(o.mLoc) { } void operator=(const const_iterator &o) { mOwner=o.mOwner; mLoc=o.mLoc; } void operator=(const iterator &o) { mOwner=o.mOwner; mLoc=o.mLoc; } const_iterator operator++() //prefix { assert(mOwner); mLoc=mOwner->next(mLoc); return *this; } const_iterator operator++(int) //postfix { assert(mOwner); const_iterator old(*this); mLoc=mOwner->next(mLoc); return old; } const_iterator operator--() //prefix { assert(mOwner); mLoc=mOwner->previous(mLoc); return *this; } const_iterator operator--(int) //postfix { assert(mOwner); const_iterator old(*this); mLoc=mOwner->previous(mLoc); return old; } bool operator!=(const const_iterator p) const {return (mLoc!=p.mLoc || mOwner!=p.mOwner);} bool operator==(const const_iterator p) const {return (mLoc==p.mLoc && mOwner==p.mOwner);} bool operator!=(const iterator p) const {return (mLoc!=p.mLoc || mOwner!=p.mOwner);} bool operator==(const iterator p) const {return (mLoc==p.mLoc && mOwner==p.mOwner);} const TTValue & operator*() const { assert(mOwner); assert(mLoc>=0&&mLocindex_to_key(mLoc); } const TTValue * operator->() const { assert(mOwner); assert(mLoc>=0&&mLocindex_to_key(mLoc); } }; friend class iterator; friend class const_iterator; //////////////////////////////////////////////////////////////////////////////////// // Seach For A Given Key. Will Return end() if Failed - O(log n) //////////////////////////////////////////////////////////////////////////////////// iterator find(const TTValue &key) { return iterator(this,find_index(key)); } //////////////////////////////////////////////////////////////////////////////////// // Get An Iterator To The Smallest Element - O(log n) //////////////////////////////////////////////////////////////////////////////////// iterator begin() { return iterator(this, tree_base::front()); } //////////////////////////////////////////////////////////////////////////////////// // Get An Iterator To The Largest Element - O(log n) //////////////////////////////////////////////////////////////////////////////////// iterator rbegin() { return iterator(this, tree_base::back()); } //////////////////////////////////////////////////////////////////////////////////// // The Invalid Iterator, Use As A Stop Condition In Your For Loops - O(1) //////////////////////////////////////////////////////////////////////////////////// iterator end() { return iterator(this); } //////////////////////////////////////////////////////////////////////////////////// // Seach For A Given Key. Will Return end() if Failed - O(log n) //////////////////////////////////////////////////////////////////////////////////// const_iterator find(const TTValue &key) const { return const_iterator(this, find_index(key)); } //////////////////////////////////////////////////////////////////////////////////// // Get An const_iterator To The Smallest Element - O(log n) //////////////////////////////////////////////////////////////////////////////////// const_iterator begin() const { return const_iterator(this, tree_base::front()); } //////////////////////////////////////////////////////////////////////////////////// // Get An const_iterator To The Largest Element - O(log n) //////////////////////////////////////////////////////////////////////////////////// const_iterator rbegin() const { return const_iterator(this, tree_base::back()); } //////////////////////////////////////////////////////////////////////////////////// // The Invalid const_iterator, Use As A Stop Condition In Your For Loops - O(1) //////////////////////////////////////////////////////////////////////////////////// const_iterator end() const { return const_iterator(this); } //////////////////////////////////////////////////////////////////////////////////// // Removes The Element Pointed To At (it) And Decrements (it) - O((log n)^2) //////////////////////////////////////////////////////////////////////////////////// void erase(const iterator &it) { assert(it.mOwner==this && it.mLoc>=0&&it.mLoc class set_vs : public set_base,0 > { public: typedef typename storage::value_semantics_node TStorageTraits; typedef typename TStorageTraits::TValue TTValue; static const int CAPACITY = ARG_CAPACITY; set_vs() {} }; template class set_os : public set_base,0 > { public: typedef typename storage::object_semantics_node TStorageTraits; typedef typename TStorageTraits::TValue TTValue; static const int CAPACITY = ARG_CAPACITY; set_os() {} }; template class set_is : public set_base,0 > { public: typedef typename storage::virtual_semantics_node TStorageTraits; typedef typename TStorageTraits::TValue TTValue; static const int CAPACITY = ARG_CAPACITY; static const int MAX_CLASS_SIZE = ARG_MAX_CLASS_SIZE; set_is() {} }; template class map_base : public tree_base { public: typedef K TKeyStorageTraits; typedef typename K::TValue TKTValue; typedef V TValueStorageTraits; typedef typename V::TValue TVTValue; //////////////////////////////////////////////////////////////////////////////////// // Capacity Enum //////////////////////////////////////////////////////////////////////////////////// static const int CAPACITY = K::CAPACITY; private: array_base mValues; public: map_base() { compile_assert(); } void clear() { tree_base::clear(); mValues.clear(); } //////////////////////////////////////////////////////////////////////////////////// // Adds Element Value At Location Key - O(log n) //////////////////////////////////////////////////////////////////////////////////// void insert(const TKTValue &key,const TVTValue &value) { assert(!IS_MULTI || (tree_base::find_index(key)==tree_node::NULL_NODE)); //fixme handle duplicates more sensibly? tree_base::alloc_key(key); tree_base::insert_alloced_key(); assert(check_validity()); mValues.construct(tree_base::index_of_alloced_key(),value); } //////////////////////////////////////////////////////////////////////////////////// // Adds Element Value At Location Key returns a reference //////////////////////////////////////////////////////////////////////////////////// TVTValue &insert(const TKTValue &key) { assert(!IS_MULTI || (tree_base::find_index(key)==tree_node::NULL_NODE)); //fixme handle duplicates more sensibly? tree_base::alloc_key(key); tree_base::insert_alloced_key(); int idx=tree_base::index_of_alloced_key(); assert(check_validity()); mValues.construct(idx); return mValues[idx]; } //////////////////////////////////////////////////////////////////////////////////// // Adds Element Value At Location Key returns a rew pointer for placement new //////////////////////////////////////////////////////////////////////////////////// TRatlNew *insert_raw(const TKTValue &key) { assert(!IS_MULTI || (tree_base::find_index(key)==tree_node::NULL_NODE)); //fixme handle duplicates more sensibly? tree_base::alloc_key(key); tree_base::insert_alloced_key(); assert(check_validity()); return mValues.alloc_raw(tree_base::index_of_alloced_key()); } //////////////////////////////////////////////////////////////////////////////////// // After calling alloc_key*, you may call this to alloc the value //////////////////////////////////////////////////////////////////////////////////// TVTValue &alloc_value() { mValues.construct(tree_base::index_of_alloced_key()); return mValues[tree_base::index_of_alloced_key()]; } //////////////////////////////////////////////////////////////////////////////////// // After calling alloc_key*, you may call this to alloc_raw the value //////////////////////////////////////////////////////////////////////////////////// TRatlNew *alloc_value_raw() { return mValues.alloc_raw(tree_base::index_of_alloced_key()); } template CAST_TO *verify_alloc(CAST_TO *p) const { return mValues.verify_alloc(p); } //////////////////////////////////////////////////////////////////////////////////// // Removes The First Element With Key (key) - O(log n) //////////////////////////////////////////////////////////////////////////////////// void erase(const TKTValue &key) { //fixme this is a double search currently int i=tree_base::find_index(key); if (i!=tree_node::NULL_NODE) { tree_base::erase_index(i); mValues.destruct(i); } } //////////////////////////////////////////////////////////////////////////////////// // Iterator // // A map is sorted in ascending order on the KEY type. ++ and -- are both // O((log n)^2) operations // //////////////////////////////////////////////////////////////////////////////////// class const_iterator; class iterator { friend class map_base; friend class const_iterator; int mLoc; map_base* mOwner; public: iterator(map_base *owner=0, int loc=tree_node::NULL_NODE) : mLoc(loc), mOwner(owner) { } iterator(const iterator &o) : mLoc(o.mLoc), mOwner(o.mOwner) { } void operator=(const iterator &o) { mOwner=o.mOwner; mLoc=o.mLoc; } iterator operator++() //prefix { assert(mOwner); mLoc=mOwner->next(mLoc); return *this; } iterator operator++(int) //postfix { assert(mOwner); iterator old(*this); mLoc=mOwner->next(mLoc); return old; } iterator operator--() //prefix { assert(mOwner); mLoc=mOwner->previous(mLoc); return *this; } iterator operator--(int) //postfix { assert(mOwner); iterator old(*this); mLoc=mOwner->previous(mLoc); return old; } bool operator!=(const iterator &p) const {return (mLoc!=p.mLoc || mOwner!=p.mOwner);} bool operator==(const iterator &p) const {return (mLoc==p.mLoc && mOwner==p.mOwner);} TVTValue & operator*() const { assert(mOwner); assert(mLoc>=0&&mLocmValues[mLoc]; } const TKTValue & key() const { assert(mOwner); assert(mLoc>=0&&mLocindex_to_key(mLoc); } TVTValue & value() const { assert(mOwner); assert(mLoc>=0&&mLocmValues[mLoc]; } TVTValue * operator->() const { assert(mOwner); assert(mLoc>=0&&mLocmValues[mLoc]; } }; class const_iterator { friend class map_base; int mLoc; const map_base* mOwner; public: const_iterator(const map_base *owner=0, int loc=tree_node::NULL_NODE) : mOwner(owner), mLoc(loc) { } const_iterator(const const_iterator &o) : mOwner(o.mOwner), mLoc(o.mLoc) { } const_iterator(const iterator &o) : mOwner(o.mOwner), mLoc(o.mLoc) { } void operator=(const const_iterator &o) { mOwner=o.mOwner; mLoc=o.mLoc; } void operator=(const iterator &o) { mOwner=o.mOwner; mLoc=o.mLoc; } const_iterator operator++() //prefix { assert(mOwner); mLoc=mOwner->next(mLoc); return *this; } const_iterator operator++(int) //postfix { assert(mOwner); const_iterator old(*this); mLoc=mOwner->next(mLoc); return old; } const_iterator operator--() //prefix { assert(mOwner); mLoc=mOwner->previous(mLoc); return *this; } const_iterator operator--(int) //postfix { assert(mOwner); const_iterator old(*this); mLoc=mOwner->previous(mLoc); return old; } bool operator!=(const const_iterator &p) const {return (mLoc!=p.mLoc || mOwner!=p.mOwner);} bool operator==(const const_iterator &p) const {return (mLoc==p.mLoc && mOwner==p.mOwner);} bool operator!=(const iterator &p) const {return (mLoc!=p.mLoc || mOwner!=p.mOwner);} bool operator==(const iterator &p) const {return (mLoc==p.mLoc && mOwner==p.mOwner);} const TVTValue & operator*() const { assert(mOwner); assert(mLoc>=0&&mLocmValues[mLoc]; } const TKTValue & key() const { assert(mOwner); assert(mLoc>=0&&mLocindex_to_key(mLoc); } const TVTValue & value() const { assert(mOwner); assert(mLoc>=0&&mLocmValues[mLoc]; } const TVTValue * operator->() const { assert(mOwner); assert(mLoc>=0&&mLocmValues[mLoc]; } }; friend class iterator; friend class const_iterator; //////////////////////////////////////////////////////////////////////////////////// // Seach For A Given Key. Will Return end() if Failed - O(log n) //////////////////////////////////////////////////////////////////////////////////// iterator find(const TKTValue &key) { return iterator(this,tree_base::find_index(key)); } //////////////////////////////////////////////////////////////////////////////////// // Get An Iterator To The Smallest Element - O(log n) //////////////////////////////////////////////////////////////////////////////////// iterator begin() { return iterator(this, tree_base::front()); } //////////////////////////////////////////////////////////////////////////////////// // Get An Iterator To The Largest Element - O(log n) //////////////////////////////////////////////////////////////////////////////////// iterator rbegin() { return iterator(this, tree_base::back()); } //////////////////////////////////////////////////////////////////////////////////// // The Invalid Iterator, Use As A Stop Condition In Your For Loops - O(1) //////////////////////////////////////////////////////////////////////////////////// iterator end() { return iterator(this); } //////////////////////////////////////////////////////////////////////////////////// // Seach For A Given Key. Will Return end() if Failed - O(log n) //////////////////////////////////////////////////////////////////////////////////// const_iterator find(const TKTValue &key) const { return const_iterator(this, find_index(key)); } //////////////////////////////////////////////////////////////////////////////////// // Get An const_iterator To The Smallest Element - O(log n) //////////////////////////////////////////////////////////////////////////////////// const_iterator begin() const { return const_iterator(this, tree_base::front()); } //////////////////////////////////////////////////////////////////////////////////// // Get An const_iterator To The Largest Element - O(log n) //////////////////////////////////////////////////////////////////////////////////// const_iterator rbegin() const { return const_iterator(this, tree_base::back()); } //////////////////////////////////////////////////////////////////////////////////// // The Invalid const_iterator, Use As A Stop Condition In Your For Loops - O(1) //////////////////////////////////////////////////////////////////////////////////// const_iterator end() const { return const_iterator(this); } //////////////////////////////////////////////////////////////////////////////////// // Removes The Element Pointed To At (it) And Decrements (it) - O((log n)^2) //////////////////////////////////////////////////////////////////////////////////// void erase(const iterator &it) { assert(it.mOwner==this && it.mLoc>=0&&it.mLoc class map_vs : public map_base< storage::value_semantics_node, storage::value_semantics, 0 > { public: typedef typename storage::value_semantics VStorageTraits; typedef typename VStorageTraits::TValue TTValue; static const int CAPACITY = ARG_CAPACITY; map_vs() {} }; template class map_os : public map_base< storage::value_semantics_node, storage::object_semantics, 0 > { public: typedef typename storage::object_semantics VStorageTraits; typedef typename VStorageTraits::TValue TTValue; static const int CAPACITY = ARG_CAPACITY; map_os() {} }; template class map_is : public map_base< storage::value_semantics_node, storage::virtual_semantics, 0 > { public: typedef typename storage::virtual_semantics VStorageTraits; typedef typename VStorageTraits::TValue TTValue; static const int CAPACITY = ARG_CAPACITY; static const int MAX_CLASS_SIZE = ARG_MAX_CLASS_SIZE; map_is() {} }; } #endif