hello world

This commit is contained in:
Timothee 'TTimo' Besset
2011-11-22 15:28:15 -06:00
commit fb1609f554
2155 changed files with 1017022 additions and 0 deletions

View File

@@ -0,0 +1,520 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __BTREE_H__
#define __BTREE_H__
/*
===============================================================================
Balanced Search Tree
===============================================================================
*/
//#define BTREE_CHECK
template< class objType, class keyType >
class idBTreeNode {
public:
keyType key; // key used for sorting
objType * object; // if != NULL pointer to object stored in leaf node
idBTreeNode * parent; // parent node
idBTreeNode * next; // next sibling
idBTreeNode * prev; // prev sibling
int numChildren; // number of children
idBTreeNode * firstChild; // first child
idBTreeNode * lastChild; // last child
};
template< class objType, class keyType, int maxChildrenPerNode >
class idBTree {
public:
idBTree( void );
~idBTree( void );
void Init( void );
void Shutdown( void );
idBTreeNode<objType,keyType> * Add( objType *object, keyType key ); // add an object to the tree
void Remove( idBTreeNode<objType,keyType> *node ); // remove an object node from the tree
objType * Find( keyType key ) const; // find an object using the given key
objType * FindSmallestLargerEqual( keyType key ) const; // find an object with the smallest key larger equal the given key
objType * FindLargestSmallerEqual( keyType key ) const; // find an object with the largest key smaller equal the given key
idBTreeNode<objType,keyType> * GetRoot( void ) const; // returns the root node of the tree
int GetNodeCount( void ) const; // returns the total number of nodes in the tree
idBTreeNode<objType,keyType> * GetNext( idBTreeNode<objType,keyType> *node ) const; // goes through all nodes of the tree
idBTreeNode<objType,keyType> * GetNextLeaf( idBTreeNode<objType,keyType> *node ) const; // goes through all leaf nodes of the tree
private:
idBTreeNode<objType,keyType> * root;
idBlockAlloc<idBTreeNode<objType,keyType>,128> nodeAllocator;
idBTreeNode<objType,keyType> * AllocNode( void );
void FreeNode( idBTreeNode<objType,keyType> *node );
void SplitNode( idBTreeNode<objType,keyType> *node );
idBTreeNode<objType,keyType> * MergeNodes( idBTreeNode<objType,keyType> *node1, idBTreeNode<objType,keyType> *node2 );
void CheckTree_r( idBTreeNode<objType,keyType> *node, int &numNodes ) const;
void CheckTree( void ) const;
};
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE idBTree<objType,keyType,maxChildrenPerNode>::idBTree( void ) {
assert( maxChildrenPerNode >= 4 );
root = NULL;
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE idBTree<objType,keyType,maxChildrenPerNode>::~idBTree( void ) {
Shutdown();
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE void idBTree<objType,keyType,maxChildrenPerNode>::Init( void ) {
root = AllocNode();
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE void idBTree<objType,keyType,maxChildrenPerNode>::Shutdown( void ) {
nodeAllocator.Shutdown();
root = NULL;
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE idBTreeNode<objType,keyType> *idBTree<objType,keyType,maxChildrenPerNode>::Add( objType *object, keyType key ) {
idBTreeNode<objType,keyType> *node, *child, *newNode;
if ( root->numChildren >= maxChildrenPerNode ) {
newNode = AllocNode();
newNode->key = root->key;
newNode->firstChild = root;
newNode->lastChild = root;
newNode->numChildren = 1;
root->parent = newNode;
SplitNode( root );
root = newNode;
}
newNode = AllocNode();
newNode->key = key;
newNode->object = object;
for ( node = root; node->firstChild != NULL; node = child ) {
if ( key > node->key ) {
node->key = key;
}
// find the first child with a key larger equal to the key of the new node
for( child = node->firstChild; child->next; child = child->next ) {
if ( key <= child->key ) {
break;
}
}
if ( child->object ) {
if ( key <= child->key ) {
// insert new node before child
if ( child->prev ) {
child->prev->next = newNode;
} else {
node->firstChild = newNode;
}
newNode->prev = child->prev;
newNode->next = child;
child->prev = newNode;
} else {
// insert new node after child
if ( child->next ) {
child->next->prev = newNode;
} else {
node->lastChild = newNode;
}
newNode->prev = child;
newNode->next = child->next;
child->next = newNode;
}
newNode->parent = node;
node->numChildren++;
#ifdef BTREE_CHECK
CheckTree();
#endif
return newNode;
}
// make sure the child has room to store another node
if ( child->numChildren >= maxChildrenPerNode ) {
SplitNode( child );
if ( key <= child->prev->key ) {
child = child->prev;
}
}
}
// we only end up here if the root node is empty
newNode->parent = root;
root->key = key;
root->firstChild = newNode;
root->lastChild = newNode;
root->numChildren++;
#ifdef BTREE_CHECK
CheckTree();
#endif
return newNode;
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE void idBTree<objType,keyType,maxChildrenPerNode>::Remove( idBTreeNode<objType,keyType> *node ) {
idBTreeNode<objType,keyType> *parent;
assert( node->object != NULL );
// unlink the node from it's parent
if ( node->prev ) {
node->prev->next = node->next;
} else {
node->parent->firstChild = node->next;
}
if ( node->next ) {
node->next->prev = node->prev;
} else {
node->parent->lastChild = node->prev;
}
node->parent->numChildren--;
// make sure there are no parent nodes with a single child
for ( parent = node->parent; parent != root && parent->numChildren <= 1; parent = parent->parent ) {
if ( parent->next ) {
parent = MergeNodes( parent, parent->next );
} else if ( parent->prev ) {
parent = MergeNodes( parent->prev, parent );
}
// a parent may not use a key higher than the key of it's last child
if ( parent->key > parent->lastChild->key ) {
parent->key = parent->lastChild->key;
}
if ( parent->numChildren > maxChildrenPerNode ) {
SplitNode( parent );
break;
}
}
for ( ; parent != NULL && parent->lastChild != NULL; parent = parent->parent ) {
// a parent may not use a key higher than the key of it's last child
if ( parent->key > parent->lastChild->key ) {
parent->key = parent->lastChild->key;
}
}
// free the node
FreeNode( node );
// remove the root node if it has a single internal node as child
if ( root->numChildren == 1 && root->firstChild->object == NULL ) {
idBTreeNode<objType,keyType> *oldRoot = root;
root->firstChild->parent = NULL;
root = root->firstChild;
FreeNode( oldRoot );
}
#ifdef BTREE_CHECK
CheckTree();
#endif
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE objType *idBTree<objType,keyType,maxChildrenPerNode>::Find( keyType key ) const {
idBTreeNode<objType,keyType> *node;
for ( node = root->firstChild; node != NULL; node = node->firstChild ) {
while( node->next ) {
if ( node->key >= key ) {
break;
}
node = node->next;
}
if ( node->object ) {
if ( node->key == key ) {
return node->object;
} else {
return NULL;
}
}
}
return NULL;
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE objType *idBTree<objType,keyType,maxChildrenPerNode>::FindSmallestLargerEqual( keyType key ) const {
idBTreeNode<objType,keyType> *node;
for ( node = root->firstChild; node != NULL; node = node->firstChild ) {
while( node->next ) {
if ( node->key >= key ) {
break;
}
node = node->next;
}
if ( node->object ) {
if ( node->key >= key ) {
return node->object;
} else {
return NULL;
}
}
}
return NULL;
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE objType *idBTree<objType,keyType,maxChildrenPerNode>::FindLargestSmallerEqual( keyType key ) const {
idBTreeNode<objType,keyType> *node;
for ( node = root->lastChild; node != NULL; node = node->lastChild ) {
while( node->prev ) {
if ( node->key <= key ) {
break;
}
node = node->prev;
}
if ( node->object ) {
if ( node->key <= key ) {
return node->object;
} else {
return NULL;
}
}
}
return NULL;
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE idBTreeNode<objType,keyType> *idBTree<objType,keyType,maxChildrenPerNode>::GetRoot( void ) const {
return root;
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE int idBTree<objType,keyType,maxChildrenPerNode>::GetNodeCount( void ) const {
return nodeAllocator.GetAllocCount();
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE idBTreeNode<objType,keyType> *idBTree<objType,keyType,maxChildrenPerNode>::GetNext( idBTreeNode<objType,keyType> *node ) const {
if ( node->firstChild ) {
return node->firstChild;
} else {
while( node && node->next == NULL ) {
node = node->parent;
}
return node;
}
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE idBTreeNode<objType,keyType> *idBTree<objType,keyType,maxChildrenPerNode>::GetNextLeaf( idBTreeNode<objType,keyType> *node ) const {
if ( node->firstChild ) {
while ( node->firstChild ) {
node = node->firstChild;
}
return node;
} else {
while( node && node->next == NULL ) {
node = node->parent;
}
if ( node ) {
node = node->next;
while ( node->firstChild ) {
node = node->firstChild;
}
return node;
} else {
return NULL;
}
}
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE idBTreeNode<objType,keyType> *idBTree<objType,keyType,maxChildrenPerNode>::AllocNode( void ) {
idBTreeNode<objType,keyType> *node = nodeAllocator.Alloc();
node->key = 0;
node->parent = NULL;
node->next = NULL;
node->prev = NULL;
node->numChildren = 0;
node->firstChild = NULL;
node->lastChild = NULL;
node->object = NULL;
return node;
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE void idBTree<objType,keyType,maxChildrenPerNode>::FreeNode( idBTreeNode<objType,keyType> *node ) {
nodeAllocator.Free( node );
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE void idBTree<objType,keyType,maxChildrenPerNode>::SplitNode( idBTreeNode<objType,keyType> *node ) {
int i;
idBTreeNode<objType,keyType> *child, *newNode;
// allocate a new node
newNode = AllocNode();
newNode->parent = node->parent;
// divide the children over the two nodes
child = node->firstChild;
child->parent = newNode;
for ( i = 3; i < node->numChildren; i += 2 ) {
child = child->next;
child->parent = newNode;
}
newNode->key = child->key;
newNode->numChildren = node->numChildren / 2;
newNode->firstChild = node->firstChild;
newNode->lastChild = child;
node->numChildren -= newNode->numChildren;
node->firstChild = child->next;
child->next->prev = NULL;
child->next = NULL;
// add the new child to the parent before the split node
assert( node->parent->numChildren < maxChildrenPerNode );
if ( node->prev ) {
node->prev->next = newNode;
} else {
node->parent->firstChild = newNode;
}
newNode->prev = node->prev;
newNode->next = node;
node->prev = newNode;
node->parent->numChildren++;
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE idBTreeNode<objType,keyType> *idBTree<objType,keyType,maxChildrenPerNode>::MergeNodes( idBTreeNode<objType,keyType> *node1, idBTreeNode<objType,keyType> *node2 ) {
idBTreeNode<objType,keyType> *child;
assert( node1->parent == node2->parent );
assert( node1->next == node2 && node2->prev == node1 );
assert( node1->object == NULL && node2->object == NULL );
assert( node1->numChildren >= 1 && node2->numChildren >= 1 );
for ( child = node1->firstChild; child->next; child = child->next ) {
child->parent = node2;
}
child->parent = node2;
child->next = node2->firstChild;
node2->firstChild->prev = child;
node2->firstChild = node1->firstChild;
node2->numChildren += node1->numChildren;
// unlink the first node from the parent
if ( node1->prev ) {
node1->prev->next = node2;
} else {
node1->parent->firstChild = node2;
}
node2->prev = node1->prev;
node2->parent->numChildren--;
FreeNode( node1 );
return node2;
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE void idBTree<objType,keyType,maxChildrenPerNode>::CheckTree_r( idBTreeNode<objType,keyType> *node, int &numNodes ) const {
int numChildren;
idBTreeNode<objType,keyType> *child;
numNodes++;
// the root node may have zero children and leaf nodes always have zero children, all other nodes should have at least 2 and at most maxChildrenPerNode children
assert( ( node == root ) || ( node->object != NULL && node->numChildren == 0 ) || ( node->numChildren >= 2 && node->numChildren <= maxChildrenPerNode ) );
// the key of a node may never be larger than the key of it's last child
assert( ( node->lastChild == NULL ) || ( node->key <= node->lastChild->key ) );
numChildren = 0;
for ( child = node->firstChild; child; child = child->next ) {
numChildren++;
// make sure the children are properly linked
if ( child->prev == NULL ) {
assert( node->firstChild == child );
} else {
assert( child->prev->next == child );
}
if ( child->next == NULL ) {
assert( node->lastChild == child );
} else {
assert( child->next->prev == child );
}
// recurse down the tree
CheckTree_r( child, numNodes );
}
// the number of children should equal the number of linked children
assert( numChildren == node->numChildren );
}
template< class objType, class keyType, int maxChildrenPerNode >
ID_INLINE void idBTree<objType,keyType,maxChildrenPerNode>::CheckTree( void ) const {
int numNodes = 0;
idBTreeNode<objType,keyType> *node, *lastNode;
CheckTree_r( root, numNodes );
// the number of nodes in the tree should equal the number of allocated nodes
assert( numNodes == nodeAllocator.GetAllocCount() );
// all the leaf nodes should be ordered
lastNode = GetNextLeaf( GetRoot() );
if ( lastNode ) {
for ( node = GetNextLeaf( lastNode ); node; lastNode = node, node = GetNextLeaf( node ) ) {
assert( lastNode->key <= node->key );
}
}
}
#endif /* !__BTREE_H__ */

View File

@@ -0,0 +1,138 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __BINSEARCH_H__
#define __BINSEARCH_H__
/*
===============================================================================
Binary Search templates
The array elements have to be ordered in increasing order.
===============================================================================
*/
/*
====================
idBinSearch_GreaterEqual
Finds the last array element which is smaller than the given value.
====================
*/
template< class type >
ID_INLINE int idBinSearch_Less( const type *array, const int arraySize, const type &value ) {
int len = arraySize;
int mid = len;
int offset = 0;
while( mid > 0 ) {
mid = len >> 1;
if ( array[offset+mid] < value ) {
offset += mid;
}
len -= mid;
}
return offset;
}
/*
====================
idBinSearch_GreaterEqual
Finds the last array element which is smaller than or equal to the given value.
====================
*/
template< class type >
ID_INLINE int idBinSearch_LessEqual( const type *array, const int arraySize, const type &value ) {
int len = arraySize;
int mid = len;
int offset = 0;
while( mid > 0 ) {
mid = len >> 1;
if ( array[offset+mid] <= value ) {
offset += mid;
}
len -= mid;
}
return offset;
}
/*
====================
idBinSearch_Greater
Finds the first array element which is greater than the given value.
====================
*/
template< class type >
ID_INLINE int idBinSearch_Greater( const type *array, const int arraySize, const type &value ) {
int len = arraySize;
int mid = len;
int offset = 0;
int res = 0;
while( mid > 0 ) {
mid = len >> 1;
if ( array[offset+mid] > value ) {
res = 0;
} else {
offset += mid;
res = 1;
}
len -= mid;
}
return offset+res;
}
/*
====================
idBinSearch_GreaterEqual
Finds the first array element which is greater than or equal to the given value.
====================
*/
template< class type >
ID_INLINE int idBinSearch_GreaterEqual( const type *array, const int arraySize, const type &value ) {
int len = arraySize;
int mid = len;
int offset = 0;
int res = 0;
while( mid > 0 ) {
mid = len >> 1;
if ( array[offset+mid] >= value ) {
res = 0;
} else {
offset += mid;
res = 1;
}
len -= mid;
}
return offset+res;
}
#endif /* !__BINSEARCH_H__ */

View File

@@ -0,0 +1,155 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../precompiled.h"
#pragma hdrstop
int idHashIndex::INVALID_INDEX[1] = { -1 };
/*
================
idHashIndex::Init
================
*/
void idHashIndex::Init( const int initialHashSize, const int initialIndexSize ) {
assert( idMath::IsPowerOfTwo( initialHashSize ) );
hashSize = initialHashSize;
hash = INVALID_INDEX;
indexSize = initialIndexSize;
indexChain = INVALID_INDEX;
granularity = DEFAULT_HASH_GRANULARITY;
hashMask = hashSize - 1;
lookupMask = 0;
}
/*
================
idHashIndex::Allocate
================
*/
void idHashIndex::Allocate( const int newHashSize, const int newIndexSize ) {
assert( idMath::IsPowerOfTwo( newHashSize ) );
Free();
hashSize = newHashSize;
hash = new int[hashSize];
memset( hash, 0xff, hashSize * sizeof( hash[0] ) );
indexSize = newIndexSize;
indexChain = new int[indexSize];
memset( indexChain, 0xff, indexSize * sizeof( indexChain[0] ) );
hashMask = hashSize - 1;
lookupMask = -1;
}
/*
================
idHashIndex::Free
================
*/
void idHashIndex::Free( void ) {
if ( hash != INVALID_INDEX ) {
delete[] hash;
hash = INVALID_INDEX;
}
if ( indexChain != INVALID_INDEX ) {
delete[] indexChain;
indexChain = INVALID_INDEX;
}
lookupMask = 0;
}
/*
================
idHashIndex::ResizeIndex
================
*/
void idHashIndex::ResizeIndex( const int newIndexSize ) {
int *oldIndexChain, mod, newSize;
if ( newIndexSize <= indexSize ) {
return;
}
mod = newIndexSize % granularity;
if ( !mod ) {
newSize = newIndexSize;
} else {
newSize = newIndexSize + granularity - mod;
}
if ( indexChain == INVALID_INDEX ) {
indexSize = newSize;
return;
}
oldIndexChain = indexChain;
indexChain = new int[newSize];
memcpy( indexChain, oldIndexChain, indexSize * sizeof(int) );
memset( indexChain + indexSize, 0xff, (newSize - indexSize) * sizeof(int) );
delete[] oldIndexChain;
indexSize = newSize;
}
/*
================
idHashIndex::GetSpread
================
*/
int idHashIndex::GetSpread( void ) const {
int i, index, totalItems, *numHashItems, average, error, e;
if ( hash == INVALID_INDEX ) {
return 100;
}
totalItems = 0;
numHashItems = new int[hashSize];
for ( i = 0; i < hashSize; i++ ) {
numHashItems[i] = 0;
for ( index = hash[i]; index >= 0; index = indexChain[index] ) {
numHashItems[i]++;
}
totalItems += numHashItems[i];
}
// if no items in hash
if ( totalItems <= 1 ) {
delete[] numHashItems;
return 100;
}
average = totalItems / hashSize;
error = 0;
for ( i = 0; i < hashSize; i++ ) {
e = abs( numHashItems[i] - average );
if ( e > 1 ) {
error += e - 1;
}
}
delete[] numHashItems;
return 100 - (error * 100 / totalItems);
}

View File

@@ -0,0 +1,405 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __HASHINDEX_H__
#define __HASHINDEX_H__
/*
===============================================================================
Fast hash table for indexes and arrays.
Does not allocate memory until the first key/index pair is added.
===============================================================================
*/
#define DEFAULT_HASH_SIZE 1024
#define DEFAULT_HASH_GRANULARITY 1024
class idHashIndex {
public:
idHashIndex( void );
idHashIndex( const int initialHashSize, const int initialIndexSize );
~idHashIndex( void );
// returns total size of allocated memory
size_t Allocated( void ) const;
// returns total size of allocated memory including size of hash index type
size_t Size( void ) const;
idHashIndex & operator=( const idHashIndex &other );
// add an index to the hash, assumes the index has not yet been added to the hash
void Add( const int key, const int index );
// remove an index from the hash
void Remove( const int key, const int index );
// get the first index from the hash, returns -1 if empty hash entry
int First( const int key ) const;
// get the next index from the hash, returns -1 if at the end of the hash chain
int Next( const int index ) const;
// insert an entry into the index and add it to the hash, increasing all indexes >= index
void InsertIndex( const int key, const int index );
// remove an entry from the index and remove it from the hash, decreasing all indexes >= index
void RemoveIndex( const int key, const int index );
// clear the hash
void Clear( void );
// clear and resize
void Clear( const int newHashSize, const int newIndexSize );
// free allocated memory
void Free( void );
// get size of hash table
int GetHashSize( void ) const;
// get size of the index
int GetIndexSize( void ) const;
// set granularity
void SetGranularity( const int newGranularity );
// force resizing the index, current hash table stays intact
void ResizeIndex( const int newIndexSize );
// returns number in the range [0-100] representing the spread over the hash table
int GetSpread( void ) const;
// returns a key for a string
int GenerateKey( const char *string, bool caseSensitive = true ) const;
// returns a key for a vector
int GenerateKey( const idVec3 &v ) const;
// returns a key for two integers
int GenerateKey( const int n1, const int n2 ) const;
private:
int hashSize;
int * hash;
int indexSize;
int * indexChain;
int granularity;
int hashMask;
int lookupMask;
static int INVALID_INDEX[1];
void Init( const int initialHashSize, const int initialIndexSize );
void Allocate( const int newHashSize, const int newIndexSize );
};
/*
================
idHashIndex::idHashIndex
================
*/
ID_INLINE idHashIndex::idHashIndex( void ) {
Init( DEFAULT_HASH_SIZE, DEFAULT_HASH_SIZE );
}
/*
================
idHashIndex::idHashIndex
================
*/
ID_INLINE idHashIndex::idHashIndex( const int initialHashSize, const int initialIndexSize ) {
Init( initialHashSize, initialIndexSize );
}
/*
================
idHashIndex::~idHashIndex
================
*/
ID_INLINE idHashIndex::~idHashIndex( void ) {
Free();
}
/*
================
idHashIndex::Allocated
================
*/
ID_INLINE size_t idHashIndex::Allocated( void ) const {
return hashSize * sizeof( int ) + indexSize * sizeof( int );
}
/*
================
idHashIndex::Size
================
*/
ID_INLINE size_t idHashIndex::Size( void ) const {
return sizeof( *this ) + Allocated();
}
/*
================
idHashIndex::operator=
================
*/
ID_INLINE idHashIndex &idHashIndex::operator=( const idHashIndex &other ) {
granularity = other.granularity;
hashMask = other.hashMask;
lookupMask = other.lookupMask;
if ( other.lookupMask == 0 ) {
hashSize = other.hashSize;
indexSize = other.indexSize;
Free();
}
else {
if ( other.hashSize != hashSize || hash == INVALID_INDEX ) {
if ( hash != INVALID_INDEX ) {
delete[] hash;
}
hashSize = other.hashSize;
hash = new int[hashSize];
}
if ( other.indexSize != indexSize || indexChain == INVALID_INDEX ) {
if ( indexChain != INVALID_INDEX ) {
delete[] indexChain;
}
indexSize = other.indexSize;
indexChain = new int[indexSize];
}
memcpy( hash, other.hash, hashSize * sizeof( hash[0] ) );
memcpy( indexChain, other.indexChain, indexSize * sizeof( indexChain[0] ) );
}
return *this;
}
/*
================
idHashIndex::Add
================
*/
ID_INLINE void idHashIndex::Add( const int key, const int index ) {
int h;
assert( index >= 0 );
if ( hash == INVALID_INDEX ) {
Allocate( hashSize, index >= indexSize ? index + 1 : indexSize );
}
else if ( index >= indexSize ) {
ResizeIndex( index + 1 );
}
h = key & hashMask;
indexChain[index] = hash[h];
hash[h] = index;
}
/*
================
idHashIndex::Remove
================
*/
ID_INLINE void idHashIndex::Remove( const int key, const int index ) {
int k = key & hashMask;
if ( hash == INVALID_INDEX ) {
return;
}
if ( hash[k] == index ) {
hash[k] = indexChain[index];
}
else {
for ( int i = hash[k]; i != -1; i = indexChain[i] ) {
if ( indexChain[i] == index ) {
indexChain[i] = indexChain[index];
break;
}
}
}
indexChain[index] = -1;
}
/*
================
idHashIndex::First
================
*/
ID_INLINE int idHashIndex::First( const int key ) const {
return hash[key & hashMask & lookupMask];
}
/*
================
idHashIndex::Next
================
*/
ID_INLINE int idHashIndex::Next( const int index ) const {
assert( index >= 0 && index < indexSize );
return indexChain[index & lookupMask];
}
/*
================
idHashIndex::InsertIndex
================
*/
ID_INLINE void idHashIndex::InsertIndex( const int key, const int index ) {
int i, max;
if ( hash != INVALID_INDEX ) {
max = index;
for ( i = 0; i < hashSize; i++ ) {
if ( hash[i] >= index ) {
hash[i]++;
if ( hash[i] > max ) {
max = hash[i];
}
}
}
for ( i = 0; i < indexSize; i++ ) {
if ( indexChain[i] >= index ) {
indexChain[i]++;
if ( indexChain[i] > max ) {
max = indexChain[i];
}
}
}
if ( max >= indexSize ) {
ResizeIndex( max + 1 );
}
for ( i = max; i > index; i-- ) {
indexChain[i] = indexChain[i-1];
}
indexChain[index] = -1;
}
Add( key, index );
}
/*
================
idHashIndex::RemoveIndex
================
*/
ID_INLINE void idHashIndex::RemoveIndex( const int key, const int index ) {
int i, max;
Remove( key, index );
if ( hash != INVALID_INDEX ) {
max = index;
for ( i = 0; i < hashSize; i++ ) {
if ( hash[i] >= index ) {
if ( hash[i] > max ) {
max = hash[i];
}
hash[i]--;
}
}
for ( i = 0; i < indexSize; i++ ) {
if ( indexChain[i] >= index ) {
if ( indexChain[i] > max ) {
max = indexChain[i];
}
indexChain[i]--;
}
}
for ( i = index; i < max; i++ ) {
indexChain[i] = indexChain[i+1];
}
indexChain[max] = -1;
}
}
/*
================
idHashIndex::Clear
================
*/
ID_INLINE void idHashIndex::Clear( void ) {
// only clear the hash table because clearing the indexChain is not really needed
if ( hash != INVALID_INDEX ) {
memset( hash, 0xff, hashSize * sizeof( hash[0] ) );
}
}
/*
================
idHashIndex::Clear
================
*/
ID_INLINE void idHashIndex::Clear( const int newHashSize, const int newIndexSize ) {
Free();
hashSize = newHashSize;
indexSize = newIndexSize;
}
/*
================
idHashIndex::GetHashSize
================
*/
ID_INLINE int idHashIndex::GetHashSize( void ) const {
return hashSize;
}
/*
================
idHashIndex::GetIndexSize
================
*/
ID_INLINE int idHashIndex::GetIndexSize( void ) const {
return indexSize;
}
/*
================
idHashIndex::SetGranularity
================
*/
ID_INLINE void idHashIndex::SetGranularity( const int newGranularity ) {
assert( newGranularity > 0 );
granularity = newGranularity;
}
/*
================
idHashIndex::GenerateKey
================
*/
ID_INLINE int idHashIndex::GenerateKey( const char *string, bool caseSensitive ) const {
if ( caseSensitive ) {
return ( idStr::Hash( string ) & hashMask );
} else {
return ( idStr::IHash( string ) & hashMask );
}
}
/*
================
idHashIndex::GenerateKey
================
*/
ID_INLINE int idHashIndex::GenerateKey( const idVec3 &v ) const {
return ( (((int) v[0]) + ((int) v[1]) + ((int) v[2])) & hashMask );
}
/*
================
idHashIndex::GenerateKey
================
*/
ID_INLINE int idHashIndex::GenerateKey( const int n1, const int n2 ) const {
return ( ( n1 + n2 ) & hashMask );
}
#endif /* !__HASHINDEX_H__ */

View File

@@ -0,0 +1,404 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __HASHTABLE_H__
#define __HASHTABLE_H__
/*
===============================================================================
General hash table. Slower than idHashIndex but it can also be used for
linked lists and other data structures than just indexes or arrays.
===============================================================================
*/
template< class Type >
class idHashTable {
public:
idHashTable( int newtablesize = 256 );
idHashTable( const idHashTable<Type> &map );
~idHashTable( void );
// returns total size of allocated memory
size_t Allocated( void ) const;
// returns total size of allocated memory including size of hash table type
size_t Size( void ) const;
void Set( const char *key, Type &value );
bool Get( const char *key, Type **value = NULL ) const;
bool Remove( const char *key );
void Clear( void );
void DeleteContents( void );
// the entire contents can be itterated over, but note that the
// exact index for a given element may change when new elements are added
int Num( void ) const;
Type * GetIndex( int index ) const;
int GetSpread( void ) const;
private:
struct hashnode_s {
idStr key;
Type value;
hashnode_s *next;
hashnode_s( const idStr &k, Type v, hashnode_s *n ) : key( k ), value( v ), next( n ) {};
hashnode_s( const char *k, Type v, hashnode_s *n ) : key( k ), value( v ), next( n ) {};
};
hashnode_s ** heads;
int tablesize;
int numentries;
int tablesizemask;
int GetHash( const char *key ) const;
};
/*
================
idHashTable<Type>::idHashTable
================
*/
template< class Type >
ID_INLINE idHashTable<Type>::idHashTable( int newtablesize ) {
assert( idMath::IsPowerOfTwo( newtablesize ) );
tablesize = newtablesize;
assert( tablesize > 0 );
heads = new hashnode_s *[ tablesize ];
memset( heads, 0, sizeof( *heads ) * tablesize );
numentries = 0;
tablesizemask = tablesize - 1;
}
/*
================
idHashTable<Type>::idHashTable
================
*/
template< class Type >
ID_INLINE idHashTable<Type>::idHashTable( const idHashTable<Type> &map ) {
int i;
hashnode_s *node;
hashnode_s **prev;
assert( map.tablesize > 0 );
tablesize = map.tablesize;
heads = new hashnode_s *[ tablesize ];
numentries = map.numentries;
tablesizemask = map.tablesizemask;
for( i = 0; i < tablesize; i++ ) {
if ( !map.heads[ i ] ) {
heads[ i ] = NULL;
continue;
}
prev = &heads[ i ];
for( node = map.heads[ i ]; node != NULL; node = node->next ) {
*prev = new hashnode_s( node->key, node->value, NULL );
prev = &( *prev )->next;
}
}
}
/*
================
idHashTable<Type>::~idHashTable<Type>
================
*/
template< class Type >
ID_INLINE idHashTable<Type>::~idHashTable( void ) {
Clear();
delete[] heads;
}
/*
================
idHashTable<Type>::Allocated
================
*/
template< class Type >
ID_INLINE size_t idHashTable<Type>::Allocated( void ) const {
return sizeof( heads ) * tablesize + sizeof( *heads ) * numentries;
}
/*
================
idHashTable<Type>::Size
================
*/
template< class Type >
ID_INLINE size_t idHashTable<Type>::Size( void ) const {
return sizeof( idHashTable<Type> ) + sizeof( heads ) * tablesize + sizeof( *heads ) * numentries;
}
/*
================
idHashTable<Type>::GetHash
================
*/
template< class Type >
ID_INLINE int idHashTable<Type>::GetHash( const char *key ) const {
return ( idStr::Hash( key ) & tablesizemask );
}
/*
================
idHashTable<Type>::Set
================
*/
template< class Type >
ID_INLINE void idHashTable<Type>::Set( const char *key, Type &value ) {
hashnode_s *node, **nextPtr;
int hash, s;
hash = GetHash( key );
for( nextPtr = &(heads[hash]), node = *nextPtr; node != NULL; nextPtr = &(node->next), node = *nextPtr ) {
s = node->key.Cmp( key );
if ( s == 0 ) {
node->value = value;
return;
}
if ( s > 0 ) {
break;
}
}
numentries++;
*nextPtr = new hashnode_s( key, value, heads[ hash ] );
(*nextPtr)->next = node;
}
/*
================
idHashTable<Type>::Get
================
*/
template< class Type >
ID_INLINE bool idHashTable<Type>::Get( const char *key, Type **value ) const {
hashnode_s *node;
int hash, s;
hash = GetHash( key );
for( node = heads[ hash ]; node != NULL; node = node->next ) {
s = node->key.Cmp( key );
if ( s == 0 ) {
if ( value ) {
*value = &node->value;
}
return true;
}
if ( s > 0 ) {
break;
}
}
if ( value ) {
*value = NULL;
}
return false;
}
/*
================
idHashTable<Type>::GetIndex
the entire contents can be itterated over, but note that the
exact index for a given element may change when new elements are added
================
*/
template< class Type >
ID_INLINE Type *idHashTable<Type>::GetIndex( int index ) const {
hashnode_s *node;
int count;
int i;
if ( ( index < 0 ) || ( index > numentries ) ) {
assert( 0 );
return NULL;
}
count = 0;
for( i = 0; i < tablesize; i++ ) {
for( node = heads[ i ]; node != NULL; node = node->next ) {
if ( count == index ) {
return &node->value;
}
count++;
}
}
return NULL;
}
/*
================
idHashTable<Type>::Remove
================
*/
template< class Type >
ID_INLINE bool idHashTable<Type>::Remove( const char *key ) {
hashnode_s **head;
hashnode_s *node;
hashnode_s *prev;
int hash;
hash = GetHash( key );
head = &heads[ hash ];
if ( *head ) {
for( prev = NULL, node = *head; node != NULL; prev = node, node = node->next ) {
if ( node->key == key ) {
if ( prev ) {
prev->next = node->next;
} else {
*head = node->next;
}
delete node;
numentries--;
return true;
}
}
}
return false;
}
/*
================
idHashTable<Type>::Clear
================
*/
template< class Type >
ID_INLINE void idHashTable<Type>::Clear( void ) {
int i;
hashnode_s *node;
hashnode_s *next;
for( i = 0; i < tablesize; i++ ) {
next = heads[ i ];
while( next != NULL ) {
node = next;
next = next->next;
delete node;
}
heads[ i ] = NULL;
}
numentries = 0;
}
/*
================
idHashTable<Type>::DeleteContents
================
*/
template< class Type >
ID_INLINE void idHashTable<Type>::DeleteContents( void ) {
int i;
hashnode_s *node;
hashnode_s *next;
for( i = 0; i < tablesize; i++ ) {
next = heads[ i ];
while( next != NULL ) {
node = next;
next = next->next;
delete node->value;
delete node;
}
heads[ i ] = NULL;
}
numentries = 0;
}
/*
================
idHashTable<Type>::Num
================
*/
template< class Type >
ID_INLINE int idHashTable<Type>::Num( void ) const {
return numentries;
}
#if defined(ID_TYPEINFO)
#define __GNUC__ 99
#endif
#if !defined(__GNUC__) || __GNUC__ < 4
/*
================
idHashTable<Type>::GetSpread
================
*/
template< class Type >
int idHashTable<Type>::GetSpread( void ) const {
int i, average, error, e;
hashnode_s *node;
// if no items in hash
if ( !numentries ) {
return 100;
}
average = numentries / tablesize;
error = 0;
for ( i = 0; i < tablesize; i++ ) {
numItems = 0;
for( node = heads[ i ]; node != NULL; node = node->next ) {
numItems++;
}
e = abs( numItems - average );
if ( e > 1 ) {
error += e - 1;
}
}
return 100 - (error * 100 / numentries);
}
#endif
#if defined(ID_TYPEINFO)
#undef __GNUC__
#endif
#endif /* !__HASHTABLE_H__ */

View File

@@ -0,0 +1,362 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __HIERARCHY_H__
#define __HIERARCHY_H__
/*
==============================================================================
idHierarchy
==============================================================================
*/
template< class type >
class idHierarchy {
public:
idHierarchy();
~idHierarchy();
void SetOwner( type *object );
type * Owner( void ) const;
void ParentTo( idHierarchy &node );
void MakeSiblingAfter( idHierarchy &node );
bool ParentedBy( const idHierarchy &node ) const;
void RemoveFromParent( void );
void RemoveFromHierarchy( void );
type * GetParent( void ) const; // parent of this node
type * GetChild( void ) const; // first child of this node
type * GetSibling( void ) const; // next node with the same parent
type * GetPriorSibling( void ) const; // previous node with the same parent
type * GetNext( void ) const; // goes through all nodes of the hierarchy
type * GetNextLeaf( void ) const; // goes through all leaf nodes of the hierarchy
private:
idHierarchy * parent;
idHierarchy * sibling;
idHierarchy * child;
type * owner;
idHierarchy<type> *GetPriorSiblingNode( void ) const; // previous node with the same parent
};
/*
================
idHierarchy<type>::idHierarchy
================
*/
template< class type >
idHierarchy<type>::idHierarchy() {
owner = NULL;
parent = NULL;
sibling = NULL;
child = NULL;
}
/*
================
idHierarchy<type>::~idHierarchy
================
*/
template< class type >
idHierarchy<type>::~idHierarchy() {
RemoveFromHierarchy();
}
/*
================
idHierarchy<type>::Owner
Gets the object that is associated with this node.
================
*/
template< class type >
type *idHierarchy<type>::Owner( void ) const {
return owner;
}
/*
================
idHierarchy<type>::SetOwner
Sets the object that this node is associated with.
================
*/
template< class type >
void idHierarchy<type>::SetOwner( type *object ) {
owner = object;
}
/*
================
idHierarchy<type>::ParentedBy
================
*/
template< class type >
bool idHierarchy<type>::ParentedBy( const idHierarchy &node ) const {
if ( parent == &node ) {
return true;
} else if ( parent ) {
return parent->ParentedBy( node );
}
return false;
}
/*
================
idHierarchy<type>::ParentTo
Makes the given node the parent.
================
*/
template< class type >
void idHierarchy<type>::ParentTo( idHierarchy &node ) {
RemoveFromParent();
parent = &node;
sibling = node.child;
node.child = this;
}
/*
================
idHierarchy<type>::MakeSiblingAfter
Makes the given node a sibling after the passed in node.
================
*/
template< class type >
void idHierarchy<type>::MakeSiblingAfter( idHierarchy &node ) {
RemoveFromParent();
parent = node.parent;
sibling = node.sibling;
node.sibling = this;
}
/*
================
idHierarchy<type>::RemoveFromParent
================
*/
template< class type >
void idHierarchy<type>::RemoveFromParent( void ) {
idHierarchy<type> *prev;
if ( parent ) {
prev = GetPriorSiblingNode();
if ( prev ) {
prev->sibling = sibling;
} else {
parent->child = sibling;
}
}
parent = NULL;
sibling = NULL;
}
/*
================
idHierarchy<type>::RemoveFromHierarchy
Removes the node from the hierarchy and adds it's children to the parent.
================
*/
template< class type >
void idHierarchy<type>::RemoveFromHierarchy( void ) {
idHierarchy<type> *parentNode;
idHierarchy<type> *node;
parentNode = parent;
RemoveFromParent();
if ( parentNode ) {
while( child ) {
node = child;
node->RemoveFromParent();
node->ParentTo( *parentNode );
}
} else {
while( child ) {
child->RemoveFromParent();
}
}
}
/*
================
idHierarchy<type>::GetParent
================
*/
template< class type >
type *idHierarchy<type>::GetParent( void ) const {
if ( parent ) {
return parent->owner;
}
return NULL;
}
/*
================
idHierarchy<type>::GetChild
================
*/
template< class type >
type *idHierarchy<type>::GetChild( void ) const {
if ( child ) {
return child->owner;
}
return NULL;
}
/*
================
idHierarchy<type>::GetSibling
================
*/
template< class type >
type *idHierarchy<type>::GetSibling( void ) const {
if ( sibling ) {
return sibling->owner;
}
return NULL;
}
/*
================
idHierarchy<type>::GetPriorSiblingNode
Returns NULL if no parent, or if it is the first child.
================
*/
template< class type >
idHierarchy<type> *idHierarchy<type>::GetPriorSiblingNode( void ) const {
if ( !parent || ( parent->child == this ) ) {
return NULL;
}
idHierarchy<type> *prev;
idHierarchy<type> *node;
node = parent->child;
prev = NULL;
while( ( node != this ) && ( node != NULL ) ) {
prev = node;
node = node->sibling;
}
if ( node != this ) {
idLib::Error( "idHierarchy::GetPriorSibling: could not find node in parent's list of children" );
}
return prev;
}
/*
================
idHierarchy<type>::GetPriorSibling
Returns NULL if no parent, or if it is the first child.
================
*/
template< class type >
type *idHierarchy<type>::GetPriorSibling( void ) const {
idHierarchy<type> *prior;
prior = GetPriorSiblingNode();
if ( prior ) {
return prior->owner;
}
return NULL;
}
/*
================
idHierarchy<type>::GetNext
Goes through all nodes of the hierarchy.
================
*/
template< class type >
type *idHierarchy<type>::GetNext( void ) const {
const idHierarchy<type> *node;
if ( child ) {
return child->owner;
} else {
node = this;
while( node && node->sibling == NULL ) {
node = node->parent;
}
if ( node ) {
return node->sibling->owner;
} else {
return NULL;
}
}
}
/*
================
idHierarchy<type>::GetNextLeaf
Goes through all leaf nodes of the hierarchy.
================
*/
template< class type >
type *idHierarchy<type>::GetNextLeaf( void ) const {
const idHierarchy<type> *node;
if ( child ) {
node = child;
while ( node->child ) {
node = node->child;
}
return node->owner;
} else {
node = this;
while( node && node->sibling == NULL ) {
node = node->parent;
}
if ( node ) {
node = node->sibling;
while ( node->child ) {
node = node->child;
}
return node->owner;
} else {
return NULL;
}
}
}
#endif /* !__HIERARCHY_H__ */

View File

@@ -0,0 +1,343 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
/*
==============================================================================
idLinkList
Circular linked list template
==============================================================================
*/
template< class type >
class idLinkList {
public:
idLinkList();
~idLinkList();
bool IsListEmpty( void ) const;
bool InList( void ) const;
int Num( void ) const;
void Clear( void );
void InsertBefore( idLinkList &node );
void InsertAfter( idLinkList &node );
void AddToEnd( idLinkList &node );
void AddToFront( idLinkList &node );
void Remove( void );
type * Next( void ) const;
type * Prev( void ) const;
type * Owner( void ) const;
void SetOwner( type *object );
idLinkList * ListHead( void ) const;
idLinkList * NextNode( void ) const;
idLinkList * PrevNode( void ) const;
private:
idLinkList * head;
idLinkList * next;
idLinkList * prev;
type * owner;
};
/*
================
idLinkList<type>::idLinkList
Node is initialized to be the head of an empty list
================
*/
template< class type >
idLinkList<type>::idLinkList() {
owner = NULL;
head = this;
next = this;
prev = this;
}
/*
================
idLinkList<type>::~idLinkList
Removes the node from the list, or if it's the head of a list, removes
all the nodes from the list.
================
*/
template< class type >
idLinkList<type>::~idLinkList() {
Clear();
}
/*
================
idLinkList<type>::IsListEmpty
Returns true if the list is empty.
================
*/
template< class type >
bool idLinkList<type>::IsListEmpty( void ) const {
return head->next == head;
}
/*
================
idLinkList<type>::InList
Returns true if the node is in a list. If called on the head of a list, will always return false.
================
*/
template< class type >
bool idLinkList<type>::InList( void ) const {
return head != this;
}
/*
================
idLinkList<type>::Num
Returns the number of nodes in the list.
================
*/
template< class type >
int idLinkList<type>::Num( void ) const {
idLinkList<type> *node;
int num;
num = 0;
for( node = head->next; node != head; node = node->next ) {
num++;
}
return num;
}
/*
================
idLinkList<type>::Clear
If node is the head of the list, clears the list. Otherwise it just removes the node from the list.
================
*/
template< class type >
void idLinkList<type>::Clear( void ) {
if ( head == this ) {
while( next != this ) {
next->Remove();
}
} else {
Remove();
}
}
/*
================
idLinkList<type>::Remove
Removes node from list
================
*/
template< class type >
void idLinkList<type>::Remove( void ) {
prev->next = next;
next->prev = prev;
next = this;
prev = this;
head = this;
}
/*
================
idLinkList<type>::InsertBefore
Places the node before the existing node in the list. If the existing node is the head,
then the new node is placed at the end of the list.
================
*/
template< class type >
void idLinkList<type>::InsertBefore( idLinkList &node ) {
Remove();
next = &node;
prev = node.prev;
node.prev = this;
prev->next = this;
head = node.head;
}
/*
================
idLinkList<type>::InsertAfter
Places the node after the existing node in the list. If the existing node is the head,
then the new node is placed at the beginning of the list.
================
*/
template< class type >
void idLinkList<type>::InsertAfter( idLinkList &node ) {
Remove();
prev = &node;
next = node.next;
node.next = this;
next->prev = this;
head = node.head;
}
/*
================
idLinkList<type>::AddToEnd
Adds node at the end of the list
================
*/
template< class type >
void idLinkList<type>::AddToEnd( idLinkList &node ) {
InsertBefore( *node.head );
}
/*
================
idLinkList<type>::AddToFront
Adds node at the beginning of the list
================
*/
template< class type >
void idLinkList<type>::AddToFront( idLinkList &node ) {
InsertAfter( *node.head );
}
/*
================
idLinkList<type>::ListHead
Returns the head of the list. If the node isn't in a list, it returns
a pointer to itself.
================
*/
template< class type >
idLinkList<type> *idLinkList<type>::ListHead( void ) const {
return head;
}
/*
================
idLinkList<type>::Next
Returns the next object in the list, or NULL if at the end.
================
*/
template< class type >
type *idLinkList<type>::Next( void ) const {
if ( !next || ( next == head ) ) {
return NULL;
}
return next->owner;
}
/*
================
idLinkList<type>::Prev
Returns the previous object in the list, or NULL if at the beginning.
================
*/
template< class type >
type *idLinkList<type>::Prev( void ) const {
if ( !prev || ( prev == head ) ) {
return NULL;
}
return prev->owner;
}
/*
================
idLinkList<type>::NextNode
Returns the next node in the list, or NULL if at the end.
================
*/
template< class type >
idLinkList<type> *idLinkList<type>::NextNode( void ) const {
if ( next == head ) {
return NULL;
}
return next;
}
/*
================
idLinkList<type>::PrevNode
Returns the previous node in the list, or NULL if at the beginning.
================
*/
template< class type >
idLinkList<type> *idLinkList<type>::PrevNode( void ) const {
if ( prev == head ) {
return NULL;
}
return prev;
}
/*
================
idLinkList<type>::Owner
Gets the object that is associated with this node.
================
*/
template< class type >
type *idLinkList<type>::Owner( void ) const {
return owner;
}
/*
================
idLinkList<type>::SetOwner
Sets the object that this node is associated with.
================
*/
template< class type >
void idLinkList<type>::SetOwner( type *object ) {
owner = object;
}
#endif /* !__LINKLIST_H__ */

950
neo/idlib/containers/List.h Normal file
View File

@@ -0,0 +1,950 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __LIST_H__
#define __LIST_H__
/*
===============================================================================
List template
Does not allocate memory until the first item is added.
===============================================================================
*/
/*
================
idListSortCompare<type>
================
*/
#ifdef __INTEL_COMPILER
// the intel compiler doesn't do the right thing here
template< class type >
ID_INLINE int idListSortCompare( const type *a, const type *b ) {
assert( 0 );
return 0;
}
#else
template< class type >
ID_INLINE int idListSortCompare( const type *a, const type *b ) {
return *a - *b;
}
#endif
/*
================
idListNewElement<type>
================
*/
template< class type >
ID_INLINE type *idListNewElement( void ) {
return new type;
}
/*
================
idSwap<type>
================
*/
template< class type >
ID_INLINE void idSwap( type &a, type &b ) {
type c = a;
a = b;
b = c;
}
template< class type >
class idList {
public:
typedef int cmp_t( const type *, const type * );
typedef type new_t( void );
idList( int newgranularity = 16 );
idList( const idList<type> &other );
~idList<type>( void );
void Clear( void ); // clear the list
int Num( void ) const; // returns number of elements in list
int NumAllocated( void ) const; // returns number of elements allocated for
void SetGranularity( int newgranularity ); // set new granularity
int GetGranularity( void ) const; // get the current granularity
size_t Allocated( void ) const; // returns total size of allocated memory
size_t Size( void ) const; // returns total size of allocated memory including size of list type
size_t MemoryUsed( void ) const; // returns size of the used elements in the list
idList<type> & operator=( const idList<type> &other );
const type & operator[]( int index ) const;
type & operator[]( int index );
void Condense( void ); // resizes list to exactly the number of elements it contains
void Resize( int newsize ); // resizes list to the given number of elements
void Resize( int newsize, int newgranularity ); // resizes list and sets new granularity
void SetNum( int newnum, bool resize = true ); // set number of elements in list and resize to exactly this number if necessary
void AssureSize( int newSize); // assure list has given number of elements, but leave them uninitialized
void AssureSize( int newSize, const type &initValue ); // assure list has given number of elements and initialize any new elements
void AssureSizeAlloc( int newSize, new_t *allocator ); // assure the pointer list has the given number of elements and allocate any new elements
type * Ptr( void ); // returns a pointer to the list
const type * Ptr( void ) const; // returns a pointer to the list
type & Alloc( void ); // returns reference to a new data element at the end of the list
int Append( const type & obj ); // append element
int Append( const idList<type> &other ); // append list
int AddUnique( const type & obj ); // add unique element
int Insert( const type & obj, int index = 0 ); // insert the element at the given index
int FindIndex( const type & obj ) const; // find the index for the given element
type * Find( type const & obj ) const; // find pointer to the given element
int FindNull( void ) const; // find the index for the first NULL pointer in the list
int IndexOf( const type *obj ) const; // returns the index for the pointer to an element in the list
bool RemoveIndex( int index ); // remove the element at the given index
bool Remove( const type & obj ); // remove the element
void Sort( cmp_t *compare = ( cmp_t * )&idListSortCompare<type> );
void SortSubSection( int startIndex, int endIndex, cmp_t *compare = ( cmp_t * )&idListSortCompare<type> );
void Swap( idList<type> &other ); // swap the contents of the lists
void DeleteContents( bool clear ); // delete the contents of the list
private:
int num;
int size;
int granularity;
type * list;
};
/*
================
idList<type>::idList( int )
================
*/
template< class type >
ID_INLINE idList<type>::idList( int newgranularity ) {
assert( newgranularity > 0 );
list = NULL;
granularity = newgranularity;
Clear();
}
/*
================
idList<type>::idList( const idList<type> &other )
================
*/
template< class type >
ID_INLINE idList<type>::idList( const idList<type> &other ) {
list = NULL;
*this = other;
}
/*
================
idList<type>::~idList<type>
================
*/
template< class type >
ID_INLINE idList<type>::~idList( void ) {
Clear();
}
/*
================
idList<type>::Clear
Frees up the memory allocated by the list. Assumes that type automatically handles freeing up memory.
================
*/
template< class type >
ID_INLINE void idList<type>::Clear( void ) {
if ( list ) {
delete[] list;
}
list = NULL;
num = 0;
size = 0;
}
/*
================
idList<type>::DeleteContents
Calls the destructor of all elements in the list. Conditionally frees up memory used by the list.
Note that this only works on lists containing pointers to objects and will cause a compiler error
if called with non-pointers. Since the list was not responsible for allocating the object, it has
no information on whether the object still exists or not, so care must be taken to ensure that
the pointers are still valid when this function is called. Function will set all pointers in the
list to NULL.
================
*/
template< class type >
ID_INLINE void idList<type>::DeleteContents( bool clear ) {
int i;
for( i = 0; i < num; i++ ) {
delete list[ i ];
list[ i ] = NULL;
}
if ( clear ) {
Clear();
} else {
memset( list, 0, size * sizeof( type ) );
}
}
/*
================
idList<type>::Allocated
return total memory allocated for the list in bytes, but doesn't take into account additional memory allocated by type
================
*/
template< class type >
ID_INLINE size_t idList<type>::Allocated( void ) const {
return size * sizeof( type );
}
/*
================
idList<type>::Size
return total size of list in bytes, but doesn't take into account additional memory allocated by type
================
*/
template< class type >
ID_INLINE size_t idList<type>::Size( void ) const {
return sizeof( idList<type> ) + Allocated();
}
/*
================
idList<type>::MemoryUsed
================
*/
template< class type >
ID_INLINE size_t idList<type>::MemoryUsed( void ) const {
return num * sizeof( *list );
}
/*
================
idList<type>::Num
Returns the number of elements currently contained in the list.
Note that this is NOT an indication of the memory allocated.
================
*/
template< class type >
ID_INLINE int idList<type>::Num( void ) const {
return num;
}
/*
================
idList<type>::NumAllocated
Returns the number of elements currently allocated for.
================
*/
template< class type >
ID_INLINE int idList<type>::NumAllocated( void ) const {
return size;
}
/*
================
idList<type>::SetNum
Resize to the exact size specified irregardless of granularity
================
*/
template< class type >
ID_INLINE void idList<type>::SetNum( int newnum, bool resize ) {
assert( newnum >= 0 );
if ( resize || newnum > size ) {
Resize( newnum );
}
num = newnum;
}
/*
================
idList<type>::SetGranularity
Sets the base size of the array and resizes the array to match.
================
*/
template< class type >
ID_INLINE void idList<type>::SetGranularity( int newgranularity ) {
int newsize;
assert( newgranularity > 0 );
granularity = newgranularity;
if ( list ) {
// resize it to the closest level of granularity
newsize = num + granularity - 1;
newsize -= newsize % granularity;
if ( newsize != size ) {
Resize( newsize );
}
}
}
/*
================
idList<type>::GetGranularity
Get the current granularity.
================
*/
template< class type >
ID_INLINE int idList<type>::GetGranularity( void ) const {
return granularity;
}
/*
================
idList<type>::Condense
Resizes the array to exactly the number of elements it contains or frees up memory if empty.
================
*/
template< class type >
ID_INLINE void idList<type>::Condense( void ) {
if ( list ) {
if ( num ) {
Resize( num );
} else {
Clear();
}
}
}
/*
================
idList<type>::Resize
Allocates memory for the amount of elements requested while keeping the contents intact.
Contents are copied using their = operator so that data is correnctly instantiated.
================
*/
template< class type >
ID_INLINE void idList<type>::Resize( int newsize ) {
type *temp;
int i;
assert( newsize >= 0 );
// free up the list if no data is being reserved
if ( newsize <= 0 ) {
Clear();
return;
}
if ( newsize == size ) {
// not changing the size, so just exit
return;
}
temp = list;
size = newsize;
if ( size < num ) {
num = size;
}
// copy the old list into our new one
list = new type[ size ];
for( i = 0; i < num; i++ ) {
list[ i ] = temp[ i ];
}
// delete the old list if it exists
if ( temp ) {
delete[] temp;
}
}
/*
================
idList<type>::Resize
Allocates memory for the amount of elements requested while keeping the contents intact.
Contents are copied using their = operator so that data is correnctly instantiated.
================
*/
template< class type >
ID_INLINE void idList<type>::Resize( int newsize, int newgranularity ) {
type *temp;
int i;
assert( newsize >= 0 );
assert( newgranularity > 0 );
granularity = newgranularity;
// free up the list if no data is being reserved
if ( newsize <= 0 ) {
Clear();
return;
}
temp = list;
size = newsize;
if ( size < num ) {
num = size;
}
// copy the old list into our new one
list = new type[ size ];
for( i = 0; i < num; i++ ) {
list[ i ] = temp[ i ];
}
// delete the old list if it exists
if ( temp ) {
delete[] temp;
}
}
/*
================
idList<type>::AssureSize
Makes sure the list has at least the given number of elements.
================
*/
template< class type >
ID_INLINE void idList<type>::AssureSize( int newSize ) {
int newNum = newSize;
if ( newSize > size ) {
if ( granularity == 0 ) { // this is a hack to fix our memset classes
granularity = 16;
}
newSize += granularity - 1;
newSize -= newSize % granularity;
Resize( newSize );
}
num = newNum;
}
/*
================
idList<type>::AssureSize
Makes sure the list has at least the given number of elements and initialize any elements not yet initialized.
================
*/
template< class type >
ID_INLINE void idList<type>::AssureSize( int newSize, const type &initValue ) {
int newNum = newSize;
if ( newSize > size ) {
if ( granularity == 0 ) { // this is a hack to fix our memset classes
granularity = 16;
}
newSize += granularity - 1;
newSize -= newSize % granularity;
num = size;
Resize( newSize );
for ( int i = num; i < newSize; i++ ) {
list[i] = initValue;
}
}
num = newNum;
}
/*
================
idList<type>::AssureSizeAlloc
Makes sure the list has at least the given number of elements and allocates any elements using the allocator.
NOTE: This function can only be called on lists containing pointers. Calling it
on non-pointer lists will cause a compiler error.
================
*/
template< class type >
ID_INLINE void idList<type>::AssureSizeAlloc( int newSize, new_t *allocator ) {
int newNum = newSize;
if ( newSize > size ) {
if ( granularity == 0 ) { // this is a hack to fix our memset classes
granularity = 16;
}
newSize += granularity - 1;
newSize -= newSize % granularity;
num = size;
Resize( newSize );
for ( int i = num; i < newSize; i++ ) {
list[i] = (*allocator)();
}
}
num = newNum;
}
/*
================
idList<type>::operator=
Copies the contents and size attributes of another list.
================
*/
template< class type >
ID_INLINE idList<type> &idList<type>::operator=( const idList<type> &other ) {
int i;
Clear();
num = other.num;
size = other.size;
granularity = other.granularity;
if ( size ) {
list = new type[ size ];
for( i = 0; i < num; i++ ) {
list[ i ] = other.list[ i ];
}
}
return *this;
}
/*
================
idList<type>::operator[] const
Access operator. Index must be within range or an assert will be issued in debug builds.
Release builds do no range checking.
================
*/
template< class type >
ID_INLINE const type &idList<type>::operator[]( int index ) const {
assert( index >= 0 );
assert( index < num );
return list[ index ];
}
/*
================
idList<type>::operator[]
Access operator. Index must be within range or an assert will be issued in debug builds.
Release builds do no range checking.
================
*/
template< class type >
ID_INLINE type &idList<type>::operator[]( int index ) {
assert( index >= 0 );
assert( index < num );
return list[ index ];
}
/*
================
idList<type>::Ptr
Returns a pointer to the begining of the array. Useful for iterating through the list in loops.
Note: may return NULL if the list is empty.
FIXME: Create an iterator template for this kind of thing.
================
*/
template< class type >
ID_INLINE type *idList<type>::Ptr( void ) {
return list;
}
/*
================
idList<type>::Ptr
Returns a pointer to the begining of the array. Useful for iterating through the list in loops.
Note: may return NULL if the list is empty.
FIXME: Create an iterator template for this kind of thing.
================
*/
template< class type >
const ID_INLINE type *idList<type>::Ptr( void ) const {
return list;
}
/*
================
idList<type>::Alloc
Returns a reference to a new data element at the end of the list.
================
*/
template< class type >
ID_INLINE type &idList<type>::Alloc( void ) {
if ( !list ) {
Resize( granularity );
}
if ( num == size ) {
Resize( size + granularity );
}
return list[ num++ ];
}
/*
================
idList<type>::Append
Increases the size of the list by one element and copies the supplied data into it.
Returns the index of the new element.
================
*/
template< class type >
ID_INLINE int idList<type>::Append( type const & obj ) {
if ( !list ) {
Resize( granularity );
}
if ( num == size ) {
int newsize;
if ( granularity == 0 ) { // this is a hack to fix our memset classes
granularity = 16;
}
newsize = size + granularity;
Resize( newsize - newsize % granularity );
}
list[ num ] = obj;
num++;
return num - 1;
}
/*
================
idList<type>::Insert
Increases the size of the list by at leat one element if necessary
and inserts the supplied data into it.
Returns the index of the new element.
================
*/
template< class type >
ID_INLINE int idList<type>::Insert( type const & obj, int index ) {
if ( !list ) {
Resize( granularity );
}
if ( num == size ) {
int newsize;
if ( granularity == 0 ) { // this is a hack to fix our memset classes
granularity = 16;
}
newsize = size + granularity;
Resize( newsize - newsize % granularity );
}
if ( index < 0 ) {
index = 0;
}
else if ( index > num ) {
index = num;
}
for ( int i = num; i > index; --i ) {
list[i] = list[i-1];
}
num++;
list[index] = obj;
return index;
}
/*
================
idList<type>::Append
adds the other list to this one
Returns the size of the new combined list
================
*/
template< class type >
ID_INLINE int idList<type>::Append( const idList<type> &other ) {
if ( !list ) {
if ( granularity == 0 ) { // this is a hack to fix our memset classes
granularity = 16;
}
Resize( granularity );
}
int n = other.Num();
for (int i = 0; i < n; i++) {
Append(other[i]);
}
return Num();
}
/*
================
idList<type>::AddUnique
Adds the data to the list if it doesn't already exist. Returns the index of the data in the list.
================
*/
template< class type >
ID_INLINE int idList<type>::AddUnique( type const & obj ) {
int index;
index = FindIndex( obj );
if ( index < 0 ) {
index = Append( obj );
}
return index;
}
/*
================
idList<type>::FindIndex
Searches for the specified data in the list and returns it's index. Returns -1 if the data is not found.
================
*/
template< class type >
ID_INLINE int idList<type>::FindIndex( type const & obj ) const {
int i;
for( i = 0; i < num; i++ ) {
if ( list[ i ] == obj ) {
return i;
}
}
// Not found
return -1;
}
/*
================
idList<type>::Find
Searches for the specified data in the list and returns it's address. Returns NULL if the data is not found.
================
*/
template< class type >
ID_INLINE type *idList<type>::Find( type const & obj ) const {
int i;
i = FindIndex( obj );
if ( i >= 0 ) {
return &list[ i ];
}
return NULL;
}
/*
================
idList<type>::FindNull
Searches for a NULL pointer in the list. Returns -1 if NULL is not found.
NOTE: This function can only be called on lists containing pointers. Calling it
on non-pointer lists will cause a compiler error.
================
*/
template< class type >
ID_INLINE int idList<type>::FindNull( void ) const {
int i;
for( i = 0; i < num; i++ ) {
if ( list[ i ] == NULL ) {
return i;
}
}
// Not found
return -1;
}
/*
================
idList<type>::IndexOf
Takes a pointer to an element in the list and returns the index of the element.
This is NOT a guarantee that the object is really in the list.
Function will assert in debug builds if pointer is outside the bounds of the list,
but remains silent in release builds.
================
*/
template< class type >
ID_INLINE int idList<type>::IndexOf( type const *objptr ) const {
int index;
index = objptr - list;
assert( index >= 0 );
assert( index < num );
return index;
}
/*
================
idList<type>::RemoveIndex
Removes the element at the specified index and moves all data following the element down to fill in the gap.
The number of elements in the list is reduced by one. Returns false if the index is outside the bounds of the list.
Note that the element is not destroyed, so any memory used by it may not be freed until the destruction of the list.
================
*/
template< class type >
ID_INLINE bool idList<type>::RemoveIndex( int index ) {
int i;
assert( list != NULL );
assert( index >= 0 );
assert( index < num );
if ( ( index < 0 ) || ( index >= num ) ) {
return false;
}
num--;
for( i = index; i < num; i++ ) {
list[ i ] = list[ i + 1 ];
}
return true;
}
/*
================
idList<type>::Remove
Removes the element if it is found within the list and moves all data following the element down to fill in the gap.
The number of elements in the list is reduced by one. Returns false if the data is not found in the list. Note that
the element is not destroyed, so any memory used by it may not be freed until the destruction of the list.
================
*/
template< class type >
ID_INLINE bool idList<type>::Remove( type const & obj ) {
int index;
index = FindIndex( obj );
if ( index >= 0 ) {
return RemoveIndex( index );
}
return false;
}
/*
================
idList<type>::Sort
Performs a qsort on the list using the supplied comparison function. Note that the data is merely moved around the
list, so any pointers to data within the list may no longer be valid.
================
*/
template< class type >
ID_INLINE void idList<type>::Sort( cmp_t *compare ) {
if ( !list ) {
return;
}
typedef int cmp_c(const void *, const void *);
cmp_c *vCompare = (cmp_c *)compare;
qsort( ( void * )list, ( size_t )num, sizeof( type ), vCompare );
}
/*
================
idList<type>::SortSubSection
Sorts a subsection of the list.
================
*/
template< class type >
ID_INLINE void idList<type>::SortSubSection( int startIndex, int endIndex, cmp_t *compare ) {
if ( !list ) {
return;
}
if ( startIndex < 0 ) {
startIndex = 0;
}
if ( endIndex >= num ) {
endIndex = num - 1;
}
if ( startIndex >= endIndex ) {
return;
}
typedef int cmp_c(const void *, const void *);
cmp_c *vCompare = (cmp_c *)compare;
qsort( ( void * )( &list[startIndex] ), ( size_t )( endIndex - startIndex + 1 ), sizeof( type ), vCompare );
}
/*
================
idList<type>::Swap
Swaps the contents of two lists
================
*/
template< class type >
ID_INLINE void idList<type>::Swap( idList<type> &other ) {
idSwap( num, other.num );
idSwap( size, other.size );
idSwap( granularity, other.granularity );
idSwap( list, other.list );
}
#endif /* !__LIST_H__ */

View File

@@ -0,0 +1,81 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __PLANESET_H__
#define __PLANESET_H__
/*
===============================================================================
Plane Set
===============================================================================
*/
class idPlaneSet : public idList<idPlane> {
public:
void Clear( void ) { idList<idPlane>::Clear(); hash.Free(); }
int FindPlane( const idPlane &plane, const float normalEps, const float distEps );
private:
idHashIndex hash;
};
ID_INLINE int idPlaneSet::FindPlane( const idPlane &plane, const float normalEps, const float distEps ) {
int i, border, hashKey;
assert( distEps <= 0.125f );
hashKey = (int)( idMath::Fabs( plane.Dist() ) * 0.125f );
for ( border = -1; border <= 1; border++ ) {
for ( i = hash.First( hashKey + border ); i >= 0; i = hash.Next( i ) ) {
if ( (*this)[i].Compare( plane, normalEps, distEps ) ) {
return i;
}
}
}
if ( plane.Type() >= PLANETYPE_NEGX && plane.Type() < PLANETYPE_TRUEAXIAL ) {
Append( -plane );
hash.Add( hashKey, Num()-1 );
Append( plane );
hash.Add( hashKey, Num()-1 );
return ( Num() - 1 );
}
else {
Append( plane );
hash.Add( hashKey, Num()-1 );
Append( -plane );
hash.Add( hashKey, Num()-1 );
return ( Num() - 2 );
}
}
#endif /* !__PLANESET_H__ */

View File

@@ -0,0 +1,88 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __QUEUE_H__
#define __QUEUE_H__
/*
===============================================================================
Queue template
===============================================================================
*/
#define idQueue( type, next ) idQueueTemplate<type, (int)&(((type*)NULL)->next)>
template< class type, int nextOffset >
class idQueueTemplate {
public:
idQueueTemplate( void );
void Add( type *element );
type * Get( void );
private:
type * first;
type * last;
};
#define QUEUE_NEXT_PTR( element ) (*((type**)(((byte*)element)+nextOffset)))
template< class type, int nextOffset >
idQueueTemplate<type,nextOffset>::idQueueTemplate( void ) {
first = last = NULL;
}
template< class type, int nextOffset >
void idQueueTemplate<type,nextOffset>::Add( type *element ) {
QUEUE_NEXT_PTR(element) = NULL;
if ( last ) {
QUEUE_NEXT_PTR(last) = element;
} else {
first = element;
}
last = element;
}
template< class type, int nextOffset >
type *idQueueTemplate<type,nextOffset>::Get( void ) {
type *element;
element = first;
if ( element ) {
first = QUEUE_NEXT_PTR(first);
if ( last == element ) {
last = NULL;
}
QUEUE_NEXT_PTR(element) = NULL;
}
return element;
}
#endif /* !__QUEUE_H__ */

View File

@@ -0,0 +1,86 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __STACK_H__
#define __STACK_H__
/*
===============================================================================
Stack template
===============================================================================
*/
#define idStack( type, next ) idStackTemplate<type, (int)&(((type*)NULL)->next)>
template< class type, int nextOffset >
class idStackTemplate {
public:
idStackTemplate( void );
void Add( type *element );
type * Get( void );
private:
type * top;
type * bottom;
};
#define STACK_NEXT_PTR( element ) (*(type**)(((byte*)element)+nextOffset))
template< class type, int nextOffset >
idStackTemplate<type,nextOffset>::idStackTemplate( void ) {
top = bottom = NULL;
}
template< class type, int nextOffset >
void idStackTemplate<type,nextOffset>::Add( type *element ) {
STACK_NEXT_PTR(element) = top;
top = element;
if ( !bottom ) {
bottom = element;
}
}
template< class type, int nextOffset >
type *idStackTemplate<type,nextOffset>::Get( void ) {
type *element;
element = top;
if ( element ) {
top = STACK_NEXT_PTR(top);
if ( bottom == element ) {
bottom = NULL;
}
STACK_NEXT_PTR(element) = NULL;
}
return element;
}
#endif /* !__STACK_H__ */

View File

@@ -0,0 +1,548 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __STATICLIST_H__
#define __STATICLIST_H__
/*
===============================================================================
Static list template
A non-growing, memset-able list using no memory allocation.
===============================================================================
*/
template<class type,int size>
class idStaticList {
public:
idStaticList();
idStaticList( const idStaticList<type,size> &other );
~idStaticList<type,size>( void );
void Clear( void ); // marks the list as empty. does not deallocate or intialize data.
int Num( void ) const; // returns number of elements in list
int Max( void ) const; // returns the maximum number of elements in the list
void SetNum( int newnum ); // set number of elements in list
size_t Allocated( void ) const; // returns total size of allocated memory
size_t Size( void ) const; // returns total size of allocated memory including size of list type
size_t MemoryUsed( void ) const; // returns size of the used elements in the list
const type & operator[]( int index ) const;
type & operator[]( int index );
type * Ptr( void ); // returns a pointer to the list
const type * Ptr( void ) const; // returns a pointer to the list
type * Alloc( void ); // returns reference to a new data element at the end of the list. returns NULL when full.
int Append( const type & obj ); // append element
int Append( const idStaticList<type,size> &other ); // append list
int AddUnique( const type & obj ); // add unique element
int Insert( const type & obj, int index ); // insert the element at the given index
int FindIndex( const type & obj ) const; // find the index for the given element
type * Find( type const & obj ) const; // find pointer to the given element
int FindNull( void ) const; // find the index for the first NULL pointer in the list
int IndexOf( const type *obj ) const; // returns the index for the pointer to an element in the list
bool RemoveIndex( int index ); // remove the element at the given index
bool Remove( const type & obj ); // remove the element
void Swap( idStaticList<type,size> &other ); // swap the contents of the lists
void DeleteContents( bool clear ); // delete the contents of the list
private:
int num;
type list[ size ];
};
/*
================
idStaticList<type,size>::idStaticList()
================
*/
template<class type,int size>
ID_INLINE idStaticList<type,size>::idStaticList() {
num = 0;
}
/*
================
idStaticList<type,size>::idStaticList( const idStaticList<type,size> &other )
================
*/
template<class type,int size>
ID_INLINE idStaticList<type,size>::idStaticList( const idStaticList<type,size> &other ) {
*this = other;
}
/*
================
idStaticList<type,size>::~idStaticList<type,size>
================
*/
template<class type,int size>
ID_INLINE idStaticList<type,size>::~idStaticList( void ) {
}
/*
================
idStaticList<type,size>::Clear
Sets the number of elements in the list to 0. Assumes that type automatically handles freeing up memory.
================
*/
template<class type,int size>
ID_INLINE void idStaticList<type,size>::Clear( void ) {
num = 0;
}
/*
================
idStaticList<type,size>::DeleteContents
Calls the destructor of all elements in the list. Conditionally frees up memory used by the list.
Note that this only works on lists containing pointers to objects and will cause a compiler error
if called with non-pointers. Since the list was not responsible for allocating the object, it has
no information on whether the object still exists or not, so care must be taken to ensure that
the pointers are still valid when this function is called. Function will set all pointers in the
list to NULL.
================
*/
template<class type,int size>
ID_INLINE void idStaticList<type,size>::DeleteContents( bool clear ) {
int i;
for( i = 0; i < size; i++ ) {
delete list[ i ];
list[ i ] = NULL;
}
if ( clear ) {
Clear();
} else {
memset( list, 0, sizeof( list ) );
}
}
/*
================
idStaticList<type,size>::Num
Returns the number of elements currently contained in the list.
================
*/
template<class type,int size>
ID_INLINE int idStaticList<type,size>::Num( void ) const {
return num;
}
/*
================
idStaticList<type,size>::Num
Returns the maximum number of elements in the list.
================
*/
template<class type,int size>
ID_INLINE int idStaticList<type,size>::Max( void ) const {
return size;
}
/*
================
idStaticList<type>::Allocated
================
*/
template<class type,int size>
ID_INLINE size_t idStaticList<type,size>::Allocated( void ) const {
return size * sizeof( type );
}
/*
================
idStaticList<type>::Size
================
*/
template<class type,int size>
ID_INLINE size_t idStaticList<type,size>::Size( void ) const {
return sizeof( idStaticList<type,size> ) + Allocated();
}
/*
================
idStaticList<type,size>::Num
================
*/
template<class type,int size>
ID_INLINE size_t idStaticList<type,size>::MemoryUsed( void ) const {
return num * sizeof( list[ 0 ] );
}
/*
================
idStaticList<type,size>::SetNum
Set number of elements in list.
================
*/
template<class type,int size>
ID_INLINE void idStaticList<type,size>::SetNum( int newnum ) {
assert( newnum >= 0 );
assert( newnum <= size );
num = newnum;
}
/*
================
idStaticList<type,size>::operator[] const
Access operator. Index must be within range or an assert will be issued in debug builds.
Release builds do no range checking.
================
*/
template<class type,int size>
ID_INLINE const type &idStaticList<type,size>::operator[]( int index ) const {
assert( index >= 0 );
assert( index < num );
return list[ index ];
}
/*
================
idStaticList<type,size>::operator[]
Access operator. Index must be within range or an assert will be issued in debug builds.
Release builds do no range checking.
================
*/
template<class type,int size>
ID_INLINE type &idStaticList<type,size>::operator[]( int index ) {
assert( index >= 0 );
assert( index < num );
return list[ index ];
}
/*
================
idStaticList<type,size>::Ptr
Returns a pointer to the begining of the array. Useful for iterating through the list in loops.
Note: may return NULL if the list is empty.
FIXME: Create an iterator template for this kind of thing.
================
*/
template<class type,int size>
ID_INLINE type *idStaticList<type,size>::Ptr( void ) {
return &list[ 0 ];
}
/*
================
idStaticList<type,size>::Ptr
Returns a pointer to the begining of the array. Useful for iterating through the list in loops.
Note: may return NULL if the list is empty.
FIXME: Create an iterator template for this kind of thing.
================
*/
template<class type,int size>
ID_INLINE const type *idStaticList<type,size>::Ptr( void ) const {
return &list[ 0 ];
}
/*
================
idStaticList<type,size>::Alloc
Returns a pointer to a new data element at the end of the list.
================
*/
template<class type,int size>
ID_INLINE type *idStaticList<type,size>::Alloc( void ) {
if ( num >= size ) {
return NULL;
}
return &list[ num++ ];
}
/*
================
idStaticList<type,size>::Append
Increases the size of the list by one element and copies the supplied data into it.
Returns the index of the new element, or -1 when list is full.
================
*/
template<class type,int size>
ID_INLINE int idStaticList<type,size>::Append( type const & obj ) {
assert( num < size );
if ( num < size ) {
list[ num ] = obj;
num++;
return num - 1;
}
return -1;
}
/*
================
idStaticList<type,size>::Insert
Increases the size of the list by at leat one element if necessary
and inserts the supplied data into it.
Returns the index of the new element, or -1 when list is full.
================
*/
template<class type,int size>
ID_INLINE int idStaticList<type,size>::Insert( type const & obj, int index ) {
int i;
assert( num < size );
if ( num >= size ) {
return -1;
}
assert( index >= 0 );
if ( index < 0 ) {
index = 0;
} else if ( index > num ) {
index = num;
}
for( i = num; i > index; --i ) {
list[i] = list[i-1];
}
num++;
list[index] = obj;
return index;
}
/*
================
idStaticList<type,size>::Append
adds the other list to this one
Returns the size of the new combined list
================
*/
template<class type,int size>
ID_INLINE int idStaticList<type,size>::Append( const idStaticList<type,size> &other ) {
int i;
int n = other.Num();
if ( num + n > size ) {
n = size - num;
}
for( i = 0; i < n; i++ ) {
list[i + num] = other.list[i];
}
num += n;
return Num();
}
/*
================
idStaticList<type,size>::AddUnique
Adds the data to the list if it doesn't already exist. Returns the index of the data in the list.
================
*/
template<class type,int size>
ID_INLINE int idStaticList<type,size>::AddUnique( type const & obj ) {
int index;
index = FindIndex( obj );
if ( index < 0 ) {
index = Append( obj );
}
return index;
}
/*
================
idStaticList<type,size>::FindIndex
Searches for the specified data in the list and returns it's index. Returns -1 if the data is not found.
================
*/
template<class type,int size>
ID_INLINE int idStaticList<type,size>::FindIndex( type const & obj ) const {
int i;
for( i = 0; i < num; i++ ) {
if ( list[ i ] == obj ) {
return i;
}
}
// Not found
return -1;
}
/*
================
idStaticList<type,size>::Find
Searches for the specified data in the list and returns it's address. Returns NULL if the data is not found.
================
*/
template<class type,int size>
ID_INLINE type *idStaticList<type,size>::Find( type const & obj ) const {
int i;
i = FindIndex( obj );
if ( i >= 0 ) {
return &list[ i ];
}
return NULL;
}
/*
================
idStaticList<type,size>::FindNull
Searches for a NULL pointer in the list. Returns -1 if NULL is not found.
NOTE: This function can only be called on lists containing pointers. Calling it
on non-pointer lists will cause a compiler error.
================
*/
template<class type,int size>
ID_INLINE int idStaticList<type,size>::FindNull( void ) const {
int i;
for( i = 0; i < num; i++ ) {
if ( list[ i ] == NULL ) {
return i;
}
}
// Not found
return -1;
}
/*
================
idStaticList<type,size>::IndexOf
Takes a pointer to an element in the list and returns the index of the element.
This is NOT a guarantee that the object is really in the list.
Function will assert in debug builds if pointer is outside the bounds of the list,
but remains silent in release builds.
================
*/
template<class type,int size>
ID_INLINE int idStaticList<type,size>::IndexOf( type const *objptr ) const {
int index;
index = objptr - list;
assert( index >= 0 );
assert( index < num );
return index;
}
/*
================
idStaticList<type,size>::RemoveIndex
Removes the element at the specified index and moves all data following the element down to fill in the gap.
The number of elements in the list is reduced by one. Returns false if the index is outside the bounds of the list.
Note that the element is not destroyed, so any memory used by it may not be freed until the destruction of the list.
================
*/
template<class type,int size>
ID_INLINE bool idStaticList<type,size>::RemoveIndex( int index ) {
int i;
assert( index >= 0 );
assert( index < num );
if ( ( index < 0 ) || ( index >= num ) ) {
return false;
}
num--;
for( i = index; i < num; i++ ) {
list[ i ] = list[ i + 1 ];
}
return true;
}
/*
================
idStaticList<type,size>::Remove
Removes the element if it is found within the list and moves all data following the element down to fill in the gap.
The number of elements in the list is reduced by one. Returns false if the data is not found in the list. Note that
the element is not destroyed, so any memory used by it may not be freed until the destruction of the list.
================
*/
template<class type,int size>
ID_INLINE bool idStaticList<type,size>::Remove( type const & obj ) {
int index;
index = FindIndex( obj );
if ( index >= 0 ) {
return RemoveIndex( index );
}
return false;
}
/*
================
idStaticList<type,size>::Swap
Swaps the contents of two lists
================
*/
template<class type,int size>
ID_INLINE void idStaticList<type,size>::Swap( idStaticList<type,size> &other ) {
idStaticList<type,size> temp = *this;
*this = other;
other = temp;
}
#endif /* !__STATICLIST_H__ */

View File

@@ -0,0 +1,204 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __STRLIST_H__
#define __STRLIST_H__
/*
===============================================================================
idStrList
===============================================================================
*/
typedef idList<idStr> idStrList;
typedef idList<idStr*> idStrPtrList;
typedef idStr *idStrPtr;
/*
================
idListSortCompare<idStrPtr>
Compares two pointers to strings. Used to sort a list of string pointers alphabetically in idList<idStr>::Sort.
================
*/
template<>
ID_INLINE int idListSortCompare<idStrPtr>( const idStrPtr *a, const idStrPtr *b ) {
return ( *a )->Icmp( **b );
}
/*
================
idStrList::Sort
Sorts the list of strings alphabetically. Creates a list of pointers to the actual strings and sorts the
pointer list. Then copies the strings into another list using the ordered list of pointers.
================
*/
template<>
ID_INLINE void idStrList::Sort( cmp_t *compare ) {
int i;
if ( !num ) {
return;
}
idList<idStr> other;
idList<idStrPtr> pointerList;
pointerList.SetNum( num );
for( i = 0; i < num; i++ ) {
pointerList[ i ] = &( *this )[ i ];
}
pointerList.Sort();
other.SetNum( num );
other.SetGranularity( granularity );
for( i = 0; i < other.Num(); i++ ) {
other[ i ] = *pointerList[ i ];
}
this->Swap( other );
}
/*
================
idStrList::SortSubSection
Sorts a subsection of the list of strings alphabetically.
================
*/
template<>
ID_INLINE void idStrList::SortSubSection( int startIndex, int endIndex, cmp_t *compare ) {
int i, s;
if ( !num ) {
return;
}
if ( startIndex < 0 ) {
startIndex = 0;
}
if ( endIndex >= num ) {
endIndex = num - 1;
}
if ( startIndex >= endIndex ) {
return;
}
idList<idStr> other;
idList<idStrPtr> pointerList;
s = endIndex - startIndex + 1;
other.SetNum( s );
pointerList.SetNum( s );
for( i = 0; i < s; i++ ) {
other[ i ] = ( *this )[ startIndex + i ];
pointerList[ i ] = &other[ i ];
}
pointerList.Sort();
for( i = 0; i < s; i++ ) {
(*this)[ startIndex + i ] = *pointerList[ i ];
}
}
/*
================
idStrList::Size
================
*/
template<>
ID_INLINE size_t idStrList::Size( void ) const {
size_t s;
int i;
s = sizeof( *this );
for( i = 0; i < Num(); i++ ) {
s += ( *this )[ i ].Size();
}
return s;
}
/*
===============================================================================
idStrList path sorting
===============================================================================
*/
/*
================
idListSortComparePaths
Compares two pointers to strings. Used to sort a list of string pointers alphabetically in idList<idStr>::Sort.
================
*/
template<class idStrPtr>
ID_INLINE int idListSortComparePaths( const idStrPtr *a, const idStrPtr *b ) {
return ( *a )->IcmpPath( **b );
}
/*
================
idStrListSortPaths
Sorts the list of path strings alphabetically and makes sure folders come first.
================
*/
ID_INLINE void idStrListSortPaths( idStrList &list ) {
int i;
if ( !list.Num() ) {
return;
}
idList<idStr> other;
idList<idStrPtr> pointerList;
pointerList.SetNum( list.Num() );
for( i = 0; i < list.Num(); i++ ) {
pointerList[ i ] = &list[ i ];
}
pointerList.Sort( idListSortComparePaths<idStrPtr> );
other.SetNum( list.Num() );
other.SetGranularity( list.GetGranularity() );
for( i = 0; i < other.Num(); i++ ) {
other[ i ] = *pointerList[ i ];
}
list.Swap( other );
}
#endif /* !__STRLIST_H__ */

View File

@@ -0,0 +1,228 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __STRPOOL_H__
#define __STRPOOL_H__
/*
===============================================================================
idStrPool
===============================================================================
*/
class idStrPool;
class idPoolStr : public idStr {
friend class idStrPool;
public:
idPoolStr() { numUsers = 0; }
~idPoolStr() { assert( numUsers == 0 ); }
// returns total size of allocated memory
size_t Allocated( void ) const { return idStr::Allocated(); }
// returns total size of allocated memory including size of string pool type
size_t Size( void ) const { return sizeof( *this ) + Allocated(); }
// returns a pointer to the pool this string was allocated from
const idStrPool * GetPool( void ) const { return pool; }
private:
idStrPool * pool;
mutable int numUsers;
};
class idStrPool {
public:
idStrPool() { caseSensitive = true; }
void SetCaseSensitive( bool caseSensitive );
int Num( void ) const { return pool.Num(); }
size_t Allocated( void ) const;
size_t Size( void ) const;
const idPoolStr * operator[]( int index ) const { return pool[index]; }
const idPoolStr * AllocString( const char *string );
void FreeString( const idPoolStr *poolStr );
const idPoolStr * CopyString( const idPoolStr *poolStr );
void Clear( void );
private:
bool caseSensitive;
idList<idPoolStr *> pool;
idHashIndex poolHash;
};
/*
================
idStrPool::SetCaseSensitive
================
*/
ID_INLINE void idStrPool::SetCaseSensitive( bool caseSensitive ) {
this->caseSensitive = caseSensitive;
}
/*
================
idStrPool::AllocString
================
*/
ID_INLINE const idPoolStr *idStrPool::AllocString( const char *string ) {
int i, hash;
idPoolStr *poolStr;
hash = poolHash.GenerateKey( string, caseSensitive );
if ( caseSensitive ) {
for ( i = poolHash.First( hash ); i != -1; i = poolHash.Next( i ) ) {
if ( pool[i]->Cmp( string ) == 0 ) {
pool[i]->numUsers++;
return pool[i];
}
}
} else {
for ( i = poolHash.First( hash ); i != -1; i = poolHash.Next( i ) ) {
if ( pool[i]->Icmp( string ) == 0 ) {
pool[i]->numUsers++;
return pool[i];
}
}
}
poolStr = new idPoolStr;
*static_cast<idStr *>(poolStr) = string;
poolStr->pool = this;
poolStr->numUsers = 1;
poolHash.Add( hash, pool.Append( poolStr ) );
return poolStr;
}
/*
================
idStrPool::FreeString
================
*/
ID_INLINE void idStrPool::FreeString( const idPoolStr *poolStr ) {
int i, hash;
assert( poolStr->numUsers >= 1 );
assert( poolStr->pool == this );
poolStr->numUsers--;
if ( poolStr->numUsers <= 0 ) {
hash = poolHash.GenerateKey( poolStr->c_str(), caseSensitive );
if ( caseSensitive ) {
for ( i = poolHash.First( hash ); i != -1; i = poolHash.Next( i ) ) {
if ( pool[i]->Cmp( poolStr->c_str() ) == 0 ) {
break;
}
}
} else {
for ( i = poolHash.First( hash ); i != -1; i = poolHash.Next( i ) ) {
if ( pool[i]->Icmp( poolStr->c_str() ) == 0 ) {
break;
}
}
}
assert( i != -1 );
assert( pool[i] == poolStr );
delete pool[i];
pool.RemoveIndex( i );
poolHash.RemoveIndex( hash, i );
}
}
/*
================
idStrPool::CopyString
================
*/
ID_INLINE const idPoolStr *idStrPool::CopyString( const idPoolStr *poolStr ) {
assert( poolStr->numUsers >= 1 );
if ( poolStr->pool == this ) {
// the string is from this pool so just increase the user count
poolStr->numUsers++;
return poolStr;
} else {
// the string is from another pool so it needs to be re-allocated from this pool.
return AllocString( poolStr->c_str() );
}
}
/*
================
idStrPool::Clear
================
*/
ID_INLINE void idStrPool::Clear( void ) {
int i;
for ( i = 0; i < pool.Num(); i++ ) {
pool[i]->numUsers = 0;
}
pool.DeleteContents( true );
poolHash.Free();
}
/*
================
idStrPool::Allocated
================
*/
ID_INLINE size_t idStrPool::Allocated( void ) const {
int i;
size_t size;
size = pool.Allocated() + poolHash.Allocated();
for ( i = 0; i < pool.Num(); i++ ) {
size += pool[i]->Allocated();
}
return size;
}
/*
================
idStrPool::Size
================
*/
ID_INLINE size_t idStrPool::Size( void ) const {
int i;
size_t size;
size = pool.Size() + poolHash.Size();
for ( i = 0; i < pool.Num(); i++ ) {
size += pool[i]->Size();
}
return size;
}
#endif /* !__STRPOOL_H__ */

View File

@@ -0,0 +1,270 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __VECTORSET_H__
#define __VECTORSET_H__
/*
===============================================================================
Vector Set
Creates a set of vectors without duplicates.
===============================================================================
*/
template< class type, int dimension >
class idVectorSet : public idList<type> {
public:
idVectorSet( void );
idVectorSet( const type &mins, const type &maxs, const int boxHashSize, const int initialSize );
// returns total size of allocated memory
size_t Allocated( void ) const { return idList<type>::Allocated() + hash.Allocated(); }
// returns total size of allocated memory including size of type
size_t Size( void ) const { return sizeof( *this ) + Allocated(); }
void Init( const type &mins, const type &maxs, const int boxHashSize, const int initialSize );
void ResizeIndex( const int newSize );
void Clear( void );
int FindVector( const type &v, const float epsilon );
private:
idHashIndex hash;
type mins;
type maxs;
int boxHashSize;
float boxInvSize[dimension];
float boxHalfSize[dimension];
};
template< class type, int dimension >
ID_INLINE idVectorSet<type,dimension>::idVectorSet( void ) {
hash.Clear( idMath::IPow( boxHashSize, dimension ), 128 );
boxHashSize = 16;
memset( boxInvSize, 0, dimension * sizeof( boxInvSize[0] ) );
memset( boxHalfSize, 0, dimension * sizeof( boxHalfSize[0] ) );
}
template< class type, int dimension >
ID_INLINE idVectorSet<type,dimension>::idVectorSet( const type &mins, const type &maxs, const int boxHashSize, const int initialSize ) {
Init( mins, maxs, boxHashSize, initialSize );
}
template< class type, int dimension >
ID_INLINE void idVectorSet<type,dimension>::Init( const type &mins, const type &maxs, const int boxHashSize, const int initialSize ) {
int i;
float boxSize;
idList<type>::AssureSize( initialSize );
idList<type>::SetNum( 0, false );
hash.Clear( idMath::IPow( boxHashSize, dimension ), initialSize );
this->mins = mins;
this->maxs = maxs;
this->boxHashSize = boxHashSize;
for ( i = 0; i < dimension; i++ ) {
boxSize = ( maxs[i] - mins[i] ) / (float) boxHashSize;
boxInvSize[i] = 1.0f / boxSize;
boxHalfSize[i] = boxSize * 0.5f;
}
}
template< class type, int dimension >
ID_INLINE void idVectorSet<type,dimension>::ResizeIndex( const int newSize ) {
idList<type>::Resize( newSize );
hash.ResizeIndex( newSize );
}
template< class type, int dimension >
ID_INLINE void idVectorSet<type,dimension>::Clear( void ) {
idList<type>::Clear();
hash.Clear();
}
template< class type, int dimension >
ID_INLINE int idVectorSet<type,dimension>::FindVector( const type &v, const float epsilon ) {
int i, j, k, hashKey, partialHashKey[dimension];
for ( i = 0; i < dimension; i++ ) {
assert( epsilon <= boxHalfSize[i] );
partialHashKey[i] = (int) ( ( v[i] - mins[i] - boxHalfSize[i] ) * boxInvSize[i] );
}
for ( i = 0; i < ( 1 << dimension ); i++ ) {
hashKey = 0;
for ( j = 0; j < dimension; j++ ) {
hashKey *= boxHashSize;
hashKey += partialHashKey[j] + ( ( i >> j ) & 1 );
}
for ( j = hash.First( hashKey ); j >= 0; j = hash.Next( j ) ) {
const type &lv = (*this)[j];
for ( k = 0; k < dimension; k++ ) {
if ( idMath::Fabs( lv[k] - v[k] ) > epsilon ) {
break;
}
}
if ( k >= dimension ) {
return j;
}
}
}
hashKey = 0;
for ( i = 0; i < dimension; i++ ) {
hashKey *= boxHashSize;
hashKey += (int) ( ( v[i] - mins[i] ) * boxInvSize[i] );
}
hash.Add( hashKey, idList<type>::Num() );
Append( v );
return idList<type>::Num()-1;
}
/*
===============================================================================
Vector Subset
Creates a subset without duplicates from an existing list with vectors.
===============================================================================
*/
template< class type, int dimension >
class idVectorSubset {
public:
idVectorSubset( void );
idVectorSubset( const type &mins, const type &maxs, const int boxHashSize, const int initialSize );
// returns total size of allocated memory
size_t Allocated( void ) const { return idList<type>::Allocated() + hash.Allocated(); }
// returns total size of allocated memory including size of type
size_t Size( void ) const { return sizeof( *this ) + Allocated(); }
void Init( const type &mins, const type &maxs, const int boxHashSize, const int initialSize );
void Clear( void );
// returns either vectorNum or an index to a previously found vector
int FindVector( const type *vectorList, const int vectorNum, const float epsilon );
private:
idHashIndex hash;
type mins;
type maxs;
int boxHashSize;
float boxInvSize[dimension];
float boxHalfSize[dimension];
};
template< class type, int dimension >
ID_INLINE idVectorSubset<type,dimension>::idVectorSubset( void ) {
hash.Clear( idMath::IPow( boxHashSize, dimension ), 128 );
boxHashSize = 16;
memset( boxInvSize, 0, dimension * sizeof( boxInvSize[0] ) );
memset( boxHalfSize, 0, dimension * sizeof( boxHalfSize[0] ) );
}
template< class type, int dimension >
ID_INLINE idVectorSubset<type,dimension>::idVectorSubset( const type &mins, const type &maxs, const int boxHashSize, const int initialSize ) {
Init( mins, maxs, boxHashSize, initialSize );
}
template< class type, int dimension >
ID_INLINE void idVectorSubset<type,dimension>::Init( const type &mins, const type &maxs, const int boxHashSize, const int initialSize ) {
int i;
float boxSize;
hash.Clear( idMath::IPow( boxHashSize, dimension ), initialSize );
this->mins = mins;
this->maxs = maxs;
this->boxHashSize = boxHashSize;
for ( i = 0; i < dimension; i++ ) {
boxSize = ( maxs[i] - mins[i] ) / (float) boxHashSize;
boxInvSize[i] = 1.0f / boxSize;
boxHalfSize[i] = boxSize * 0.5f;
}
}
template< class type, int dimension >
ID_INLINE void idVectorSubset<type,dimension>::Clear( void ) {
idList<type>::Clear();
hash.Clear();
}
template< class type, int dimension >
ID_INLINE int idVectorSubset<type,dimension>::FindVector( const type *vectorList, const int vectorNum, const float epsilon ) {
int i, j, k, hashKey, partialHashKey[dimension];
const type &v = vectorList[vectorNum];
for ( i = 0; i < dimension; i++ ) {
assert( epsilon <= boxHalfSize[i] );
partialHashKey[i] = (int) ( ( v[i] - mins[i] - boxHalfSize[i] ) * boxInvSize[i] );
}
for ( i = 0; i < ( 1 << dimension ); i++ ) {
hashKey = 0;
for ( j = 0; j < dimension; j++ ) {
hashKey *= boxHashSize;
hashKey += partialHashKey[j] + ( ( i >> j ) & 1 );
}
for ( j = hash.First( hashKey ); j >= 0; j = hash.Next( j ) ) {
const type &lv = vectorList[j];
for ( k = 0; k < dimension; k++ ) {
if ( idMath::Fabs( lv[k] - v[k] ) > epsilon ) {
break;
}
}
if ( k >= dimension ) {
return j;
}
}
}
hashKey = 0;
for ( i = 0; i < dimension; i++ ) {
hashKey *= boxHashSize;
hashKey += (int) ( ( v[i] - mins[i] ) * boxInvSize[i] );
}
hash.Add( hashKey, vectorNum );
return vectorNum;
}
#endif /* !__VECTORSET_H__ */