1 /*--------------------------------------------------------------------------*\
2  *				   -----===== HashTable =====-----
3  *
4  * Author: Keith Pomakis (pomakis@pobox.com)
5  * Date:   August, 1998
6  * Released to the public domain.
7  *
8  *--------------------------------------------------------------------------
9  * $Id: hashtable.c,v 9999.42 2019/12/05 03:05:37 cvs Exp $
10 \*--------------------------------------------------------------------------*/
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <assert.h>
16 #include <pthread.h>
17 #include "hashtable.h"
18 #include "core.h"
19 #include "input-files.h"
20 
21 static int pointercmp(const void *pointer1, const void *pointer2);
22 static srUInt_64 pointerHashFunction(const void *pointer);
23 static int isProbablePrime(srInt_64 number);
24 static srInt_64 calculateIdealNumOfBuckets(HashTable *hashTable);
25 
long_random_val()26 srInt_64 long_random_val(){
27 	srInt_64 ret = 0;
28 	if(RAND_MAX<255){
29 		SUBREADprintf("Is this a embedded computer????\n");
30 		return -1;
31 	}
32 	int i;
33 	for(i=0;i<8;i++){
34 		if(i>0)ret = (ret << 8) ^ (myrand_rand() & 0xff);
35 		else ret = (ret << 8) ^ (myrand_rand() & 0x7f);
36 	}
37 	return ret;
38 }
39 
ArrayListToLookupTable_Int(ArrayList * arr)40 HashTable * ArrayListToLookupTable_Int(ArrayList * arr){
41 	srInt_64 x1;
42 	HashTable * ret = HashTableCreate( max(1,arr -> numOfElements / 6) );
43 	for(x1 = 0; x1 < arr->numOfElements; x1++) HashTablePut(ret, ArrayListGet(arr, x1)+1, NULL+x1+1);
44 	return ret;
45 }
46 
ArrayListContainsPtr(ArrayList * list,void * who)47 int ArrayListContainsPtr(ArrayList * list, void * who){
48 	srInt_64 x1;
49 	for(x1 = 0; x1 < list->numOfElements; x1++) if(list->elementList [ x1 ]==who) return 1;
50 	return 0;
51 }
52 
ArrayListShift(ArrayList * list)53 void * ArrayListShift(ArrayList * list){
54 	if(list->numOfElements<1) return NULL;
55 	void *ret = list->elementList [0];
56 	srInt_64 xx;
57 	list->numOfElements -- ;
58 	for(xx=0; xx<list->numOfElements; xx++) list->elementList [ xx ] = list->elementList [ xx+1 ];
59 	return ret;
60 }
61 
ArrayListPop(ArrayList * list)62 void * ArrayListPop(ArrayList * list){
63 	if(list->numOfElements<1) return NULL;
64 	return list->elementList [ -- list->numOfElements];
65 }
66 
67 
ArrayListRandom(ArrayList * list)68 void * ArrayListRandom(ArrayList * list){
69 	srInt_64 ii = long_random_val() % list -> numOfElements;
70 	return list -> elementList[ii];
71 }
72 
73 
ArrayListCreate(int init_capacity)74 ArrayList * ArrayListCreate(int init_capacity){
75 	ArrayList * ret = malloc(sizeof(ArrayList));
76 	memset(ret,0,sizeof(ArrayList));
77 	ret -> capacityOfElements = init_capacity;
78 	ret -> elementList = malloc(sizeof(void *)*init_capacity);
79 	return ret;
80 }
81 
ArrayListDuplicate(ArrayList * ori)82 ArrayList * ArrayListDuplicate(ArrayList * ori){
83 	ArrayList * ret = malloc(sizeof(ArrayList));
84 	memset(ret,0,sizeof(ArrayList));
85 	ret -> capacityOfElements = ori -> numOfElements;
86 	ret -> numOfElements = ori -> numOfElements;
87 	ret -> elementList = malloc(sizeof(void *)*ret -> capacityOfElements);
88 	memcpy(ret -> elementList, ori -> elementList, sizeof(void *)*ret -> capacityOfElements);
89 	ret -> elemDeallocator = ori -> elemDeallocator;
90 	return ret;
91 }
92 
ArrayListDestroy(ArrayList * list)93 void ArrayListDestroy(ArrayList * list){
94 	srInt_64 x1;
95 	if(list -> elemDeallocator)
96 		for(x1 = 0;x1 < list->numOfElements; x1++)
97 			list -> elemDeallocator(list -> elementList[x1]);
98 
99 	free(list -> elementList);
100 	free(list);
101 }
102 
ArrayListGet(ArrayList * list,srInt_64 n)103 void * ArrayListGet(ArrayList * list, srInt_64 n){
104 	if(n<0 || n >= list->numOfElements)return NULL;
105 	return list -> elementList[n];
106 }
107 
ArrayListPush_NoRepeatedPtr(ArrayList * list,void * new_elem)108 int ArrayListPush_NoRepeatedPtr(ArrayList * list, void * new_elem){
109 	srInt_64 ii;
110 	for(ii = 0; ii < list->numOfElements; ii++){
111 		if(list -> elementList[ii] == new_elem) return -1;
112 	}
113 	return ArrayListPush(list,new_elem);
114 }
115 
ArrayListPush(ArrayList * list,void * new_elem)116 int ArrayListPush(ArrayList * list, void * new_elem){
117 	if(list -> capacityOfElements <= list->numOfElements){
118 		if(list -> capacityOfElements *1.3 > list -> capacityOfElements + 10)
119 				list -> capacityOfElements = list -> capacityOfElements *1.3;
120 		else	list -> capacityOfElements = list -> capacityOfElements + 10;
121 
122 		list -> elementList=realloc(list -> elementList, sizeof(void *) * list -> capacityOfElements);
123 		assert(list -> elementList);
124 	}
125 	list->elementList[list->numOfElements++] = new_elem;
126 	return list->numOfElements;
127 }
ArrayListSetDeallocationFunction(ArrayList * list,void (* elem_deallocator)(void * elem))128 void ArrayListSetDeallocationFunction(ArrayList * list,  void (*elem_deallocator)(void *elem)){
129 	list -> elemDeallocator = elem_deallocator;
130 }
131 
ArrayListSort_comp_pntr(void * L_elem,void * R_elem,ArrayList * me)132 int ArrayListSort_comp_pntr( void * L_elem, void * R_elem, ArrayList * me ){
133 	if( L_elem > R_elem )return 1;
134 	if( L_elem < R_elem )return -1;
135 	return 0;
136 }
137 
ArrayListSort_compare(void * sortdata0,int L,int R)138 int ArrayListSort_compare(void * sortdata0, int L, int R){
139 	void ** sortdata = sortdata0;
140 	ArrayList * list = sortdata[0];
141 	int (*comp_elems)(void * L_elem, void * R_elem, ArrayList * me) = sortdata[1];
142 
143 	void * L_elem = list -> elementList[L];
144 	void * R_elem = list -> elementList[R];
145 	return comp_elems(L_elem, R_elem, list);
146 }
147 
ArrayListSort_exchange(void * sortdata0,int L,int R)148 void ArrayListSort_exchange(void * sortdata0, int L, int R){
149 	void ** sortdata = sortdata0;
150 	ArrayList * list = sortdata[0];
151 
152 	void * tmpp = list -> elementList[L];
153 	list -> elementList[L] = list -> elementList[R];
154 	list -> elementList[R] = tmpp;
155 }
156 
ArrayListSort_merge(void * sortdata0,int start,int items,int items2)157 void ArrayListSort_merge(void * sortdata0, int start, int items, int items2){
158 	void ** sortdata = sortdata0;
159 	ArrayList * list = sortdata[0];
160 	int (*comp_elems)(void * L_elem, void * R_elem, ArrayList * me) = sortdata[1];
161 
162 	void ** merged = malloc(sizeof(void *)*(items + items2));
163 	int write_cursor, read1=start, read2=start+items;
164 
165 	for(write_cursor = 0; write_cursor < items + items2; write_cursor++){
166 		void * Elm1 = (read1 == start + items)? NULL:list -> elementList[read1];
167 		void * Elm2 = (read2 == start + items + items2)?NULL:list -> elementList[read2];
168 
169 		int select_1 = (read1 == start + items)?0:( read2 == start + items + items2 || comp_elems(Elm1, Elm2, list) < 0 );
170 		if(select_1) merged[write_cursor] = list -> elementList[read1++];
171 		else merged[write_cursor] = list -> elementList[read2++];
172 		if(read2 > start + items + items2){
173 			SUBREADprintf("R1: %d < %d ; R2: %d < %d\n", read1,  start + items, read2, start + items + items2);
174 		}
175 		assert(read2 <=start + items + items2);
176 		assert(read1 <=start + items);
177 	}
178 
179 	memcpy(list -> elementList + start, merged, sizeof(void *) * (items + items2));
180 	free(merged);
181 }
182 
ArrayListSort(ArrayList * list,int compare_L_minus_R (void * L_elem,void * R_elem,ArrayList * me))183 void ArrayListSort(ArrayList * list, int compare_L_minus_R(void * L_elem, void * R_elem, ArrayList * me)){
184 	void * sortdata[2];
185 	sortdata[0] = list;
186 	sortdata[1] = compare_L_minus_R?compare_L_minus_R:ArrayListSort_comp_pntr;
187 
188 	if(list -> numOfElements > 20)
189 		merge_sort(sortdata, list -> numOfElements, ArrayListSort_compare, ArrayListSort_exchange, ArrayListSort_merge);
190 	else
191 		basic_sort(sortdata, list -> numOfElements, ArrayListSort_compare, ArrayListSort_exchange);
192 }
193 
ArrayListLLUComparison(void * L_elem,void * R_elem)194 int ArrayListLLUComparison(void * L_elem, void * R_elem){
195 	srUInt_64 lint = L_elem-NULL;
196 	srUInt_64 rint = R_elem-NULL;
197 	if(lint<rint)return -1;
198 	if(lint>rint)return 1;
199 	return 0;
200 }
201 
ArrayListFindNextDent(ArrayList * list,srUInt_64 value_less_than_dent)202 srInt_64 ArrayListFindNextDent(ArrayList * list, srUInt_64 value_less_than_dent){
203 	srInt_64 h=list->numOfElements-1,l=0,m=-1l;
204 	if( list -> elementList[h]- NULL <= value_less_than_dent )return -1l;
205 	while(h>l){
206 		m=(h+l)/2;
207 		srUInt_64 mv = list -> elementList[m] - NULL;
208 		if(mv < value_less_than_dent) l=m+1;
209 		else if(mv > value_less_than_dent) h=m-1;
210 		else break;
211 	}
212 	if(m<2)m=0;
213 	else m-=2;
214 
215 	for(; m>=0 && list -> elementList[m] - NULL >= value_less_than_dent; m--);
216 
217 	for(m = max(0, m); m < list->numOfElements ; m++){
218 		if( list -> elementList[m] - NULL > value_less_than_dent )return m;
219 	}
220 	SUBREADprintf("ALGORITHM ERROR!! DID YOU SORT THE LIST???\n");
221 	return -2l;
222 }
223 
224 /*--------------------------------------------------------------------------*\
225  *  NAME:
226  *	  HashTableCreate() - creates a new HashTable
227  *  DESCRIPTION:
228  *	  Creates a new HashTable.  When finished with this HashTable, it
229  *	  should be explicitly destroyed by calling the HashTableDestroy()
230  *	  function.
231  *  EFFICIENCY:
232  *	  O(1)
233  *  ARGUMENTS:
234  *	  numOfBuckets - the number of buckets to start the HashTable out with.
235  *					 Must be greater than zero, and should be prime.
236  *					 Ideally, the number of buckets should between 1/5
237  *					 and 1 times the expected number of elements in the
238  *					 HashTable.  Values much more or less than this will
239  *					 result in wasted memory or decreased performance
240  *					 respectively.  The number of buckets in a HashTable
241  *					 can be re-calculated to an appropriate number by
242  *					 calling the HashTableRehash() function once the
243  *					 HashTable has been populated.  The number of buckets
244  *					 in a HashTable may also be re-calculated
245  *					 automatically if the ratio of elements to buckets
246  *					 passes the thresholds set by HashTableSetIdealRatio().
247  *  RETURNS:
248  *	  HashTable	- a new Hashtable, or NULL on error
249 \*--------------------------------------------------------------------------*/
250 
StringTableCreate(srInt_64 numOfBuckets)251 HashTable * StringTableCreate(srInt_64 numOfBuckets){
252 	HashTable * ret = HashTableCreate(numOfBuckets);
253 	HashTableSetHashFunction(ret, HashTableStringHashFunction);
254 	HashTableSetKeyComparisonFunction(ret , my_strcmp);
255 	return ret;
256 }
257 
StringTableReverse_Run(void * ky,void * va,HashTable * tab)258 void StringTableReverse_Run(void * ky, void * va, HashTable * tab){
259 	HashTable * res = tab -> appendix1;
260 	HashTablePut(res, va, ky);
261 }
262 
StringTableReverse(HashTable * ori)263 HashTable * StringTableReverse(HashTable * ori){
264 	HashTable * res = StringTableCreate(ori -> numOfBuckets);
265 	void * oriap1 = ori -> appendix1;
266 	ori -> appendix1 = res;
267 
268 	HashTableIteration(ori, StringTableReverse_Run);
269 	ori -> appendix1 = oriap1;
270 	return res;
271 }
272 
HashTableKeys(HashTable * tab)273 ArrayList * HashTableKeys(HashTable * tab){
274 	int i;
275 	ArrayList * ret = ArrayListCreate(tab -> numOfElements);
276 	for (i=0; i< tab ->numOfBuckets; i++) {
277 		KeyValuePair *pair = tab ->bucketArray[i];
278 		while (pair != NULL) {
279 			ArrayListPush(ret, pair -> key);
280 			KeyValuePair *nextPair = pair->next;
281 			pair = nextPair;
282 		}
283 	}
284 	return ret;
285 }
286 
HashTableCreate(srInt_64 numOfBuckets)287 HashTable *HashTableCreate(srInt_64 numOfBuckets) {
288 	HashTable *hashTable;
289 	int i;
290 
291 
292 	assert(numOfBuckets > 0);
293 
294 	hashTable = (HashTable *) malloc(sizeof(HashTable));
295 	if (hashTable == NULL)
296 		return NULL;
297 
298 	hashTable->appendix1=NULL;
299 	hashTable->appendix2=NULL;
300 	hashTable->appendix3=NULL;
301 
302 	hashTable->counter1=0;
303 	hashTable->counter2=0;
304 	hashTable->counter3=0;
305 
306 	hashTable->bucketArray = (KeyValuePair **)
307 						malloc(numOfBuckets * sizeof(KeyValuePair *));
308 	if (hashTable->bucketArray == NULL) {
309 		free(hashTable);
310 		return NULL;
311 	}
312 
313 	hashTable->numOfBuckets = numOfBuckets;
314 	hashTable->numOfElements = 0;
315 
316 	for (i=0; i<numOfBuckets; i++)
317 		hashTable->bucketArray[i] = NULL;
318 
319 	hashTable->idealRatio = 3.0;
320 	hashTable->lowerRehashThreshold = 0.0;
321 	hashTable->upperRehashThreshold = 15.0;
322 
323 	hashTable->keycmp = pointercmp;
324 	hashTable->valuecmp = pointercmp;
325 	hashTable->hashFunction = pointerHashFunction;
326 	hashTable->keyDeallocator = NULL;
327 	hashTable->valueDeallocator = NULL;
328 
329 	return hashTable;
330 }
331 
332 
333 /*--------------------------------------------------------------------------*\
334  *  NAME:
335  *	  HashTableDestroy() - destroys an existing HashTable
336  *  DESCRIPTION:
337  *	  Destroys an existing HashTable.
338  *  EFFICIENCY:
339  *	  O(n)
340  *  ARGUMENTS:
341  *	  hashTable	- the HashTable to destroy
342  *  RETURNS:
343  *	  <nothing>
344 \*--------------------------------------------------------------------------*/
345 
HashTableDestroy(HashTable * hashTable)346 void HashTableDestroy(HashTable *hashTable) {
347 	int i;
348 
349 	for (i=0; i<hashTable->numOfBuckets; i++) {
350 		KeyValuePair *pair = hashTable->bucketArray[i];
351 		while (pair != NULL) {
352 			KeyValuePair *nextPair = pair->next;
353 
354 			if (hashTable->keyDeallocator != NULL)
355 				hashTable->keyDeallocator((void *) pair->key);
356 			if (hashTable->valueDeallocator != NULL){
357 //			fprintf(stderr,"FREE %p\n", pair->value);
358 			hashTable->valueDeallocator(pair->value);
359 		}
360 			free(pair);
361 			pair = nextPair;
362 		}
363 	}
364 
365 	free(hashTable->bucketArray);
366 	free(hashTable);
367 }
368 
369 /*--------------------------------------------------------------------------*\
370  *  NAME:
371  *	  HashTableContainsKey() - checks the existence of a key in a HashTable
372  *  DESCRIPTION:
373  *	  Determines whether or not the specified HashTable contains the
374  *	  specified key.  Uses the comparison function specified by
375  *	  HashTableSetKeyComparisonFunction().
376  *  EFFICIENCY:
377  *	  O(1), assuming a good hash function and element-to-bucket ratio
378  *  ARGUMENTS:
379  *	  hashTable	- the HashTable to search
380  *	  key		  - the key to search for
381  *  RETURNS:
382  *	  bool		 - whether or not the specified HashTable contains the
383  *					 specified key.
384 \*--------------------------------------------------------------------------*/
385 
HashTableContainsKey(const HashTable * hashTable,const void * key)386 int HashTableContainsKey(const HashTable *hashTable, const void *key) {
387 	return (HashTableGet(hashTable, key) != NULL);
388 }
389 
390 /*--------------------------------------------------------------------------*\
391  *  NAME:
392  *	  HashTableContainsValue()
393  *						 - checks the existence of a value in a HashTable
394  *  DESCRIPTION:
395  *	  Determines whether or not the specified HashTable contains the
396  *	  specified value.  Unlike HashTableContainsKey(), this function is
397  *	  not very efficient, since it has to scan linearly looking for a
398  *	  match.  Uses the comparison function specified by
399  *	  HashTableSetValueComparisonFunction().
400  *  EFFICIENCY:
401  *	  O(n)
402  *  ARGUMENTS:
403  *	  hashTable	- the HashTable to search
404  *	  value		- the value to search for
405  *  RETURNS:
406  *	  bool		 - whether or not the specified HashTable contains the
407  *					 specified value.
408 \*--------------------------------------------------------------------------*/
409 
HashTableContainsValue(const HashTable * hashTable,const void * value)410 int HashTableContainsValue(const HashTable *hashTable, const void *value) {
411 	int i;
412 
413 	for (i=0; i<hashTable->numOfBuckets; i++) {
414 		KeyValuePair *pair = hashTable->bucketArray[i];
415 		while (pair != NULL) {
416 			if (hashTable->valuecmp(value, pair->value) == 0)
417 				return 1;
418 			pair = pair->next;
419 		}
420 	}
421 
422 	return 0;
423 }
424 
425 /*--------------------------------------------------------------------------*\
426  *  NAME:
427  *	  HashTablePut() - adds a key/value pair to a HashTable
428  *  DESCRIPTION:
429  *	  Adds the specified key/value pair to the specified HashTable.  If
430  *	  the key already exists in the HashTable (determined by the comparison
431  *	  function specified by HashTableSetKeyComparisonFunction()), its value
432  *	  is replaced by the new value.  May trigger an auto-rehash (see
433  *	  HashTableSetIdealRatio()).  It is illegal to specify NULL as the
434  *	  key or value.
435  *  EFFICIENCY:
436  *	  O(1), assuming a good hash function and element-to-bucket ratio
437  *  ARGUMENTS:
438  *	  hashTable	- the HashTable to add to
439  *	  key		  - the key to add or whose value to replace
440  *	  value		- the value associated with the key
441  *  RETURNS:
442  *	  err		  - 0 if successful, -1 if an error was encountered
443 \*--------------------------------------------------------------------------*/
444 
HashTablePut(HashTable * hashTable,const void * key,void * value)445 int HashTablePut(HashTable *hashTable, const void *key, void *value) {
446 	return HashTablePutReplace(hashTable, key, value, 1);
447 }
448 
HashTablePutReplaceEx(HashTable * hashTable,const void * key,void * value,int replace_key,int dealloc_key,int dealloc_value)449 int HashTablePutReplaceEx(HashTable *hashTable, const void *key, void *value, int replace_key, int dealloc_key, int dealloc_value) {
450 	srInt_64 hashValue;
451 	KeyValuePair *pair;
452 
453 	assert(key != NULL);
454 	assert(value != NULL);
455 
456 	hashValue = hashTable->hashFunction(key) % hashTable->numOfBuckets;
457 
458 
459 	pair = hashTable->bucketArray[hashValue];
460 
461 	while (pair != NULL && hashTable->keycmp(key, pair->key) != 0)
462 		pair = pair->next;
463 
464 	if (pair) {
465 		if (pair->key != key) {
466 			if(replace_key) {
467 				if(hashTable->keyDeallocator && dealloc_key)
468 					hashTable->keyDeallocator((void *) pair->key);
469 				pair->key = (void *)key;
470 			}
471 		}
472 		if (pair->value != value) {
473 			if (hashTable->valueDeallocator != NULL && dealloc_value)
474 				hashTable->valueDeallocator(pair->value);
475 			pair->value = (void *)value;
476 		}
477 	}
478 	else {
479 		KeyValuePair *newPair = (KeyValuePair *) malloc(sizeof(KeyValuePair));
480 		if (newPair == NULL) {
481 		return -1;
482 		}
483 		else {
484 			newPair->key = (void *)key;
485 			newPair->value = (void *)value;
486 			newPair->next = hashTable->bucketArray[hashValue];
487 			hashTable->bucketArray[hashValue] = newPair;
488 			hashTable->numOfElements++;
489 
490 			if (hashTable->upperRehashThreshold > hashTable->idealRatio) {
491 				float elementToBucketRatio = (float) hashTable->numOfElements /
492 											 (float) hashTable->numOfBuckets;
493 				if (elementToBucketRatio > hashTable->upperRehashThreshold)
494 					HashTableRehash(hashTable, 0);
495 			}
496 		}
497 	}
498 
499 	return 0;
500 }
HashTablePutReplace(HashTable * hashTable,const void * key,void * value,int replace_key)501 int HashTablePutReplace(HashTable *hashTable, const void *key, void *value, int replace_key) {
502 	return HashTablePutReplaceEx(hashTable, key, value,  replace_key, 1, 1);
503 }
504 
505 /*--------------------------------------------------------------------------*\
506  *  NAME:
507  *	  HashTableGet() - retrieves the value of a key in a HashTable
508  *  DESCRIPTION:
509  *	  Retrieves the value of the specified key in the specified HashTable.
510  *	  Uses the comparison function specified by
511  *	  HashTableSetKeyComparisonFunction().
512  *  EFFICIENCY:
513  *	  O(1), assuming a good hash function and element-to-bucket ratio
514  *  ARGUMENTS:
515  *	  hashTable	- the HashTable to search
516  *	  key		  - the key whose value is desired
517  *  RETURNS:
518  *	  void *	   - the value of the specified key, or NULL if the key
519  *					 doesn't exist in the HashTable
520 \*--------------------------------------------------------------------------*/
521 
HashTableGetKey(const HashTable * hashTable,const void * key)522 void *HashTableGetKey(const HashTable *hashTable, const void *key) {
523 	srInt_64 hashValue = hashTable->hashFunction(key) % hashTable->numOfBuckets;
524 
525 	KeyValuePair *pair = hashTable->bucketArray[hashValue];
526 
527 	while (pair != NULL && hashTable->keycmp(key, pair->key) != 0)
528 		pair = pair->next;
529 
530 	return (pair == NULL)? NULL : pair->key;
531 }
532 
533 
HashTableGet(const HashTable * hashTable,const void * key)534 void *HashTableGet(const HashTable *hashTable, const void *key) {
535 	srInt_64 hashValue = hashTable->hashFunction(key) % hashTable->numOfBuckets;
536 
537 	KeyValuePair *pair = hashTable->bucketArray[hashValue];
538 
539 	while (pair != NULL && hashTable->keycmp(key, pair->key) != 0)
540 		pair = pair->next;
541 
542 	return (pair == NULL)? NULL : pair->value;
543 }
544 
545 /*--------------------------------------------------------------------------*\
546  *  NAME:
547  *	  HashTableRemove() - removes a key/value pair from a HashTable
548  *  DESCRIPTION:
549  *	  Removes the key/value pair identified by the specified key from the
550  *	  specified HashTable if the key exists in the HashTable.  May trigger
551  *	  an auto-rehash (see HashTableSetIdealRatio()).
552  *  EFFICIENCY:
553  *	  O(1), assuming a good hash function and element-to-bucket ratio
554  *  ARGUMENTS:
555  *	  hashTable	- the HashTable to remove the key/value pair from
556  *	  key		  - the key specifying the key/value pair to be removed
557  *  RETURNS:
558  *	  <nothing>
559 \*--------------------------------------------------------------------------*/
560 
HashTableRemove(HashTable * hashTable,const void * key)561 void HashTableRemove(HashTable *hashTable, const void *key) {
562 	srInt_64 hashValue = hashTable->hashFunction(key) % hashTable->numOfBuckets;
563 
564 
565 	KeyValuePair *pair = hashTable->bucketArray[hashValue];
566 	KeyValuePair *previousPair = NULL;
567 
568 	while (pair != NULL && hashTable->keycmp(key, pair->key) != 0) {
569 		previousPair = pair;
570 		pair = pair->next;
571 	}
572 
573 	if (pair != NULL) {
574 		if (hashTable->keyDeallocator != NULL)
575 			hashTable->keyDeallocator((void *) pair->key);
576 		if (hashTable->valueDeallocator != NULL)
577 			hashTable->valueDeallocator(pair->value);
578 		if (previousPair != NULL)
579 			previousPair->next = pair->next;
580 		else
581 			hashTable->bucketArray[hashValue] = pair->next;
582 		free(pair);
583 		hashTable->numOfElements--;
584 
585 		if (hashTable->lowerRehashThreshold > 0.0) {
586 			float elementToBucketRatio = (float) hashTable->numOfElements /
587 										 (float) hashTable->numOfBuckets;
588 			if (elementToBucketRatio < hashTable->lowerRehashThreshold)
589 				HashTableRehash(hashTable, 0);
590 		}
591 	}
592 
593 
594 }
595 
596 /*--------------------------------------------------------------------------*\
597  *  NAME:
598  *	  HashTableRemoveAll() - removes all key/value pairs from a HashTable
599  *  DESCRIPTION:
600  *	  Removes all key/value pairs from the specified HashTable.  May trigger
601  *	  an auto-rehash (see HashTableSetIdealRatio()).
602  *  EFFICIENCY:
603  *	  O(n)
604  *  ARGUMENTS:
605  *	  hashTable	- the HashTable to remove all key/value pairs from
606  *  RETURNS:
607  *	  <nothing>
608 \*--------------------------------------------------------------------------*/
609 
HashTableRemoveAll(HashTable * hashTable)610 void HashTableRemoveAll(HashTable *hashTable) {
611 	int i;
612 
613 	for (i=0; i<hashTable->numOfBuckets; i++) {
614 		KeyValuePair *pair = hashTable->bucketArray[i];
615 		while (pair != NULL) {
616 			KeyValuePair *nextPair = pair->next;
617 			if (hashTable->keyDeallocator != NULL)
618 				hashTable->keyDeallocator((void *) pair->key);
619 			if (hashTable->valueDeallocator != NULL)
620 				hashTable->valueDeallocator(pair->value);
621 			free(pair);
622 			pair = nextPair;
623 		}
624 		hashTable->bucketArray[i] = NULL;
625 	}
626 
627 	hashTable->numOfElements = 0;
628 	HashTableRehash(hashTable, 5);
629 }
630 
631 /*--------------------------------------------------------------------------*\
632  *  NAME:
633  *	  HashTableIsEmpty() - determines if a HashTable is empty
634  *  DESCRIPTION:
635  *	  Determines whether or not the specified HashTable contains any
636  *	  key/value pairs.
637  *  EFFICIENCY:
638  *	  O(1)
639  *  ARGUMENTS:
640  *	  hashTable	- the HashTable to check
641  *  RETURNS:
642  *	  bool		 - whether or not the specified HashTable contains any
643  *					 key/value pairs
644 \*--------------------------------------------------------------------------*/
645 
HashTableIsEmpty(const HashTable * hashTable)646 int HashTableIsEmpty(const HashTable *hashTable) {
647 	return (hashTable->numOfElements == 0);
648 }
649 
650 /*--------------------------------------------------------------------------*\
651  *  NAME:
652  *	  HashTableSize() - returns the number of elements in a HashTable
653  *  DESCRIPTION:
654  *	  Returns the number of key/value pairs that are present in the
655  *	  specified HashTable.
656  *  EFFICIENCY:
657  *	  O(1)
658  *  ARGUMENTS:
659  *	  hashTable	- the HashTable whose size is requested
660  *  RETURNS:
661  *	  long		 - the number of key/value pairs that are present in
662  *					 the specified HashTable
663 \*--------------------------------------------------------------------------*/
664 
HashTableSize(const HashTable * hashTable)665 srInt_64 HashTableSize(const HashTable *hashTable) {
666 	return hashTable->numOfElements;
667 }
668 
669 /*--------------------------------------------------------------------------*\
670  *  NAME:
671  *	  HashTableGetNumBuckets() - returns the number of buckets in a HashTable
672  *  DESCRIPTION:
673  *	  Returns the number of buckets that are in the specified HashTable.
674  *	  This may change dynamically throughout the life of a HashTable if
675  *	  automatic or manual rehashing is performed.
676  *  EFFICIENCY:
677  *	  O(1)
678  *  ARGUMENTS:
679  *	  hashTable	- the HashTable whose number of buckets is requested
680  *  RETURNS:
681  *	  long		 - the number of buckets that are in the specified
682  *					 HashTable
683 \*--------------------------------------------------------------------------*/
684 
HashTableGetNumBuckets(const HashTable * hashTable)685 srInt_64 HashTableGetNumBuckets(const HashTable *hashTable) {
686 	return hashTable->numOfBuckets;
687 }
688 
689 /*--------------------------------------------------------------------------*\
690  *  NAME:
691  *	  HashTableSetKeyComparisonFunction()
692  *			  - specifies the function used to compare keys in a HashTable
693  *  DESCRIPTION:
694  *	  Specifies the function used to compare keys in the specified
695  *	  HashTable.  The specified function should return zero if the two
696  *	  keys are considered equal, and non-zero otherwise.  The default
697  *	  function is one that simply compares pointers.
698  *  ARGUMENTS:
699  *	  hashTable	- the HashTable whose key comparison function is being
700  *					 specified
701  *	  keycmp	   - a function which returns zero if the two arguments
702  *					 passed to it are considered "equal" keys and non-zero
703  *					 otherwise
704  *  RETURNS:
705  *	  <nothing>
706 \*--------------------------------------------------------------------------*/
707 
HashTableSetKeyComparisonFunction(HashTable * hashTable,int (* keycmp)(const void * key1,const void * key2))708 void HashTableSetKeyComparisonFunction(HashTable *hashTable,
709 		int (*keycmp)(const void *key1, const void *key2)) {
710 	assert(keycmp != NULL);
711 	hashTable->keycmp = keycmp;
712 }
713 
714 /*--------------------------------------------------------------------------*\
715  *  NAME:
716  *	  HashTableSetValueComparisonFunction()
717  *			  - specifies the function used to compare values in a HashTable
718  *  DESCRIPTION:
719  *	  Specifies the function used to compare values in the specified
720  *	  HashTable.  The specified function should return zero if the two
721  *	  values are considered equal, and non-zero otherwise.  The default
722  *	  function is one that simply compares pointers.
723  *  ARGUMENTS:
724  *	  hashTable	- the HashTable whose value comparison function is being
725  *					 specified
726  *	  valuecmp	 - a function which returns zero if the two arguments
727  *					 passed to it are considered "equal" values and non-zero
728  *					 otherwise
729  *  RETURNS:
730  *	  <nothing>
731 \*--------------------------------------------------------------------------*/
732 
HashTableSetValueComparisonFunction(HashTable * hashTable,int (* valuecmp)(const void * value1,const void * value2))733 void HashTableSetValueComparisonFunction(HashTable *hashTable,
734 		int (*valuecmp)(const void *value1, const void *value2)) {
735 	assert(valuecmp != NULL);
736 	hashTable->valuecmp = valuecmp;
737 }
738 
739 /*--------------------------------------------------------------------------*\
740  *  NAME:
741  *	  HashTableSetHashFunction()
742  *			  - specifies the hash function used by a HashTable
743  *  DESCRIPTION:
744  *	  Specifies the function used to determine the hash value for a key
745  *	  in the specified HashTable (before modulation).  An ideal hash
746  *	  function is one which is easy to compute and approximates a
747  *	  "random" function.  The default function is one that works
748  *	  relatively well for pointers.  If the HashTable keys are to be
749  *	  strings (which is probably the case), then this default function
750  *	  will not suffice, in which case consider using the provided
751  *	  HashTableStringHashFunction() function.
752  *  ARGUMENTS:
753  *	  hashTable	- the HashTable whose hash function is being specified
754  *	  hashFunction - a function which returns an appropriate hash code
755  *					 for a given key
756  *  RETURNS:
757  *	  <nothing>
758 \*--------------------------------------------------------------------------*/
759 
HashTableSetHashFunction(HashTable * hashTable,srUInt_64 (* hashFunction)(const void * key))760 void HashTableSetHashFunction(HashTable *hashTable,
761 		srUInt_64 (*hashFunction)(const void *key))
762 {
763 	assert(hashFunction != NULL);
764 	hashTable->hashFunction = hashFunction;
765 }
766 
767 /*--------------------------------------------------------------------------*\
768  *  NAME:
769  *	  HashTableRehash() - reorganizes a HashTable to be more efficient
770  *  DESCRIPTION:
771  *	  Reorganizes a HashTable to be more efficient.  If a number of
772  *	  buckets is specified, the HashTable is rehashed to that number of
773  *	  buckets.  If 0 is specified, the HashTable is rehashed to a number
774  *	  of buckets which is automatically calculated to be a prime number
775  *	  that achieves (as closely as possible) the ideal element-to-bucket
776  *	  ratio specified by the HashTableSetIdealRatio() function.
777  *  EFFICIENCY:
778  *	  O(n)
779  *  ARGUMENTS:
780  *	  hashTable	- the HashTable to be reorganized
781  *	  numOfBuckets - the number of buckets to rehash the HashTable to.
782  *					 Should be prime.  Ideally, the number of buckets
783  *					 should be between 1/5 and 1 times the expected
784  *					 number of elements in the HashTable.  Values much
785  *					 more or less than this will result in wasted memory
786  *					 or decreased performance respectively.  If 0 is
787  *					 specified, an appropriate number of buckets is
788  *					 automatically calculated.
789  *  RETURNS:
790  *	  <nothing>
791 \*--------------------------------------------------------------------------*/
792 
HashTableRehash(HashTable * hashTable,srInt_64 numOfBuckets)793 void HashTableRehash(HashTable *hashTable, srInt_64 numOfBuckets) {
794 	KeyValuePair **newBucketArray;
795 	int i;
796 
797 	assert(numOfBuckets >= 0);
798 	if (numOfBuckets == 0)
799 		numOfBuckets = calculateIdealNumOfBuckets(hashTable);
800 
801 	if (numOfBuckets == hashTable->numOfBuckets)
802 		return; /* already the right size! */
803 
804 	newBucketArray = (KeyValuePair **)
805 								malloc(numOfBuckets * sizeof(KeyValuePair *));
806 	if (newBucketArray == NULL) {
807 		/* Couldn't allocate memory for the new array.  This isn't a fatal
808 		 * error; we just can't perform the rehash. */
809 		return;
810 	}
811 
812 	for (i=0; i<numOfBuckets; i++)
813 		newBucketArray[i] = NULL;
814 
815 	for (i=0; i<hashTable->numOfBuckets; i++) {
816 		KeyValuePair *pair = hashTable->bucketArray[i];
817 		while (pair != NULL) {
818 			KeyValuePair *nextPair = pair->next;
819 			srInt_64 hashValue = hashTable->hashFunction(pair->key) % numOfBuckets;
820 			pair->next = newBucketArray[hashValue];
821 			newBucketArray[hashValue] = pair;
822 			pair = nextPair;
823 		}
824 	}
825 
826 	free(hashTable->bucketArray);
827 	hashTable->bucketArray = newBucketArray;
828 	hashTable->numOfBuckets = numOfBuckets;
829 }
830 
831 /*--------------------------------------------------------------------------*\
832  *  NAME:
833  *	  HashTableSetIdealRatio()
834  *			  - sets the ideal element-to-bucket ratio of a HashTable
835  *  DESCRIPTION:
836  *	  Sets the ideal element-to-bucket ratio, as well as the lower and
837  *	  upper auto-rehash thresholds, of the specified HashTable.  Note
838  *	  that this function doesn't actually perform a rehash.
839  *
840  *	  The default values for these properties are 3.0, 0.0 and 15.0
841  *	  respectively.  This is likely fine for most situations, so there
842  *	  is probably no need to call this function.
843  *  ARGUMENTS:
844  *	  hashTable	- a HashTable
845  *	  idealRatio   - the ideal element-to-bucket ratio.  When a rehash
846  *					 occurs (either manually via a call to the
847  *					 HashTableRehash() function or automatically due the
848  *					 the triggering of one of the thresholds below), the
849  *					 number of buckets in the HashTable will be
850  *					 recalculated to be a prime number that achieves (as
851  *					 closely as possible) this ideal ratio.  Must be a
852  *					 positive number.
853  *	  lowerRehashThreshold
854  *				   - the element-to-bucket ratio that is considered
855  *					 unacceptably low (i.e., too few elements per bucket).
856  *					 If the actual ratio falls below this number, a
857  *					 rehash will automatically be performed.  Must be
858  *					 lower than the value of idealRatio.  If no ratio
859  *					 is considered unacceptably low, a value of 0.0 can
860  *					 be specified.
861  *	  upperRehashThreshold
862  *				   - the element-to-bucket ratio that is considered
863  *					 unacceptably high (i.e., too many elements per bucket).
864  *					 If the actual ratio rises above this number, a
865  *					 rehash will automatically be performed.  Must be
866  *					 higher than idealRatio.  However, if no ratio
867  *					 is considered unacceptably high, a value of 0.0 can
868  *					 be specified.
869  *  RETURNS:
870  *	  <nothing>
871 \*--------------------------------------------------------------------------*/
872 
HashTableSetIdealRatio(HashTable * hashTable,float idealRatio,float lowerRehashThreshold,float upperRehashThreshold)873 void HashTableSetIdealRatio(HashTable *hashTable, float idealRatio,
874 		float lowerRehashThreshold, float upperRehashThreshold) {
875 	assert(idealRatio > 0.0);
876 	assert(lowerRehashThreshold < idealRatio);
877 	assert(upperRehashThreshold == 0.0 || upperRehashThreshold > idealRatio);
878 
879 	hashTable->idealRatio = idealRatio;
880 	hashTable->lowerRehashThreshold = lowerRehashThreshold;
881 	hashTable->upperRehashThreshold = upperRehashThreshold;
882 }
883 
884 /*--------------------------------------------------------------------------*\
885  *  NAME:
886  *	  HashTableSetDeallocationFunctions()
887  *			  - sets the key and value deallocation functions of a HashTable
888  *  DESCRIPTION:
889  *	  Sets the key and value deallocation functions of the specified
890  *	  HashTable.  This determines what happens to a key or a value when it
891  *	  is removed from the HashTable.  If the deallocation function is NULL
892  *	  (the default if this function is never called), its reference is
893  *	  simply dropped and it is up to the calling program to perform the
894  *	  proper memory management.  If the deallocation function is non-NULL,
895  *	  it is called to free the memory used by the object.  E.g., for simple
896  *	  objects, an appropriate deallocation function may be free().
897  *
898  *	  This affects the behaviour of the HashTableDestroy(), HashTablePut(),
899  *	  HashTableRemove() and HashTableRemoveAll() functions.
900  *  ARGUMENTS:
901  *	  hashTable	- a HashTable
902  *	  keyDeallocator
903  *				   - if non-NULL, the function to be called when a key is
904  *					 removed from the HashTable.
905  *	  valueDeallocator
906  *				   - if non-NULL, the function to be called when a value is
907  *					 removed from the HashTable.
908  *  RETURNS:
909  *	  <nothing>
910 \*--------------------------------------------------------------------------*/
911 
HashTableSetDeallocationFunctions(HashTable * hashTable,void (* keyDeallocator)(void * key),void (* valueDeallocator)(void * value))912 void HashTableSetDeallocationFunctions(HashTable *hashTable,
913 		void (*keyDeallocator)(void *key),
914 		void (*valueDeallocator)(void *value)) {
915 	hashTable->keyDeallocator = keyDeallocator;
916 	hashTable->valueDeallocator = valueDeallocator;
917 }
918 
919 /*--------------------------------------------------------------------------*\
920  *  NAME:
921  *	  HashTableStringHashFunction() - a good hash function for strings
922  *  DESCRIPTION:
923  *	  A hash function that is appropriate for hashing strings.  Note that
924  *	  this is not the default hash function.  To make it the default hash
925  *	  function, call HashTableSetHashFunction(hashTable,
926  *	  HashTableStringHashFunction).
927  *  ARGUMENTS:
928  *	  key	- the key to be hashed
929  *  RETURNS:
930  *	  unsigned long - the unmodulated hash value of the key
931 \*--------------------------------------------------------------------------*/
932 
HashTableStringHashFunction(const void * key)933 srUInt_64 HashTableStringHashFunction(const void *key) {
934 	const unsigned char *str = (const unsigned char *) key;
935 	srUInt_64 hashValue = 0;
936 	int i;
937 
938 	for (i=0; str[i] != '\0'; i++)
939 		hashValue = hashValue * 37 + str[i];
940 
941 	return hashValue;
942 }
943 
pointercmp(const void * pointer1,const void * pointer2)944 static int pointercmp(const void *pointer1, const void *pointer2) {
945 	return (pointer1 != pointer2);
946 }
947 
pointerHashFunction(const void * pointer)948 static srUInt_64 pointerHashFunction(const void *pointer) {
949 	return (srUInt_64)(pointer - NULL);
950 }
951 
isProbablePrime(srInt_64 oddNumber)952 static int isProbablePrime(srInt_64 oddNumber) {
953 	srInt_64 i;
954 
955 	for (i=3; i<51; i+=2)
956 		if (oddNumber == i)
957 			return 1;
958 		else if (oddNumber%i == 0)
959 			return 0;
960 
961 	return 1; /* maybe */
962 }
963 
calculateIdealNumOfBuckets(HashTable * hashTable)964 static srInt_64 calculateIdealNumOfBuckets(HashTable *hashTable) {
965 	srInt_64 idealNumOfBuckets = hashTable->numOfElements / hashTable->idealRatio;
966 	if (idealNumOfBuckets < 5)
967 		idealNumOfBuckets = 5;
968 	else
969 		idealNumOfBuckets |= 0x01; /* make it an odd number */
970 	while (!isProbablePrime(idealNumOfBuckets))
971 		idealNumOfBuckets += 2;
972 
973 	return idealNumOfBuckets;
974 }
975 
976 
free_values_destroy(HashTable * tab)977 void free_values_destroy(HashTable * tab)
978 {
979 
980 	KeyValuePair * cursor;
981 	int bucket;
982 
983 	for(bucket=0; bucket< tab -> numOfBuckets; bucket++)
984 	{
985 		cursor = tab -> bucketArray[bucket];
986 		while (1)
987 		{
988 			if(!cursor) break;
989 			char * read_txt = (char *) cursor ->value;
990 			free(read_txt);
991 			cursor = cursor->next;
992 		}
993 	}
994 
995 	HashTableDestroy(tab);
996 }
997 
HashTableKeyArray(HashTable * tab)998 ArrayList * HashTableKeyArray(HashTable * tab){
999 	ArrayList *ret = ArrayListCreate(20);
1000 	int i;
1001 	for (i=0; i< tab ->numOfBuckets; i++) {
1002 		KeyValuePair *pair = tab ->bucketArray[i];
1003 		while (pair != NULL) {
1004 			ArrayListPush(ret, (void *)pair -> key);
1005 			KeyValuePair *nextPair = pair->next;
1006 			pair = nextPair;
1007 		}
1008 	}
1009 	return ret;
1010 }
1011 
HashTableIteration(HashTable * tab,void process_item (void * key,void * hashed_obj,HashTable * tab))1012 void HashTableIteration(HashTable * tab, void process_item(void * key, void * hashed_obj, HashTable * tab) )
1013 {
1014 	int i;
1015 	for (i=0; i< tab ->numOfBuckets; i++) {
1016 		KeyValuePair *pair = tab ->bucketArray[i];
1017 		while (pair != NULL) {
1018 			process_item(( void * )pair -> key, pair -> value, tab);
1019 			KeyValuePair *nextPair = pair->next;
1020 			pair = nextPair;
1021 		}
1022 	}
1023 }
1024 
HashTableSortedIndexes_copy_idx(void * k,void * v,HashTable * k2int_tab)1025 void HashTableSortedIndexes_copy_idx( void *k, void *v, HashTable * k2int_tab ){
1026 	ArrayList * dsta = k2int_tab -> appendix1;
1027 	ArrayListPush(dsta, k);
1028 }
1029 
HashTableSortedIndexes_cmp_idx(void * Lv,void * Rv,ArrayList * me)1030 int HashTableSortedIndexes_cmp_idx( void * Lv, void * Rv, ArrayList * me ){
1031 	void ** appdx = me -> appendix1;
1032 	HashTable * k2int_tab = appdx[0];
1033 	void * Lhash = HashTableGet(k2int_tab, Lv);
1034 	void * Rhash = HashTableGet(k2int_tab, Rv);
1035 	void * large_first = appdx[1];
1036 	if(large_first){
1037 		if(Lhash > Rhash) return -1;
1038 		if(Lhash < Rhash) return 1;
1039 	}else{
1040 		if(Lhash > Rhash) return 1;
1041 		if(Lhash < Rhash) return -1;
1042 	}
1043 	return 0;
1044 }
1045 
HashTableSortedIndexes(HashTable * k2int_tab,int larger_value_first)1046 ArrayList * HashTableSortedIndexes(HashTable * k2int_tab, int larger_value_first){
1047 	ArrayList *ret = HashTableKeys(k2int_tab);
1048 	void * appx[2];
1049 	ret -> appendix1 = appx;
1050 	appx[0]=k2int_tab;
1051 	appx[1]=NULL+larger_value_first;
1052 	ArrayListSort(ret, HashTableSortedIndexes_cmp_idx);
1053 	return ret;
1054 }
1055