blob: 15e1efe988bc167604e3c933da8ce3c79088d611 [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
50/*
51 * A single entry in the hash table
52 */
53typedef struct _xmlHashEntry xmlHashEntry;
54typedef xmlHashEntry *xmlHashEntryPtr;
55struct _xmlHashEntry {
56 struct _xmlHashEntry *next;
57 xmlChar *name;
58 xmlChar *name2;
59 xmlChar *name3;
60 void *payload;
Daniel Veillardfdc91562002-07-01 21:52:03 +000061 int valid;
Owen Taylor3473f882001-02-23 17:55:21 +000062};
63
64/*
65 * The entire hash table
66 */
67struct _xmlHashTable {
Daniel Veillardfdc91562002-07-01 21:52:03 +000068 struct _xmlHashEntry *table;
Owen Taylor3473f882001-02-23 17:55:21 +000069 int size;
70 int nbElems;
Daniel Veillard316a5c32005-01-23 22:56:39 +000071 xmlDictPtr dict;
Daniel Veillard8973d582012-02-04 19:07:44 +080072#ifdef HASH_RANDOMIZATION
73 int random_seed;
74#endif
Owen Taylor3473f882001-02-23 17:55:21 +000075};
76
77/*
78 * xmlHashComputeKey:
79 * Calculate the hash key
80 */
81static unsigned long
Daniel Veillarda10efa82001-04-18 13:09:01 +000082xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
83 const xmlChar *name2, const xmlChar *name3) {
Owen Taylor3473f882001-02-23 17:55:21 +000084 unsigned long value = 0L;
85 char ch;
86
Daniel Veillard8973d582012-02-04 19:07:44 +080087#ifdef HASH_RANDOMIZATION
88 value = table->random_seed;
89#endif
Daniel Veillarda10efa82001-04-18 13:09:01 +000090 if (name != NULL) {
91 value += 30 * (*name);
92 while ((ch = *name++) != 0) {
Daniel Veillard5f7f9912002-06-17 17:03:00 +000093 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Daniel Veillarda10efa82001-04-18 13:09:01 +000094 }
95 }
96 if (name2 != NULL) {
97 while ((ch = *name2++) != 0) {
Daniel Veillard5f7f9912002-06-17 17:03:00 +000098 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Daniel Veillarda10efa82001-04-18 13:09:01 +000099 }
100 }
101 if (name3 != NULL) {
102 while ((ch = *name3++) != 0) {
Daniel Veillard5f7f9912002-06-17 17:03:00 +0000103 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Daniel Veillarda10efa82001-04-18 13:09:01 +0000104 }
Owen Taylor3473f882001-02-23 17:55:21 +0000105 }
106 return (value % table->size);
107}
108
Daniel Veillarde57ec792003-09-10 10:50:59 +0000109static unsigned long
110xmlHashComputeQKey(xmlHashTablePtr table,
Daniel Veillard8e36e6a2003-09-10 10:50:59 +0000111 const xmlChar *prefix, const xmlChar *name,
112 const xmlChar *prefix2, const xmlChar *name2,
113 const xmlChar *prefix3, const xmlChar *name3) {
Daniel Veillarde57ec792003-09-10 10:50:59 +0000114 unsigned long value = 0L;
115 char ch;
116
Daniel Veillard8973d582012-02-04 19:07:44 +0800117#ifdef HASH_RANDOMIZATION
118 value = table->random_seed;
119#endif
Daniel Veillarde57ec792003-09-10 10:50:59 +0000120 if (prefix != NULL)
121 value += 30 * (*prefix);
122 else
123 value += 30 * (*name);
124
125 if (prefix != NULL) {
126 while ((ch = *prefix++) != 0) {
127 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
128 }
129 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
130 }
131 if (name != NULL) {
132 while ((ch = *name++) != 0) {
133 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
134 }
135 }
136 if (prefix2 != NULL) {
137 while ((ch = *prefix2++) != 0) {
138 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
139 }
140 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
141 }
142 if (name2 != NULL) {
143 while ((ch = *name2++) != 0) {
144 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
145 }
146 }
147 if (prefix3 != NULL) {
148 while ((ch = *prefix3++) != 0) {
149 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
150 }
151 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
152 }
153 if (name3 != NULL) {
154 while ((ch = *name3++) != 0) {
155 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
156 }
157 }
158 return (value % table->size);
159}
160
Owen Taylor3473f882001-02-23 17:55:21 +0000161/**
162 * xmlHashCreate:
163 * @size: the size of the hash table
164 *
165 * Create a new xmlHashTablePtr.
166 *
167 * Returns the newly created object, or NULL if an error occured.
168 */
169xmlHashTablePtr
170xmlHashCreate(int size) {
171 xmlHashTablePtr table;
172
173 if (size <= 0)
174 size = 256;
175
176 table = xmlMalloc(sizeof(xmlHashTable));
177 if (table) {
Daniel Veillard316a5c32005-01-23 22:56:39 +0000178 table->dict = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +0000179 table->size = size;
180 table->nbElems = 0;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000181 table->table = xmlMalloc(size * sizeof(xmlHashEntry));
Owen Taylor3473f882001-02-23 17:55:21 +0000182 if (table->table) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000183 memset(table->table, 0, size * sizeof(xmlHashEntry));
Daniel Veillard8973d582012-02-04 19:07:44 +0800184#ifdef HASH_RANDOMIZATION
Daniel Veillard379ebc12012-05-18 15:41:31 +0800185 table->random_seed = __xmlRandom();
Daniel Veillard8973d582012-02-04 19:07:44 +0800186#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000187 return(table);
188 }
189 xmlFree(table);
190 }
191 return(NULL);
192}
193
194/**
Daniel Veillard316a5c32005-01-23 22:56:39 +0000195 * xmlHashCreateDict:
196 * @size: the size of the hash table
197 * @dict: a dictionary to use for the hash
198 *
199 * Create a new xmlHashTablePtr which will use @dict as the internal dictionary
200 *
201 * Returns the newly created object, or NULL if an error occured.
202 */
203xmlHashTablePtr
204xmlHashCreateDict(int size, xmlDictPtr dict) {
205 xmlHashTablePtr table;
206
207 table = xmlHashCreate(size);
208 if (table != NULL) {
209 table->dict = dict;
210 xmlDictReference(dict);
211 }
212 return(table);
213}
214
215/**
Daniel Veillarda10efa82001-04-18 13:09:01 +0000216 * xmlHashGrow:
217 * @table: the hash table
218 * @size: the new size of the hash table
219 *
220 * resize the hash table
221 *
222 * Returns 0 in case of success, -1 in case of failure
223 */
Daniel Veillarddab4cb32001-04-20 13:03:48 +0000224static int
Daniel Veillarda10efa82001-04-18 13:09:01 +0000225xmlHashGrow(xmlHashTablePtr table, int size) {
226 unsigned long key;
227 int oldsize, i;
228 xmlHashEntryPtr iter, next;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000229 struct _xmlHashEntry *oldtable;
Daniel Veillarda10efa82001-04-18 13:09:01 +0000230#ifdef DEBUG_GROW
231 unsigned long nbElem = 0;
232#endif
233
234 if (table == NULL)
235 return(-1);
236 if (size < 8)
237 return(-1);
238 if (size > 8 * 2048)
239 return(-1);
240
241 oldsize = table->size;
242 oldtable = table->table;
243 if (oldtable == NULL)
244 return(-1);
245
Daniel Veillardfdc91562002-07-01 21:52:03 +0000246 table->table = xmlMalloc(size * sizeof(xmlHashEntry));
Daniel Veillarda10efa82001-04-18 13:09:01 +0000247 if (table->table == NULL) {
248 table->table = oldtable;
249 return(-1);
250 }
Daniel Veillardfdc91562002-07-01 21:52:03 +0000251 memset(table->table, 0, size * sizeof(xmlHashEntry));
Daniel Veillarda10efa82001-04-18 13:09:01 +0000252 table->size = size;
253
Daniel Veillardfdc91562002-07-01 21:52:03 +0000254 /* If the two loops are merged, there would be situations where
255 a new entry needs to allocated and data copied into it from
256 the main table. So instead, we run through the array twice, first
257 copying all the elements in the main array (where we can't get
258 conflicts) and then the rest, so we only free (and don't allocate)
259 */
Daniel Veillarda10efa82001-04-18 13:09:01 +0000260 for (i = 0; i < oldsize; i++) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000261 if (oldtable[i].valid == 0)
262 continue;
263 key = xmlHashComputeKey(table, oldtable[i].name, oldtable[i].name2,
264 oldtable[i].name3);
265 memcpy(&(table->table[key]), &(oldtable[i]), sizeof(xmlHashEntry));
266 table->table[key].next = NULL;
267 }
268
269 for (i = 0; i < oldsize; i++) {
270 iter = oldtable[i].next;
Daniel Veillarda10efa82001-04-18 13:09:01 +0000271 while (iter) {
272 next = iter->next;
273
274 /*
275 * put back the entry in the new table
276 */
277
278 key = xmlHashComputeKey(table, iter->name, iter->name2,
279 iter->name3);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000280 if (table->table[key].valid == 0) {
281 memcpy(&(table->table[key]), iter, sizeof(xmlHashEntry));
282 table->table[key].next = NULL;
283 xmlFree(iter);
284 } else {
285 iter->next = table->table[key].next;
286 table->table[key].next = iter;
287 }
Daniel Veillarda10efa82001-04-18 13:09:01 +0000288
289#ifdef DEBUG_GROW
290 nbElem++;
291#endif
292
293 iter = next;
294 }
295 }
296
297 xmlFree(oldtable);
298
299#ifdef DEBUG_GROW
300 xmlGenericError(xmlGenericErrorContext,
301 "xmlHashGrow : from %d to %d, %d elems\n", oldsize, size, nbElem);
302#endif
303
304 return(0);
305}
306
307/**
Owen Taylor3473f882001-02-23 17:55:21 +0000308 * xmlHashFree:
309 * @table: the hash table
310 * @f: the deallocator function for items in the hash
311 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000312 * Free the hash @table and its contents. The userdata is
313 * deallocated with @f if provided.
Owen Taylor3473f882001-02-23 17:55:21 +0000314 */
315void
316xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) {
317 int i;
318 xmlHashEntryPtr iter;
319 xmlHashEntryPtr next;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000320 int inside_table = 0;
Daniel Veillard6155d8a2003-08-19 15:01:28 +0000321 int nbElems;
Owen Taylor3473f882001-02-23 17:55:21 +0000322
323 if (table == NULL)
324 return;
325 if (table->table) {
Daniel Veillard6155d8a2003-08-19 15:01:28 +0000326 nbElems = table->nbElems;
327 for(i = 0; (i < table->size) && (nbElems > 0); i++) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000328 iter = &(table->table[i]);
329 if (iter->valid == 0)
330 continue;
331 inside_table = 1;
Owen Taylor3473f882001-02-23 17:55:21 +0000332 while (iter) {
333 next = iter->next;
Daniel Veillarde991fe92003-10-29 11:18:37 +0000334 if ((f != NULL) && (iter->payload != NULL))
Daniel Veillarda10efa82001-04-18 13:09:01 +0000335 f(iter->payload, iter->name);
Daniel Veillard316a5c32005-01-23 22:56:39 +0000336 if (table->dict == NULL) {
337 if (iter->name)
338 xmlFree(iter->name);
339 if (iter->name2)
340 xmlFree(iter->name2);
341 if (iter->name3)
342 xmlFree(iter->name3);
343 }
Owen Taylor3473f882001-02-23 17:55:21 +0000344 iter->payload = NULL;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000345 if (!inside_table)
346 xmlFree(iter);
Daniel Veillard6155d8a2003-08-19 15:01:28 +0000347 nbElems--;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000348 inside_table = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000349 iter = next;
350 }
Owen Taylor3473f882001-02-23 17:55:21 +0000351 }
352 xmlFree(table->table);
353 }
Daniel Veillard316a5c32005-01-23 22:56:39 +0000354 if (table->dict)
355 xmlDictFree(table->dict);
Owen Taylor3473f882001-02-23 17:55:21 +0000356 xmlFree(table);
357}
358
359/**
360 * xmlHashAddEntry:
361 * @table: the hash table
362 * @name: the name of the userdata
363 * @userdata: a pointer to the userdata
364 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000365 * Add the @userdata to the hash @table. This can later be retrieved
366 * by using the @name. Duplicate names generate errors.
Owen Taylor3473f882001-02-23 17:55:21 +0000367 *
368 * Returns 0 the addition succeeded and -1 in case of error.
369 */
370int
371xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata) {
372 return(xmlHashAddEntry3(table, name, NULL, NULL, userdata));
373}
374
375/**
376 * xmlHashAddEntry2:
377 * @table: the hash table
378 * @name: the name of the userdata
379 * @name2: a second name of the userdata
380 * @userdata: a pointer to the userdata
381 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000382 * Add the @userdata to the hash @table. This can later be retrieved
383 * by using the (@name, @name2) tuple. Duplicate tuples generate errors.
Owen Taylor3473f882001-02-23 17:55:21 +0000384 *
385 * Returns 0 the addition succeeded and -1 in case of error.
386 */
387int
388xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name,
389 const xmlChar *name2, void *userdata) {
390 return(xmlHashAddEntry3(table, name, name2, NULL, userdata));
391}
392
393/**
394 * xmlHashUpdateEntry:
395 * @table: the hash table
396 * @name: the name of the userdata
397 * @userdata: a pointer to the userdata
398 * @f: the deallocator function for replaced item (if any)
399 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000400 * Add the @userdata to the hash @table. This can later be retrieved
401 * by using the @name. Existing entry for this @name will be removed
Owen Taylor3473f882001-02-23 17:55:21 +0000402 * and freed with @f if found.
403 *
404 * Returns 0 the addition succeeded and -1 in case of error.
405 */
406int
407xmlHashUpdateEntry(xmlHashTablePtr table, const xmlChar *name,
408 void *userdata, xmlHashDeallocator f) {
409 return(xmlHashUpdateEntry3(table, name, NULL, NULL, userdata, f));
410}
411
412/**
413 * xmlHashUpdateEntry2:
414 * @table: the hash table
415 * @name: the name of the userdata
416 * @name2: a second name of the userdata
417 * @userdata: a pointer to the userdata
418 * @f: the deallocator function for replaced item (if any)
419 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000420 * Add the @userdata to the hash @table. This can later be retrieved
421 * by using the (@name, @name2) tuple. Existing entry for this tuple will
Owen Taylor3473f882001-02-23 17:55:21 +0000422 * be removed and freed with @f if found.
423 *
424 * Returns 0 the addition succeeded and -1 in case of error.
425 */
426int
427xmlHashUpdateEntry2(xmlHashTablePtr table, const xmlChar *name,
428 const xmlChar *name2, void *userdata,
429 xmlHashDeallocator f) {
430 return(xmlHashUpdateEntry3(table, name, name2, NULL, userdata, f));
431}
432
433/**
434 * xmlHashLookup:
435 * @table: the hash table
436 * @name: the name of the userdata
437 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000438 * Find the userdata specified by the @name.
Owen Taylor3473f882001-02-23 17:55:21 +0000439 *
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000440 * Returns the pointer to the userdata
Owen Taylor3473f882001-02-23 17:55:21 +0000441 */
442void *
443xmlHashLookup(xmlHashTablePtr table, const xmlChar *name) {
444 return(xmlHashLookup3(table, name, NULL, NULL));
445}
446
447/**
448 * xmlHashLookup2:
449 * @table: the hash table
450 * @name: the name of the userdata
451 * @name2: a second name of the userdata
452 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000453 * Find the userdata specified by the (@name, @name2) tuple.
Owen Taylor3473f882001-02-23 17:55:21 +0000454 *
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000455 * Returns the pointer to the userdata
Owen Taylor3473f882001-02-23 17:55:21 +0000456 */
457void *
458xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name,
459 const xmlChar *name2) {
460 return(xmlHashLookup3(table, name, name2, NULL));
461}
462
463/**
Daniel Veillarde57ec792003-09-10 10:50:59 +0000464 * xmlHashQLookup:
465 * @table: the hash table
466 * @prefix: the prefix of the userdata
467 * @name: the name of the userdata
468 *
469 * Find the userdata specified by the QName @prefix:@name/@name.
470 *
471 * Returns the pointer to the userdata
472 */
473void *
474xmlHashQLookup(xmlHashTablePtr table, const xmlChar *prefix,
475 const xmlChar *name) {
476 return(xmlHashQLookup3(table, prefix, name, NULL, NULL, NULL, NULL));
477}
478
479/**
Daniel Veillard7a02cfe2003-09-25 12:18:34 +0000480 * xmlHashQLookup2:
Daniel Veillarde57ec792003-09-10 10:50:59 +0000481 * @table: the hash table
482 * @prefix: the prefix of the userdata
483 * @name: the name of the userdata
Daniel Veillard092643b2003-09-25 14:29:29 +0000484 * @prefix2: the second prefix of the userdata
Daniel Veillarde57ec792003-09-10 10:50:59 +0000485 * @name2: a second name of the userdata
486 *
487 * Find the userdata specified by the QNames tuple
488 *
489 * Returns the pointer to the userdata
490 */
491void *
492xmlHashQLookup2(xmlHashTablePtr table, const xmlChar *prefix,
493 const xmlChar *name, const xmlChar *prefix2,
494 const xmlChar *name2) {
495 return(xmlHashQLookup3(table, prefix, name, prefix2, name2, NULL, NULL));
496}
497
498/**
Owen Taylor3473f882001-02-23 17:55:21 +0000499 * xmlHashAddEntry3:
500 * @table: the hash table
501 * @name: the name of the userdata
502 * @name2: a second name of the userdata
503 * @name3: a third name of the userdata
504 * @userdata: a pointer to the userdata
505 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000506 * Add the @userdata to the hash @table. This can later be retrieved
507 * by using the tuple (@name, @name2, @name3). Duplicate entries generate
Owen Taylor3473f882001-02-23 17:55:21 +0000508 * errors.
509 *
510 * Returns 0 the addition succeeded and -1 in case of error.
511 */
512int
513xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
514 const xmlChar *name2, const xmlChar *name3,
515 void *userdata) {
Daniel Veillarda10efa82001-04-18 13:09:01 +0000516 unsigned long key, len = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000517 xmlHashEntryPtr entry;
518 xmlHashEntryPtr insert;
519
Daniel Veillard316a5c32005-01-23 22:56:39 +0000520 if ((table == NULL) || (name == NULL))
Owen Taylor3473f882001-02-23 17:55:21 +0000521 return(-1);
522
523 /*
Daniel Veillard316a5c32005-01-23 22:56:39 +0000524 * If using a dict internalize if needed
525 */
526 if (table->dict) {
527 if (!xmlDictOwns(table->dict, name)) {
528 name = xmlDictLookup(table->dict, name, -1);
529 if (name == NULL)
530 return(-1);
531 }
532 if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) {
533 name2 = xmlDictLookup(table->dict, name2, -1);
534 if (name2 == NULL)
535 return(-1);
536 }
537 if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) {
538 name3 = xmlDictLookup(table->dict, name3, -1);
539 if (name3 == NULL)
540 return(-1);
541 }
542 }
543
544 /*
Owen Taylor3473f882001-02-23 17:55:21 +0000545 * Check for duplicate and insertion location.
546 */
Daniel Veillarda10efa82001-04-18 13:09:01 +0000547 key = xmlHashComputeKey(table, name, name2, name3);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000548 if (table->table[key].valid == 0) {
Owen Taylor3473f882001-02-23 17:55:21 +0000549 insert = NULL;
550 } else {
Daniel Veillard316a5c32005-01-23 22:56:39 +0000551 if (table->dict) {
552 for (insert = &(table->table[key]); insert->next != NULL;
553 insert = insert->next) {
554 if ((insert->name == name) &&
555 (insert->name2 == name2) &&
556 (insert->name3 == name3))
557 return(-1);
558 len++;
559 }
560 if ((insert->name == name) &&
561 (insert->name2 == name2) &&
562 (insert->name3 == name3))
563 return(-1);
564 } else {
565 for (insert = &(table->table[key]); insert->next != NULL;
566 insert = insert->next) {
567 if ((xmlStrEqual(insert->name, name)) &&
568 (xmlStrEqual(insert->name2, name2)) &&
569 (xmlStrEqual(insert->name3, name3)))
570 return(-1);
571 len++;
572 }
Owen Taylor3473f882001-02-23 17:55:21 +0000573 if ((xmlStrEqual(insert->name, name)) &&
574 (xmlStrEqual(insert->name2, name2)) &&
575 (xmlStrEqual(insert->name3, name3)))
576 return(-1);
577 }
Owen Taylor3473f882001-02-23 17:55:21 +0000578 }
579
Daniel Veillardfdc91562002-07-01 21:52:03 +0000580 if (insert == NULL) {
581 entry = &(table->table[key]);
582 } else {
583 entry = xmlMalloc(sizeof(xmlHashEntry));
584 if (entry == NULL)
585 return(-1);
586 }
587
Daniel Veillard316a5c32005-01-23 22:56:39 +0000588 if (table->dict != NULL) {
589 entry->name = (xmlChar *) name;
590 entry->name2 = (xmlChar *) name2;
591 entry->name3 = (xmlChar *) name3;
592 } else {
593 entry->name = xmlStrdup(name);
594 entry->name2 = xmlStrdup(name2);
595 entry->name3 = xmlStrdup(name3);
596 }
Owen Taylor3473f882001-02-23 17:55:21 +0000597 entry->payload = userdata;
598 entry->next = NULL;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000599 entry->valid = 1;
Owen Taylor3473f882001-02-23 17:55:21 +0000600
601
Daniel Veillardfdc91562002-07-01 21:52:03 +0000602 if (insert != NULL)
Owen Taylor3473f882001-02-23 17:55:21 +0000603 insert->next = entry;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000604
Owen Taylor3473f882001-02-23 17:55:21 +0000605 table->nbElems++;
Daniel Veillarda10efa82001-04-18 13:09:01 +0000606
607 if (len > MAX_HASH_LEN)
608 xmlHashGrow(table, MAX_HASH_LEN * table->size);
609
Owen Taylor3473f882001-02-23 17:55:21 +0000610 return(0);
611}
612
613/**
614 * xmlHashUpdateEntry3:
615 * @table: the hash table
616 * @name: the name of the userdata
617 * @name2: a second name of the userdata
618 * @name3: a third name of the userdata
619 * @userdata: a pointer to the userdata
620 * @f: the deallocator function for replaced item (if any)
621 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000622 * Add the @userdata to the hash @table. This can later be retrieved
623 * by using the tuple (@name, @name2, @name3). Existing entry for this tuple
Owen Taylor3473f882001-02-23 17:55:21 +0000624 * will be removed and freed with @f if found.
625 *
626 * Returns 0 the addition succeeded and -1 in case of error.
627 */
628int
629xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name,
630 const xmlChar *name2, const xmlChar *name3,
631 void *userdata, xmlHashDeallocator f) {
632 unsigned long key;
633 xmlHashEntryPtr entry;
634 xmlHashEntryPtr insert;
635
636 if ((table == NULL) || name == NULL)
637 return(-1);
638
639 /*
Daniel Veillard316a5c32005-01-23 22:56:39 +0000640 * If using a dict internalize if needed
641 */
642 if (table->dict) {
643 if (!xmlDictOwns(table->dict, name)) {
644 name = xmlDictLookup(table->dict, name, -1);
645 if (name == NULL)
646 return(-1);
647 }
648 if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) {
649 name2 = xmlDictLookup(table->dict, name2, -1);
650 if (name2 == NULL)
651 return(-1);
652 }
653 if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) {
654 name3 = xmlDictLookup(table->dict, name3, -1);
655 if (name3 == NULL)
656 return(-1);
657 }
658 }
659
660 /*
Owen Taylor3473f882001-02-23 17:55:21 +0000661 * Check for duplicate and insertion location.
662 */
Daniel Veillarda10efa82001-04-18 13:09:01 +0000663 key = xmlHashComputeKey(table, name, name2, name3);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000664 if (table->table[key].valid == 0) {
Owen Taylor3473f882001-02-23 17:55:21 +0000665 insert = NULL;
666 } else {
Daniel Veillard316a5c32005-01-23 22:56:39 +0000667 if (table ->dict) {
668 for (insert = &(table->table[key]); insert->next != NULL;
669 insert = insert->next) {
670 if ((insert->name == name) &&
671 (insert->name2 == name2) &&
672 (insert->name3 == name3)) {
673 if (f)
674 f(insert->payload, insert->name);
675 insert->payload = userdata;
676 return(0);
677 }
678 }
679 if ((insert->name == name) &&
680 (insert->name2 == name2) &&
681 (insert->name3 == name3)) {
682 if (f)
683 f(insert->payload, insert->name);
684 insert->payload = userdata;
685 return(0);
686 }
687 } else {
688 for (insert = &(table->table[key]); insert->next != NULL;
689 insert = insert->next) {
690 if ((xmlStrEqual(insert->name, name)) &&
691 (xmlStrEqual(insert->name2, name2)) &&
692 (xmlStrEqual(insert->name3, name3))) {
693 if (f)
694 f(insert->payload, insert->name);
695 insert->payload = userdata;
696 return(0);
697 }
698 }
Owen Taylor3473f882001-02-23 17:55:21 +0000699 if ((xmlStrEqual(insert->name, name)) &&
700 (xmlStrEqual(insert->name2, name2)) &&
701 (xmlStrEqual(insert->name3, name3))) {
702 if (f)
703 f(insert->payload, insert->name);
704 insert->payload = userdata;
705 return(0);
706 }
707 }
Owen Taylor3473f882001-02-23 17:55:21 +0000708 }
709
Daniel Veillardfdc91562002-07-01 21:52:03 +0000710 if (insert == NULL) {
711 entry = &(table->table[key]);
712 } else {
713 entry = xmlMalloc(sizeof(xmlHashEntry));
714 if (entry == NULL)
715 return(-1);
716 }
717
Daniel Veillard316a5c32005-01-23 22:56:39 +0000718 if (table->dict != NULL) {
719 entry->name = (xmlChar *) name;
720 entry->name2 = (xmlChar *) name2;
721 entry->name3 = (xmlChar *) name3;
722 } else {
723 entry->name = xmlStrdup(name);
724 entry->name2 = xmlStrdup(name2);
725 entry->name3 = xmlStrdup(name3);
726 }
Owen Taylor3473f882001-02-23 17:55:21 +0000727 entry->payload = userdata;
728 entry->next = NULL;
Daniel Veillardfdc91562002-07-01 21:52:03 +0000729 entry->valid = 1;
Owen Taylor3473f882001-02-23 17:55:21 +0000730 table->nbElems++;
731
732
Daniel Veillardfdc91562002-07-01 21:52:03 +0000733 if (insert != NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +0000734 insert->next = entry;
735 }
736 return(0);
737}
738
739/**
Daniel Veillard5e2dace2001-07-18 19:30:27 +0000740 * xmlHashLookup3:
Owen Taylor3473f882001-02-23 17:55:21 +0000741 * @table: the hash table
742 * @name: the name of the userdata
743 * @name2: a second name of the userdata
744 * @name3: a third name of the userdata
745 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000746 * Find the userdata specified by the (@name, @name2, @name3) tuple.
Owen Taylor3473f882001-02-23 17:55:21 +0000747 *
748 * Returns the a pointer to the userdata
749 */
750void *
751xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name,
752 const xmlChar *name2, const xmlChar *name3) {
753 unsigned long key;
754 xmlHashEntryPtr entry;
755
756 if (table == NULL)
757 return(NULL);
758 if (name == NULL)
759 return(NULL);
Daniel Veillarda10efa82001-04-18 13:09:01 +0000760 key = xmlHashComputeKey(table, name, name2, name3);
Daniel Veillardfdc91562002-07-01 21:52:03 +0000761 if (table->table[key].valid == 0)
762 return(NULL);
Daniel Veillard316a5c32005-01-23 22:56:39 +0000763 if (table->dict) {
764 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
765 if ((entry->name == name) &&
766 (entry->name2 == name2) &&
767 (entry->name3 == name3))
768 return(entry->payload);
769 }
770 }
Daniel Veillardfdc91562002-07-01 21:52:03 +0000771 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
Owen Taylor3473f882001-02-23 17:55:21 +0000772 if ((xmlStrEqual(entry->name, name)) &&
773 (xmlStrEqual(entry->name2, name2)) &&
774 (xmlStrEqual(entry->name3, name3)))
775 return(entry->payload);
776 }
777 return(NULL);
778}
779
Daniel Veillarde57ec792003-09-10 10:50:59 +0000780/**
781 * xmlHashQLookup3:
782 * @table: the hash table
783 * @prefix: the prefix of the userdata
784 * @name: the name of the userdata
785 * @prefix2: the second prefix of the userdata
786 * @name2: a second name of the userdata
787 * @prefix3: the third prefix of the userdata
788 * @name3: a third name of the userdata
789 *
790 * Find the userdata specified by the (@name, @name2, @name3) tuple.
791 *
792 * Returns the a pointer to the userdata
793 */
794void *
795xmlHashQLookup3(xmlHashTablePtr table,
796 const xmlChar *prefix, const xmlChar *name,
797 const xmlChar *prefix2, const xmlChar *name2,
798 const xmlChar *prefix3, const xmlChar *name3) {
799 unsigned long key;
800 xmlHashEntryPtr entry;
801
802 if (table == NULL)
803 return(NULL);
804 if (name == NULL)
805 return(NULL);
806 key = xmlHashComputeQKey(table, prefix, name, prefix2,
807 name2, prefix3, name3);
808 if (table->table[key].valid == 0)
809 return(NULL);
810 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
811 if ((xmlStrQEqual(prefix, name, entry->name)) &&
812 (xmlStrQEqual(prefix2, name2, entry->name2)) &&
813 (xmlStrQEqual(prefix3, name3, entry->name3)))
814 return(entry->payload);
815 }
816 return(NULL);
817}
818
Daniel Veillard153120c2002-06-18 07:58:35 +0000819typedef struct {
820 xmlHashScanner hashscanner;
821 void *data;
822} stubData;
823
824static void
825stubHashScannerFull (void *payload, void *data, const xmlChar *name,
Daniel Veillardaeb258a2002-09-13 14:48:12 +0000826 const xmlChar *name2 ATTRIBUTE_UNUSED,
827 const xmlChar *name3 ATTRIBUTE_UNUSED) {
Daniel Veillard153120c2002-06-18 07:58:35 +0000828 stubData *stubdata = (stubData *) data;
829 stubdata->hashscanner (payload, stubdata->data, (xmlChar *) name);
830}
831
Daniel Veillard01c13b52002-12-10 15:19:08 +0000832/**
833 * xmlHashScan:
834 * @table: the hash table
835 * @f: the scanner function for items in the hash
836 * @data: extra data passed to f
837 *
838 * Scan the hash @table and applied @f to each value.
839 */
Owen Taylor3473f882001-02-23 17:55:21 +0000840void
841xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data) {
Daniel Veillard153120c2002-06-18 07:58:35 +0000842 stubData stubdata;
843 stubdata.data = data;
844 stubdata.hashscanner = f;
845 xmlHashScanFull (table, stubHashScannerFull, &stubdata);
Thomas Broyere8126242001-07-22 03:54:15 +0000846}
847
848/**
849 * xmlHashScanFull:
850 * @table: the hash table
851 * @f: the scanner function for items in the hash
852 * @data: extra data passed to f
853 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000854 * Scan the hash @table and applied @f to each value.
Thomas Broyere8126242001-07-22 03:54:15 +0000855 */
856void
857xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data) {
Daniel Veillardac4118d2008-01-11 05:27:32 +0000858 int i, nb;
Owen Taylor3473f882001-02-23 17:55:21 +0000859 xmlHashEntryPtr iter;
860 xmlHashEntryPtr next;
861
862 if (table == NULL)
863 return;
864 if (f == NULL)
865 return;
866
867 if (table->table) {
868 for(i = 0; i < table->size; i++) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000869 if (table->table[i].valid == 0)
870 continue;
871 iter = &(table->table[i]);
Owen Taylor3473f882001-02-23 17:55:21 +0000872 while (iter) {
873 next = iter->next;
Daniel Veillardac4118d2008-01-11 05:27:32 +0000874 nb = table->nbElems;
Daniel Veillarde991fe92003-10-29 11:18:37 +0000875 if ((f != NULL) && (iter->payload != NULL))
Thomas Broyere8126242001-07-22 03:54:15 +0000876 f(iter->payload, data, iter->name,
877 iter->name2, iter->name3);
Daniel Veillardac4118d2008-01-11 05:27:32 +0000878 if (nb != table->nbElems) {
879 /* table was modified by the callback, be careful */
880 if (iter == &(table->table[i])) {
881 if (table->table[i].valid == 0)
882 iter = NULL;
883 if (table->table[i].next != next)
884 iter = &(table->table[i]);
885 } else
886 iter = next;
887 } else
888 iter = next;
Owen Taylor3473f882001-02-23 17:55:21 +0000889 }
890 }
891 }
892}
893
894/**
895 * xmlHashScan3:
896 * @table: the hash table
897 * @name: the name of the userdata or NULL
898 * @name2: a second name of the userdata or NULL
899 * @name3: a third name of the userdata or NULL
900 * @f: the scanner function for items in the hash
901 * @data: extra data passed to f
902 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000903 * Scan the hash @table and applied @f to each value matching
904 * (@name, @name2, @name3) tuple. If one of the names is null,
Owen Taylor3473f882001-02-23 17:55:21 +0000905 * the comparison is considered to match.
906 */
907void
908xmlHashScan3(xmlHashTablePtr table, const xmlChar *name,
909 const xmlChar *name2, const xmlChar *name3,
910 xmlHashScanner f, void *data) {
Thomas Broyere8126242001-07-22 03:54:15 +0000911 xmlHashScanFull3 (table, name, name2, name3,
912 (xmlHashScannerFull) f, data);
913}
914
915/**
916 * xmlHashScanFull3:
917 * @table: the hash table
918 * @name: the name of the userdata or NULL
919 * @name2: a second name of the userdata or NULL
920 * @name3: a third name of the userdata or NULL
921 * @f: the scanner function for items in the hash
922 * @data: extra data passed to f
923 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000924 * Scan the hash @table and applied @f to each value matching
925 * (@name, @name2, @name3) tuple. If one of the names is null,
Thomas Broyere8126242001-07-22 03:54:15 +0000926 * the comparison is considered to match.
927 */
928void
929xmlHashScanFull3(xmlHashTablePtr table, const xmlChar *name,
930 const xmlChar *name2, const xmlChar *name3,
931 xmlHashScannerFull f, void *data) {
Owen Taylor3473f882001-02-23 17:55:21 +0000932 int i;
933 xmlHashEntryPtr iter;
934 xmlHashEntryPtr next;
935
936 if (table == NULL)
937 return;
938 if (f == NULL)
939 return;
940
941 if (table->table) {
942 for(i = 0; i < table->size; i++) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000943 if (table->table[i].valid == 0)
944 continue;
945 iter = &(table->table[i]);
Owen Taylor3473f882001-02-23 17:55:21 +0000946 while (iter) {
947 next = iter->next;
948 if (((name == NULL) || (xmlStrEqual(name, iter->name))) &&
949 ((name2 == NULL) || (xmlStrEqual(name2, iter->name2))) &&
Daniel Veillarde991fe92003-10-29 11:18:37 +0000950 ((name3 == NULL) || (xmlStrEqual(name3, iter->name3))) &&
951 (iter->payload != NULL)) {
Thomas Broyere8126242001-07-22 03:54:15 +0000952 f(iter->payload, data, iter->name,
953 iter->name2, iter->name3);
Owen Taylor3473f882001-02-23 17:55:21 +0000954 }
955 iter = next;
956 }
957 }
958 }
959}
960
961/**
962 * xmlHashCopy:
963 * @table: the hash table
964 * @f: the copier function for items in the hash
965 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000966 * Scan the hash @table and applied @f to each value.
Owen Taylor3473f882001-02-23 17:55:21 +0000967 *
968 * Returns the new table or NULL in case of error.
969 */
970xmlHashTablePtr
971xmlHashCopy(xmlHashTablePtr table, xmlHashCopier f) {
972 int i;
973 xmlHashEntryPtr iter;
974 xmlHashEntryPtr next;
975 xmlHashTablePtr ret;
976
977 if (table == NULL)
978 return(NULL);
979 if (f == NULL)
980 return(NULL);
981
982 ret = xmlHashCreate(table->size);
983 if (table->table) {
984 for(i = 0; i < table->size; i++) {
Daniel Veillardfdc91562002-07-01 21:52:03 +0000985 if (table->table[i].valid == 0)
986 continue;
987 iter = &(table->table[i]);
Owen Taylor3473f882001-02-23 17:55:21 +0000988 while (iter) {
989 next = iter->next;
990 xmlHashAddEntry3(ret, iter->name, iter->name2,
991 iter->name3, f(iter->payload, iter->name));
992 iter = next;
993 }
994 }
995 }
996 ret->nbElems = table->nbElems;
997 return(ret);
998}
999
1000/**
1001 * xmlHashSize:
1002 * @table: the hash table
1003 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001004 * Query the number of elements installed in the hash @table.
Daniel Veillard5e2dace2001-07-18 19:30:27 +00001005 *
Owen Taylor3473f882001-02-23 17:55:21 +00001006 * Returns the number of elements in the hash table or
1007 * -1 in case of error
1008 */
1009int
1010xmlHashSize(xmlHashTablePtr table) {
1011 if (table == NULL)
1012 return(-1);
1013 return(table->nbElems);
1014}
1015
1016/**
Daniel Veillardf69bb4b2001-05-19 13:24:56 +00001017 * xmlHashRemoveEntry:
Owen Taylor3473f882001-02-23 17:55:21 +00001018 * @table: the hash table
1019 * @name: the name of the userdata
1020 * @f: the deallocator function for removed item (if any)
1021 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001022 * Find the userdata specified by the @name and remove
1023 * it from the hash @table. Existing userdata for this tuple will be removed
Owen Taylor3473f882001-02-23 17:55:21 +00001024 * and freed with @f.
1025 *
1026 * Returns 0 if the removal succeeded and -1 in case of error or not found.
1027 */
1028int xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name,
Daniel Veillarda10efa82001-04-18 13:09:01 +00001029 xmlHashDeallocator f) {
1030 return(xmlHashRemoveEntry3(table, name, NULL, NULL, f));
Owen Taylor3473f882001-02-23 17:55:21 +00001031}
1032
1033/**
Daniel Veillardf69bb4b2001-05-19 13:24:56 +00001034 * xmlHashRemoveEntry2:
Owen Taylor3473f882001-02-23 17:55:21 +00001035 * @table: the hash table
1036 * @name: the name of the userdata
1037 * @name2: a second name of the userdata
1038 * @f: the deallocator function for removed item (if any)
1039 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001040 * Find the userdata specified by the (@name, @name2) tuple and remove
1041 * it from the hash @table. Existing userdata for this tuple will be removed
Owen Taylor3473f882001-02-23 17:55:21 +00001042 * and freed with @f.
1043 *
1044 * Returns 0 if the removal succeeded and -1 in case of error or not found.
1045 */
Daniel Veillard01c13b52002-12-10 15:19:08 +00001046int
1047xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name,
Daniel Veillarda10efa82001-04-18 13:09:01 +00001048 const xmlChar *name2, xmlHashDeallocator f) {
1049 return(xmlHashRemoveEntry3(table, name, name2, NULL, f));
Owen Taylor3473f882001-02-23 17:55:21 +00001050}
1051
1052/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00001053 * xmlHashRemoveEntry3:
Owen Taylor3473f882001-02-23 17:55:21 +00001054 * @table: the hash table
1055 * @name: the name of the userdata
1056 * @name2: a second name of the userdata
1057 * @name3: a third name of the userdata
1058 * @f: the deallocator function for removed item (if any)
1059 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001060 * Find the userdata specified by the (@name, @name2, @name3) tuple and remove
1061 * it from the hash @table. Existing userdata for this tuple will be removed
Owen Taylor3473f882001-02-23 17:55:21 +00001062 * and freed with @f.
1063 *
1064 * Returns 0 if the removal succeeded and -1 in case of error or not found.
1065 */
Daniel Veillard01c13b52002-12-10 15:19:08 +00001066int
1067xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name,
Daniel Veillarda10efa82001-04-18 13:09:01 +00001068 const xmlChar *name2, const xmlChar *name3, xmlHashDeallocator f) {
1069 unsigned long key;
1070 xmlHashEntryPtr entry;
1071 xmlHashEntryPtr prev = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +00001072
Daniel Veillarda10efa82001-04-18 13:09:01 +00001073 if (table == NULL || name == NULL)
1074 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001075
Daniel Veillarda10efa82001-04-18 13:09:01 +00001076 key = xmlHashComputeKey(table, name, name2, name3);
Daniel Veillardfdc91562002-07-01 21:52:03 +00001077 if (table->table[key].valid == 0) {
Daniel Veillarda10efa82001-04-18 13:09:01 +00001078 return(-1);
1079 } else {
Daniel Veillardfdc91562002-07-01 21:52:03 +00001080 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
Daniel Veillarda10efa82001-04-18 13:09:01 +00001081 if (xmlStrEqual(entry->name, name) &&
1082 xmlStrEqual(entry->name2, name2) &&
1083 xmlStrEqual(entry->name3, name3)) {
Daniel Veillarde991fe92003-10-29 11:18:37 +00001084 if ((f != NULL) && (entry->payload != NULL))
Daniel Veillarda10efa82001-04-18 13:09:01 +00001085 f(entry->payload, entry->name);
1086 entry->payload = NULL;
Daniel Veillard316a5c32005-01-23 22:56:39 +00001087 if (table->dict == NULL) {
1088 if(entry->name)
1089 xmlFree(entry->name);
1090 if(entry->name2)
1091 xmlFree(entry->name2);
1092 if(entry->name3)
1093 xmlFree(entry->name3);
1094 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00001095 if(prev) {
Daniel Veillarda10efa82001-04-18 13:09:01 +00001096 prev->next = entry->next;
Daniel Veillardfdc91562002-07-01 21:52:03 +00001097 xmlFree(entry);
1098 } else {
1099 if (entry->next == NULL) {
1100 entry->valid = 0;
1101 } else {
1102 entry = entry->next;
1103 memcpy(&(table->table[key]), entry, sizeof(xmlHashEntry));
1104 xmlFree(entry);
1105 }
1106 }
Daniel Veillarda10efa82001-04-18 13:09:01 +00001107 table->nbElems--;
1108 return(0);
1109 }
1110 prev = entry;
1111 }
1112 return(-1);
1113 }
Daniel Veillard9e7160d2001-03-18 23:17:47 +00001114}
1115
Daniel Veillard5d4644e2005-04-01 13:11:58 +00001116#define bottom_hash
1117#include "elfgcchack.h"