mcabber/libjabber/genhash.c
author Mikael Berthe <mikael@lilotux.net>
Mon, 15 May 2006 23:06:13 +0200
changeset 857 ef35a2bb40d7
parent 417 c3ae9251c197
permissions -rw-r--r--
scr_LogPrint(): do not use static buffer size
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
25
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     1
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     2
 *  This program is free software; you can redistribute it and/or modify
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     3
 *  it under the terms of the GNU General Public License as published by
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     4
 *  the Free Software Foundation; either version 2 of the License, or
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     5
 *  (at your option) any later version.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     6
 *
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     7
 *  This program is distributed in the hope that it will be useful,
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     8
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     9
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    10
 *  GNU General Public License for more details.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    11
 *
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    12
 *  You should have received a copy of the GNU General Public License
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    13
 *  along with this program; if not, write to the Free Software
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    14
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    15
 *
417
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    16
 * Copyrights
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    17
 *
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    18
 * Portions created by or assigned to Jabber.com, Inc. are 
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    19
 * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    20
 * information for Jabber.com, Inc. is available at http://www.jabber.com/.
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    21
 *
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    22
 * Portions Copyright (c) 1998-1999 Jeremie Miller.
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    23
 *
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    24
 * Acknowledgements
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    25
 *
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    26
 * Special thanks to the Jabber Open Source Contributors for their
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    27
 * suggestions and support of Jabber.
c3ae9251c197 Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents: 414
diff changeset
    28
 *
25
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    29
 */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    30
