/*
===========================================================================
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