jedi-academy/code/qcommon/fixedmap.h
2013-04-23 15:21:39 +10:00

149 lines
2.2 KiB
C++

#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++;
}
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