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