diff src/protocols/jabber/genhash.c @ 3127:4e7cefc55971

[gaim-migrate @ 3142] Upgraded jabber to most recent stable version committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Thu, 04 Apr 2002 03:04:57 +0000
parents 424a40f12a6c
children
line wrap: on
line diff
--- a/src/protocols/jabber/genhash.c	Thu Apr 04 00:59:12 2002 +0000
+++ b/src/protocols/jabber/genhash.c	Thu Apr 04 03:04:57 2002 +0000
@@ -1,490 +1,101 @@
-/*
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
+/* --------------------------------------------------------------------------
+ *
+ * License
  *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
+ * The contents of this file are subject to the Jabber Open Source License
+ * Version 1.0 (the "JOSL").  You may not copy or use this file, in either
+ * source code or executable form, except in compliance with the JOSL. You
+ * may obtain a copy of the JOSL at http://www.jabber.org/ or at
+ * http://www.opensource.org/.  
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Software distributed under the JOSL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL
+ * for the specific language governing rights and limitations under the
+ * JOSL.
  *
- *  Jabber
- *  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
- */
-#include <libxode.h>
-
-/*****************************************************************************
- * Internal type definitions
- */
-
-typedef struct tagHNODE
-{
-    struct tagHNODE *next;             /* next node in list */
-    const void *key;                   /* key pointer */
-    void *value;                       /* value pointer */
-} HNODE;
-
-#define SLAB_NUM_NODES     64        /* allocate this many nodes per slab */
-
-typedef struct tagHSLAB
-{
-    struct tagHSLAB *next;             /* next slab pointer */
-    HNODE nodes[SLAB_NUM_NODES];       /* the actual nodes */
-} HSLAB;
-
-#define HASH_NUM_BUCKETS   509       /* should be a prime number; see Knuth */
-
-typedef struct tagHASHTABLE_INTERNAL
-{
-    unsigned long sig1;                /* first signature word */
-    KEYHASHFUNC hash;                  /* hash function */
-    KEYCOMPAREFUNC cmp;                /* comparison function */
-    int count;                         /* table entry count */
-    int bcount;                        /* bucket count */
-    HNODE **buckets;                   /* the hash buckets */
-    unsigned long sig2;                /* second signature word */
-
-} HASHTABLE_INTERNAL;
-
-#define HASH_SIG1      0x68736148UL  /* "Hash" */
-#define HASH_SIG2      0x6F627245UL  /* "Erbo" */
-
-#define do_hash(tb,key)     ((*((tb)->hash))(key) % ((tb)->bcount))
-
-static HNODE *s_free_nodes = NULL;   /* free nodes list */
-static HSLAB *s_slabs = NULL;        /* node slabs list */
-
-/*****************************************************************************
- * Internal functions
- */
-
-static HNODE *allocate_node(
-    const void *key,   /* key pointer for this node */
-    void *value)       /* value pointer for this node */
-/*
-    allocate_node allocates a new hash node and fills it.  Returns NULL if the
-    node could not be allocated.
-*/
-{
-    HNODE *rc;   /* return from this function */
+ * Copyrights
+ * 
+ * Portions created by or assigned to Jabber.com, Inc. are 
+ * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
+ * information for Jabber.com, Inc. is available at http://www.jabber.com/.
+ *
+ * Portions Copyright (c) 1998-1999 Jeremie Miller.
+ * 
+ * Acknowledgements
+ * 
+ * Special thanks to the Jabber Open Source Contributors for their
+ * suggestions and support of Jabber.
+ * 
+ * Alternatively, the contents of this file may be used under the terms of the
+ * GNU General Public License Version 2 or later (the "GPL"), in which case
+ * the provisions of the GPL are applicable instead of those above.  If you
+ * wish to allow use of your version of this file only under the terms of the
+ * GPL and not to allow others to use your version of this file under the JOSL,
+ * indicate your decision by deleting the provisions above and replace them
+ * with the notice and other provisions required by the GPL.  If you do not
+ * delete the provisions above, a recipient may use your version of this file
+ * under either the JOSL or the GPL. 
+ * 
+ * 
+ * --------------------------------------------------------------------------*/
 
-    if (!s_free_nodes)
-    { /* allocate a new slabful of nodes and chain them to make a new free list */
-        register int i;  /* loop counter */
-        HSLAB *slab = (HSLAB *)malloc(sizeof(HSLAB));
-        if (!slab)
-            return NULL;
-        memset(slab,0,sizeof(HSLAB));
-        slab->next = s_slabs;
-        for (i=0; i<(SLAB_NUM_NODES-1); i++)
-            slab->nodes[i].next = &(slab->nodes[i+1]);
-        s_free_nodes = &(slab->nodes[0]);
-        s_slabs = slab;
-
-    } /* end if */
+#include "lib.h"
 
-    /* grab a node off the fron of the free list and fill it */
-    rc = s_free_nodes;
-    s_free_nodes = rc->next;
-    rc->next = NULL;
-    rc->key = key;
-    rc->value = value;
-    return rc;
-
-} /* end allocate_node */
-
-static void free_node(
-    HNODE *node)   /* node to be freed */
-/*
-    free_node returns a hash node to the list.
-*/
-{
-    /* zap the node contents to avoid problems later */
-    memset(node,0,sizeof(HNODE));
-
-    /* chain it onto the free list */
-    node->next = s_free_nodes;
-    s_free_nodes = node;
+/*** stubs that hook back to new xhash */
 
-} /* end free_node */
-
-static HNODE *find_node(
-    HASHTABLE_INTERNAL *tab,  /* pointer to hash table */
-    const void *key,          /* key value to look up */
-    int bucket)               /* bucket number (-1 to have function compute it) */
-/*
-    find_node walks a hash bucket to find a node whose key matches the named key value.
-    Returns the node pointer, or NULL if it's not found.
-*/
+HASHTABLE ghash_create(int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp)
 {
-    register HNODE *p;  /* search pointer/return from this function */
-
-    if (bucket<0)  /* compute hash value if we don't know it already */
-        bucket = do_hash(tab,key);
-
-    /* search through the bucket contents */
-    for (p=tab->buckets[bucket]; p; p=p->next)
-        if ((*(tab->cmp))(key,p->key)==0)
-            return p;  /* found! */
-
-    return NULL;   /* not found */
-
-} /* end find_node */
-
-static HASHTABLE_INTERNAL *handle2ptr(
-    HASHTABLE tbl)  /* hash table handle */
-/*
-    handle2ptr converts a hash table handle into a pointer and checks its signatures
-    to make sure someone's not trying to pull a whizzer on this module.
-*/
-{
-    register HASHTABLE_INTERNAL *rc = (HASHTABLE_INTERNAL *)tbl;
-    if ((rc->sig1==HASH_SIG1) && (rc->sig2==HASH_SIG2))
-        return rc;     /* signatures match */
-    else
-        return NULL;   /* yIkes! */
+    return xhash_new(buckets);
 }
 
