Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhash.c
Go to the documentation of this file.
00001 /* 00002 * hash.c: chained hash tables 00003 * 00004 * Reference: Your favorite introductory book on algorithms 00005 * 00006 * Copyright (C) 2000 Bjorn Reese and Daniel Veillard. 00007 * 00008 * Permission to use, copy, modify, and distribute this software for any 00009 * purpose with or without fee is hereby granted, provided that the above 00010 * copyright notice and this permission notice appear in all copies. 00011 * 00012 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 00013 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 00014 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND 00015 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. 00016 * 00017 * Author: breese@users.sourceforge.net 00018 */ 00019 00020 #define IN_LIBXML 00021 #include "libxml.h" 00022 00023 #include <string.h> 00024 #include <libxml/parser.h> 00025 #include <libxml/hash.h> 00026 #include <libxml/xmlmemory.h> 00027 #include <libxml/xmlerror.h> 00028 #include <libxml/globals.h> 00029 00030 #define MAX_HASH_LEN 8 00031 00032 /* #define DEBUG_GROW */ 00033 00034 /* 00035 * A single entry in the hash table 00036 */ 00037 typedef struct _xmlHashEntry xmlHashEntry; 00038 typedef xmlHashEntry *xmlHashEntryPtr; 00039 struct _xmlHashEntry { 00040 struct _xmlHashEntry *next; 00041 xmlChar *name; 00042 xmlChar *name2; 00043 xmlChar *name3; 00044 void *payload; 00045 int valid; 00046 }; 00047 00048 /* 00049 * The entire hash table 00050 */ 00051 struct _xmlHashTable { 00052 struct _xmlHashEntry *table; 00053 int size; 00054 int nbElems; 00055 xmlDictPtr dict; 00056 }; 00057 00058 /* 00059 * xmlHashComputeKey: 00060 * Calculate the hash key 00061 */ 00062 static unsigned long 00063 xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name, 00064 const xmlChar *name2, const xmlChar *name3) { 00065 unsigned long value = 0L; 00066 char ch; 00067 00068 if (name != NULL) { 00069 value += 30 * (*name); 00070 while ((ch = *name++) != 0) { 00071 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); 00072 } 00073 } 00074 if (name2 != NULL) { 00075 while ((ch = *name2++) != 0) { 00076 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); 00077 } 00078 } 00079 if (name3 != NULL) { 00080 while ((ch = *name3++) != 0) { 00081 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); 00082 } 00083 } 00084 return (value % table->size); 00085 } 00086 00087 static unsigned long 00088 xmlHashComputeQKey(xmlHashTablePtr table, 00089 const xmlChar *prefix, const xmlChar *name, 00090 const xmlChar *prefix2, const xmlChar *name2, 00091 const xmlChar *prefix3, const xmlChar *name3) { 00092 unsigned long value = 0L; 00093 char ch; 00094 00095 if (prefix != NULL) 00096 value += 30 * (*prefix); 00097 else 00098 value += 30 * (*name); 00099 00100 if (prefix != NULL) { 00101 while ((ch = *prefix++) != 0) { 00102 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); 00103 } 00104 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':'); 00105 } 00106 if (name != NULL) { 00107 while ((ch = *name++) != 0) { 00108 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); 00109 } 00110 } 00111 if (prefix2 != NULL) { 00112 while ((ch = *prefix2++) != 0) { 00113 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); 00114 } 00115 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':'); 00116 } 00117 if (name2 != NULL) { 00118 while ((ch = *name2++) != 0) { 00119 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); 00120 } 00121 } 00122 if (prefix3 != NULL) { 00123 while ((ch = *prefix3++) != 0) { 00124 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); 00125 } 00126 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':'); 00127 } 00128 if (name3 != NULL) { 00129 while ((ch = *name3++) != 0) { 00130 value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); 00131 } 00132 } 00133 return (value % table->size); 00134 } 00135 00144 xmlHashTablePtr 00145 xmlHashCreate(int size) { 00146 xmlHashTablePtr table; 00147 00148 if (size <= 0) 00149 size = 256; 00150 00151 table = xmlMalloc(sizeof(xmlHashTable)); 00152 if (table) { 00153 table->dict = NULL; 00154 table->size = size; 00155 table->nbElems = 0; 00156 table->table = xmlMalloc(size * sizeof(xmlHashEntry)); 00157 if (table->table) { 00158 memset(table->table, 0, size * sizeof(xmlHashEntry)); 00159 return(table); 00160 } 00161 xmlFree(table); 00162 } 00163 return(NULL); 00164 } 00165 00175 xmlHashTablePtr 00176 xmlHashCreateDict(int size, xmlDictPtr dict) { 00177 xmlHashTablePtr table; 00178 00179 table = xmlHashCreate(size); 00180 if (table != NULL) { 00181 table->dict = dict; 00182 xmlDictReference(dict); 00183 } 00184 return(table); 00185 } 00186 00196 static int 00197 xmlHashGrow(xmlHashTablePtr table, int size) { 00198 unsigned long key; 00199 int oldsize, i; 00200 xmlHashEntryPtr iter, next; 00201 struct _xmlHashEntry *oldtable; 00202 #ifdef DEBUG_GROW 00203 unsigned long nbElem = 0; 00204 #endif 00205 00206 if (table == NULL) 00207 return(-1); 00208 if (size < 8) 00209 return(-1); 00210 if (size > 8 * 2048) 00211 return(-1); 00212 00213 oldsize = table->size; 00214 oldtable = table->table; 00215 if (oldtable == NULL) 00216 return(-1); 00217 00218 table->table = xmlMalloc(size * sizeof(xmlHashEntry)); 00219 if (table->table == NULL) { 00220 table->table = oldtable; 00221 return(-1); 00222 } 00223 memset(table->table, 0, size * sizeof(xmlHashEntry)); 00224 table->size = size; 00225 00226 /* If the two loops are merged, there would be situations where 00227 a new entry needs to allocated and data copied into it from 00228 the main table. So instead, we run through the array twice, first 00229 copying all the elements in the main array (where we can't get 00230 conflicts) and then the rest, so we only free (and don't allocate) 00231 */ 00232 for (i = 0; i < oldsize; i++) { 00233 if (oldtable[i].valid == 0) 00234 continue; 00235 key = xmlHashComputeKey(table, oldtable[i].name, oldtable[i].name2, 00236 oldtable[i].name3); 00237 memcpy(&(table->table[key]), &(oldtable[i]), sizeof(xmlHashEntry)); 00238 table->table[key].next = NULL; 00239 } 00240 00241 for (i = 0; i < oldsize; i++) { 00242 iter = oldtable[i].next; 00243 while (iter) { 00244 next = iter->next; 00245 00246 /* 00247 * put back the entry in the new table 00248 */ 00249 00250 key = xmlHashComputeKey(table, iter->name, iter->name2, 00251 iter->name3); 00252 if (table->table[key].valid == 0) { 00253 memcpy(&(table->table[key]), iter, sizeof(xmlHashEntry)); 00254 table->table[key].next = NULL; 00255 xmlFree(iter); 00256 } else { 00257 iter->next = table->table[key].next; 00258 table->table[key].next = iter; 00259 } 00260 00261 #ifdef DEBUG_GROW 00262 nbElem++; 00263 #endif 00264 00265 iter = next; 00266 } 00267 } 00268 00269 xmlFree(oldtable); 00270 00271 #ifdef DEBUG_GROW 00272 xmlGenericError(xmlGenericErrorContext, 00273 "xmlHashGrow : from %d to %d, %d elems\n", oldsize, size, nbElem); 00274 #endif 00275 00276 return(0); 00277 } 00278 00287 void 00288 xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) { 00289 int i; 00290 xmlHashEntryPtr iter; 00291 xmlHashEntryPtr next; 00292 int inside_table = 0; 00293 int nbElems; 00294 00295 if (table == NULL) 00296 return; 00297 if (table->table) { 00298 nbElems = table->nbElems; 00299 for(i = 0; (i < table->size) && (nbElems > 0); i++) { 00300 iter = &(table->table[i]); 00301 if (iter->valid == 0) 00302 continue; 00303 inside_table = 1; 00304 while (iter) { 00305 next = iter->next; 00306 if ((f != NULL) && (iter->payload != NULL)) 00307 f(iter->payload, iter->name); 00308 if (table->dict == NULL) { 00309 if (iter->name) 00310 xmlFree(iter->name); 00311 if (iter->name2) 00312 xmlFree(iter->name2); 00313 if (iter->name3) 00314 xmlFree(iter->name3); 00315 } 00316 iter->payload = NULL; 00317 if (!inside_table) 00318 xmlFree(iter); 00319 nbElems--; 00320 inside_table = 0; 00321 iter = next; 00322 } 00323 } 00324 xmlFree(table->table); 00325 } 00326 if (table->dict) 00327 xmlDictFree(table->dict); 00328 xmlFree(table); 00329 } 00330 00342 int 00343 xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata) { 00344 return(xmlHashAddEntry3(table, name, NULL, NULL, userdata)); 00345 } 00346 00359 int 00360 xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, 00361 const xmlChar *name2, void *userdata) { 00362 return(xmlHashAddEntry3(table, name, name2, NULL, userdata)); 00363 } 00364 00378 int 00379 xmlHashUpdateEntry(xmlHashTablePtr table, const xmlChar *name, 00380 void *userdata, xmlHashDeallocator f) { 00381 return(xmlHashUpdateEntry3(table, name, NULL, NULL, userdata, f)); 00382 } 00383 00398 int 00399 xmlHashUpdateEntry2(xmlHashTablePtr table, const xmlChar *name, 00400 const xmlChar *name2, void *userdata, 00401 xmlHashDeallocator f) { 00402 return(xmlHashUpdateEntry3(table, name, name2, NULL, userdata, f)); 00403 } 00404 00414 void * 00415 xmlHashLookup(xmlHashTablePtr table, const xmlChar *name) { 00416 return(xmlHashLookup3(table, name, NULL, NULL)); 00417 } 00418 00429 void * 00430 xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, 00431 const xmlChar *name2) { 00432 return(xmlHashLookup3(table, name, name2, NULL)); 00433 } 00434 00445 void * 00446 xmlHashQLookup(xmlHashTablePtr table, const xmlChar *prefix, 00447 const xmlChar *name) { 00448 return(xmlHashQLookup3(table, prefix, name, NULL, NULL, NULL, NULL)); 00449 } 00450 00463 void * 00464 xmlHashQLookup2(xmlHashTablePtr table, const xmlChar *prefix, 00465 const xmlChar *name, const xmlChar *prefix2, 00466 const xmlChar *name2) { 00467 return(xmlHashQLookup3(table, prefix, name, prefix2, name2, NULL, NULL)); 00468 } 00469 00484 int 00485 xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name, 00486 const xmlChar *name2, const xmlChar *name3, 00487 void *userdata) { 00488 unsigned long key, len = 0; 00489 xmlHashEntryPtr entry; 00490 xmlHashEntryPtr insert; 00491 00492 if ((table == NULL) || (name == NULL)) 00493 return(-1); 00494 00495 /* 00496 * If using a dict internalize if needed 00497 */ 00498 if (table->dict) { 00499 if (!xmlDictOwns(table->dict, name)) { 00500 name = xmlDictLookup(table->dict, name, -1); 00501 if (name == NULL) 00502 return(-1); 00503 } 00504 if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) { 00505 name2 = xmlDictLookup(table->dict, name2, -1); 00506 if (name2 == NULL) 00507 return(-1); 00508 } 00509 if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) { 00510 name3 = xmlDictLookup(table->dict, name3, -1); 00511 if (name3 == NULL) 00512 return(-1); 00513 } 00514 } 00515 00516 /* 00517 * Check for duplicate and insertion location. 00518 */ 00519 key = xmlHashComputeKey(table, name, name2, name3); 00520 if (table->table[key].valid == 0) { 00521 insert = NULL; 00522 } else { 00523 if (table->dict) { 00524 for (insert = &(table->table[key]); insert->next != NULL; 00525 insert = insert->next) { 00526 if ((insert->name == name) && 00527 (insert->name2 == name2) && 00528 (insert->name3 == name3)) 00529 return(-1); 00530 len++; 00531 } 00532 if ((insert->name == name) && 00533 (insert->name2 == name2) && 00534 (insert->name3 == name3)) 00535 return(-1); 00536 } else { 00537 for (insert = &(table->table[key]); insert->next != NULL; 00538 insert = insert->next) { 00539 if ((xmlStrEqual(insert->name, name)) && 00540 (xmlStrEqual(insert->name2, name2)) && 00541 (xmlStrEqual(insert->name3, name3))) 00542 return(-1); 00543 len++; 00544 } 00545 if ((xmlStrEqual(insert->name, name)) && 00546 (xmlStrEqual(insert->name2, name2)) && 00547 (xmlStrEqual(insert->name3, name3))) 00548 return(-1); 00549 } 00550 } 00551 00552 if (insert == NULL) { 00553 entry = &(table->table[key]); 00554 } else { 00555 entry = xmlMalloc(sizeof(xmlHashEntry)); 00556 if (entry == NULL) 00557 return(-1); 00558 } 00559 00560 if (table->dict != NULL) { 00561 entry->name = (xmlChar *) name; 00562 entry->name2 = (xmlChar *) name2; 00563 entry->name3 = (xmlChar *) name3; 00564 } else { 00565 entry->name = xmlStrdup(name); 00566 entry->name2 = xmlStrdup(name2); 00567 entry->name3 = xmlStrdup(name3); 00568 } 00569 entry->payload = userdata; 00570 entry->next = NULL; 00571 entry->valid = 1; 00572 00573 00574 if (insert != NULL) 00575 insert->next = entry; 00576 00577 table->nbElems++; 00578 00579 if (len > MAX_HASH_LEN) 00580 xmlHashGrow(table, MAX_HASH_LEN * table->size); 00581 00582 return(0); 00583 } 00584 00600 int 00601 xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name, 00602 const xmlChar *name2, const xmlChar *name3, 00603 void *userdata, xmlHashDeallocator f) { 00604 unsigned long key; 00605 xmlHashEntryPtr entry; 00606 xmlHashEntryPtr insert; 00607 00608 if ((table == NULL) || name == NULL) 00609 return(-1); 00610 00611 /* 00612 * If using a dict internalize if needed 00613 */ 00614 if (table->dict) { 00615 if (!xmlDictOwns(table->dict, name)) { 00616 name = xmlDictLookup(table->dict, name, -1); 00617 if (name == NULL) 00618 return(-1); 00619 } 00620 if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) { 00621 name2 = xmlDictLookup(table->dict, name2, -1); 00622 if (name2 == NULL) 00623 return(-1); 00624 } 00625 if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) { 00626 name3 = xmlDictLookup(table->dict, name3, -1); 00627 if (name3 == NULL) 00628 return(-1); 00629 } 00630 } 00631 00632 /* 00633 * Check for duplicate and insertion location. 00634 */ 00635 key = xmlHashComputeKey(table, name, name2, name3); 00636 if (table->table[key].valid == 0) { 00637 insert = NULL; 00638 } else { 00639 if (table ->dict) { 00640 for (insert = &(table->table[key]); insert->next != NULL; 00641 insert = insert->next) { 00642 if ((insert->name == name) && 00643 (insert->name2 == name2) && 00644 (insert->name3 == name3)) { 00645 if (f) 00646 f(insert->payload, insert->name); 00647 insert->payload = userdata; 00648 return(0); 00649 } 00650 } 00651 if ((insert->name == name) && 00652 (insert->name2 == name2) && 00653 (insert->name3 == name3)) { 00654 if (f) 00655 f(insert->payload, insert->name); 00656 insert->payload = userdata; 00657 return(0); 00658 } 00659 } else { 00660 for (insert = &(table->table[key]); insert->next != NULL; 00661 insert = insert->next) { 00662 if ((xmlStrEqual(insert->name, name)) && 00663 (xmlStrEqual(insert->name2, name2)) && 00664 (xmlStrEqual(insert->name3, name3))) { 00665 if (f) 00666 f(insert->payload, insert->name); 00667 insert->payload = userdata; 00668 return(0); 00669 } 00670 } 00671 if ((xmlStrEqual(insert->name, name)) && 00672 (xmlStrEqual(insert->name2, name2)) && 00673 (xmlStrEqual(insert->name3, name3))) { 00674 if (f) 00675 f(insert->payload, insert->name); 00676 insert->payload = userdata; 00677 return(0); 00678 } 00679 } 00680 } 00681 00682 if (insert == NULL) { 00683 entry = &(table->table[key]); 00684 } else { 00685 entry = xmlMalloc(sizeof(xmlHashEntry)); 00686 if (entry == NULL) 00687 return(-1); 00688 } 00689 00690 if (table->dict != NULL) { 00691 entry->name = (xmlChar *) name; 00692 entry->name2 = (xmlChar *) name2; 00693 entry->name3 = (xmlChar *) name3; 00694 } else { 00695 entry->name = xmlStrdup(name); 00696 entry->name2 = xmlStrdup(name2); 00697 entry->name3 = xmlStrdup(name3); 00698 } 00699 entry->payload = userdata; 00700 entry->next = NULL; 00701 entry->valid = 1; 00702 table->nbElems++; 00703 00704 00705 if (insert != NULL) { 00706 insert->next = entry; 00707 } 00708 return(0); 00709 } 00710 00722 void * 00723 xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name, 00724 const xmlChar *name2, const xmlChar *name3) { 00725 unsigned long key; 00726 xmlHashEntryPtr entry; 00727 00728 if (table == NULL) 00729 return(NULL); 00730 if (name == NULL) 00731 return(NULL); 00732 key = xmlHashComputeKey(table, name, name2, name3); 00733 if (table->table[key].valid == 0) 00734 return(NULL); 00735 if (table->dict) { 00736 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { 00737 if ((entry->name == name) && 00738 (entry->name2 == name2) && 00739 (entry->name3 == name3)) 00740 return(entry->payload); 00741 } 00742 } 00743 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { 00744 if ((xmlStrEqual(entry->name, name)) && 00745 (xmlStrEqual(entry->name2, name2)) && 00746 (xmlStrEqual(entry->name3, name3))) 00747 return(entry->payload); 00748 } 00749 return(NULL); 00750 } 00751 00766 void * 00767 xmlHashQLookup3(xmlHashTablePtr table, 00768 const xmlChar *prefix, const xmlChar *name, 00769 const xmlChar *prefix2, const xmlChar *name2, 00770 const xmlChar *prefix3, const xmlChar *name3) { 00771 unsigned long key; 00772 xmlHashEntryPtr entry; 00773 00774 if (table == NULL) 00775 return(NULL); 00776 if (name == NULL) 00777 return(NULL); 00778 key = xmlHashComputeQKey(table, prefix, name, prefix2, 00779 name2, prefix3, name3); 00780 if (table->table[key].valid == 0) 00781 return(NULL); 00782 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { 00783 if ((xmlStrQEqual(prefix, name, entry->name)) && 00784 (xmlStrQEqual(prefix2, name2, entry->name2)) && 00785 (xmlStrQEqual(prefix3, name3, entry->name3))) 00786 return(entry->payload); 00787 } 00788 return(NULL); 00789 } 00790 00791 typedef struct { 00792 xmlHashScanner hashscanner; 00793 void *data; 00794 } stubData; 00795 00796 static void 00797 stubHashScannerFull (void *payload, void *data, const xmlChar *name, 00798 const xmlChar *name2 ATTRIBUTE_UNUSED, 00799 const xmlChar *name3 ATTRIBUTE_UNUSED) { 00800 stubData *stubdata = (stubData *) data; 00801 stubdata->hashscanner (payload, stubdata->data, (xmlChar *) name); 00802 } 00803 00812 void 00813 xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data) { 00814 stubData stubdata; 00815 stubdata.data = data; 00816 stubdata.hashscanner = f; 00817 xmlHashScanFull (table, stubHashScannerFull, &stubdata); 00818 } 00819 00828 void 00829 xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data) { 00830 int i, nb; 00831 xmlHashEntryPtr iter; 00832 xmlHashEntryPtr next; 00833 00834 if (table == NULL) 00835 return; 00836 if (f == NULL) 00837 return; 00838 00839 if (table->table) { 00840 for(i = 0; i < table->size; i++) { 00841 if (table->table[i].valid == 0) 00842 continue; 00843 iter = &(table->table[i]); 00844 while (iter) { 00845 next = iter->next; 00846 nb = table->nbElems; 00847 if ((f != NULL) && (iter->payload != NULL)) 00848 f(iter->payload, data, iter->name, 00849 iter->name2, iter->name3); 00850 if (nb != table->nbElems) { 00851 /* table was modified by the callback, be careful */ 00852 if (iter == &(table->table[i])) { 00853 if (table->table[i].valid == 0) 00854 iter = NULL; 00855 if (table->table[i].next != next) 00856 iter = &(table->table[i]); 00857 } else 00858 iter = next; 00859 } else 00860 iter = next; 00861 } 00862 } 00863 } 00864 } 00865 00879 void 00880 xmlHashScan3(xmlHashTablePtr table, const xmlChar *name, 00881 const xmlChar *name2, const xmlChar *name3, 00882 xmlHashScanner f, void *data) { 00883 xmlHashScanFull3 (table, name, name2, name3, 00884 (xmlHashScannerFull) f, data); 00885 } 00886 00900 void 00901 xmlHashScanFull3(xmlHashTablePtr table, const xmlChar *name, 00902 const xmlChar *name2, const xmlChar *name3, 00903 xmlHashScannerFull f, void *data) { 00904 int i; 00905 xmlHashEntryPtr iter; 00906 xmlHashEntryPtr next; 00907 00908 if (table == NULL) 00909 return; 00910 if (f == NULL) 00911 return; 00912 00913 if (table->table) { 00914 for(i = 0; i < table->size; i++) { 00915 if (table->table[i].valid == 0) 00916 continue; 00917 iter = &(table->table[i]); 00918 while (iter) { 00919 next = iter->next; 00920 if (((name == NULL) || (xmlStrEqual(name, iter->name))) && 00921 ((name2 == NULL) || (xmlStrEqual(name2, iter->name2))) && 00922 ((name3 == NULL) || (xmlStrEqual(name3, iter->name3))) && 00923 (iter->payload != NULL)) { 00924 f(iter->payload, data, iter->name, 00925 iter->name2, iter->name3); 00926 } 00927 iter = next; 00928 } 00929 } 00930 } 00931 } 00932 00942 xmlHashTablePtr 00943 xmlHashCopy(xmlHashTablePtr table, xmlHashCopier f) { 00944 int i; 00945 xmlHashEntryPtr iter; 00946 xmlHashEntryPtr next; 00947 xmlHashTablePtr ret; 00948 00949 if (table == NULL) 00950 return(NULL); 00951 if (f == NULL) 00952 return(NULL); 00953 00954 ret = xmlHashCreate(table->size); 00955 if (table->table) { 00956 for(i = 0; i < table->size; i++) { 00957 if (table->table[i].valid == 0) 00958 continue; 00959 iter = &(table->table[i]); 00960 while (iter) { 00961 next = iter->next; 00962 xmlHashAddEntry3(ret, iter->name, iter->name2, 00963 iter->name3, f(iter->payload, iter->name)); 00964 iter = next; 00965 } 00966 } 00967 } 00968 ret->nbElems = table->nbElems; 00969 return(ret); 00970 } 00971 00981 int 00982 xmlHashSize(xmlHashTablePtr table) { 00983 if (table == NULL) 00984 return(-1); 00985 return(table->nbElems); 00986 } 00987 01000 int xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, 01001 xmlHashDeallocator f) { 01002 return(xmlHashRemoveEntry3(table, name, NULL, NULL, f)); 01003 } 01004 01018 int 01019 xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name, 01020 const xmlChar *name2, xmlHashDeallocator f) { 01021 return(xmlHashRemoveEntry3(table, name, name2, NULL, f)); 01022 } 01023 01038 int 01039 xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name, 01040 const xmlChar *name2, const xmlChar *name3, xmlHashDeallocator f) { 01041 unsigned long key; 01042 xmlHashEntryPtr entry; 01043 xmlHashEntryPtr prev = NULL; 01044 01045 if (table == NULL || name == NULL) 01046 return(-1); 01047 01048 key = xmlHashComputeKey(table, name, name2, name3); 01049 if (table->table[key].valid == 0) { 01050 return(-1); 01051 } else { 01052 for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { 01053 if (xmlStrEqual(entry->name, name) && 01054 xmlStrEqual(entry->name2, name2) && 01055 xmlStrEqual(entry->name3, name3)) { 01056 if ((f != NULL) && (entry->payload != NULL)) 01057 f(entry->payload, entry->name); 01058 entry->payload = NULL; 01059 if (table->dict == NULL) { 01060 if(entry->name) 01061 xmlFree(entry->name); 01062 if(entry->name2) 01063 xmlFree(entry->name2); 01064 if(entry->name3) 01065 xmlFree(entry->name3); 01066 } 01067 if(prev) { 01068 prev->next = entry->next; 01069 xmlFree(entry); 01070 } else { 01071 if (entry->next == NULL) { 01072 entry->valid = 0; 01073 } else { 01074 entry = entry->next; 01075 memcpy(&(table->table[key]), entry, sizeof(xmlHashEntry)); 01076 xmlFree(entry); 01077 } 01078 } 01079 table->nbElems--; 01080 return(0); 01081 } 01082 prev = entry; 01083 } 01084 return(-1); 01085 } 01086 } 01087 01088 #define bottom_hash 01089 #include "elfgcchack.h" Generated on Sun May 27 2012 04:20:18 for ReactOS by
1.7.6.1
|