#include <libxode.h>
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    31
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    32
/*****************************************************************************
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    33
 * Internal type definitions
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    34
 */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    35
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    36
typedef struct tagHNODE
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    37
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    38
    struct tagHNODE *next;             /* next node in list */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    39
    const void *key;                   /* key pointer */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    40
    void *value;                       /* value pointer */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    41
} HNODE;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    42
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    43
#define SLAB_NUM_NODES     64        /* allocate this many nodes per slab */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    44
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    45
typedef struct tagHSLAB
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    46
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    47
    struct tagHSLAB *next;             /* next slab pointer */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    48
    HNODE nodes[SLAB_NUM_NODES];       /* the actual nodes */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    49
} HSLAB;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    50
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    51
#define HASH_NUM_BUCKETS   509       /* should be a prime number; see Knuth */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    52
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    53
typedef struct tagHASHTABLE_INTERNAL
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    54
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    55
    unsigned long sig1;                /* first signature word */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    56
    KEYHASHFUNC hash;                  /* hash function */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    57
    KEYCOMPAREFUNC cmp;                /* comparison function */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    58
    int count;                         /* table entry count */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    59
    int bcount;                        /* bucket count */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    60
    HNODE **buckets;                   /* the hash buckets */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    61
    unsigned long sig2;                /* second signature word */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    62
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    63
} HASHTABLE_INTERNAL;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    64
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    65
#define HASH_SIG1      0x68736148UL  /* "Hash" */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    66
#define HASH_SIG2      0x6F627245UL  /* "Erbo" */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    67
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    68
#define do_hash(tb,key)     ((*((tb)->hash))(key) % ((tb)->bcount))
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    69
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    70
static HNODE *s_free_nodes = NULL;   /* free nodes list */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    71
static HSLAB *s_slabs = NULL;        /* node slabs list */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    72
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    73
/*****************************************************************************
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    74
 * Internal functions
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    75
 */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    76
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    77
static HNODE *allocate_node(
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    78
    const void *key,   /* key pointer for this node */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    79
    void *value)       /* value pointer for this node */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    80
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    81
    allocate_node allocates a new hash node and fills it.  Returns NULL if the
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    82
    node could not be allocated.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    83
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    84
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    85
    HNODE *rc;   /* return from this function */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    86
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    87
    if (!s_free_nodes)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    88
    { /* allocate a new slabful of nodes and chain them to make a new free list */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    89
        register int i;  /* loop counter */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    90
        HSLAB *slab = (HSLAB *)malloc(sizeof(HSLAB));
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    91
        if (!slab)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    92
            return NULL;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    93
        memset(slab,0,sizeof(HSLAB));
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    94
        slab->next = s_slabs;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    95
        for (i=0; i<(SLAB_NUM_NODES-1); i++)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    96
            slab->nodes[i].next = &(slab->nodes[i+1]);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    97
        s_free_nodes = &(slab->nodes[0]);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    98
        s_slabs = slab;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    99
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   100
    } /* end if */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   101
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   102
    /* grab a node off the fron of the free list and fill it */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   103
    rc = s_free_nodes;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   104
    s_free_nodes = rc->next;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   105
    rc->next = NULL;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   106
    rc->key = key;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   107
    rc->value = value;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   108
    return rc;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   109
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   110
} /* end allocate_node */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   111
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   112
static void free_node(
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   113
    HNODE *node)   /* node to be freed */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   114
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   115
    free_node returns a hash node to the list.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   116
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   117
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   118
    /* zap the node contents to avoid problems later */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   119
    memset(node,0,sizeof(HNODE));
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   120
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   121
    /* chain it onto the free list */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   122
    node->next = s_free_nodes;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   123
    s_free_nodes = node;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   124
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   125
} /* end free_node */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   126
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   127
static HNODE *find_node(
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   128
    HASHTABLE_INTERNAL *tab,  /* pointer to hash table */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   129
    const void *key,          /* key value to look up */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   130
    int bucket)               /* bucket number (-1 to have function compute it) */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   131
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   132
    find_node walks a hash bucket to find a node whose key matches the named key value.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   133
    Returns the node pointer, or NULL if it's not found.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   134
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   135
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   136
    register HNODE *p;  /* search pointer/return from this function */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   137
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   138
    if (bucket<0)  /* compute hash value if we don't know it already */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   139
        bucket = do_hash(tab,key);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   140
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   141
    /* search through the bucket contents */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   142
    for (p=tab->buckets[bucket]; p; p=p->next)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   143
        if ((*(tab->cmp))(key,p->key)==0)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   144
            return p;  /* found! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   145
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   146
    return NULL;   /* not found */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   147
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   148
} /* end find_node */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   149
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   150
static HASHTABLE_INTERNAL *handle2ptr(
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   151
    HASHTABLE tbl)  /* hash table handle */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   152
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   153
    handle2ptr converts a hash table handle into a pointer and checks its signatures
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   154
    to make sure someone's not trying to pull a whizzer on this module.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   155
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   156
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   157
    register HASHTABLE_INTERNAL *rc = (HASHTABLE_INTERNAL *)tbl;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   158
    if ((rc->sig1==HASH_SIG1) && (rc->sig2==HASH_SIG2))
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   159
        return rc;     /* signatures match */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   160
    else
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   161
        return NULL;   /* yIkes! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   162
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   163
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   164
/*****************************************************************************
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   165
 * External functions
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   166
 */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   167
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   168
HASHTABLE ghash_create(int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   169
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   170
    Description:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   171
        Creates a new hash table.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   172
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   173
    Input:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   174
        Parameters:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   175
        buckets - Number of buckets to allocate for the hash table; this value
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   176
                  should be a prime number for maximum efficiency.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   177
        hash - Key hash code function to use.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   178
        cmp - Key comparison function to use.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   179
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   180
    Output:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   181
        Returns:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   182
        NULL - Table could not be allocated.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   183
        Other - Handle to the new hashtable.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   184
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   185
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   186
    HASHTABLE_INTERNAL *tab;  /* new table structure */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   187
    char *allocated;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   188
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   189
    if (!hash || !cmp)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   190
        return NULL;  /* bogus! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   191
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   192
    if (buckets<=0)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   193
        buckets = HASH_NUM_BUCKETS;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   194
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   195
    /* allocate a hash table structure */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   196
    allocated = malloc(sizeof(HASHTABLE_INTERNAL) + (buckets * sizeof(HNODE *)));
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   197
    if (!allocated)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   198
        return NULL;  /* memory error */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   199
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   200
    /* fill the fields of the hash table */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   201
    tab = (HASHTABLE_INTERNAL *)allocated;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   202
    allocated += sizeof(HASHTABLE_INTERNAL);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   203
    memset(tab,0,sizeof(HASHTABLE_INTERNAL));
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   204
    memset(allocated,0,buckets * sizeof(HNODE *));
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   205
    tab->sig1 = HASH_SIG1;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   206
    tab->hash = hash;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   207
    tab->cmp = cmp;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   208
    tab->bcount = buckets;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   209
    tab->buckets = (HNODE **)allocated;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   210
    tab->sig2 = HASH_SIG2;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   211
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   212
    return (HASHTABLE)tab;  /* Qa'pla! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   213
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   214
} /* end ghash_create */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   215
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   216
void ghash_destroy(HASHTABLE tbl)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   217
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   218
    Description:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   219
        Destroys a hash table.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   220
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   221
    Input:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   222
        Parameters:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   223
        tbl - Table to be destroyed.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   224
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   225
    Output:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   226
        Returns:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   227
        Nothing.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   228
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   229
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   230
    HASHTABLE_INTERNAL *tab;  /* new table structure */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   231
    int i;                    /* loop counter */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   232
    HNODE *p, *p2;            /* temporary pointers */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   233
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   234
    if (!tbl)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   235
        return;  /* bogus! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   236
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   237
    /* Convert the handle to a table pointer. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   238
    tab = handle2ptr(tbl);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   239
    if (!tab)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   240
        return;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   241
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   242
    /* Nuke the nodes it contains. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   243
    for (i=0; i<tab->bcount; i++)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   244
    { /* free the contents of each bucket */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   245
        p = tab->buckets[i];
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   246
        while (p)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   247
        { /* free each node in turn */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   248
            p2 = p->next;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   249
            free_node(p);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   250
            p = p2;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   251
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   252
        } /* end while */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   253
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   254
    } /* end for */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   255
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   256
    free(tab);  /* bye bye now! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   257
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   258
} /* end ghash_destroy */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   259
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   260
void *ghash_get(HASHTABLE tbl, const void *key)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   261
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   262
    Description:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   263
        Retrieves a value stored in the hash table.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   264
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   265
    Input:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   266
        Parameters:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   267
        tbl - The hash table to look in.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   268
        key - The key value to search on.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   269
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   270
    Output:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   271
        Returns:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   272
        NULL - Value not found.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   273
        Other - Value corresponding to the specified key.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   274
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   275
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   276
    HASHTABLE_INTERNAL *tab;  /* internal table pointer */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   277
    HNODE *node;              /* hash node */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   278
    void *rc = NULL;          /* return from this function */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   279
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   280
    if (!tbl || !key)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   281
        return NULL;  /* bogus! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   282
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   283
    /* Convert the handle to a table pointer. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   284
    tab = handle2ptr(tbl);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   285
    if (!tab)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   286
        return NULL;  /* error */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   287
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   288
    /* Attempt to find the node. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   289
    node = find_node(tab,key,-1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   290
    if (node)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   291
        rc = node->value;  /* found it! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   292
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   293
    return rc;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   294
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   295
} /* end ghash_get */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   296
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   297
int ghash_put(HASHTABLE tbl, const void *key, void *value)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   298
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   299
    Description:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   300
        Associates a key with a value in this hash table.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   301
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   302
    Input:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   303
        Parameters:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   304
        tbl - Hash table to add.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   305
        key - Key to use for the value in the table.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   306
        value - Value to add for this key.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   307
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   308
    Output:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   309
        Returns:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   310
        1 - Success.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   311
        0 - Failure.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   312
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   313
    Notes:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   314
        If the specified key is already in the hashtable, its value will be replaced.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   315
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   316
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   317
    HASHTABLE_INTERNAL *tab;  /* internal table pointer */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   318
    int bucket;               /* bucket value goes into */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   319
    HNODE *node;              /* hash node */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   320
    int rc = 1;               /* return from this function */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   321
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   322
    if (!tbl || !key || !value)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   323
        return 0;  /* bogus! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   324
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   325
    /* Convert the handle to a table pointer. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   326
    tab = handle2ptr(tbl);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   327
    if (!tab)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   328
        return 0;  /* error */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   329
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   330
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   331
    /* Compute the hash bucket and try to find an existing node. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   332
    bucket = do_hash(tab,key);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   333
    node = find_node(tab,key,bucket);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   334
    if (!node)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   335
    { /* OK, try to allocate a new node. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   336
        node = allocate_node(key,value);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   337
        if (node)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   338
        { /* Chain the new node into the hash table. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   339
            node->next = tab->buckets[bucket];
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   340
            tab->buckets[bucket] = node;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   341
            tab->count++;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   342
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   343
        } /* end if */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   344
        else  /* allocation error */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   345
            rc = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   346
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   347
    } /* end if */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   348
    else  /* already in table - just reassign value */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   349
        node->value = value;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   350
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   351
    return rc;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   352
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   353
} /* end ghash_put */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   354
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   355
int ghash_remove(HASHTABLE tbl, const void *key)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   356
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   357
    Description:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   358
        Removes an entry from a hash table, given its key.
