void census_ht_insert(census_ht *ht, census_ht_key key, void *data) { gpr_int32 idx = find_bucket_idx(ht, key); ht_entry *ptr = NULL; entry_locator loc = ht_find(ht, key); if (loc.found) { /* Replace old value with new value. */ ptr = loc.is_first_in_chain ? ht->buckets[loc.bucket_idx].next : loc.prev_entry->next; if (ht->options.delete_data != NULL) { ht->options.delete_data(ptr->data); } ptr->data = data; return; } /* first entry in the table. */ if (ht->size == 0) { ht->buckets[idx].next_non_empty_bucket = -1; ht->buckets[idx].prev_non_empty_bucket = -1; ht->first_non_empty_bucket = idx; ht->last_non_empty_bucket = idx; } else if (ht->buckets[idx].next == NULL) { /* first entry in the bucket. */ ht->buckets[ht->last_non_empty_bucket].next_non_empty_bucket = idx; ht->buckets[idx].prev_non_empty_bucket = ht->last_non_empty_bucket; ht->buckets[idx].next_non_empty_bucket = -1; ht->last_non_empty_bucket = idx; } ptr = (ht_entry *)gpr_malloc(sizeof(ht_entry)); ptr->key = key; ptr->data = data; ptr->next = ht->buckets[idx].next; ht->buckets[idx].next = ptr; ht->size++; }
/* Modifies interpolated data. * * Finds point* pd in the underlying Delaunay triangulation such that * pd->x = p->x and pd->y = p->y, and copies p->z to pd->z. Exits with error * if the point is not found. * * @param nnhpi Natural Neighbours hashing point interpolator * @param p New data */ void nnhpi_modify_data(nnhpi* nnhpi, point* p) { point* orig = ht_find(nnhpi->ht_data, p); assert(orig != NULL); orig->z = p->z; }
int main (int argc, char **argv) { if (argc != 3) { printf("Error on usage: %s <key> <value>\n", argv[0]); return EXIT_FAILURE; } char *key = argv[1]; char *value = argv[2]; // testing add function ht_add(key, value); ht_add("my", "diego"); ht_add("baby", "looks"); ht_add("rocks", "great!"); printf("- Entity added for key %s is %s.\n", key, ht_find(key)); // printing function printf("\nPrinting all entries:\n"); ht_print(); // testing remove function printf("\n- Trying to remove entry for key %s: %s.\n", key, (ht_remove(key) ? "done" : "fail")); // printing function printf("\nPrinting all entries:\n"); ht_print(); return EXIT_SUCCESS; }
void census_ht_erase(census_ht *ht, census_ht_key key) { entry_locator loc = ht_find(ht, key); if (loc.found == 0) { /* noop if not found */ return; } ht->size--; if (loc.is_first_in_chain) { bucket *b = &ht->buckets[loc.bucket_idx]; GPR_ASSERT(b->next != NULL); /* The only entry in the bucket */ if (b->next->next == NULL) { int prev = b->prev_non_empty_bucket; int next = b->next_non_empty_bucket; if (prev != -1) { ht->buckets[prev].next_non_empty_bucket = next; } else { ht->first_non_empty_bucket = next; } if (next != -1) { ht->buckets[next].prev_non_empty_bucket = prev; } else { ht->last_non_empty_bucket = prev; } } REMOVE_NEXT(&ht->options, b); } else { GPR_ASSERT(loc.prev_entry->next != NULL); REMOVE_NEXT(&ht->options, loc.prev_entry); } }
int hash_table_exists(SExp h, SExp key) { SHash* p; HashEntry* e; type_check(h, &TSHash); p = h.hash; e = ht_find(&p->ht, key.p); return e != NULL; }
SExp intern(const char* name) { HashEntry* e = ht_find(&s_symbol_table, name); if (e != NULL) { return ptr2s(e->val); } else { return exec_intern(name); } }
void *census_ht_find(const census_ht *ht, census_ht_key key) { entry_locator loc = ht_find(ht, key); if (loc.found == 0) { return NULL; } return loc.is_first_in_chain ? ht->buckets[loc.bucket_idx].next->data : loc.prev_entry->next->data; }
R_API RAnalBlock * r_anal_state_search_bb(RAnalState* state, ut64 addr) { /* * Return 0 if no rehash is needed, otherwise return 1 */ const char *key = sdb_fmt (0, "0x%08"PFMT64x, addr); RAnalBlock *tmp_bb = ht_find (state->ht, key, NULL); return tmp_bb; }
void* r_set_contains( struct r_set const* set, void const* cmp ) { set_dbg("Check whether set %p contains element which compares to %p", (void*) set, (void*) cmp); return ht_find(&set->ht, cmp, set->cfg); }
block_t *cache_get(cache_t *cache, uint64_t blkno){ block_t *block = NULL; pthread_mutex_lock(&cache->ca_lock); if (!ht_find(cache->ca_ht, &blkno, (void *)block)) // block is in the cache goto got_block; // it's not in the cache, so we need to read it in from disk if ((cache->ca_currsz + sizeof(block_t) + cache->ca_blksz) < cache->ca_maxsz) { // we're not at max size yet, so allocate some more memory block = malloc(sizeof(block_t)); if (block == NULL) { printf("malloc() error\n"); goto fail; } memset(block, 0, sizeof(block_t)); pthread_rwlock_init(&block->bl_lock, NULL); block->bl_blkno = blkno; block->bl_refcnt = 0; block->bl_data = malloc(cache->ca_blksz); if (block->bl_data == NULL) { printf("malloc() error\n"); goto fail; } // XXX shouldn't hold ca_lock over the pread.. set a flag on block and use condition variable to synchronize if (pread(cache->ca_fd, block->bl_data, cache->ca_blksz, blkno * cache->ca_blksz) != cache->ca_blksz) { printf("pread() error\n"); goto fail; } } else { // we're at max size, so we need to evict someone printf("cache eviction not yet supported\n"); goto fail; } got_block: if (block->bl_refcnt == 0) // remove it from the free list ll_remove(cache->ca_free_list, (void *)&blkno, LL_NO_FREE); // XXX don't do this if you just alloc'd it.. block->bl_refcnt++; pthread_mutex_unlock(&cache->ca_lock); return block; fail: printf("something failed and your code doesn't deal with failure yet..\n"); pthread_mutex_unlock(&cache->ca_lock); return block; }
/** * Saffire method: Returns object stored at "key" inside the hash (or NULL when not found) */ SAFFIRE_METHOD(hash, find) { t_string_object *key; if (! object_parse_arguments(SAFFIRE_METHOD_ARGS, "s", &key)) { saffire_warning("Error while parsing argument list\n"); RETURN_NUMERICAL(0); } t_object *obj = ht_find(self->ht, key->value); if (obj == NULL) RETURN_NULL; RETURN_OBJECT(obj); }
void hash_table_put(SExp h, SExp key, SExp val) { SHash* p; HashEntry* e; type_check(h, &TSHash); p = h.hash; e = ht_find(&p->ht, key.p); if (e != NULL) { e->val = S2PTR(val); } else { ht_add_direct(&p->ht, key.p, val.p); } }
SExp hash_table_get(SExp h, SExp key) { SHash* p; HashEntry* e; type_check(h, &TSHash); p = h.hash; e = ht_find(&p->ht, key.p); if (e != NULL) { return ptr2s(e->val); } else { return sUNDEF; } }
const struct CmdTemplate* parser_get_cmd_template(const char *input) { // const struct CmdTemplate *cmdp; // int cmdlen; const char *begin = input, *end = input; // Skip the ID, and get the command if (!get_word(&begin, &end)) return NULL; if (!get_word(&begin, &end)) return NULL; return (const struct CmdTemplate*)ht_find(&commands, begin, end-begin); }
/** * Find the template for the command contained in the text line. * The template can be used to tokenize the command and interpret * it. * * This function can be used to find out which command is contained * in a given text line without parsing all the parameters and * executing it. * * \param input Text line to be processed (ASCIIZ) * * \return The command template associated with the command contained * in the line, or NULL if the command is invalid. */ const struct CmdTemplate* parser_get_cmd_template(const char *input) { const char *begin = input, *end = input; #if CONFIG_ENABLE_COMPAT_BEHAVIOUR // Skip the ID, and get the command if (!get_word(&begin, &end)) return NULL; #endif if (!get_word(&begin, &end)) return NULL; return (const struct CmdTemplate*)ht_find(&commands, begin, end-begin); }
void unregister_message_proc(MessageMap* _map, u32 _msg) { ht_node_t* pm = 0; ls_node_t* p = 0; union { Ptr ptr; u32 uint; } u; assert(_map); if(_msg < MESSAGE_TABLE_SIZE) { _map->fast_table[_msg] = 0; } else { pm = _map->proc_map; u.uint = _msg; p = ht_find(pm, u.ptr); if(p) { ht_remove(pm, p->extra); } } }
/** \ingroup dbprim_hash * \brief Move an entry in the hash table. * * This function moves an existing entry in the hash table to * correspond to the new key. * * \param table A pointer to a #hash_table_t. * \param entry A pointer to a #hash_entry_t to be moved. It must * already be in the hash table. * \param key A pointer to a #db_key_t describing the new key for * the entry. * * \retval DB_ERR_BADARGS An invalid argument was given. * \retval DB_ERR_UNUSED Entry is not in a hash table. * \retval DB_ERR_WRONGTABLE Entry is not in this hash table. * \retval DB_ERR_FROZEN Hash table is frozen. * \retval DB_ERR_DUPLICATE New key is a duplicate of an existing * key. * \retval DB_ERR_READDFAILED Unable to re-add entry to table. */ unsigned long ht_move(hash_table_t *table, hash_entry_t *entry, db_key_t *key) { unsigned long retval; initialize_dbpr_error_table(); /* initialize error table */ if (!ht_verify(table) || !he_verify(entry) || !key) /* verify arguments */ return DB_ERR_BADARGS; if (!entry->he_table) /* it's not in a table */ return DB_ERR_UNUSED; if (entry->he_table != table) /* it's in the wrong table */ return DB_ERR_WRONGTABLE; if (table->ht_flags & HASH_FLAG_FREEZE) /* don't mess with frozen tables */ return DB_ERR_FROZEN; if (!ht_find(table, 0, key)) /* don't permit duplicates */ return DB_ERR_DUPLICATE; /* remove the entry from the table */ if ((retval = ll_remove(&table->ht_table[entry->he_hash], &entry->he_elem))) return retval; /* rekey the entry */ entry->he_key = *key; /* thank goodness for structure copy! */ /* get the new hash value for the entry */ entry->he_hash = (*table->ht_func)(table, &entry->he_key) % table->ht_modulus; /* Now re-add it to the table */ if ((retval = ll_add(&table->ht_table[entry->he_hash], &entry->he_elem, LINK_LOC_HEAD, 0))) { table->ht_count--; /* decrement the count--don't worry about shrinking */ entry->he_table = 0; /* zero the table pointer */ return DB_ERR_READDFAILED; } return 0; }
int main(int argc, char **argv) { hash_table_t table[] = { /* some tables to operate on */ HASH_TABLE_INIT(0, check_func, check_comp, 0, TABLE0), HASH_TABLE_INIT(0, check_func, check_comp, 0, TABLE1), { DEADINT, DEADINT, DEADINT, DEADINT, DEADINT, DEADINT, DEADPTR, (hash_func_t)DEADPTR, (hash_comp_t)DEADPTR, (hash_resize_t)DEADPTR, DEADPTR } /* table[2] */ }; hash_entry_t entry[] = { /* some entries to operate on */ HASH_ENTRY_INIT(OBJECT0), HASH_ENTRY_INIT(OBJECT1), HASH_ENTRY_INIT(OBJECT2), HASH_ENTRY_INIT(OBJECT3), HASH_ENTRY_INIT(OBJECT4), HASH_ENTRY_INIT(OBJECT5), { DEADINT, { DEADINT, DEADPTR, DEADPTR, DEADPTR, DEADPTR, DEADINT }, DEADPTR, DEADINT, { DEADPTR, DEADINT }, DEADPTR } /* entry[6] */ }; hash_entry_t *entry_p; db_key_t key[] = { /* some keys... */ DB_KEY_INIT("obj0", 0), DB_KEY_INIT("obj1", 1), DB_KEY_INIT("obj2", 2), DB_KEY_INIT("obj3", 3), DB_KEY_INIT("obj4", 4), DB_KEY_INIT("obj5", 5), DB_KEY_INIT("obj6", 6) }; /* initialize the tables with a size */ if (ht_init(&table[0], 0, check_func, check_comp, 0, TABLE0, 7) || ht_init(&table[1], 0, check_func, check_comp, 0, TABLE1, 7)) return -1; /* failed to initialize test */ /* Check ht_find()'s handling of bad arguments */ check_result(ht_find(0, 0, 0), DB_ERR_BADARGS, "ht_find_noargs", "ht_find() with no valid arguments", 0); check_result(ht_find(&table[2], 0, &key[6]), DB_ERR_BADARGS, "ht_find_badtable", "ht_find() with bad table", 0); check_result(ht_find(&table[0], 0, 0), DB_ERR_BADARGS, "ht_find_badkey", "ht_find() with bad key", 0); /* Check if empty tables return DB_ERR_NOENTRY */ check_result(ht_find(&table[0], 0, &key[6]), DB_ERR_NOENTRY, "ht_find_emptytable", "ht_find() with empty table", 1); /* Check ht_add()'s handling of bad arguments */ check_result(ht_add(0, 0, 0), DB_ERR_BADARGS, "ht_add_noargs", "ht_add() with no valid arguments", 0); check_result(ht_add(&table[2], &entry[0], &key[0]), DB_ERR_BADARGS, "ht_add_badtable", "ht_add() with bad table", 1); check_result(ht_add(&table[0], &entry[6], &key[6]), DB_ERR_BADARGS, "ht_add_badentry", "ht_add() with bad entry", 1); check_result(ht_add(&table[0], &entry[0], 0), DB_ERR_BADARGS, "ht_add_nokey", "ht_add() with no key", 1); /* Freeze the table temporarily */ ht_flags(&table[0]) |= HASH_FLAG_FREEZE; /* Check adds to frozen tables */ check_result(ht_add(&table[0], &entry[0], &key[0]), DB_ERR_FROZEN, "ht_add_frozen", "ht_add() on frozen table", 1); /* Unfreeze the table */ ht_flags(&table[0]) &= ~HASH_FLAG_FREEZE; /* Add an element to a hash table */ check_result(ht_add(&table[1], &entry[5], &key[5]), 0, "ht_add_t1e5", "Add entry 5 to table 1", 1); /* Now try to add the same element to another hash table */ check_result(ht_add(&table[0], &entry[5], &key[5]), DB_ERR_BUSY, "ht_add_busy", "Add busy entry 5 to table 0", 1); /* Try ht_find() to see if it can find elements */ check_result(ht_find(&table[1], &entry_p, &key[5]), 0, "ht_find_t1e5", "Look up entry 5 in table 1", 1); if (entry_p != &entry[5]) { printf("FAIL/ht_find_t1e5_entry:Attempt to look up entry 5 retrieved " "%p (correct answer is %p)\n", (void *)entry_p, (void *)&entry[5]); return 0; } else printf("PASS/ht_find_t1e5_entry:Retrieved correct entry %p\n", (void *)entry_p); /* Try looking up an element that isn't there in a populated table */ check_result(ht_find(&table[1], 0, &key[6]), DB_ERR_NOENTRY, "ht_find_t1e6", "Look up non-existant entry 5 in table 1", 1); /* Now we know that ht_find() works properly--finish testing ht_add() */ check_result(ht_add(&table[1], &entry[0], &key[5]), DB_ERR_DUPLICATE, "ht_add_duplicate", "Attempt to add duplicate entry to table", 1); /* Now try adding several entries to the table */ check_result(ht_add(&table[0], &entry[0], &key[0]), 0, "ht_add_t0e0", "Add entry 0 to table 0", 1); check_result(ht_add(&table[0], &entry[1], &key[1]), 0, "ht_add_t0e1", "Add entry 1 to table 0", 1); check_result(ht_add(&table[0], &entry[2], &key[2]), 0, "ht_add_t0e2", "Add entry 2 to table 0", 1); check_result(ht_add(&table[0], &entry[3], &key[3]), 0, "ht_add_t0e3", "Add entry 3 to table 0", 1); check_result(ht_add(&table[0], &entry[4], &key[4]), 0, "ht_add_t0e4", "Add entry 4 to table 0", 1); /* Check to see if an element can be found */ check_result(ht_find(&table[0], 0, &key[2]), 0, "ht_find_t0e2", "Find entry 2 in table 0", 1); return 0; }
char* sdb_ht_find(SdbHash* ht, const char* key, bool* found) { return (char *)ht_find (ht, key, found); }
const char *get_style(struct game_state *s, const char *name) { char *n = my_strlower(strdup(name)); char *v = ht_find(s->styles, n); free(n); return v; }
/* Finds Natural Neighbours-interpolated value in a point. * * @param nnhpi NN point hashing interpolator * @param p Point to be interpolated (p->x, p->y -- input; p->z -- output) */ void nnhpi_interpolate(nnhpi* nnhpi, point* p) { nnpi* nnpi = nnhpi->nnpi; delaunay* d = nnpi->d; hashtable* ht_weights = nnhpi->ht_weights; nn_weights* weights; int i; if (ht_find(ht_weights, p) != NULL) { weights = ht_find(ht_weights, p); if (nn_verbose) fprintf(stderr, " <hashtable>\n"); } else { nnpi_calculate_weights(nnpi, p); weights = malloc(sizeof(nn_weights)); weights->vertices = malloc(sizeof(int) * nnpi->nvertices); weights->weights = malloc(sizeof(double) * nnpi->nvertices); weights->nvertices = nnpi->nvertices; for (i = 0; i < nnpi->nvertices; ++i) { weights->vertices[i] = nnpi->vertices[i]; weights->weights[i] = nnpi->weights[i]; } ht_insert(ht_weights, p, weights); if (nn_verbose) { if (nn_test_vertice == -1) { if (nnpi->n == 0) fprintf(stderr, "weights:\n"); fprintf(stderr, " %d: {", nnpi->n); for (i = 0; i < nnpi->nvertices; ++i) { fprintf(stderr, "(%d,%.5g)", nnpi->vertices[i], nnpi->weights[i]); if (i < nnpi->nvertices - 1) fprintf(stderr, ", "); } fprintf(stderr, "}\n"); } else { double w = 0.0; if (nnpi->n == 0) fprintf(stderr, "weights for vertex %d:\n", nn_test_vertice); for (i = 0; i < nnpi->nvertices; ++i) { if (nnpi->vertices[i] == nn_test_vertice) { w = nnpi->weights[i]; break; } } fprintf(stderr, "%15.7g %15.7g %15.7g\n", p->x, p->y, w); } } nnpi->n++; } nnhpi->n++; if (weights->nvertices == 0) { p->z = NaN; return; } p->z = 0.0; for (i = 0; i < weights->nvertices; ++i) { if (weights->weights[i] < nnpi->wmin) { p->z = NaN; return; } p->z += d->points[weights->vertices[i]].z * weights->weights[i]; } }
static t_snode *_interpreter(t_ast_element *p) { t_object *obj, *obj1, *obj2, *obj3; t_snode *node1, *node2, *node3; int initial_loop; t_ast_element *hte; char *ctx_name, *name; wchar_t *wchar_tmp; t_dll *dll; t_scope *scope; // Append to lineno dll_append(lineno_stack, (void *)p->lineno); // No element found, return NULL object if (!p) { RETURN_SNODE_OBJECT(Object_Null); } switch (p->type) { case typeAstNull : RETURN_SNODE_NULL(); break; case typeAstInterface: // @TODO RETURN_SNODE_NULL(); break; case typeAstString : DEBUG_PRINT("new string object: '%s'\n", p->string.value); // Allocate enough room to hold string in wchar and convert int len = strlen(p->string.value) * sizeof(wchar_t); wchar_tmp = (wchar_t *)smm_malloc(len * sizeof(wchar_t)); memset(wchar_tmp, 0, len * sizeof(wchar_t)); mbstowcs(wchar_tmp, p->string.value, strlen(p->string.value)); // create string object obj = object_new(Object_String, wchar_tmp); // Free tmp wide string smm_free(wchar_tmp); RETURN_SNODE_OBJECT(obj); break; case typeAstNumerical : DEBUG_PRINT("new numerical object: %d\n", p->numerical.value); // Create numerical object obj = object_new(Object_Numerical, p->numerical.value); RETURN_SNODE_OBJECT(obj); break; case typeAstIdentifier : // Do constant vars if (strcasecmp(p->string.value, "True") == 0) { //RETURN_SNODE_OBJECT(Object_True); RETURN_SNODE_IDENTIFIER(NULL, Object_True); } if (strcasecmp(p->string.value, "False") == 0) { DEBUG_PRINT("Retuning false!"); //RETURN_SNODE_OBJECT(Object_False); RETURN_SNODE_IDENTIFIER(NULL, Object_False); } if (strcasecmp(p->string.value, "Null") == 0) { //RETURN_SNODE_OBJECT(Object_Null); RETURN_SNODE_IDENTIFIER(NULL, Object_Null); } obj = si_find_var_in_context(p->string.value, NULL); RETURN_SNODE_IDENTIFIER(p->string.value, obj); break; case typeAstClass : obj = (t_object *)smm_malloc(sizeof(t_object)); obj->ref_count = 0; obj->type = objectTypeAny; obj->name = smm_strdup(p->class.name); obj->flags = OBJECT_TYPE_CLASS; obj->parent = NULL; obj->implement_count = 0; obj->implements = NULL; obj->methods = ht_create(); obj->properties = ht_create(); obj->constants = ht_create(); obj->operators = NULL; obj->comparisons = NULL; obj->funcs = &user_funcs; // @TODO: Add modifier flags to obj->flags // Check extends obj->parent = Object_Base; // Interpret body. t_object *saved_obj = current_obj; current_obj = obj; _interpreter(p->class.body); current_obj = saved_obj; // Add the object to the current context t_ns_context *ctx = si_get_current_context(); si_context_add_object(ctx, obj); break; case typeAstMethod : if (current_obj == NULL) { saffire_error("Trying to define a method outside a class. This should be caught by the parser!"); } DEBUG_PRINT("Adding method: %s to %s\n", p->method.name, current_obj->name); // @TODO: ADD FLAGS AND VISIBILITY int vis = 0; if (p->method.modifiers & MODIFIER_PUBLIC) vis |= METHOD_VISIBILITY_PUBLIC; if (p->method.modifiers & MODIFIER_PROTECTED) vis |= METHOD_VISIBILITY_PROTECTED; if (p->method.modifiers & MODIFIER_PRIVATE) vis |= METHOD_VISIBILITY_PRIVATE; int flags = 0; if (p->method.modifiers & MODIFIER_FINAL) flags |= METHOD_FLAG_FINAL; if (p->method.modifiers & MODIFIER_ABSTRACT) flags |= METHOD_FLAG_ABSTRACT; if (p->method.modifiers & MODIFIER_STATIC) flags |= METHOD_FLAG_STATIC; object_add_external_method(current_obj, p->method.name, flags, vis, p->method.body); break; case typeAstOpr : DEBUG_PRINT("opr.oper: %s(%d)\n", get_token_string(p->opr.oper), p->opr.oper); switch (p->opr.oper) { case T_PROGRAM : SI0(p); // parse use declarations SI1(p); // parse top statements break; case T_TOP_STATEMENTS: case T_USE_STATEMENTS: case T_STATEMENTS : for (int i=0; i!=OP_CNT(p); i++) { _interpreter(p->opr.ops[i]); } // Statements do not return anything RETURN_SNODE_NULL(); // (well, it should) break; case T_IMPORT : // Class to import node1 = SI0(p); obj1 = si_get_object(node1); char *classname = OBJ2STR(obj1); // Fetch alias node2 = SI1(p); if (IS_NULL(node2)) { node2 = node1; // Alias X as X if needed } obj2 = si_get_object(node2); char *alias = OBJ2STR(obj2); // context to import from node3 = SI2(p); obj3 = si_get_object(node3); ctx_name = OBJ2STR(obj3); // Check if variable is free if (si_find_var_in_context(alias, NULL)) { saffire_error("A variable named %s is already present or imported.", alias); } // Find class in context ctx = si_get_context(ctx_name); if (ctx == NULL) { saffire_error("Cannot find context: %s", ctx_name); } obj = si_find_var_in_context(classname, ctx); if (! obj) { saffire_error("Cannot find class %s inside context: %s", classname, ctx_name); } // Add the object to the current context as the alias variable si_create_var_in_context(alias, NULL, obj, CTX_CREATE_ONLY); DEBUG_PRINT("Imported class %s as %s from %s into %s\n", classname, alias, ctx_name, ctx->name); break; case T_USE : // Class to use node1 = SI0(p); obj1 = si_get_object(node1); name = OBJ2STR(obj1); if (OP_CNT(p) > 1) { // Fetch alias node2 = SI1(p); if (IS_NULL(node2)) { node2 = node1; // Alias X as X } } else { node2 = node1; // Alias X as X } obj2 = si_get_object(node2); alias = OBJ2STR(obj2); // Check if variable is free ctx = si_find_context(alias); if (ctx != NULL) { saffire_error("A context named %s is already present or imported.", alias); } ctx = si_find_context(name); if (ctx == NULL) { saffire_error("Context %s was not found.", name); } si_create_context_alias(alias, ctx); break; case T_RETURN : // Check the current scope. scope = get_current_scope(); if (scope->depth == 1) { DEBUG_PRINT("Cannot leave the global scope!"); } node1 = SI0(p); obj = si_get_object(node1); RETURN_SNODE_OBJECT(obj); break; case T_EXPRESSIONS : // No expression, just return NULL if (OP_CNT(p) == 0) { RETURN_SNODE_NULL(); } // Do all expressions for (int i=0; i!=OP_CNT(p); i++) { node1 = _interpreter(p->opr.ops[i]); // Remember the first node if (i == 0) node2 = node1; } return node2; break; case T_ASSIGNMENT : // Fetch LHS node node1 = SI0(p); // it should be a variable, otherwise we cannot write to it.. // @TODO: THIS IS WRONG. AN ID ALWAYS HAS AN KEY? if (! HAS_IDENTIFIER_ID(node1)) { saffire_error("Left hand side is not writable!"); } // Check if we have a normal assignment. We only support this for now... t_ast_element *e = p->opr.ops[1]; if (e->type != typeAstOpr || e->opr.oper != T_ASSIGNMENT) { saffire_error("We only support = assignments (no += etc)"); } // Evaluate the RHS node3 = SI2(p); // Get the object and store it obj1 = si_get_object(node3); si_set_object(node1, obj1); RETURN_SNODE_OBJECT(obj1); break; /** * Control structures */ case T_DO : do { // Always execute our inner block at least once SI0(p); // Check condition node1 = SI1(p); obj1 = si_get_object(node1); // Check if it's already a boolean. If not, cast this object to boolean if (! OBJECT_IS_BOOLEAN(obj1)) { obj2 = object_find_method(obj1, "boolean"); obj1 = object_call(obj1, obj2, 0); } // False, we can break our do-loop if (obj1 == Object_False) { break; } } while (1); RETURN_SNODE_NULL(); break; case T_WHILE : initial_loop = 1; while (1) { // Check condition first node1 = SI0(p); obj1 = si_get_object(node1); // Check if it's already a boolean. If not, cast this object to boolean if (! OBJECT_IS_BOOLEAN(obj1)) { obj2 = object_find_method(obj1, "boolean"); obj1 = object_call(obj1, obj2, 0); } // if condition is true, execute our inner block if (obj1 == Object_True) { SI1(p); } else { // If the first loop is false and we've got an else statement, execute it. if (initial_loop && OP_CNT(p) > 2) { SI2(p); } break; } initial_loop = 0; } RETURN_SNODE_NULL(); break; case T_FOR : // Evaluate first part node1 = SI0(p); while (1) { // Check condition first node2 = SI1(p); obj1 = si_get_object(node2); // Check if it's already a boolean. If not, cast this object to boolean if (! OBJECT_IS_BOOLEAN(obj1)) { obj2 = object_find_method(obj1, "boolean"); obj1 = object_call(obj1, obj2, 0); } // if condition is not true, break our loop if (obj1 != Object_True) { break; } // Condition is true, execute our inner loop SI3(p); // Finally, evaluate our last block SI2(p); } // All done break; /** * Conditional statements */ case T_IF: node1 = SI0(p); obj1 = si_get_object(node1); // Check if it's already a boolean. If not, cast this object to boolean if (! OBJECT_IS_BOOLEAN(obj1)) { obj2 = object_find_method(obj1, "boolean"); obj1 = object_call(obj1, obj2, 0); } if (obj1 == Object_True) { // Execute if-block node2 = SI1(p); } else if (OP_CNT(p) > 2) { // Execute (optional) else-block node2 = SI2(p); } break; case T_ARGUMENT_LIST: dll = dll_init(); for (int i=0; i!=OP_CNT(p); i++) { node1 = _interpreter(p->opr.ops[i]); obj1 = si_get_object(node1); dll_append(dll, obj1); } RETURN_SNODE_DLL(dll); case T_METHOD_CALL : // Get object node1 = SI0(p); obj1 = IS_NULL(node1) ? NULL : si_get_object(node1); if (obj1 != NULL) { hte = p->opr.ops[1]; obj2 = object_find_method(obj1, hte->identifier.name); if (! obj2) { saffire_error("Cannot find method or property named '%s' in '%s'", hte->identifier.name, obj1->name); } } else { // Get object node2 = SI1(p); obj2 = si_get_object(node2); } // Get arguments (or NULL) t_dll *dll = NULL; node2 = SI2(p); if (IS_DLL(node2)) { dll = node2->data.dll; } else if (IS_NULL(node2)) { dll = NULL; } else { saffire_error("Expected a DLL (or null)"); } // assume nothing found obj3 = Object_Null; if (OBJECT_IS_METHOD(obj2)) { /* * Lots of method checks before we can actually call this */ t_method_object *method = (t_method_object *)obj2; if (METHOD_IS_CONSTRUCTOR(method)) { saffire_error("Cannot call constructor"); } if (METHOD_IS_DESTRUCTOR(method)) { saffire_error("Cannot call destructor"); } if (OBJECT_TYPE_IS_ABSTRACT(obj1)) { saffire_error("Cannot call an abstract class"); } if (OBJECT_TYPE_IS_INTERFACE(obj1)) { saffire_error("Cannot call an interface"); } if (OBJECT_TYPE_IS_INSTANCE(obj1) && METHOD_IS_STATIC(method)) { saffire_error("Cannot call a static method from an instance. Hint: use %s.%s()", obj1->name, obj2->name); } if (OBJECT_TYPE_IS_CLASS(obj1) && ! METHOD_IS_STATIC(method)) { saffire_error("Cannot call a non-static method directly from a class. Hint: instantiate first"); } // Set new scope enter_scope(p); // We need to do a method call DEBUG_PRINT("+++ Calling method %s \n", obj2->name); obj3 = object_call_args(obj1, obj2, dll); leave_scope(); } else if (OBJECT_TYPE_IS_CLASS(obj2)) { // We need to instantiate DEBUG_PRINT("+++ Instantiating a new class for %s\n", obj2->name); enter_scope(p); obj3 = object_new(obj2, dll); if (! obj3) { saffire_error("Cannot instantiate class %s", obj2->name); } leave_scope(); } else { saffire_error("Cannot call or instantiate %s", obj2->name); } // } else { // // // get class or method name // hte = p->opr.ops[1]; // if (hte->type != typeAstIdentifier) { // saffire_error("Can only have identifiers here", hte->identifier.name); // } // // method_name = smm_strdup(hte->identifier.name); // } // // // At this point we need to fetch the objec, // // // //// if (hte->type == typeAstNull && (obj->flags & OBJECT_TYPE_CLASS) == OBJECT_TYPE_CLASS) { // // if (instantiation) { // // Instantiating // DEBUG_PRINT("+++ Instantiating a new class for %s\n", obj1->name); // // if (! OBJECT_TYPE_IS_CLASS(obj1)) { // saffire_error("Can only instantiate classes"); // } // // obj2 = object_new(obj1, dll); // if (! obj2) { // saffire_error("Cannot instantiate class %s", obj1->name); // } // // } else { // // if (hte->type != typeAstIdentifier) { // saffire_error("Can only have identifiers here", hte->identifier.name); // } // method_name = smm_strdup(hte->identifier.name); // // obj2 = object_call_args(obj1, method_name, dll); // // smm_free(method_name); // } if (dll) dll_free(dll); RETURN_SNODE_OBJECT(obj3); break; /* Comparisons */ case '<' : return si_comparison(p, COMPARISON_LT); break; case '>' : return si_comparison(p, COMPARISON_GT); break; case T_GE : return si_comparison(p, COMPARISON_GE); break; case T_LE : return si_comparison(p, COMPARISON_LE); break; case T_NE : return si_comparison(p, COMPARISON_NE); break; case T_EQ : return si_comparison(p, COMPARISON_EQ); break; /* Operators */ case '+' : return si_operator(p, OPERATOR_ADD); break; case '-' : return si_operator(p, OPERATOR_SUB); break; case '*' : return si_operator(p, OPERATOR_MUL); break; case '/' : return si_operator(p, OPERATOR_DIV); break; case T_AND : return si_operator(p, OPERATOR_AND); break; case T_OR : return si_operator(p, OPERATOR_OR); break; case '^' : return si_operator(p, OPERATOR_XOR); break; case T_SHIFT_LEFT : return si_operator(p, OPERATOR_SHL); break; case T_SHIFT_RIGHT : return si_operator(p, OPERATOR_SHR); break; /* Unary operators */ case T_OP_INC : // We must be a variable node1 = SI0(p); if (! HAS_IDENTIFIER_ID(node1)) { saffire_error("Left hand side is not writable!"); } obj1 = si_get_object(node1); obj2 = object_new(Object_Numerical, 1); obj3 = object_operator(obj1, OPERATOR_ADD, 0, 1, obj2); si_set_object(node1, obj3); RETURN_SNODE_OBJECT(obj3); break; case T_OP_DEC : // We must be a variable node1 = SI0(p); if (! HAS_IDENTIFIER_ID(node1)) { saffire_error("Left hand side is not writable!"); } obj1 = si_get_object(node1); obj2 = object_new(Object_Numerical, 1); obj3 = object_operator(obj1, OPERATOR_SUB, 0, 1, obj2); si_set_object(node1, obj3); RETURN_SNODE_OBJECT(obj3); break; case '.' : node1 = SI0(p); obj1 = si_get_object(node1); // get method name from object hte = p->opr.ops[1]; if (hte->type != typeAstIdentifier) { saffire_error("Can only have identifiers here", hte->identifier.name); } DEBUG_PRINT("Figuring out: '%s' in object '%s'\n", hte->identifier.name, obj1->name); obj = ht_find(obj1->properties, hte->identifier.name); if (obj == NULL) { obj = ht_find(obj1->constants, hte->identifier.name); if (obj == NULL) { saffire_error("Cannot find constant or property '%s' from '%s'", hte->identifier.name, obj1->name); } } RETURN_SNODE_OBJECT(obj); break; case T_CONST : if (current_obj == NULL) { // @TODO: We could create constants OUTSIDE a class! saffire_error("Defining constants outside classes is not yet supported!"); } hte = p->opr.ops[0]; if (hte->type != typeAstIdentifier) { saffire_error("Constant name needs to be an identifier"); } node2 = SI1(p); obj2 = si_get_object(node2); DEBUG_PRINT("Added constant %s to %s\n", hte->identifier.name, current_obj->name); ht_add(current_obj->constants, hte->identifier.name, obj2); break; case T_PROPERTY : if (current_obj == NULL) { saffire_error("Cannot define properties outside classes. This should be caught by the parser!"); } hte = p->opr.ops[0]; if (hte->type != typeAstNumerical) { saffire_error("Flags name needs to be numerical"); } hte = p->opr.ops[1]; if (hte->type != typeAstIdentifier) { saffire_error("Property name needs to be an identifier"); } node2 = SI2(p); obj2 = si_get_object(node2); DEBUG_PRINT("Added property %s to %s\n", hte->identifier.name, current_obj->name); ht_add(current_obj->properties, hte->identifier.name, obj2); break; default: saffire_error("Unhandled opcode: %d\n", p->opr.oper); break; } break; } RETURN_SNODE_NULL(); }
/* This is a central procedure for the Natural Neighbours interpolation. It * uses the Watson's algorithm for the required areas calculation and implies * that the vertices of the delaunay triangulation are listed in uniform * (clockwise or counterclockwise) order. */ static void nnpi_triangle_process(nnpi* nn, point* p, int i) { delaunay* d = nn->d; triangle* t = &d->triangles[i]; circle* c = &d->circles[i]; circle cs[3]; int j; /* * There used to be a useful assertion here: * * assert(circle_contains(c, p)); * * I removed it after introducing flag `contains' to * delaunay_circles_find(). It looks like the code is robust enough to * run without this assertion. */ /* * Sibson interpolation by using Watson's algorithm */ for (j = 0; j < 3; ++j) { int j1 = (j + 1) % 3; int j2 = (j + 2) % 3; int v1 = t->vids[j1]; int v2 = t->vids[j2]; if (!circle_build2(&cs[j], &d->points[v1], &d->points[v2], p)) { point* p1 = &d->points[v1]; point* p2 = &d->points[v2]; if ((fabs(p1->x - p->x) + fabs(p1->y - p->y)) / c->r < EPS_SAME) { /* * if (p1->x == p->x && p1->y == p->y) { */ nnpi_add_weight(nn, v1, BIGNUMBER); return; } else if ((fabs(p2->x - p->x) + fabs(p2->y - p->y)) / c->r < EPS_SAME) { /* * } else if (p2->x == p->x && p2->y == p->y) { */ nnpi_add_weight(nn, v2, BIGNUMBER); return; } } } for (j = 0; j < 3; ++j) { int j1 = (j + 1) % 3; int j2 = (j + 2) % 3; double det = ((cs[j1].x - c->x) * (cs[j2].y - c->y) - (cs[j2].x - c->x) * (cs[j1].y - c->y)); if (isnan(det)) { /* * Here, if the determinant is NaN, then the interpolation point * lies almost in between two data points. This case is difficult to * handle robustly because the areas (determinants) calculated by * Watson's algorithm are obtained as a diference between two big * numbers. This case is handled here in the following way. * * If a circle is recognised as very large in circle_build2(), then * its parameters are replaced by NaNs, which results in the * variable `det' above being NaN. * * When this happens inside convex hall of the data, there is * always a triangle on another side of the edge, processing of * which also produces an invalid circle. Processing of this edge * yields two pairs of infinite determinants, with singularities * of each pair cancelling if the point moves slightly off the edge. * * Each of the determinants corresponds to the (signed) area of a * triangle, and an inifinite determinant corresponds to the area of * a triangle with one vertex moved to infinity. "Subtracting" one * triangle from another within each pair yields a valid * quadrilateral (in fact, a trapezoid). The doubled area of these * quadrilaterals is calculated in the cycle over ii below. */ int j1bad = isnan(cs[j1].x); int key[2]; double* v = NULL; key[0] = t->vids[j]; if (nn->bad == NULL) nn->bad = ht_create_i2(HT_SIZE); key[1] = (j1bad) ? t->vids[j2] : t->vids[j1]; v = ht_find(nn->bad, &key); if (v == NULL) { v = malloc(8 * sizeof(double)); if (j1bad) { v[0] = cs[j2].x; v[1] = cs[j2].y; } else { v[0] = cs[j1].x; v[1] = cs[j1].y; } v[2] = c->x; v[3] = c->y; (void) ht_insert(nn->bad, &key, v); det = 0.0; } else { int ii; if (j1bad) { v[6] = cs[j2].x; v[7] = cs[j2].y; } else { v[6] = cs[j1].x; v[7] = cs[j1].y; } v[4] = c->x; v[5] = c->y; det = 0; for (ii = 0; ii < 4; ++ii) { int ii1 = (ii + 1) % 4; det += (v[ii * 2] + v[ii1 * 2]) * (v[ii * 2 + 1] - v[ii1 * 2 + 1]); } det = fabs(det); free(v); ht_delete(nn->bad, &key); } } nnpi_add_weight(nn, t->vids[j], det); } }
/* This is a central procedure for the Natural Neighbours interpolation. It * uses the Watson's algorithm for the required areas calculation and implies * that the vertices of the delaunay triangulation are listed in uniform * (clockwise or counterclockwise) order. */ static void nnpi_triangle_process(nnpi* nn, point* p, int i) { delaunay* d = nn->d; triangle* t = &d->triangles[i]; circle* c = &d->circles[i]; circle cs[3]; int j; /* * There used to be a useful assertion here: * * assert(circle_contains(c, p)); * * I removed it after introducing flag `contains' to * delaunay_circles_find(). It looks like the code is robust enough to * run without this assertion. */ /* * Sibson interpolation by using Watson's algorithm */ for (j = 0; j < 3; ++j) { int j1 = (j + 1) % 3; int j2 = (j + 2) % 3; int v1 = t->vids[j1]; int v2 = t->vids[j2]; if (!circle_build2(&cs[j], &d->points[v1], &d->points[v2], p)) { point* p1 = &d->points[v1]; point* p2 = &d->points[v2]; if ((fabs(p1->x - p->x) + fabs(p1->y - p->y)) / c->r < EPS_SAME) { /* * if (p1->x == p->x && p1->y == p->y) { */ nnpi_add_weight(nn, v1, BIGNUMBER); return; } else if ((fabs(p2->x - p->x) + fabs(p2->y - p->y)) / c->r < EPS_SAME) { /* * } else if (p2->x == p->x && p2->y == p->y) { */ nnpi_add_weight(nn, v2, BIGNUMBER); return; } } } for (j = 0; j < 3; ++j) { int j1 = (j + 1) % 3; int j2 = (j + 2) % 3; double det = ((cs[j1].x - c->x) * (cs[j2].y - c->y) - (cs[j2].x - c->x) * (cs[j1].y - c->y)); if (isnan(det)) { /* * If the determinant is NaN, then the interpolation point lies * almost in between two data points. This case is difficult to * handle robustly because the areas calculated are obtained as a * diference between two big numbers. * * Here this is handles in the following way. If a circle is * recognised as very large in circle_build2(), then it parameters * are replaced by NaNs, which results in det above being NaN. * The resulting area to be calculated for a vertex does not * change if the circle center is moved along some line. The closer * it is moved to the actual data point positions, the more * numerically robust the calculation of areas becomes. In * particular, it can be moved to coincide with one of the other * circle centers. When this is done, it is ticked by placing the * edge parameters into the hash table, so that when the * "cancelling" would be about to be done, this new position is * used instead. * * One complicated circumstance is that sometimes a circle is * recognised as very large in cases when it is actually not, * when the interpolated point is close to a data point. This is * handled by a special treatment in _nnpi_calculate_weights(). */ int remove = 1; circle* cc = NULL; int key[2]; key[0] = t->vids[j]; if (nn->bad == NULL) nn->bad = ht_create_i2(HT_SIZE); if (isnan(cs[j1].x)) { key[1] = t->vids[j2]; cc = ht_find(nn->bad, &key); if (cc == NULL) { remove = 0; cc = malloc(sizeof(circle)); cc->x = cs[j2].x; cc->y = cs[j2].y; assert(ht_insert(nn->bad, &key, cc) == NULL); } det = ((cc->x - c->x) * (cs[j2].y - c->y) - (cs[j2].x - c->x) * (cc->y - c->y)); } else { /* j2 */ key[1] = t->vids[j1]; cc = ht_find(nn->bad, &key); if (cc == NULL) { remove = 0; cc = malloc(sizeof(circle)); cc->x = cs[j1].x; cc->y = cs[j1].y; assert(ht_insert(nn->bad, &key, cc) == NULL); } det = ((cs[j1].x - c->x) * (cc->y - c->y) - (cc->x - c->x) * (cs[j1].y - c->y)); } if (remove) assert(ht_delete(nn->bad, &key) != NULL); } nnpi_add_weight(nn, t->vids[j], det); } }
int main() { double points[] = { 922803.7855, 7372394.688, 0, 922849.2037, 7372307.027, 1, 922894.657, 7372219.306, 2, 922940.1475, 7372131.528, 3, 922985.6777, 7372043.692, 4, 923031.2501, 7371955.802, 5, 923076.8669, 7371867.857, 6, 923122.5307, 7371779.861, 7, 923168.2439, 7371691.816, 8, 923214.0091, 7371603.722, 9, 923259.8288, 7371515.583, 10, 922891.3958, 7372440.117, 11, 922936.873, 7372352.489, 12, 922982.3839, 7372264.804, 13, 923027.9308, 7372177.064, 14, 923073.5159, 7372089.268, 15, 923119.1415, 7372001.42, 16, 923164.8099, 7371913.521, 17, 923210.5233, 7371825.572, 18, 923256.2841, 7371737.575, 19, 923302.0946, 7371649.534, 20, 923347.9572, 7371561.45, 21, 922978.9747, 7372485.605, 22, 923024.5085, 7372398.009, 23, 923070.0748, 7372310.358, 24, 923115.6759, 7372222.654, 25, 923161.3136, 7372134.897, 26, 923206.9903, 7372047.09, 27, 923252.7079, 7371959.233, 28, 923298.4686, 7371871.33, 29, 923344.2745, 7371783.381, 30, 923390.1279, 7371695.389, 31, 923436.0309, 7371607.357, 32, 923066.5232, 7372531.148, 33, 923112.1115, 7372443.583, 34, 923157.7311, 7372355.966, 35, 923203.3842, 7372268.296, 36, 923249.0725, 7372180.577, 37, 923294.7981, 7372092.808, 38, 923340.5628, 7372004.993, 39, 923386.3686, 7371917.132, 40, 923432.2176, 7371829.229, 41, 923478.1116, 7371741.284, 42, 923524.0527, 7371653.302, 43, 923154.0423, 7372576.746, 44, 923199.6831, 7372489.211, 45, 923245.3541, 7372401.625, 46, 923291.0572, 7372313.989, 47, 923336.7941, 7372226.305, 48, 923382.5667, 7372138.574, 49, 923428.3766, 7372050.798, 50, 923474.2256, 7371962.978, 51, 923520.1155, 7371875.118, 52, 923566.0481, 7371787.218, 53, 923612.0252, 7371699.282, 54, 923241.533, 7372622.396, 55, 923287.2244, 7372534.889, 56, 923332.9449, 7372447.334, 57, 923378.6963, 7372359.731, 58, 923424.4801, 7372272.081, 59, 923470.2979, 7372184.385, 60, 923516.1513, 7372096.646, 61, 923562.0418, 7372008.866, 62, 923607.9709, 7371921.046, 63, 923653.9402, 7371833.188, 64, 923699.9514, 7371745.296, 65, 923328.9962, 7372668.095, 66, 923374.7365, 7372580.617, 67, 923420.5049, 7372493.091, 68, 923466.303, 7372405.519, 69, 923512.1321, 7372317.901, 70, 923557.9936, 7372230.24, 71, 923603.8889, 7372142.536, 72, 923649.8192, 7372054.793, 73, 923695.786, 7371967.011, 74, 923741.7905, 7371879.193, 75, 923787.8341, 7371791.342, 76, 923416.4327, 7372713.844, 77, 923462.2204, 7372626.393, 78, 923508.0353, 7372538.895, 79, 923553.8787, 7372451.353, 80, 923599.7517, 7372363.766, 81, 923645.6555, 7372276.137, 82, 923691.5914, 7372188.467, 83, 923737.5603, 7372100.757, 84, 923783.5634, 7372013.011, 85, 923829.6017, 7371925.231, 86, 923875.6763, 7371837.419, 87, 923503.8433, 7372759.64, 88, 923549.6771, 7372672.214, 89, 923595.5372, 7372584.744, 90, 923641.4246, 7372497.23, 91, 923687.3404, 7372409.673, 92, 923733.2855, 7372322.074, 93, 923779.2608, 7372234.436, 94, 923825.2672, 7372146.759, 95, 923871.3056, 7372059.047, 96, 923917.3766, 7371971.301, 97, 923963.4812, 7371883.524, 98, 923591.2288, 7372805.481, 99, 923637.1076, 7372718.081, 100, 923683.0118, 7372630.638, 101, 923728.9423, 7372543.151, 102, 923774.8998, 7372455.622, 103, 923820.8852, 7372368.052, 104, 923866.8991, 7372280.443, 105, 923912.9422, 7372192.797, 106, 923959.015, 7372105.116, 107, 924005.118, 7372017.402, 108, 924051.2518, 7371929.657, 109, 923678.5898, 7372851.367, 110, 923724.5126, 7372763.992, 111, 923770.46, 7372676.574, 112, 923816.4328, 7372589.113, 113, 923862.4314, 7372501.611, 114, 923908.4564, 7372414.069, 115, 923954.5083, 7372326.488, 116, 924000.5875, 7372238.87, 117, 924046.6941, 7372151.218, 118, 924092.8286, 7372063.533, 119, 924138.9911, 7371975.818, 120 }; int size = sizeof(points) / sizeof(double) / 3; hashtable* ht; int i; /* * double[2] key */ printf("\n1. Testing a table with key of double[2] type\n\n"); printf(" creating a table..."); ht = ht_create_d2(size); printf("done\n"); printf(" inserting %d values from a file...", size); for (i = 0; i < size; ++i) ht_insert(ht, &points[i * 3], &points[i * 3 + 2]); printf("done\n"); printf(" stats:\n"); printf(" %d entries, %d table elements, %d filled elements\n", ht->n, ht->size, ht->nhash); printf(" %f entries per hash value in use\n", (double) ht->n / ht->nhash); printf(" finding and printing each 10th data:\n"); for (i = 0; i < size; i += 10) { double* point = &points[i * 3]; double* data = ht_find(ht, point); if (data != NULL) printf(" i = %d; data = \"%d\"\n", i, (int)* data); else printf(" i = %d; data = <none>\n", i); } printf(" removing every 3rd element..."); for (i = 0; i < size; i += 3) { double* point = &points[i * 3]; ht_delete(ht, point); } printf("done\n"); printf(" stats:\n"); printf(" %d entries, %d table elements, %d filled elements\n", ht->n, ht->size, ht->nhash); printf(" %f entries per hash value in use\n", (double) ht->n / ht->nhash); printf(" finding and printing each 10th data:\n"); for (i = 0; i < size; i += 10) { double* point = &points[i * 3]; double* data = ht_find(ht, point); if (data != NULL) printf(" i = %d; data = \"%d\"\n", i, (int)* data); else printf(" i = %d; data = <none>\n", i); } printf(" printing all data by calling ht_process():\n "); ht_process(ht, print_double); printf("\n destroying the hash table..."); ht_destroy(ht); printf("done\n"); /* * char* key */ printf("\n2. Testing a table with key of char* type\n\n"); printf(" creating a table..."); ht = ht_create_str(size); printf("done\n"); printf(" inserting %d elements with deep copy of each data string...", size); for (i = 0; i < size; ++i) { char key[BUFSIZE]; char str[BUFSIZE]; char* data; sprintf(key, "%d-th key", i); sprintf(str, "%d-th data", i); data = strdup(str); ht_insert(ht, key, data); } printf("done\n"); printf(" stats:\n"); printf(" %d entries, %d table elements, %d filled elements\n", ht->n, ht->size, ht->nhash); printf(" %f entries per hash value in use\n", (double) ht->n / ht->nhash); printf(" finding and printing each 10th data:\n"); for (i = 0; i < size; i += 10) { char key[BUFSIZE]; char* data; sprintf(key, "%d-th key", i); data = ht_find(ht, key); if (data != NULL) printf(" i = %d; data = \"%s\"\n", i, data); else printf(" i = %d; data = <none>\n", i); } printf(" removing every 3rd element..."); for (i = 0; i < size; i += 3) { char key[BUFSIZE]; sprintf(key, "%d-th key", i); free(ht_delete(ht, key)); } printf("done\n"); printf(" stats:\n"); printf(" %d entries, %d table elements, %d filled elements\n", ht->n, ht->size, ht->nhash); printf(" %f entries per hash value in use\n", (double) ht->n / ht->nhash); printf(" finding and printing each 10th data:\n"); for (i = 0; i < size; i += 10) { char key[BUFSIZE]; char* data; sprintf(key, "%d-th key", i); data = ht_find(ht, key); if (data != NULL) printf(" i = %d; data = \"%s\"\n", i, data); else printf(" i = %d; data = <none>\n", i); } printf(" printing all data by calling ht_process():\n "); ht_process(ht, print_string); printf("\n freeing the remaining data by calling ht_process()..."); ht_process(ht, free); printf("done\n"); printf(" destroying the hash table..."); ht_destroy(ht); printf("done\n"); return 0; }
/** * Return value of key, or NULL when nothing found */ void *ht_num_find(t_hash_table *ht, long index) { char key[32]; snprintf(key, 31, "%ld", index); return ht_find(ht, key); }