15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * dict.c: dictionary of reusable strings, just used to avoid allocation
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         and freeing operations.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2003 Daniel Veillard.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission to use, copy, modify, and distribute this software for any
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * purpose with or without fee is hereby granted, provided that the above
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copyright notice and this permission notice appear in all copies.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Author: daniel@veillard.com
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IN_LIBXML
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "libxml.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_STDINT_H
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h>
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_INTTYPES_H
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <inttypes.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(WIN32)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef unsigned __int32 uint32_t;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/tree.h>
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/dict.h>
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xmlmemory.h>
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xmlerror.h>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/globals.h>
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* #define DEBUG_GROW */
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* #define DICT_DEBUG_PATTERNS */
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_HASH_LEN 3
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MIN_DICT_SIZE 128
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_DICT_HASH 8 * 2048
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WITH_BIG_KEY
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_BIG_KEY
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define xmlDictComputeKey(dict, name, len)			\
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((dict)->size == MIN_DICT_SIZE) ?				\
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     xmlDictComputeFastKey(name, len) :				\
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     xmlDictComputeBigKey(name, len))
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define xmlDictComputeQKey(dict, prefix, plen, name, len)	\
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((prefix) == NULL) ?					\
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (xmlDictComputeKey(dict, name, len)) :			\
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (((dict)->size == MIN_DICT_SIZE) ?			\
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       xmlDictComputeFastQKey(prefix, plen, name, len) :	\
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       xmlDictComputeBigQKey(prefix, plen, name, len)))
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else /* !WITH_BIG_KEY */
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define xmlDictComputeKey(dict, name, len)			\
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlDictComputeFastKey(name, len)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define xmlDictComputeQKey(dict, prefix, plen, name, len)	\
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlDictComputeFastQKey(prefix, plen, name, len)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* WITH_BIG_KEY */
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * An entry in the dictionnary
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct _xmlDictEntry xmlDictEntry;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef xmlDictEntry *xmlDictEntryPtr;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct _xmlDictEntry {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct _xmlDictEntry *next;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *name;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int len;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int valid;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long okey;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct _xmlDictStrings xmlDictStrings;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef xmlDictStrings *xmlDictStringsPtr;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct _xmlDictStrings {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictStringsPtr next;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *free;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *end;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int size;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nbStrings;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar array[1];
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The entire dictionnary
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct _xmlDict {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ref_counter;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct _xmlDictEntry *dict;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int size;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nbElems;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictStringsPtr strings;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct _xmlDict *subdict;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A mutex for modifying the reference counter for shared
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * dictionaries.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlRMutexPtr xmlDictMutex = NULL;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Whether the dictionary mutex was initialized.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int xmlDictInitialized = 0;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlInitializeDict:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Do the dictionary mutex initialization.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this function is not thread safe, initialization should
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * preferably be done once at startup
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int xmlInitializeDict(void) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xmlDictInitialized)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(1);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((xmlDictMutex = xmlNewRMutex()) == NULL)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(0);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictInitialized = 1;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(1);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictCleanup:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Free the dictionary mutex.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictCleanup(void) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xmlDictInitialized)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFreeRMutex(xmlDictMutex);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictInitialized = 0;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictAddString:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dict: the dictionnary
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @name: the name of the userdata
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @len: the length of the name, if -1 it is recomputed
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add the string to the array[s]
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the pointer of the local string, or NULL in case of error.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const xmlChar *
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictStringsPtr pool;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ret;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DICT_DEBUG_PATTERNS
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "-");
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool = dict->strings;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (pool != NULL) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pool->end - pool->free > namelen)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto found_pool;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pool->size > size) size = pool->size;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool = pool->next;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Not found, need to allocate
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pool == NULL) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (size == 0) size = 1000;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else size *= 4; /* exponential growth */
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (size < 4 * namelen)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    size = 4 * namelen; /* just in case ! */
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pool == NULL)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(NULL);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool->size = size;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool->nbStrings = 0;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool->free = &pool->array[0];
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool->end = &pool->array[size];
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool->next = dict->strings;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dict->strings = pool;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DICT_DEBUG_PATTERNS
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr, "+");
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)found_pool:
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = pool->free;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(pool->free, name, namelen);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool->free += namelen;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *(pool->free++) = 0;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool->nbStrings++;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(ret);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictAddQString:
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dict: the dictionnary
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @prefix: the prefix of the userdata
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @plen: the prefix length
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @name: the name of the userdata
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @len: the length of the name, if -1 it is recomputed
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add the QName to the array[s]
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the pointer of the local string, or NULL in case of error.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const xmlChar *
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, int plen,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const xmlChar *name, int namelen)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictStringsPtr pool;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ret;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (prefix == NULL) return(xmlDictAddString(dict, name, namelen));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DICT_DEBUG_PATTERNS
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "=");
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool = dict->strings;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (pool != NULL) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pool->end - pool->free > namelen + plen + 1)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto found_pool;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pool->size > size) size = pool->size;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool = pool->next;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Not found, need to allocate
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pool == NULL) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (size == 0) size = 1000;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else size *= 4; /* exponential growth */
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (size < 4 * (namelen + plen + 1))
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    size = 4 * (namelen + plen + 1); /* just in case ! */
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pool == NULL)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(NULL);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool->size = size;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool->nbStrings = 0;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool->free = &pool->array[0];
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool->end = &pool->array[size];
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool->next = dict->strings;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dict->strings = pool;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DICT_DEBUG_PATTERNS
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr, "+");
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)found_pool:
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = pool->free;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(pool->free, prefix, plen);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool->free += plen;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *(pool->free++) = ':';
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(pool->free, name, namelen);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool->free += namelen;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *(pool->free++) = 0;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool->nbStrings++;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(ret);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_BIG_KEY
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictComputeBigKey:
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Calculate a hash key using a good hash function that works well for
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * larger hash table sizes.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Hash function by "One-at-a-Time Hash" see
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://burtleburtle.net/bob/hash/doobs.html
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static uint32_t
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictComputeBigKey(const xmlChar* data, int namelen) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t hash;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (namelen <= 0 || data == NULL) return(0);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash = 0;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0;i < namelen; i++) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hash += data[i];
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hash += (hash << 10);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hash ^= (hash >> 6);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash += (hash << 3);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash ^= (hash >> 11);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash += (hash << 15);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hash;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictComputeBigQKey:
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Calculate a hash key for two strings using a good hash function
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that works well for larger hash table sizes.
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Hash function by "One-at-a-Time Hash" see
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://burtleburtle.net/bob/hash/doobs.html
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Neither of the two strings must be NULL.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned long
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const xmlChar *name, int len)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t hash;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash = 0;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0;i < plen; i++) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hash += prefix[i];
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hash += (hash << 10);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hash ^= (hash >> 6);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash += ':';
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash += (hash << 10);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash ^= (hash >> 6);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0;i < len; i++) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hash += name[i];
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hash += (hash << 10);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hash ^= (hash >> 6);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash += (hash << 3);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash ^= (hash >> 11);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash += (hash << 15);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hash;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* WITH_BIG_KEY */
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictComputeFastKey:
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Calculate a hash key using a fast hash function that works well
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for low hash table fill.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned long
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictComputeFastKey(const xmlChar *name, int namelen) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long value = 0L;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name == NULL) return(0);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value = *name;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value <<= 5;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (namelen > 10) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value += name[namelen - 1];
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        namelen = 10;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (namelen) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 10: value += name[9];
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 9: value += name[8];
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 8: value += name[7];
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 7: value += name[6];
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 6: value += name[5];
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 5: value += name[4];
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 4: value += name[3];
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 3: value += name[2];
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 2: value += name[1];
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default: break;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(value);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictComputeFastQKey:
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Calculate a hash key for two strings using a fast hash function
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that works well for low hash table fill.
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Neither of the two strings must be NULL.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned long
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictComputeFastQKey(const xmlChar *prefix, int plen,
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const xmlChar *name, int len)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long value = 0L;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (plen == 0)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	value += 30 * (unsigned long) ':';
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	value += 30 * (*prefix);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (len > 10) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value += name[len - (plen + 1 + 1)];
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len = 10;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (plen > 10)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    plen = 10;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (plen) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 10: value += prefix[9];
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 9: value += prefix[8];
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 8: value += prefix[7];
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 7: value += prefix[6];
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 6: value += prefix[5];
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 5: value += prefix[4];
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 4: value += prefix[3];
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 3: value += prefix[2];
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 2: value += prefix[1];
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 1: value += prefix[0];
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default: break;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len -= plen;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (len > 0) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value += (unsigned long) ':';
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	len--;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (len) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 10: value += name[9];
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 9: value += name[8];
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 8: value += name[7];
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 7: value += name[6];
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 6: value += name[5];
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 5: value += name[4];
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 4: value += name[3];
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 3: value += name[2];
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 2: value += name[1];
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 1: value += name[0];
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default: break;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(value);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictCreate:
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create a new dictionary
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the newly created dictionnary, or NULL if an error occured.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictPtr
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictCreate(void) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictPtr dict;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xmlDictInitialized)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!xmlInitializeDict())
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return(NULL);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DICT_DEBUG_PATTERNS
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "C");
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict = xmlMalloc(sizeof(xmlDict));
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dict->ref_counter = 1;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dict->size = MIN_DICT_SIZE;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dict->nbElems = 0;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dict->strings = NULL;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dict->subdict = NULL;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (dict->dict) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(dict);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlFree(dict);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(NULL);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictCreateSub:
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @sub: an existing dictionnary
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create a new dictionary, inheriting strings from the read-only
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * dictionnary @sub. On lookup, strings are first searched in the
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * new dictionnary, then in @sub, and if not found are created in the
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * new dictionnary.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the newly created dictionnary, or NULL if an error occured.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictPtr
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictCreateSub(xmlDictPtr sub) {
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictPtr dict = xmlDictCreate();
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dict != NULL) && (sub != NULL)) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DICT_DEBUG_PATTERNS
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr, "R");
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dict->subdict = sub;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlDictReference(dict->subdict);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(dict);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictReference:
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dict: the dictionnary
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Increment the reference counter of a dictionary
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 0 in case of success and -1 in case of error
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictReference(xmlDictPtr dict) {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xmlDictInitialized)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!xmlInitializeDict())
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return(-1);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict == NULL) return -1;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlRMutexLock(xmlDictMutex);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->ref_counter++;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlRMutexUnlock(xmlDictMutex);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(0);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictGrow:
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dict: the dictionnary
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @size: the new size of the dictionnary
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * resize the dictionnary
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 0 in case of success, -1 in case of failure
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictGrow(xmlDictPtr dict, int size) {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long key, okey;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int oldsize, i;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictEntryPtr iter, next;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct _xmlDictEntry *olddict;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_GROW
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long nbElem = 0;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = 0;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int keep_keys = 1;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict == NULL)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(-1);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size < 8)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(-1);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size > 8 * 2048)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(-1);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DICT_DEBUG_PATTERNS
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "*");
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    oldsize = dict->size;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    olddict = dict->dict;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (olddict == NULL)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(-1);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (oldsize == MIN_DICT_SIZE)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        keep_keys = 0;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->dict = xmlMalloc(size * sizeof(xmlDictEntry));
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->dict == NULL) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dict->dict = olddict;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(-1);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(dict->dict, 0, size * sizeof(xmlDictEntry));
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->size = size;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*	If the two loops are merged, there would be situations where
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	a new entry needs to allocated and data copied into it from
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	the main dict. It is nicer to run through the array twice, first
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	copying all the elements in the main array (less probability of
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	allocate) and then the rest, so we only free in the second loop.
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < oldsize; i++) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (olddict[i].valid == 0)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    continue;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (keep_keys)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    okey = olddict[i].okey;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    okey = xmlDictComputeKey(dict, olddict[i].name, olddict[i].len);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	key = okey % dict->size;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dict->dict[key].valid == 0) {
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry));
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    dict->dict[key].next = NULL;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    dict->dict[key].okey = okey;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlDictEntryPtr entry;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    entry = xmlMalloc(sizeof(xmlDictEntry));
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (entry != NULL) {
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		entry->name = olddict[i].name;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		entry->len = olddict[i].len;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		entry->okey = okey;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		entry->next = dict->dict[key].next;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		entry->valid = 1;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		dict->dict[key].next = entry;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        /*
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * we don't have much ways to alert from herei
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * result is loosing an entry and unicity garantee
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 */
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        ret = -1;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_GROW
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	nbElem++;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < oldsize; i++) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	iter = olddict[i].next;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (iter) {
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    next = iter->next;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * put back the entry in the new dict
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     */
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (keep_keys)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		okey = iter->okey;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    else
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		okey = xmlDictComputeKey(dict, iter->name, iter->len);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    key = okey % dict->size;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (dict->dict[key].valid == 0) {
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		memcpy(&(dict->dict[key]), iter, sizeof(xmlDictEntry));
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		dict->dict[key].next = NULL;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		dict->dict[key].valid = 1;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		dict->dict[key].okey = okey;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xmlFree(iter);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		iter->next = dict->dict[key].next;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		iter->okey = okey;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		dict->dict[key].next = iter;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_GROW
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    nbElem++;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    iter = next;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(olddict);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_GROW
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlGenericError(xmlGenericErrorContext,
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "xmlDictGrow : from %d to %d, %d elems\n", oldsize, size, nbElem);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(ret);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictFree:
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dict: the dictionnary
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Free the hash @dict and its contents. The userdata is
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * deallocated with @f if provided.
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictFree(xmlDictPtr dict) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictEntryPtr iter;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictEntryPtr next;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int inside_dict = 0;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictStringsPtr pool, nextp;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict == NULL)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xmlDictInitialized)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!xmlInitializeDict())
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* decrement the counter, it may be shared by a parser and docs */
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlRMutexLock(xmlDictMutex);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->ref_counter--;
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->ref_counter > 0) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlRMutexUnlock(xmlDictMutex);
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlRMutexUnlock(xmlDictMutex);
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->subdict != NULL) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlDictFree(dict->subdict);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->dict) {
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) {
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    iter = &(dict->dict[i]);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (iter->valid == 0)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		continue;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    inside_dict = 1;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    while (iter) {
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		next = iter->next;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (!inside_dict)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    xmlFree(iter);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		dict->nbElems--;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		inside_dict = 0;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		iter = next;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(dict->dict);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool = dict->strings;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (pool != NULL) {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nextp = pool->next;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(pool);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool = nextp;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(dict);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictLookup:
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dict: the dictionnary
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @name: the name of the userdata
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @len: the length of the name, if -1 it is recomputed
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add the @name to the dictionnary @dict if not present.
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the internal copy of the name or NULL in case of internal error
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const xmlChar *
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long key, okey, nbi = 0;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictEntryPtr entry;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictEntryPtr insert;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ret;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dict == NULL) || (name == NULL))
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (len < 0)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len = strlen((const char *) name);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Check for duplicate and insertion location.
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    okey = xmlDictComputeKey(dict, name, len);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key = okey % dict->size;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->dict[key].valid == 0) {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	insert = NULL;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (insert = &(dict->dict[key]); insert->next != NULL;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     insert = insert->next) {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((insert->okey == okey) && (insert->len == len)) {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (!memcmp(insert->name, name, len))
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    return(insert->name);
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((insert->okey == okey) && (insert->len == len) &&
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        (!xmlStrncmp(insert->name, name, len)))
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return(insert->name);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    nbi++;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((insert->okey == okey) && (insert->len == len)) {
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (!memcmp(insert->name, name, len))
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return(insert->name);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((insert->okey == okey) && (insert->len == len) &&
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (!xmlStrncmp(insert->name, name, len)))
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(insert->name);
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->subdict) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unsigned long skey;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* we cannot always reuse the same okey for the subdict */
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (((dict->size == MIN_DICT_SIZE) &&
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     (dict->subdict->size != MIN_DICT_SIZE)) ||
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ((dict->size != MIN_DICT_SIZE) &&
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     (dict->subdict->size == MIN_DICT_SIZE)))
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    skey = xmlDictComputeKey(dict->subdict, name, len);
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    skey = okey;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	key = skey % dict->subdict->size;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dict->subdict->dict[key].valid != 0) {
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlDictEntryPtr tmp;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 tmp = tmp->next) {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ((tmp->okey == skey) && (tmp->len == len)) {
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (!memcmp(tmp->name, name, len))
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return(tmp->name);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ((tmp->okey == skey) && (tmp->len == len) &&
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (!xmlStrncmp(tmp->name, name, len)))
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    return(tmp->name);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		nbi++;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((tmp->okey == skey) && (tmp->len == len)) {
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (!memcmp(tmp->name, name, len))
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    return(tmp->name);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((tmp->okey == skey) && (tmp->len == len) &&
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(!xmlStrncmp(tmp->name, name, len)))
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return(tmp->name);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	key = okey % dict->size;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = xmlDictAddString(dict, name, len);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(NULL);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (insert == NULL) {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	entry = &(dict->dict[key]);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	entry = xmlMalloc(sizeof(xmlDictEntry));
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (entry == NULL)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     return(NULL);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->name = ret;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->len = len;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->next = NULL;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->valid = 1;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->okey = okey;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (insert != NULL)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	insert->next = entry;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->nbElems++;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nbi > MAX_HASH_LEN) &&
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size) != 0)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(NULL);
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Note that entry may have been freed at this point by xmlDictGrow */
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(ret);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictExists:
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dict: the dictionnary
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @name: the name of the userdata
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @len: the length of the name, if -1 it is recomputed
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Check if the @name exists in the dictionnary @dict.
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the internal copy of the name or NULL if not found.
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const xmlChar *
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long key, okey, nbi = 0;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictEntryPtr insert;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dict == NULL) || (name == NULL))
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (len < 0)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len = strlen((const char *) name);
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Check for duplicate and insertion location.
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    okey = xmlDictComputeKey(dict, name, len);
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key = okey % dict->size;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->dict[key].valid == 0) {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	insert = NULL;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (insert = &(dict->dict[key]); insert->next != NULL;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     insert = insert->next) {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((insert->okey == okey) && (insert->len == len)) {
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (!memcmp(insert->name, name, len))
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    return(insert->name);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((insert->okey == okey) && (insert->len == len) &&
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        (!xmlStrncmp(insert->name, name, len)))
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return(insert->name);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    nbi++;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((insert->okey == okey) && (insert->len == len)) {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (!memcmp(insert->name, name, len))
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return(insert->name);
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((insert->okey == okey) && (insert->len == len) &&
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (!xmlStrncmp(insert->name, name, len)))
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(insert->name);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->subdict) {
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unsigned long skey;
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* we cannot always reuse the same okey for the subdict */
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (((dict->size == MIN_DICT_SIZE) &&
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     (dict->subdict->size != MIN_DICT_SIZE)) ||
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ((dict->size != MIN_DICT_SIZE) &&
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     (dict->subdict->size == MIN_DICT_SIZE)))
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    skey = xmlDictComputeKey(dict->subdict, name, len);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    skey = okey;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	key = skey % dict->subdict->size;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dict->subdict->dict[key].valid != 0) {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlDictEntryPtr tmp;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 tmp = tmp->next) {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ((tmp->okey == skey) && (tmp->len == len)) {
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (!memcmp(tmp->name, name, len))
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return(tmp->name);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ((tmp->okey == skey) && (tmp->len == len) &&
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (!xmlStrncmp(tmp->name, name, len)))
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    return(tmp->name);
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		nbi++;
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((tmp->okey == skey) && (tmp->len == len)) {
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (!memcmp(tmp->name, name, len))
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    return(tmp->name);
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((tmp->okey == skey) && (tmp->len == len) &&
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(!xmlStrncmp(tmp->name, name, len)))
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return(tmp->name);
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* not found */
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(NULL);
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictQLookup:
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dict: the dictionnary
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @prefix: the prefix
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @name: the name
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add the QName @prefix:@name to the hash @dict if not present.
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the internal copy of the QName or NULL in case of internal error
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const xmlChar *
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long okey, key, nbi = 0;
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictEntryPtr entry;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictEntryPtr insert;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ret;
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int len, plen, l;
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dict == NULL) || (name == NULL))
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (prefix == NULL)
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(xmlDictLookup(dict, name, -1));
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l = len = strlen((const char *) name);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plen = strlen((const char *) prefix);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len += 1 + plen;
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Check for duplicate and insertion location.
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    okey = xmlDictComputeQKey(dict, prefix, plen, name, l);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key = okey % dict->size;
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->dict[key].valid == 0) {
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	insert = NULL;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (insert = &(dict->dict[key]); insert->next != NULL;
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     insert = insert->next) {
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((insert->okey == okey) && (insert->len == len) &&
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        (xmlStrQEqual(prefix, name, insert->name)))
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return(insert->name);
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    nbi++;
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((insert->okey == okey) && (insert->len == len) &&
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (xmlStrQEqual(prefix, name, insert->name)))
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(insert->name);
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->subdict) {
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unsigned long skey;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* we cannot always reuse the same okey for the subdict */
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (((dict->size == MIN_DICT_SIZE) &&
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     (dict->subdict->size != MIN_DICT_SIZE)) ||
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ((dict->size != MIN_DICT_SIZE) &&
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     (dict->subdict->size == MIN_DICT_SIZE)))
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    skey = xmlDictComputeQKey(dict->subdict, prefix, plen, name, l);
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    skey = okey;
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	key = skey % dict->subdict->size;
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dict->subdict->dict[key].valid != 0) {
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlDictEntryPtr tmp;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 tmp = tmp->next) {
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ((tmp->okey == skey) && (tmp->len == len) &&
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (xmlStrQEqual(prefix, name, tmp->name)))
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    return(tmp->name);
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		nbi++;
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((tmp->okey == skey) && (tmp->len == len) &&
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(xmlStrQEqual(prefix, name, tmp->name)))
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return(tmp->name);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	key = okey % dict->size;
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = xmlDictAddQString(dict, prefix, plen, name, l);
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(NULL);
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (insert == NULL) {
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	entry = &(dict->dict[key]);
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	entry = xmlMalloc(sizeof(xmlDictEntry));
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (entry == NULL)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     return(NULL);
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->name = ret;
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->len = len;
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->next = NULL;
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->valid = 1;
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->okey = okey;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (insert != NULL)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	insert->next = entry;
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->nbElems++;
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nbi > MAX_HASH_LEN) &&
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN)))
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size);
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Note that entry may have been freed at this point by xmlDictGrow */
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(ret);
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictOwns:
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dict: the dictionnary
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @str: the string
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * check if a string is owned by the disctionary
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 1 if true, 0 if false and -1 in case of error
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * -1 in case of error
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictOwns(xmlDictPtr dict, const xmlChar *str) {
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlDictStringsPtr pool;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dict == NULL) || (str == NULL))
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(-1);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool = dict->strings;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (pool != NULL) {
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((str >= &pool->array[0]) && (str <= pool->free))
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return(1);
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pool = pool->next;
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->subdict)
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(xmlDictOwns(dict->subdict, str));
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(0);
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xmlDictSize:
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dict: the dictionnary
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Query the number of elements installed in the hash @dict.
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the number of elements in the dictionnary or
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * -1 in case of error
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlDictSize(xmlDictPtr dict) {
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict == NULL)
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(-1);
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dict->subdict)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(dict->nbElems + dict->subdict->nbElems);
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(dict->nbElems);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define bottom_dict
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "elfgcchack.h"
1101