示例#1
0
/* Search. */
void *
dwarf_tfind(const void *key, void *const *rootp,
            int (*compar)(const void *, const void *))
{
    /*  Nothing will change, but we discard const
        so we can use tsearch_inner(). */
    struct hs_base **proot = (struct hs_base **)rootp;
    struct hs_base *head = *proot;
    struct ts_entry *r = 0;
    /* inserted flag won't be set. */
    int inserted = 0;
    /* nullme won't be set. */
    struct ts_entry * nullme = 0;
    /* Get to actual tree. */

    if (!head) {
        return NULL;
    }

    r = tsearch_inner(key,head,compar,only_find,&inserted,&nullme);
    if(!r) {
        return NULL;
    }
    return (void *)(&(r->keyptr));
}
示例#2
0
/*  Unlike the simple binary tree case,
    a fully-empty hash situation does not null the *rootp
*/
void *
dwarf_tdelete(const void *key, void **rootp,
              int (*compar)(const void *, const void *))
{
    struct hs_base **proot = (struct hs_base **)rootp;
    struct hs_base *head = *proot;
    struct ts_entry *found = 0;
    /* inserted flag won't be set. */
    int inserted = 0;
    struct ts_entry * parentp = 0;

    if (!head) {
        return NULL;
    }

    found = tsearch_inner(key,head,compar,want_delete,&inserted,
                          &parentp);
    if(found) {
        if(parentp) {
            /* Delete a chain entry. */
            head->record_count_--;
            parentp->next = found->next;
            /*  We free our storage. It would be up
                to caller to do a tfind to find
                a record and delete content if necessary. */
            free(found);
            return (void *)&(parentp->keyptr);
        }
        /* So found is the head of a chain. */
        if(found->next) {
            /*  Delete a chain entry, pull up to hash tab, freeing
                up the chain entry. */
            struct ts_entry *pullup = found->next;
            *found = *pullup;
            free(pullup);
            head->record_count_--;
            return (void *)&(found->keyptr);
        } else {
            /*  Delete a main hash table entry.
                Problem: what the heck to return as a keyptr pointer?
                Well, we return NULL. As in the standard
                tsearch, returning NULL does not mean
                failure! Here it just means 'empty chain somewhere'.
            */
            head->record_count_--;
            found->next = 0;
            found->keyptr = 0;
            found->entryused = 0;
            return NULL;
        }
    }
    return NULL;
}
示例#3
0
/* 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);
}
示例#4
0
/* Search and, if missing, insert. */
void *
dwarf_tsearch(const void *key, void **headin,
              int (*compar)(const void *, const void *))
{
    struct hs_base **rootp = (struct hs_base **)headin;
    struct hs_base *head = *rootp;
    struct ts_entry *r = 0;
    int inserted = 0;
    /* nullme won't be set. */
    struct ts_entry *nullme = 0;

    if (!head) {
        /* something is wrong here, not initialized. */
        return NULL;
    }
    r = tsearch_inner(key,head,compar,want_insert,&inserted,&nullme);
    if (!r) {
        return NULL;
    }
    return (void *)&(r->keyptr);
}
示例#5
0
/* 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);
}
示例#6
0
static void
resize_table(struct hs_base *head,
             int (*compar)(const void *, const void *))
{
    struct hs_base newhead;
    unsigned new_entry_index = 0;
    unsigned long prime_to_use = 0;

    /* Copy the values we have. */
    newhead = *head;
    /* But drop the hashtab_ from new. calloc below. */
    newhead.hashtab_ = 0;
    newhead.record_count_ = 0;
    new_entry_index = head->tablesize_entry_index_ +1;
    prime_to_use = primes[new_entry_index];
    if(prime_to_use == 0) {
        /*  Oops, too large. Leave table size as is, though
            it will get slow as it overfills. */
        return;
    }
    newhead.tablesize_ = prime_to_use;
    newhead.allowed_fill_ = calculate_allowed_fill(allowed_fill_percent,
                            prime_to_use);
    if( newhead.allowed_fill_< (newhead.tablesize_/2)) {
        /* Oops. We are in trouble.  */
        return;
    }
    newhead.tablesize_entry_index_ = new_entry_index;
    newhead.hashtab_ = calloc(sizeof(struct ts_entry),newhead.tablesize_);
    if(!newhead.hashtab_) {
        /*  Oops, too large. Leave table size as is, though
            things will get slow as it overfills. */
        free(newhead.hashtab_);
        return;
    }
    {
        /*  Insert all the records from the old table into
            the new table. */
        int fillnewfail = 0;
        unsigned long ix = 0;
        unsigned long tsize = head->tablesize_;
        struct ts_entry *p = &head->hashtab_[0];
        for(  ; ix < tsize; ix++,p++) {
            int inserted = 0;
            struct ts_entry*n = 0;
            if(fillnewfail) {
                break;
            }
            if(p->keyptr) {
                tsearch_inner(p->keyptr,
                              &newhead,compar,
                              want_insert,
                              &inserted,
                              0);
                if(!inserted) {
                    fillnewfail = 1;
                    break;
                }
            }
            for(n = p->next; n ; n = n->next) {
                inserted = 0;
                tsearch_inner(n->keyptr,
                              &newhead,compar,
                              want_insert,
                              &inserted,
                              0);
                if(!inserted) {
                    fillnewfail = 1;
                    break;
                }
            }
        }
        if(fillnewfail) {
            free(newhead.hashtab_);
            return;
        }
    }
    /* Now get rid of the chain entries of the old table. */
    dwarf_tdestroy_inner(head,0,0);
    /* Now get rid of the old table itself. */
    free(head->hashtab_);
    head->hashtab_ = 0;
    *head = newhead;
    return;
}