414
ec86d759ed54 Trailing whitespace cleanup
Mikael Berthe <mikael@lilotux.net>
parents: 25
diff changeset
   359
25
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   360
    Input:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   361
        Parameters:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   362
        tbl - Hash table to remove from.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   363
        key - Key of value to remove.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   364
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   365
    Output:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   366
        Returns:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   367
        1 - Success.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   368
        0 - Failure; key not present in hash table.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   369
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   370
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   371
    HASHTABLE_INTERNAL *tab;  /* internal table pointer */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   372
    int bucket;               /* bucket value goes into */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   373
    HNODE *node;              /* hash node */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   374
    register HNODE *p;        /* removal pointer */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   375
    int rc = 1;               /* return from this function */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   376
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   377
    if (!tbl || !key)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   378
        return 0;  /* bogus! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   379
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   380
    /* Convert the handle to a table pointer. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   381
    tab = handle2ptr(tbl);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   382
    if (!tab)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   383
        return 0;  /* error */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   384
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   385
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   386
    /* Compute the hash bucket and try to find an existing node. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   387
    bucket = do_hash(tab,key);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   388
    node = find_node(tab,key,bucket);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   389
    if (node)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   390
    { /* look to unchain it from the bucket it's in */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   391
        if (node==tab->buckets[bucket])
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   392
            tab->buckets[bucket] = node->next;  /* unchain at head */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   393
        else
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   394
        { /* unchain in middle of list */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   395
            for (p=tab->buckets[bucket]; p->next!=node; p=p->next) ;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   396
            p->next = node->next;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   397
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   398
        } /* end else */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   399
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   400
        free_node(node);  /* bye bye now! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   401
        tab->count--;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   402
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   403
    } /* end if */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   404
    else  /* node not found */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   405
        rc = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   406
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   407
    return rc;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   408
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   409
} /* end ghash_remove */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   410
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   411
int ghash_walk(HASHTABLE tbl, TABLEWALKFUNC func, void *user_data)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   412
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   413
    Description:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   414
        "Walks" through a hash table, calling a callback function for each element
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   415
    stored in it.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   416
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   417
    Input:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   418
        Parameters:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   419
        tbl - Hash table to walk.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   420
        func - Function to be called for each node.  It takes three parameters,
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   421
                   a user data pointer, a key value pointer, and a data value pointer.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   422
           It returns 0 to stop the enumeration or 1 to keep it going.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   423
        user_data - Value to use as the first parameter for the callback
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   424
                    function.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   425
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   426
    Output:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   427
        Returns:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   428
        0 - Error occurred.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   429
        Other - Number of nodes visited up to and including the one for which
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   430
                the callback function returned 0, if it did; ranges from 1
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   431
            to the number of nodes in the hashtable.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   432
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   433
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   434
    HASHTABLE_INTERNAL *tab;  /* internal table pointer */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   435
    int i;                    /* loop counter */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   436
    int running = 1;          /* we're still running */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   437
    int count = 0;            /* number of nodes visited before stop node */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   438
    register HNODE *p, *p2;   /* loop pointer */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   439
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   440
    if (!tbl || !func)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   441
        return -1;  /* bogus values! */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   442
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   443
    /* Convert the handle to a table pointer. */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   444
    tab = handle2ptr(tbl);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   445
    if (!tab)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   446
        return -1;  /* error */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   447
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   448
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   449
    for (i=0; running && (i<tab->bcount); i++)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   450
    { /* visit the contents of each bucket */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   451
        p = tab->buckets[i];
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   452
        while (running && p)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   453
        { /* visit each node in turn */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   454
            p2 = p->next;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   455
            count++;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   456
            running = (*func)(user_data,p->key,p->value);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   457
            p = p2;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   458
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   459
        } /* end while */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   460
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   461
    } /* end for */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   462
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   463
    return count;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   464
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   465
} /* end ghash_walk */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   466
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   467
int str_hash_code(const char *s)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   468
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   469
    Description:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   470
        Generates a hash code for a string.  This function uses the ELF hashing
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   471
        algorithm as reprinted in Andrew Binstock, "Hashing Rehashed," _Dr.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   472
        Dobb's Journal_, April 1996.
414
ec86d759ed54 Trailing whitespace cleanup
Mikael Berthe <mikael@lilotux.net>
parents: 25
diff changeset
   473
25
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   474
    Input:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   475
        Parameters:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   476
            s - The string to be hashed.
414
ec86d759ed54 Trailing whitespace cleanup
Mikael Berthe <mikael@lilotux.net>
parents: 25
diff changeset
   477
25
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   478
    Output:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   479
        Returns:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   480
            A hash code for the string.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   481
*/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   482
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   483
    /* ELF hash uses unsigned chars and unsigned arithmetic for portability */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   484
    const unsigned char *name = (const unsigned char *)s;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   485
    unsigned long h = 0, g;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   486
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   487
    if (!name)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   488
        return 0;  /* anti-NULL guard not in the original */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   489
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   490
    while (*name)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   491
    { /* do some fancy bitwanking on the string */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   492
        h = (h << 4) + (unsigned long)(*name++);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   493
        if ((g = (h & 0xF0000000UL))!=0)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   494
            h ^= (g >> 24);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   495
        h &= ~g;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   496
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   497
    } /* end while */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   498
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   499
    return (int)h;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   500
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   501
}