Annotation of XML/hash.c, revision 1.2
1.1 veillard 1: /*
2: * hash.c: chained hash tables
3: *
4: * Reference: Your favorite introductory book on algorithms
5: *
6: * Copyright (C) 2000 Bjorn Reese and Daniel Veillard.
7: *
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: *
17: * Author: bjorn.reese@systematic.dk
18: */
19:
20: #include <libxml/hash.h>
21: #include <libxml/xmlmemory.h>
22: #include <libxml/parser.h>
23:
24: /*
25: * xmlHashComputeKey:
26: * Calculate the hash key
27: */
28: static unsigned long
29: xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *string) {
30: unsigned long value = 0L;
31: char ch;
32:
33: while ((ch = *string++) != 0) {
34: /* value *= 31; */
35: value += (unsigned long)ch;
36: }
37: return (value % table->size);
38: }
39:
40: /**
41: * xmlHashCreate:
42: * @size: the size of the hash table
43: *
44: * Create a new xmlHashTablePtr.
45: *
46: * Returns the newly created object, or NULL if an error occured.
47: */
48: xmlHashTablePtr
49: xmlHashCreate(int size) {
50: xmlHashTablePtr table;
51:
52: if (size <= 0)
53: size = 256;
54:
55: table = xmlMalloc(sizeof(xmlHashTable));
56: if (table) {
57: table->size = size;
58: table->table = xmlMalloc(size * sizeof(xmlHashEntry));
59: if (table->table) {
60: memset(table->table, 0, size * sizeof(xmlHashEntry));
61: return(table);
62: }
63: xmlFree(table);
64: }
65: return(NULL);
66: }
67:
68: /**
69: * xmlHashFree:
70: * @table: the hash table
71: * @f: the deallocator function for items in the hash
72: *
73: * Free the hash table and its contents. The userdata is
74: * deallocated with f if provided.
75: */
76: void
77: xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) {
78: int i;
79: xmlHashEntryPtr iter;
80: xmlHashEntryPtr next;
81:
82: if (table == NULL)
83: return;
84: if (table->table) {
85: for(i = 0; i < table->size; i++) {
86: iter = table->table[i];
87: while (iter) {
88: next = iter->next;
89: if (iter->name)
90: xmlFree(iter->name);
91: if (f)
92: f(iter->payload);
93: iter->payload = NULL;
94: xmlFree(iter);
95: iter = next;
96: }
97: table->table[i] = NULL;
98: }
99: xmlFree(table->table);
100: }
101: xmlFree(table);
102: }
103:
104: /**
105: * xmlHashAddEntry:
106: * @table: the hash table
107: * @name: the name of the userdata
108: * @userdata: a pointer to the userdata
109: *
110: * Add the userdata to the hash table. This can later be retrieved
111: * by using the name. Duplicate names generate errors.
112: *
113: * Returns 0 the addition succeeded and -1 in case of error.
114: */
115: int
116: xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata) {
117: unsigned long key;
118: xmlHashEntryPtr entry;
119: xmlHashEntryPtr insert;
120:
121: if ((table == NULL) || name == NULL)
122: return(-1);
123:
124: /*
125: * Check for duplicate and insertion location.
126: */
127: key = xmlHashComputeKey(table, name);
128: if (table->table[key] == NULL) {
129: insert = NULL;
130: } else {
131: for (insert = table->table[key]; insert->next != NULL;
132: insert = insert->next) {
133: if (xmlStrEqual(insert->name, name))
134: return(-1);
135: }
136: if (xmlStrEqual(insert->name, name))
137: return(-1);
138: }
139:
140: entry = xmlMalloc(sizeof(xmlHashEntry));
141: if (entry == NULL)
142: return(-1);
143: entry->name = xmlStrdup(name);
144: entry->payload = userdata;
145: entry->next = NULL;
146:
147:
148: if (insert == NULL) {
149: table->table[key] = entry;
150: } else {
151: insert->next = entry;
152: }
153: return(0);
154: }
155:
156: /**
157: * xmlHashUpdateEntry:
158: * @table: the hash table
159: * @name: the name of the userdata
160: * @userdata: a pointer to the userdata
161: * @f: the deallocator function for replaced item (if any)
162: *
163: * Add the userdata to the hash table. This can later be retrieved
164: * by using the name. Existing entry for this name will be removed
165: * and freed with @f if found.
166: *
167: * Returns 0 the addition succeeded and -1 in case of error.
168: */
169: int
170: xmlHashUpdateEntry(xmlHashTablePtr table, const xmlChar *name,
171: void *userdata, xmlHashDeallocator f) {
172: unsigned long key;
173: xmlHashEntryPtr entry;
174: xmlHashEntryPtr insert;
175:
176: if ((table == NULL) || name == NULL)
177: return(-1);
178:
179: /*
180: * Check for duplicate and insertion location.
181: */
182: key = xmlHashComputeKey(table, name);
183: if (table->table[key] == NULL) {
184: insert = NULL;
185: } else {
186: for (insert = table->table[key]; insert->next != NULL;
187: insert = insert->next) {
188: if (xmlStrEqual(insert->name, name)) {
189: if (f)
190: f(insert->payload);
191: insert->payload = userdata;
192: return(0);
193: }
194: }
195: if (xmlStrEqual(insert->name, name)) {
196: if (f)
197: f(insert->payload);
198: insert->payload = userdata;
199: return(0);
200: }
201: }
202:
203: entry = xmlMalloc(sizeof(xmlHashEntry));
204: if (entry == NULL)
205: return(-1);
206: entry->name = xmlStrdup(name);
207: entry->payload = userdata;
208: entry->next = NULL;
209:
210:
211: if (insert == NULL) {
212: table->table[key] = entry;
213: } else {
214: insert->next = entry;
215: }
216: return(0);
217: }
218:
219: /**
220: * xmlHashLookup:
221: * @table: the hash table
222: * @name: the name of the userdata
223: *
224: * Find the userdata specified by the name.
225: *
226: * Returns the a pointer to the userdata
227: */
228: void *
229: xmlHashLookup(xmlHashTablePtr table, const xmlChar *name) {
230: unsigned long key;
231: xmlHashEntryPtr entry;
232:
233: if (table == NULL)
234: return(NULL);
235: if (name == NULL)
236: return(NULL);
237: key = xmlHashComputeKey(table, name);
238: for (entry = table->table[key]; entry != NULL; entry = entry->next) {
239: if (xmlStrEqual(name, entry->name))
240: return(entry->payload);
241: }
242: return(NULL);
243: }
1.2 ! veillard 244:
! 245: /**
! 246: * xmlHashScan:
! 247: * @table: the hash table
! 248: * @f: the scanner function for items in the hash
! 249: * @data: extra data passed to f
! 250: *
! 251: * Scan the hash table and applied f to each value.
! 252: */
! 253: void
! 254: xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data) {
! 255: int i;
! 256: xmlHashEntryPtr iter;
! 257: xmlHashEntryPtr next;
! 258:
! 259: if (table == NULL)
! 260: return;
! 261: if (f == NULL)
! 262: return;
! 263:
! 264: if (table->table) {
! 265: for(i = 0; i < table->size; i++) {
! 266: iter = table->table[i];
! 267: while (iter) {
! 268: next = iter->next;
! 269: if (f)
! 270: f(iter->payload, data);
! 271: iter = next;
! 272: }
! 273: }
! 274: }
! 275: }
! 276:
! 277: /**
! 278: * xmlHashCopy:
! 279: * @table: the hash table
! 280: * @f: the copier function for items in the hash
! 281: *
! 282: * Scan the hash table and applied f to each value.
! 283: *
! 284: * Returns the new table or NULL in case of error.
! 285: */
! 286: xmlHashTablePtr
! 287: xmlHashCopy(xmlHashTablePtr table, xmlHashCopier f) {
! 288: int i;
! 289: xmlHashEntryPtr iter;
! 290: xmlHashEntryPtr next;
! 291: xmlHashTablePtr ret;
! 292:
! 293: if (table == NULL)
! 294: return(NULL);
! 295: if (f == NULL)
! 296: return(NULL);
! 297:
! 298: ret = xmlHashCreate(table->size);
! 299: if (table->table) {
! 300: for(i = 0; i < table->size; i++) {
! 301: iter = table->table[i];
! 302: while (iter) {
! 303: next = iter->next;
! 304: xmlHashAddEntry(ret, iter->name, f(iter));
! 305: iter = next;
! 306: }
! 307: }
! 308: }
! 309: return(ret);
! 310: }
! 311:
Webmaster