⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl_util_table.c

📁 mod_ssl-2.8.31-1.3.41.tar.gz 好用的ssl工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/*                      _             _**  _ __ ___   ___   __| |    ___ ___| |  mod_ssl** | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL** | | | | | | (_) | (_| |   \__ \__ \ |  www.modssl.org** |_| |_| |_|\___/ \__,_|___|___/___/_|  ftp.modssl.org**                      |_____|**  ssl_util_table.c**  High Performance Hash Table Functions*//* ==================================================================== * Copyright (c) 1999-2004 Ralf S. Engelschall. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following *    disclaimer in the documentation and/or other materials *    provided with the distribution. * * 3. All advertising materials mentioning features or use of this *    software must display the following acknowledgment: *    "This product includes software developed by *     Ralf S. Engelschall <rse@engelschall.com> for use in the *     mod_ssl project (http://www.modssl.org/)." * * 4. The names "mod_ssl" must not be used to endorse or promote *    products derived from this software without prior written *    permission. For written permission, please contact *    rse@engelschall.com. * * 5. Products derived from this software may not be called "mod_ssl" *    nor may "mod_ssl" appear in their names without prior *    written permission of Ralf S. Engelschall. * * 6. Redistributions of any form whatsoever must retain the following *    acknowledgment: *    "This product includes software developed by *     Ralf S. Engelschall <rse@engelschall.com> for use in the *     mod_ssl project (http://www.modssl.org/)." * * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== *//* * Generic hash table handler * Table 4.1.0 July-28-1998 * * This library is a generic open hash table with buckets and * linked lists.  It is pretty high performance.  Each element * has a key and a data.  The user indexes on the key to find the * data. * * Copyright 1998 by Gray Watson <gray@letters.com> * * Permission to use, copy, modify, and distribute this software for any * purpose and without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, * and that the name of Gray Watson not be used in advertising or * publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose.  It is provided "as is" * without express or implied warranty. * * Modified in March 1999 by Ralf S. Engelschall <rse@engelschall.com> * for use in the mod_ssl project: *   o merged table_loc.h header into table.c *   o removed fillproto-comments from table.h *   o removed mmap() support because it's too unportable *   o added support for MM library via ta_{malloc,calloc,realloc,free} */#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef WIN32#include <io.h>#include <errno.h>#else#include <unistd.h>#endif/* forward definitions for table.h */typedef struct table_st table_t;typedef struct table_entry_st table_entry_t;#define TABLE_PRIVATE#include "ssl_util_table.h"/****************************** local defines ******************************/#ifndef BITSPERBYTE#define BITSPERBYTE     8#endif#ifndef BITS#define BITS(type)      (BITSPERBYTE * (int)sizeof(type))#endif#define TABLE_MAGIC     0xBADF00D       /* very magic magicness */#define LINEAR_MAGIC    0xAD00D00       /* magic value for linear struct */#define DEFAULT_SIZE    1024    /* default table size */#define MAX_ALIGNMENT   128     /* max alignment value */#define MAX_SORT_SPLITS 128     /* qsort can handle 2^128 entries *//* returns 1 when we should grow or shrink the table */#define SHOULD_TABLE_GROW(tab)  ((tab)->ta_entry_n > (tab)->ta_bucket_n * 2)#define SHOULD_TABLE_SHRINK(tab) ((tab)->ta_entry_n < (tab)->ta_bucket_n / 2)/* * void HASH_MIX * * DESCRIPTION: * * Mix 3 32-bit values reversibly.  For every delta with one or two bits * set, and the deltas of all three high bits or all three low bits, * whether the original value of a,b,c is almost all zero or is * uniformly distributed. * * If HASH_MIX() is run forward or backward, at least 32 bits in a,b,c * have at least 1/4 probability of changing.  If mix() is run * forward, every bit of c will change between 1/3 and 2/3 of the * time.  (Well, 22/100 and 78/100 for some 2-bit deltas.) * * HASH_MIX() takes 36 machine instructions, but only 18 cycles on a * superscalar machine (like a Pentium or a Sparc).  No faster mixer * seems to work, that's the result of my brute-force search.  There * were about 2^68 hashes to choose from.  I only tested about a * billion of those. */#define HASH_MIX(a, b, c) \ do { \   a -= b; a -= c; a ^= (c >> 13); \   b -= c; b -= a; b ^= (a << 8); \   c -= a; c -= b; c ^= (b >> 13); \   a -= b; a -= c; a ^= (c >> 12); \   b -= c; b -= a; b ^= (a << 16); \   c -= a; c -= b; c ^= (b >> 5); \   a -= b; a -= c; a ^= (c >> 3); \   b -= c; b -= a; b ^= (a << 10); \   c -= a; c -= b; c ^= (b >> 15); \ } while(0)#define TABLE_POINTER(table, type, pnt)         (pnt)/* * Macros to get at the key and the data pointers */#define ENTRY_KEY_BUF(entry_p)          ((entry_p)->te_key_buf)#define ENTRY_DATA_BUF(tab_p, entry_p)  \     (ENTRY_KEY_BUF(entry_p) + (entry_p)->te_key_size)/* * Table structures... *//* * HACK: this should be equiv as the table_entry_t without the key_buf * char.  We use this with the ENTRY_SIZE() macro above which solves * the problem with the lack of the [0] GNU hack.  We use the * table_entry_t structure to better map the memory and make things * faster. */typedef struct table_shell_st {    unsigned int te_key_size;   /* size of data */    unsigned int te_data_size;  /* size of data */    struct table_shell_st *te_next_p;   /* pointer to next in the list */    /* NOTE: this does not have the te_key_buf field here */} table_shell_t;/* * Elements in the bucket linked-lists.  The key[1] is the start of * the key with the rest of the key and all of the data information * packed in memory directly after the end of this structure. * * NOTE: if this structure is changed, the table_shell_t must be changed * to match. */struct table_entry_st {    unsigned int te_key_size;   /* size of data */    unsigned int te_data_size;  /* size of data */    struct table_entry_st *te_next_p;   /* pointer to next in the list */    unsigned char te_key_buf[1];        /* 1st byte of key buf */};/* external structure for debuggers be able to see void */typedef table_entry_t table_entry_ext_t;/* main table structure */struct table_st {    unsigned int ta_magic;      /* magic number */    unsigned int ta_flags;      /* table's flags defined in table.h */    unsigned int ta_bucket_n;   /* num of buckets, should be 2^X */    unsigned int ta_entry_n;    /* num of entries in all buckets */    unsigned int ta_data_align; /* data alignment value */    table_entry_t **ta_buckets; /* array of linked lists */    table_linear_t ta_linear;   /* linear tracking */    unsigned long ta_file_size; /* size of on-disk space */    void *(*ta_malloc)(size_t size);    void *(*ta_calloc)(size_t number, size_t size);    void *(*ta_realloc)(void *ptr, size_t size);    void (*ta_free)(void *ptr);};/* external table structure for debuggers */typedef table_t table_ext_t;/* local comparison functions */typedef int (*compare_t) (const void *element1_p, const void *element2_p,                          table_compare_t user_compare,                          const table_t * table_p);/* * to map error to string */typedef struct {    int es_error;               /* error number */    char *es_string;            /* assocaited string */} error_str_t;static error_str_t errors[] ={    {TABLE_ERROR_NONE, "no error"},    {TABLE_ERROR_PNT, "invalid table pointer"},    {TABLE_ERROR_ARG_NULL, "buffer argument is null"},    {TABLE_ERROR_SIZE, "incorrect size argument"},    {TABLE_ERROR_OVERWRITE, "key exists and no overwrite"},    {TABLE_ERROR_NOT_FOUND, "key does not exist"},    {TABLE_ERROR_ALLOC, "error allocating memory"},    {TABLE_ERROR_LINEAR, "linear access not in progress"},    {TABLE_ERROR_OPEN, "could not open file"},    {TABLE_ERROR_SEEK, "could not seek to position in file"},    {TABLE_ERROR_READ, "could not read from file"},    {TABLE_ERROR_WRITE, "could not write to file"},    {TABLE_ERROR_EMPTY, "table is empty"},    {TABLE_ERROR_NOT_EMPTY, "table contains data"},    {TABLE_ERROR_ALIGNMENT, "invalid alignment value"},    {0}};#define INVALID_ERROR   "invalid error code"/****************************** local functions ******************************//* * static table_entry_t *first_entry * * DESCRIPTION: * * Return the first entry in the table.  It will set the linear * structure counter to the position of the first entry. * * RETURNS: * * Success: A pointer to the first entry in the table. * * Failure: NULL if there is no first entry. * * ARGUMENTS: * * table_p - Table whose next entry we are finding. * * linear_p - Pointer to a linear structure which we will advance and * then find the corresponding entry. */static table_entry_t *first_entry(table_t * table_p,                                  table_linear_t * linear_p){    table_entry_t *entry_p;    unsigned int bucket_c = 0;    /* look for the first non-empty bucket */    for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) {        entry_p = table_p->ta_buckets[bucket_c];        if (entry_p != NULL) {            if (linear_p != NULL) {                linear_p->tl_bucket_c = bucket_c;                linear_p->tl_entry_c = 0;            }            return TABLE_POINTER(table_p, table_entry_t *, entry_p);        }    }    return NULL;}/* * static table_entry_t *next_entry * * DESCRIPTION: * * Return the next entry in the table which is past the position in * our linear pointer.  It will advance the linear structure counters. * * RETURNS: * * Success: A pointer to the next entry in the table. * * Failure: NULL. * * ARGUMENTS: * * table_p - Table whose next entry we are finding. * * linear_p - Pointer to a linear structure which we will advance and * then find the corresponding entry. * * error_p - Pointer to an integer which when the routine returns will * contain a table error code. */static table_entry_t *next_entry(table_t * table_p, table_linear_t * linear_p,                                 int *error_p){    table_entry_t *entry_p;    int entry_c;    /* can't next if we haven't first-ed */    if (linear_p == NULL) {        if (error_p != NULL)            *error_p = TABLE_ERROR_LINEAR;        return NULL;    }    if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {        /*         * NOTE: this might happen if we delete an item which shortens the         * table bucket numbers.         */        if (error_p != NULL)            *error_p = TABLE_ERROR_NOT_FOUND;        return NULL;    }    linear_p->tl_entry_c++;    /* find the entry which is the nth in the list */    entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];    /* NOTE: we swap the order here to be more efficient */    for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) {        /* did we reach the end of the list? */        if (entry_p == NULL)            break;        entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;    }    /* did we find an entry in the current bucket? */    if (entry_p != NULL) {        if (error_p != NULL)            *error_p = TABLE_ERROR_NONE;        return TABLE_POINTER(table_p, table_entry_t *, entry_p);    }    /* find the first entry in the next non-empty bucket */    linear_p->tl_entry_c = 0;    for (linear_p->tl_bucket_c++; linear_p->tl_bucket_c < table_p->ta_bucket_n;         linear_p->tl_bucket_c++) {        entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];        if (entry_p != NULL) {            if (error_p != NULL)                *error_p = TABLE_ERROR_NONE;            return TABLE_POINTER(table_p, table_entry_t *, entry_p);        }    }    if (error_p != NULL)        *error_p = TABLE_ERROR_NOT_FOUND;    return NULL;}/* * static unsigned int hash * * DESCRIPTION: * * Hash a variable-length key into a 32-bit value.  Every bit of the * key affects every bit of the return value.  Every 1-bit and 2-bit * delta achieves avalanche.  About (6 * len + 35) instructions.  The * best hash table sizes are powers of 2.  There is no need to use mod * (sooo slow!).  If you need less than 32 bits, use a bitmask.  For * example, if you need only 10 bits, do h = (h & hashmask(10)); In * which case, the hash table should have hashsize(10) elements. * * By Bob Jenkins, 1996.  bob_jenkins@compuserve.com.  You may use * this code any way you wish, private, educational, or commercial. * It's free.  See * http://ourworld.compuserve.com/homepages/bob_jenkins/evahash.htm * Use for hash table lookup, or anything where one collision in 2^^32 * is acceptable.  Do NOT use for cryptographic purposes.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -