revise hashvector_contents to optionally create the target vector
[rrq/rrqmisc.git] / vector / hashvector.c
index c9c2fb3ea7e360da75553ec3efb156010eefd100..8b88135f0b660fec87e9994cc73803cb3af09a31 100644 (file)
@@ -56,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;
 }
@@ -147,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)
@@ -176,7 +192,7 @@ unsigned long hashvector_hashcode(unsigned char *key,unsigned long n) {
 }
 
 
-hashvector *hashvector_create(int variant,itemkeyfun *type) {
+hashvector *hashvector_create(enum vector_variant variant,itemkeyfun *type) {
     hashvector *hv = (hashvector*) malloc( sizeof( hashvector ) );
     (*hv) = (hashvector) {
        .table = (vector) {