/** * find_tree * @t: tree to search in * @val: value to find * * Search for given value in the tree. I relies on fact that sorted tree is populated * by &f_val structures (that can be compared by val_compare()). In each node of tree, * either single value (then t->from==t->to) or range is present. * * Both set matching and |switch() { }| construction is implemented using this function, * thus both are as fast as they can be. */ struct f_tree * find_tree(struct f_tree *t, struct f_val val) { if (!t) return NULL; if ((val_compare(t->from, val) != 1) && (val_compare(t->to, val) != -1)) return t; if (val_compare(t->from, val) == -1) return find_tree(t->right, val); else return find_tree(t->left, val); }
static void cache_module( const char *filename, aptime time, value main ) { cache *c = (cache*)local_get(cache_root), *prev = NULL; value fname = alloc_string(filename); while( c != NULL ) { if( val_compare(fname,c->file) == 0 ) { if( main == NULL ) { if( prev == NULL ) local_set(cache_root,c->next); else prev->next = c->next; free_root((value*)c); } else { c->main = main; c->time = time; } return; } prev = c; c = c->next; } c = (cache*)alloc_root(sizeof(struct cache) / sizeof(value)); c->file = fname; c->main = main; c->time = time; c->hits = 0; c->next = (cache*)local_get(cache_root); local_set(cache_root,c); }
static value cache_find( request_rec *r ) { cache *c = (cache*)local_get(cache_root); cache *prev = NULL; value fname = alloc_string(r->filename); while( c != NULL ) { if( val_compare(fname,c->file) == 0 ) { if( config.use_cache && FTIME(r) == c->time ) { c->hits++; return c->main; } if( prev == NULL ) local_set(cache_root,c->next); else prev->next = c->next; free_root((value*)c); // try to lower memory partitioning // when a module is updated c = NULL; gc_major(); break; } prev = c; c = c->next; } return NULL; }
/** * same_tree * @t1: first tree to be compared * @t2: second one * * Compares two trees and returns 1 if they are same */ int same_tree(struct f_tree *t1, struct f_tree *t2) { if ((!!t1) != (!!t2)) return 0; if (!t1) return 1; if (val_compare(t1->from, t2->from)) return 0; if (val_compare(t1->to, t2->to)) return 0; if (!same_tree(t1->left, t2->left)) return 0; if (!same_tree(t1->right, t2->right)) return 0; if (!i_same(t1->data, t2->data)) return 0; return 1; }
/** $hset : 'hash -> k:any -> v:any -> cmp:function:2? -> bool <doc> Set the value bound to key [k] to [v] or add it to the hashtable if not found. Return true if the value was added to the hashtable. </doc> **/ static value builtin_hset( value vh, value key, value val, value cmp ) { vhash *h; hcell *c; int hkey; if( !val_is_null(cmp) ) val_check_function(cmp,2); val_check_kind(vh,k_hash); h = val_hdata(vh); hkey = val_hash(key); c = h->cells[hkey % h->ncells]; if( val_is_null(cmp) ) { while( c != NULL ) { if( val_compare(key,c->key) == 0 ) { c->val = val; return val_false; } c = c->next; } } else { while( c != NULL ) { if( val_call2(cmp,key,c->key) == alloc_int(0) ) { c->val = val; return val_false; } c = c->next; } } if( h->nitems >= (h->ncells << 1) ) builtin_hresize(vh,alloc_int(h->ncells << 1)); c = (hcell*)alloc(sizeof(hcell)); c->hkey = hkey; c->key = key; c->val = val; hkey %= h->ncells; c->next = h->cells[hkey]; h->cells[hkey] = c; h->nitems++; return val_true; }
/** $hremove : 'hash -> k:any -> cmp:function:2? -> bool <doc> Look for the value bound to the key [k] in the hashtable. Use the comparison function [cmp] or [$compare] if [null]. Return true if such value exists and remove it from the hash, false either. </doc> **/ static value builtin_hremove( value vh, value key, value cmp ) { vhash *h; hcell *c, *prev = NULL; int hkey; if( !val_is_null(cmp) ) val_check_function(cmp,2); val_check_kind(vh,k_hash); h = val_hdata(vh); hkey = val_hash(key) % h->ncells; c = h->cells[hkey]; if( val_is_null(cmp) ) { while( c != NULL ) { if( val_compare(key,c->key) == 0 ) { if( prev == NULL ) h->cells[hkey] = c->next; else prev->next = c->next; h->nitems--; return val_true; } prev = c; c = c->next; } } else { while( c != NULL ) { if( val_call2(cmp,key,c->key) == alloc_int(0) ) { if( prev == NULL ) h->cells[hkey] = c->next; else prev->next = c->next; h->nitems--; return val_true; } prev = c; c = c->next; } } return val_false; }
/** $hmem : 'hash -> k:any -> cmp:function:2? -> bool <doc> Look for the value bound to the key [k] in the hashtable. Use the comparison function [cmp] or [$compare] if [null]. Return true if such value exists, false either. </doc> **/ static value builtin_hmem( value vh, value key, value cmp ) { vhash *h; hcell *c; if( !val_is_null(cmp) ) val_check_function(cmp,2); val_check_kind(vh,k_hash); h = val_hdata(vh); c = h->cells[val_hash(key) % h->ncells]; if( val_is_null(cmp) ) { while( c != NULL ) { if( val_compare(key,c->key) == 0 ) return val_true; c = c->next; } } else { while( c != NULL ) { if( val_call2(cmp,key,c->key) == alloc_int(0) ) return val_true; c = c->next; } } return val_false; }
/** $compare : any -> any -> int? <doc>Compare two values and return 1, -1 or 0. Return [null] if comparison is not possible</doc> **/ static value builtin_compare( value a, value b ) { int r = val_compare(a,b); return (r == invalid_comparison)?val_null:alloc_int(r); }