/src/libtiff/libtiff/tif_hash_set.c
Line | Count | Source (jump to first uncovered line) |
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 | | |
39 | | /** List element structure. */ |
40 | | typedef struct _TIFFList TIFFList; |
41 | | |
42 | | /** List element structure. */ |
43 | | struct _TIFFList |
44 | | { |
45 | | /*! Pointer to the data object. Should be allocated and freed by the |
46 | | * caller. |
47 | | * */ |
48 | | void *pData; |
49 | | /*! Pointer to the next element in list. NULL, if current element is the |
50 | | * last one. |
51 | | */ |
52 | | struct _TIFFList *psNext; |
53 | | }; |
54 | | |
55 | | struct _TIFFHashSet |
56 | | { |
57 | | TIFFHashSetHashFunc fnHashFunc; |
58 | | TIFFHashSetEqualFunc fnEqualFunc; |
59 | | TIFFHashSetFreeEltFunc fnFreeEltFunc; |
60 | | TIFFList **tabList; |
61 | | int nSize; |
62 | | int nIndiceAllocatedSize; |
63 | | int nAllocatedSize; |
64 | | TIFFList *psRecyclingList; |
65 | | int nRecyclingListSize; |
66 | | bool bRehash; |
67 | | #ifdef HASH_DEBUG |
68 | | int nCollisions; |
69 | | #endif |
70 | | }; |
71 | | |
72 | | static 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 | | |
82 | | /** |
83 | | * Hash function for an arbitrary pointer |
84 | | * |
85 | | * @param elt the arbitrary pointer to hash |
86 | | * |
87 | | * @return the hash value of the pointer |
88 | | */ |
89 | | |
90 | | static unsigned long TIFFHashSetHashPointer(const void *elt) |
91 | 0 | { |
92 | 0 | return (unsigned long)(uintptr_t)((void *)(elt)); |
93 | 0 | } |
94 | | |
95 | | /************************************************************************/ |
96 | | /* TIFFHashSetEqualPointer() */ |
97 | | /************************************************************************/ |
98 | | |
99 | | /** |
100 | | * Equality function for arbitrary pointers |
101 | | * |
102 | | * @param elt1 the first arbitrary pointer to compare |
103 | | * @param elt2 the second arbitrary pointer to compare |
104 | | * |
105 | | * @return true if the pointers are equal |
106 | | */ |
107 | | |
108 | | static bool TIFFHashSetEqualPointer(const void *elt1, const void *elt2) |
109 | 0 | { |
110 | 0 | return elt1 == elt2; |
111 | 0 | } |
112 | | |
113 | | /************************************************************************/ |
114 | | /* TIFFHashSetNew() */ |
115 | | /************************************************************************/ |
116 | | |
117 | | /** |
118 | | * Creates a new hash set |
119 | | * |
120 | | * The hash function must return a hash value for the elements to insert. |
121 | | * If fnHashFunc is NULL, TIFFHashSetHashPointer will be used. |
122 | | * |
123 | | * The equal function must return if two elements are equal. |
124 | | * If fnEqualFunc is NULL, TIFFHashSetEqualPointer will be used. |
125 | | * |
126 | | * The free function is used to free elements inserted in the hash set, |
127 | | * when the hash set is destroyed, when elements are removed or replaced. |
128 | | * If fnFreeEltFunc is NULL, elements inserted into the hash set will not be |
129 | | * freed. |
130 | | * |
131 | | * @param fnHashFunc hash function. May be NULL. |
132 | | * @param fnEqualFunc equal function. May be NULL. |
133 | | * @param fnFreeEltFunc element free function. May be NULL. |
134 | | * |
135 | | * @return a new hash set |
136 | | */ |
137 | | |
138 | | TIFFHashSet *TIFFHashSetNew(TIFFHashSetHashFunc fnHashFunc, |
139 | | TIFFHashSetEqualFunc fnEqualFunc, |
140 | | TIFFHashSetFreeEltFunc fnFreeEltFunc) |
141 | 0 | { |
142 | 0 | TIFFHashSet *set = (TIFFHashSet *)malloc(sizeof(TIFFHashSet)); |
143 | 0 | if (set == NULL) |
144 | 0 | return NULL; |
145 | 0 | set->fnHashFunc = fnHashFunc ? fnHashFunc : TIFFHashSetHashPointer; |
146 | 0 | set->fnEqualFunc = fnEqualFunc ? fnEqualFunc : TIFFHashSetEqualPointer; |
147 | 0 | set->fnFreeEltFunc = fnFreeEltFunc; |
148 | 0 | set->nSize = 0; |
149 | 0 | set->tabList = (TIFFList **)(calloc(53, sizeof(TIFFList *))); |
150 | 0 | if (set->tabList == NULL) |
151 | 0 | { |
152 | 0 | free(set); |
153 | 0 | return NULL; |
154 | 0 | } |
155 | 0 | set->nIndiceAllocatedSize = 0; |
156 | 0 | set->nAllocatedSize = 53; |
157 | 0 | set->psRecyclingList = NULL; |
158 | 0 | set->nRecyclingListSize = 0; |
159 | 0 | set->bRehash = false; |
160 | | #ifdef HASH_DEBUG |
161 | | set->nCollisions = 0; |
162 | | #endif |
163 | 0 | return set; |
164 | 0 | } |
165 | | |
166 | | /************************************************************************/ |
167 | | /* TIFFHashSetSize() */ |
168 | | /************************************************************************/ |
169 | | |
170 | | /** |
171 | | * Returns the number of elements inserted in the hash set |
172 | | * |
173 | | * Note: this is not the internal size of the hash set |
174 | | * |
175 | | * @param set the hash set |
176 | | * |
177 | | * @return the number of elements in the hash set |
178 | | */ |
179 | | |
180 | | int TIFFHashSetSize(const TIFFHashSet *set) |
181 | 0 | { |
182 | 0 | assert(set != NULL); |
183 | 0 | return set->nSize; |
184 | 0 | } |
185 | | |
186 | | /************************************************************************/ |
187 | | /* TIFFHashSetGetNewListElt() */ |
188 | | /************************************************************************/ |
189 | | |
190 | | static TIFFList *TIFFHashSetGetNewListElt(TIFFHashSet *set) |
191 | 0 | { |
192 | 0 | if (set->psRecyclingList) |
193 | 0 | { |
194 | 0 | TIFFList *psRet = set->psRecyclingList; |
195 | 0 | psRet->pData = NULL; |
196 | 0 | set->nRecyclingListSize--; |
197 | 0 | set->psRecyclingList = psRet->psNext; |
198 | 0 | return psRet; |
199 | 0 | } |
200 | | |
201 | 0 | return (TIFFList *)malloc(sizeof(TIFFList)); |
202 | 0 | } |
203 | | |
204 | | /************************************************************************/ |
205 | | /* TIFFHashSetReturnListElt() */ |
206 | | /************************************************************************/ |
207 | | |
208 | | static void TIFFHashSetReturnListElt(TIFFHashSet *set, TIFFList *psList) |
209 | 0 | { |
210 | 0 | if (set->nRecyclingListSize < 128) |
211 | 0 | { |
212 | 0 | psList->psNext = set->psRecyclingList; |
213 | 0 | set->psRecyclingList = psList; |
214 | 0 | set->nRecyclingListSize++; |
215 | 0 | } |
216 | 0 | else |
217 | 0 | { |
218 | 0 | free(psList); |
219 | 0 | } |
220 | 0 | } |
221 | | |
222 | | /************************************************************************/ |
223 | | /* TIFFHashSetClearInternal() */ |
224 | | /************************************************************************/ |
225 | | |
226 | | static void TIFFHashSetClearInternal(TIFFHashSet *set, bool bFinalize) |
227 | 0 | { |
228 | 0 | assert(set != NULL); |
229 | 0 | for (int i = 0; i < set->nAllocatedSize; i++) |
230 | 0 | { |
231 | 0 | TIFFList *cur = set->tabList[i]; |
232 | 0 | while (cur) |
233 | 0 | { |
234 | 0 | if (set->fnFreeEltFunc) |
235 | 0 | set->fnFreeEltFunc(cur->pData); |
236 | 0 | TIFFList *psNext = cur->psNext; |
237 | 0 | if (bFinalize) |
238 | 0 | free(cur); |
239 | 0 | else |
240 | 0 | TIFFHashSetReturnListElt(set, cur); |
241 | 0 | cur = psNext; |
242 | 0 | } |
243 | 0 | set->tabList[i] = NULL; |
244 | 0 | } |
245 | 0 | set->bRehash = false; |
246 | 0 | } |
247 | | |
248 | | /************************************************************************/ |
249 | | /* TIFFListDestroy() */ |
250 | | /************************************************************************/ |
251 | | |
252 | | /** |
253 | | * Destroy a list. Caller responsible for freeing data objects contained in |
254 | | * list elements. |
255 | | * |
256 | | * @param psList pointer to list head. |
257 | | * |
258 | | */ |
259 | | |
260 | | static void TIFFListDestroy(TIFFList *psList) |
261 | 0 | { |
262 | 0 | TIFFList *psCurrent = psList; |
263 | |
|
264 | 0 | while (psCurrent) |
265 | 0 | { |
266 | 0 | TIFFList *const psNext = psCurrent->psNext; |
267 | 0 | free(psCurrent); |
268 | 0 | psCurrent = psNext; |
269 | 0 | } |
270 | 0 | } |
271 | | |
272 | | /************************************************************************/ |
273 | | /* TIFFHashSetDestroy() */ |
274 | | /************************************************************************/ |
275 | | |
276 | | /** |
277 | | * Destroys an allocated hash set. |
278 | | * |
279 | | * This function also frees the elements if a free function was |
280 | | * provided at the creation of the hash set. |
281 | | * |
282 | | * @param set the hash set |
283 | | */ |
284 | | |
285 | | void TIFFHashSetDestroy(TIFFHashSet *set) |
286 | 0 | { |
287 | 0 | if (set) |
288 | 0 | { |
289 | 0 | TIFFHashSetClearInternal(set, true); |
290 | 0 | free(set->tabList); |
291 | 0 | TIFFListDestroy(set->psRecyclingList); |
292 | 0 | free(set); |
293 | 0 | } |
294 | 0 | } |
295 | | |
296 | | #ifdef notused |
297 | | /************************************************************************/ |
298 | | /* TIFFHashSetClear() */ |
299 | | /************************************************************************/ |
300 | | |
301 | | /** |
302 | | * Clear all elements from a hash set. |
303 | | * |
304 | | * This function also frees the elements if a free function was |
305 | | * provided at the creation of the hash set. |
306 | | * |
307 | | * @param set the hash set |
308 | | */ |
309 | | |
310 | | void TIFFHashSetClear(TIFFHashSet *set) |
311 | | { |
312 | | TIFFHashSetClearInternal(set, false); |
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 | | |
325 | | /** |
326 | | * Walk through the hash set and runs the provided function on all the |
327 | | * elements |
328 | | * |
329 | | * This function is provided the user_data argument of TIFFHashSetForeach. |
330 | | * It must return true to go on the walk through the hash set, or FALSE to |
331 | | * make it stop. |
332 | | * |
333 | | * Note : the structure of the hash set must *NOT* be modified during the |
334 | | * walk. |
335 | | * |
336 | | * @param set the hash set. |
337 | | * @param fnIterFunc the function called on each element. |
338 | | * @param user_data the user data provided to the function. |
339 | | */ |
340 | | |
341 | | void 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 | | |
366 | | static bool TIFFHashSetRehash(TIFFHashSet *set) |
367 | 0 | { |
368 | 0 | int nNewAllocatedSize = anPrimes[set->nIndiceAllocatedSize]; |
369 | 0 | TIFFList **newTabList = |
370 | 0 | (TIFFList **)(calloc(nNewAllocatedSize, sizeof(TIFFList *))); |
371 | 0 | if (newTabList == NULL) |
372 | 0 | 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 | 0 | for (int i = 0; i < set->nAllocatedSize; i++) |
382 | 0 | { |
383 | 0 | TIFFList *cur = set->tabList[i]; |
384 | 0 | while (cur) |
385 | 0 | { |
386 | 0 | const unsigned long nNewHashVal = |
387 | 0 | set->fnHashFunc(cur->pData) % nNewAllocatedSize; |
388 | | #ifdef HASH_DEBUG |
389 | | if (newTabList[nNewHashVal]) |
390 | | set->nCollisions++; |
391 | | #endif |
392 | 0 | TIFFList *psNext = cur->psNext; |
393 | 0 | cur->psNext = newTabList[nNewHashVal]; |
394 | 0 | newTabList[nNewHashVal] = cur; |
395 | 0 | cur = psNext; |
396 | 0 | } |
397 | 0 | } |
398 | 0 | free(set->tabList); |
399 | 0 | set->tabList = newTabList; |
400 | 0 | set->nAllocatedSize = nNewAllocatedSize; |
401 | 0 | set->bRehash = false; |
402 | 0 | return true; |
403 | 0 | } |
404 | | |
405 | | /************************************************************************/ |
406 | | /* TIFFHashSetFindPtr() */ |
407 | | /************************************************************************/ |
408 | | |
409 | | static void **TIFFHashSetFindPtr(TIFFHashSet *set, const void *elt) |
410 | 0 | { |
411 | 0 | const unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize; |
412 | 0 | TIFFList *cur = set->tabList[nHashVal]; |
413 | 0 | while (cur) |
414 | 0 | { |
415 | 0 | if (set->fnEqualFunc(cur->pData, elt)) |
416 | 0 | return &cur->pData; |
417 | 0 | cur = cur->psNext; |
418 | 0 | } |
419 | 0 | return NULL; |
420 | 0 | } |
421 | | |
422 | | /************************************************************************/ |
423 | | /* TIFFHashSetInsert() */ |
424 | | /************************************************************************/ |
425 | | |
426 | | /** |
427 | | * Inserts an element into a hash set. |
428 | | * |
429 | | * If the element was already inserted in the hash set, the previous |
430 | | * element is replaced by the new element. If a free function was provided, |
431 | | * it is used to free the previously inserted element |
432 | | * |
433 | | * @param set the hash set |
434 | | * @param elt the new element to insert in the hash set |
435 | | * |
436 | | * @return true if success. If false is returned, elt has not been inserted, |
437 | | * but TIFFHashSetInsert() will have run the free function if provided. |
438 | | */ |
439 | | |
440 | | bool TIFFHashSetInsert(TIFFHashSet *set, void *elt) |
441 | 0 | { |
442 | 0 | assert(set != NULL); |
443 | 0 | void **pElt = TIFFHashSetFindPtr(set, elt); |
444 | 0 | if (pElt) |
445 | 0 | { |
446 | 0 | if (set->fnFreeEltFunc) |
447 | 0 | set->fnFreeEltFunc(*pElt); |
448 | |
|
449 | 0 | *pElt = elt; |
450 | 0 | return true; |
451 | 0 | } |
452 | | |
453 | 0 | if (set->nSize >= 2 * set->nAllocatedSize / 3 || |
454 | 0 | (set->bRehash && set->nIndiceAllocatedSize > 0 && |
455 | 0 | set->nSize <= set->nAllocatedSize / 2)) |
456 | 0 | { |
457 | 0 | set->nIndiceAllocatedSize++; |
458 | 0 | if (!TIFFHashSetRehash(set)) |
459 | 0 | { |
460 | 0 | set->nIndiceAllocatedSize--; |
461 | 0 | if (set->fnFreeEltFunc) |
462 | 0 | set->fnFreeEltFunc(elt); |
463 | 0 | return false; |
464 | 0 | } |
465 | 0 | } |
466 | | |
467 | 0 | const unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize; |
468 | | #ifdef HASH_DEBUG |
469 | | if (set->tabList[nHashVal]) |
470 | | set->nCollisions++; |
471 | | #endif |
472 | |
|
473 | 0 | TIFFList *new_elt = TIFFHashSetGetNewListElt(set); |
474 | 0 | if (new_elt == NULL) |
475 | 0 | { |
476 | 0 | if (set->fnFreeEltFunc) |
477 | 0 | set->fnFreeEltFunc(elt); |
478 | 0 | return false; |
479 | 0 | } |
480 | 0 | new_elt->pData = elt; |
481 | 0 | new_elt->psNext = set->tabList[nHashVal]; |
482 | 0 | set->tabList[nHashVal] = new_elt; |
483 | 0 | set->nSize++; |
484 | |
|
485 | 0 | return true; |
486 | 0 | } |
487 | | |
488 | | /************************************************************************/ |
489 | | /* TIFFHashSetLookup() */ |
490 | | /************************************************************************/ |
491 | | |
492 | | /** |
493 | | * Returns the element found in the hash set corresponding to the element to |
494 | | * look up The element must not be modified. |
495 | | * |
496 | | * @param set the hash set |
497 | | * @param elt the element to look up in the hash set |
498 | | * |
499 | | * @return the element found in the hash set or NULL |
500 | | */ |
501 | | |
502 | | void *TIFFHashSetLookup(TIFFHashSet *set, const void *elt) |
503 | 0 | { |
504 | 0 | assert(set != NULL); |
505 | 0 | void **pElt = TIFFHashSetFindPtr(set, elt); |
506 | 0 | if (pElt) |
507 | 0 | return *pElt; |
508 | | |
509 | 0 | return NULL; |
510 | 0 | } |
511 | | |
512 | | /************************************************************************/ |
513 | | /* TIFFHashSetRemoveInternal() */ |
514 | | /************************************************************************/ |
515 | | |
516 | | static bool TIFFHashSetRemoveInternal(TIFFHashSet *set, const void *elt, |
517 | | bool bDeferRehash) |
518 | 0 | { |
519 | 0 | assert(set != NULL); |
520 | 0 | if (set->nIndiceAllocatedSize > 0 && set->nSize <= set->nAllocatedSize / 2) |
521 | 0 | { |
522 | 0 | set->nIndiceAllocatedSize--; |
523 | 0 | if (bDeferRehash) |
524 | 0 | set->bRehash = true; |
525 | 0 | else |
526 | 0 | { |
527 | 0 | if (!TIFFHashSetRehash(set)) |
528 | 0 | { |
529 | 0 | set->nIndiceAllocatedSize++; |
530 | 0 | return false; |
531 | 0 | } |
532 | 0 | } |
533 | 0 | } |
534 | | |
535 | 0 | int nHashVal = (int)(set->fnHashFunc(elt) % set->nAllocatedSize); |
536 | 0 | TIFFList *cur = set->tabList[nHashVal]; |
537 | 0 | TIFFList *prev = NULL; |
538 | 0 | while (cur) |
539 | 0 | { |
540 | 0 | if (set->fnEqualFunc(cur->pData, elt)) |
541 | 0 | { |
542 | 0 | if (prev) |
543 | 0 | prev->psNext = cur->psNext; |
544 | 0 | else |
545 | 0 | set->tabList[nHashVal] = cur->psNext; |
546 | |
|
547 | 0 | if (set->fnFreeEltFunc) |
548 | 0 | set->fnFreeEltFunc(cur->pData); |
549 | |
|
550 | 0 | TIFFHashSetReturnListElt(set, cur); |
551 | | #ifdef HASH_DEBUG |
552 | | if (set->tabList[nHashVal]) |
553 | | set->nCollisions--; |
554 | | #endif |
555 | 0 | set->nSize--; |
556 | 0 | return true; |
557 | 0 | } |
558 | 0 | prev = cur; |
559 | 0 | cur = cur->psNext; |
560 | 0 | } |
561 | 0 | return false; |
562 | 0 | } |
563 | | |
564 | | /************************************************************************/ |
565 | | /* TIFFHashSetRemove() */ |
566 | | /************************************************************************/ |
567 | | |
568 | | /** |
569 | | * Removes an element from a hash set |
570 | | * |
571 | | * @param set the hash set |
572 | | * @param elt the new element to remove from the hash set |
573 | | * |
574 | | * @return true if the element was in the hash set |
575 | | */ |
576 | | |
577 | | bool TIFFHashSetRemove(TIFFHashSet *set, const void *elt) |
578 | 0 | { |
579 | 0 | return TIFFHashSetRemoveInternal(set, elt, false); |
580 | 0 | } |
581 | | |
582 | | #ifdef notused |
583 | | /************************************************************************/ |
584 | | /* TIFFHashSetRemoveDeferRehash() */ |
585 | | /************************************************************************/ |
586 | | |
587 | | /** |
588 | | * Removes an element from a hash set. |
589 | | * |
590 | | * This will defer potential rehashing of the set to later calls to |
591 | | * TIFFHashSetInsert() or TIFFHashSetRemove(). |
592 | | * |
593 | | * @param set the hash set |
594 | | * @param elt the new element to remove from the hash set |
595 | | * |
596 | | * @return true if the element was in the hash set |
597 | | */ |
598 | | |
599 | | bool TIFFHashSetRemoveDeferRehash(TIFFHashSet *set, const void *elt) |
600 | | { |
601 | | return TIFFHashSetRemoveInternal(set, elt, true); |
602 | | } |
603 | | #endif |