You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.1 KiB
C

#include <stdlib.h>
#ifdef BUILD_TESTS
#include <stdio.h>
#endif
#include "sarray2.h"
static void *EmptyArrayData[256];
static SparseArray EmptyArray = { 0, 0xff, (void**)&EmptyArrayData};
static void init_pointers(SparseArray * sarray)
{
sarray->data = calloc(256, sizeof(void*));
if(sarray->shift != 0)
{
for(unsigned i=0 ; i<256 ; i++)
{
sarray->data[i] = &EmptyArray;
}
}
}
SparseArray * SparseArrayNew()
{
SparseArray * sarray = calloc(1, sizeof(SparseArray));
sarray->shift = 24;
sarray->mask = 0xff000000;
init_pointers(sarray);
return sarray;
}
void * SparseArrayNext(SparseArray * sarray, uint32_t * index)
{
uint32_t j = MASK_INDEX((*index));
uint32_t max = (sarray->mask >> sarray->shift) + 1;
if(sarray->shift == 0)
{
while(j<max)
{
(*index)++;
if(sarray->data[j] != SARRAY_EMPTY)
{
return sarray->data[j];
}
j++;
}
}
else while(j<max)
{
uint32_t zeromask = ~(sarray->mask >> 8);
while(j<max)
{
//Look in child nodes
if(sarray->data[j] != SARRAY_EMPTY)
{
void * ret = SparseArrayNext(sarray->data[j], index);
if(ret != SARRAY_EMPTY)
{
return ret;
}
}
//Go to the next child
j++;
//Add 2^n to index so j is still correct
(*index) += 1<<sarray->shift;
//Zero off the next component of the index so we don't miss any.
*index &= zeromask;
}
}
return SARRAY_EMPTY;
}
void SparseArrayInsert(SparseArray * sarray, uint32_t index, void * value)
{
while(sarray->shift > 0)
{
uint32_t i = MASK_INDEX(index);
if(sarray->data[i] == &EmptyArray)
{
SparseArray * newsarray = calloc(1, sizeof(SparseArray));
newsarray->shift = sarray->shift - 8;
newsarray->mask = sarray->mask >> 8;
init_pointers(newsarray);
sarray->data[i] = newsarray;
}
sarray = sarray->data[i];
}
sarray->data[index & sarray->mask] = value;
}
void SparseArrayDestroy(SparseArray * sarray)
{
if(sarray->shift > 0)
{
uint32_t max = (sarray->mask >> sarray->shift) + 1;
for(uint32_t i=0 ; i<max ; i++)
{
SparseArrayDestroy((SparseArray*)sarray->data[i]);
}
}
free(sarray->data);
free(sarray);
}