xref: /aosp_15_r20/external/cronet/third_party/libxml/src/hash.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker /*
2*6777b538SAndroid Build Coastguard Worker  * hash.c: hash tables
3*6777b538SAndroid Build Coastguard Worker  *
4*6777b538SAndroid Build Coastguard Worker  * Hash table with open addressing, linear probing and
5*6777b538SAndroid Build Coastguard Worker  * Robin Hood reordering.
6*6777b538SAndroid Build Coastguard Worker  *
7*6777b538SAndroid Build Coastguard Worker  * See Copyright for the status of this software.
8*6777b538SAndroid Build Coastguard Worker  */
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #define IN_LIBXML
11*6777b538SAndroid Build Coastguard Worker #include "libxml.h"
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #include <string.h>
14*6777b538SAndroid Build Coastguard Worker #include <limits.h>
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #include <libxml/parser.h>
17*6777b538SAndroid Build Coastguard Worker #include <libxml/hash.h>
18*6777b538SAndroid Build Coastguard Worker #include <libxml/dict.h>
19*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
20*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlstring.h>
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker #include "private/dict.h"
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker #ifndef SIZE_MAX
25*6777b538SAndroid Build Coastguard Worker   #define SIZE_MAX ((size_t) -1)
26*6777b538SAndroid Build Coastguard Worker #endif
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker #define MAX_FILL_NUM 7
29*6777b538SAndroid Build Coastguard Worker #define MAX_FILL_DENOM 8
30*6777b538SAndroid Build Coastguard Worker #define MIN_HASH_SIZE 8
31*6777b538SAndroid Build Coastguard Worker #define MAX_HASH_SIZE (1u << 31)
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker /*
34*6777b538SAndroid Build Coastguard Worker  * A single entry in the hash table
35*6777b538SAndroid Build Coastguard Worker  */
36*6777b538SAndroid Build Coastguard Worker typedef struct {
37*6777b538SAndroid Build Coastguard Worker     unsigned hashValue; /* 0 means unoccupied, occupied entries have the
38*6777b538SAndroid Build Coastguard Worker                          * MAX_HASH_SIZE bit set to 1 */
39*6777b538SAndroid Build Coastguard Worker     xmlChar *key;
40*6777b538SAndroid Build Coastguard Worker     xmlChar *key2; /* TODO: Don't allocate possibly empty keys */
41*6777b538SAndroid Build Coastguard Worker     xmlChar *key3;
42*6777b538SAndroid Build Coastguard Worker     void *payload;
43*6777b538SAndroid Build Coastguard Worker } xmlHashEntry;
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker /*
46*6777b538SAndroid Build Coastguard Worker  * The entire hash table
47*6777b538SAndroid Build Coastguard Worker  */
48*6777b538SAndroid Build Coastguard Worker struct _xmlHashTable {
49*6777b538SAndroid Build Coastguard Worker     xmlHashEntry *table;
50*6777b538SAndroid Build Coastguard Worker     unsigned size; /* power of two */
51*6777b538SAndroid Build Coastguard Worker     unsigned nbElems;
52*6777b538SAndroid Build Coastguard Worker     xmlDictPtr dict;
53*6777b538SAndroid Build Coastguard Worker     unsigned randomSeed;
54*6777b538SAndroid Build Coastguard Worker };
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker static int
57*6777b538SAndroid Build Coastguard Worker xmlHashGrow(xmlHashTablePtr hash, unsigned size);
58*6777b538SAndroid Build Coastguard Worker 
59*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
60*6777b538SAndroid Build Coastguard Worker static unsigned
xmlHashValue(unsigned seed,const xmlChar * key,const xmlChar * key2,const xmlChar * key3,size_t * lengths)61*6777b538SAndroid Build Coastguard Worker xmlHashValue(unsigned seed, const xmlChar *key, const xmlChar *key2,
62*6777b538SAndroid Build Coastguard Worker              const xmlChar *key3, size_t *lengths) {
63*6777b538SAndroid Build Coastguard Worker     unsigned h1, h2;
64*6777b538SAndroid Build Coastguard Worker     size_t i;
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker     HASH_INIT(h1, h2, seed);
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker     for (i = 0; key[i] != 0; i++) {
69*6777b538SAndroid Build Coastguard Worker         HASH_UPDATE(h1, h2, key[i]);
70*6777b538SAndroid Build Coastguard Worker     }
71*6777b538SAndroid Build Coastguard Worker     if (lengths)
72*6777b538SAndroid Build Coastguard Worker         lengths[0] = i;
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker     HASH_UPDATE(h1, h2, 0);
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker     if (key2 != NULL) {
77*6777b538SAndroid Build Coastguard Worker         for (i = 0; key2[i] != 0; i++) {
78*6777b538SAndroid Build Coastguard Worker             HASH_UPDATE(h1, h2, key2[i]);
79*6777b538SAndroid Build Coastguard Worker         }
80*6777b538SAndroid Build Coastguard Worker         if (lengths)
81*6777b538SAndroid Build Coastguard Worker             lengths[1] = i;
82*6777b538SAndroid Build Coastguard Worker     }
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker     HASH_UPDATE(h1, h2, 0);
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker     if (key3 != NULL) {
87*6777b538SAndroid Build Coastguard Worker         for (i = 0; key3[i] != 0; i++) {
88*6777b538SAndroid Build Coastguard Worker             HASH_UPDATE(h1, h2, key3[i]);
89*6777b538SAndroid Build Coastguard Worker         }
90*6777b538SAndroid Build Coastguard Worker         if (lengths)
91*6777b538SAndroid Build Coastguard Worker             lengths[2] = i;
92*6777b538SAndroid Build Coastguard Worker     }
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker     HASH_FINISH(h1, h2);
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker     return(h2);
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
100*6777b538SAndroid Build Coastguard Worker static unsigned
xmlHashQNameValue(unsigned seed,const xmlChar * prefix,const xmlChar * name,const xmlChar * prefix2,const xmlChar * name2,const xmlChar * prefix3,const xmlChar * name3)101*6777b538SAndroid Build Coastguard Worker xmlHashQNameValue(unsigned seed,
102*6777b538SAndroid Build Coastguard Worker                   const xmlChar *prefix, const xmlChar *name,
103*6777b538SAndroid Build Coastguard Worker                   const xmlChar *prefix2, const xmlChar *name2,
104*6777b538SAndroid Build Coastguard Worker                   const xmlChar *prefix3, const xmlChar *name3) {
105*6777b538SAndroid Build Coastguard Worker     unsigned h1, h2, ch;
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker     HASH_INIT(h1, h2, seed);
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker     if (prefix != NULL) {
110*6777b538SAndroid Build Coastguard Worker         while ((ch = *prefix++) != 0) {
111*6777b538SAndroid Build Coastguard Worker             HASH_UPDATE(h1, h2, ch);
112*6777b538SAndroid Build Coastguard Worker         }
113*6777b538SAndroid Build Coastguard Worker         HASH_UPDATE(h1, h2, ':');
114*6777b538SAndroid Build Coastguard Worker     }
115*6777b538SAndroid Build Coastguard Worker     if (name != NULL) {
116*6777b538SAndroid Build Coastguard Worker         while ((ch = *name++) != 0) {
117*6777b538SAndroid Build Coastguard Worker             HASH_UPDATE(h1, h2, ch);
118*6777b538SAndroid Build Coastguard Worker         }
119*6777b538SAndroid Build Coastguard Worker     }
120*6777b538SAndroid Build Coastguard Worker     HASH_UPDATE(h1, h2, 0);
121*6777b538SAndroid Build Coastguard Worker     if (prefix2 != NULL) {
122*6777b538SAndroid Build Coastguard Worker         while ((ch = *prefix2++) != 0) {
123*6777b538SAndroid Build Coastguard Worker             HASH_UPDATE(h1, h2, ch);
124*6777b538SAndroid Build Coastguard Worker         }
125*6777b538SAndroid Build Coastguard Worker         HASH_UPDATE(h1, h2, ':');
126*6777b538SAndroid Build Coastguard Worker     }
127*6777b538SAndroid Build Coastguard Worker     if (name2 != NULL) {
128*6777b538SAndroid Build Coastguard Worker         while ((ch = *name2++) != 0) {
129*6777b538SAndroid Build Coastguard Worker             HASH_UPDATE(h1, h2, ch);
130*6777b538SAndroid Build Coastguard Worker         }
131*6777b538SAndroid Build Coastguard Worker     }
132*6777b538SAndroid Build Coastguard Worker     HASH_UPDATE(h1, h2, 0);
133*6777b538SAndroid Build Coastguard Worker     if (prefix3 != NULL) {
134*6777b538SAndroid Build Coastguard Worker         while ((ch = *prefix3++) != 0) {
135*6777b538SAndroid Build Coastguard Worker             HASH_UPDATE(h1, h2, ch);
136*6777b538SAndroid Build Coastguard Worker         }
137*6777b538SAndroid Build Coastguard Worker         HASH_UPDATE(h1, h2, ':');
138*6777b538SAndroid Build Coastguard Worker     }
139*6777b538SAndroid Build Coastguard Worker     if (name3 != NULL) {
140*6777b538SAndroid Build Coastguard Worker         while ((ch = *name3++) != 0) {
141*6777b538SAndroid Build Coastguard Worker             HASH_UPDATE(h1, h2, ch);
142*6777b538SAndroid Build Coastguard Worker         }
143*6777b538SAndroid Build Coastguard Worker     }
144*6777b538SAndroid Build Coastguard Worker 
145*6777b538SAndroid Build Coastguard Worker     HASH_FINISH(h1, h2);
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker     return(h2);
148*6777b538SAndroid Build Coastguard Worker }
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker /**
151*6777b538SAndroid Build Coastguard Worker  * xmlHashCreate:
152*6777b538SAndroid Build Coastguard Worker  * @size: initial size of the hash table
153*6777b538SAndroid Build Coastguard Worker  *
154*6777b538SAndroid Build Coastguard Worker  * Create a new hash table. Set size to zero if the number of entries
155*6777b538SAndroid Build Coastguard Worker  * can't be estimated.
156*6777b538SAndroid Build Coastguard Worker  *
157*6777b538SAndroid Build Coastguard Worker  * Returns the newly created object, or NULL if a memory allocation failed.
158*6777b538SAndroid Build Coastguard Worker  */
159*6777b538SAndroid Build Coastguard Worker xmlHashTablePtr
xmlHashCreate(int size)160*6777b538SAndroid Build Coastguard Worker xmlHashCreate(int size) {
161*6777b538SAndroid Build Coastguard Worker     xmlHashTablePtr hash;
162*6777b538SAndroid Build Coastguard Worker 
163*6777b538SAndroid Build Coastguard Worker     xmlInitParser();
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker     hash = xmlMalloc(sizeof(*hash));
166*6777b538SAndroid Build Coastguard Worker     if (hash == NULL)
167*6777b538SAndroid Build Coastguard Worker         return(NULL);
168*6777b538SAndroid Build Coastguard Worker     hash->dict = NULL;
169*6777b538SAndroid Build Coastguard Worker     hash->size = 0;
170*6777b538SAndroid Build Coastguard Worker     hash->table = NULL;
171*6777b538SAndroid Build Coastguard Worker     hash->nbElems = 0;
172*6777b538SAndroid Build Coastguard Worker     hash->randomSeed = xmlRandom();
173*6777b538SAndroid Build Coastguard Worker #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
174*6777b538SAndroid Build Coastguard Worker     hash->randomSeed = 0;
175*6777b538SAndroid Build Coastguard Worker #endif
176*6777b538SAndroid Build Coastguard Worker 
177*6777b538SAndroid Build Coastguard Worker     /*
178*6777b538SAndroid Build Coastguard Worker      * Unless a larger size is passed, the backing table is created
179*6777b538SAndroid Build Coastguard Worker      * lazily with MIN_HASH_SIZE capacity. In practice, there are many
180*6777b538SAndroid Build Coastguard Worker      * hash tables which are never filled.
181*6777b538SAndroid Build Coastguard Worker      */
182*6777b538SAndroid Build Coastguard Worker     if (size > MIN_HASH_SIZE) {
183*6777b538SAndroid Build Coastguard Worker         unsigned newSize = MIN_HASH_SIZE * 2;
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker         while ((newSize < (unsigned) size) && (newSize < MAX_HASH_SIZE))
186*6777b538SAndroid Build Coastguard Worker             newSize *= 2;
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker         if (xmlHashGrow(hash, newSize) != 0) {
189*6777b538SAndroid Build Coastguard Worker             xmlFree(hash);
190*6777b538SAndroid Build Coastguard Worker             return(NULL);
191*6777b538SAndroid Build Coastguard Worker         }
192*6777b538SAndroid Build Coastguard Worker     }
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker     return(hash);
195*6777b538SAndroid Build Coastguard Worker }
196*6777b538SAndroid Build Coastguard Worker 
197*6777b538SAndroid Build Coastguard Worker /**
198*6777b538SAndroid Build Coastguard Worker  * xmlHashCreateDict:
199*6777b538SAndroid Build Coastguard Worker  * @size: the size of the hash table
200*6777b538SAndroid Build Coastguard Worker  * @dict: a dictionary to use for the hash
201*6777b538SAndroid Build Coastguard Worker  *
202*6777b538SAndroid Build Coastguard Worker  * Create a new hash table backed by a dictionary. This can reduce
203*6777b538SAndroid Build Coastguard Worker  * resource usage considerably if most keys passed to API functions
204*6777b538SAndroid Build Coastguard Worker  * originate from this dictionary.
205*6777b538SAndroid Build Coastguard Worker  *
206*6777b538SAndroid Build Coastguard Worker  * Returns the newly created object, or NULL if a memory allocation failed.
207*6777b538SAndroid Build Coastguard Worker  */
208*6777b538SAndroid Build Coastguard Worker xmlHashTablePtr
xmlHashCreateDict(int size,xmlDictPtr dict)209*6777b538SAndroid Build Coastguard Worker xmlHashCreateDict(int size, xmlDictPtr dict) {
210*6777b538SAndroid Build Coastguard Worker     xmlHashTablePtr hash;
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker     hash = xmlHashCreate(size);
213*6777b538SAndroid Build Coastguard Worker     if (hash != NULL) {
214*6777b538SAndroid Build Coastguard Worker         hash->dict = dict;
215*6777b538SAndroid Build Coastguard Worker         xmlDictReference(dict);
216*6777b538SAndroid Build Coastguard Worker     }
217*6777b538SAndroid Build Coastguard Worker     return(hash);
218*6777b538SAndroid Build Coastguard Worker }
219*6777b538SAndroid Build Coastguard Worker 
220*6777b538SAndroid Build Coastguard Worker /**
221*6777b538SAndroid Build Coastguard Worker  * xmlHashFree:
222*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
223*6777b538SAndroid Build Coastguard Worker  * @dealloc: deallocator function or NULL
224*6777b538SAndroid Build Coastguard Worker  *
225*6777b538SAndroid Build Coastguard Worker  * Free the hash and its contents. The payload is deallocated with
226*6777b538SAndroid Build Coastguard Worker  * @dealloc if provided.
227*6777b538SAndroid Build Coastguard Worker  */
228*6777b538SAndroid Build Coastguard Worker void
xmlHashFree(xmlHashTablePtr hash,xmlHashDeallocator dealloc)229*6777b538SAndroid Build Coastguard Worker xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc) {
230*6777b538SAndroid Build Coastguard Worker     if (hash == NULL)
231*6777b538SAndroid Build Coastguard Worker         return;
232*6777b538SAndroid Build Coastguard Worker 
233*6777b538SAndroid Build Coastguard Worker     if (hash->table) {
234*6777b538SAndroid Build Coastguard Worker         const xmlHashEntry *end = &hash->table[hash->size];
235*6777b538SAndroid Build Coastguard Worker         const xmlHashEntry *entry;
236*6777b538SAndroid Build Coastguard Worker 
237*6777b538SAndroid Build Coastguard Worker         for (entry = hash->table; entry < end; entry++) {
238*6777b538SAndroid Build Coastguard Worker             if (entry->hashValue == 0)
239*6777b538SAndroid Build Coastguard Worker                 continue;
240*6777b538SAndroid Build Coastguard Worker             if ((dealloc != NULL) && (entry->payload != NULL))
241*6777b538SAndroid Build Coastguard Worker                 dealloc(entry->payload, entry->key);
242*6777b538SAndroid Build Coastguard Worker             if (hash->dict == NULL) {
243*6777b538SAndroid Build Coastguard Worker                 if (entry->key)
244*6777b538SAndroid Build Coastguard Worker                     xmlFree(entry->key);
245*6777b538SAndroid Build Coastguard Worker                 if (entry->key2)
246*6777b538SAndroid Build Coastguard Worker                     xmlFree(entry->key2);
247*6777b538SAndroid Build Coastguard Worker                 if (entry->key3)
248*6777b538SAndroid Build Coastguard Worker                     xmlFree(entry->key3);
249*6777b538SAndroid Build Coastguard Worker             }
250*6777b538SAndroid Build Coastguard Worker         }
251*6777b538SAndroid Build Coastguard Worker 
252*6777b538SAndroid Build Coastguard Worker         xmlFree(hash->table);
253*6777b538SAndroid Build Coastguard Worker     }
254*6777b538SAndroid Build Coastguard Worker 
255*6777b538SAndroid Build Coastguard Worker     if (hash->dict)
256*6777b538SAndroid Build Coastguard Worker         xmlDictFree(hash->dict);
257*6777b538SAndroid Build Coastguard Worker 
258*6777b538SAndroid Build Coastguard Worker     xmlFree(hash);
259*6777b538SAndroid Build Coastguard Worker }
260*6777b538SAndroid Build Coastguard Worker 
261*6777b538SAndroid Build Coastguard Worker /**
262*6777b538SAndroid Build Coastguard Worker  * xmlFastStrEqual:
263*6777b538SAndroid Build Coastguard Worker  * @s1: string
264*6777b538SAndroid Build Coastguard Worker  * @s2: string
265*6777b538SAndroid Build Coastguard Worker  *
266*6777b538SAndroid Build Coastguard Worker  * Compare two strings for equality, allowing NULL values.
267*6777b538SAndroid Build Coastguard Worker  */
268*6777b538SAndroid Build Coastguard Worker static int
xmlFastStrEqual(const xmlChar * s1,const xmlChar * s2)269*6777b538SAndroid Build Coastguard Worker xmlFastStrEqual(const xmlChar *s1, const xmlChar *s2) {
270*6777b538SAndroid Build Coastguard Worker     if (s1 == NULL)
271*6777b538SAndroid Build Coastguard Worker         return(s2 == NULL);
272*6777b538SAndroid Build Coastguard Worker     else
273*6777b538SAndroid Build Coastguard Worker         return((s2 != NULL) &&
274*6777b538SAndroid Build Coastguard Worker                (strcmp((const char *) s1, (const char *) s2) == 0));
275*6777b538SAndroid Build Coastguard Worker }
276*6777b538SAndroid Build Coastguard Worker 
277*6777b538SAndroid Build Coastguard Worker /**
278*6777b538SAndroid Build Coastguard Worker  * xmlHashFindEntry:
279*6777b538SAndroid Build Coastguard Worker  * @hash: hash table, non-NULL, size > 0
280*6777b538SAndroid Build Coastguard Worker  * @key: first string key, non-NULL
281*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
282*6777b538SAndroid Build Coastguard Worker  * @key3: third string key
283*6777b538SAndroid Build Coastguard Worker  * @hashValue: valid hash value of keys
284*6777b538SAndroid Build Coastguard Worker  * @pfound: result of search
285*6777b538SAndroid Build Coastguard Worker  *
286*6777b538SAndroid Build Coastguard Worker  * Try to find a matching hash table entry. If an entry was found, set
287*6777b538SAndroid Build Coastguard Worker  * @found to 1 and return the entry. Otherwise, set @found to 0 and return
288*6777b538SAndroid Build Coastguard Worker  * the location where a new entry should be inserted.
289*6777b538SAndroid Build Coastguard Worker  */
290*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
291*6777b538SAndroid Build Coastguard Worker static xmlHashEntry *
xmlHashFindEntry(const xmlHashTable * hash,const xmlChar * key,const xmlChar * key2,const xmlChar * key3,unsigned hashValue,int * pfound)292*6777b538SAndroid Build Coastguard Worker xmlHashFindEntry(const xmlHashTable *hash, const xmlChar *key,
293*6777b538SAndroid Build Coastguard Worker                  const xmlChar *key2, const xmlChar *key3,
294*6777b538SAndroid Build Coastguard Worker                  unsigned hashValue, int *pfound) {
295*6777b538SAndroid Build Coastguard Worker     xmlHashEntry *entry;
296*6777b538SAndroid Build Coastguard Worker     unsigned mask, pos, displ;
297*6777b538SAndroid Build Coastguard Worker     int found = 0;
298*6777b538SAndroid Build Coastguard Worker 
299*6777b538SAndroid Build Coastguard Worker     mask = hash->size - 1;
300*6777b538SAndroid Build Coastguard Worker     pos = hashValue & mask;
301*6777b538SAndroid Build Coastguard Worker     entry = &hash->table[pos];
302*6777b538SAndroid Build Coastguard Worker 
303*6777b538SAndroid Build Coastguard Worker     if (entry->hashValue != 0) {
304*6777b538SAndroid Build Coastguard Worker         /*
305*6777b538SAndroid Build Coastguard Worker          * Robin hood hashing: abort if the displacement of the entry
306*6777b538SAndroid Build Coastguard Worker          * is smaller than the displacement of the key we look for.
307*6777b538SAndroid Build Coastguard Worker          * This also stops at the correct position when inserting.
308*6777b538SAndroid Build Coastguard Worker          */
309*6777b538SAndroid Build Coastguard Worker         displ = 0;
310*6777b538SAndroid Build Coastguard Worker         hashValue |= MAX_HASH_SIZE;
311*6777b538SAndroid Build Coastguard Worker 
312*6777b538SAndroid Build Coastguard Worker         do {
313*6777b538SAndroid Build Coastguard Worker             if (entry->hashValue == hashValue) {
314*6777b538SAndroid Build Coastguard Worker                 if (hash->dict) {
315*6777b538SAndroid Build Coastguard Worker                     if ((entry->key == key) &&
316*6777b538SAndroid Build Coastguard Worker                         (entry->key2 == key2) &&
317*6777b538SAndroid Build Coastguard Worker                         (entry->key3 == key3)) {
318*6777b538SAndroid Build Coastguard Worker                         found = 1;
319*6777b538SAndroid Build Coastguard Worker                         break;
320*6777b538SAndroid Build Coastguard Worker                     }
321*6777b538SAndroid Build Coastguard Worker                 }
322*6777b538SAndroid Build Coastguard Worker                 if ((strcmp((const char *) entry->key,
323*6777b538SAndroid Build Coastguard Worker                             (const char *) key) == 0) &&
324*6777b538SAndroid Build Coastguard Worker                     (xmlFastStrEqual(entry->key2, key2)) &&
325*6777b538SAndroid Build Coastguard Worker                     (xmlFastStrEqual(entry->key3, key3))) {
326*6777b538SAndroid Build Coastguard Worker                     found = 1;
327*6777b538SAndroid Build Coastguard Worker                     break;
328*6777b538SAndroid Build Coastguard Worker                 }
329*6777b538SAndroid Build Coastguard Worker             }
330*6777b538SAndroid Build Coastguard Worker 
331*6777b538SAndroid Build Coastguard Worker             displ++;
332*6777b538SAndroid Build Coastguard Worker             pos++;
333*6777b538SAndroid Build Coastguard Worker             entry++;
334*6777b538SAndroid Build Coastguard Worker             if ((pos & mask) == 0)
335*6777b538SAndroid Build Coastguard Worker                 entry = hash->table;
336*6777b538SAndroid Build Coastguard Worker         } while ((entry->hashValue != 0) &&
337*6777b538SAndroid Build Coastguard Worker                  (((pos - entry->hashValue) & mask) >= displ));
338*6777b538SAndroid Build Coastguard Worker     }
339*6777b538SAndroid Build Coastguard Worker 
340*6777b538SAndroid Build Coastguard Worker     *pfound = found;
341*6777b538SAndroid Build Coastguard Worker     return(entry);
342*6777b538SAndroid Build Coastguard Worker }
343*6777b538SAndroid Build Coastguard Worker 
344*6777b538SAndroid Build Coastguard Worker /**
345*6777b538SAndroid Build Coastguard Worker  * xmlHashGrow:
346*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
347*6777b538SAndroid Build Coastguard Worker  * @size: new size of the hash table
348*6777b538SAndroid Build Coastguard Worker  *
349*6777b538SAndroid Build Coastguard Worker  * Resize the hash table.
350*6777b538SAndroid Build Coastguard Worker  *
351*6777b538SAndroid Build Coastguard Worker  * Returns 0 in case of success, -1 if a memory allocation failed.
352*6777b538SAndroid Build Coastguard Worker  */
353*6777b538SAndroid Build Coastguard Worker static int
xmlHashGrow(xmlHashTablePtr hash,unsigned size)354*6777b538SAndroid Build Coastguard Worker xmlHashGrow(xmlHashTablePtr hash, unsigned size) {
355*6777b538SAndroid Build Coastguard Worker     const xmlHashEntry *oldentry, *oldend, *end;
356*6777b538SAndroid Build Coastguard Worker     xmlHashEntry *table;
357*6777b538SAndroid Build Coastguard Worker     unsigned oldsize, i;
358*6777b538SAndroid Build Coastguard Worker 
359*6777b538SAndroid Build Coastguard Worker     /* Add 0 to avoid spurious -Wtype-limits warning on 64-bit GCC */
360*6777b538SAndroid Build Coastguard Worker     if ((size_t) size + 0 > SIZE_MAX / sizeof(table[0]))
361*6777b538SAndroid Build Coastguard Worker         return(-1);
362*6777b538SAndroid Build Coastguard Worker     table = xmlMalloc(size * sizeof(table[0]));
363*6777b538SAndroid Build Coastguard Worker     if (table == NULL)
364*6777b538SAndroid Build Coastguard Worker         return(-1);
365*6777b538SAndroid Build Coastguard Worker     memset(table, 0, size * sizeof(table[0]));
366*6777b538SAndroid Build Coastguard Worker 
367*6777b538SAndroid Build Coastguard Worker     oldsize = hash->size;
368*6777b538SAndroid Build Coastguard Worker     if (oldsize == 0)
369*6777b538SAndroid Build Coastguard Worker         goto done;
370*6777b538SAndroid Build Coastguard Worker 
371*6777b538SAndroid Build Coastguard Worker     oldend = &hash->table[oldsize];
372*6777b538SAndroid Build Coastguard Worker     end = &table[size];
373*6777b538SAndroid Build Coastguard Worker 
374*6777b538SAndroid Build Coastguard Worker     /*
375*6777b538SAndroid Build Coastguard Worker      * Robin Hood sorting order is maintained if we
376*6777b538SAndroid Build Coastguard Worker      *
377*6777b538SAndroid Build Coastguard Worker      * - compute hash indices with modulo
378*6777b538SAndroid Build Coastguard Worker      * - resize by an integer factor
379*6777b538SAndroid Build Coastguard Worker      * - start to copy from the beginning of a probe sequence
380*6777b538SAndroid Build Coastguard Worker      */
381*6777b538SAndroid Build Coastguard Worker     oldentry = hash->table;
382*6777b538SAndroid Build Coastguard Worker     while (oldentry->hashValue != 0) {
383*6777b538SAndroid Build Coastguard Worker         if (++oldentry >= oldend)
384*6777b538SAndroid Build Coastguard Worker             oldentry = hash->table;
385*6777b538SAndroid Build Coastguard Worker     }
386*6777b538SAndroid Build Coastguard Worker 
387*6777b538SAndroid Build Coastguard Worker     for (i = 0; i < oldsize; i++) {
388*6777b538SAndroid Build Coastguard Worker         if (oldentry->hashValue != 0) {
389*6777b538SAndroid Build Coastguard Worker             xmlHashEntry *entry = &table[oldentry->hashValue & (size - 1)];
390*6777b538SAndroid Build Coastguard Worker 
391*6777b538SAndroid Build Coastguard Worker             while (entry->hashValue != 0) {
392*6777b538SAndroid Build Coastguard Worker                 if (++entry >= end)
393*6777b538SAndroid Build Coastguard Worker                     entry = table;
394*6777b538SAndroid Build Coastguard Worker             }
395*6777b538SAndroid Build Coastguard Worker             *entry = *oldentry;
396*6777b538SAndroid Build Coastguard Worker         }
397*6777b538SAndroid Build Coastguard Worker 
398*6777b538SAndroid Build Coastguard Worker         if (++oldentry >= oldend)
399*6777b538SAndroid Build Coastguard Worker             oldentry = hash->table;
400*6777b538SAndroid Build Coastguard Worker     }
401*6777b538SAndroid Build Coastguard Worker 
402*6777b538SAndroid Build Coastguard Worker     xmlFree(hash->table);
403*6777b538SAndroid Build Coastguard Worker 
404*6777b538SAndroid Build Coastguard Worker done:
405*6777b538SAndroid Build Coastguard Worker     hash->table = table;
406*6777b538SAndroid Build Coastguard Worker     hash->size = size;
407*6777b538SAndroid Build Coastguard Worker 
408*6777b538SAndroid Build Coastguard Worker     return(0);
409*6777b538SAndroid Build Coastguard Worker }
410*6777b538SAndroid Build Coastguard Worker 
411*6777b538SAndroid Build Coastguard Worker /**
412*6777b538SAndroid Build Coastguard Worker  * xmlHashUpdateInternal:
413*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
414*6777b538SAndroid Build Coastguard Worker  * @key: first string key
415*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
416*6777b538SAndroid Build Coastguard Worker  * @key3: third string key
417*6777b538SAndroid Build Coastguard Worker  * @payload: pointer to the payload
418*6777b538SAndroid Build Coastguard Worker  * @dealloc: deallocator function for replaced item or NULL
419*6777b538SAndroid Build Coastguard Worker  * @update: whether existing entries should be updated
420*6777b538SAndroid Build Coastguard Worker  *
421*6777b538SAndroid Build Coastguard Worker  * Internal function to add or update hash entries.
422*6777b538SAndroid Build Coastguard Worker  */
423*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
424*6777b538SAndroid Build Coastguard Worker static int
xmlHashUpdateInternal(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,const xmlChar * key3,void * payload,xmlHashDeallocator dealloc,int update)425*6777b538SAndroid Build Coastguard Worker xmlHashUpdateInternal(xmlHashTablePtr hash, const xmlChar *key,
426*6777b538SAndroid Build Coastguard Worker                       const xmlChar *key2, const xmlChar *key3,
427*6777b538SAndroid Build Coastguard Worker                       void *payload, xmlHashDeallocator dealloc, int update) {
428*6777b538SAndroid Build Coastguard Worker     xmlChar *copy, *copy2, *copy3;
429*6777b538SAndroid Build Coastguard Worker     xmlHashEntry *entry = NULL;
430*6777b538SAndroid Build Coastguard Worker     size_t lengths[3];
431*6777b538SAndroid Build Coastguard Worker     unsigned hashValue;
432*6777b538SAndroid Build Coastguard Worker     int found = 0;
433*6777b538SAndroid Build Coastguard Worker 
434*6777b538SAndroid Build Coastguard Worker     if ((hash == NULL) || (key == NULL))
435*6777b538SAndroid Build Coastguard Worker         return(-1);
436*6777b538SAndroid Build Coastguard Worker 
437*6777b538SAndroid Build Coastguard Worker     /*
438*6777b538SAndroid Build Coastguard Worker      * Check for an existing entry
439*6777b538SAndroid Build Coastguard Worker      */
440*6777b538SAndroid Build Coastguard Worker     hashValue = xmlHashValue(hash->randomSeed, key, key2, key3, lengths);
441*6777b538SAndroid Build Coastguard Worker     if (hash->size > 0)
442*6777b538SAndroid Build Coastguard Worker         entry = xmlHashFindEntry(hash, key, key2, key3, hashValue, &found);
443*6777b538SAndroid Build Coastguard Worker     if (found) {
444*6777b538SAndroid Build Coastguard Worker         if (update) {
445*6777b538SAndroid Build Coastguard Worker             if (dealloc)
446*6777b538SAndroid Build Coastguard Worker                 dealloc(entry->payload, entry->key);
447*6777b538SAndroid Build Coastguard Worker             entry->payload = payload;
448*6777b538SAndroid Build Coastguard Worker         }
449*6777b538SAndroid Build Coastguard Worker 
450*6777b538SAndroid Build Coastguard Worker         return(0);
451*6777b538SAndroid Build Coastguard Worker     }
452*6777b538SAndroid Build Coastguard Worker 
453*6777b538SAndroid Build Coastguard Worker     /*
454*6777b538SAndroid Build Coastguard Worker      * Grow the hash table if needed
455*6777b538SAndroid Build Coastguard Worker      */
456*6777b538SAndroid Build Coastguard Worker     if (hash->nbElems + 1 > hash->size / MAX_FILL_DENOM * MAX_FILL_NUM) {
457*6777b538SAndroid Build Coastguard Worker         unsigned newSize, mask, displ, pos;
458*6777b538SAndroid Build Coastguard Worker 
459*6777b538SAndroid Build Coastguard Worker         if (hash->size == 0) {
460*6777b538SAndroid Build Coastguard Worker             newSize = MIN_HASH_SIZE;
461*6777b538SAndroid Build Coastguard Worker         } else {
462*6777b538SAndroid Build Coastguard Worker             /* This guarantees that nbElems < INT_MAX */
463*6777b538SAndroid Build Coastguard Worker             if (hash->size >= MAX_HASH_SIZE)
464*6777b538SAndroid Build Coastguard Worker                 return(-1);
465*6777b538SAndroid Build Coastguard Worker             newSize = hash->size * 2;
466*6777b538SAndroid Build Coastguard Worker         }
467*6777b538SAndroid Build Coastguard Worker         if (xmlHashGrow(hash, newSize) != 0)
468*6777b538SAndroid Build Coastguard Worker             return(-1);
469*6777b538SAndroid Build Coastguard Worker 
470*6777b538SAndroid Build Coastguard Worker         /*
471*6777b538SAndroid Build Coastguard Worker          * Find new entry
472*6777b538SAndroid Build Coastguard Worker          */
473*6777b538SAndroid Build Coastguard Worker         mask = hash->size - 1;
474*6777b538SAndroid Build Coastguard Worker         displ = 0;
475*6777b538SAndroid Build Coastguard Worker         pos = hashValue & mask;
476*6777b538SAndroid Build Coastguard Worker         entry = &hash->table[pos];
477*6777b538SAndroid Build Coastguard Worker 
478*6777b538SAndroid Build Coastguard Worker         if (entry->hashValue != 0) {
479*6777b538SAndroid Build Coastguard Worker             do {
480*6777b538SAndroid Build Coastguard Worker                 displ++;
481*6777b538SAndroid Build Coastguard Worker                 pos++;
482*6777b538SAndroid Build Coastguard Worker                 entry++;
483*6777b538SAndroid Build Coastguard Worker                 if ((pos & mask) == 0)
484*6777b538SAndroid Build Coastguard Worker                     entry = hash->table;
485*6777b538SAndroid Build Coastguard Worker             } while ((entry->hashValue != 0) &&
486*6777b538SAndroid Build Coastguard Worker                      ((pos - entry->hashValue) & mask) >= displ);
487*6777b538SAndroid Build Coastguard Worker         }
488*6777b538SAndroid Build Coastguard Worker     }
489*6777b538SAndroid Build Coastguard Worker 
490*6777b538SAndroid Build Coastguard Worker     /*
491*6777b538SAndroid Build Coastguard Worker      * Copy keys
492*6777b538SAndroid Build Coastguard Worker      */
493*6777b538SAndroid Build Coastguard Worker     if (hash->dict != NULL) {
494*6777b538SAndroid Build Coastguard Worker         if (xmlDictOwns(hash->dict, key)) {
495*6777b538SAndroid Build Coastguard Worker             copy = (xmlChar *) key;
496*6777b538SAndroid Build Coastguard Worker         } else {
497*6777b538SAndroid Build Coastguard Worker             copy = (xmlChar *) xmlDictLookup(hash->dict, key, -1);
498*6777b538SAndroid Build Coastguard Worker             if (copy == NULL)
499*6777b538SAndroid Build Coastguard Worker                 return(-1);
500*6777b538SAndroid Build Coastguard Worker         }
501*6777b538SAndroid Build Coastguard Worker 
502*6777b538SAndroid Build Coastguard Worker         if ((key2 == NULL) || (xmlDictOwns(hash->dict, key2))) {
503*6777b538SAndroid Build Coastguard Worker             copy2 = (xmlChar *) key2;
504*6777b538SAndroid Build Coastguard Worker         } else {
505*6777b538SAndroid Build Coastguard Worker             copy2 = (xmlChar *) xmlDictLookup(hash->dict, key2, -1);
506*6777b538SAndroid Build Coastguard Worker             if (copy2 == NULL)
507*6777b538SAndroid Build Coastguard Worker                 return(-1);
508*6777b538SAndroid Build Coastguard Worker         }
509*6777b538SAndroid Build Coastguard Worker         if ((key3 == NULL) || (xmlDictOwns(hash->dict, key3))) {
510*6777b538SAndroid Build Coastguard Worker             copy3 = (xmlChar *) key3;
511*6777b538SAndroid Build Coastguard Worker         } else {
512*6777b538SAndroid Build Coastguard Worker             copy3 = (xmlChar *) xmlDictLookup(hash->dict, key3, -1);
513*6777b538SAndroid Build Coastguard Worker             if (copy3 == NULL)
514*6777b538SAndroid Build Coastguard Worker                 return(-1);
515*6777b538SAndroid Build Coastguard Worker         }
516*6777b538SAndroid Build Coastguard Worker     } else {
517*6777b538SAndroid Build Coastguard Worker         copy = xmlMalloc(lengths[0] + 1);
518*6777b538SAndroid Build Coastguard Worker         if (copy == NULL)
519*6777b538SAndroid Build Coastguard Worker             return(-1);
520*6777b538SAndroid Build Coastguard Worker         memcpy(copy, key, lengths[0] + 1);
521*6777b538SAndroid Build Coastguard Worker 
522*6777b538SAndroid Build Coastguard Worker         if (key2 != NULL) {
523*6777b538SAndroid Build Coastguard Worker             copy2 = xmlMalloc(lengths[1] + 1);
524*6777b538SAndroid Build Coastguard Worker             if (copy2 == NULL) {
525*6777b538SAndroid Build Coastguard Worker                 xmlFree(copy);
526*6777b538SAndroid Build Coastguard Worker                 return(-1);
527*6777b538SAndroid Build Coastguard Worker             }
528*6777b538SAndroid Build Coastguard Worker             memcpy(copy2, key2, lengths[1] + 1);
529*6777b538SAndroid Build Coastguard Worker         } else {
530*6777b538SAndroid Build Coastguard Worker             copy2 = NULL;
531*6777b538SAndroid Build Coastguard Worker         }
532*6777b538SAndroid Build Coastguard Worker 
533*6777b538SAndroid Build Coastguard Worker         if (key3 != NULL) {
534*6777b538SAndroid Build Coastguard Worker             copy3 = xmlMalloc(lengths[2] + 1);
535*6777b538SAndroid Build Coastguard Worker             if (copy3 == NULL) {
536*6777b538SAndroid Build Coastguard Worker                 xmlFree(copy);
537*6777b538SAndroid Build Coastguard Worker                 xmlFree(copy2);
538*6777b538SAndroid Build Coastguard Worker                 return(-1);
539*6777b538SAndroid Build Coastguard Worker             }
540*6777b538SAndroid Build Coastguard Worker             memcpy(copy3, key3, lengths[2] + 1);
541*6777b538SAndroid Build Coastguard Worker         } else {
542*6777b538SAndroid Build Coastguard Worker             copy3 = NULL;
543*6777b538SAndroid Build Coastguard Worker         }
544*6777b538SAndroid Build Coastguard Worker     }
545*6777b538SAndroid Build Coastguard Worker 
546*6777b538SAndroid Build Coastguard Worker     /*
547*6777b538SAndroid Build Coastguard Worker      * Shift the remainder of the probe sequence to the right
548*6777b538SAndroid Build Coastguard Worker      */
549*6777b538SAndroid Build Coastguard Worker     if (entry->hashValue != 0) {
550*6777b538SAndroid Build Coastguard Worker         const xmlHashEntry *end = &hash->table[hash->size];
551*6777b538SAndroid Build Coastguard Worker         const xmlHashEntry *cur = entry;
552*6777b538SAndroid Build Coastguard Worker 
553*6777b538SAndroid Build Coastguard Worker         do {
554*6777b538SAndroid Build Coastguard Worker             cur++;
555*6777b538SAndroid Build Coastguard Worker             if (cur >= end)
556*6777b538SAndroid Build Coastguard Worker                 cur = hash->table;
557*6777b538SAndroid Build Coastguard Worker         } while (cur->hashValue != 0);
558*6777b538SAndroid Build Coastguard Worker 
559*6777b538SAndroid Build Coastguard Worker         if (cur < entry) {
560*6777b538SAndroid Build Coastguard Worker             /*
561*6777b538SAndroid Build Coastguard Worker              * If we traversed the end of the buffer, handle the part
562*6777b538SAndroid Build Coastguard Worker              * at the start of the buffer.
563*6777b538SAndroid Build Coastguard Worker              */
564*6777b538SAndroid Build Coastguard Worker             memmove(&hash->table[1], hash->table,
565*6777b538SAndroid Build Coastguard Worker                     (char *) cur - (char *) hash->table);
566*6777b538SAndroid Build Coastguard Worker             cur = end - 1;
567*6777b538SAndroid Build Coastguard Worker             hash->table[0] = *cur;
568*6777b538SAndroid Build Coastguard Worker         }
569*6777b538SAndroid Build Coastguard Worker 
570*6777b538SAndroid Build Coastguard Worker         memmove(&entry[1], entry, (char *) cur - (char *) entry);
571*6777b538SAndroid Build Coastguard Worker     }
572*6777b538SAndroid Build Coastguard Worker 
573*6777b538SAndroid Build Coastguard Worker     /*
574*6777b538SAndroid Build Coastguard Worker      * Populate entry
575*6777b538SAndroid Build Coastguard Worker      */
576*6777b538SAndroid Build Coastguard Worker     entry->key = copy;
577*6777b538SAndroid Build Coastguard Worker     entry->key2 = copy2;
578*6777b538SAndroid Build Coastguard Worker     entry->key3 = copy3;
579*6777b538SAndroid Build Coastguard Worker     entry->payload = payload;
580*6777b538SAndroid Build Coastguard Worker     /* OR with MAX_HASH_SIZE to make sure that the value is non-zero */
581*6777b538SAndroid Build Coastguard Worker     entry->hashValue = hashValue | MAX_HASH_SIZE;
582*6777b538SAndroid Build Coastguard Worker 
583*6777b538SAndroid Build Coastguard Worker     hash->nbElems++;
584*6777b538SAndroid Build Coastguard Worker 
585*6777b538SAndroid Build Coastguard Worker     return(1);
586*6777b538SAndroid Build Coastguard Worker }
587*6777b538SAndroid Build Coastguard Worker 
588*6777b538SAndroid Build Coastguard Worker /**
589*6777b538SAndroid Build Coastguard Worker  * xmlHashDefaultDeallocator:
590*6777b538SAndroid Build Coastguard Worker  * @entry: hash table entry
591*6777b538SAndroid Build Coastguard Worker  * @key: the entry's string key
592*6777b538SAndroid Build Coastguard Worker  *
593*6777b538SAndroid Build Coastguard Worker  * Free a hash table entry with xmlFree.
594*6777b538SAndroid Build Coastguard Worker  */
595*6777b538SAndroid Build Coastguard Worker void
xmlHashDefaultDeallocator(void * entry,const xmlChar * key ATTRIBUTE_UNUSED)596*6777b538SAndroid Build Coastguard Worker xmlHashDefaultDeallocator(void *entry, const xmlChar *key ATTRIBUTE_UNUSED) {
597*6777b538SAndroid Build Coastguard Worker     xmlFree(entry);
598*6777b538SAndroid Build Coastguard Worker }
599*6777b538SAndroid Build Coastguard Worker 
600*6777b538SAndroid Build Coastguard Worker /**
601*6777b538SAndroid Build Coastguard Worker  * xmlHashAdd:
602*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
603*6777b538SAndroid Build Coastguard Worker  * @key: string key
604*6777b538SAndroid Build Coastguard Worker  * @payload: pointer to the payload
605*6777b538SAndroid Build Coastguard Worker  *
606*6777b538SAndroid Build Coastguard Worker  * Add a hash table entry. If an entry with this key already exists,
607*6777b538SAndroid Build Coastguard Worker  * payload will not be updated and 0 is returned. This return value
608*6777b538SAndroid Build Coastguard Worker  * can't be distinguished from out-of-memory errors, so this function
609*6777b538SAndroid Build Coastguard Worker  * should be used with care.
610*6777b538SAndroid Build Coastguard Worker  *
611*6777b538SAndroid Build Coastguard Worker  * Returns 1 on success, 0 if an entry exists and -1 in case of error.
612*6777b538SAndroid Build Coastguard Worker  */
613*6777b538SAndroid Build Coastguard Worker int
xmlHashAdd(xmlHashTablePtr hash,const xmlChar * key,void * payload)614*6777b538SAndroid Build Coastguard Worker xmlHashAdd(xmlHashTablePtr hash, const xmlChar *key, void *payload) {
615*6777b538SAndroid Build Coastguard Worker     return(xmlHashUpdateInternal(hash, key, NULL, NULL, payload, NULL, 0));
616*6777b538SAndroid Build Coastguard Worker }
617*6777b538SAndroid Build Coastguard Worker 
618*6777b538SAndroid Build Coastguard Worker /**
619*6777b538SAndroid Build Coastguard Worker  * xmlHashAdd2:
620*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
621*6777b538SAndroid Build Coastguard Worker  * @key: first string key
622*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
623*6777b538SAndroid Build Coastguard Worker  * @payload: pointer to the payload
624*6777b538SAndroid Build Coastguard Worker  *
625*6777b538SAndroid Build Coastguard Worker  * Add a hash table entry with two strings as key.
626*6777b538SAndroid Build Coastguard Worker  *
627*6777b538SAndroid Build Coastguard Worker  * See xmlHashAdd.
628*6777b538SAndroid Build Coastguard Worker  */
629*6777b538SAndroid Build Coastguard Worker int
xmlHashAdd2(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,void * payload)630*6777b538SAndroid Build Coastguard Worker xmlHashAdd2(xmlHashTablePtr hash, const xmlChar *key,
631*6777b538SAndroid Build Coastguard Worker                  const xmlChar *key2, void *payload) {
632*6777b538SAndroid Build Coastguard Worker     return(xmlHashUpdateInternal(hash, key, key2, NULL, payload, NULL, 0));
633*6777b538SAndroid Build Coastguard Worker }
634*6777b538SAndroid Build Coastguard Worker 
635*6777b538SAndroid Build Coastguard Worker /**
636*6777b538SAndroid Build Coastguard Worker  * xmlHashAdd3:
637*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
638*6777b538SAndroid Build Coastguard Worker  * @key: first string key
639*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
640*6777b538SAndroid Build Coastguard Worker  * @key3: third string key
641*6777b538SAndroid Build Coastguard Worker  * @payload: pointer to the payload
642*6777b538SAndroid Build Coastguard Worker  *
643*6777b538SAndroid Build Coastguard Worker  * Add a hash table entry with three strings as key.
644*6777b538SAndroid Build Coastguard Worker  *
645*6777b538SAndroid Build Coastguard Worker  * See xmlHashAdd.
646*6777b538SAndroid Build Coastguard Worker  */
647*6777b538SAndroid Build Coastguard Worker int
xmlHashAdd3(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,const xmlChar * key3,void * payload)648*6777b538SAndroid Build Coastguard Worker xmlHashAdd3(xmlHashTablePtr hash, const xmlChar *key,
649*6777b538SAndroid Build Coastguard Worker                  const xmlChar *key2, const xmlChar *key3,
650*6777b538SAndroid Build Coastguard Worker                  void *payload) {
651*6777b538SAndroid Build Coastguard Worker     return(xmlHashUpdateInternal(hash, key, key2, key3, payload, NULL, 0));
652*6777b538SAndroid Build Coastguard Worker }
653*6777b538SAndroid Build Coastguard Worker 
654*6777b538SAndroid Build Coastguard Worker /**
655*6777b538SAndroid Build Coastguard Worker  * xmlHashAddEntry:
656*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
657*6777b538SAndroid Build Coastguard Worker  * @key: string key
658*6777b538SAndroid Build Coastguard Worker  * @payload: pointer to the payload
659*6777b538SAndroid Build Coastguard Worker  *
660*6777b538SAndroid Build Coastguard Worker  * Add a hash table entry. If an entry with this key already exists,
661*6777b538SAndroid Build Coastguard Worker  * payload will not be updated and -1 is returned. This return value
662*6777b538SAndroid Build Coastguard Worker  * can't be distinguished from out-of-memory errors, so this function
663*6777b538SAndroid Build Coastguard Worker  * should be used with care.
664*6777b538SAndroid Build Coastguard Worker  *
665*6777b538SAndroid Build Coastguard Worker  * NOTE: This function doesn't allow to distinguish malloc failures from
666*6777b538SAndroid Build Coastguard Worker  *       existing entries. Use xmlHashAdd instead.
667*6777b538SAndroid Build Coastguard Worker  *
668*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success and -1 in case of error.
669*6777b538SAndroid Build Coastguard Worker  */
670*6777b538SAndroid Build Coastguard Worker int
xmlHashAddEntry(xmlHashTablePtr hash,const xmlChar * key,void * payload)671*6777b538SAndroid Build Coastguard Worker xmlHashAddEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload) {
672*6777b538SAndroid Build Coastguard Worker     int res = xmlHashUpdateInternal(hash, key, NULL, NULL, payload, NULL, 0);
673*6777b538SAndroid Build Coastguard Worker 
674*6777b538SAndroid Build Coastguard Worker     if (res == 0)
675*6777b538SAndroid Build Coastguard Worker         res = -1;
676*6777b538SAndroid Build Coastguard Worker     else if (res == 1)
677*6777b538SAndroid Build Coastguard Worker         res = 0;
678*6777b538SAndroid Build Coastguard Worker 
679*6777b538SAndroid Build Coastguard Worker     return(res);
680*6777b538SAndroid Build Coastguard Worker }
681*6777b538SAndroid Build Coastguard Worker 
682*6777b538SAndroid Build Coastguard Worker /**
683*6777b538SAndroid Build Coastguard Worker  * xmlHashAddEntry2:
684*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
685*6777b538SAndroid Build Coastguard Worker  * @key: first string key
686*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
687*6777b538SAndroid Build Coastguard Worker  * @payload: pointer to the payload
688*6777b538SAndroid Build Coastguard Worker  *
689*6777b538SAndroid Build Coastguard Worker  * Add a hash table entry with two strings as key.
690*6777b538SAndroid Build Coastguard Worker  *
691*6777b538SAndroid Build Coastguard Worker  * See xmlHashAddEntry.
692*6777b538SAndroid Build Coastguard Worker  *
693*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success and -1 in case of error.
694*6777b538SAndroid Build Coastguard Worker  */
695*6777b538SAndroid Build Coastguard Worker int
xmlHashAddEntry2(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,void * payload)696*6777b538SAndroid Build Coastguard Worker xmlHashAddEntry2(xmlHashTablePtr hash, const xmlChar *key,
697*6777b538SAndroid Build Coastguard Worker                  const xmlChar *key2, void *payload) {
698*6777b538SAndroid Build Coastguard Worker     int res = xmlHashUpdateInternal(hash, key, key2, NULL, payload, NULL, 0);
699*6777b538SAndroid Build Coastguard Worker 
700*6777b538SAndroid Build Coastguard Worker     if (res == 0)
701*6777b538SAndroid Build Coastguard Worker         res = -1;
702*6777b538SAndroid Build Coastguard Worker     else if (res == 1)
703*6777b538SAndroid Build Coastguard Worker         res = 0;
704*6777b538SAndroid Build Coastguard Worker 
705*6777b538SAndroid Build Coastguard Worker     return(res);
706*6777b538SAndroid Build Coastguard Worker }
707*6777b538SAndroid Build Coastguard Worker 
708*6777b538SAndroid Build Coastguard Worker /**
709*6777b538SAndroid Build Coastguard Worker  * xmlHashAddEntry3:
710*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
711*6777b538SAndroid Build Coastguard Worker  * @key: first string key
712*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
713*6777b538SAndroid Build Coastguard Worker  * @key3: third string key
714*6777b538SAndroid Build Coastguard Worker  * @payload: pointer to the payload
715*6777b538SAndroid Build Coastguard Worker  *
716*6777b538SAndroid Build Coastguard Worker  * Add a hash table entry with three strings as key.
717*6777b538SAndroid Build Coastguard Worker  *
718*6777b538SAndroid Build Coastguard Worker  * See xmlHashAddEntry.
719*6777b538SAndroid Build Coastguard Worker  *
720*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success and -1 in case of error.
721*6777b538SAndroid Build Coastguard Worker  */
722*6777b538SAndroid Build Coastguard Worker int
xmlHashAddEntry3(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,const xmlChar * key3,void * payload)723*6777b538SAndroid Build Coastguard Worker xmlHashAddEntry3(xmlHashTablePtr hash, const xmlChar *key,
724*6777b538SAndroid Build Coastguard Worker                  const xmlChar *key2, const xmlChar *key3,
725*6777b538SAndroid Build Coastguard Worker                  void *payload) {
726*6777b538SAndroid Build Coastguard Worker     int res = xmlHashUpdateInternal(hash, key, key2, key3, payload, NULL, 0);
727*6777b538SAndroid Build Coastguard Worker 
728*6777b538SAndroid Build Coastguard Worker     if (res == 0)
729*6777b538SAndroid Build Coastguard Worker         res = -1;
730*6777b538SAndroid Build Coastguard Worker     else if (res == 1)
731*6777b538SAndroid Build Coastguard Worker         res = 0;
732*6777b538SAndroid Build Coastguard Worker 
733*6777b538SAndroid Build Coastguard Worker     return(res);
734*6777b538SAndroid Build Coastguard Worker }
735*6777b538SAndroid Build Coastguard Worker 
736*6777b538SAndroid Build Coastguard Worker /**
737*6777b538SAndroid Build Coastguard Worker  * xmlHashUpdateEntry:
738*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
739*6777b538SAndroid Build Coastguard Worker  * @key: string key
740*6777b538SAndroid Build Coastguard Worker  * @payload: pointer to the payload
741*6777b538SAndroid Build Coastguard Worker  * @dealloc: deallocator function for replaced item or NULL
742*6777b538SAndroid Build Coastguard Worker  *
743*6777b538SAndroid Build Coastguard Worker  * Add a hash table entry. If an entry with this key already exists,
744*6777b538SAndroid Build Coastguard Worker  * the old payload will be freed and updated with the new value.
745*6777b538SAndroid Build Coastguard Worker  *
746*6777b538SAndroid Build Coastguard Worker  * Returns 0 in case of success, -1 if a memory allocation failed.
747*6777b538SAndroid Build Coastguard Worker  */
748*6777b538SAndroid Build Coastguard Worker int
xmlHashUpdateEntry(xmlHashTablePtr hash,const xmlChar * key,void * payload,xmlHashDeallocator dealloc)749*6777b538SAndroid Build Coastguard Worker xmlHashUpdateEntry(xmlHashTablePtr hash, const xmlChar *key,
750*6777b538SAndroid Build Coastguard Worker                    void *payload, xmlHashDeallocator dealloc) {
751*6777b538SAndroid Build Coastguard Worker     int res = xmlHashUpdateInternal(hash, key, NULL, NULL, payload,
752*6777b538SAndroid Build Coastguard Worker                                     dealloc, 1);
753*6777b538SAndroid Build Coastguard Worker 
754*6777b538SAndroid Build Coastguard Worker     if (res == 1)
755*6777b538SAndroid Build Coastguard Worker         res = 0;
756*6777b538SAndroid Build Coastguard Worker 
757*6777b538SAndroid Build Coastguard Worker     return(res);
758*6777b538SAndroid Build Coastguard Worker }
759*6777b538SAndroid Build Coastguard Worker 
760*6777b538SAndroid Build Coastguard Worker /**
761*6777b538SAndroid Build Coastguard Worker  * xmlHashUpdateEntry2:
762*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
763*6777b538SAndroid Build Coastguard Worker  * @key: first string key
764*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
765*6777b538SAndroid Build Coastguard Worker  * @payload: pointer to the payload
766*6777b538SAndroid Build Coastguard Worker  * @dealloc: deallocator function for replaced item or NULL
767*6777b538SAndroid Build Coastguard Worker  *
768*6777b538SAndroid Build Coastguard Worker  * Add a hash table entry with two strings as key.
769*6777b538SAndroid Build Coastguard Worker  *
770*6777b538SAndroid Build Coastguard Worker  * See xmlHashUpdateEntry.
771*6777b538SAndroid Build Coastguard Worker  *
772*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success and -1 in case of error.
773*6777b538SAndroid Build Coastguard Worker  */
774*6777b538SAndroid Build Coastguard Worker int
xmlHashUpdateEntry2(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,void * payload,xmlHashDeallocator dealloc)775*6777b538SAndroid Build Coastguard Worker xmlHashUpdateEntry2(xmlHashTablePtr hash, const xmlChar *key,
776*6777b538SAndroid Build Coastguard Worker                    const xmlChar *key2, void *payload,
777*6777b538SAndroid Build Coastguard Worker                    xmlHashDeallocator dealloc) {
778*6777b538SAndroid Build Coastguard Worker     int res = xmlHashUpdateInternal(hash, key, key2, NULL, payload,
779*6777b538SAndroid Build Coastguard Worker                                     dealloc, 1);
780*6777b538SAndroid Build Coastguard Worker 
781*6777b538SAndroid Build Coastguard Worker     if (res == 1)
782*6777b538SAndroid Build Coastguard Worker         res = 0;
783*6777b538SAndroid Build Coastguard Worker 
784*6777b538SAndroid Build Coastguard Worker     return(res);
785*6777b538SAndroid Build Coastguard Worker }
786*6777b538SAndroid Build Coastguard Worker 
787*6777b538SAndroid Build Coastguard Worker /**
788*6777b538SAndroid Build Coastguard Worker  * xmlHashUpdateEntry3:
789*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
790*6777b538SAndroid Build Coastguard Worker  * @key: first string key
791*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
792*6777b538SAndroid Build Coastguard Worker  * @key3: third string key
793*6777b538SAndroid Build Coastguard Worker  * @payload: pointer to the payload
794*6777b538SAndroid Build Coastguard Worker  * @dealloc: deallocator function for replaced item or NULL
795*6777b538SAndroid Build Coastguard Worker  *
796*6777b538SAndroid Build Coastguard Worker  * Add a hash table entry with three strings as key.
797*6777b538SAndroid Build Coastguard Worker  *
798*6777b538SAndroid Build Coastguard Worker  * See xmlHashUpdateEntry.
799*6777b538SAndroid Build Coastguard Worker  *
800*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success and -1 in case of error.
801*6777b538SAndroid Build Coastguard Worker  */
802*6777b538SAndroid Build Coastguard Worker int
xmlHashUpdateEntry3(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,const xmlChar * key3,void * payload,xmlHashDeallocator dealloc)803*6777b538SAndroid Build Coastguard Worker xmlHashUpdateEntry3(xmlHashTablePtr hash, const xmlChar *key,
804*6777b538SAndroid Build Coastguard Worker                    const xmlChar *key2, const xmlChar *key3,
805*6777b538SAndroid Build Coastguard Worker                    void *payload, xmlHashDeallocator dealloc) {
806*6777b538SAndroid Build Coastguard Worker     int res = xmlHashUpdateInternal(hash, key, key2, key3, payload,
807*6777b538SAndroid Build Coastguard Worker                                     dealloc, 1);
808*6777b538SAndroid Build Coastguard Worker 
809*6777b538SAndroid Build Coastguard Worker     if (res == 1)
810*6777b538SAndroid Build Coastguard Worker         res = 0;
811*6777b538SAndroid Build Coastguard Worker 
812*6777b538SAndroid Build Coastguard Worker     return(res);
813*6777b538SAndroid Build Coastguard Worker }
814*6777b538SAndroid Build Coastguard Worker 
815*6777b538SAndroid Build Coastguard Worker /**
816*6777b538SAndroid Build Coastguard Worker  * xmlHashLookup:
817*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
818*6777b538SAndroid Build Coastguard Worker  * @key: string key
819*6777b538SAndroid Build Coastguard Worker  *
820*6777b538SAndroid Build Coastguard Worker  * Find the entry specified by @key.
821*6777b538SAndroid Build Coastguard Worker  *
822*6777b538SAndroid Build Coastguard Worker  * Returns a pointer to the payload or NULL if no entry was found.
823*6777b538SAndroid Build Coastguard Worker  */
824*6777b538SAndroid Build Coastguard Worker void *
xmlHashLookup(xmlHashTablePtr hash,const xmlChar * key)825*6777b538SAndroid Build Coastguard Worker xmlHashLookup(xmlHashTablePtr hash, const xmlChar *key) {
826*6777b538SAndroid Build Coastguard Worker     return(xmlHashLookup3(hash, key, NULL, NULL));
827*6777b538SAndroid Build Coastguard Worker }
828*6777b538SAndroid Build Coastguard Worker 
829*6777b538SAndroid Build Coastguard Worker /**
830*6777b538SAndroid Build Coastguard Worker  * xmlHashLookup2:
831*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
832*6777b538SAndroid Build Coastguard Worker  * @key: first string key
833*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
834*6777b538SAndroid Build Coastguard Worker  *
835*6777b538SAndroid Build Coastguard Worker  * Find the payload specified by the (@key, @key2) tuple.
836*6777b538SAndroid Build Coastguard Worker  *
837*6777b538SAndroid Build Coastguard Worker  * Returns a pointer to the payload or NULL if no entry was found.
838*6777b538SAndroid Build Coastguard Worker  */
839*6777b538SAndroid Build Coastguard Worker void *
xmlHashLookup2(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2)840*6777b538SAndroid Build Coastguard Worker xmlHashLookup2(xmlHashTablePtr hash, const xmlChar *key,
841*6777b538SAndroid Build Coastguard Worker               const xmlChar *key2) {
842*6777b538SAndroid Build Coastguard Worker     return(xmlHashLookup3(hash, key, key2, NULL));
843*6777b538SAndroid Build Coastguard Worker }
844*6777b538SAndroid Build Coastguard Worker 
845*6777b538SAndroid Build Coastguard Worker /**
846*6777b538SAndroid Build Coastguard Worker  * xmlHashQLookup:
847*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
848*6777b538SAndroid Build Coastguard Worker  * @prefix: prefix of the string key
849*6777b538SAndroid Build Coastguard Worker  * @name: local name of the string key
850*6777b538SAndroid Build Coastguard Worker  *
851*6777b538SAndroid Build Coastguard Worker  * Find the payload specified by the QName @prefix:@name or @name.
852*6777b538SAndroid Build Coastguard Worker  *
853*6777b538SAndroid Build Coastguard Worker  * Returns a pointer to the payload or NULL if no entry was found.
854*6777b538SAndroid Build Coastguard Worker  */
855*6777b538SAndroid Build Coastguard Worker void *
xmlHashQLookup(xmlHashTablePtr hash,const xmlChar * prefix,const xmlChar * name)856*6777b538SAndroid Build Coastguard Worker xmlHashQLookup(xmlHashTablePtr hash, const xmlChar *prefix,
857*6777b538SAndroid Build Coastguard Worker                const xmlChar *name) {
858*6777b538SAndroid Build Coastguard Worker     return(xmlHashQLookup3(hash, prefix, name, NULL, NULL, NULL, NULL));
859*6777b538SAndroid Build Coastguard Worker }
860*6777b538SAndroid Build Coastguard Worker 
861*6777b538SAndroid Build Coastguard Worker /**
862*6777b538SAndroid Build Coastguard Worker  * xmlHashQLookup2:
863*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
864*6777b538SAndroid Build Coastguard Worker  * @prefix: first prefix
865*6777b538SAndroid Build Coastguard Worker  * @name: first local name
866*6777b538SAndroid Build Coastguard Worker  * @prefix2: second prefix
867*6777b538SAndroid Build Coastguard Worker  * @name2: second local name
868*6777b538SAndroid Build Coastguard Worker  *
869*6777b538SAndroid Build Coastguard Worker  * Find the payload specified by the QNames tuple.
870*6777b538SAndroid Build Coastguard Worker  *
871*6777b538SAndroid Build Coastguard Worker  * Returns a pointer to the payload or NULL if no entry was found.
872*6777b538SAndroid Build Coastguard Worker  */
873*6777b538SAndroid Build Coastguard Worker void *
xmlHashQLookup2(xmlHashTablePtr hash,const xmlChar * prefix,const xmlChar * name,const xmlChar * prefix2,const xmlChar * name2)874*6777b538SAndroid Build Coastguard Worker xmlHashQLookup2(xmlHashTablePtr hash, const xmlChar *prefix,
875*6777b538SAndroid Build Coastguard Worker                 const xmlChar *name, const xmlChar *prefix2,
876*6777b538SAndroid Build Coastguard Worker                 const xmlChar *name2) {
877*6777b538SAndroid Build Coastguard Worker     return(xmlHashQLookup3(hash, prefix, name, prefix2, name2, NULL, NULL));
878*6777b538SAndroid Build Coastguard Worker }
879*6777b538SAndroid Build Coastguard Worker 
880*6777b538SAndroid Build Coastguard Worker /**
881*6777b538SAndroid Build Coastguard Worker  * xmlHashLookup3:
882*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
883*6777b538SAndroid Build Coastguard Worker  * @key: first string key
884*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
885*6777b538SAndroid Build Coastguard Worker  * @key3: third string key
886*6777b538SAndroid Build Coastguard Worker  *
887*6777b538SAndroid Build Coastguard Worker  * Find the payload specified by the (@key, @key2, @key3) tuple.
888*6777b538SAndroid Build Coastguard Worker  *
889*6777b538SAndroid Build Coastguard Worker  * Returns a pointer to the payload or NULL if no entry was found.
890*6777b538SAndroid Build Coastguard Worker  */
891*6777b538SAndroid Build Coastguard Worker void *
xmlHashLookup3(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,const xmlChar * key3)892*6777b538SAndroid Build Coastguard Worker xmlHashLookup3(xmlHashTablePtr hash, const xmlChar *key,
893*6777b538SAndroid Build Coastguard Worker                const xmlChar *key2, const xmlChar *key3) {
894*6777b538SAndroid Build Coastguard Worker     const xmlHashEntry *entry;
895*6777b538SAndroid Build Coastguard Worker     unsigned hashValue;
896*6777b538SAndroid Build Coastguard Worker     int found;
897*6777b538SAndroid Build Coastguard Worker 
898*6777b538SAndroid Build Coastguard Worker     if ((hash == NULL) || (hash->size == 0) || (key == NULL))
899*6777b538SAndroid Build Coastguard Worker         return(NULL);
900*6777b538SAndroid Build Coastguard Worker     hashValue = xmlHashValue(hash->randomSeed, key, key2, key3, NULL);
901*6777b538SAndroid Build Coastguard Worker     entry = xmlHashFindEntry(hash, key, key2, key3, hashValue, &found);
902*6777b538SAndroid Build Coastguard Worker     if (found)
903*6777b538SAndroid Build Coastguard Worker         return(entry->payload);
904*6777b538SAndroid Build Coastguard Worker     return(NULL);
905*6777b538SAndroid Build Coastguard Worker }
906*6777b538SAndroid Build Coastguard Worker 
907*6777b538SAndroid Build Coastguard Worker /**
908*6777b538SAndroid Build Coastguard Worker  * xmlHashQLookup3:
909*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
910*6777b538SAndroid Build Coastguard Worker  * @prefix: first prefix
911*6777b538SAndroid Build Coastguard Worker  * @name: first local name
912*6777b538SAndroid Build Coastguard Worker  * @prefix2: second prefix
913*6777b538SAndroid Build Coastguard Worker  * @name2: second local name
914*6777b538SAndroid Build Coastguard Worker  * @prefix3: third prefix
915*6777b538SAndroid Build Coastguard Worker  * @name3: third local name
916*6777b538SAndroid Build Coastguard Worker  *
917*6777b538SAndroid Build Coastguard Worker  * Find the payload specified by the QNames tuple.
918*6777b538SAndroid Build Coastguard Worker  *
919*6777b538SAndroid Build Coastguard Worker  * Returns a pointer to the payload or NULL if no entry was found.
920*6777b538SAndroid Build Coastguard Worker  */
921*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
922*6777b538SAndroid Build Coastguard Worker void *
xmlHashQLookup3(xmlHashTablePtr hash,const xmlChar * prefix,const xmlChar * name,const xmlChar * prefix2,const xmlChar * name2,const xmlChar * prefix3,const xmlChar * name3)923*6777b538SAndroid Build Coastguard Worker xmlHashQLookup3(xmlHashTablePtr hash,
924*6777b538SAndroid Build Coastguard Worker                 const xmlChar *prefix, const xmlChar *name,
925*6777b538SAndroid Build Coastguard Worker                 const xmlChar *prefix2, const xmlChar *name2,
926*6777b538SAndroid Build Coastguard Worker                 const xmlChar *prefix3, const xmlChar *name3) {
927*6777b538SAndroid Build Coastguard Worker     const xmlHashEntry *entry;
928*6777b538SAndroid Build Coastguard Worker     unsigned hashValue, mask, pos, displ;
929*6777b538SAndroid Build Coastguard Worker 
930*6777b538SAndroid Build Coastguard Worker     if ((hash == NULL) || (hash->size == 0) || (name == NULL))
931*6777b538SAndroid Build Coastguard Worker         return(NULL);
932*6777b538SAndroid Build Coastguard Worker 
933*6777b538SAndroid Build Coastguard Worker     hashValue = xmlHashQNameValue(hash->randomSeed, prefix, name, prefix2,
934*6777b538SAndroid Build Coastguard Worker                                   name2, prefix3, name3);
935*6777b538SAndroid Build Coastguard Worker     mask = hash->size - 1;
936*6777b538SAndroid Build Coastguard Worker     pos = hashValue & mask;
937*6777b538SAndroid Build Coastguard Worker     entry = &hash->table[pos];
938*6777b538SAndroid Build Coastguard Worker 
939*6777b538SAndroid Build Coastguard Worker     if (entry->hashValue != 0) {
940*6777b538SAndroid Build Coastguard Worker         displ = 0;
941*6777b538SAndroid Build Coastguard Worker         hashValue |= MAX_HASH_SIZE;
942*6777b538SAndroid Build Coastguard Worker 
943*6777b538SAndroid Build Coastguard Worker         do {
944*6777b538SAndroid Build Coastguard Worker             if ((hashValue == entry->hashValue) &&
945*6777b538SAndroid Build Coastguard Worker                 (xmlStrQEqual(prefix, name, entry->key)) &&
946*6777b538SAndroid Build Coastguard Worker                 (xmlStrQEqual(prefix2, name2, entry->key2)) &&
947*6777b538SAndroid Build Coastguard Worker                 (xmlStrQEqual(prefix3, name3, entry->key3)))
948*6777b538SAndroid Build Coastguard Worker                 return(entry->payload);
949*6777b538SAndroid Build Coastguard Worker 
950*6777b538SAndroid Build Coastguard Worker             displ++;
951*6777b538SAndroid Build Coastguard Worker             pos++;
952*6777b538SAndroid Build Coastguard Worker             entry++;
953*6777b538SAndroid Build Coastguard Worker             if ((pos & mask) == 0)
954*6777b538SAndroid Build Coastguard Worker                 entry = hash->table;
955*6777b538SAndroid Build Coastguard Worker         } while ((entry->hashValue != 0) &&
956*6777b538SAndroid Build Coastguard Worker                  (((pos - entry->hashValue) & mask) >= displ));
957*6777b538SAndroid Build Coastguard Worker     }
958*6777b538SAndroid Build Coastguard Worker 
959*6777b538SAndroid Build Coastguard Worker     return(NULL);
960*6777b538SAndroid Build Coastguard Worker }
961*6777b538SAndroid Build Coastguard Worker 
962*6777b538SAndroid Build Coastguard Worker typedef struct {
963*6777b538SAndroid Build Coastguard Worker     xmlHashScanner scan;
964*6777b538SAndroid Build Coastguard Worker     void *data;
965*6777b538SAndroid Build Coastguard Worker } stubData;
966*6777b538SAndroid Build Coastguard Worker 
967*6777b538SAndroid Build Coastguard Worker static void
stubHashScannerFull(void * payload,void * data,const xmlChar * key,const xmlChar * key2 ATTRIBUTE_UNUSED,const xmlChar * key3 ATTRIBUTE_UNUSED)968*6777b538SAndroid Build Coastguard Worker stubHashScannerFull(void *payload, void *data, const xmlChar *key,
969*6777b538SAndroid Build Coastguard Worker                     const xmlChar *key2 ATTRIBUTE_UNUSED,
970*6777b538SAndroid Build Coastguard Worker                     const xmlChar *key3 ATTRIBUTE_UNUSED) {
971*6777b538SAndroid Build Coastguard Worker     stubData *sdata = (stubData *) data;
972*6777b538SAndroid Build Coastguard Worker     sdata->scan(payload, sdata->data, key);
973*6777b538SAndroid Build Coastguard Worker }
974*6777b538SAndroid Build Coastguard Worker 
975*6777b538SAndroid Build Coastguard Worker /**
976*6777b538SAndroid Build Coastguard Worker  * xmlHashScan:
977*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
978*6777b538SAndroid Build Coastguard Worker  * @scan: scanner function for items in the hash
979*6777b538SAndroid Build Coastguard Worker  * @data: extra data passed to @scan
980*6777b538SAndroid Build Coastguard Worker  *
981*6777b538SAndroid Build Coastguard Worker  * Scan the hash @table and apply @scan to each value.
982*6777b538SAndroid Build Coastguard Worker  */
983*6777b538SAndroid Build Coastguard Worker void
xmlHashScan(xmlHashTablePtr hash,xmlHashScanner scan,void * data)984*6777b538SAndroid Build Coastguard Worker xmlHashScan(xmlHashTablePtr hash, xmlHashScanner scan, void *data) {
985*6777b538SAndroid Build Coastguard Worker     stubData sdata;
986*6777b538SAndroid Build Coastguard Worker     sdata.data = data;
987*6777b538SAndroid Build Coastguard Worker     sdata.scan = scan;
988*6777b538SAndroid Build Coastguard Worker     xmlHashScanFull(hash, stubHashScannerFull, &sdata);
989*6777b538SAndroid Build Coastguard Worker }
990*6777b538SAndroid Build Coastguard Worker 
991*6777b538SAndroid Build Coastguard Worker /**
992*6777b538SAndroid Build Coastguard Worker  * xmlHashScanFull:
993*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
994*6777b538SAndroid Build Coastguard Worker  * @scan: scanner function for items in the hash
995*6777b538SAndroid Build Coastguard Worker  * @data: extra data passed to @scan
996*6777b538SAndroid Build Coastguard Worker  *
997*6777b538SAndroid Build Coastguard Worker  * Scan the hash @table and apply @scan to each value.
998*6777b538SAndroid Build Coastguard Worker  */
999*6777b538SAndroid Build Coastguard Worker void
xmlHashScanFull(xmlHashTablePtr hash,xmlHashScannerFull scan,void * data)1000*6777b538SAndroid Build Coastguard Worker xmlHashScanFull(xmlHashTablePtr hash, xmlHashScannerFull scan, void *data) {
1001*6777b538SAndroid Build Coastguard Worker     const xmlHashEntry *entry, *end;
1002*6777b538SAndroid Build Coastguard Worker     xmlHashEntry old;
1003*6777b538SAndroid Build Coastguard Worker     unsigned i;
1004*6777b538SAndroid Build Coastguard Worker 
1005*6777b538SAndroid Build Coastguard Worker     if ((hash == NULL) || (hash->size == 0) || (scan == NULL))
1006*6777b538SAndroid Build Coastguard Worker         return;
1007*6777b538SAndroid Build Coastguard Worker 
1008*6777b538SAndroid Build Coastguard Worker     /*
1009*6777b538SAndroid Build Coastguard Worker      * We must handle the case that a scanned entry is removed when executing
1010*6777b538SAndroid Build Coastguard Worker      * the callback (xmlCleanSpecialAttr and possibly other places).
1011*6777b538SAndroid Build Coastguard Worker      *
1012*6777b538SAndroid Build Coastguard Worker      * Find the start of a probe sequence to avoid scanning entries twice if
1013*6777b538SAndroid Build Coastguard Worker      * a deletion happens.
1014*6777b538SAndroid Build Coastguard Worker      */
1015*6777b538SAndroid Build Coastguard Worker     entry = hash->table;
1016*6777b538SAndroid Build Coastguard Worker     end = &hash->table[hash->size];
1017*6777b538SAndroid Build Coastguard Worker     while (entry->hashValue != 0) {
1018*6777b538SAndroid Build Coastguard Worker         if (++entry >= end)
1019*6777b538SAndroid Build Coastguard Worker             entry = hash->table;
1020*6777b538SAndroid Build Coastguard Worker     }
1021*6777b538SAndroid Build Coastguard Worker 
1022*6777b538SAndroid Build Coastguard Worker     for (i = 0; i < hash->size; i++) {
1023*6777b538SAndroid Build Coastguard Worker         if ((entry->hashValue != 0) && (entry->payload != NULL)) {
1024*6777b538SAndroid Build Coastguard Worker             /*
1025*6777b538SAndroid Build Coastguard Worker              * Make sure to rescan after a possible deletion.
1026*6777b538SAndroid Build Coastguard Worker              */
1027*6777b538SAndroid Build Coastguard Worker             do {
1028*6777b538SAndroid Build Coastguard Worker                 old = *entry;
1029*6777b538SAndroid Build Coastguard Worker                 scan(entry->payload, data, entry->key, entry->key2, entry->key3);
1030*6777b538SAndroid Build Coastguard Worker             } while ((entry->hashValue != 0) &&
1031*6777b538SAndroid Build Coastguard Worker                      (entry->payload != NULL) &&
1032*6777b538SAndroid Build Coastguard Worker                      ((entry->key != old.key) ||
1033*6777b538SAndroid Build Coastguard Worker                       (entry->key2 != old.key2) ||
1034*6777b538SAndroid Build Coastguard Worker                       (entry->key3 != old.key3)));
1035*6777b538SAndroid Build Coastguard Worker         }
1036*6777b538SAndroid Build Coastguard Worker         if (++entry >= end)
1037*6777b538SAndroid Build Coastguard Worker             entry = hash->table;
1038*6777b538SAndroid Build Coastguard Worker     }
1039*6777b538SAndroid Build Coastguard Worker }
1040*6777b538SAndroid Build Coastguard Worker 
1041*6777b538SAndroid Build Coastguard Worker /**
1042*6777b538SAndroid Build Coastguard Worker  * xmlHashScan3:
1043*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
1044*6777b538SAndroid Build Coastguard Worker  * @key: first string key or NULL
1045*6777b538SAndroid Build Coastguard Worker  * @key2: second string key or NULL
1046*6777b538SAndroid Build Coastguard Worker  * @key3: third string key or NULL
1047*6777b538SAndroid Build Coastguard Worker  * @scan: scanner function for items in the hash
1048*6777b538SAndroid Build Coastguard Worker  * @data: extra data passed to @scan
1049*6777b538SAndroid Build Coastguard Worker  *
1050*6777b538SAndroid Build Coastguard Worker  * Scan the hash @table and apply @scan to each value matching
1051*6777b538SAndroid Build Coastguard Worker  * (@key, @key2, @key3) tuple. If one of the keys is null,
1052*6777b538SAndroid Build Coastguard Worker  * the comparison is considered to match.
1053*6777b538SAndroid Build Coastguard Worker  */
1054*6777b538SAndroid Build Coastguard Worker void
xmlHashScan3(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,const xmlChar * key3,xmlHashScanner scan,void * data)1055*6777b538SAndroid Build Coastguard Worker xmlHashScan3(xmlHashTablePtr hash, const xmlChar *key,
1056*6777b538SAndroid Build Coastguard Worker              const xmlChar *key2, const xmlChar *key3,
1057*6777b538SAndroid Build Coastguard Worker              xmlHashScanner scan, void *data) {
1058*6777b538SAndroid Build Coastguard Worker     stubData sdata;
1059*6777b538SAndroid Build Coastguard Worker     sdata.data = data;
1060*6777b538SAndroid Build Coastguard Worker     sdata.scan = scan;
1061*6777b538SAndroid Build Coastguard Worker     xmlHashScanFull3(hash, key, key2, key3, stubHashScannerFull, &sdata);
1062*6777b538SAndroid Build Coastguard Worker }
1063*6777b538SAndroid Build Coastguard Worker 
1064*6777b538SAndroid Build Coastguard Worker /**
1065*6777b538SAndroid Build Coastguard Worker  * xmlHashScanFull3:
1066*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
1067*6777b538SAndroid Build Coastguard Worker  * @key: first string key or NULL
1068*6777b538SAndroid Build Coastguard Worker  * @key2: second string key or NULL
1069*6777b538SAndroid Build Coastguard Worker  * @key3: third string key or NULL
1070*6777b538SAndroid Build Coastguard Worker  * @scan: scanner function for items in the hash
1071*6777b538SAndroid Build Coastguard Worker  * @data: extra data passed to @scan
1072*6777b538SAndroid Build Coastguard Worker  *
1073*6777b538SAndroid Build Coastguard Worker  * Scan the hash @table and apply @scan to each value matching
1074*6777b538SAndroid Build Coastguard Worker  * (@key, @key2, @key3) tuple. If one of the keys is null,
1075*6777b538SAndroid Build Coastguard Worker  * the comparison is considered to match.
1076*6777b538SAndroid Build Coastguard Worker  */
1077*6777b538SAndroid Build Coastguard Worker void
xmlHashScanFull3(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,const xmlChar * key3,xmlHashScannerFull scan,void * data)1078*6777b538SAndroid Build Coastguard Worker xmlHashScanFull3(xmlHashTablePtr hash, const xmlChar *key,
1079*6777b538SAndroid Build Coastguard Worker                  const xmlChar *key2, const xmlChar *key3,
1080*6777b538SAndroid Build Coastguard Worker                  xmlHashScannerFull scan, void *data) {
1081*6777b538SAndroid Build Coastguard Worker     const xmlHashEntry *entry, *end;
1082*6777b538SAndroid Build Coastguard Worker     xmlHashEntry old;
1083*6777b538SAndroid Build Coastguard Worker     unsigned i;
1084*6777b538SAndroid Build Coastguard Worker 
1085*6777b538SAndroid Build Coastguard Worker     if ((hash == NULL) || (hash->size == 0) || (scan == NULL))
1086*6777b538SAndroid Build Coastguard Worker         return;
1087*6777b538SAndroid Build Coastguard Worker 
1088*6777b538SAndroid Build Coastguard Worker     /*
1089*6777b538SAndroid Build Coastguard Worker      * We must handle the case that a scanned entry is removed when executing
1090*6777b538SAndroid Build Coastguard Worker      * the callback (xmlCleanSpecialAttr and possibly other places).
1091*6777b538SAndroid Build Coastguard Worker      *
1092*6777b538SAndroid Build Coastguard Worker      * Find the start of a probe sequence to avoid scanning entries twice if
1093*6777b538SAndroid Build Coastguard Worker      * a deletion happens.
1094*6777b538SAndroid Build Coastguard Worker      */
1095*6777b538SAndroid Build Coastguard Worker     entry = hash->table;
1096*6777b538SAndroid Build Coastguard Worker     end = &hash->table[hash->size];
1097*6777b538SAndroid Build Coastguard Worker     while (entry->hashValue != 0) {
1098*6777b538SAndroid Build Coastguard Worker         if (++entry >= end)
1099*6777b538SAndroid Build Coastguard Worker             entry = hash->table;
1100*6777b538SAndroid Build Coastguard Worker     }
1101*6777b538SAndroid Build Coastguard Worker 
1102*6777b538SAndroid Build Coastguard Worker     for (i = 0; i < hash->size; i++) {
1103*6777b538SAndroid Build Coastguard Worker         if ((entry->hashValue != 0) && (entry->payload != NULL)) {
1104*6777b538SAndroid Build Coastguard Worker             /*
1105*6777b538SAndroid Build Coastguard Worker              * Make sure to rescan after a possible deletion.
1106*6777b538SAndroid Build Coastguard Worker              */
1107*6777b538SAndroid Build Coastguard Worker             do {
1108*6777b538SAndroid Build Coastguard Worker                 if (((key != NULL) && (strcmp((const char *) key,
1109*6777b538SAndroid Build Coastguard Worker                                               (const char *) entry->key) != 0)) ||
1110*6777b538SAndroid Build Coastguard Worker                     ((key2 != NULL) && (!xmlFastStrEqual(key2, entry->key2))) ||
1111*6777b538SAndroid Build Coastguard Worker                     ((key3 != NULL) && (!xmlFastStrEqual(key3, entry->key3))))
1112*6777b538SAndroid Build Coastguard Worker                     break;
1113*6777b538SAndroid Build Coastguard Worker                 old = *entry;
1114*6777b538SAndroid Build Coastguard Worker                 scan(entry->payload, data, entry->key, entry->key2, entry->key3);
1115*6777b538SAndroid Build Coastguard Worker             } while ((entry->hashValue != 0) &&
1116*6777b538SAndroid Build Coastguard Worker                      (entry->payload != NULL) &&
1117*6777b538SAndroid Build Coastguard Worker                      ((entry->key != old.key) ||
1118*6777b538SAndroid Build Coastguard Worker                       (entry->key2 != old.key2) ||
1119*6777b538SAndroid Build Coastguard Worker                       (entry->key3 != old.key3)));
1120*6777b538SAndroid Build Coastguard Worker         }
1121*6777b538SAndroid Build Coastguard Worker         if (++entry >= end)
1122*6777b538SAndroid Build Coastguard Worker             entry = hash->table;
1123*6777b538SAndroid Build Coastguard Worker     }
1124*6777b538SAndroid Build Coastguard Worker }
1125*6777b538SAndroid Build Coastguard Worker 
1126*6777b538SAndroid Build Coastguard Worker /*
1127*6777b538SAndroid Build Coastguard Worker  * xmlHashCopySafe:
1128*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
1129*6777b538SAndroid Build Coastguard Worker  * @copyFunc: copier function for items in the hash
1130*6777b538SAndroid Build Coastguard Worker  * @deallocFunc: deallocation function in case of errors
1131*6777b538SAndroid Build Coastguard Worker  *
1132*6777b538SAndroid Build Coastguard Worker  * Copy the hash table using @copyFunc to copy payloads.
1133*6777b538SAndroid Build Coastguard Worker  *
1134*6777b538SAndroid Build Coastguard Worker  * Returns the new table or NULL if a memory allocation failed.
1135*6777b538SAndroid Build Coastguard Worker  */
1136*6777b538SAndroid Build Coastguard Worker xmlHashTablePtr
xmlHashCopySafe(xmlHashTablePtr hash,xmlHashCopier copyFunc,xmlHashDeallocator deallocFunc)1137*6777b538SAndroid Build Coastguard Worker xmlHashCopySafe(xmlHashTablePtr hash, xmlHashCopier copyFunc,
1138*6777b538SAndroid Build Coastguard Worker                 xmlHashDeallocator deallocFunc) {
1139*6777b538SAndroid Build Coastguard Worker     const xmlHashEntry *entry, *end;
1140*6777b538SAndroid Build Coastguard Worker     xmlHashTablePtr ret;
1141*6777b538SAndroid Build Coastguard Worker 
1142*6777b538SAndroid Build Coastguard Worker     if ((hash == NULL) || (copyFunc == NULL))
1143*6777b538SAndroid Build Coastguard Worker         return(NULL);
1144*6777b538SAndroid Build Coastguard Worker 
1145*6777b538SAndroid Build Coastguard Worker     ret = xmlHashCreate(hash->size);
1146*6777b538SAndroid Build Coastguard Worker     if (ret == NULL)
1147*6777b538SAndroid Build Coastguard Worker         return(NULL);
1148*6777b538SAndroid Build Coastguard Worker 
1149*6777b538SAndroid Build Coastguard Worker     if (hash->size == 0)
1150*6777b538SAndroid Build Coastguard Worker         return(ret);
1151*6777b538SAndroid Build Coastguard Worker 
1152*6777b538SAndroid Build Coastguard Worker     end = &hash->table[hash->size];
1153*6777b538SAndroid Build Coastguard Worker 
1154*6777b538SAndroid Build Coastguard Worker     for (entry = hash->table; entry < end; entry++) {
1155*6777b538SAndroid Build Coastguard Worker         if (entry->hashValue != 0) {
1156*6777b538SAndroid Build Coastguard Worker             void *copy;
1157*6777b538SAndroid Build Coastguard Worker 
1158*6777b538SAndroid Build Coastguard Worker             copy = copyFunc(entry->payload, entry->key);
1159*6777b538SAndroid Build Coastguard Worker             if (copy == NULL)
1160*6777b538SAndroid Build Coastguard Worker                 goto error;
1161*6777b538SAndroid Build Coastguard Worker             if (xmlHashAdd3(ret, entry->key, entry->key2, entry->key3,
1162*6777b538SAndroid Build Coastguard Worker                             copy) <= 0) {
1163*6777b538SAndroid Build Coastguard Worker                 if (deallocFunc != NULL)
1164*6777b538SAndroid Build Coastguard Worker                     deallocFunc(copy, entry->key);
1165*6777b538SAndroid Build Coastguard Worker                 goto error;
1166*6777b538SAndroid Build Coastguard Worker             }
1167*6777b538SAndroid Build Coastguard Worker         }
1168*6777b538SAndroid Build Coastguard Worker     }
1169*6777b538SAndroid Build Coastguard Worker 
1170*6777b538SAndroid Build Coastguard Worker     return(ret);
1171*6777b538SAndroid Build Coastguard Worker 
1172*6777b538SAndroid Build Coastguard Worker error:
1173*6777b538SAndroid Build Coastguard Worker     xmlHashFree(ret, deallocFunc);
1174*6777b538SAndroid Build Coastguard Worker     return(NULL);
1175*6777b538SAndroid Build Coastguard Worker }
1176*6777b538SAndroid Build Coastguard Worker 
1177*6777b538SAndroid Build Coastguard Worker /*
1178*6777b538SAndroid Build Coastguard Worker  * xmlHashCopy:
1179*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
1180*6777b538SAndroid Build Coastguard Worker  * @copy: copier function for items in the hash
1181*6777b538SAndroid Build Coastguard Worker  *
1182*6777b538SAndroid Build Coastguard Worker  * DEPRECATED: Leaks memory in error case.
1183*6777b538SAndroid Build Coastguard Worker  *
1184*6777b538SAndroid Build Coastguard Worker  * Copy the hash table using @copy to copy payloads.
1185*6777b538SAndroid Build Coastguard Worker  *
1186*6777b538SAndroid Build Coastguard Worker  * Returns the new table or NULL if a memory allocation failed.
1187*6777b538SAndroid Build Coastguard Worker  */
1188*6777b538SAndroid Build Coastguard Worker xmlHashTablePtr
xmlHashCopy(xmlHashTablePtr hash,xmlHashCopier copy)1189*6777b538SAndroid Build Coastguard Worker xmlHashCopy(xmlHashTablePtr hash, xmlHashCopier copy) {
1190*6777b538SAndroid Build Coastguard Worker     return(xmlHashCopySafe(hash, copy, NULL));
1191*6777b538SAndroid Build Coastguard Worker }
1192*6777b538SAndroid Build Coastguard Worker 
1193*6777b538SAndroid Build Coastguard Worker /**
1194*6777b538SAndroid Build Coastguard Worker  * xmlHashSize:
1195*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
1196*6777b538SAndroid Build Coastguard Worker  *
1197*6777b538SAndroid Build Coastguard Worker  * Query the number of elements in the hash table.
1198*6777b538SAndroid Build Coastguard Worker  *
1199*6777b538SAndroid Build Coastguard Worker  * Returns the number of elements in the hash table or
1200*6777b538SAndroid Build Coastguard Worker  * -1 in case of error.
1201*6777b538SAndroid Build Coastguard Worker  */
1202*6777b538SAndroid Build Coastguard Worker int
xmlHashSize(xmlHashTablePtr hash)1203*6777b538SAndroid Build Coastguard Worker xmlHashSize(xmlHashTablePtr hash) {
1204*6777b538SAndroid Build Coastguard Worker     if (hash == NULL)
1205*6777b538SAndroid Build Coastguard Worker         return(-1);
1206*6777b538SAndroid Build Coastguard Worker     return(hash->nbElems);
1207*6777b538SAndroid Build Coastguard Worker }
1208*6777b538SAndroid Build Coastguard Worker 
1209*6777b538SAndroid Build Coastguard Worker /**
1210*6777b538SAndroid Build Coastguard Worker  * xmlHashRemoveEntry:
1211*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
1212*6777b538SAndroid Build Coastguard Worker  * @key: string key
1213*6777b538SAndroid Build Coastguard Worker  * @dealloc: deallocator function for removed item or NULL
1214*6777b538SAndroid Build Coastguard Worker  *
1215*6777b538SAndroid Build Coastguard Worker  * Find the entry specified by the @key and remove it from the hash table.
1216*6777b538SAndroid Build Coastguard Worker  * Payload will be freed with @dealloc.
1217*6777b538SAndroid Build Coastguard Worker  *
1218*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success and -1 if no entry was found.
1219*6777b538SAndroid Build Coastguard Worker  */
xmlHashRemoveEntry(xmlHashTablePtr hash,const xmlChar * key,xmlHashDeallocator dealloc)1220*6777b538SAndroid Build Coastguard Worker int xmlHashRemoveEntry(xmlHashTablePtr hash, const xmlChar *key,
1221*6777b538SAndroid Build Coastguard Worker                        xmlHashDeallocator dealloc) {
1222*6777b538SAndroid Build Coastguard Worker     return(xmlHashRemoveEntry3(hash, key, NULL, NULL, dealloc));
1223*6777b538SAndroid Build Coastguard Worker }
1224*6777b538SAndroid Build Coastguard Worker 
1225*6777b538SAndroid Build Coastguard Worker /**
1226*6777b538SAndroid Build Coastguard Worker  * xmlHashRemoveEntry2:
1227*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
1228*6777b538SAndroid Build Coastguard Worker  * @key: first string key
1229*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
1230*6777b538SAndroid Build Coastguard Worker  * @dealloc: deallocator function for removed item or NULL
1231*6777b538SAndroid Build Coastguard Worker  *
1232*6777b538SAndroid Build Coastguard Worker  * Remove an entry with two strings as key.
1233*6777b538SAndroid Build Coastguard Worker  *
1234*6777b538SAndroid Build Coastguard Worker  * See xmlHashRemoveEntry.
1235*6777b538SAndroid Build Coastguard Worker  *
1236*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success and -1 in case of error.
1237*6777b538SAndroid Build Coastguard Worker  */
1238*6777b538SAndroid Build Coastguard Worker int
xmlHashRemoveEntry2(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,xmlHashDeallocator dealloc)1239*6777b538SAndroid Build Coastguard Worker xmlHashRemoveEntry2(xmlHashTablePtr hash, const xmlChar *key,
1240*6777b538SAndroid Build Coastguard Worker                     const xmlChar *key2, xmlHashDeallocator dealloc) {
1241*6777b538SAndroid Build Coastguard Worker     return(xmlHashRemoveEntry3(hash, key, key2, NULL, dealloc));
1242*6777b538SAndroid Build Coastguard Worker }
1243*6777b538SAndroid Build Coastguard Worker 
1244*6777b538SAndroid Build Coastguard Worker /**
1245*6777b538SAndroid Build Coastguard Worker  * xmlHashRemoveEntry3:
1246*6777b538SAndroid Build Coastguard Worker  * @hash: hash table
1247*6777b538SAndroid Build Coastguard Worker  * @key: first string key
1248*6777b538SAndroid Build Coastguard Worker  * @key2: second string key
1249*6777b538SAndroid Build Coastguard Worker  * @key3: third string key
1250*6777b538SAndroid Build Coastguard Worker  * @dealloc: deallocator function for removed item or NULL
1251*6777b538SAndroid Build Coastguard Worker  *
1252*6777b538SAndroid Build Coastguard Worker  * Remove an entry with three strings as key.
1253*6777b538SAndroid Build Coastguard Worker  *
1254*6777b538SAndroid Build Coastguard Worker  * See xmlHashRemoveEntry.
1255*6777b538SAndroid Build Coastguard Worker  *
1256*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success and -1 in case of error.
1257*6777b538SAndroid Build Coastguard Worker  */
1258*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE_INTEGER
1259*6777b538SAndroid Build Coastguard Worker int
xmlHashRemoveEntry3(xmlHashTablePtr hash,const xmlChar * key,const xmlChar * key2,const xmlChar * key3,xmlHashDeallocator dealloc)1260*6777b538SAndroid Build Coastguard Worker xmlHashRemoveEntry3(xmlHashTablePtr hash, const xmlChar *key,
1261*6777b538SAndroid Build Coastguard Worker                     const xmlChar *key2, const xmlChar *key3,
1262*6777b538SAndroid Build Coastguard Worker                     xmlHashDeallocator dealloc) {
1263*6777b538SAndroid Build Coastguard Worker     xmlHashEntry *entry, *cur, *next;
1264*6777b538SAndroid Build Coastguard Worker     unsigned hashValue, mask, pos, nextpos;
1265*6777b538SAndroid Build Coastguard Worker     int found;
1266*6777b538SAndroid Build Coastguard Worker 
1267*6777b538SAndroid Build Coastguard Worker     if ((hash == NULL) || (hash->size == 0) || (key == NULL))
1268*6777b538SAndroid Build Coastguard Worker         return(-1);
1269*6777b538SAndroid Build Coastguard Worker 
1270*6777b538SAndroid Build Coastguard Worker     hashValue = xmlHashValue(hash->randomSeed, key, key2, key3, NULL);
1271*6777b538SAndroid Build Coastguard Worker     entry = xmlHashFindEntry(hash, key, key2, key3, hashValue, &found);
1272*6777b538SAndroid Build Coastguard Worker     if (!found)
1273*6777b538SAndroid Build Coastguard Worker         return(-1);
1274*6777b538SAndroid Build Coastguard Worker 
1275*6777b538SAndroid Build Coastguard Worker     if ((dealloc != NULL) && (entry->payload != NULL))
1276*6777b538SAndroid Build Coastguard Worker         dealloc(entry->payload, entry->key);
1277*6777b538SAndroid Build Coastguard Worker     if (hash->dict == NULL) {
1278*6777b538SAndroid Build Coastguard Worker         if (entry->key)
1279*6777b538SAndroid Build Coastguard Worker             xmlFree(entry->key);
1280*6777b538SAndroid Build Coastguard Worker         if (entry->key2)
1281*6777b538SAndroid Build Coastguard Worker             xmlFree(entry->key2);
1282*6777b538SAndroid Build Coastguard Worker         if (entry->key3)
1283*6777b538SAndroid Build Coastguard Worker             xmlFree(entry->key3);
1284*6777b538SAndroid Build Coastguard Worker     }
1285*6777b538SAndroid Build Coastguard Worker 
1286*6777b538SAndroid Build Coastguard Worker     /*
1287*6777b538SAndroid Build Coastguard Worker      * Find end of probe sequence. Entries at their initial probe
1288*6777b538SAndroid Build Coastguard Worker      * position start a new sequence.
1289*6777b538SAndroid Build Coastguard Worker      */
1290*6777b538SAndroid Build Coastguard Worker     mask = hash->size - 1;
1291*6777b538SAndroid Build Coastguard Worker     pos = entry - hash->table;
1292*6777b538SAndroid Build Coastguard Worker     cur = entry;
1293*6777b538SAndroid Build Coastguard Worker 
1294*6777b538SAndroid Build Coastguard Worker     while (1) {
1295*6777b538SAndroid Build Coastguard Worker         nextpos = pos + 1;
1296*6777b538SAndroid Build Coastguard Worker         next = cur + 1;
1297*6777b538SAndroid Build Coastguard Worker         if ((nextpos & mask) == 0)
1298*6777b538SAndroid Build Coastguard Worker             next = hash->table;
1299*6777b538SAndroid Build Coastguard Worker 
1300*6777b538SAndroid Build Coastguard Worker         if ((next->hashValue == 0) ||
1301*6777b538SAndroid Build Coastguard Worker             (((next->hashValue - nextpos) & mask) == 0))
1302*6777b538SAndroid Build Coastguard Worker             break;
1303*6777b538SAndroid Build Coastguard Worker 
1304*6777b538SAndroid Build Coastguard Worker         cur = next;
1305*6777b538SAndroid Build Coastguard Worker         pos = nextpos;
1306*6777b538SAndroid Build Coastguard Worker     }
1307*6777b538SAndroid Build Coastguard Worker 
1308*6777b538SAndroid Build Coastguard Worker     /*
1309*6777b538SAndroid Build Coastguard Worker      * Backward shift
1310*6777b538SAndroid Build Coastguard Worker      */
1311*6777b538SAndroid Build Coastguard Worker     next = entry + 1;
1312*6777b538SAndroid Build Coastguard Worker 
1313*6777b538SAndroid Build Coastguard Worker     if (cur < entry) {
1314*6777b538SAndroid Build Coastguard Worker         xmlHashEntry *end = &hash->table[hash->size];
1315*6777b538SAndroid Build Coastguard Worker 
1316*6777b538SAndroid Build Coastguard Worker         memmove(entry, next, (char *) end - (char *) next);
1317*6777b538SAndroid Build Coastguard Worker         entry = hash->table;
1318*6777b538SAndroid Build Coastguard Worker         end[-1] = *entry;
1319*6777b538SAndroid Build Coastguard Worker         next = entry + 1;
1320*6777b538SAndroid Build Coastguard Worker     }
1321*6777b538SAndroid Build Coastguard Worker 
1322*6777b538SAndroid Build Coastguard Worker     memmove(entry, next, (char *) cur - (char *) entry);
1323*6777b538SAndroid Build Coastguard Worker 
1324*6777b538SAndroid Build Coastguard Worker     /*
1325*6777b538SAndroid Build Coastguard Worker      * Update entry
1326*6777b538SAndroid Build Coastguard Worker      */
1327*6777b538SAndroid Build Coastguard Worker     cur->hashValue = 0;
1328*6777b538SAndroid Build Coastguard Worker 
1329*6777b538SAndroid Build Coastguard Worker     hash->nbElems--;
1330*6777b538SAndroid Build Coastguard Worker 
1331*6777b538SAndroid Build Coastguard Worker     return(0);
1332*6777b538SAndroid Build Coastguard Worker }
1333*6777b538SAndroid Build Coastguard Worker 
1334