blob: fe1424f29192d15bb8fbe46671102d900b2bb37d [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * hash.c: chained hash tables
3 *
4 * Reference: Your favorite introductory book on algorithms
5 *
Daniel Veillard8973d582012-02-04 19:07:44 +08006 * Copyright (C) 2000,2012 Bjorn Reese and Daniel Veillard.
Owen Taylor3473f882001-02-23 17:55:21 +00007 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
13 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
14 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
15 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
16 *
Bjorn Reese70a9da52001-04-21 16:57:29 +000017 * Author: breese@users.sourceforge.net
Owen Taylor3473f882001-02-23 17:55:21 +000018 */
19
Daniel Veillard34ce8be2002-03-18 19:37:11 +000020#define IN_LIBXML
Bjorn Reese70a9da52001-04-21 16:57:29 +000021#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000022
23#include <string.h>
Daniel Veillard8973d582012-02-04 19:07:44 +080024#ifdef HAVE_STDLIB_H
25#include <stdlib.h>
26#endif
27#ifdef HAVE_TIME_H
28#include <time.h>
29#endif
30
31/*
32 * Following http://www.ocert.org/advisories/ocert-2011-003.html
33 * it seems that having hash randomization might be a good idea
34 * when using XML with untrusted data
35 */
36#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME)
37#define HASH_RANDOMIZATION
38#endif
39
Daniel Veillarde57ec792003-09-10 10:50:59 +000040#include <libxml/parser.h>
Owen Taylor3473f882001-02-23 17:55:21 +000041#include <libxml/hash.h>
42#include <libxml/xmlmemory.h>
Daniel Veillarda10efa82001-04-18 13:09:01 +000043#include <libxml/xmlerror.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000044#include <libxml/globals.h>
Daniel Veillarda10efa82001-04-18 13:09:01 +000045
46#define MAX_HASH_LEN 8
47
48/* #define DEBUG_GROW */
Owen Taylor3473f882001-02-23 17:55:21 +000049
Daniel Veillard8973d582012-02-04 19:07:44 +080050#ifdef HASH_RANDOMIZATION
51static int hash_initialized = 0;
52#endif
53
Owen Taylor3473f882001-02-23 17:55:21 +000054/*
55 * A single entry in the hash table
56 */
57typedef struct _xmlHashEntry xmlHashEntry;
58typedef xmlHashEntry *xmlHashEntryPtr;
59struct _xmlHashEntry {
60 struct _xmlHashEntry *next;
61 xmlChar *name;
62 xmlChar *name2;
63 xmlChar *name3;
64 void *payload;
Daniel Veillardfdc91562002-07-01 21:52:03 +000065 int valid;
Owen Taylor3473f882001-02-23 17:55:21 +000066};
67
68/*
69 * The entire hash table
70 */
71struct _xmlHashTable {
Daniel Veillardfdc91562002-07-01 21:52:03 +000072 struct _xmlHashEntry *table;
Owen Taylor3473f882001-02-23 17:55:21 +000073 int size;
74 int nbElems;
Daniel Veillard316a5c32005-01-23 22:56:39 +000075 xmlDictPtr dict;
Daniel Veillard8973d582012-02-04 19:07:44 +080076#ifdef HASH_RANDOMIZATION
77 int random_seed;
78#endif
Owen Taylor3473f882001-02-23 17:55:21 +000079};
80
81/*
82 * xmlHashComputeKey:
83 * Calculate the hash key
84 */
85static unsigned long
Daniel Veillarda10efa82001-04-18 13:09:01 +000086xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
87 const xmlChar *name2, const xmlChar *name3) {
Owen Taylor3473f882001-02-23 17:55:21 +000088 unsigned long value = 0L;
89 char ch;
90
Daniel Veillard8973d582012-02-04 19:07:44 +080091#ifdef HASH_RANDOMIZATION
92 value = table->random_seed;
93#endif
Daniel Veillarda10efa82001-04-18 13:09:01 +000094 if (name != NULL) {
95 value += 30 * (*name);
96 while ((ch = *name++) != 0) {
Daniel Veillard5f7f9912002-06-17 17:03:00 +000097 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Daniel Veillarda10efa82001-04-18 13:09:01 +000098 }
99 }
100 if (name2 != NULL) {
101 while ((ch = *name2++) != 0) {
Daniel Veillard5f7f9912002-06-17 17:03:00 +0000102 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Daniel Veillarda10efa82001-04-18 13:09:01 +0000103 }
104 }
105 if (name3 != NULL) {
106 while ((ch = *name3++) != 0) {
Daniel Veillard5f7f9912002-06-17 17:03:00 +0000107 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Daniel Veillarda10efa82001-04-18 13:09:01 +0000108 }
Owen Taylor3473f882001-02-23 17:55:21 +0000109 }
110 return (value % table->size);
111}
112
Daniel Veillarde57ec792003-09-10 10:50:59 +0000113static unsigned long
114xmlHashComputeQKey(xmlHashTablePtr table,
Daniel Veillard8e36e6a2003-09-10 10:50:59 +0000115 const xmlChar *prefix, const xmlChar *name,
116 const xmlChar *prefix2, const xmlChar *name2,
117 const xmlChar *prefix3, const xmlChar *name3) {
Daniel Veillarde57ec792003-09-10 10:50:59 +0000118 unsigned long value = 0L;
119 char ch;
120
Daniel Veillard8973d582012-02-04 19:07:44 +0800121#ifdef HASH_RANDOMIZATION
122 value = table->random_seed;
123#endif
Daniel Veillarde57ec792003-09-10 10:50:59 +0000124 if (prefix != NULL)
125 value += 30 * (*prefix);
126 else
127 value += 30 * (*name);
128
129 if (prefix != NULL) {
130 while ((ch = *prefix++) != 0) {
131 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
132 }
133 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
134 }
135 if (name != NULL) {
136 while ((ch = *name++) != 0) {
137 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
138 }
139 }
140 if (prefix2 != NULL) {
141 while ((ch = *prefix2++) != 0) {
142 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
143 }
144 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
145 }
146 if (name2 != NULL) {
147 while ((ch = *name2++) != 0) {
148 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
149 }
150 }
151 if (prefix3 != NULL) {
152 while ((ch = *prefix3++) != 0) {
153 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
154 }
155 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
156 }
157 if (name3 != NULL) {
158 while ((ch = *name3++) != 0) {
159 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
160 }
161 }
162 return (value % table->size);
163}
164
Owen Taylor3473f882001-02-23 17:55:21 +0000165/**
166 * xmlHashCreate:
167 * @size: the size of the hash table
168 *
169 * Create a new xmlHashTablePtr.
170 *
171 * Returns the newly created object, or NULL if an error occured.
172 */
173xmlHashTablePtr
174xmlHashCreate(int size) {
175 xmlHashTablePtr table;
176
177 if (size <= 0)
178 size = 256;
179
180 table = xmlMalloc(sizeof(xmlHashTable));
181 if (table) {
Daniel Veillard316a5c32005-01-23 22:56:39 +0000182 table->dict = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +0000183 table->size = size;
184 table->nbElems = 0;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000185 table->table = xmlMalloc(size * sizeof(xmlHashEntry));
Owen Taylor3473f882001-02-23 17:55:21 +0000186 if (table->table) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000187 memset(table->table, 0, size * sizeof(xmlHashEntry));
Daniel Veillard8973d582012-02-04 19:07:44 +0800188#ifdef HASH_RANDOMIZATION
189 if (!hash_initialized) {
190 srand(time(NULL));
191 hash_initialized = 1;
192 }
193 table->random_seed = rand();
194#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000195 return(table);
196 }
197 xmlFree(table);
198 }
199 return(NULL);
200}
201
202/**
Daniel Veillard316a5c32005-01-23 22:56:39 +0000203 * xmlHashCreateDict:
204 * @size: the size of the hash table
205 * @dict: a dictionary to use for the hash
206 *
207 * Create a new xmlHashTablePtr which will use @dict as the internal dictionary
208 *
209 * Returns the newly created object, or NULL if an error occured.
210 */
211xmlHashTablePtr
212xmlHashCreateDict(int size, xmlDictPtr dict) {
213 xmlHashTablePtr table;
214
215 table = xmlHashCreate(size);
216 if (table != NULL) {
217 table->dict = dict;
218 xmlDictReference(dict);
219 }
220 return(table);
221}
222
223/**
Daniel Veillarda10efa82001-04-18 13:09:01 +0000224 * xmlHashGrow:
225 * @table: the hash table
226 * @size: the new size of the hash table
227 *
228 * resize the hash table
229 *
230 * Returns 0 in case of success, -1 in case of failure
231 */
Daniel Veillarddab4cb32001-04-20 13:03:48 +0000232static int
Daniel Veillarda10efa82001-04-18 13:09:01 +0000233xmlHashGrow(xmlHashTablePtr table, int size) {
234 unsigned long key;
235 int oldsize, i;
236 xmlHashEntryPtr iter, next;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000237 struct _xmlHashEntry *oldtable;
Daniel Veillarda10efa82001-04-18 13:09:01 +0000238#ifdef DEBUG_GROW
239 unsigned long nbElem = 0;
240#endif
241
242 if (table == NULL)
243 return(-1);
244 if (size < 8)
245 return(-1);
246 if (size > 8 * 2048)
247 return(-1);
248
249 oldsize = table->size;
250 oldtable = table->table;
251 if (oldtable == NULL)
252 return(-1);
253
Daniel Veillardfdc91562002-07-01 21:52:03 +0000254 table->table = xmlMalloc(size * sizeof(xmlHashEntry));
Daniel Veillarda10efa82001-04-18 13:09:01 +0000255 if (table->table == NULL) {
256 table->table = oldtable;
257 return(-1);
258 }
Daniel Veillardfdc91562002-07-01 21:52:03 +0000259 memset(table->table, 0, size * sizeof(xmlHashEntry));
Daniel Veillarda10efa82001-04-18 13:09:01 +0000260 table->size = size;
261
Daniel Veillardfdc91562002-07-01 21:52:03 +0000262 /* If the two loops are merged, there would be situations where
263 a new entry needs to allocated and data copied into it from
264 the main table. So instead, we run through the array twice, first
265 copying all the elements in the main array (where we can't get
266 conflicts) and then the rest, so we only free (and don't allocate)
267 */
Daniel Veillarda10efa82001-04-18 13:09:01 +0000268 for (i = 0; i < oldsize; i++) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000269 if (oldtable[i].valid == 0)
270 continue;
271 key = xmlHashComputeKey(table, oldtable[i].name, oldtable[i].name2,
272 oldtable[i].name3);
273 memcpy(&(table->table[key]), &(oldtable[i]), sizeof(xmlHashEntry));
274 table->table[key].next = NULL;
275 }
276
277 for (i = 0; i < oldsize; i++) {
278 iter = oldtable[i].next;
Daniel Veillarda10efa82001-04-18 13:09:01 +0000279 while (iter) {
280 next = iter->next;
281
282 /*
283 * put back the entry in the new table
284 */
285
286 key = xmlHashComputeKey(table, iter->name, iter->name2,
287 iter->name3);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000288 if (table->table[key].valid == 0) {
289 memcpy(&(table->table[key]), iter, sizeof(xmlHashEntry));
290 table->table[key].next = NULL;
291 xmlFree(iter);
292 } else {
293 iter->next = table->table[key].next;
294 table->table[key].next = iter;
295 }
Daniel Veillarda10efa82001-04-18 13:09:01 +0000296
297#ifdef DEBUG_GROW
298 nbElem++;
299#endif
300
301 iter = next;
302 }
303 }
304
305 xmlFree(oldtable);
306
307#ifdef DEBUG_GROW
308 xmlGenericError(xmlGenericErrorContext,
309 "xmlHashGrow : from %d to %d, %d elems\n", oldsize, size, nbElem);
310#endif
311
312 return(0);
313}
314
315/**
Owen Taylor3473f882001-02-23 17:55:21 +0000316 * xmlHashFree:
317 * @table: the hash table
318 * @f: the deallocator function for items in the hash
319 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000320 * Free the hash @table and its contents. The userdata is
321 * deallocated with @f if provided.
Owen Taylor3473f882001-02-23 17:55:21 +0000322 */
323void
324xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) {
325 int i;
326 xmlHashEntryPtr iter;
327 xmlHashEntryPtr next;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000328 int inside_table = 0;
Daniel Veillard6155d8a2003-08-19 15:01:28 +0000329 int nbElems;
Owen Taylor3473f882001-02-23 17:55:21 +0000330
331 if (table == NULL)
332 return;
333 if (table->table) {
Daniel Veillard6155d8a2003-08-19 15:01:28 +0000334 nbElems = table->nbElems;
335 for(i = 0; (i < table->size) && (nbElems > 0); i++) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000336 iter = &(table->table[i]);
337 if (iter->valid == 0)
338 continue;
339 inside_table = 1;
Owen Taylor3473f882001-02-23 17:55:21 +0000340 while (iter) {
341 next = iter->next;
Daniel Veillarde991fe92003-10-29 11:18:37 +0000342 if ((f != NULL) && (iter->payload != NULL))
Daniel Veillarda10efa82001-04-18 13:09:01 +0000343 f(iter->payload, iter->name);
Daniel Veillard316a5c32005-01-23 22:56:39 +0000344 if (table->dict == NULL) {
345 if (iter->name)
346 xmlFree(iter->name);
347 if (iter->name2)
348 xmlFree(iter->name2);
349 if (iter->name3)
350 xmlFree(iter->name3);
351 }
Owen Taylor3473f882001-02-23 17:55:21 +0000352 iter->payload = NULL;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000353 if (!inside_table)
354 xmlFree(iter);
Daniel Veillard6155d8a2003-08-19 15:01:28 +0000355 nbElems--;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000356 inside_table = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000357 iter = next;
358 }
Owen Taylor3473f882001-02-23 17:55:21 +0000359 }
360 xmlFree(table->table);
361 }
Daniel Veillard316a5c32005-01-23 22:56:39 +0000362 if (table->dict)
363 xmlDictFree(table->dict);
Owen Taylor3473f882001-02-23 17:55:21 +0000364 xmlFree(table);
365}
366
367/**
368 * xmlHashAddEntry:
369 * @table: the hash table
370 * @name: the name of the userdata
371 * @userdata: a pointer to the userdata
372 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000373 * Add the @userdata to the hash @table. This can later be retrieved
374 * by using the @name. Duplicate names generate errors.
Owen Taylor3473f882001-02-23 17:55:21 +0000375 *
376 * Returns 0 the addition succeeded and -1 in case of error.
377 */
378int
379xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata) {
380 return(xmlHashAddEntry3(table, name, NULL, NULL, userdata));
381}
382
383/**
384 * xmlHashAddEntry2:
385 * @table: the hash table
386 * @name: the name of the userdata
387 * @name2: a second name of the userdata
388 * @userdata: a pointer to the userdata
389 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000390 * Add the @userdata to the hash @table. This can later be retrieved
391 * by using the (@name, @name2) tuple. Duplicate tuples generate errors.
Owen Taylor3473f882001-02-23 17:55:21 +0000392 *
393 * Returns 0 the addition succeeded and -1 in case of error.
394 */
395int
396xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name,
397 const xmlChar *name2, void *userdata) {
398 return(xmlHashAddEntry3(table, name, name2, NULL, userdata));
399}
400
401/**
402 * xmlHashUpdateEntry:
403 * @table: the hash table
404 * @name: the name of the userdata
405 * @userdata: a pointer to the userdata
406 * @f: the deallocator function for replaced item (if any)
407 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000408 * Add the @userdata to the hash @table. This can later be retrieved
409 * by using the @name. Existing entry for this @name will be removed
Owen Taylor3473f882001-02-23 17:55:21 +0000410 * and freed with @f if found.
411 *
412 * Returns 0 the addition succeeded and -1 in case of error.
413 */
414int
415xmlHashUpdateEntry(xmlHashTablePtr table, const xmlChar *name,
416 void *userdata, xmlHashDeallocator f) {
417 return(xmlHashUpdateEntry3(table, name, NULL, NULL, userdata, f));
418}
419
420/**
421 * xmlHashUpdateEntry2:
422 * @table: the hash table
423 * @name: the name of the userdata
424 * @name2: a second name of the userdata
425 * @userdata: a pointer to the userdata
426 * @f: the deallocator function for replaced item (if any)
427 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000428 * Add the @userdata to the hash @table. This can later be retrieved
429 * by using the (@name, @name2) tuple. Existing entry for this tuple will
Owen Taylor3473f882001-02-23 17:55:21 +0000430 * be removed and freed with @f if found.
431 *
432 * Returns 0 the addition succeeded and -1 in case of error.
433 */
434int
435xmlHashUpdateEntry2(xmlHashTablePtr table, const xmlChar *name,
436 const xmlChar *name2, void *userdata,
437 xmlHashDeallocator f) {
438 return(xmlHashUpdateEntry3(table, name, name2, NULL, userdata, f));
439}
440
441/**
442 * xmlHashLookup:
443 * @table: the hash table
444 * @name: the name of the userdata
445 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000446 * Find the userdata specified by the @name.
Owen Taylor3473f882001-02-23 17:55:21 +0000447 *
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000448 * Returns the pointer to the userdata
Owen Taylor3473f882001-02-23 17:55:21 +0000449 */
450void *
451xmlHashLookup(xmlHashTablePtr table, const xmlChar *name) {
452 return(xmlHashLookup3(table, name, NULL, NULL));
453}
454
455/**
456 * xmlHashLookup2:
457 * @table: the hash table
458 * @name: the name of the userdata
459 * @name2: a second name of the userdata
460 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000461 * Find the userdata specified by the (@name, @name2) tuple.
Owen Taylor3473f882001-02-23 17:55:21 +0000462 *
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000463 * Returns the pointer to the userdata
Owen Taylor3473f882001-02-23 17:55:21 +0000464 */
465void *
466xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name,
467 const xmlChar *name2) {
468 return(xmlHashLookup3(table, name, name2, NULL));
469}
470
471/**
Daniel Veillarde57ec792003-09-10 10:50:59 +0000472 * xmlHashQLookup:
473 * @table: the hash table
474 * @prefix: the prefix of the userdata
475 * @name: the name of the userdata
476 *
477 * Find the userdata specified by the QName @prefix:@name/@name.
478 *
479 * Returns the pointer to the userdata
480 */
481void *
482xmlHashQLookup(xmlHashTablePtr table, const xmlChar *prefix,
483 const xmlChar *name) {
484 return(xmlHashQLookup3(table, prefix, name, NULL, NULL, NULL, NULL));
485}
486
487/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +0000488 * xmlHashQLookup2:
Daniel Veillarde57ec792003-09-10 10:50:59 +0000489 * @table: the hash table
490 * @prefix: the prefix of the userdata
491 * @name: the name of the userdata
Daniel Veillard092643b2003-09-25 14:29:29 +0000492 * @prefix2: the second prefix of the userdata
Daniel Veillarde57ec792003-09-10 10:50:59 +0000493 * @name2: a second name of the userdata
494 *
495 * Find the userdata specified by the QNames tuple
496 *
497 * Returns the pointer to the userdata
498 */
499void *
500xmlHashQLookup2(xmlHashTablePtr table, const xmlChar *prefix,
501 const xmlChar *name, const xmlChar *prefix2,
502 const xmlChar *name2) {
503 return(xmlHashQLookup3(table, prefix, name, prefix2, name2, NULL, NULL));
504}
505
506/**
Owen Taylor3473f882001-02-23 17:55:21 +0000507 * xmlHashAddEntry3:
508 * @table: the hash table
509 * @name: the name of the userdata
510 * @name2: a second name of the userdata
511 * @name3: a third name of the userdata
512 * @userdata: a pointer to the userdata
513 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000514 * Add the @userdata to the hash @table. This can later be retrieved
515 * by using the tuple (@name, @name2, @name3). Duplicate entries generate
Owen Taylor3473f882001-02-23 17:55:21 +0000516 * errors.
517 *
518 * Returns 0 the addition succeeded and -1 in case of error.
519 */
520int
521xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
522 const xmlChar *name2, const xmlChar *name3,
523 void *userdata) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000524 unsigned long key, len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000525 xmlHashEntryPtr entry;
526 xmlHashEntryPtr insert;
527
Daniel Veillard316a5c32005-01-23 22:56:39 +0000528 if ((table == NULL) || (name == NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000529 return(-1);
530
531 /*
Daniel Veillard316a5c32005-01-23 22:56:39 +0000532 * If using a dict internalize if needed
533 */
534 if (table->dict) {
535 if (!xmlDictOwns(table->dict, name)) {
536 name = xmlDictLookup(table->dict, name, -1);
537 if (name == NULL)
538 return(-1);
539 }
540 if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) {
541 name2 = xmlDictLookup(table->dict, name2, -1);
542 if (name2 == NULL)
543 return(-1);
544 }
545 if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) {
546 name3 = xmlDictLookup(table->dict, name3, -1);
547 if (name3 == NULL)
548 return(-1);
549 }
550 }
551
552 /*
Owen Taylor3473f882001-02-23 17:55:21 +0000553 * Check for duplicate and insertion location.
554 */
Daniel Veillarda10efa82001-04-18 13:09:01 +0000555 key = xmlHashComputeKey(table, name, name2, name3);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000556 if (table->table[key].valid == 0) {
Owen Taylor3473f882001-02-23 17:55:21 +0000557 insert = NULL;
558 } else {
Daniel Veillard316a5c32005-01-23 22:56:39 +0000559 if (table->dict) {
560 for (insert = &(table->table[key]); insert->next != NULL;
561 insert = insert->next) {
562 if ((insert->name == name) &&
563 (insert->name2 == name2) &&
564 (insert->name3 == name3))
565 return(-1);
566 len++;
567 }
568 if ((insert->name == name) &&
569 (insert->name2 == name2) &&
570 (insert->name3 == name3))
571 return(-1);
572 } else {
573 for (insert = &(table->table[key]); insert->next != NULL;
574 insert = insert->next) {
575 if ((xmlStrEqual(insert->name, name)) &&
576 (xmlStrEqual(insert->name2, name2)) &&
577 (xmlStrEqual(insert->name3, name3)))
578 return(-1);
579 len++;
580 }
Owen Taylor3473f882001-02-23 17:55:21 +0000581 if ((xmlStrEqual(insert->name, name)) &&
582 (xmlStrEqual(insert->name2, name2)) &&
583 (xmlStrEqual(insert->name3, name3)))
584 return(-1);
585 }
Owen Taylor3473f882001-02-23 17:55:21 +0000586 }
587
Daniel Veillardfdc91562002-07-01 21:52:03 +0000588 if (insert == NULL) {
589 entry = &(table->table[key]);
590 } else {
591 entry = xmlMalloc(sizeof(xmlHashEntry));
592 if (entry == NULL)
593 return(-1);
594 }
595
Daniel Veillard316a5c32005-01-23 22:56:39 +0000596 if (table->dict != NULL) {
597 entry->name = (xmlChar *) name;
598 entry->name2 = (xmlChar *) name2;
599 entry->name3 = (xmlChar *) name3;
600 } else {
601 entry->name = xmlStrdup(name);
602 entry->name2 = xmlStrdup(name2);
603 entry->name3 = xmlStrdup(name3);
604 }
Owen Taylor3473f882001-02-23 17:55:21 +0000605 entry->payload = userdata;
606 entry->next = NULL;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000607 entry->valid = 1;
Owen Taylor3473f882001-02-23 17:55:21 +0000608
609
Daniel Veillardfdc91562002-07-01 21:52:03 +0000610 if (insert != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000611 insert->next = entry;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000612
Owen Taylor3473f882001-02-23 17:55:21 +0000613 table->nbElems++;
Daniel Veillarda10efa82001-04-18 13:09:01 +0000614
615 if (len > MAX_HASH_LEN)
616 xmlHashGrow(table, MAX_HASH_LEN * table->size);
617
Owen Taylor3473f882001-02-23 17:55:21 +0000618 return(0);
619}
620
621/**
622 * xmlHashUpdateEntry3:
623 * @table: the hash table
624 * @name: the name of the userdata
625 * @name2: a second name of the userdata
626 * @name3: a third name of the userdata
627 * @userdata: a pointer to the userdata
628 * @f: the deallocator function for replaced item (if any)
629 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000630 * Add the @userdata to the hash @table. This can later be retrieved
631 * by using the tuple (@name, @name2, @name3). Existing entry for this tuple
Owen Taylor3473f882001-02-23 17:55:21 +0000632 * will be removed and freed with @f if found.
633 *
634 * Returns 0 the addition succeeded and -1 in case of error.
635 */
636int
637xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name,
638 const xmlChar *name2, const xmlChar *name3,
639 void *userdata, xmlHashDeallocator f) {
640 unsigned long key;
641 xmlHashEntryPtr entry;
642 xmlHashEntryPtr insert;
643
644 if ((table == NULL) || name == NULL)
645 return(-1);
646
647 /*
Daniel Veillard316a5c32005-01-23 22:56:39 +0000648 * If using a dict internalize if needed
649 */
650 if (table->dict) {
651 if (!xmlDictOwns(table->dict, name)) {
652 name = xmlDictLookup(table->dict, name, -1);
653 if (name == NULL)
654 return(-1);
655 }
656 if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) {
657 name2 = xmlDictLookup(table->dict, name2, -1);
658 if (name2 == NULL)
659 return(-1);
660 }
661 if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) {
662 name3 = xmlDictLookup(table->dict, name3, -1);
663 if (name3 == NULL)
664 return(-1);
665 }
666 }
667
668 /*
Owen Taylor3473f882001-02-23 17:55:21 +0000669 * Check for duplicate and insertion location.
670 */
Daniel Veillarda10efa82001-04-18 13:09:01 +0000671 key = xmlHashComputeKey(table, name, name2, name3);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000672 if (table->table[key].valid == 0) {
Owen Taylor3473f882001-02-23 17:55:21 +0000673 insert = NULL;
674 } else {
Daniel Veillard316a5c32005-01-23 22:56:39 +0000675 if (table ->dict) {
676 for (insert = &(table->table[key]); insert->next != NULL;
677 insert = insert->next) {
678 if ((insert->name == name) &&
679 (insert->name2 == name2) &&
680 (insert->name3 == name3)) {
681 if (f)
682 f(insert->payload, insert->name);
683 insert->payload = userdata;
684 return(0);
685 }
686 }
687 if ((insert->name == name) &&
688 (insert->name2 == name2) &&
689 (insert->name3 == name3)) {
690 if (f)
691 f(insert->payload, insert->name);
692 insert->payload = userdata;
693 return(0);
694 }
695 } else {
696 for (insert = &(table->table[key]); insert->next != NULL;
697 insert = insert->next) {
698 if ((xmlStrEqual(insert->name, name)) &&
699 (xmlStrEqual(insert->name2, name2)) &&
700 (xmlStrEqual(insert->name3, name3))) {
701 if (f)
702 f(insert->payload, insert->name);
703 insert->payload = userdata;
704 return(0);
705 }
706 }
Owen Taylor3473f882001-02-23 17:55:21 +0000707 if ((xmlStrEqual(insert->name, name)) &&
708 (xmlStrEqual(insert->name2, name2)) &&
709 (xmlStrEqual(insert->name3, name3))) {
710 if (f)
711 f(insert->payload, insert->name);
712 insert->payload = userdata;
713 return(0);
714 }
715 }
Owen Taylor3473f882001-02-23 17:55:21 +0000716 }
717
Daniel Veillardfdc91562002-07-01 21:52:03 +0000718 if (insert == NULL) {
719 entry = &(table->table[key]);
720 } else {
721 entry = xmlMalloc(sizeof(xmlHashEntry));
722 if (entry == NULL)
723 return(-1);
724 }
725
Daniel Veillard316a5c32005-01-23 22:56:39 +0000726 if (table->dict != NULL) {
727 entry->name = (xmlChar *) name;
728 entry->name2 = (xmlChar *) name2;
729 entry->name3 = (xmlChar *) name3;
730 } else {
731 entry->name = xmlStrdup(name);
732 entry->name2 = xmlStrdup(name2);
733 entry->name3 = xmlStrdup(name3);
734 }
Owen Taylor3473f882001-02-23 17:55:21 +0000735 entry->payload = userdata;
736 entry->next = NULL;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000737 entry->valid = 1;
Owen Taylor3473f882001-02-23 17:55:21 +0000738 table->nbElems++;
739
740
Daniel Veillardfdc91562002-07-01 21:52:03 +0000741 if (insert != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +0000742 insert->next = entry;
743 }
744 return(0);
745}
746
747/**
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000748 * xmlHashLookup3:
Owen Taylor3473f882001-02-23 17:55:21 +0000749 * @table: the hash table
750 * @name: the name of the userdata
751 * @name2: a second name of the userdata
752 * @name3: a third name of the userdata
753 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000754 * Find the userdata specified by the (@name, @name2, @name3) tuple.
Owen Taylor3473f882001-02-23 17:55:21 +0000755 *
756 * Returns the a pointer to the userdata
757 */
758void *
759xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name,
760 const xmlChar *name2, const xmlChar *name3) {
761 unsigned long key;
762 xmlHashEntryPtr entry;
763
764 if (table == NULL)
765 return(NULL);
766 if (name == NULL)
767 return(NULL);
Daniel Veillarda10efa82001-04-18 13:09:01 +0000768 key = xmlHashComputeKey(table, name, name2, name3);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000769 if (table->table[key].valid == 0)
770 return(NULL);
Daniel Veillard316a5c32005-01-23 22:56:39 +0000771 if (table->dict) {
772 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
773 if ((entry->name == name) &&
774 (entry->name2 == name2) &&
775 (entry->name3 == name3))
776 return(entry->payload);
777 }
778 }
Daniel Veillardfdc91562002-07-01 21:52:03 +0000779 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
Owen Taylor3473f882001-02-23 17:55:21 +0000780 if ((xmlStrEqual(entry->name, name)) &&
781 (xmlStrEqual(entry->name2, name2)) &&
782 (xmlStrEqual(entry->name3, name3)))
783 return(entry->payload);
784 }
785 return(NULL);
786}
787
Daniel Veillarde57ec792003-09-10 10:50:59 +0000788/**
789 * xmlHashQLookup3:
790 * @table: the hash table
791 * @prefix: the prefix of the userdata
792 * @name: the name of the userdata
793 * @prefix2: the second prefix of the userdata
794 * @name2: a second name of the userdata
795 * @prefix3: the third prefix of the userdata
796 * @name3: a third name of the userdata
797 *
798 * Find the userdata specified by the (@name, @name2, @name3) tuple.
799 *
800 * Returns the a pointer to the userdata
801 */
802void *
803xmlHashQLookup3(xmlHashTablePtr table,
804 const xmlChar *prefix, const xmlChar *name,
805 const xmlChar *prefix2, const xmlChar *name2,
806 const xmlChar *prefix3, const xmlChar *name3) {
807 unsigned long key;
808 xmlHashEntryPtr entry;
809
810 if (table == NULL)
811 return(NULL);
812 if (name == NULL)
813 return(NULL);
814 key = xmlHashComputeQKey(table, prefix, name, prefix2,
815 name2, prefix3, name3);
816 if (table->table[key].valid == 0)
817 return(NULL);
818 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
819 if ((xmlStrQEqual(prefix, name, entry->name)) &&
820 (xmlStrQEqual(prefix2, name2, entry->name2)) &&
821 (xmlStrQEqual(prefix3, name3, entry->name3)))
822 return(entry->payload);
823 }
824 return(NULL);
825}
826
Daniel Veillard153120c2002-06-18 07:58:35 +0000827typedef struct {
828 xmlHashScanner hashscanner;
829 void *data;
830} stubData;
831
832static void
833stubHashScannerFull (void *payload, void *data, const xmlChar *name,
Daniel Veillardaeb258a2002-09-13 14:48:12 +0000834 const xmlChar *name2 ATTRIBUTE_UNUSED,
835 const xmlChar *name3 ATTRIBUTE_UNUSED) {
Daniel Veillard153120c2002-06-18 07:58:35 +0000836 stubData *stubdata = (stubData *) data;
837 stubdata->hashscanner (payload, stubdata->data, (xmlChar *) name);
838}
839
Daniel Veillard01c13b52002-12-10 15:19:08 +0000840/**
841 * xmlHashScan:
842 * @table: the hash table
843 * @f: the scanner function for items in the hash
844 * @data: extra data passed to f
845 *
846 * Scan the hash @table and applied @f to each value.
847 */
Owen Taylor3473f882001-02-23 17:55:21 +0000848void
849xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data) {
Daniel Veillard153120c2002-06-18 07:58:35 +0000850 stubData stubdata;
851 stubdata.data = data;
852 stubdata.hashscanner = f;
853 xmlHashScanFull (table, stubHashScannerFull, &stubdata);
Thomas Broyere8126242001-07-22 03:54:15 +0000854}
855
856/**
857 * xmlHashScanFull:
858 * @table: the hash table
859 * @f: the scanner function for items in the hash
860 * @data: extra data passed to f
861 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000862 * Scan the hash @table and applied @f to each value.
Thomas Broyere8126242001-07-22 03:54:15 +0000863 */
864void
865xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data) {
Daniel Veillardac4118d2008-01-11 05:27:32 +0000866 int i, nb;
Owen Taylor3473f882001-02-23 17:55:21 +0000867 xmlHashEntryPtr iter;
868 xmlHashEntryPtr next;
869
870 if (table == NULL)
871 return;
872 if (f == NULL)
873 return;
874
875 if (table->table) {
876 for(i = 0; i < table->size; i++) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000877 if (table->table[i].valid == 0)
878 continue;
879 iter = &(table->table[i]);
Owen Taylor3473f882001-02-23 17:55:21 +0000880 while (iter) {
881 next = iter->next;
Daniel Veillardac4118d2008-01-11 05:27:32 +0000882 nb = table->nbElems;
Daniel Veillarde991fe92003-10-29 11:18:37 +0000883 if ((f != NULL) && (iter->payload != NULL))
Thomas Broyere8126242001-07-22 03:54:15 +0000884 f(iter->payload, data, iter->name,
885 iter->name2, iter->name3);
Daniel Veillardac4118d2008-01-11 05:27:32 +0000886 if (nb != table->nbElems) {
887 /* table was modified by the callback, be careful */
888 if (iter == &(table->table[i])) {
889 if (table->table[i].valid == 0)
890 iter = NULL;
891 if (table->table[i].next != next)
892 iter = &(table->table[i]);
893 } else
894 iter = next;
895 } else
896 iter = next;
Owen Taylor3473f882001-02-23 17:55:21 +0000897 }
898 }
899 }
900}
901
902/**
903 * xmlHashScan3:
904 * @table: the hash table
905 * @name: the name of the userdata or NULL
906 * @name2: a second name of the userdata or NULL
907 * @name3: a third name of the userdata or NULL
908 * @f: the scanner function for items in the hash
909 * @data: extra data passed to f
910 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000911 * Scan the hash @table and applied @f to each value matching
912 * (@name, @name2, @name3) tuple. If one of the names is null,
Owen Taylor3473f882001-02-23 17:55:21 +0000913 * the comparison is considered to match.
914 */
915void
916xmlHashScan3(xmlHashTablePtr table, const xmlChar *name,
917 const xmlChar *name2, const xmlChar *name3,
918 xmlHashScanner f, void *data) {
Thomas Broyere8126242001-07-22 03:54:15 +0000919 xmlHashScanFull3 (table, name, name2, name3,
920 (xmlHashScannerFull) f, data);
921}
922
923/**
924 * xmlHashScanFull3:
925 * @table: the hash table
926 * @name: the name of the userdata or NULL
927 * @name2: a second name of the userdata or NULL
928 * @name3: a third name of the userdata or NULL
929 * @f: the scanner function for items in the hash
930 * @data: extra data passed to f
931 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000932 * Scan the hash @table and applied @f to each value matching
933 * (@name, @name2, @name3) tuple. If one of the names is null,
Thomas Broyere8126242001-07-22 03:54:15 +0000934 * the comparison is considered to match.
935 */
936void
937xmlHashScanFull3(xmlHashTablePtr table, const xmlChar *name,
938 const xmlChar *name2, const xmlChar *name3,
939 xmlHashScannerFull f, void *data) {
Owen Taylor3473f882001-02-23 17:55:21 +0000940 int i;
941 xmlHashEntryPtr iter;
942 xmlHashEntryPtr next;
943
944 if (table == NULL)
945 return;
946 if (f == NULL)
947 return;
948
949 if (table->table) {
950 for(i = 0; i < table->size; i++) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000951 if (table->table[i].valid == 0)
952 continue;
953 iter = &(table->table[i]);
Owen Taylor3473f882001-02-23 17:55:21 +0000954 while (iter) {
955 next = iter->next;
956 if (((name == NULL) || (xmlStrEqual(name, iter->name))) &&
957 ((name2 == NULL) || (xmlStrEqual(name2, iter->name2))) &&
Daniel Veillarde991fe92003-10-29 11:18:37 +0000958 ((name3 == NULL) || (xmlStrEqual(name3, iter->name3))) &&
959 (iter->payload != NULL)) {
Thomas Broyere8126242001-07-22 03:54:15 +0000960 f(iter->payload, data, iter->name,
961 iter->name2, iter->name3);
Owen Taylor3473f882001-02-23 17:55:21 +0000962 }
963 iter = next;
964 }
965 }
966 }
967}
968
969/**
970 * xmlHashCopy:
971 * @table: the hash table
972 * @f: the copier function for items in the hash
973 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000974 * Scan the hash @table and applied @f to each value.
Owen Taylor3473f882001-02-23 17:55:21 +0000975 *
976 * Returns the new table or NULL in case of error.
977 */
978xmlHashTablePtr
979xmlHashCopy(xmlHashTablePtr table, xmlHashCopier f) {
980 int i;
981 xmlHashEntryPtr iter;
982 xmlHashEntryPtr next;
983 xmlHashTablePtr ret;
984
985 if (table == NULL)
986 return(NULL);
987 if (f == NULL)
988 return(NULL);
989
990 ret = xmlHashCreate(table->size);
991 if (table->table) {
992 for(i = 0; i < table->size; i++) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000993 if (table->table[i].valid == 0)
994 continue;
995 iter = &(table->table[i]);
Owen Taylor3473f882001-02-23 17:55:21 +0000996 while (iter) {
997 next = iter->next;
998 xmlHashAddEntry3(ret, iter->name, iter->name2,
999 iter->name3, f(iter->payload, iter->name));
1000 iter = next;
1001 }
1002 }
1003 }
1004 ret->nbElems = table->nbElems;
1005 return(ret);
1006}
1007
1008/**
1009 * xmlHashSize:
1010 * @table: the hash table
1011 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001012 * Query the number of elements installed in the hash @table.
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001013 *
Owen Taylor3473f882001-02-23 17:55:21 +00001014 * Returns the number of elements in the hash table or
1015 * -1 in case of error
1016 */
1017int
1018xmlHashSize(xmlHashTablePtr table) {
1019 if (table == NULL)
1020 return(-1);
1021 return(table->nbElems);
1022}
1023
1024/**
Daniel Veillardf69bb4b2001-05-19 13:24:56 +00001025 * xmlHashRemoveEntry:
Owen Taylor3473f882001-02-23 17:55:21 +00001026 * @table: the hash table
1027 * @name: the name of the userdata
1028 * @f: the deallocator function for removed item (if any)
1029 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001030 * Find the userdata specified by the @name and remove
1031 * it from the hash @table. Existing userdata for this tuple will be removed
Owen Taylor3473f882001-02-23 17:55:21 +00001032 * and freed with @f.
1033 *
1034 * Returns 0 if the removal succeeded and -1 in case of error or not found.
1035 */
1036int xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name,
Daniel Veillarda10efa82001-04-18 13:09:01 +00001037 xmlHashDeallocator f) {
1038 return(xmlHashRemoveEntry3(table, name, NULL, NULL, f));
Owen Taylor3473f882001-02-23 17:55:21 +00001039}
1040
1041/**
Daniel Veillardf69bb4b2001-05-19 13:24:56 +00001042 * xmlHashRemoveEntry2:
Owen Taylor3473f882001-02-23 17:55:21 +00001043 * @table: the hash table
1044 * @name: the name of the userdata
1045 * @name2: a second name of the userdata
1046 * @f: the deallocator function for removed item (if any)
1047 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001048 * Find the userdata specified by the (@name, @name2) tuple and remove
1049 * it from the hash @table. Existing userdata for this tuple will be removed
Owen Taylor3473f882001-02-23 17:55:21 +00001050 * and freed with @f.
1051 *
1052 * Returns 0 if the removal succeeded and -1 in case of error or not found.
1053 */
Daniel Veillard01c13b52002-12-10 15:19:08 +00001054int
1055xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name,
Daniel Veillarda10efa82001-04-18 13:09:01 +00001056 const xmlChar *name2, xmlHashDeallocator f) {
1057 return(xmlHashRemoveEntry3(table, name, name2, NULL, f));
Owen Taylor3473f882001-02-23 17:55:21 +00001058}
1059
1060/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00001061 * xmlHashRemoveEntry3:
Owen Taylor3473f882001-02-23 17:55:21 +00001062 * @table: the hash table
1063 * @name: the name of the userdata
1064 * @name2: a second name of the userdata
1065 * @name3: a third name of the userdata
1066 * @f: the deallocator function for removed item (if any)
1067 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001068 * Find the userdata specified by the (@name, @name2, @name3) tuple and remove
1069 * it from the hash @table. Existing userdata for this tuple will be removed
Owen Taylor3473f882001-02-23 17:55:21 +00001070 * and freed with @f.
1071 *
1072 * Returns 0 if the removal succeeded and -1 in case of error or not found.
1073 */
Daniel Veillard01c13b52002-12-10 15:19:08 +00001074int
1075xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name,
Daniel Veillarda10efa82001-04-18 13:09:01 +00001076 const xmlChar *name2, const xmlChar *name3, xmlHashDeallocator f) {
1077 unsigned long key;
1078 xmlHashEntryPtr entry;
1079 xmlHashEntryPtr prev = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001080
Daniel Veillarda10efa82001-04-18 13:09:01 +00001081 if (table == NULL || name == NULL)
1082 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001083
Daniel Veillarda10efa82001-04-18 13:09:01 +00001084 key = xmlHashComputeKey(table, name, name2, name3);
Daniel Veillardfdc91562002-07-01 21:52:03 +00001085 if (table->table[key].valid == 0) {
Daniel Veillarda10efa82001-04-18 13:09:01 +00001086 return(-1);
1087 } else {
Daniel Veillardfdc91562002-07-01 21:52:03 +00001088 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
Daniel Veillarda10efa82001-04-18 13:09:01 +00001089 if (xmlStrEqual(entry->name, name) &&
1090 xmlStrEqual(entry->name2, name2) &&
1091 xmlStrEqual(entry->name3, name3)) {
Daniel Veillarde991fe92003-10-29 11:18:37 +00001092 if ((f != NULL) && (entry->payload != NULL))
Daniel Veillarda10efa82001-04-18 13:09:01 +00001093 f(entry->payload, entry->name);
1094 entry->payload = NULL;
Daniel Veillard316a5c32005-01-23 22:56:39 +00001095 if (table->dict == NULL) {
1096 if(entry->name)
1097 xmlFree(entry->name);
1098 if(entry->name2)
1099 xmlFree(entry->name2);
1100 if(entry->name3)
1101 xmlFree(entry->name3);
1102 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00001103 if(prev) {
Daniel Veillarda10efa82001-04-18 13:09:01 +00001104 prev->next = entry->next;
Daniel Veillardfdc91562002-07-01 21:52:03 +00001105 xmlFree(entry);
1106 } else {
1107 if (entry->next == NULL) {
1108 entry->valid = 0;
1109 } else {
1110 entry = entry->next;
1111 memcpy(&(table->table[key]), entry, sizeof(xmlHashEntry));
1112 xmlFree(entry);
1113 }
1114 }
Daniel Veillarda10efa82001-04-18 13:09:01 +00001115 table->nbElems--;
1116 return(0);
1117 }
1118 prev = entry;
1119 }
1120 return(-1);
1121 }
Daniel Veillard9e7160d2001-03-18 23:17:47 +00001122}
1123
Daniel Veillard5d4644e2005-04-01 13:11:58 +00001124#define bottom_hash
1125#include "elfgcchack.h"