X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;f=vector%2Fvector.c;h=129ba02990e8e01d03ec6364b1092ac418e654d9;hb=d8c1ccad095640b40192055bff9ad37e98216970;hp=8dadf00a440873ad7ee4e4962ee50c822b75db29;hpb=9e0cc3c3727ec7069e7f6f6ae252895308753b5a;p=rrq%2Frrqmisc.git diff --git a/vector/vector.c b/vector/vector.c index 8dadf00..129ba02 100644 --- a/vector/vector.c +++ b/vector/vector.c @@ -7,6 +7,31 @@ * void*, and an index is "unsigned long" (64 bits). */ +#if VECTOR_LEVEL_BITS == 4 +typedef union { + vector_index as_whole; + struct { + unsigned int msb:4; unsigned int lsb:4; + } __attribute__ ((__packed__)) as_byte[8]; +} vector_indexing; + +#define VECTOR_PART_BYTE(i,p) ((vector_indexing*)(i))->as_byte[ (p)/2 ] + +static int VECTOR_INDEX_PART(vector_index *index,int part) { + if ( part & 1 ) { + return VECTOR_PART_BYTE(index,part).lsb; + } + return VECTOR_PART_BYTE(index,part).msb; +} + +static int VECTOR_INDEX_PART_INC(vector_index *index,int part) { + if ( part & 1 ) { + return ++VECTOR_PART_BYTE(index,part).lsb; + } + return ++VECTOR_PART_BYTE(index,part).msb; +} +#endif + /** * Advances a vector index to the next used slot at or below the * given level, starting from the indexed entry (inclusive) and up. @@ -35,7 +60,7 @@ static void **vector_level_next_used( *p = 0; } } - if ( ++VECTOR_INDEX_PART( index, level ) == 0 ) { + if ( VECTOR_INDEX_PART_INC( index, level ) == 0 ) { break; // cycling this level => nothing found } } @@ -149,15 +174,21 @@ int vector_resize( vector_page *entries; vector_page **pp = &pv->entries; while ( level.old-- > level.new ) { - pp = (vector_page **)(*pp)[0]; + if ( pp ) { + pp = (vector_page **)(*pp)[0]; + } } if ( pp != &pv->entries ) { entries = pv->entries; - pv->entries = *pp; - *pp = 0; + if ( pp ) { + pv->entries = *pp; + *pp = 0; // Detach subtree + } else { + pv->entries = 0; + } vector_reclaim( entries, level.old ); } - if ( new_size == 0 ) { + if ( new_size == 0 && pv->entries ) { free( pv->entries ); pv->entries = 0; }