150 lines
2.3 KiB
C
150 lines
2.3 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
|