-/*****************************************************************************
- * External functions
- */
-
-HASHTABLE ghash_create(int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp)
-/*
-    Description:
-        Creates a new hash table.
-
-    Input:
-        Parameters:
-        buckets - Number of buckets to allocate for the hash table; this value
-                  should be a prime number for maximum efficiency.
-        hash - Key hash code function to use.
-        cmp - Key comparison function to use.
-
-    Output:
-        Returns:
-        NULL - Table could not be allocated.
-        Other - Handle to the new hashtable.
-*/
+HASHTABLE ghash_create_pool(pool p, int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp)
 {
-    HASHTABLE_INTERNAL *tab;  /* new table structure */
-    char *allocated;
-
-    if (!hash || !cmp)
-        return NULL;  /* bogus! */
-
-    if (buckets<=0)
-        buckets = HASH_NUM_BUCKETS;
-
-    /* allocate a hash table structure */
-    allocated = malloc(sizeof(HASHTABLE_INTERNAL) + (buckets * sizeof(HNODE *)));
-    if (!allocated)
-        return NULL;  /* memory error */
-
-    /* fill the fields of the hash table */
-    tab = (HASHTABLE_INTERNAL *)allocated;
-    allocated += sizeof(HASHTABLE_INTERNAL);
-    memset(tab,0,sizeof(HASHTABLE_INTERNAL));
-    memset(allocated,0,buckets * sizeof(HNODE *));
-    tab->sig1 = HASH_SIG1;
-    tab->hash = hash;
-    tab->cmp = cmp;
-    tab->bcount = buckets;
-    tab->buckets = (HNODE **)allocated;
-    tab->sig2 = HASH_SIG2;
-
-    return (HASHTABLE)tab;  /* Qa'pla! */
-
-} /* end ghash_create */
+    xht h = xhash_new(buckets);
+    pool_cleanup(p, (pool_cleaner)xhash_free, h);
+    return h;
+}
 
 void ghash_destroy(HASHTABLE tbl)
