core: import NSS bit and hash helpers into libnwcore
All checks were successful
Source release / source-package (push) Successful in 1m5s

This commit is contained in:
Mario Fetka
2026-06-12 14:05:55 +00:00
parent 4602d9fa2a
commit 205e1e48d0
6 changed files with 742 additions and 1 deletions

23
AI.md
View File

@@ -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
View 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
View 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

View File

@@ -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
View 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
View 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");
}
}