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