X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;f=vector%2Fhashvector.c;h=8b88135f0b660fec87e9994cc73803cb3af09a31;hb=74eec6f62db4459232f95b5d39069b9b4ceeb830;hp=27c2d65e5d63bec9bedbe5f33ff5006599c72873;hpb=c1aae73b1fafd372c4f38a1a205e20a9f22a2fa0;p=rrq%2Frrqmisc.git diff --git a/vector/hashvector.c b/vector/hashvector.c index 27c2d65..8b88135 100644 --- a/vector/hashvector.c +++ b/vector/hashvector.c @@ -1,4 +1,5 @@ -#include "hashvector.h" +#include +#include #define SELF hv->type @@ -6,7 +7,7 @@ // to the first of holes encountered while considering collisions. // Returns a pointer to the place for the item, or 0 in case of OOM or // overfull hashvector (i.e. 0 shouldn't happen). -// If itemkey is set, then the itmekey callback function is used for +// If itemkey is set, then the itemkey callback function is used for // obtaining a temporary key from the item. static void **hashvector_find_slot( hashvector *hv, void *key, unsigned long *i, int itemkey ) @@ -55,16 +56,27 @@ static void **hashvector_find_slot( } } -// Find the keyed element, and assign the x pointer, or assign 0. -// Returns 1 if element is found and 0 otherwise. -int hashvector_find(hashvector *hv,void *key,void **x) { - unsigned long i; - void **p = hashvector_find_slot( hv, key, &i, 0 ); - if ( p && *p && *p != HV_HOLE ) { - if ( x ) { - *x = *p; +// Find the keyed element at or after the index. Update index and +// return item. +void *hashvector_next(hashvector *hv,vector_index *index,void *key) { + unsigned long i = index? *index : 0; + for ( ; i < hv->table.size; i++ ) { + void **p = vector_next_used( &hv->table, &i ); + if ( p == 0 ) { + break; + } + if ( *p && *p != HV_HOLE ) { + if ( key && hv->type->haskey( hv->type, *p, key ) == 0 ) { + continue; + } + if ( index ) { + (*index) = i; + } + return *p; } - return 1; + } + if ( index ) { + (*index) = hv->table.size; } return 0; } @@ -146,23 +158,28 @@ int hashvector_delete(hashvector *hv,void *item) { return 1; } -// Copy items into a vector. Returns 0 on success and -1 on failure. -int hashvector_contents(hashvector *hv,vector *pv) { - if ( vector_resize( pv, hv->fill, 0, 0 ) ) { - return -1; - } - unsigned long from = 0; - unsigned long to = 0; - for ( ; to < hv->fill; from++ ) { - void **slot = vector_next_used( &hv->table, &from ); - if ( slot == 0 ) { - break; - } - if ( *slot != HV_HOLE ) { - vector_set( pv, to++, *slot ); +vector *hashvector_contents( + hashvector *hv,enum vector_variant variant,vector *v) +{ + if ( v == 0 ) { + if ( hv->fill == 0 ) { + return 0; } + v = (vector*) malloc( sizeof( vector ) ); + } else { + vector_resize( v, 0, vector_clear_any, 0 ); } - return 0; + (*v) = (vector) { .variant = variant, 0, 0 }; + if ( hv->fill == 0 ) { + return v; + } + vector_resize( v, hv->fill, 0, 0 ); + vector_index i; + vector_index j = 0; + for ( i = 0; i < v->size; i++, j++ ) { + vector_set( v, i, hashvector_next( hv, &j, 0 ) ); + } + return v; } // A simple binary hashcode, (before modulo table size) @@ -174,3 +191,19 @@ unsigned long hashvector_hashcode(unsigned char *key,unsigned long n) { return value; } + +hashvector *hashvector_create(enum vector_variant variant,itemkeyfun *type) { + hashvector *hv = (hashvector*) malloc( sizeof( hashvector ) ); + (*hv) = (hashvector) { + .table = (vector) { + .variant = variant, + .size = 16, + .entries = 0 + }, + .fill = 0, + .holes = 0, + .type = type + }; + return hv; +} +