int main(int argc, char **argv) { int i, len, res; struct htable *table; table = htable_new(16, 0, &htable_cstring_cmpfn, &string_copyfn, &string_freefn); assert(table != NULL); len = sizeof(string_data)/sizeof(string_data[0]); for (i = 0; i < 4; i++) { res = htable_add(table, strlen(string_data[i]), string_data[i], NULL); assert(res == 1); assert(strcmp(table->entries[i]->key, string_data[i]) == 0); } assert(htable_resize(table, 0, 1024) == 1); for (i = 4; i < len; i++) { res = htable_add(table, strlen(string_data[i]), string_data[i], NULL); assert(res == 1); assert(strcmp(table->entries[i]->key, string_data[i]) == 0); } assert(htable_resize(table, 0, 512) == 1); for (i = 0; i < len; i++) { assert(strcmp(table->entries[i]->key, string_data[i]) == 0); } htable_delete(table); return 0; }
int main(int argc, char **argv) { struct htable ht; foobar_t *foo; foobar_t *ret; htable_init(&ht, rehash, NULL); foo = malloc(sizeof(foobar_t)); foo->name = strdup("fumier"); foo->blah = 123; htable_add(&ht, hash_string(foo->name), foo); ret = (foobar_t *)htable_get(&ht, hash_string("gugus"), streq, "gugus"); if (ret) { printf("Found\n"); } else { printf("Not found\n"); } free(foo->name); free(foo); return 0; }
int faup_snapshot_value_count_append(faup_snapshot_item_t *item, char *value) { faup_snapshot_value_count_t *vc; if (!item) { fprintf(stderr, "Cannot append value '%s' to item\n", value); return -1; } /* printf("Adding value '%s' to the item '%s'\n", item->key, value); */ vc = faup_snapshot_value_count_get(item, value); if (!vc) { vc = faup_snapshot_value_count_new(); vc->value = strdup(value); vc->first_time_seen = vc->last_time_seen = time(NULL); vc->count++; htable_add(&item->values, hash_string(vc->value), vc); item->length++; } else { vc->count++; vc->last_time_seen = time(NULL); } return 0; }
static struct trace *add_trace(const char *condstr, const char *file, unsigned int line, bool expect) { struct trace *trace = malloc(sizeof(*trace)); init_trace(trace, condstr, file, line, expect); htable_add(htable, hash_trace(trace), trace); return trace; }
int get_ip_leases(main_server_st* s, struct proc_st* proc) { int ret; char buf[128]; if (proc->ipv4 == NULL) { ret = get_ipv4_lease(s, proc); if (ret < 0) return ret; if (proc->ipv4) { if (htable_add(&s->ip_leases.ht, rehash(proc->ipv4, NULL), proc->ipv4) == 0) { mslog(s, proc, LOG_ERR, "could not add IPv4 lease to hash table."); return -1; } } } if (proc->ipv6 == NULL) { ret = get_ipv6_lease(s, proc); if (ret < 0) return ret; if (proc->ipv6) { if (htable_add(&s->ip_leases.ht, rehash(proc->ipv6, NULL), proc->ipv6) == 0) { mslog(s, proc, LOG_ERR, "could not add IPv6 lease to hash table."); return -1; } } } if (proc->ipv4 == 0 && proc->ipv6 == 0) { mslog(s, proc, LOG_ERR, "no IPv4 or IPv6 addresses are configured. Cannot obtain lease."); return -1; } if (proc->ipv4) mslog(s, proc, LOG_INFO, "assigned IPv4 to '%s': %s", proc->username, human_addr((void*)&proc->ipv4->rip, proc->ipv4->rip_len, buf, sizeof(buf))); if (proc->ipv6) mslog(s, proc, LOG_INFO, "assigned IPv6 to '%s': %s", proc->username, human_addr((void*)&proc->ipv6->rip, proc->ipv6->rip_len, buf, sizeof(buf))); return 0; }
void hh_add_dep(value ocaml_dep) { unsigned long dep = Long_val(ocaml_dep); unsigned long hash = (dep >> 31) * (dep & ((1l << 31) - 1)); if(!htable_add(deptbl_bindings, hash, hash)) { return; } htable_add(deptbl, dep >> 31, dep); }
static void refill_vals(struct htable *ht, const uint64_t val[], unsigned int num) { uint64_t i; for (i = 0; i < num; i++) { if (htable_get(ht, hash(&i, NULL), objcmp, &i)) continue; htable_add(ht, hash(&val[i], NULL), &val[i]); } }
void hh_add_dep(value ocaml_dep) { CAMLparam1(ocaml_dep); uint64_t dep = Long_val(ocaml_dep); unsigned long hash = (dep >> 31) * (dep & ((1ul << 31) - 1)); if(!htable_add(deptbl_bindings, hash, hash)) { CAMLreturn0; } htable_add(deptbl, dep >> 31, dep); CAMLreturn0; }
/** * @fn _Bool virtual_cache_update(virtual_cache_t vc, cache_item_name_t name, cache_item_load_fct cache_item_load, struct cache_item_data_s *body) * @brief Update a cache item and add if the item is not found. * @param vc The virtual cache pointer. * @param name The item name. * @param cache_item_load The load callback. * @param body The output result.(free(item->data) is required) * @return false if the function failed, true else. */ _Bool virtual_cache_update(virtual_cache_t vc, cache_item_name_t name, cache_item_load_fct cache_item_load, struct cache_item_data_s *body) { struct virtual_cache_s *v = (struct virtual_cache_s*)vc; virtual_cache_item_t *item; struct cache_item_data_s temp; if(!v || !body) return false; body->data = NULL, body->length = -1; if (strlen(name) == 0) { if(v->enable_logs) logger(LOG_ERR, "virtual_cache_update -> Null or empty item name\n"); return false; } if (virtual_cache_contains_key(vc, name)) { item = htable_lookup(v->table, name); if(v->enable_logs) logger(LOG_DEBUG, "virtual_cache_update -> Load item %s from cache, item size %ld bytes\n", name, virtual_cache_item_get_item_length(item)); virtual_cache_decrement_counts(vc); virtual_cache_item_update_count(item); virtual_cache_item_get_item(item, body); if (body->data == NULL) { if(v->enable_logs) logger(LOG_ERR, "virtual_cache_update -> Unable to load item %s from cache\n", name); return false; } return true; } else {// item not found. bzero(&temp, sizeof(struct cache_item_data_s)); cache_item_load(name, &temp); if(v->enable_logs) logger(LOG_DEBUG, "virtual_cache_update -> Load item %s from resources, item size %ld bytes\n", name, temp.length); if (!temp.data) { if(v->enable_logs) logger(LOG_ERR, "virtual_cache_update -> Unable to load item %s from resources\n", name); return false; } if(virtual_cache_can_cache(vc, name)) { item = virtual_cache_item_new(name, temp); free(temp.data); virtual_cache_decrement_counts(vc); virtual_cache_item_update_count(item); htable_add(v->table, name, item, sizeof(virtual_cache_item_t)); virtual_cache_item_get_item(item, body); } else { body->length = temp.length; body->data = malloc(temp.length + 1); bzero(body->data, temp.length + 1); memcpy(body->data, temp.data, temp.length); } return true; } }
static void register_first_touch(int pid, void * start_of_page) { size_t hash = hash_pointer(start_of_page, 0); /* Is this the first time we touch this page ? */ ft_entry * t = htable_get(&firsttouch, hash, ptrequ, start_of_page); /* If not record the touching thread to the firsttouch htable */ if (!t) { t = malloc(sizeof(ft_entry)); t->tid = pid; t->start_of_page = start_of_page; htable_add(&firsttouch, hash, t); debug_print("First touch by %d detected at %p\n", pid, start_of_page); } ft_entry * x = htable_get(&firsttouch, hash, ptrequ, start_of_page); }
void opt_insert(int old_container_id, int chunk_size){ ReferItem * rf=htable_lookup(scan_htable,&old_container_id); if(rf) { rf->size+=chunk_size; rf->count++; } else{ rf=(ReferItem *)malloc(sizeof(ReferItem)); rf->size=chunk_size; rf->container_id=old_container_id; rf->count=1; rf->rewrite=0; htable_add(scan_htable,&rf->container_id,rf); } }
client_entry_st *new_client_entry(sec_mod_st *sec, const char *ip) { struct htable *db = sec->client_db; client_entry_st *e, *te; int ret; int retries = 3; e = talloc_zero(db, client_entry_st); if (e == NULL) { return NULL; } strlcpy(e->auth_info.remote_ip, ip, sizeof(e->auth_info.remote_ip)); do { ret = gnutls_rnd(GNUTLS_RND_RANDOM, e->sid, sizeof(e->sid)); if (ret < 0) { seclog(sec, LOG_ERR, "error generating SID"); goto fail; } /* check if in use */ te = find_client_entry(sec, e->sid); } while(te != NULL && retries-- >= 0); if (te != NULL) { seclog(sec, LOG_ERR, "could not generate a unique SID!"); goto fail; } base64_encode((char *)e->sid, SID_SIZE, (char *)e->auth_info.psid, sizeof(e->auth_info.psid)); e->time = time(0); if (htable_add(db, rehash(e, NULL), e) == 0) { seclog(sec, LOG_ERR, "could not add client entry to hash table"); goto fail; } return e; fail: talloc_free(e); return NULL; }
void test_memory_copy() { int i, len, res; struct htable *table; table = htable_new(512, 0, &htable_cstring_cmpfn, &string_copyfn, &string_freefn); assert(table != NULL); len = sizeof(string_data)/sizeof(string_data[0]); for (i = 0; i < len; i++) { res = htable_add(table, strlen(string_data[i]), string_data[i], NULL); assert(res == 1); assert(strcmp((char *)table->entries[i]->key, string_data[i]) == 0); } htable_delete(table); }
static struct aga_node *nr_to_n(struct agar_state *sr, const void *nr) { struct agar_node *nn; size_t hash = hash_pointer(nr, HASH_BASE); bool rc; nn = htable_get(&sr->nodes, hash, agar_node_cmp, nr); if (!nn) { nn = tal(sr, struct agar_node); assert(nn); nn->nr = nr; aga_node_init(&nn->n); rc = htable_add(&sr->nodes, hash, nn); assert(rc); }
int handle_resume_store_req(main_server_st * s, struct proc_st *proc, const SessionResumeStoreReqMsg * req) { tls_cache_st *cache; size_t key; unsigned int max; if (req->session_id.len > GNUTLS_MAX_SESSION_ID) return -1; if (req->session_data.len > MAX_SESSION_DATA_SIZE) return -1; max = MAX(2 * s->config->max_clients, DEFAULT_MAX_CACHED_TLS_SESSIONS); if (s->tls_db.entries >= max) { mslog(s, NULL, LOG_INFO, "maximum number of stored TLS sessions reached (%u)", max); need_maintenance = 1; return -1; } key = hash_any(req->session_id.data, req->session_id.len, 0); cache = talloc(s->tls_db.ht, tls_cache_st); if (cache == NULL) return -1; cache->session_id_size = req->session_id.len; cache->session_data_size = req->session_data.len; cache->remote_addr_len = proc->remote_addr_len; memcpy(cache->session_id, req->session_id.data, req->session_id.len); memcpy(cache->session_data, req->session_data.data, req->session_data.len); memcpy(&cache->remote_addr, &proc->remote_addr, proc->remote_addr_len); htable_add(s->tls_db.ht, key, cache); s->tls_db.entries++; mslog_hex(s, proc, LOG_DEBUG, "TLS session DB storing", req->session_id.data, req->session_id.len, 0); return 0; }
static void add_vals(struct htable *ht, const uint64_t val[], unsigned int off, unsigned int num) { uint64_t i; for (i = off; i < off+num; i++) { if (htable_get(ht, hash(&i, NULL), objcmp, &i)) { fail("%llu already in hash", (long long)i); return; } htable_add(ht, hash(&val[i], NULL), &val[i]); if (htable_get(ht, hash(&i, NULL), objcmp, &i) != &val[i]) { fail("%llu not added to hash", (long long)i); return; } } pass("Added %llu numbers to hash", (long long)i); }
static void add_forkserv_pages(L4_Word_t start, L4_Word_t end) { for(L4_Word_t addr = start & ~PAGE_MASK; addr <= (end | PAGE_MASK); addr += PAGE_SIZE) { size_t hash = int_hash(addr); void *ptr = htable_get(&forkserv_pages, hash, &forkserv_page_cmp, &addr); if(ptr == NULL) { struct forkserv_page *p = malloc(sizeof(*p)); p->address = addr; if(!htable_add(&forkserv_pages, hash, p)) { fprintf(stderr, "htable_add() failed\n"); abort(); } } } }
int main(int argc, char **argv) { int i, len, res; struct htable *table; table = htable_new(512, 0, &htable_int32_cmpfn, ©fn, &freefn); assert(table != NULL); len = sizeof(data)/sizeof(data[0]); for (i = 0; i < len; i++) { res = htable_add(table, 4, &data[i], NULL); assert(res == 1); assert(*(int*)table->entries[i]->key == data[i]); } htable_delete(table); return 0; }
int main(int argc, char *argv[]) { struct htable ht; uint64_t val[NUM_VALS]; unsigned int i; plan_tests((NUM_VALS) * 2); for (i = 0; i < NUM_VALS; i++) val[i] = i; htable_init(&ht, hash, NULL); for (i = 0; i < NUM_VALS; i++) { ok1(ht.max >= i); ok1(ht.max <= i * 2); htable_add(&ht, hash(&val[i], NULL), &val[i]); } htable_clear(&ht); return exit_status(); }
void hh_load_dep_table(value in_filename) { CAMLparam1(in_filename); struct timeval tv; gettimeofday(&tv, NULL); FILE* fp = fopen(String_val(in_filename), "rb"); if (fp == NULL) { unix_error(errno, "fopen", in_filename); } fread_header(fp); int compressed_size = 0; read_all(fileno(fp), (void*)&compressed_size, sizeof compressed_size); char* compressed = malloc(compressed_size * sizeof(char)); assert(compressed != NULL); read_all(fileno(fp), compressed, compressed_size * sizeof(char)); int actual_compressed_size = LZ4_decompress_fast( compressed, (char*)deptbl, DEP_SIZE_B); assert(compressed_size == actual_compressed_size); tv = log_duration("Loading file", tv); uintptr_t slot = 0; unsigned long hash = 0; for (slot = 0; slot < DEP_SIZE; ++slot) { hash = deptbl[slot]; if (hash != 0) { htable_add(deptbl_bindings, hash, hash); } } fclose(fp); log_duration("Bindings", tv); CAMLreturn0; }
static void check_addr(void *ip, void *addr) { if (!inst_enable) return; address *new_addr = (address*)malloc(sizeof(*new_addr)); *new_addr = (address)addr; size_t new_addr_hash = addr_hash(new_addr, NULL); if (htable_get(&addresses, new_addr_hash, cmp, new_addr)) { if (instr_count > max_instr_count) { max_instr_count = instr_count; instr_count = 0; } htable_clear(&addresses); } htable_add(&addresses, new_addr_hash, new_addr); }
struct inode * kfs_link(struct inode *target, struct inode *parent, const char *name) { struct inode *link; dbg("name=`%s`\n",name); #if 0 char p1[2048], p2[2048]; *p1 = 0; get_full_path(parent, p1); *p2 = 0; get_full_path(target, p2); printk("linking %s%s -> %s\n", p1, name, p2); #endif if(NULL != htable_lookup( parent->files, name )) { printk(KERN_WARNING "link exists.\n"); return NULL; } link = kfs_create_inode(); if(NULL == link) return NULL; strncpy(link->name, name, sizeof(link->name)); link->name[sizeof(link->name) - 1] = '\0'; link->mode = 0666 | S_IFLNK; if(S_ISDIR(target->mode)) link->mode |= 0111; link->link_target = target; link->parent = parent; htable_add(parent->files, link); return link; }
int kmscon_hashtable_insert(struct kmscon_hashtable *tbl, void *key, void *value) { struct kmscon_hashentry *entry; size_t hash; if (!tbl) return -EINVAL; entry = malloc(sizeof(*entry)); if (!entry) return -ENOMEM; entry->key = key; entry->value = value; hash = tbl->hash_cb(key); if (!htable_add(&tbl->tbl, hash, entry)) { free(entry); return -ENOMEM; } return 0; }
static void gdbio_htable_add(struct gdbio_state *gs){ spin_lock(&htable_lock); htable_add(gdbio_htable, gs); spin_unlock(&htable_lock); }
int faup_snapshot_value_count_append_object(faup_snapshot_item_t *item, faup_snapshot_value_count_t *vc) { htable_add(&item->values, hash_string(vc->value), vc); item->length++; }
struct inode * kfs_mkdirent(struct inode * parent, const char * name, const struct inode_operations * i_ops, const struct kfs_fops * f_ops, unsigned mode, void * priv, size_t priv_len) { char buf[MAX_PATHLEN]; if ( parent ) { get_full_path(parent, buf); } dbg( "name=`%s/%s`\n", buf, name ); struct inode * inode = NULL; int new_entry = 0; if(parent) { if(parent->link_target) parent = parent->link_target; if(!S_ISDIR(parent->mode)) { printk(KERN_WARNING "%s is not a directory.\n", name); return NULL; } } // Try a lookup in the parent first, then allocate a new file if( parent && name ) inode = htable_lookup( parent->files, name ); if( !inode ) { inode = kfs_create_inode(); if (!inode) return NULL; new_entry = 1; } #if 0 else { printk( KERN_WARNING "%s: '%s' already exists\n", __func__, name ); } #endif // If this is a new allocation, create the directory table // \todo Do this only when a sub-file is created if( !inode->files && S_ISDIR(mode) ) inode->files = htable_create(7, offsetof( struct inode, name ), offsetof( struct inode, ht_link ), kfs_hash_filename, kfs_compare_filename); // \todo This will overwrite any existing file; should it warn? inode->parent = parent; inode->i_fop = f_ops; inode->i_op = i_ops; inode->priv = priv; inode->priv_len = priv_len; inode->mode = mode; if ( i_ops && i_ops->create ) { if ( i_ops->create( inode, mode ) ) { printk("%s:%d() ????\n",__FUNCTION__,__LINE__); return NULL; } } /* note: refs is initialized to 0 in kfs_create_inode() */ if( name ) { // Copy up to the first / or nul, stopping before we over run int offset = 0; while( *name && *name != '/' && offset < sizeof(inode->name)-1 ) inode->name[offset++] = *name++; inode->name[offset] = '\0'; } if( parent && new_entry ) htable_add( parent->files, inode ); return inode; }
int main(int argc, char *argv[]) { unsigned int i; struct htable_obj ht, ht2; struct obj val[NUM_VALS], *result; unsigned int dne; void *p; struct htable_obj_iter iter; plan_tests(29); for (i = 0; i < NUM_VALS; i++) val[i].key = i; dne = i; htable_obj_init(&ht); ok1(ht.raw.max == 0); ok1(ht.raw.bits == 0); /* We cannot find an entry which doesn't exist. */ ok1(!htable_obj_get(&ht, &dne)); /* Fill it, it should increase in size. */ add_vals(&ht, val, NUM_VALS); ok1(ht.raw.bits == NUM_BITS + 1); ok1(ht.raw.max < (1 << ht.raw.bits)); /* Mask should be set. */ ok1(ht.raw.common_mask != 0); ok1(ht.raw.common_mask != -1); ok1(check_mask(&ht.raw, val, NUM_VALS)); /* Find all. */ find_vals(&ht, val, NUM_VALS); ok1(!htable_obj_get(&ht, &dne)); /* Walk once, should get them all. */ i = 0; for (p = htable_obj_first(&ht,&iter); p; p = htable_obj_next(&ht, &iter)) i++; ok1(i == NUM_VALS); i = 0; for (p = htable_obj_prev(&ht,&iter); p; p = htable_obj_prev(&ht, &iter)) i++; ok1(i == NUM_VALS); /* Delete all. */ del_vals(&ht, val, NUM_VALS); ok1(!htable_obj_get(&ht, &val[0].key)); /* Worst case, a "pointer" which doesn't have any matching bits. */ htable_add(&ht.raw, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]); htable_obj_add(&ht, &val[NUM_VALS-1]); ok1(ht.raw.common_mask == 0); ok1(ht.raw.common_bits == 0); /* Delete the bogus one before we trip over it. */ htable_del(&ht.raw, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]); /* Add the rest. */ add_vals(&ht, val, NUM_VALS-1); /* Check we can find them all. */ find_vals(&ht, val, NUM_VALS); ok1(!htable_obj_get(&ht, &dne)); /* Check copy. */ ok1(htable_obj_copy(&ht2, &ht)); /* Delete them all by key. */ del_vals_bykey(&ht, val, NUM_VALS); del_vals_bykey(&ht2, val, NUM_VALS); /* Write two of the same value. */ val[1] = val[0]; htable_obj_add(&ht, &val[0]); htable_obj_add(&ht, &val[1]); i = 0; result = htable_obj_getfirst(&ht, &i, &iter); ok1(result == &val[0] || result == &val[1]); if (result == &val[0]) { ok1(htable_obj_getnext(&ht, &i, &iter) == &val[1]); ok1(htable_obj_getnext(&ht, &i, &iter) == NULL); /* Deleting first should make us iterate over the other. */ ok1(htable_obj_del(&ht, &val[0])); ok1(htable_obj_getfirst(&ht, &i, &iter) == &val[1]); ok1(htable_obj_getnext(&ht, &i, &iter) == NULL); } else { ok1(htable_obj_getnext(&ht, &i, &iter) == &val[0]); ok1(htable_obj_getnext(&ht, &i, &iter) == NULL); /* Deleting first should make us iterate over the other. */ ok1(htable_obj_del(&ht, &val[1])); ok1(htable_obj_getfirst(&ht, &i, &iter) == &val[0]); ok1(htable_obj_getnext(&ht, &i, &iter) == NULL); } htable_obj_clear(&ht); htable_obj_clear(&ht2); return exit_status(); }
static void plain_group_list(void *pool, void *additional, char ***groupname, unsigned *groupname_size) { FILE *fp; char line[512]; ssize_t ll; char *p, *sp; unsigned i; size_t hval; struct htable_iter iter; char *tgroup[MAX_GROUPS]; unsigned tgroup_size; struct htable hash; struct plain_cfg_st *config = additional; htable_init(&hash, rehash, NULL); pool = talloc_init("plain"); fp = fopen(config->passwd, "r"); if (fp == NULL) { syslog(LOG_AUTH, "error in plain authentication; cannot open: %s", (char*)config->passwd); return; } line[sizeof(line)-1] = 0; while ((p=fgets(line, sizeof(line)-1, fp)) != NULL) { ll = strlen(p); if (ll <= 4) continue; if (line[ll - 1] == '\n') { ll--; line[ll] = 0; } if (line[ll - 1] == '\r') { ll--; line[ll] = 0; } #ifdef HAVE_STRSEP sp = line; p = strsep(&sp, ":"); if (p != NULL) { p = strsep(&sp, ":"); #else p = strtok_r(line, ":", &sp); if (p != NULL) { p = strtok_r(NULL, ":", &sp); #endif if (p != NULL) { break_group_list(pool, p, tgroup, &tgroup_size); for (i=0; i<tgroup_size; i++) { hval = rehash(tgroup[i], NULL); if (htable_get(&hash, hval, str_cmp, tgroup[i]) == NULL) { if (strlen(tgroup[i]) > 1) htable_add(&hash, hval, tgroup[i]); } } } } } *groupname_size = 0; *groupname = talloc_size(pool, sizeof(char*)*MAX_GROUPS); if (*groupname == NULL) { goto exit; } p = htable_first(&hash, &iter); while (p != NULL && (*groupname_size) < MAX_GROUPS) { (*groupname)[(*groupname_size)] = talloc_strdup(*groupname, p); p = htable_next(&hash, &iter); (*groupname_size)++; } /* always succeed */ exit: htable_clear(&hash); safe_memset(line, 0, sizeof(line)); fclose(fp); return; } const struct auth_mod_st plain_auth_funcs = { .type = AUTH_TYPE_PLAIN | AUTH_TYPE_USERNAME_PASS, .allows_retries = 1, .global_init = plain_global_init, .auth_init = plain_auth_init, .auth_deinit = plain_auth_deinit, .auth_msg = plain_auth_msg, .auth_pass = plain_auth_pass, .auth_user = plain_auth_user, .auth_group = plain_auth_group, .group_list = plain_group_list };
int main(int argc, char *argv[]) { unsigned int i; uintptr_t perfect_bit; struct htable ht; uint64_t val[NUM_VALS]; uint64_t dne; void *p; struct htable_iter iter; plan_tests(29); for (i = 0; i < NUM_VALS; i++) val[i] = i; dne = i; htable_init(&ht, hash, NULL); ok1(ht.max == 0); ok1(ht.bits == 0); /* We cannot find an entry which doesn't exist. */ ok1(!htable_get(&ht, hash(&dne, NULL), objcmp, &dne)); /* This should increase it once. */ add_vals(&ht, val, 0, 1); ok1(ht.bits == 1); ok1(ht.max == 1); ok1(ht.common_mask == -1); /* Mask should be set. */ ok1(check_mask(&ht, val, 1)); /* This should increase it again. */ add_vals(&ht, val, 1, 1); ok1(ht.bits == 2); ok1(ht.max == 3); /* Mask should be set. */ ok1(ht.common_mask != 0); ok1(ht.common_mask != -1); ok1(check_mask(&ht, val, 2)); /* Now do the rest. */ add_vals(&ht, val, 2, NUM_VALS - 2); /* Find all. */ find_vals(&ht, val, NUM_VALS); ok1(!htable_get(&ht, hash(&dne, NULL), objcmp, &dne)); /* Walk once, should get them all. */ i = 0; for (p = htable_first(&ht,&iter); p; p = htable_next(&ht, &iter)) i++; ok1(i == NUM_VALS); /* Delete all. */ del_vals(&ht, val, NUM_VALS); ok1(!htable_get(&ht, hash(&val[0], NULL), objcmp, &val[0])); /* Worst case, a "pointer" which doesn't have any matching bits. */ htable_add(&ht, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]); htable_add(&ht, hash(&val[NUM_VALS-1], NULL), &val[NUM_VALS-1]); ok1(ht.common_mask == 0); ok1(ht.common_bits == 0); /* Get rid of bogus pointer before we trip over it! */ htable_del(&ht, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]); /* Add the rest. */ add_vals(&ht, val, 0, NUM_VALS-1); /* Check we can find them all. */ find_vals(&ht, val, NUM_VALS); ok1(!htable_get(&ht, hash(&dne, NULL), objcmp, &dne)); /* Corner cases: wipe out the perfect bit using bogus pointer. */ htable_clear(&ht); htable_add(&ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1])); ok1(ht.perfect_bit); perfect_bit = ht.perfect_bit; htable_add(&ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1] | perfect_bit)); ok1(ht.perfect_bit == 0); htable_del(&ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1] | perfect_bit)); /* Enlarging should restore it... */ add_vals(&ht, val, 0, NUM_VALS-1); ok1(ht.perfect_bit != 0); htable_clear(&ht); return exit_status(); }