mirror of
https://github.com/id-Software/DOOM-3.git
synced 2026-03-20 08:59:56 +01:00
hello world
This commit is contained in:
520
neo/idlib/containers/BTree.h
Normal file
520
neo/idlib/containers/BTree.h
Normal 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__ */
|
||||
138
neo/idlib/containers/BinSearch.h
Normal file
138
neo/idlib/containers/BinSearch.h
Normal 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__ */
|
||||
155
neo/idlib/containers/HashIndex.cpp
Normal file
155
neo/idlib/containers/HashIndex.cpp
Normal 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);
|
||||
}
|
||||
405
neo/idlib/containers/HashIndex.h
Normal file
405
neo/idlib/containers/HashIndex.h
Normal 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__ */
|
||||
404
neo/idlib/containers/HashTable.h
Normal file
404
neo/idlib/containers/HashTable.h
Normal 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__ */
|
||||
362
neo/idlib/containers/Hierarchy.h
Normal file
362
neo/idlib/containers/Hierarchy.h
Normal 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__ */
|
||||
343
neo/idlib/containers/LinkList.h
Normal file
343
neo/idlib/containers/LinkList.h
Normal 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
950
neo/idlib/containers/List.h
Normal 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__ */
|
||||
81
neo/idlib/containers/PlaneSet.h
Normal file
81
neo/idlib/containers/PlaneSet.h
Normal 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__ */
|
||||
88
neo/idlib/containers/Queue.h
Normal file
88
neo/idlib/containers/Queue.h
Normal 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__ */
|
||||
86
neo/idlib/containers/Stack.h
Normal file
86
neo/idlib/containers/Stack.h
Normal 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__ */
|
||||
548
neo/idlib/containers/StaticList.h
Normal file
548
neo/idlib/containers/StaticList.h
Normal 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__ */
|
||||
204
neo/idlib/containers/StrList.h
Normal file
204
neo/idlib/containers/StrList.h
Normal 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__ */
|
||||
228
neo/idlib/containers/StrPool.h
Normal file
228
neo/idlib/containers/StrPool.h
Normal 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__ */
|
||||
270
neo/idlib/containers/VectorSet.h
Normal file
270
neo/idlib/containers/VectorSet.h
Normal 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__ */
|
||||
Reference in New Issue
Block a user