ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dict.c
Go to the documentation of this file.
00001 /*
00002  * dict.c: dictionary of reusable strings, just used to avoid allocation
00003  *         and freeing operations.
00004  *
00005  * Copyright (C) 2003 Daniel Veillard.
00006  *
00007  * Permission to use, copy, modify, and distribute this software for any
00008  * purpose with or without fee is hereby granted, provided that the above
00009  * copyright notice and this permission notice appear in all copies.
00010  *
00011  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
00012  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00013  * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
00014  * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
00015  *
00016  * Author: daniel@veillard.com
00017  */
00018 
00019 #define IN_LIBXML
00020 #include "libxml.h"
00021 
00022 #include <string.h>
00023 #ifdef HAVE_STDINT_H
00024 #include <stdint.h>
00025 #else
00026 #ifdef HAVE_INTTYPES_H
00027 #include <inttypes.h>
00028 #elif defined(WIN32)
00029 typedef unsigned __int32 uint32_t;
00030 #endif
00031 #endif
00032 #include <libxml/tree.h>
00033 #include <libxml/dict.h>
00034 #include <libxml/xmlmemory.h>
00035 #include <libxml/xmlerror.h>
00036 #include <libxml/globals.h>
00037 
00038 /* #define DEBUG_GROW */
00039 /* #define DICT_DEBUG_PATTERNS */
00040 
00041 #define MAX_HASH_LEN 3
00042 #define MIN_DICT_SIZE 128
00043 #define MAX_DICT_HASH 8 * 2048
00044 #define WITH_BIG_KEY
00045 
00046 #ifdef WITH_BIG_KEY
00047 #define xmlDictComputeKey(dict, name, len)          \
00048     (((dict)->size == MIN_DICT_SIZE) ?              \
00049      xmlDictComputeFastKey(name, len) :             \
00050      xmlDictComputeBigKey(name, len))
00051 
00052 #define xmlDictComputeQKey(dict, prefix, plen, name, len)   \
00053     (((prefix) == NULL) ?                   \
00054       (xmlDictComputeKey(dict, name, len)) :            \
00055       (((dict)->size == MIN_DICT_SIZE) ?            \
00056        xmlDictComputeFastQKey(prefix, plen, name, len) :    \
00057        xmlDictComputeBigQKey(prefix, plen, name, len)))
00058 
00059 #else /* !WITH_BIG_KEY */
00060 #define xmlDictComputeKey(dict, name, len)          \
00061         xmlDictComputeFastKey(name, len)
00062 #define xmlDictComputeQKey(dict, prefix, plen, name, len)   \
00063         xmlDictComputeFastQKey(prefix, plen, name, len)
00064 #endif /* WITH_BIG_KEY */
00065 
00066 /*
00067  * An entry in the dictionnary
00068  */
00069 typedef struct _xmlDictEntry xmlDictEntry;
00070 typedef xmlDictEntry *xmlDictEntryPtr;
00071 struct _xmlDictEntry {
00072     struct _xmlDictEntry *next;
00073     const xmlChar *name;
00074     int len;
00075     int valid;
00076     unsigned long okey;
00077 };
00078 
00079 typedef struct _xmlDictStrings xmlDictStrings;
00080 typedef xmlDictStrings *xmlDictStringsPtr;
00081 struct _xmlDictStrings {
00082     xmlDictStringsPtr next;
00083     xmlChar *free;
00084     xmlChar *end;
00085     int size;
00086     int nbStrings;
00087     xmlChar array[1];
00088 };
00089 /*
00090  * The entire dictionnary
00091  */
00092 struct _xmlDict {
00093     int ref_counter;
00094 
00095     struct _xmlDictEntry *dict;
00096     int size;
00097     int nbElems;
00098     xmlDictStringsPtr strings;
00099 
00100     struct _xmlDict *subdict;
00101 };
00102 
00103 /*
00104  * A mutex for modifying the reference counter for shared
00105  * dictionaries.
00106  */
00107 static xmlRMutexPtr xmlDictMutex = NULL;
00108 
00109 /*
00110  * Whether the dictionary mutex was initialized.
00111  */
00112 static int xmlDictInitialized = 0;
00113 
00121 static int xmlInitializeDict(void) {
00122     if (xmlDictInitialized)
00123         return(1);
00124 
00125     if ((xmlDictMutex = xmlNewRMutex()) == NULL)
00126         return(0);
00127 
00128     xmlDictInitialized = 1;
00129     return(1);
00130 }
00131 
00137 void
00138 xmlDictCleanup(void) {
00139     if (!xmlDictInitialized)
00140         return;
00141 
00142     xmlFreeRMutex(xmlDictMutex);
00143 
00144     xmlDictInitialized = 0;
00145 }
00146 
00147 /*
00148  * xmlDictAddString:
00149  * @dict: the dictionnary
00150  * @name: the name of the userdata
00151  * @len: the length of the name, if -1 it is recomputed
00152  *
00153  * Add the string to the array[s]
00154  *
00155  * Returns the pointer of the local string, or NULL in case of error.
00156  */
00157 static const xmlChar *
00158 xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) {
00159     xmlDictStringsPtr pool;
00160     const xmlChar *ret;
00161     int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
00162 
00163 #ifdef DICT_DEBUG_PATTERNS
00164     fprintf(stderr, "-");
00165 #endif
00166     pool = dict->strings;
00167     while (pool != NULL) {
00168     if (pool->end - pool->free > namelen)
00169         goto found_pool;
00170     if (pool->size > size) size = pool->size;
00171     pool = pool->next;
00172     }
00173     /*
00174      * Not found, need to allocate
00175      */
00176     if (pool == NULL) {
00177         if (size == 0) size = 1000;
00178     else size *= 4; /* exponential growth */
00179         if (size < 4 * namelen) 
00180         size = 4 * namelen; /* just in case ! */
00181     pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
00182     if (pool == NULL)
00183         return(NULL);
00184     pool->size = size;
00185     pool->nbStrings = 0;
00186     pool->free = &pool->array[0];
00187     pool->end = &pool->array[size];
00188     pool->next = dict->strings;
00189     dict->strings = pool;
00190 #ifdef DICT_DEBUG_PATTERNS
00191         fprintf(stderr, "+");
00192 #endif
00193     }
00194 found_pool:
00195     ret = pool->free;
00196     memcpy(pool->free, name, namelen);
00197     pool->free += namelen;
00198     *(pool->free++) = 0;
00199     pool->nbStrings++;
00200     return(ret);
00201 }
00202 
00203 /*
00204  * xmlDictAddQString:
00205  * @dict: the dictionnary
00206  * @prefix: the prefix of the userdata
00207  * @plen: the prefix length
00208  * @name: the name of the userdata
00209  * @len: the length of the name, if -1 it is recomputed
00210  *
00211  * Add the QName to the array[s]
00212  *
00213  * Returns the pointer of the local string, or NULL in case of error.
00214  */
00215 static const xmlChar *
00216 xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, int plen,
00217                  const xmlChar *name, int namelen)
00218 {
00219     xmlDictStringsPtr pool;
00220     const xmlChar *ret;
00221     int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
00222 
00223     if (prefix == NULL) return(xmlDictAddString(dict, name, namelen));
00224 
00225 #ifdef DICT_DEBUG_PATTERNS
00226     fprintf(stderr, "=");
00227 #endif
00228     pool = dict->strings;
00229     while (pool != NULL) {
00230     if (pool->end - pool->free > namelen + plen + 1)
00231         goto found_pool;
00232     if (pool->size > size) size = pool->size;
00233     pool = pool->next;
00234     }
00235     /*
00236      * Not found, need to allocate
00237      */
00238     if (pool == NULL) {
00239         if (size == 0) size = 1000;
00240     else size *= 4; /* exponential growth */
00241         if (size < 4 * (namelen + plen + 1))
00242         size = 4 * (namelen + plen + 1); /* just in case ! */
00243     pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
00244     if (pool == NULL)
00245         return(NULL);
00246     pool->size = size;
00247     pool->nbStrings = 0;
00248     pool->free = &pool->array[0];
00249     pool->end = &pool->array[size];
00250     pool->next = dict->strings;
00251     dict->strings = pool;
00252 #ifdef DICT_DEBUG_PATTERNS
00253         fprintf(stderr, "+");
00254 #endif
00255     }
00256 found_pool:
00257     ret = pool->free;
00258     memcpy(pool->free, prefix, plen);
00259     pool->free += plen;
00260     *(pool->free++) = ':';
00261     memcpy(pool->free, name, namelen);
00262     pool->free += namelen;
00263     *(pool->free++) = 0;
00264     pool->nbStrings++;
00265     return(ret);
00266 }
00267 
00268 #ifdef WITH_BIG_KEY
00269 /*
00270  * xmlDictComputeBigKey:
00271  *
00272  * Calculate a hash key using a good hash function that works well for
00273  * larger hash table sizes.
00274  *
00275  * Hash function by "One-at-a-Time Hash" see
00276  * http://burtleburtle.net/bob/hash/doobs.html
00277  */
00278 
00279 static uint32_t
00280 xmlDictComputeBigKey(const xmlChar* data, int namelen) {
00281     uint32_t hash;
00282     int i;
00283 
00284     if (namelen <= 0 || data == NULL) return(0);
00285 
00286     hash = 0;
00287 
00288     for (i = 0;i < namelen; i++) {
00289         hash += data[i];
00290     hash += (hash << 10);
00291     hash ^= (hash >> 6);
00292     }
00293     hash += (hash << 3);
00294     hash ^= (hash >> 11);
00295     hash += (hash << 15);
00296 
00297     return hash;
00298 }
00299 
00300 /*
00301  * xmlDictComputeBigQKey:
00302  *
00303  * Calculate a hash key for two strings using a good hash function
00304  * that works well for larger hash table sizes.
00305  *
00306  * Hash function by "One-at-a-Time Hash" see
00307  * http://burtleburtle.net/bob/hash/doobs.html
00308  *
00309  * Neither of the two strings must be NULL.
00310  */
00311 static unsigned long
00312 xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
00313                       const xmlChar *name, int len)
00314 {
00315     uint32_t hash;
00316     int i;
00317 
00318     hash = 0;
00319 
00320     for (i = 0;i < plen; i++) {
00321         hash += prefix[i];
00322     hash += (hash << 10);
00323     hash ^= (hash >> 6);
00324     }
00325     hash += ':';
00326     hash += (hash << 10);
00327     hash ^= (hash >> 6);
00328 
00329     for (i = 0;i < len; i++) {
00330         hash += name[i];
00331     hash += (hash << 10);
00332     hash ^= (hash >> 6);
00333     }
00334     hash += (hash << 3);
00335     hash ^= (hash >> 11);
00336     hash += (hash << 15);
00337 
00338     return hash;
00339 }
00340 #endif /* WITH_BIG_KEY */
00341 
00342 /*
00343  * xmlDictComputeFastKey:
00344  *
00345  * Calculate a hash key using a fast hash function that works well
00346  * for low hash table fill.
00347  */
00348 static unsigned long
00349 xmlDictComputeFastKey(const xmlChar *name, int namelen) {
00350     unsigned long value = 0L;
00351 
00352     if (name == NULL) return(0);
00353     value = *name;
00354     value <<= 5;
00355     if (namelen > 10) {
00356         value += name[namelen - 1];
00357         namelen = 10;
00358     }
00359     switch (namelen) {
00360         case 10: value += name[9];
00361         case 9: value += name[8];
00362         case 8: value += name[7];
00363         case 7: value += name[6];
00364         case 6: value += name[5];
00365         case 5: value += name[4];
00366         case 4: value += name[3];
00367         case 3: value += name[2];
00368         case 2: value += name[1];
00369         default: break;
00370     }
00371     return(value);
00372 }
00373 
00374 /*
00375  * xmlDictComputeFastQKey:
00376  *
00377  * Calculate a hash key for two strings using a fast hash function
00378  * that works well for low hash table fill.
00379  *
00380  * Neither of the two strings must be NULL.
00381  */
00382 static unsigned long
00383 xmlDictComputeFastQKey(const xmlChar *prefix, int plen,
00384                        const xmlChar *name, int len)
00385 {
00386     unsigned long value = 0L;
00387 
00388     if (plen == 0)
00389     value += 30 * (unsigned long) ':';
00390     else
00391     value += 30 * (*prefix);
00392 
00393     if (len > 10) {
00394         value += name[len - (plen + 1 + 1)];
00395         len = 10;
00396     if (plen > 10)
00397         plen = 10;
00398     }
00399     switch (plen) {
00400         case 10: value += prefix[9];
00401         case 9: value += prefix[8];
00402         case 8: value += prefix[7];
00403         case 7: value += prefix[6];
00404         case 6: value += prefix[5];
00405         case 5: value += prefix[4];
00406         case 4: value += prefix[3];
00407         case 3: value += prefix[2];
00408         case 2: value += prefix[1];
00409         case 1: value += prefix[0];
00410         default: break;
00411     }
00412     len -= plen;
00413     if (len > 0) {
00414         value += (unsigned long) ':';
00415     len--;
00416     }
00417     switch (len) {
00418         case 10: value += name[9];
00419         case 9: value += name[8];
00420         case 8: value += name[7];
00421         case 7: value += name[6];
00422         case 6: value += name[5];
00423         case 5: value += name[4];
00424         case 4: value += name[3];
00425         case 3: value += name[2];
00426         case 2: value += name[1];
00427         case 1: value += name[0];
00428         default: break;
00429     }
00430     return(value);
00431 }
00432 
00440 xmlDictPtr
00441 xmlDictCreate(void) {
00442     xmlDictPtr dict;
00443 
00444     if (!xmlDictInitialized)
00445         if (!xmlInitializeDict())
00446             return(NULL);
00447 
00448 #ifdef DICT_DEBUG_PATTERNS
00449     fprintf(stderr, "C");
00450 #endif
00451 
00452     dict = xmlMalloc(sizeof(xmlDict));
00453     if (dict) {
00454         dict->ref_counter = 1;
00455 
00456         dict->size = MIN_DICT_SIZE;
00457     dict->nbElems = 0;
00458         dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
00459     dict->strings = NULL;
00460     dict->subdict = NULL;
00461         if (dict->dict) {
00462         memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
00463         return(dict);
00464         }
00465         xmlFree(dict);
00466     }
00467     return(NULL);
00468 }
00469 
00481 xmlDictPtr
00482 xmlDictCreateSub(xmlDictPtr sub) {
00483     xmlDictPtr dict = xmlDictCreate();
00484 
00485     if ((dict != NULL) && (sub != NULL)) {
00486 #ifdef DICT_DEBUG_PATTERNS
00487         fprintf(stderr, "R");
00488 #endif
00489         dict->subdict = sub;
00490     xmlDictReference(dict->subdict);
00491     }
00492     return(dict);
00493 }
00494 
00503 int
00504 xmlDictReference(xmlDictPtr dict) {
00505     if (!xmlDictInitialized)
00506         if (!xmlInitializeDict())
00507             return(-1);
00508 
00509     if (dict == NULL) return -1;
00510     xmlRMutexLock(xmlDictMutex);
00511     dict->ref_counter++;
00512     xmlRMutexUnlock(xmlDictMutex);
00513     return(0);
00514 }
00515 
00525 static int
00526 xmlDictGrow(xmlDictPtr dict, int size) {
00527     unsigned long key, okey;
00528     int oldsize, i;
00529     xmlDictEntryPtr iter, next;
00530     struct _xmlDictEntry *olddict;
00531 #ifdef DEBUG_GROW
00532     unsigned long nbElem = 0;
00533 #endif
00534     int ret = 0;
00535     int keep_keys = 1;
00536 
00537     if (dict == NULL)
00538     return(-1);
00539     if (size < 8)
00540         return(-1);
00541     if (size > 8 * 2048)
00542     return(-1);
00543 
00544 #ifdef DICT_DEBUG_PATTERNS
00545     fprintf(stderr, "*");
00546 #endif
00547 
00548     oldsize = dict->size;
00549     olddict = dict->dict;
00550     if (olddict == NULL)
00551         return(-1);
00552     if (oldsize == MIN_DICT_SIZE)
00553         keep_keys = 0;
00554 
00555     dict->dict = xmlMalloc(size * sizeof(xmlDictEntry));
00556     if (dict->dict == NULL) {
00557     dict->dict = olddict;
00558     return(-1);
00559     }
00560     memset(dict->dict, 0, size * sizeof(xmlDictEntry));
00561     dict->size = size;
00562 
00563     /*  If the two loops are merged, there would be situations where
00564     a new entry needs to allocated and data copied into it from
00565     the main dict. It is nicer to run through the array twice, first
00566     copying all the elements in the main array (less probability of
00567     allocate) and then the rest, so we only free in the second loop.
00568     */
00569     for (i = 0; i < oldsize; i++) {
00570     if (olddict[i].valid == 0)
00571         continue;
00572 
00573     if (keep_keys)
00574         okey = olddict[i].okey;
00575     else
00576         okey = xmlDictComputeKey(dict, olddict[i].name, olddict[i].len);
00577     key = okey % dict->size;
00578 
00579     if (dict->dict[key].valid == 0) {
00580         memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry));
00581         dict->dict[key].next = NULL;
00582         dict->dict[key].okey = okey;
00583     } else {
00584         xmlDictEntryPtr entry;
00585 
00586         entry = xmlMalloc(sizeof(xmlDictEntry));
00587         if (entry != NULL) {
00588         entry->name = olddict[i].name;
00589         entry->len = olddict[i].len;
00590         entry->okey = okey;
00591         entry->next = dict->dict[key].next;
00592         entry->valid = 1;
00593         dict->dict[key].next = entry;
00594         } else {
00595             /*
00596          * we don't have much ways to alert from herei
00597          * result is loosing an entry and unicity garantee
00598          */
00599             ret = -1;
00600         }
00601     }
00602 #ifdef DEBUG_GROW
00603     nbElem++;
00604 #endif
00605     }
00606 
00607     for (i = 0; i < oldsize; i++) {
00608     iter = olddict[i].next;
00609     while (iter) {
00610         next = iter->next;
00611 
00612         /*
00613          * put back the entry in the new dict
00614          */
00615 
00616         if (keep_keys)
00617         okey = iter->okey;
00618         else
00619         okey = xmlDictComputeKey(dict, iter->name, iter->len);
00620         key = okey % dict->size;
00621         if (dict->dict[key].valid == 0) {
00622         memcpy(&(dict->dict[key]), iter, sizeof(xmlDictEntry));
00623         dict->dict[key].next = NULL;
00624         dict->dict[key].valid = 1;
00625         dict->dict[key].okey = okey;
00626         xmlFree(iter);
00627         } else {
00628         iter->next = dict->dict[key].next;
00629         iter->okey = okey;
00630         dict->dict[key].next = iter;
00631         }
00632 
00633 #ifdef DEBUG_GROW
00634         nbElem++;
00635 #endif
00636 
00637         iter = next;
00638     }
00639     }
00640 
00641     xmlFree(olddict);
00642 
00643 #ifdef DEBUG_GROW
00644     xmlGenericError(xmlGenericErrorContext,
00645         "xmlDictGrow : from %d to %d, %d elems\n", oldsize, size, nbElem);
00646 #endif
00647 
00648     return(ret);
00649 }
00650 
00658 void
00659 xmlDictFree(xmlDictPtr dict) {
00660     int i;
00661     xmlDictEntryPtr iter;
00662     xmlDictEntryPtr next;
00663     int inside_dict = 0;
00664     xmlDictStringsPtr pool, nextp;
00665 
00666     if (dict == NULL)
00667     return;
00668 
00669     if (!xmlDictInitialized)
00670         if (!xmlInitializeDict())
00671             return;
00672 
00673     /* decrement the counter, it may be shared by a parser and docs */
00674     xmlRMutexLock(xmlDictMutex);
00675     dict->ref_counter--;
00676     if (dict->ref_counter > 0) {
00677         xmlRMutexUnlock(xmlDictMutex);
00678         return;
00679     }
00680 
00681     xmlRMutexUnlock(xmlDictMutex);
00682 
00683     if (dict->subdict != NULL) {
00684         xmlDictFree(dict->subdict);
00685     }
00686 
00687     if (dict->dict) {
00688     for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) {
00689         iter = &(dict->dict[i]);
00690         if (iter->valid == 0)
00691         continue;
00692         inside_dict = 1;
00693         while (iter) {
00694         next = iter->next;
00695         if (!inside_dict)
00696             xmlFree(iter);
00697         dict->nbElems--;
00698         inside_dict = 0;
00699         iter = next;
00700         }
00701     }
00702     xmlFree(dict->dict);
00703     }
00704     pool = dict->strings;
00705     while (pool != NULL) {
00706         nextp = pool->next;
00707     xmlFree(pool);
00708     pool = nextp;
00709     }
00710     xmlFree(dict);
00711 }
00712 
00723 const xmlChar *
00724 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
00725     unsigned long key, okey, nbi = 0;
00726     xmlDictEntryPtr entry;
00727     xmlDictEntryPtr insert;
00728     const xmlChar *ret;
00729 
00730     if ((dict == NULL) || (name == NULL))
00731     return(NULL);
00732 
00733     if (len < 0)
00734         len = strlen((const char *) name);
00735 
00736     /*
00737      * Check for duplicate and insertion location.
00738      */
00739     okey = xmlDictComputeKey(dict, name, len);
00740     key = okey % dict->size;
00741     if (dict->dict[key].valid == 0) {
00742     insert = NULL;
00743     } else {
00744     for (insert = &(dict->dict[key]); insert->next != NULL;
00745          insert = insert->next) {
00746 #ifdef __GNUC__
00747         if ((insert->okey == okey) && (insert->len == len)) {
00748         if (!memcmp(insert->name, name, len))
00749             return(insert->name);
00750         }
00751 #else
00752         if ((insert->okey == okey) && (insert->len == len) &&
00753             (!xmlStrncmp(insert->name, name, len)))
00754         return(insert->name);
00755 #endif
00756         nbi++;
00757     }
00758 #ifdef __GNUC__
00759     if ((insert->okey == okey) && (insert->len == len)) {
00760         if (!memcmp(insert->name, name, len))
00761         return(insert->name);
00762     }
00763 #else
00764     if ((insert->okey == okey) && (insert->len == len) &&
00765         (!xmlStrncmp(insert->name, name, len)))
00766         return(insert->name);
00767 #endif
00768     }
00769 
00770     if (dict->subdict) {
00771         unsigned long skey;
00772 
00773         /* we cannot always reuse the same okey for the subdict */
00774         if (((dict->size == MIN_DICT_SIZE) &&
00775          (dict->subdict->size != MIN_DICT_SIZE)) ||
00776             ((dict->size != MIN_DICT_SIZE) &&
00777          (dict->subdict->size == MIN_DICT_SIZE)))
00778         skey = xmlDictComputeKey(dict->subdict, name, len);
00779     else
00780         skey = okey;
00781 
00782     key = skey % dict->subdict->size;
00783     if (dict->subdict->dict[key].valid != 0) {
00784         xmlDictEntryPtr tmp;
00785 
00786         for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
00787          tmp = tmp->next) {
00788 #ifdef __GNUC__
00789         if ((tmp->okey == skey) && (tmp->len == len)) {
00790             if (!memcmp(tmp->name, name, len))
00791             return(tmp->name);
00792         }
00793 #else
00794         if ((tmp->okey == skey) && (tmp->len == len) &&
00795             (!xmlStrncmp(tmp->name, name, len)))
00796             return(tmp->name);
00797 #endif
00798         nbi++;
00799         }
00800 #ifdef __GNUC__
00801         if ((tmp->okey == skey) && (tmp->len == len)) {
00802         if (!memcmp(tmp->name, name, len))
00803             return(tmp->name);
00804         }
00805 #else
00806         if ((tmp->okey == skey) && (tmp->len == len) &&
00807         (!xmlStrncmp(tmp->name, name, len)))
00808         return(tmp->name);
00809 #endif
00810     }
00811     key = okey % dict->size;
00812     }
00813 
00814     ret = xmlDictAddString(dict, name, len);
00815     if (ret == NULL)
00816         return(NULL);
00817     if (insert == NULL) {
00818     entry = &(dict->dict[key]);
00819     } else {
00820     entry = xmlMalloc(sizeof(xmlDictEntry));
00821     if (entry == NULL)
00822          return(NULL);
00823     }
00824     entry->name = ret;
00825     entry->len = len;
00826     entry->next = NULL;
00827     entry->valid = 1;
00828     entry->okey = okey;
00829 
00830 
00831     if (insert != NULL) 
00832     insert->next = entry;
00833 
00834     dict->nbElems++;
00835 
00836     if ((nbi > MAX_HASH_LEN) &&
00837         (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) {
00838     if (xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size) != 0)
00839         return(NULL);
00840     }
00841     /* Note that entry may have been freed at this point by xmlDictGrow */
00842 
00843     return(ret);
00844 }
00845 
00856 const xmlChar *
00857 xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
00858     unsigned long key, okey, nbi = 0;
00859     xmlDictEntryPtr insert;
00860 
00861     if ((dict == NULL) || (name == NULL))
00862     return(NULL);
00863 
00864     if (len < 0)
00865         len = strlen((const char *) name);
00866 
00867     /*
00868      * Check for duplicate and insertion location.
00869      */
00870     okey = xmlDictComputeKey(dict, name, len);
00871     key = okey % dict->size;
00872     if (dict->dict[key].valid == 0) {
00873     insert = NULL;
00874     } else {
00875     for (insert = &(dict->dict[key]); insert->next != NULL;
00876          insert = insert->next) {
00877 #ifdef __GNUC__
00878         if ((insert->okey == okey) && (insert->len == len)) {
00879         if (!memcmp(insert->name, name, len))
00880             return(insert->name);
00881         }
00882 #else
00883         if ((insert->okey == okey) && (insert->len == len) &&
00884             (!xmlStrncmp(insert->name, name, len)))
00885         return(insert->name);
00886 #endif
00887         nbi++;
00888     }
00889 #ifdef __GNUC__
00890     if ((insert->okey == okey) && (insert->len == len)) {
00891         if (!memcmp(insert->name, name, len))
00892         return(insert->name);
00893     }
00894 #else
00895     if ((insert->okey == okey) && (insert->len == len) &&
00896         (!xmlStrncmp(insert->name, name, len)))
00897         return(insert->name);
00898 #endif
00899     }
00900 
00901     if (dict->subdict) {
00902         unsigned long skey;
00903 
00904         /* we cannot always reuse the same okey for the subdict */
00905         if (((dict->size == MIN_DICT_SIZE) &&
00906          (dict->subdict->size != MIN_DICT_SIZE)) ||
00907             ((dict->size != MIN_DICT_SIZE) &&
00908          (dict->subdict->size == MIN_DICT_SIZE)))
00909         skey = xmlDictComputeKey(dict->subdict, name, len);
00910     else
00911         skey = okey;
00912 
00913     key = skey % dict->subdict->size;
00914     if (dict->subdict->dict[key].valid != 0) {
00915         xmlDictEntryPtr tmp;
00916 
00917         for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
00918          tmp = tmp->next) {
00919 #ifdef __GNUC__
00920         if ((tmp->okey == skey) && (tmp->len == len)) {
00921             if (!memcmp(tmp->name, name, len))
00922             return(tmp->name);
00923         }
00924 #else
00925         if ((tmp->okey == skey) && (tmp->len == len) &&
00926             (!xmlStrncmp(tmp->name, name, len)))
00927             return(tmp->name);
00928 #endif
00929         nbi++;
00930         }
00931 #ifdef __GNUC__
00932         if ((tmp->okey == skey) && (tmp->len == len)) {
00933         if (!memcmp(tmp->name, name, len))
00934             return(tmp->name);
00935         }
00936 #else
00937         if ((tmp->okey == skey) && (tmp->len == len) &&
00938         (!xmlStrncmp(tmp->name, name, len)))
00939         return(tmp->name);
00940 #endif
00941     }
00942     }
00943 
00944     /* not found */
00945     return(NULL);
00946 }
00947 
00958 const xmlChar *
00959 xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
00960     unsigned long okey, key, nbi = 0;
00961     xmlDictEntryPtr entry;
00962     xmlDictEntryPtr insert;
00963     const xmlChar *ret;
00964     int len, plen, l;
00965 
00966     if ((dict == NULL) || (name == NULL))
00967     return(NULL);
00968     if (prefix == NULL)
00969         return(xmlDictLookup(dict, name, -1));
00970 
00971     l = len = strlen((const char *) name);
00972     plen = strlen((const char *) prefix);
00973     len += 1 + plen;
00974 
00975     /*
00976      * Check for duplicate and insertion location.
00977      */
00978     okey = xmlDictComputeQKey(dict, prefix, plen, name, l);
00979     key = okey % dict->size;
00980     if (dict->dict[key].valid == 0) {
00981     insert = NULL;
00982     } else {
00983     for (insert = &(dict->dict[key]); insert->next != NULL;
00984          insert = insert->next) {
00985         if ((insert->okey == okey) && (insert->len == len) &&
00986             (xmlStrQEqual(prefix, name, insert->name)))
00987         return(insert->name);
00988         nbi++;
00989     }
00990     if ((insert->okey == okey) && (insert->len == len) &&
00991         (xmlStrQEqual(prefix, name, insert->name)))
00992         return(insert->name);
00993     }
00994 
00995     if (dict->subdict) {
00996         unsigned long skey;
00997 
00998         /* we cannot always reuse the same okey for the subdict */
00999         if (((dict->size == MIN_DICT_SIZE) &&
01000          (dict->subdict->size != MIN_DICT_SIZE)) ||
01001             ((dict->size != MIN_DICT_SIZE) &&
01002          (dict->subdict->size == MIN_DICT_SIZE)))
01003         skey = xmlDictComputeQKey(dict->subdict, prefix, plen, name, l);
01004     else
01005         skey = okey;
01006 
01007     key = skey % dict->subdict->size;
01008     if (dict->subdict->dict[key].valid != 0) {
01009         xmlDictEntryPtr tmp;
01010         for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
01011          tmp = tmp->next) {
01012         if ((tmp->okey == skey) && (tmp->len == len) &&
01013             (xmlStrQEqual(prefix, name, tmp->name)))
01014             return(tmp->name);
01015         nbi++;
01016         }
01017         if ((tmp->okey == skey) && (tmp->len == len) &&
01018         (xmlStrQEqual(prefix, name, tmp->name)))
01019         return(tmp->name);
01020     }
01021     key = okey % dict->size;
01022     }
01023 
01024     ret = xmlDictAddQString(dict, prefix, plen, name, l);
01025     if (ret == NULL)
01026         return(NULL);
01027     if (insert == NULL) {
01028     entry = &(dict->dict[key]);
01029     } else {
01030     entry = xmlMalloc(sizeof(xmlDictEntry));
01031     if (entry == NULL)
01032          return(NULL);
01033     }
01034     entry->name = ret;
01035     entry->len = len;
01036     entry->next = NULL;
01037     entry->valid = 1;
01038     entry->okey = okey;
01039 
01040     if (insert != NULL) 
01041     insert->next = entry;
01042 
01043     dict->nbElems++;
01044 
01045     if ((nbi > MAX_HASH_LEN) &&
01046         (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN)))
01047     xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size);
01048     /* Note that entry may have been freed at this point by xmlDictGrow */
01049 
01050     return(ret);
01051 }
01052 
01063 int
01064 xmlDictOwns(xmlDictPtr dict, const xmlChar *str) {
01065     xmlDictStringsPtr pool;
01066 
01067     if ((dict == NULL) || (str == NULL))
01068     return(-1);
01069     pool = dict->strings;
01070     while (pool != NULL) {
01071         if ((str >= &pool->array[0]) && (str <= pool->free))
01072         return(1);
01073     pool = pool->next;
01074     }
01075     if (dict->subdict)
01076         return(xmlDictOwns(dict->subdict, str));
01077     return(0);
01078 }
01079 
01089 int
01090 xmlDictSize(xmlDictPtr dict) {
01091     if (dict == NULL)
01092     return(-1);
01093     if (dict->subdict)
01094         return(dict->nbElems + dict->subdict->nbElems);
01095     return(dict->nbElems);
01096 }
01097 
01098 
01099 #define bottom_dict
01100 #include "elfgcchack.h"

Generated on Fri May 25 2012 04:21:58 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.