Initial commit.
This commit is contained in:
169
code/qcommon/fixedmap.h
Normal file
169
code/qcommon/fixedmap.h
Normal file
@@ -0,0 +1,169 @@
|
||||
#ifndef __FIXEDMAP_H
|
||||
#define __FIXEDMAP_H
|
||||
|
||||
|
||||
/*
|
||||
An STL map-like container. Quickly thrown together to replace STL maps
|
||||
in specific instances. Many gotchas. Use with caution.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
template < class T, class U >
|
||||
class VVFixedMap
|
||||
{
|
||||
private:
|
||||
struct Data {
|
||||
T data;
|
||||
U key;
|
||||
};
|
||||
|
||||
Data *items;
|
||||
unsigned int numItems;
|
||||
unsigned int maxItems;
|
||||
|
||||
VVFixedMap(void) {}
|
||||
|
||||
public:
|
||||
VVFixedMap(unsigned int maxItems)
|
||||
{
|
||||
items = new Data[maxItems];
|
||||
numItems = 0;
|
||||
this->maxItems = maxItems;
|
||||
}
|
||||
|
||||
|
||||
~VVFixedMap(void)
|
||||
{
|
||||
items -= ( maxItems - numItems );
|
||||
delete [] items;
|
||||
numItems = 0;
|
||||
}
|
||||
|
||||
|
||||
bool Insert(const T &newItem, const U &key)
|
||||
{
|
||||
Data *storage = NULL;
|
||||
|
||||
//Check for fullness.
|
||||
if(numItems >= maxItems) {
|
||||
assert( 0 );
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check for reuse.
|
||||
if(!FindUnsorted(key, storage)) {
|
||||
storage = items + numItems;
|
||||
numItems++;
|
||||
}
|
||||
else
|
||||
assert( 0 );
|
||||
|
||||
storage->data = newItem;
|
||||
storage->key = key;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Faster version of Insert(), but it doesn't check for dupes. Used
|
||||
// by the filecode cache (when we know the data we're inserting is good).
|
||||
bool InsertUnsafe(const T &newItem, const U &key)
|
||||
{
|
||||
//Check for fullness.
|
||||
if(numItems >= maxItems) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Data *storage = items + numItems;
|
||||
numItems++;
|
||||
|
||||
storage->data = newItem;
|
||||
storage->key = key;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Sort(void)
|
||||
{
|
||||
qsort(items, numItems, sizeof(Data),
|
||||
VVFixedMap< T, U >::FixedMapSorter);
|
||||
}
|
||||
|
||||
|
||||
//Binary search, items must have been sorted!
|
||||
T *Find(const U &key)
|
||||
{
|
||||
int i;
|
||||
int high;
|
||||
int low;
|
||||
|
||||
for(low = -1, high = numItems; high - low > 1; ) {
|
||||
i = (high + low) / 2;
|
||||
if(key < items[i].key) {
|
||||
high = i;
|
||||
} else if(key > items[i].key) {
|
||||
low = i;
|
||||
} else {
|
||||
return &items[i].data;
|
||||
}
|
||||
}
|
||||
|
||||
if(items[i+1].key == key) {
|
||||
return &items[i+1].data;
|
||||
} else if(items[i-1].key == key) {
|
||||
return &items[i-1].data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//Slower, but don't need to call sort first.
|
||||
T *FindUnsorted(const U &key, Data *&storage)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<numItems; i++) {
|
||||
if(items[i].key == key) {
|
||||
storage = items + i;
|
||||
return &items[i].data;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// returns the top item's data
|
||||
// and removes the item from the map
|
||||
T *Pop(void)
|
||||
{
|
||||
T* top = NULL;
|
||||
|
||||
if(numItems)
|
||||
{
|
||||
top = &items[0].data;
|
||||
items++;
|
||||
numItems--;
|
||||
}
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
|
||||
static int FixedMapSorter(const void *a, const void *b)
|
||||
{
|
||||
if(((Data*)a)->key > ((Data*)b)->key) {
|
||||
return 1;
|
||||
} else if(((Data*)a)->key == ((Data*)b)->key) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user