core: import NSS bit and hash helpers into libnwcore
All checks were successful
Source release / source-package (push) Successful in 1m5s
All checks were successful
Source release / source-package (push) Successful in 1m5s
This commit is contained in:
23
AI.md
23
AI.md
@@ -1,5 +1,28 @@
|
||||
# AI working notes for mars-nwe
|
||||
|
||||
## Current handoff status after NSS low-level imports 0404-0409
|
||||
|
||||
Current accepted MARS-NWE server line in this work session includes the NSS
|
||||
low-level libnwcore imports through `0409`:
|
||||
|
||||
- `0404` imports NSS `bitmap.c` directly as `src/core/bitmap.c`.
|
||||
- `0405` moves the imported bitmap/NSS base headers directly into
|
||||
`include/core/`.
|
||||
- `0406` removes trailing whitespace from the imported NSS headers.
|
||||
- `0407` imports NSS `crc.c`/`crc.h`; Unicode folding still uses the local
|
||||
ASCII-compatible fallback until `xUnicode`/`NSSUniToLower` is imported.
|
||||
- `0408` imports NSS `que.h` directly as `include/core/que.h`.
|
||||
- `0409` imports NSS `bit.h`, `hash.h`, and `hash.c` into libnwcore. The
|
||||
supplied NSS archives expose `LB_CountBits`, `LB_findHighBit`,
|
||||
`LB_findLowBit`, `LB_RotateLeft`, and `LB_RotateRight` in `libNSS.imp`, but
|
||||
do not include a `bit.c`; MARS-NWE therefore provides `src/core/bit.c` as a
|
||||
small compatibility implementation that preserves the original NSS public
|
||||
API names so imported `hash.c` links cleanly.
|
||||
|
||||
Keep future NSS low-level imports directly under `src/core/<original>.c` and
|
||||
`include/core/<original>.h`. Do not add a new `nwcore/nss/` or
|
||||
`src/core/nss/` path for the active libnwcore imports.
|
||||
|
||||
## Current handoff status after quota completion
|
||||
|
||||
This file may keep patch chronology because it is the ChatGPT handoff document.
|
||||
|
||||
90
include/core/bit.h
Normal file
90
include/core/bit.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/****************************************************************************
|
||||
|
|
||||
| (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc.
|
||||
| All Rights Reserved.
|
||||
|
|
||||
| This program is free software; you can redistribute it and/or
|
||||
| modify it under the terms of version 2 of the GNU General Public
|
||||
| License as published by the Free Software Foundation.
|
||||
|
|
||||
| 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.
|
||||
|
|
||||
| You should have received a copy of the GNU General Public License
|
||||
| along with this program; if not, contact Novell, Inc.
|
||||
|
|
||||
| To contact Novell about this file by physical or electronic mail,
|
||||
| you may find current contact information at www.novell.com
|
||||
|
|
||||
|***************************************************************************
|
||||
|
|
||||
| NetWare Advance File Services (NSS) module
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| $Author: taysom $
|
||||
| $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $
|
||||
|
|
||||
| $RCSfile$
|
||||
| $Revision: 465 $
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
| This module is used to:
|
||||
| NSS Library routine
|
||||
|
|
||||
| WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
|
||||
|
|
||||
| This header file should ONLY be used for NSS internal development.
|
||||
| This includes Semantic Agents (SA) and Loadable Storage Services (LSS).
|
||||
| Any other use may cause conflicts which NSS will NOT fix.
|
||||
+-------------------------------------------------------------------------*/
|
||||
#ifndef _BIT_H_
|
||||
#define _BIT_H_
|
||||
|
||||
#ifndef _OMNI_H_
|
||||
#include <omni.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WATCOMC_
|
||||
#ifndef _INLINES_H_
|
||||
#include <inlines.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Translate the names */
|
||||
#define CountBits(p1) LB_CountBits(p1)
|
||||
#define findHighBit(p1) LB_findHighBit(p1)
|
||||
#define findLowBit(p1) LB_findLowBit(p1)
|
||||
|
||||
extern NINT LB_CountBits(NINT word);
|
||||
extern NINT LB_findHighBit(NINT n);
|
||||
extern NINT LB_findLowBit(NINT n);
|
||||
|
||||
#ifdef _WATCOMC_
|
||||
|
||||
#define RotateLeft(v,n) inline_RotateLeft(v,n)
|
||||
#define RotateRight(v,n) inline_RotateRight(v,n)
|
||||
|
||||
#else
|
||||
|
||||
#define RotateLeft(p1,p2) LB_RotateLeft(p1,p2)
|
||||
#define RotateRight(p1,p2) LB_RotateRight(p1,p2)
|
||||
|
||||
NINT LB_RotateLeft(NINT value, NINT numBits);
|
||||
NINT LB_RotateRight(NINT value, NINT numBits);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
99
include/core/hash.h
Normal file
99
include/core/hash.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/****************************************************************************
|
||||
|
|
||||
| (C) Copyright 1995-1997 Novell, Inc.
|
||||
| All Rights Reserved.
|
||||
|
|
||||
| This program is free software; you can redistribute it and/or
|
||||
| modify it under the terms of version 2 of the GNU General Public
|
||||
| License as published by the Free Software Foundation.
|
||||
|
|
||||
| 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.
|
||||
|
|
||||
| You should have received a copy of the GNU General Public License
|
||||
| along with this program; if not, contact Novell, Inc.
|
||||
|
|
||||
| To contact Novell about this file by physical or electronic mail,
|
||||
| you may find current contact information at www.novell.com
|
||||
|
|
||||
|***************************************************************************
|
||||
|
|
||||
| NetWare Advance File Services (PSS) Initialization module
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| $Author: taysom $
|
||||
| $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $
|
||||
| $RCSfile$
|
||||
| $Revision: 465 $
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
| This module is used to: Typedefs for hash code.
|
||||
+-------------------------------------------------------------------------*/
|
||||
#ifndef _NSS_HASH_H_
|
||||
#define _NSS_HASH_H_
|
||||
|
||||
#ifndef _ZOMNI_H_
|
||||
#include "zOmni.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CRC_H_
|
||||
#include "crc.h"
|
||||
#endif
|
||||
|
||||
typedef struct HashRecord_s {
|
||||
struct HashRecord_s *next;
|
||||
crc_t crc;
|
||||
} HashRecord_s;
|
||||
|
||||
typedef struct HashTable_s {
|
||||
NINT mask; /* num buckets - 1 (num buckets is power of two) */
|
||||
NINT numRecords;
|
||||
BOOL (*isMatch)(void *key, HashRecord_s *rec);
|
||||
crc_t (*hash)(void *key);
|
||||
void *(*alloc)(void *key, void *data);
|
||||
void (*destroy)(void *rec);
|
||||
HashRecord_s **table;
|
||||
} HashTable_s;
|
||||
|
||||
typedef struct HashStats_s
|
||||
{
|
||||
NINT totalRecords;
|
||||
NINT numBuckets;
|
||||
NINT maxChain;
|
||||
NINT minChain;
|
||||
#ifdef UNIX
|
||||
float avgChain;
|
||||
#endif
|
||||
} HashStats_s;
|
||||
|
||||
/*
|
||||
* Hash function prototypes
|
||||
*/
|
||||
extern HashTable_s *hashInit(
|
||||
HashTable_s *ht,
|
||||
NINT numBuckets,
|
||||
BOOL (*isMatch)(void *key, HashRecord_s *rec),
|
||||
crc_t (*hash)(void *key),
|
||||
void *(*alloc)(void *key, void *data),
|
||||
void (*destroy)(void *rec));
|
||||
|
||||
extern STATUS hashApply(
|
||||
HashTable_s *ht,
|
||||
STATUS (*myFunc)(HashRecord_s *rec, void *metaData),
|
||||
void *metaData);
|
||||
|
||||
extern HashStats_s *hashStats(
|
||||
HashTable_s *ht,
|
||||
HashStats_s *stats);
|
||||
|
||||
extern void hashDelete(HashTable_s *ht, void *key);
|
||||
extern void *hashFind(HashTable_s *ht, void *key);
|
||||
extern void *hashInsert(HashTable_s *ht, void *key, void *data);
|
||||
extern HashTable_s *hashGrow(HashTable_s *ht, NINT factor);
|
||||
extern HashTable_s *hashShrink (HashTable_s *ht, NINT factor);
|
||||
extern void hashDestroy(HashTable_s *ht);
|
||||
|
||||
#endif
|
||||
@@ -51,6 +51,14 @@ configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/include/core/crc.h"
|
||||
"${NWCORE_BUILD_INCLUDE_DIR}/crc.h"
|
||||
COPYONLY)
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/include/core/bit.h"
|
||||
"${NWCORE_BUILD_INCLUDE_DIR}/bit.h"
|
||||
COPYONLY)
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/include/core/hash.h"
|
||||
"${NWCORE_BUILD_INCLUDE_DIR}/hash.h"
|
||||
COPYONLY)
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/include/core/que.h"
|
||||
"${NWCORE_BUILD_INCLUDE_DIR}/que.h"
|
||||
@@ -70,7 +78,9 @@ configure_file(
|
||||
|
||||
set(NWCORE_IMPORTED_NSS_SOURCES
|
||||
bitmap.c
|
||||
crc.c)
|
||||
bit.c
|
||||
crc.c
|
||||
hash.c)
|
||||
|
||||
add_library(nwcore SHARED
|
||||
core.c
|
||||
|
||||
79
src/core/bit.c
Normal file
79
src/core/bit.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
|
|
||||
| MARS-NWE libnwcore compatibility implementation for NSS bit.h symbols.
|
||||
|
|
||||
| The imported NSS public source archives provide shared/sdk/library/bit.h
|
||||
| and export LB_CountBits, LB_findHighBit, LB_findLowBit, LB_RotateLeft and
|
||||
| LB_RotateRight through libNSS.imp, but do not include a bit.c source file.
|
||||
| Keep the original NSS public API names so later imported NSS helpers such
|
||||
| as hash.c can link against libnwcore without a private wrapper namespace.
|
||||
|
|
||||
+-------------------------------------------------------------------------*/
|
||||
#include "bit.h"
|
||||
|
||||
NINT LB_CountBits(NINT word)
|
||||
{
|
||||
unsigned int value = (unsigned int)word;
|
||||
NINT count = 0;
|
||||
|
||||
while (value != 0)
|
||||
{
|
||||
value &= value - 1;
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
NINT LB_findHighBit(NINT n)
|
||||
{
|
||||
unsigned int value = (unsigned int)n;
|
||||
NINT bit = -1;
|
||||
|
||||
while (value != 0)
|
||||
{
|
||||
value >>= 1;
|
||||
++bit;
|
||||
}
|
||||
return bit;
|
||||
}
|
||||
|
||||
NINT LB_findLowBit(NINT n)
|
||||
{
|
||||
unsigned int value = (unsigned int)n;
|
||||
NINT bit = 0;
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
while ((value & 1U) == 0)
|
||||
{
|
||||
value >>= 1;
|
||||
++bit;
|
||||
}
|
||||
return bit;
|
||||
}
|
||||
|
||||
NINT LB_RotateLeft(NINT value, NINT numBits)
|
||||
{
|
||||
unsigned int v = (unsigned int)value;
|
||||
unsigned int shift = (unsigned int)numBits & 31U;
|
||||
|
||||
if (shift == 0)
|
||||
{
|
||||
return (NINT)v;
|
||||
}
|
||||
return (NINT)((v << shift) | (v >> (32U - shift)));
|
||||
}
|
||||
|
||||
NINT LB_RotateRight(NINT value, NINT numBits)
|
||||
{
|
||||
unsigned int v = (unsigned int)value;
|
||||
unsigned int shift = (unsigned int)numBits & 31U;
|
||||
|
||||
if (shift == 0)
|
||||
{
|
||||
return (NINT)v;
|
||||
}
|
||||
return (NINT)((v >> shift) | (v << (32U - shift)));
|
||||
}
|
||||
440
src/core/hash.c
Normal file
440
src/core/hash.c
Normal file
@@ -0,0 +1,440 @@
|
||||
/****************************************************************************
|
||||
|
|
||||
| (C) Copyright 1995-1997 Novell, Inc.
|
||||
| All Rights Reserved.
|
||||
|
|
||||
| This program is free software; you can redistribute it and/or
|
||||
| modify it under the terms of version 2 of the GNU General Public
|
||||
| License as published by the Free Software Foundation.
|
||||
|
|
||||
| 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.
|
||||
|
|
||||
| You should have received a copy of the GNU General Public License
|
||||
| along with this program; if not, contact Novell, Inc.
|
||||
|
|
||||
| To contact Novell about this file by physical or electronic mail,
|
||||
| you may find current contact information at www.novell.com
|
||||
|
|
||||
|***************************************************************************
|
||||
|
|
||||
| NetWare Advance File Services (PSS) Initialization module
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| $Author: vandana $
|
||||
| $Date: 2005-08-10 01:03:51 +0530 (Wed, 10 Aug 2005) $
|
||||
| $RCSfile$
|
||||
| $Revision: 1177 $
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
| This module is used to: Generic Hashing.
|
||||
|
|
||||
| Ideally, this routine should be in a library that is then loaded with
|
||||
| another library that as the malloc/free/realloc code in it. So it
|
||||
| can at load time pick-up the right routines. This requires creating
|
||||
| yet another library in NSS which I'm not ready to do yet.
|
||||
+-------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "omni.h"
|
||||
#include "bit.h"
|
||||
#include "hash.h"
|
||||
|
||||
/*
|
||||
* The generic hash code provides a basic set of functions for
|
||||
* managing hash tables.
|
||||
*
|
||||
* The code assumes each record has HashRecord_s at the beginning of
|
||||
* each record stored in the hash table. By careful use of the macros
|
||||
* offsetof (STRUCT), the HashRecord_s structure can be placed anywhere
|
||||
* in the users data structures. The user supplies the HashTable_s
|
||||
* structure, but the system allocates space for the actual table.
|
||||
*
|
||||
* hashInit - initializes the hash table
|
||||
* numBuckets - number of buckets to use (we take the first power of
|
||||
* 2 less than numBuckets).
|
||||
* isMatch - returns True if the key for the record mathes the key
|
||||
* passed in.
|
||||
* hash - generates a hash of the key (see crc.c and crc.h).
|
||||
* Even though the term CRC is used in the code,
|
||||
* it does not have to be a CRC. CRC just make
|
||||
* a very nice hash value.
|
||||
* alloc - allocates the record, if it already exits, it can
|
||||
* do nothing.
|
||||
* destory - used to free the allocated record.
|
||||
*/
|
||||
HashTable_s *hashInit (
|
||||
HashTable_s *ht,
|
||||
NINT numBuckets,
|
||||
BOOL (*isMatch)(void *key, HashRecord_s *rec),
|
||||
crc_t (*hash)(void *key),
|
||||
void *(*alloc)(void *key, void *data),
|
||||
void (*destroy)(void *rec))
|
||||
{
|
||||
HashRecord_s **table;
|
||||
NINT highBit;
|
||||
NINT size;
|
||||
|
||||
if ((isMatch == NULL)
|
||||
|| (hash == NULL)
|
||||
|| (alloc == NULL)
|
||||
|| (destroy == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
highBit = findHighBit(numBuckets);
|
||||
if (highBit > 28) // You've got to be kidding
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
numBuckets = (1<<highBit);
|
||||
|
||||
size = sizeof(HashRecord_s *) * numBuckets;
|
||||
table = malloc(size);
|
||||
if (table == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
bzero(table, size);
|
||||
|
||||
ht->mask = numBuckets - 1;
|
||||
ht->numRecords = 0;
|
||||
ht->isMatch = isMatch;
|
||||
ht->hash = hash;
|
||||
ht->alloc = alloc;
|
||||
ht->destroy = destroy;
|
||||
ht->table = table;
|
||||
|
||||
return ht;
|
||||
}
|
||||
|
||||
/*
|
||||
* hashLookup looks for a record that matches the crc first
|
||||
* and then the key.
|
||||
*/
|
||||
HashRecord_s *hashLookup (
|
||||
HashTable_s *ht,
|
||||
crc_t crc,
|
||||
void *key)
|
||||
{
|
||||
NINT bucket;
|
||||
HashRecord_s *next;
|
||||
HashRecord_s *prev;
|
||||
|
||||
bucket = crc & ht->mask;
|
||||
next = ht->table[bucket];
|
||||
|
||||
if (next == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (crc == next->crc)
|
||||
{
|
||||
if (ht->isMatch(key, next))
|
||||
{
|
||||
return next;
|
||||
}
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
prev = next;
|
||||
next = prev->next;
|
||||
|
||||
if (next == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (crc == next->crc)
|
||||
{
|
||||
if (ht->isMatch(key, next))
|
||||
{
|
||||
prev->next = next->next;
|
||||
next->next = ht->table[bucket];
|
||||
ht->table[bucket] = next;
|
||||
return next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* hashFind computes the crc and then calls hashLookup
|
||||
* which returns the record if it is found.
|
||||
*/
|
||||
void *hashFind (HashTable_s *ht, void *key)
|
||||
{
|
||||
return hashLookup(ht, ht->hash(key), key);
|
||||
}
|
||||
|
||||
/*
|
||||
* hashDelete deletes the record matching the key
|
||||
*/
|
||||
void hashDelete (HashTable_s *ht, void *key)
|
||||
{
|
||||
HashRecord_s *rec;
|
||||
|
||||
rec = hashLookup(ht, ht->hash(key), key);
|
||||
if (rec != NULL)
|
||||
{
|
||||
ht->table[rec->crc & ht->mask] = rec->next;
|
||||
ht->destroy(rec);
|
||||
--ht->numRecords;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* hashInsert tries to insert a new record. If an record
|
||||
* already exits that matches the key, that record is
|
||||
* returned.
|
||||
*/
|
||||
void *hashInsert (HashTable_s *ht, void *key, void *data)
|
||||
{
|
||||
crc_t crc;
|
||||
NINT bucket;
|
||||
HashRecord_s *rec;
|
||||
|
||||
crc = ht->hash(key);
|
||||
rec = hashLookup(ht, crc, key);
|
||||
if (rec != NULL)
|
||||
{
|
||||
return rec;
|
||||
}
|
||||
rec = ht->alloc(key, data);
|
||||
if (rec == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
bucket = crc & ht->mask;
|
||||
rec->next = ht->table[bucket];
|
||||
ht->table[bucket] = rec;
|
||||
rec->crc = crc;
|
||||
|
||||
++ht->numRecords;
|
||||
|
||||
return rec;
|
||||
}
|
||||
|
||||
/*
|
||||
* hashApply applies the given function, myFunc, to each record
|
||||
* in the table and passes along the metaData supplied
|
||||
*/
|
||||
STATUS hashApply (
|
||||
HashTable_s *ht,
|
||||
STATUS (*myFunc)(HashRecord_s *rec, void *metaData),
|
||||
void *metaData)
|
||||
{
|
||||
STATUS rc;
|
||||
unsigned i;
|
||||
unsigned numBuckets = ht->mask + 1;
|
||||
HashRecord_s **table = ht->table;
|
||||
HashRecord_s *rec;
|
||||
|
||||
for (i = 0; i < numBuckets; ++i)
|
||||
{
|
||||
rec = table[i];
|
||||
while (rec != NULL)
|
||||
{
|
||||
rc = myFunc(rec, metaData);
|
||||
if (rc != 0)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
rec = rec->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Increases the number of hash buckets - the first power of
|
||||
* 2 less than or equal to the factor is used.
|
||||
*/
|
||||
HashTable_s *hashGrow (HashTable_s *ht, NINT factor)
|
||||
{
|
||||
NINT i;
|
||||
NINT highBit;
|
||||
NINT numBuckets = ht->mask + 1;
|
||||
HashRecord_s **table = ht->table;
|
||||
HashRecord_s *rec;
|
||||
HashRecord_s *next;
|
||||
NINT newMask;
|
||||
NINT newNumBuckets;
|
||||
NINT bucket;
|
||||
|
||||
highBit = findHighBit(factor);
|
||||
factor = (1 << highBit);
|
||||
|
||||
newNumBuckets = numBuckets * factor;
|
||||
newMask = newNumBuckets - 1;
|
||||
table = realloc(table, newNumBuckets * sizeof(HashRecord_s *));
|
||||
if (table == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
for (i = numBuckets; i < newNumBuckets; ++i)
|
||||
{
|
||||
table[i] = NULL;
|
||||
}
|
||||
for (i = 0; i < numBuckets; ++i)
|
||||
{
|
||||
rec = table[i];
|
||||
table[i] = NULL;
|
||||
while (rec != NULL)
|
||||
{
|
||||
bucket = (rec->crc & newMask);
|
||||
next = rec->next;
|
||||
rec->next = table[bucket];
|
||||
table[bucket] = rec;
|
||||
rec = next;
|
||||
}
|
||||
}
|
||||
ht->mask = newMask;
|
||||
ht->table = table;
|
||||
return ht;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decreases the number of hash buckets - the first power of
|
||||
* 2 less than or equal to the factor is used.
|
||||
*/
|
||||
HashTable_s *hashShrink (HashTable_s *ht, NINT factor)
|
||||
{
|
||||
NINT i;
|
||||
NINT highBit;
|
||||
NINT numBuckets = ht->mask + 1;
|
||||
HashRecord_s **table = ht->table;
|
||||
HashRecord_s *rec;
|
||||
HashRecord_s *next;
|
||||
NINT newMask;
|
||||
NINT newNumBuckets;
|
||||
NINT bucket;
|
||||
|
||||
highBit = findHighBit(factor);
|
||||
factor = (1 << highBit);
|
||||
|
||||
newNumBuckets = numBuckets / factor;
|
||||
if (newNumBuckets == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
newMask = newNumBuckets - 1;
|
||||
ht->mask = newMask;
|
||||
|
||||
for (i = newNumBuckets; i < numBuckets; ++i)
|
||||
{
|
||||
rec = table[i];
|
||||
table[i] = NULL;
|
||||
while (rec != NULL)
|
||||
{
|
||||
bucket = (rec->crc & newMask);
|
||||
next = rec->next;
|
||||
rec->next = table[bucket];
|
||||
table[bucket] = rec;
|
||||
rec = next;
|
||||
}
|
||||
}
|
||||
table = realloc(table,
|
||||
newNumBuckets * sizeof(HashRecord_s *));
|
||||
if (table == NULL)
|
||||
{
|
||||
return ht;
|
||||
}
|
||||
ht->table = table;
|
||||
return ht;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destory the hash table, all the users destroy function
|
||||
* for each record and then freeing the table.
|
||||
*/
|
||||
void hashDestroy (HashTable_s *ht)
|
||||
{
|
||||
NINT i;
|
||||
NINT numBuckets = ht->mask + 1;
|
||||
HashRecord_s **table = ht->table;
|
||||
HashRecord_s *rec;
|
||||
HashRecord_s *next;
|
||||
|
||||
for (i = 0; i < numBuckets; ++i)
|
||||
{
|
||||
rec = table[i];
|
||||
while (rec != NULL)
|
||||
{
|
||||
next = rec->next;
|
||||
ht->destroy(rec);
|
||||
rec = next;
|
||||
}
|
||||
}
|
||||
free(table);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate statistics for the hash table
|
||||
*/
|
||||
HashStats_s *hashStats (
|
||||
HashTable_s *ht,
|
||||
HashStats_s *stats)
|
||||
{
|
||||
NINT maxChain = 0;
|
||||
NINT minChain = ~0;
|
||||
NINT total = 0;
|
||||
NINT sum;
|
||||
NINT i;
|
||||
NINT numBuckets = ht->mask + 1;
|
||||
HashRecord_s **table = ht->table;
|
||||
HashRecord_s *rec;
|
||||
|
||||
for (i = 0; i < numBuckets; ++i)
|
||||
{
|
||||
sum = 0;
|
||||
rec = table[i];
|
||||
while (rec != NULL)
|
||||
{
|
||||
++sum;
|
||||
rec = rec->next;
|
||||
}
|
||||
total += sum;
|
||||
if (sum > maxChain)
|
||||
{
|
||||
maxChain = sum;
|
||||
}
|
||||
if (sum < minChain)
|
||||
{
|
||||
minChain = sum;
|
||||
}
|
||||
}
|
||||
stats->numBuckets = numBuckets;
|
||||
stats->totalRecords = total;
|
||||
stats->maxChain = maxChain;
|
||||
stats->minChain = minChain;
|
||||
#if 0
|
||||
// stats->avgChain = ((float)total) / numBuckets;
|
||||
#endif
|
||||
return stats;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dumps the hash table (just the CRC values) to the screen
|
||||
*/
|
||||
void hashDump (HashTable_s *ht)
|
||||
{
|
||||
NINT i;
|
||||
NINT numBuckets = ht->mask + 1;
|
||||
HashRecord_s **table = ht->table;
|
||||
HashRecord_s *rec;
|
||||
|
||||
for (i = 0; i < numBuckets; ++i)
|
||||
{
|
||||
rec = table[i];
|
||||
while (rec != NULL)
|
||||
{
|
||||
//printf("%x ", rec->crc);
|
||||
rec = rec->next;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user