-/*
-    Description:
-        Destroys a hash table.
-
-    Input:
-        Parameters:
-        tbl - Table to be destroyed.
-
-    Output:
-        Returns:
-        Nothing.
-*/
 {
-    HASHTABLE_INTERNAL *tab;  /* new table structure */
-    int i;                    /* loop counter */
-    HNODE *p, *p2;            /* temporary pointers */
-
-    if (!tbl)
-        return;  /* bogus! */
-
-    /* Convert the handle to a table pointer. */
-    tab = handle2ptr(tbl);
-    if (!tab)
-        return;
-
-    /* Nuke the nodes it contains. */
-    for (i=0; i<tab->bcount; i++)
-    { /* free the contents of each bucket */
-        p = tab->buckets[i];
-        while (p)
-        { /* free each node in turn */
-            p2 = p->next;
-            free_node(p);
-            p = p2;
-
-        } /* end while */
-
-    } /* end for */
-
-    free(tab);  /* bye bye now! */
-
-} /* end ghash_destroy */
+    xhash_free(tbl);
+}
 
 void *ghash_get(HASHTABLE tbl, const void *key)
-/*
-    Description:
-        Retrieves a value stored in the hash table.
-
-    Input:
-        Parameters:
-        tbl - The hash table to look in.
-        key - The key value to search on.
-
-    Output:
-        Returns:
-        NULL - Value not found.
-        Other - Value corresponding to the specified key.
-*/
 {
-    HASHTABLE_INTERNAL *tab;  /* internal table pointer */
-    HNODE *node;              /* hash node */
-    void *rc = NULL;          /* return from this function */
-
-    if (!tbl || !key)
-        return NULL;  /* bogus! */
-
-    /* Convert the handle to a table pointer. */
-    tab = handle2ptr(tbl);
-    if (!tab)
-        return NULL;  /* error */
-
-    /* Attempt to find the node. */
-    node = find_node(tab,key,-1);
-    if (node)
-        rc = node->value;  /* found it! */
-
-    return rc;
-
-} /* end ghash_get */
+    return xhash_get(tbl, key);
+}
 
 int ghash_put(HASHTABLE tbl, const void *key, void *value)
-/*
-    Description:
-        Associates a key with a value in this hash table.
-
-    Input:
-        Parameters:
-        tbl - Hash table to add.
-        key - Key to use for the value in the table.
-        value - Value to add for this key.
-
-    Output:
-        Returns:
-        1 - Success.
-        0 - Failure.
-
-    Notes:
-        If the specified key is already in the hashtable, its value will be replaced.
-*/
 {
-    HASHTABLE_INTERNAL *tab;  /* internal table pointer */
-    int bucket;               /* bucket value goes into */
-    HNODE *node;              /* hash node */
-    int rc = 1;               /* return from this function */
-
-    if (!tbl || !key || !value)
-        return 0;  /* bogus! */
-
-    /* Convert the handle to a table pointer. */
-    tab = handle2ptr(tbl);
-    if (!tab)
-        return 0;  /* error */
-
-
-    /* Compute the hash bucket and try to find an existing node. */
-    bucket = do_hash(tab,key);
-    node = find_node(tab,key,bucket);
-    if (!node)
-    { /* OK, try to allocate a new node. */
-        node = allocate_node(key,value);
-        if (node)
-        { /* Chain the new node into the hash table. */
-            node->next = tab->buckets[bucket];
-            tab->buckets[bucket] = node;
-            tab->count++;
-
-        } /* end if */
-        else  /* allocation error */
-            rc = 0;
-
-    } /* end if */
-    else  /* already in table - just reassign value */
-        node->value = value;
-
-    return rc;
-
-} /* end ghash_put */
+    xhash_put(tbl, key, value);
+    return 1;
+}
 
 int ghash_remove(HASHTABLE tbl, const void *key)
-/*
-    Description:
-        Removes an entry from a hash table, given its key.
-    
-    Input:
-        Parameters:
-        tbl - Hash table to remove from.
-        key - Key of value to remove.
-
-    Output:
-        Returns:
-        1 - Success.
-        0 - Failure; key not present in hash table.
-*/
 {
-    HASHTABLE_INTERNAL *tab;  /* internal table pointer */
-    int bucket;               /* bucket value goes into */
-    HNODE *node;              /* hash node */
-    register HNODE *p;        /* removal pointer */
-    int rc = 1;               /* return from this function */
-
-    if (!tbl || !key)
-        return 0;  /* bogus! */
+    xhash_zap(tbl, key);
+    return 1;
+}
 
