/* Search and, if missing, insert. */ void * dwarf_tsearch(const void *key, void **headpin, int (*compar)(const void *, const void *)) { struct ts_entry *head = 0; struct ts_entry *root = 0; struct ts_entry *r = 0; int inserted = 0; if(!headpin) { return NULL; } head = (struct ts_entry *)*headpin; if(head) { root = head->rlink; } if(!head || !root) { if(!head) { head = allocate_ts_entry(0); } if(!head) { return NULL; } root = allocate_ts_entry(key); if(!root) { free(root); return NULL; } head->rlink = root; *headpin = head; return (void *)(&(root->keyptr)); } root = head->rlink; r = tsearch_inner(key,root,compar,&inserted); if (!r) { return NULL; } /* Was this found or inserted? Value is the same either way, but the pointer to return is not the same! */ /* Discards const. Required by the interface definition. */ return (void *)&(r->keyptr); }
/* Search and, if missing, insert. */ void * dwarf_tsearch(const void *key, void **headin, int (*compar)(const void *, const void *)) { struct ts_entry **headp = (struct ts_entry **)headin; struct ts_entry *head = 0; struct ts_entry *r = 0; int inserted = 0; /* kcomparv should be ignored */ int kcomparv = 0; /* nullme won't be set. */ struct ts_entry *nullme = 0; if (!headp) { return NULL; } head = *headp; if (!head) { struct ts_entry *root = 0; head = allocate_ts_entry(0); if(!head) { return NULL; } root = allocate_ts_entry(key); if(!root) { free(head); return NULL; } head->rlink = root; /* head->llink is used for the depth, as a count */ /* head points to the special head node ... */ *headin = head; return (void *)(&(root->keyptr)); } r = tsearch_inner(key,head,compar,&inserted,&nullme,&kcomparv); if (!r) { return NULL; } return (void *)&(r->keyptr); }
/* Knuth step T5, the insert. */ static struct ts_entry * tsearch_insert_k(const void *key,int kc, struct ts_entry *p) { struct ts_entry *q = allocate_ts_entry(key); if (!q) { /* out of memory */ return NULL; } setlink(p,kc,q); /* Non-NULL means inserted. */ return q; }
/* Knuth step T5, the insert. */ static struct ts_entry * tsearch_insert_k(const void *key,int kc, struct ts_entry *p) { struct ts_entry *e = allocate_ts_entry(key); if (!e) { /* out of memory */ return NULL; } if( kc < 0) { p->llink = e; } else { p->rlink = e; } /* Non-NULL means inserted. */ return e; }
/* Inner search of the hash and synonym chains. */ static struct ts_entry * tsearch_inner( const void *key, struct hs_base* head, int (*compar)(const void *, const void *), const enum search_intent_t intent, int*inserted, /* owner_ptr used for delete. Only set if the to-be-deleted item is on a chain, not in the hashtab. Points to the item pointing to the to-be-deleted-item.*/ struct ts_entry **owner_ptr) { struct ts_entry *s =0; struct ts_entry *c =0; struct ts_entry *q =0; int kc = 0; unsigned long keyhash = 0; unsigned long hindx = 0; struct ts_entry *chain_parent = 0; if(! head->hashfunc_) { /* Not fully initialized. */ return NULL; } keyhash = head->hashfunc_(key); if (intent == want_insert) { if( head->record_count_ > head->allowed_fill_) { resize_table(head,compar); } } hindx = keyhash%head->tablesize_; s = &head->hashtab_[hindx]; if(!s->entryused) { /* Not found. */ if(intent != want_insert) { return NULL; } /* Insert in the base hash table in an empty slot. */ *inserted = 1; head->record_count_++; s->keyptr = (const void *)key; s->entryused = 1; s->next = 0; return s; } kc = compar(key,s->keyptr); if(kc == 0 ) { /* found! */ if(want_delete) { *owner_ptr = 0; } return (void *)&(s->keyptr); } chain_parent = s; for(c = s->next; c; c = c->next) { kc = compar(key,c->keyptr); if(kc == 0 ) { /* found! */ if(want_delete) { *owner_ptr = chain_parent; } return (void *)&(c->keyptr); } chain_parent = c; } if(intent != want_insert) { return NULL; } /* Insert following head record of the chain. */ q = allocate_ts_entry(key); if (!q) { return q; } q->next = s->next; s->next = q; head->record_count_++; *inserted = 1; return q; }