webengine/osswebengine/WebCore/platform/symbian/Libxml2/Libxml2_dict.c
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * dict.c: dictionary of reusable strings, just used to avoid allocation
       
     3  *         and freeing operations.
       
     4  *
       
     5  * Copyright (C) 2003 Daniel Veillard.
       
     6  *
       
     7  * Permission to use, copy, modify, and distribute this software for any
       
     8  * purpose with or without fee is hereby granted, provided that the above
       
     9  * copyright notice and this permission notice appear in all copies.
       
    10  *
       
    11  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
       
    12  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
       
    13  * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
       
    14  * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
       
    15  *
       
    16  * Author: daniel@veillard.com
       
    17  */
       
    18 
       
    19 #define IN_LIBXML
       
    20 #include "XmlEnglibxml.h"
       
    21 
       
    22 #include <string.h>
       
    23 #include "Libxml2_globals.h"
       
    24 
       
    25 #define MAX_HASH_LEN 4
       
    26 // TODO: Optimize: "Magic number" -- make it configurable global parameter
       
    27 //       1 entry is 16 bytes
       
    28 #define MIN_DICT_SIZE 128
       
    29 #define MAX_DICT_HASH 8 * 2048
       
    30 
       
    31 /* #define ALLOW_REMOVAL */
       
    32 /* #define DEBUG_GROW */
       
    33 
       
    34 /*
       
    35  * xmlDictAddString:
       
    36  * @dict: the dictionnary
       
    37  * @name: the name of the userdata
       
    38  * @len: the length of the name, if -1 it is recomputed
       
    39  *
       
    40  * Add the string to the array[s]
       
    41  *
       
    42  * Returns the pointer of the local string, or NULL in case of error.
       
    43  *
       
    44  * OOM: possible --> NULL is returned, OOM flag is set
       
    45  */
       
    46 static const xmlChar*
       
    47 xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) {
       
    48     xmlDictStringsPtr pool;
       
    49     const xmlChar *ret;
       
    50     int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
       
    51 
       
    52     pool = dict->strings;
       
    53     while (pool != NULL) {
       
    54         if (pool->end - pool->free > namelen)
       
    55             goto found_pool;
       
    56         if (pool->size > size) size = pool->size;
       
    57             pool = pool->next;
       
    58     }
       
    59     /*
       
    60      * Not found, need to allocate
       
    61      */
       
    62     if (pool == NULL) {
       
    63         if (size == 0) 
       
    64             size = 1000;
       
    65         else 
       
    66             size *= 4; /* exponential growth */
       
    67 
       
    68         if (size < 4 * namelen)
       
    69             size = 4 * namelen; /* just in case ! */
       
    70 
       
    71         pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
       
    72         if (pool == NULL)
       
    73             return(NULL);
       
    74         pool->size = size;
       
    75         pool->nbStrings = 0;
       
    76         pool->free = &pool->array[0];
       
    77         pool->end = &pool->array[size];
       
    78         pool->next = dict->strings;
       
    79         dict->strings = pool;
       
    80     }
       
    81 found_pool:
       
    82     ret = pool->free;
       
    83     memcpy(pool->free, name, namelen);
       
    84     pool->free += namelen;
       
    85     *(pool->free++) = 0;
       
    86     return(ret);
       
    87 }
       
    88 
       
    89 /*
       
    90  * xmlDictAddQString:
       
    91  * @dict: the dictionnary
       
    92  * @prefix: the prefix of the userdata
       
    93  * @name: the name of the userdata
       
    94  * @len: the length of the name, if -1 it is recomputed
       
    95  *
       
    96  * Add the QName to the array[s]
       
    97  *
       
    98  * Returns the pointer of the local string, or NULL in case of error.
       
    99  */
       
   100 static const xmlChar *
       
   101 xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix,
       
   102                  const xmlChar *name, int namelen)
       
   103 {
       
   104     xmlDictStringsPtr pool;
       
   105     const xmlChar *ret;
       
   106     int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
       
   107     int plen;
       
   108 
       
   109     if (prefix == NULL) return(xmlDictAddString(dict, name, namelen));
       
   110     plen = xmlStrlen(prefix);
       
   111 
       
   112     pool = dict->strings;
       
   113     while (pool != NULL) {
       
   114     if (pool->end - pool->free > namelen)
       
   115         goto found_pool;
       
   116     if (pool->size > size) size = pool->size;
       
   117     pool = pool->next;
       
   118     }
       
   119     /*
       
   120      * Not found, need to allocate
       
   121      */
       
   122     if (pool == NULL) {
       
   123         if (size == 0) size = 1000;
       
   124     else size *= 4; /* exponential growth */
       
   125         if (size < 4 * namelen)
       
   126         size = 4 * namelen; /* just in case ! */
       
   127     pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
       
   128     if (pool == NULL)
       
   129         return(NULL);
       
   130     pool->size = size;
       
   131     pool->nbStrings = 0;
       
   132     pool->free = &pool->array[0];
       
   133     pool->end = &pool->array[size];
       
   134     pool->next = dict->strings;
       
   135     dict->strings = pool;
       
   136     }
       
   137 found_pool:
       
   138     ret = pool->free;
       
   139     memcpy(pool->free, prefix, plen);
       
   140     pool->free += plen;
       
   141     *(pool->free++) = ':';
       
   142     namelen -= plen + 1;
       
   143     memcpy(pool->free, name, namelen);
       
   144     pool->free += namelen;
       
   145     *(pool->free++) = 0;
       
   146     return(ret);
       
   147 }
       
   148 
       
   149 /*
       
   150  * xmlDictComputeKey:
       
   151  * Calculate the hash key
       
   152  *
       
   153  * OOM: never
       
   154  */
       
   155 static unsigned long
       
   156 xmlDictComputeKey(const xmlChar *name, int namelen) {
       
   157     unsigned long value = 0L;
       
   158 
       
   159     if (name == NULL) return(0);
       
   160     value = *name;
       
   161     value <<= 5;
       
   162     if (namelen > 10) {
       
   163         value += name[namelen - 1];
       
   164         namelen = 10;
       
   165     }
       
   166     switch (namelen) {
       
   167         case 10: value += name[9];
       
   168         case 9: value += name[8];
       
   169         case 8: value += name[7];
       
   170         case 7: value += name[6];
       
   171         case 6: value += name[5];
       
   172         case 5: value += name[4];
       
   173         case 4: value += name[3];
       
   174         case 3: value += name[2];
       
   175         case 2: value += name[1];
       
   176         default: break;
       
   177     }
       
   178     return(value);
       
   179 }
       
   180 
       
   181 /*
       
   182  * xmlDictComputeQKey:
       
   183  * Calculate the hash key
       
   184  */
       
   185 static unsigned long
       
   186 xmlDictComputeQKey(const xmlChar *prefix, const xmlChar *name, int len)
       
   187 {
       
   188     unsigned long value = 0L;
       
   189     int plen;
       
   190 
       
   191     if (prefix == NULL)
       
   192         return(xmlDictComputeKey(name, len));
       
   193 
       
   194     plen = xmlStrlen(prefix);
       
   195     if (plen == 0)
       
   196     value += 30 * (unsigned long) ':';
       
   197     else
       
   198     value += 30 * (*prefix);
       
   199 
       
   200     if (len > 10) {
       
   201         value += name[len - (plen + 1 + 1)];
       
   202         len = 10;
       
   203     if (plen > 10)
       
   204         plen = 10;
       
   205     }
       
   206     switch (plen) {
       
   207         case 10: value += prefix[9];
       
   208         case 9: value += prefix[8];
       
   209         case 8: value += prefix[7];
       
   210         case 7: value += prefix[6];
       
   211         case 6: value += prefix[5];
       
   212         case 5: value += prefix[4];
       
   213         case 4: value += prefix[3];
       
   214         case 3: value += prefix[2];
       
   215         case 2: value += prefix[1];
       
   216         case 1: value += prefix[0];
       
   217         default: break;
       
   218     }
       
   219     len -= plen;
       
   220     if (len > 0) {
       
   221         value += (unsigned long) ':';
       
   222     len--;
       
   223     }
       
   224     switch (len) {
       
   225         case 10: value += name[9];
       
   226         case 9: value += name[8];
       
   227         case 8: value += name[7];
       
   228         case 7: value += name[6];
       
   229         case 6: value += name[5];
       
   230         case 5: value += name[4];
       
   231         case 4: value += name[3];
       
   232         case 3: value += name[2];
       
   233         case 2: value += name[1];
       
   234         case 1: value += name[0];
       
   235         default: break;
       
   236     }
       
   237     return(value);
       
   238 }
       
   239 
       
   240 /**
       
   241  * xmlDictCreate:
       
   242  *
       
   243  * Create a new dictionary
       
   244  *
       
   245  * Returns the newly created dictionnary, or NULL if an error occured.
       
   246  *
       
   247  * OOM: possible --> NULL is returned; OOM flag is set
       
   248  */
       
   249 xmlDictPtr
       
   250 xmlDictCreate(void) {
       
   251     xmlDictPtr dict;
       
   252 
       
   253     dict = (xmlDictPtr)xmlMalloc(sizeof(xmlDict));
       
   254     if (dict) {
       
   255         dict->ref_counter = 1;
       
   256 
       
   257         dict->size = MIN_DICT_SIZE;
       
   258         dict->nbElems = 0;
       
   259         dict->dict = (xmlDictEntryPtr)xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
       
   260         dict->strings = NULL;
       
   261         dict->subdict = NULL;
       
   262         if (dict->dict) {
       
   263             memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
       
   264             return(dict);
       
   265         }
       
   266         xmlFree(dict); // OOM
       
   267     }
       
   268     return(NULL); // OOM
       
   269 }
       
   270 
       
   271 /**
       
   272  * xmlDictCreateSub:
       
   273  * @sub: an existing dictionnary
       
   274  *
       
   275  * Create a new dictionary, inheriting strings from the read-only
       
   276  * dictionnary @sub. On lookup, strings are first searched in the
       
   277  * new dictionnary, then in @sub, and if not found are created in the
       
   278  * new dictionnary.
       
   279  *
       
   280  * Returns the newly created dictionnary, or NULL if an error occured.
       
   281  */
       
   282 xmlDictPtr
       
   283 xmlDictCreateSub(xmlDictPtr sub) {
       
   284     xmlDictPtr dict = xmlDictCreate();
       
   285 
       
   286     if ((dict != NULL) && (sub != NULL)) {
       
   287         dict->subdict = sub;
       
   288     xmlDictReference(dict->subdict);
       
   289     }
       
   290     return(dict);
       
   291 }
       
   292 
       
   293 /**
       
   294  * xmlDictReference:
       
   295  * @dict: the dictionnary
       
   296  *
       
   297  * Increment the reference counter of a dictionary
       
   298  *
       
   299  * Returns 0 in case of success and -1 in case of error
       
   300  *
       
   301  * OOM: never
       
   302  */
       
   303 int
       
   304 xmlDictReference(xmlDictPtr dict) {
       
   305     if (dict == NULL) return -1;
       
   306     dict->ref_counter++;
       
   307     return(0);
       
   308 }
       
   309 
       
   310 /**
       
   311  * xmlDictGrow:
       
   312  * @dict: the dictionnary
       
   313  * @size: the new size of the dictionnary
       
   314  *
       
   315  * resize the dictionnary
       
   316  *
       
   317  * Returns 0 in case of success, -1 in case of failure
       
   318  *
       
   319  * OOM: possible --> returns -1, OOM is set
       
   320  */
       
   321 static int
       
   322 xmlDictGrow(xmlDictPtr dict, int size) {
       
   323     unsigned long key;
       
   324     int oldsize, i;
       
   325     xmlDictEntryPtr iter, next;
       
   326     struct _xmlDictEntry *olddict;
       
   327 #ifdef DEBUG_GROW
       
   328     unsigned long nbElem = 0;
       
   329 #endif
       
   330 
       
   331     if (dict == NULL)
       
   332         return(-1);
       
   333     if (size < 8)
       
   334         return(-1);
       
   335     if (size > 8 * 2048)
       
   336         return(-1);
       
   337 
       
   338     oldsize = dict->size;
       
   339     olddict = dict->dict;
       
   340     if (olddict == NULL)
       
   341         return(-1);
       
   342 
       
   343     dict->dict = (xmlDictEntryPtr)xmlMalloc(size * sizeof(xmlDictEntry));
       
   344     if (dict->dict == NULL) {
       
   345         dict->dict = olddict;
       
   346         return(-1);
       
   347     }
       
   348     memset(dict->dict, 0, size * sizeof(xmlDictEntry));
       
   349     dict->size = size;
       
   350 
       
   351     /*  If the two loops are merged, there would be situations where
       
   352     a new entry needs to allocated and data copied into it from
       
   353     the main dict. So instead, we run through the array twice, first
       
   354     copying all the elements in the main array (where we can't get
       
   355     conflicts) and then the rest, so we only free (and don't allocate)
       
   356     */
       
   357     for (i = 0; i < oldsize; i++) {
       
   358         if (olddict[i].valid == 0)
       
   359             continue;
       
   360         key = xmlDictComputeKey(olddict[i].name, olddict[i].len) % dict->size;
       
   361         memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry));
       
   362         dict->dict[key].next = NULL;
       
   363 #ifdef DEBUG_GROW
       
   364         nbElem++;
       
   365 #endif
       
   366     }
       
   367 
       
   368     for (i = 0; i < oldsize; i++) {
       
   369         iter = olddict[i].next;
       
   370         while (iter) {
       
   371             next = iter->next;
       
   372             /*
       
   373             * put back the entry in the new dict
       
   374             */
       
   375             key = xmlDictComputeKey(iter->name, iter->len) % dict->size;
       
   376             if (dict->dict[key].valid == 0) {
       
   377                 memcpy(&(dict->dict[key]), iter, sizeof(xmlDictEntry));
       
   378                 dict->dict[key].next = NULL;
       
   379                 dict->dict[key].valid = 1;
       
   380                 xmlFree(iter);
       
   381             } else {
       
   382                 iter->next = dict->dict[key].next;
       
   383                 dict->dict[key].next = iter;
       
   384             }
       
   385 #ifdef DEBUG_GROW
       
   386             nbElem++;
       
   387 #endif
       
   388             iter = next;
       
   389         } // while (iter)
       
   390     } // for (i = 0; i < oldsize; i++)
       
   391 
       
   392     xmlFree(olddict);
       
   393 
       
   394 #ifdef DEBUG_GROW
       
   395     xmlGenericError(xmlGenericErrorContext,
       
   396         "xmlDictGrow : from %d to %d, %d elems\n", oldsize, size, nbElem);
       
   397 #endif
       
   398 
       
   399     return(0);
       
   400 }
       
   401 
       
   402 /**
       
   403  * xmlDictFree:
       
   404  * @dict: the dictionnary
       
   405  *
       
   406  * Free the hash @dict and its contents. The userdata is
       
   407  * deallocated with @f if provided.
       
   408  */
       
   409 void
       
   410 xmlDictFree(xmlDictPtr dict) {
       
   411     int i;
       
   412     xmlDictEntryPtr iter;
       
   413     xmlDictEntryPtr next;
       
   414     int inside_dict = 0;
       
   415     xmlDictStringsPtr pool, nextp;
       
   416 
       
   417     if (dict == NULL)
       
   418         return;
       
   419 
       
   420     /* decrement the counter, it may be shared by a parser and docs */
       
   421     dict->ref_counter--;
       
   422     if (dict->ref_counter > 0)
       
   423         return;
       
   424 
       
   425     if (dict->subdict != NULL) {
       
   426         xmlDictFree(dict->subdict);
       
   427     }
       
   428 
       
   429     if (dict->dict) {
       
   430         for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++)
       
   431         {
       
   432             iter = &(dict->dict[i]);
       
   433             if (iter->valid == 0)
       
   434                 continue;
       
   435             inside_dict = 1;
       
   436             while (iter)
       
   437             {
       
   438                 next = iter->next;
       
   439                 if (!inside_dict)
       
   440                     xmlFree(iter);
       
   441                 dict->nbElems--;
       
   442                 inside_dict = 0;
       
   443                 iter = next;
       
   444             }
       
   445             inside_dict = 0;
       
   446         }
       
   447         xmlFree(dict->dict);
       
   448     }
       
   449 
       
   450     pool = dict->strings;
       
   451     while (pool != NULL) {
       
   452         nextp = pool->next;
       
   453         xmlFree(pool);
       
   454         pool = nextp;
       
   455     }
       
   456     xmlFree(dict);
       
   457 }
       
   458 
       
   459 /**
       
   460  * xmlDictLookup:
       
   461  * @dict: the dictionnary
       
   462  * @name: the name of the userdata
       
   463  * @len: the length of the name, if -1 it is recomputed
       
   464  *
       
   465  * Add the @name to the hash @dict if not present.
       
   466  *
       
   467  * Returns the internal copy of the name or NULL in case of internal error
       
   468  *
       
   469  * OOM: possible --> returns NULL and OOM flag is set
       
   470  */
       
   471 const xmlChar*
       
   472 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
       
   473     unsigned long key, okey, nbi = 0;
       
   474     xmlDictEntryPtr entry;
       
   475     xmlDictEntryPtr insert;
       
   476     const xmlChar *ret;
       
   477 
       
   478     if ((dict == NULL) || (name == NULL))
       
   479         return(NULL);
       
   480 
       
   481     if (len < 0)
       
   482         len = xmlStrlen(name);
       
   483 
       
   484     /*
       
   485      * Check for duplicate and insertion location.
       
   486      */
       
   487     okey = xmlDictComputeKey(name, len);
       
   488     key = okey % dict->size;
       
   489     if (dict->dict[key].valid == 0) {
       
   490         insert = NULL;
       
   491     } else {
       
   492         for (insert = &(dict->dict[key]); 
       
   493              insert->next != NULL; 
       
   494              insert = insert->next)
       
   495         {
       
   496 #ifdef __GNUC__
       
   497             if (insert->len == len) {
       
   498                 if (!memcmp(insert->name, name, len))
       
   499                     return(insert->name);
       
   500             }
       
   501 #else
       
   502             if ((insert->len == len) && (!xmlStrncmp(insert->name, name, len)))
       
   503                 return(insert->name);
       
   504 #endif
       
   505             nbi++;
       
   506         }
       
   507 #ifdef __GNUC__
       
   508         if (insert->len == len) {
       
   509             if (!memcmp(insert->name, name, len))
       
   510                 return(insert->name);
       
   511         }
       
   512 #else
       
   513         if ((insert->len == len) && (!xmlStrncmp(insert->name, name, len)))
       
   514             return(insert->name);
       
   515 #endif
       
   516     }
       
   517 
       
   518     if (dict->subdict) {
       
   519         key = okey % dict->subdict->size;
       
   520         if (dict->subdict->dict[key].valid != 0) {
       
   521             xmlDictEntryPtr tmp;
       
   522     
       
   523             for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; tmp = tmp->next)
       
   524             {
       
   525 #ifdef __GNUC__
       
   526                 if (tmp->len == len) {
       
   527                     if (!memcmp(tmp->name, name, len))
       
   528                         return(tmp->name);
       
   529                 }
       
   530 #else
       
   531                 if ((tmp->len == len) && (!xmlStrncmp(tmp->name, name, len)))
       
   532                         return(tmp->name);
       
   533 #endif
       
   534                 nbi++;
       
   535             }
       
   536 #ifdef __GNUC__
       
   537             if (tmp->len == len) {
       
   538                 if (!memcmp(tmp->name, name, len))
       
   539                     return(tmp->name);
       
   540             }
       
   541 #else
       
   542             if ((tmp->len == len) && (!xmlStrncmp(tmp->name, name, len)))
       
   543                 return(tmp->name);
       
   544 #endif
       
   545         } // if (dict->subdict->dict[key].valid != 0)
       
   546 
       
   547         key = okey % dict->size;
       
   548     } // if (dict->subdict)
       
   549 
       
   550     ret = xmlDictAddString(dict, name, len); // may set OOM flag
       
   551     if (!ret)
       
   552         return(NULL);
       
   553 
       
   554     if (insert == NULL) {
       
   555         entry = &(dict->dict[key]);
       
   556     } else {
       
   557         entry = (xmlDictEntryPtr)xmlMalloc(sizeof(xmlDictEntry));
       
   558         if (entry == NULL)
       
   559              return(NULL); //OOM
       
   560     }
       
   561     entry->name = ret;
       
   562     entry->len = len;
       
   563     entry->next = NULL;
       
   564     entry->valid = 1;
       
   565 
       
   566     if (insert != NULL)
       
   567         insert->next = entry;
       
   568 
       
   569     dict->nbElems++;
       
   570 
       
   571     if ((nbi > MAX_HASH_LEN) && 
       
   572         (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN)))
       
   573     {
       
   574         xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size);
       
   575         if(OOM_FLAG)
       
   576             return NULL;
       
   577     }
       
   578 
       
   579     /* Note that entry may have been freed at this point by xmlDictGrow */
       
   580 
       
   581     return(ret);
       
   582 }
       
   583 
       
   584 /**
       
   585  * xmlDictQLookup:
       
   586  * @dict: the dictionnary
       
   587  * @prefix: the prefix
       
   588  * @name: the name
       
   589  *
       
   590  * Add the QName @prefix:@name to the hash @dict if not present.
       
   591  *
       
   592  * Returns the internal copy of the QName or NULL in case of internal error
       
   593  */
       
   594 const xmlChar *
       
   595 xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
       
   596     unsigned long okey, key, nbi = 0;
       
   597     xmlDictEntryPtr entry;
       
   598     xmlDictEntryPtr insert;
       
   599     const xmlChar *ret;
       
   600     int len;
       
   601 
       
   602     if ((dict == NULL) || (name == NULL))
       
   603     return(NULL);
       
   604 
       
   605     len = xmlStrlen(name);
       
   606     if (prefix != NULL)
       
   607         len += 1 + xmlStrlen(prefix);
       
   608 
       
   609     /*
       
   610      * Check for duplicate and insertion location.
       
   611      */
       
   612     okey = xmlDictComputeQKey(prefix, name, len);
       
   613     key = okey % dict->size;
       
   614     if (dict->dict[key].valid == 0) {
       
   615     insert = NULL;
       
   616     } else {
       
   617     for (insert = &(dict->dict[key]); insert->next != NULL;
       
   618          insert = insert->next) {
       
   619         if ((insert->len == len) &&
       
   620             (xmlStrQEqual(prefix, name, insert->name)))
       
   621         return(insert->name);
       
   622         nbi++;
       
   623     }
       
   624     if ((insert->len == len) &&
       
   625         (xmlStrQEqual(prefix, name, insert->name)))
       
   626         return(insert->name);
       
   627     }
       
   628 
       
   629     if (dict->subdict) {
       
   630     key = okey % dict->subdict->size;
       
   631     if (dict->subdict->dict[key].valid != 0) {
       
   632         xmlDictEntryPtr tmp;
       
   633         for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
       
   634          tmp = tmp->next) {
       
   635         if ((tmp->len == len) &&
       
   636             (xmlStrQEqual(prefix, name, tmp->name)))
       
   637             return(tmp->name);
       
   638         nbi++;
       
   639         }
       
   640         if ((tmp->len == len) &&
       
   641         (xmlStrQEqual(prefix, name, tmp->name)))
       
   642         return(tmp->name);
       
   643     }
       
   644     key = okey % dict->size;
       
   645     }
       
   646 
       
   647     ret = xmlDictAddQString(dict, prefix, name, len);
       
   648     if (ret == NULL)
       
   649         return(NULL);
       
   650     if (insert == NULL) {
       
   651     entry = &(dict->dict[key]);
       
   652     } else {
       
   653         entry = (xmlDictEntryPtr)xmlMalloc(sizeof(xmlDictEntry));
       
   654     if (entry == NULL)
       
   655          return(NULL);
       
   656     }
       
   657     entry->name = ret;
       
   658     entry->len = len;
       
   659     entry->next = NULL;
       
   660     entry->valid = 1;
       
   661 
       
   662     if (insert != NULL)
       
   663     insert->next = entry;
       
   664 
       
   665     dict->nbElems++;
       
   666 
       
   667     if ((nbi > MAX_HASH_LEN) &&
       
   668         (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN)))
       
   669     xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size);
       
   670     /* Note that entry may have been freed at this point by xmlDictGrow */
       
   671 
       
   672     return(ret);
       
   673 }
       
   674 
       
   675 
       
   676 /**
       
   677  * xmlDictOwns:
       
   678  * @dict: the dictionnary
       
   679  * @str: the string
       
   680  *
       
   681  * check if a string is owned by the disctionary
       
   682  *
       
   683  * Returns 1 if true, 0 if false and -1 in case of error
       
   684  * -1 in case of error
       
   685  *
       
   686  * OOM: impossible
       
   687  */
       
   688 int
       
   689 xmlDictOwns(xmlDictPtr dict, const xmlChar *str) {
       
   690     xmlDictStringsPtr pool;
       
   691 
       
   692     if ((dict == NULL) || (str == NULL))
       
   693     {
       
   694         return(-1);
       
   695     }
       
   696     pool = dict->strings;
       
   697     while (pool != NULL) {
       
   698         if ((str >= pool->array) && (str <= pool->free))
       
   699         {
       
   700             return(1);
       
   701         }
       
   702         pool = pool->next;
       
   703     }
       
   704     if (dict->subdict)
       
   705         return(xmlDictOwns(dict->subdict, str));
       
   706     return(0);
       
   707 }
       
   708 
       
   709