sexpr lx_make_environment (sexpr env) { static struct memory_pool pool = MEMORY_POOL_INITIALISER(sizeof (struct environment)); struct environment *rv; struct tree_node *n; int_pointer hash = hash_murmur2_pt ((void *)&env, sizeof(env), 0); /* note: the hashing may seem pointless, but it does help performance by * effectively randomising the input data, thus helping the tree performance * by making it far less likely for the tree to degenerate into a linked * list. */ if ((n = tree_get_node (&environment_tree, hash))) { return (sexpr)node_get_value (n); } rv = get_pool_mem (&pool); if (rv == (struct environment *)0) { return sx_nonexistent; } rv->type = environment_type_identifier; rv->environment = env; tree_add_node_value (&environment_tree, hash, (void *)rv); return (sexpr)rv; }
/*@null@*/ static node_t list_get_node_by_value(list_t inst, void* val) { node_t n = inst->head; int ctr = 0; while ((n != NULL) && (inst->cmp(node_get_value(n), val))) { ctr++; n = n->next; } return n; }
/*@null@*/ void* iter_get(iter_t inst) { void* rval = NULL; node_t node; node = iter_get_node(inst); if (node != NULL) { rval = node_get_value(iter_get_node(inst)); } return rval; }
int list_index_of(list_t inst, void* val) { node_t n = inst->head; int rval = 0; while ((n != NULL) && (inst->cmp(node_get_value(n), val))) { rval++; n = n->next; } if (n == NULL) { rval = -1; } return rval; }
static unsigned int test_tree_value(unsigned int keys) { struct tree *t = tree_create (); unsigned int i; struct tree_node *n; for (i = 0; i < keys; i++) { tree_add_node_value (t, i, sentinelvalue(i)); } for (i = 0; i < keys; i++) { n = tree_get_node (t, i); if (n == (struct tree_node *)0) { tree_destroy(t); return 7; } if (n->key != i) { tree_destroy(t); return 8; } if (node_get_value (n) != sentinelvalue(i)) { tree_destroy(t); return 9; } } n = tree_get_node (t, keys + 1); if (n != (struct tree_node *)0) { tree_destroy(t); return 10; } /* we do this twice to stress the optimising algo once it's in */ for (i = 0; i < keys; i++) { n = tree_get_node (t, i); if (n == (struct tree_node *)0) { tree_destroy(t); return 11; } if (n->key != i) { tree_destroy(t); return 12; } if (node_get_value (n) != sentinelvalue(i)) { tree_destroy(t); return 13; } } n = tree_get_node (t, keys + 1); if (n != (struct tree_node *)0) { tree_destroy(t); return 14; } tree_destroy(t); return 0; }
const void *immutable (const void * data, unsigned long length) { const char *rv; const char *data_char = (const char *)data; struct tree_node *n; int_pointer hash = hash_murmur2_pt (&data, sizeof (const void *), 0); if (tree_get_node (&immutable_data_tree, hash) != (struct tree_node *)0) { return data; } hash = hash_murmur2_pt (data, length, 0); if ((n = tree_get_node (&immutable_hashes, hash)) != (struct tree_node *)0) { return (const void *)node_get_value (n); } if ((length + 1) > immutable_data_space_left) { unsigned long new_size = IMMUTABLE_CHUNKSIZE; lock_immutable_pages(); if (length > IMMUTABLE_CHUNKSIZE) { new_size = ((length / IMMUTABLE_CHUNKSIZE) + (((length % IMMUTABLE_CHUNKSIZE) != 0) ? 1 : 0)) * IMMUTABLE_CHUNKSIZE; } if (immutable_data != (void *)0) { lock_immutable_pages(); } immutable_data = get_mem(new_size); immutable_data_space_left = new_size; immutable_cursor = immutable_data; immutable_data_size = new_size; } for (rv = immutable_cursor; length != 0; immutable_cursor++, data_char++, length--, immutable_data_space_left--) { *immutable_cursor = *data_char; } *immutable_cursor = 0; /* write an extra 0 after whatever we just wrote */ immutable_cursor++; immutable_data_space_left--; while ((((unsigned long)immutable_cursor) % sizeof(void *)) != 0) { *immutable_cursor = 0; immutable_cursor++; immutable_data_space_left--; } tree_add_node_value (&immutable_hashes, hash, (void *)rv); hash = hash_murmur2_pt (&rv, sizeof (const void *), 0); tree_add_node (&immutable_data_tree, hash); return rv; }
static unsigned int test_tree_node_removal(unsigned int keys) { struct tree *t = tree_create (); unsigned int i; struct tree_node *n; for (i = 0; i < keys; i++) { tree_add_node_value (t, i, sentinelvalue(i)); } /* remove half the nodes */ for (i = 0; i < keys; i+=2) { tree_remove_node (t, i); } /* search for the nodes that should still be present */ for (i = 1; i < keys; i+=2) { n = tree_get_node (t, i); if (n == (struct tree_node *)0) { tree_destroy(t); return 15; } if (n->key != i) { tree_destroy(t); return 16; } if (node_get_value (n) != sentinelvalue(i)) { tree_destroy(t); return 17; } } /* search for the nodes that should be missing */ for (i = 0; i < keys; i+=2) { n = tree_get_node (t, i); if (n != (struct tree_node *)0) { tree_destroy(t); return 18; } } /* search for an arbitrary node that can't be present */ n = tree_get_node (t, keys + 1); if (n != (struct tree_node *)0) { tree_destroy(t); return 19; } /* we do the searches twice to stress the optimising algo once it's in */ /* search for the nodes that should still be present */ for (i = 1; i < keys; i+=2) { n = tree_get_node (t, i); if (n == (struct tree_node *)0) { tree_destroy(t); return 20; } if (n->key != i) { tree_destroy(t); return 21; } if (node_get_value (n) != sentinelvalue(i)) { tree_destroy(t); return 22; } } /* search for the nodes that should be missing */ for (i = 0; i < keys; i+=2) { n = tree_get_node (t, i); if (n != (struct tree_node *)0) { tree_destroy(t); return 23; } } /* remove the remaining nodes */ for (i = 1; i < keys; i+=2) { tree_remove_node (t, i); } if (t->root != (struct tree_node *)0) { tree_destroy(t); return 24; } tree_destroy(t); return 0; }
/*@null@*/ static char* node_to_string(node_t inst) { char rval[256]; snprintf(rval, sizeof(rval), "(node_t) { val=%p }", node_get_value(inst)); return strdup(rval); }
/*@null@*/ void* list_get(list_t inst, int idx) { node_t n = list_get_node_by_index(inst, idx); return node_get_value(n); }
/*@null@*/ static void* node_exit(node_t inst) { void* rval = node_get_value(inst); //printf("exit node@%p\n", inst); free(inst); return rval; }