ReactOS 0.4.16-dev-2546-g56481e1
tif_hash_set.c
Go to the documentation of this file.
1/**********************************************************************
2 *
3 * Name: tif_hash_set.c
4 * Purpose: Hash set functions.
5 * Author: Even Rouault, <even dot rouault at spatialys.com>
6 *
7 **********************************************************************
8 * Copyright (c) 2008-2009, Even Rouault <even dot rouault at spatialys.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
29#include "tif_config.h"
30
31#include "tif_hash_set.h"
32
33#include <assert.h>
34#include <stdbool.h>
35#include <stdint.h>
36#include <stdio.h>
37#include <stdlib.h>
38
40typedef struct _TIFFList TIFFList;
41
44{
48 void *pData;
53};
54
56{
61 int nSize;
66 bool bRehash;
67#ifdef HASH_DEBUG
68 int nCollisions;
69#endif
70};
71
72static const int anPrimes[] = {
73 53, 97, 193, 389, 769, 1543, 3079,
74 6151, 12289, 24593, 49157, 98317, 196613, 393241,
75 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653,
76 100663319, 201326611, 402653189, 805306457, 1610612741};
77
78/************************************************************************/
79/* TIFFHashSetHashPointer() */
80/************************************************************************/
81
90static unsigned long TIFFHashSetHashPointer(const void *elt)
91{
92 return (unsigned long)(uintptr_t)((void *)(elt));
93}
94
95/************************************************************************/
96/* TIFFHashSetEqualPointer() */
97/************************************************************************/
98
108static bool TIFFHashSetEqualPointer(const void *elt1, const void *elt2)
109{
110 return elt1 == elt2;
111}
112
113/************************************************************************/
114/* TIFFHashSetNew() */
115/************************************************************************/
116
139 TIFFHashSetEqualFunc fnEqualFunc,
140 TIFFHashSetFreeEltFunc fnFreeEltFunc)
141{
143 if (set == NULL)
144 return NULL;
145 set->fnHashFunc = fnHashFunc ? fnHashFunc : TIFFHashSetHashPointer;
146 set->fnEqualFunc = fnEqualFunc ? fnEqualFunc : TIFFHashSetEqualPointer;
147 set->fnFreeEltFunc = fnFreeEltFunc;
148 set->nSize = 0;
149 set->tabList = (TIFFList **)(calloc(53, sizeof(TIFFList *)));
150 if (set->tabList == NULL)
151 {
152 free(set);
153 return NULL;
154 }
155 set->nIndiceAllocatedSize = 0;
156 set->nAllocatedSize = 53;
157 set->psRecyclingList = NULL;
158 set->nRecyclingListSize = 0;
159 set->bRehash = false;
160#ifdef HASH_DEBUG
161 set->nCollisions = 0;
162#endif
163 return set;
164}
165
166/************************************************************************/
167/* TIFFHashSetSize() */
168/************************************************************************/
169
181{
182 assert(set != NULL);
183 return set->nSize;
184}
185
186/************************************************************************/
187/* TIFFHashSetGetNewListElt() */
188/************************************************************************/
189
191{
192 if (set->psRecyclingList)
193 {
194 TIFFList *psRet = set->psRecyclingList;
195 psRet->pData = NULL;
196 set->nRecyclingListSize--;
197 set->psRecyclingList = psRet->psNext;
198 return psRet;
199 }
200
201 return (TIFFList *)malloc(sizeof(TIFFList));
202}
203
204/************************************************************************/
205/* TIFFHashSetReturnListElt() */
206/************************************************************************/
207
209{
210 if (set->nRecyclingListSize < 128)
211 {
212 psList->psNext = set->psRecyclingList;
213 set->psRecyclingList = psList;
214 set->nRecyclingListSize++;
215 }
216 else
217 {
218 free(psList);
219 }
220}
221
222/************************************************************************/
223/* TIFFHashSetClearInternal() */
224/************************************************************************/
225
226static void TIFFHashSetClearInternal(TIFFHashSet *set, bool bFinalize)
227{
228 assert(set != NULL);
229 for (int i = 0; i < set->nAllocatedSize; i++)
230 {
231 TIFFList *cur = set->tabList[i];
232 while (cur)
233 {
234 if (set->fnFreeEltFunc)
235 set->fnFreeEltFunc(cur->pData);
236 TIFFList *psNext = cur->psNext;
237 if (bFinalize)
238 free(cur);
239 else
241 cur = psNext;
242 }
243 set->tabList[i] = NULL;
244 }
245 set->bRehash = false;
246}
247
248/************************************************************************/
249/* TIFFListDestroy() */
250/************************************************************************/
251
260static void TIFFListDestroy(TIFFList *psList)
261{
262 TIFFList *psCurrent = psList;
263
264 while (psCurrent)
265 {
266 TIFFList *const psNext = psCurrent->psNext;
267 free(psCurrent);
268 psCurrent = psNext;
269 }
270}
271
272/************************************************************************/
273/* TIFFHashSetDestroy() */
274/************************************************************************/
275
286{
287 if (set)
288 {
290 free(set->tabList);
291 TIFFListDestroy(set->psRecyclingList);
292 free(set);
293 }
294}
295
296#ifdef notused
297/************************************************************************/
298/* TIFFHashSetClear() */
299/************************************************************************/
300
310void TIFFHashSetClear(TIFFHashSet *set)
311{
313 set->nIndiceAllocatedSize = 0;
314 set->nAllocatedSize = 53;
315#ifdef HASH_DEBUG
316 set->nCollisions = 0;
317#endif
318 set->nSize = 0;
319}
320
321/************************************************************************/
322/* TIFFHashSetForeach() */
323/************************************************************************/
324
341void TIFFHashSetForeach(TIFFHashSet *set, TIFFHashSetIterEltFunc fnIterFunc,
342 void *user_data)
343{
344 assert(set != NULL);
345 if (!fnIterFunc)
346 return;
347
348 for (int i = 0; i < set->nAllocatedSize; i++)
349 {
350 TIFFList *cur = set->tabList[i];
351 while (cur)
352 {
353 if (!fnIterFunc(cur->pData, user_data))
354 return;
355
356 cur = cur->psNext;
357 }
358 }
359}
360#endif
361
362/************************************************************************/
363/* TIFFHashSetRehash() */
364/************************************************************************/
365
367{
368 int nNewAllocatedSize = anPrimes[set->nIndiceAllocatedSize];
369 TIFFList **newTabList =
370 (TIFFList **)(calloc(nNewAllocatedSize, sizeof(TIFFList *)));
371 if (newTabList == NULL)
372 return false;
373#ifdef HASH_DEBUG
374 TIFFDebug("TIFFHASH",
375 "hashSet=%p, nSize=%d, nCollisions=%d, "
376 "fCollisionRate=%.02f",
377 set, set->nSize, set->nCollisions,
378 set->nCollisions * 100.0 / set->nSize);
379 set->nCollisions = 0;
380#endif
381 for (int i = 0; i < set->nAllocatedSize; i++)
382 {
383 TIFFList *cur = set->tabList[i];
384 while (cur)
385 {
386 const unsigned long nNewHashVal =
387 set->fnHashFunc(cur->pData) % nNewAllocatedSize;
388#ifdef HASH_DEBUG
389 if (newTabList[nNewHashVal])
390 set->nCollisions++;
391#endif
392 TIFFList *psNext = cur->psNext;
393 cur->psNext = newTabList[nNewHashVal];
394 newTabList[nNewHashVal] = cur;
395 cur = psNext;
396 }
397 }
398 free(set->tabList);
399 set->tabList = newTabList;
400 set->nAllocatedSize = nNewAllocatedSize;
401 set->bRehash = false;
402 return true;
403}
404
405/************************************************************************/
406/* TIFFHashSetFindPtr() */
407/************************************************************************/
408
409static void **TIFFHashSetFindPtr(TIFFHashSet *set, const void *elt)
410{
411 const unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize;
412 TIFFList *cur = set->tabList[nHashVal];
413 while (cur)
414 {
415 if (set->fnEqualFunc(cur->pData, elt))
416 return &cur->pData;
417 cur = cur->psNext;
418 }
419 return NULL;
420}
421
422/************************************************************************/
423/* TIFFHashSetInsert() */
424/************************************************************************/
425
441{
442 assert(set != NULL);
443 void **pElt = TIFFHashSetFindPtr(set, elt);
444 if (pElt)
445 {
446 if (set->fnFreeEltFunc)
447 set->fnFreeEltFunc(*pElt);
448
449 *pElt = elt;
450 return true;
451 }
452
453 if (set->nSize >= 2 * set->nAllocatedSize / 3 ||
454 (set->bRehash && set->nIndiceAllocatedSize > 0 &&
455 set->nSize <= set->nAllocatedSize / 2))
456 {
457 set->nIndiceAllocatedSize++;
459 {
460 set->nIndiceAllocatedSize--;
461 if (set->fnFreeEltFunc)
462 set->fnFreeEltFunc(elt);
463 return false;
464 }
465 }
466
467 const unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize;
468#ifdef HASH_DEBUG
469 if (set->tabList[nHashVal])
470 set->nCollisions++;
471#endif
472
474 if (new_elt == NULL)
475 {
476 if (set->fnFreeEltFunc)
477 set->fnFreeEltFunc(elt);
478 return false;
479 }
480 new_elt->pData = elt;
481 new_elt->psNext = set->tabList[nHashVal];
482 set->tabList[nHashVal] = new_elt;
483 set->nSize++;
484
485 return true;
486}
487
488/************************************************************************/
489/* TIFFHashSetLookup() */
490/************************************************************************/
491
502void *TIFFHashSetLookup(TIFFHashSet *set, const void *elt)
503{
504 assert(set != NULL);
505 void **pElt = TIFFHashSetFindPtr(set, elt);
506 if (pElt)
507 return *pElt;
508
509 return NULL;
510}
511
512/************************************************************************/
513/* TIFFHashSetRemoveInternal() */
514/************************************************************************/
515
516static bool TIFFHashSetRemoveInternal(TIFFHashSet *set, const void *elt,
517 bool bDeferRehash)
518{
519 assert(set != NULL);
520 if (set->nIndiceAllocatedSize > 0 && set->nSize <= set->nAllocatedSize / 2)
521 {
522 set->nIndiceAllocatedSize--;
523 if (bDeferRehash)
524 set->bRehash = true;
525 else
526 {
528 {
529 set->nIndiceAllocatedSize++;
530 return false;
531 }
532 }
533 }
534
535 int nHashVal = (int)(set->fnHashFunc(elt) % set->nAllocatedSize);
536 TIFFList *cur = set->tabList[nHashVal];
537 TIFFList *prev = NULL;
538 while (cur)
539 {
540 if (set->fnEqualFunc(cur->pData, elt))
541 {
542 if (prev)
543 prev->psNext = cur->psNext;
544 else
545 set->tabList[nHashVal] = cur->psNext;
546
547 if (set->fnFreeEltFunc)
548 set->fnFreeEltFunc(cur->pData);
549
551#ifdef HASH_DEBUG
552 if (set->tabList[nHashVal])
553 set->nCollisions--;
554#endif
555 set->nSize--;
556 return true;
557 }
558 prev = cur;
559 cur = cur->psNext;
560 }
561 return false;
562}
563
564/************************************************************************/
565/* TIFFHashSetRemove() */
566/************************************************************************/
567
577bool TIFFHashSetRemove(TIFFHashSet *set, const void *elt)
578{
579 return TIFFHashSetRemoveInternal(set, elt, false);
580}
581
582#ifdef notused
583/************************************************************************/
584/* TIFFHashSetRemoveDeferRehash() */
585/************************************************************************/
586
599bool TIFFHashSetRemoveDeferRehash(TIFFHashSet *set, const void *elt)
600{
601 return TIFFHashSetRemoveInternal(set, elt, true);
602}
603#endif
Definition: _set.h:50
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
static void * user_data
Definition: metahost.c:106
#define assert(_expr)
Definition: assert.h:32
unsigned int uintptr_t
Definition: corecrt.h:185
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
FxCollectionEntry * cur
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define calloc
Definition: rosglue.h:14
int nIndiceAllocatedSize
Definition: tif_hash_set.c:62
TIFFList * psRecyclingList
Definition: tif_hash_set.c:64
TIFFHashSetEqualFunc fnEqualFunc
Definition: tif_hash_set.c:58
TIFFHashSetFreeEltFunc fnFreeEltFunc
Definition: tif_hash_set.c:59
TIFFList ** tabList
Definition: tif_hash_set.c:60
TIFFHashSetHashFunc fnHashFunc
Definition: tif_hash_set.c:57
int nAllocatedSize
Definition: tif_hash_set.c:63
int nRecyclingListSize
Definition: tif_hash_set.c:65
struct _TIFFList * psNext
Definition: tif_hash_set.c:52
void * pData
Definition: tif_hash_set.c:48
static void TIFFHashSetReturnListElt(TIFFHashSet *set, TIFFList *psList)
Definition: tif_hash_set.c:208
static unsigned long TIFFHashSetHashPointer(const void *elt)
Definition: tif_hash_set.c:90
void * TIFFHashSetLookup(TIFFHashSet *set, const void *elt)
Definition: tif_hash_set.c:502
bool TIFFHashSetInsert(TIFFHashSet *set, void *elt)
Definition: tif_hash_set.c:440
bool TIFFHashSetRemove(TIFFHashSet *set, const void *elt)
Definition: tif_hash_set.c:577
int TIFFHashSetSize(const TIFFHashSet *set)
Definition: tif_hash_set.c:180
TIFFHashSet * TIFFHashSetNew(TIFFHashSetHashFunc fnHashFunc, TIFFHashSetEqualFunc fnEqualFunc, TIFFHashSetFreeEltFunc fnFreeEltFunc)
Definition: tif_hash_set.c:138
static TIFFList * TIFFHashSetGetNewListElt(TIFFHashSet *set)
Definition: tif_hash_set.c:190
static bool TIFFHashSetEqualPointer(const void *elt1, const void *elt2)
Definition: tif_hash_set.c:108
void TIFFHashSetDestroy(TIFFHashSet *set)
Definition: tif_hash_set.c:285
static const int anPrimes[]
Definition: tif_hash_set.c:72
static void TIFFListDestroy(TIFFList *psList)
Definition: tif_hash_set.c:260
static void ** TIFFHashSetFindPtr(TIFFHashSet *set, const void *elt)
Definition: tif_hash_set.c:409
static bool TIFFHashSetRemoveInternal(TIFFHashSet *set, const void *elt, bool bDeferRehash)
Definition: tif_hash_set.c:516
static void TIFFHashSetClearInternal(TIFFHashSet *set, bool bFinalize)
Definition: tif_hash_set.c:226
static bool TIFFHashSetRehash(TIFFHashSet *set)
Definition: tif_hash_set.c:366
bool(* TIFFHashSetEqualFunc)(const void *elt1, const void *elt2)
Definition: tif_hash_set.h:61
void(* TIFFHashSetFreeEltFunc)(void *elt)
Definition: tif_hash_set.h:64
unsigned long(* TIFFHashSetHashFunc)(const void *elt)
Definition: tif_hash_set.h:58