-    /* Convert the handle to a table pointer. */
-    tab = handle2ptr(tbl);
-    if (!tab)
-        return 0;  /* error */
-
-
-    /* Compute the hash bucket and try to find an existing node. */
-    bucket = do_hash(tab,key);
-    node = find_node(tab,key,bucket);
-    if (node)
-    { /* look to unchain it from the bucket it's in */
-        if (node==tab->buckets[bucket])
-            tab->buckets[bucket] = node->next;  /* unchain at head */
-        else
-        { /* unchain in middle of list */
-            for (p=tab->buckets[bucket]; p->next!=node; p=p->next) ;
-            p->next = node->next;
-
-        } /* end else */
-
-        free_node(node);  /* bye bye now! */
-        tab->count--;
-
-    } /* end if */
-    else  /* node not found */
-        rc = 0;
-
-    return rc;
-
-} /* end ghash_remove */
 
 int ghash_walk(HASHTABLE tbl, TABLEWALKFUNC func, void *user_data)
-/*
-    Description:
-        "Walks" through a hash table, calling a callback function for each element
-    stored in it.
-
-    Input:
-        Parameters:
-        tbl - Hash table to walk.
-        func - Function to be called for each node.  It takes three parameters,
-                   a user data pointer, a key value pointer, and a data value pointer.
-           It returns 0 to stop the enumeration or 1 to keep it going.
-        user_data - Value to use as the first parameter for the callback
-                    function.
+{
+    int i;
+    xhn n;
+    xht h = (xht)tbl;
 
-    Output:
-        Returns:
-        0 - Error occurred.
-        Other - Number of nodes visited up to and including the one for which
-                the callback function returned 0, if it did; ranges from 1
-            to the number of nodes in the hashtable.
-*/
-{
-    HASHTABLE_INTERNAL *tab;  /* internal table pointer */
-    int i;                    /* loop counter */
-    int running = 1;          /* we're still running */
-    int count = 0;            /* number of nodes visited before stop node */
-    register HNODE *p, *p2;   /* loop pointer */
+    for(i = 0; i < h->prime; i++)
+        for(n = &h->zen[i]; n != NULL; n = n->next)
+            if(n->key != NULL && n->val != NULL)
+                (*func)(user_data, n->key, n->val);
 
-    if (!tbl || !func)
-        return -1;  /* bogus values! */
-
-    /* Convert the handle to a table pointer. */
-    tab = handle2ptr(tbl);
-    if (!tab)
-        return -1;  /* error */
+    return 1;
+}
 
 
-    for (i=0; running && (i<tab->bcount); i++)
-    { /* visit the contents of each bucket */
-        p = tab->buckets[i];
-        while (running && p)
-        { /* visit each node in turn */
-            p2 = p->next;
-            count++;
-            running = (*func)(user_data,p->key,p->value);
-            p = p2;
-
-        } /* end while */
-
-    } /* end for */
-
-    return count;
-
-} /* end ghash_walk */
-
+int _xhasher(const char *key);
 int str_hash_code(const char *s)
-/*
-    Description:
-        Generates a hash code for a string.  This function uses the ELF hashing
-        algorithm as reprinted in Andrew Binstock, "Hashing Rehashed," _Dr.
-        Dobb's Journal_, April 1996.
- 
-    Input:
-        Parameters:
-            s - The string to be hashed.
- 
-    Output:
-        Returns:
-            A hash code for the string.
-*/
 {
-    /* ELF hash uses unsigned chars and unsigned arithmetic for portability */
-    const unsigned char *name = (const unsigned char *)s;
-    unsigned long h = 0, g;
-
-    if (!name)
-        return 0;  /* anti-NULL guard not in the original */
+    return _xhasher(s);
+}
 
-    while (*name)
-    { /* do some fancy bitwanking on the string */
-        h = (h << 4) + (unsigned long)(*name++);
-        if ((g = (h & 0xF0000000UL))!=0)
-            h ^= (g >> 24);
-        h &= ~g;
-
-    } /* end while */
-
-    return (int)h;
-
-}