]>
git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/c-lib/src/hash.c
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 * This was borrowed from Don Acton and Terry Coatta's Raven Code.
21 * It has been modified somewhat.
24 * This is a set or routines that implements an extensible hashing
25 * algorithm. At the moment it assumes that all the hash codes are unique
26 * (ie. there are no collisions). For the way hash codes are currently being
27 * supplied this is not a bad assumption.
28 * The extensible hashing routine used is based on a multiway tree with
29 * each node in the tree being a fixed array of (2^n) size. At a given
30 * level, i, in the tree with the first level being level 0, bits
31 * i*n through i*n through (i+1)*n-1 are used as the index into the table.
32 * Each entry in the table is either NULL (unused) or a pointer to an
33 * object of type entry. The entry contains all the information about a
34 * hash entry. The entry also contains a field indicating whether or not this
35 * is a leaf node. If an entry isn't a leaf node then it references a table at
36 * at the next level and not a value. With the current implementation
37 * a 32 hash value is used and table sizes are 256. The algorithm used
38 * here is the same as the one used in the Set class of the Raven
41 * Copyright (C) 1992 University of British Columbia
43 * This library is free software; you can redistribute it and/or
44 * modify it provided that this copyright/license information is retained
47 * If you modify this file, you must clearly indicate your changes.
49 * This source code is distributed in the hope that it will be
50 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
51 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
53 * $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/c-lib/src/hash.c,v 1.1.1.1 2001/05/18 23:14:08 mb Exp $
55 * Revision 1.1.1.1 2001/05/18 23:14:08 mb
56 * Move from private repository to open source repository
58 * Revision 1.2 2001/05/05 00:59:25 rmurphy
59 * Adding darwin license headers
61 * Revision 1.1.1.1 1999/03/16 18:06:32 aram
62 * Originals from SMIME Free Library.
64 * Revision 1.3 1997/02/28 13:39:51 wan
65 * Modifications collected for new version 1.3: Bug fixes, tk4.2.
67 * Revision 1.2 1995/07/27 09:05:54 rj
68 * use memzero that is defined in .../snacc.h to use either memset or bzero.
70 * changed `_' to `-' in file names.
72 * Revision 1.1 1994/08/28 09:46:06 rj
73 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
77 #include "asn-config.h"
83 * From sdbm, an ndbm work-alike hashed database library
84 * Author: oz@nexus.yorku.ca
85 * Status: public domain.
87 * polynomial conversion ignoring overflows
88 * [this seems to work remarkably well, in fact better
89 * then the ndbm hash function. Replace at your own risk]
93 * [In one experiment, this function hashed 84165 symbols (English words
94 * plus symbol table values) with no collisions. -bjb]
99 MakeHash
PARAMS ((str
, len
),
101 unsigned long int len
)
106 #define HASHC n = *str++ + 65587 * n
111 loop
= (len
+ 8 - 1) >> 3;
112 switch (len
& (8 - 1))
131 /* Creates and clears a new hash slot */
137 foo
= (HashSlot
*) malloc (sizeof (HashSlot
));
140 memzero (foo
, sizeof (HashSlot
));
144 /* Create a new cleared hash table */
150 new_table
= (Table
*) malloc (sizeof (Table
));
151 if (new_table
== NULL
)
153 memzero (new_table
, sizeof (Table
));
157 /* This routine is used to initialize the hash tables. When it is called
158 * it returns a value which is used to identify which hash table
159 * a particular request is to operate on.
172 /* When a hash collision occurs at a leaf slot this routine is called to
173 * split the entry and add a new level to the tree at this point.
176 SplitAndInsert
PARAMS ((entry
, element
, hash_value
),
177 HashSlot
*entry _AND_
182 if (((entry
->table
= NewTable()) == NULL
) ||
183 !Insert (entry
->table
, entry
->value
, entry
->hash
>> INDEXSHIFT
) ||
184 !Insert (entry
->table
, element
, hash_value
>> INDEXSHIFT
))
191 /* This routine takes a hash table identifier, an element (value) and the
192 * coresponding hash value for that element and enters it into the table
193 * assuming it isn't already there.
196 Insert
PARAMS ((table
, element
, hash_value
),
203 entry
= (HashSlot
*) (*table
)[hash_value
& INDEXMASK
];
206 /* Need to add this element here */
207 entry
= NewHashSlot();
211 entry
->value
= element
;
212 entry
->hash
= hash_value
;
213 (*table
)[hash_value
& INDEXMASK
] = (void*)entry
;
217 if (hash_value
== entry
->hash
)
221 return SplitAndInsert (entry
, element
, hash_value
);
223 return Insert (entry
->table
, element
, hash_value
>> INDEXSHIFT
);
227 /* This routine looks to see if a particular hash value is already stored in
228 * the table. It returns true if it is and false otherwise.
231 CheckFor
PARAMS ((table
, hash
),
237 entry
= (HashSlot
*) table
[hash
& INDEXMASK
];
242 return entry
->hash
== hash
;
243 return CheckFor (entry
->table
, hash
>> INDEXSHIFT
);
246 /* In addition to checking for a hash value in the tree this function also
247 * returns the coresponding element value into the space pointed to by
248 * the value parameter. If the hash value isn't found FALSE is returned
249 * the the space pointed to by value is not changed.
252 CheckForAndReturnValue
PARAMS ((table
, hash
, value
),
258 entry
= (HashSlot
*) (*table
)[hash
& INDEXMASK
];
265 if (entry
->hash
== hash
)
267 *value
= entry
->value
;
273 return CheckForAndReturnValue (entry
->table
, hash
>> INDEXSHIFT
, value
);