#include "vqueue.h" #include "fch_buckets.h" #include #include #include //#define DEBUG #include "debug.h" typedef struct __fch_bucket_entry_t { char * value; cmph_uint32 length; } fch_bucket_entry_t; typedef struct __fch_bucket_t { fch_bucket_entry_t * entries; cmph_uint32 capacity, size; } fch_bucket_t; static void fch_bucket_new(fch_bucket_t *bucket) { assert(bucket); bucket->size = 0; bucket->entries = NULL; bucket->capacity = 0; } static void fch_bucket_destroy(fch_bucket_t *bucket) { cmph_uint32 i; assert(bucket); for (i = 0; i < bucket->size; i++) { free((bucket->entries + i)->value); } free(bucket->entries); } static void fch_bucket_reserve(fch_bucket_t *bucket, cmph_uint32 size) { assert(bucket); if (bucket->capacity < size) { cmph_uint32 new_capacity = bucket->capacity + 1; DEBUGP("Increasing current capacity %u to %u\n", bucket->capacity, size); while (new_capacity < size) { new_capacity *= 2; } bucket->entries = (fch_bucket_entry_t *)realloc(bucket->entries, sizeof(fch_bucket_entry_t)*new_capacity); assert(bucket->entries); bucket->capacity = new_capacity; DEBUGP("Increased\n"); } } static void fch_bucket_insert(fch_bucket_t *bucket, char *val, cmph_uint32 val_length) { assert(bucket); fch_bucket_reserve(bucket, bucket->size + 1); (bucket->entries + bucket->size)->value = val; (bucket->entries + bucket->size)->length = val_length; ++(bucket->size); } static cmph_uint8 fch_bucket_is_empty(fch_bucket_t *bucket) { assert(bucket); return (cmph_uint8)(bucket->size == 0); } static cmph_uint32 fch_bucket_size(fch_bucket_t *bucket) { assert(bucket); return bucket->size; } static char * fch_bucket_get_key(fch_bucket_t *bucket, cmph_uint32 index_key) { assert(bucket); assert(index_key < bucket->size); return (bucket->entries + index_key)->value; } static cmph_uint32 fch_bucket_get_length(fch_bucket_t *bucket, cmph_uint32 index_key) { assert(bucket); assert(index_key < bucket->size); return (bucket->entries + index_key)->length; } static void fch_bucket_print(fch_bucket_t * bucket, cmph_uint32 index) { cmph_uint32 i; assert(bucket); fprintf(stderr, "Printing bucket %u ...\n", index); for (i = 0; i < bucket->size; i++) { fprintf(stderr, " key: %s\n", (bucket->entries + i)->value); } } ////////////////////////////////////////////////////////////////////////////////////// struct __fch_buckets_t { fch_bucket_t * values; cmph_uint32 nbuckets, max_size; }; fch_buckets_t * fch_buckets_new(cmph_uint32 nbuckets) { cmph_uint32 i; fch_buckets_t *buckets = (fch_buckets_t *)malloc(sizeof(fch_buckets_t)); assert(buckets); buckets->values = (fch_bucket_t *)calloc((size_t)nbuckets, sizeof(fch_bucket_t)); for (i = 0; i < nbuckets; i++) fch_bucket_new(buckets->values + i); assert(buckets->values); buckets->nbuckets = nbuckets; buckets->max_size = 0; return buckets; } cmph_uint8 fch_buckets_is_empty(fch_buckets_t * buckets, cmph_uint32 index) { assert(index < buckets->nbuckets); return fch_bucket_is_empty(buckets->values + index); } void fch_buckets_insert(fch_buckets_t * buckets, cmph_uint32 index, char * key, cmph_uint32 length) { assert(index < buckets->nbuckets); fch_bucket_insert(buckets->values + index, key, length); if (fch_bucket_size(buckets->values + index) > buckets->max_size) { buckets->max_size = fch_bucket_size(buckets->values + index); } } cmph_uint32 fch_buckets_get_size(fch_buckets_t * buckets, cmph_uint32 index) { assert(index < buckets->nbuckets); return fch_bucket_size(buckets->values + index); } char * fch_buckets_get_key(fch_buckets_t * buckets, cmph_uint32 index, cmph_uint32 index_key) { assert(index < buckets->nbuckets); return fch_bucket_get_key(buckets->values + index, index_key); } cmph_uint32 fch_buckets_get_keylength(fch_buckets_t * buckets, cmph_uint32 index, cmph_uint32 index_key) { assert(index < buckets->nbuckets); return fch_bucket_get_length(buckets->values + index, index_key); } cmph_uint32 fch_buckets_get_max_size(fch_buckets_t * buckets) { return buckets->max_size; } cmph_uint32 fch_buckets_get_nbuckets(fch_buckets_t * buckets) { return buckets->nbuckets; } cmph_uint32 * fch_buckets_get_indexes_sorted_by_size(fch_buckets_t * buckets) { cmph_uint32 i = 0; cmph_uint32 sum = 0, value; cmph_uint32 *nbuckets_size = (cmph_uint32 *) calloc((size_t)buckets->max_size + 1, sizeof(cmph_uint32)); cmph_uint32 * sorted_indexes = (cmph_uint32 *) calloc((size_t)buckets->nbuckets, sizeof(cmph_uint32)); // collect how many buckets for each size. for(i = 0; i < buckets->nbuckets; i++) nbuckets_size[fch_bucket_size(buckets->values + i)] ++; // calculating offset considering a decreasing order of buckets size. value = nbuckets_size[buckets->max_size]; nbuckets_size[buckets->max_size] = sum; for(i = (int)buckets->max_size - 1; i >= 0; i--) { sum += value; value = nbuckets_size[i]; nbuckets_size[i] = sum; } for(i = 0; i < buckets->nbuckets; i++) { sorted_indexes[nbuckets_size[fch_bucket_size(buckets->values + i)]] = (cmph_uint32)i; nbuckets_size[fch_bucket_size(buckets->values + i)] ++; } free(nbuckets_size); return sorted_indexes; } void fch_buckets_print(fch_buckets_t * buckets) { cmph_uint32 i; for (i = 0; i < buckets->nbuckets; i++) fch_bucket_print(buckets->values + i, i); } void fch_buckets_destroy(fch_buckets_t * buckets) { cmph_uint32 i; for (i = 0; i < buckets->nbuckets; i++) fch_bucket_destroy(buckets->values + i); free(buckets->values); free(buckets); }