2003-08-18 12:15:38 +00:00
/*
* dict . c : dictionary of reusable strings , just used to avoid allocation
* and freeing operations .
*
* Copyright ( C ) 2003 Daniel Veillard .
*
* Permission to use , copy , modify , and distribute this software for any
* purpose with or without fee is hereby granted , provided that the above
* copyright notice and this permission notice appear in all copies .
*
* THIS SOFTWARE IS PROVIDED ` ` AS IS ' ' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES , INCLUDING , WITHOUT LIMITATION , THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE . THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER .
*
* Author : daniel @ veillard . com
*/
# define IN_LIBXML
# include "libxml.h"
# include <string.h>
# include <libxml/tree.h>
# include <libxml/dict.h>
# include <libxml/xmlmemory.h>
# include <libxml/xmlerror.h>
# include <libxml/globals.h>
# define MAX_HASH_LEN 4
# define MIN_DICT_SIZE 128
# define MAX_DICT_HASH 8 * 2048
/* #define ALLOW_REMOVAL */
/* #define DEBUG_GROW */
/*
* An entry in the dictionnary
*/
typedef struct _xmlDictEntry xmlDictEntry ;
typedef xmlDictEntry * xmlDictEntryPtr ;
struct _xmlDictEntry {
struct _xmlDictEntry * next ;
2003-09-16 23:17:26 +00:00
const xmlChar * name ;
2003-08-18 12:15:38 +00:00
int len ;
int valid ;
} ;
2003-09-16 23:17:26 +00:00
typedef struct _xmlDictStrings xmlDictStrings ;
typedef xmlDictStrings * xmlDictStringsPtr ;
struct _xmlDictStrings {
xmlDictStringsPtr next ;
xmlChar * free ;
xmlChar * end ;
int size ;
int nbStrings ;
xmlChar array [ 1 ] ;
} ;
2003-08-18 12:15:38 +00:00
/*
* The entire dictionnary
*/
struct _xmlDict {
2003-09-24 21:23:56 +00:00
int ref_counter ;
2003-08-18 12:15:38 +00:00
struct _xmlDictEntry * dict ;
int size ;
int nbElems ;
2003-09-16 23:17:26 +00:00
xmlDictStringsPtr strings ;
2004-01-23 13:15:13 +00:00
struct _xmlDict * subdict ;
2003-08-18 12:15:38 +00:00
} ;
2003-09-16 23:17:26 +00:00
/*
* xmlDictAddString :
* @ dict : the dictionnary
* @ name : the name of the userdata
* @ len : the length of the name , if - 1 it is recomputed
*
* Add the string to the array [ s ]
*
* Returns the pointer of the local string , or NULL in case of error .
*/
static const xmlChar *
xmlDictAddString ( xmlDictPtr dict , const xmlChar * name , int namelen ) {
xmlDictStringsPtr pool ;
const xmlChar * ret ;
int size = 0 ; /* + sizeof(_xmlDictStrings) == 1024 */
pool = dict - > strings ;
while ( pool ! = NULL ) {
if ( pool - > end - pool - > free > namelen )
goto found_pool ;
if ( pool - > size > size ) size = pool - > size ;
pool = pool - > next ;
}
/*
* Not found , need to allocate
*/
if ( pool = = NULL ) {
if ( size = = 0 ) size = 1000 ;
else size * = 4 ; /* exponential growth */
if ( size < 4 * namelen )
size = 4 * namelen ; /* just in case ! */
pool = ( xmlDictStringsPtr ) xmlMalloc ( sizeof ( xmlDictStrings ) + size ) ;
if ( pool = = NULL )
return ( NULL ) ;
pool - > size = size ;
pool - > nbStrings = 0 ;
pool - > free = & pool - > array [ 0 ] ;
pool - > end = & pool - > array [ size ] ;
pool - > next = dict - > strings ;
dict - > strings = pool ;
}
found_pool :
ret = pool - > free ;
memcpy ( pool - > free , name , namelen ) ;
pool - > free + = namelen ;
* ( pool - > free + + ) = 0 ;
return ( ret ) ;
}
2003-09-19 12:44:05 +00:00
/*
* xmlDictAddQString :
* @ dict : the dictionnary
* @ prefix : the prefix of the userdata
* @ name : the name of the userdata
* @ len : the length of the name , if - 1 it is recomputed
*
* Add the QName to the array [ s ]
*
* Returns the pointer of the local string , or NULL in case of error .
*/
static const xmlChar *
xmlDictAddQString ( xmlDictPtr dict , const xmlChar * prefix ,
const xmlChar * name , int namelen )
{
xmlDictStringsPtr pool ;
const xmlChar * ret ;
int size = 0 ; /* + sizeof(_xmlDictStrings) == 1024 */
int plen ;
if ( prefix = = NULL ) return ( xmlDictAddString ( dict , name , namelen ) ) ;
plen = xmlStrlen ( prefix ) ;
pool = dict - > strings ;
while ( pool ! = NULL ) {
if ( pool - > end - pool - > free > namelen )
goto found_pool ;
if ( pool - > size > size ) size = pool - > size ;
pool = pool - > next ;
}
/*
* Not found , need to allocate
*/
if ( pool = = NULL ) {
if ( size = = 0 ) size = 1000 ;
else size * = 4 ; /* exponential growth */
if ( size < 4 * namelen )
size = 4 * namelen ; /* just in case ! */
pool = ( xmlDictStringsPtr ) xmlMalloc ( sizeof ( xmlDictStrings ) + size ) ;
if ( pool = = NULL )
return ( NULL ) ;
pool - > size = size ;
pool - > nbStrings = 0 ;
pool - > free = & pool - > array [ 0 ] ;
pool - > end = & pool - > array [ size ] ;
pool - > next = dict - > strings ;
dict - > strings = pool ;
}
found_pool :
ret = pool - > free ;
memcpy ( pool - > free , prefix , plen ) ;
pool - > free + = plen ;
* ( pool - > free + + ) = ' : ' ;
namelen - = plen + 1 ;
memcpy ( pool - > free , name , namelen ) ;
pool - > free + = namelen ;
* ( pool - > free + + ) = 0 ;
return ( ret ) ;
}
2003-08-18 12:15:38 +00:00
/*
* xmlDictComputeKey :
* Calculate the hash key
*/
static unsigned long
2004-01-23 13:15:13 +00:00
xmlDictComputeKey ( const xmlChar * name , int namelen ) {
2003-08-18 12:15:38 +00:00
unsigned long value = 0L ;
if ( name = = NULL ) return ( 0 ) ;
2004-01-23 13:15:13 +00:00
value = * name ;
value < < = 5 ;
2003-08-18 12:15:38 +00:00
if ( namelen > 10 ) {
value + = name [ namelen - 1 ] ;
namelen = 10 ;
}
switch ( namelen ) {
case 10 : value + = name [ 9 ] ;
case 9 : value + = name [ 8 ] ;
case 8 : value + = name [ 7 ] ;
case 7 : value + = name [ 6 ] ;
case 6 : value + = name [ 5 ] ;
case 5 : value + = name [ 4 ] ;
case 4 : value + = name [ 3 ] ;
case 3 : value + = name [ 2 ] ;
case 2 : value + = name [ 1 ] ;
default : break ;
}
2004-01-23 13:15:13 +00:00
return ( value ) ;
2003-09-19 12:44:05 +00:00
}
/*
* xmlDictComputeQKey :
* Calculate the hash key
*/
static unsigned long
2004-01-23 13:15:13 +00:00
xmlDictComputeQKey ( const xmlChar * prefix , const xmlChar * name , int len )
2003-09-19 12:44:05 +00:00
{
unsigned long value = 0L ;
int plen ;
if ( prefix = = NULL )
2004-01-23 13:15:13 +00:00
return ( xmlDictComputeKey ( name , len ) ) ;
2003-09-19 12:44:05 +00:00
plen = xmlStrlen ( prefix ) ;
if ( plen = = 0 )
value + = 30 * ( unsigned long ) ' : ' ;
else
value + = 30 * ( * prefix ) ;
if ( len > 10 ) {
value + = name [ len - ( plen + 1 + 1 ) ] ;
len = 10 ;
if ( plen > 10 )
plen = 10 ;
}
switch ( plen ) {
case 10 : value + = prefix [ 9 ] ;
case 9 : value + = prefix [ 8 ] ;
case 8 : value + = prefix [ 7 ] ;
case 7 : value + = prefix [ 6 ] ;
case 6 : value + = prefix [ 5 ] ;
case 5 : value + = prefix [ 4 ] ;
case 4 : value + = prefix [ 3 ] ;
case 3 : value + = prefix [ 2 ] ;
case 2 : value + = prefix [ 1 ] ;
case 1 : value + = prefix [ 0 ] ;
default : break ;
2003-08-18 12:15:38 +00:00
}
2003-09-19 12:44:05 +00:00
len - = plen ;
if ( len > 0 ) {
value + = ( unsigned long ) ' : ' ;
len - - ;
}
switch ( len ) {
case 10 : value + = name [ 9 ] ;
case 9 : value + = name [ 8 ] ;
case 8 : value + = name [ 7 ] ;
case 7 : value + = name [ 6 ] ;
case 6 : value + = name [ 5 ] ;
case 5 : value + = name [ 4 ] ;
case 4 : value + = name [ 3 ] ;
case 3 : value + = name [ 2 ] ;
case 2 : value + = name [ 1 ] ;
case 1 : value + = name [ 0 ] ;
default : break ;
2003-08-18 12:15:38 +00:00
}
2004-01-23 13:15:13 +00:00
return ( value ) ;
2003-08-18 12:15:38 +00:00
}
/**
* xmlDictCreate :
*
* Create a new dictionary
*
2004-01-23 13:15:13 +00:00
* Returns the newly created dictionnary , or NULL if an error occured .
2003-08-18 12:15:38 +00:00
*/
xmlDictPtr
xmlDictCreate ( void ) {
xmlDictPtr dict ;
dict = xmlMalloc ( sizeof ( xmlDict ) ) ;
if ( dict ) {
2003-09-24 21:23:56 +00:00
dict - > ref_counter = 1 ;
2003-08-18 12:15:38 +00:00
dict - > size = MIN_DICT_SIZE ;
dict - > nbElems = 0 ;
dict - > dict = xmlMalloc ( MIN_DICT_SIZE * sizeof ( xmlDictEntry ) ) ;
2003-09-16 23:17:26 +00:00
dict - > strings = NULL ;
2004-01-23 13:15:13 +00:00
dict - > subdict = NULL ;
2003-08-18 12:15:38 +00:00
if ( dict - > dict ) {
memset ( dict - > dict , 0 , MIN_DICT_SIZE * sizeof ( xmlDictEntry ) ) ;
return ( dict ) ;
}
xmlFree ( dict ) ;
}
return ( NULL ) ;
}
2004-01-23 13:15:13 +00:00
/**
* xmlDictCreateSub :
* @ sub : an existing dictionnary
*
* Create a new dictionary , inheriting strings from the read - only
* dictionnary @ sub . On lookup , strings are first searched in the
* new dictionnary , then in @ sub , and if not found are created in the
* new dictionnary .
*
* Returns the newly created dictionnary , or NULL if an error occured .
*/
xmlDictPtr
xmlDictCreateSub ( xmlDictPtr sub ) {
xmlDictPtr dict = xmlDictCreate ( ) ;
if ( ( dict ! = NULL ) & & ( sub ! = NULL ) ) {
dict - > subdict = sub ;
xmlDictReference ( dict - > subdict ) ;
}
return ( dict ) ;
}
2003-09-24 21:23:56 +00:00
/**
* xmlDictReference :
* @ dict : the dictionnary
*
* Increment the reference counter of a dictionary
*
* Returns 0 in case of success and - 1 in case of error
*/
int
xmlDictReference ( xmlDictPtr dict ) {
if ( dict = = NULL ) return - 1 ;
dict - > ref_counter + + ;
return ( 0 ) ;
}
2003-08-18 12:15:38 +00:00
/**
* xmlDictGrow :
* @ dict : the dictionnary
* @ size : the new size of the dictionnary
*
* resize the dictionnary
*
* Returns 0 in case of success , - 1 in case of failure
*/
static int
xmlDictGrow ( xmlDictPtr dict , int size ) {
unsigned long key ;
int oldsize , i ;
xmlDictEntryPtr iter , next ;
struct _xmlDictEntry * olddict ;
# ifdef DEBUG_GROW
unsigned long nbElem = 0 ;
# endif
if ( dict = = NULL )
return ( - 1 ) ;
if ( size < 8 )
return ( - 1 ) ;
if ( size > 8 * 2048 )
return ( - 1 ) ;
oldsize = dict - > size ;
olddict = dict - > dict ;
if ( olddict = = NULL )
return ( - 1 ) ;
dict - > dict = xmlMalloc ( size * sizeof ( xmlDictEntry ) ) ;
if ( dict - > dict = = NULL ) {
dict - > dict = olddict ;
return ( - 1 ) ;
}
memset ( dict - > dict , 0 , size * sizeof ( xmlDictEntry ) ) ;
dict - > size = size ;
/* If the two loops are merged, there would be situations where
a new entry needs to allocated and data copied into it from
the main dict . So instead , we run through the array twice , first
copying all the elements in the main array ( where we can ' t get
conflicts ) and then the rest , so we only free ( and don ' t allocate )
*/
for ( i = 0 ; i < oldsize ; i + + ) {
if ( olddict [ i ] . valid = = 0 )
continue ;
2004-01-23 13:15:13 +00:00
key = xmlDictComputeKey ( olddict [ i ] . name , olddict [ i ] . len ) % dict - > size ;
2003-08-18 12:15:38 +00:00
memcpy ( & ( dict - > dict [ key ] ) , & ( olddict [ i ] ) , sizeof ( xmlDictEntry ) ) ;
dict - > dict [ key ] . next = NULL ;
# ifdef DEBUG_GROW
nbElem + + ;
# endif
}
for ( i = 0 ; i < oldsize ; i + + ) {
iter = olddict [ i ] . next ;
while ( iter ) {
next = iter - > next ;
/*
* put back the entry in the new dict
*/
2004-01-23 13:15:13 +00:00
key = xmlDictComputeKey ( iter - > name , iter - > len ) % dict - > size ;
2003-08-18 12:15:38 +00:00
if ( dict - > dict [ key ] . valid = = 0 ) {
memcpy ( & ( dict - > dict [ key ] ) , iter , sizeof ( xmlDictEntry ) ) ;
dict - > dict [ key ] . next = NULL ;
dict - > dict [ key ] . valid = 1 ;
xmlFree ( iter ) ;
} else {
iter - > next = dict - > dict [ key ] . next ;
dict - > dict [ key ] . next = iter ;
}
# ifdef DEBUG_GROW
nbElem + + ;
# endif
iter = next ;
}
}
xmlFree ( olddict ) ;
# ifdef DEBUG_GROW
xmlGenericError ( xmlGenericErrorContext ,
" xmlDictGrow : from %d to %d, %d elems \n " , oldsize , size , nbElem ) ;
# endif
return ( 0 ) ;
}
/**
* xmlDictFree :
* @ dict : the dictionnary
*
* Free the hash @ dict and its contents . The userdata is
* deallocated with @ f if provided .
*/
void
xmlDictFree ( xmlDictPtr dict ) {
int i ;
xmlDictEntryPtr iter ;
xmlDictEntryPtr next ;
int inside_dict = 0 ;
2003-09-16 23:17:26 +00:00
xmlDictStringsPtr pool , nextp ;
2003-08-18 12:15:38 +00:00
if ( dict = = NULL )
return ;
2003-09-24 21:23:56 +00:00
/* decrement the counter, it may be shared by a parser and docs */
dict - > ref_counter - - ;
if ( dict - > ref_counter > 0 ) return ;
2004-01-23 13:15:13 +00:00
if ( dict - > subdict ! = NULL ) {
xmlDictFree ( dict - > subdict ) ;
}
2003-08-18 12:15:38 +00:00
if ( dict - > dict ) {
2003-08-19 15:01:28 +00:00
for ( i = 0 ; ( ( i < dict - > size ) & & ( dict - > nbElems > 0 ) ) ; i + + ) {
2003-08-18 12:15:38 +00:00
iter = & ( dict - > dict [ i ] ) ;
if ( iter - > valid = = 0 )
continue ;
inside_dict = 1 ;
while ( iter ) {
next = iter - > next ;
if ( ! inside_dict )
xmlFree ( iter ) ;
2003-08-19 15:01:28 +00:00
dict - > nbElems - - ;
2003-08-18 12:15:38 +00:00
inside_dict = 0 ;
iter = next ;
}
inside_dict = 0 ;
}
xmlFree ( dict - > dict ) ;
}
2003-09-16 23:17:26 +00:00
pool = dict - > strings ;
while ( pool ! = NULL ) {
nextp = pool - > next ;
xmlFree ( pool ) ;
pool = nextp ;
}
2003-08-18 12:15:38 +00:00
xmlFree ( dict ) ;
}
/**
* xmlDictLookup :
* @ dict : the dictionnary
* @ name : the name of the userdata
2003-09-07 09:14:37 +00:00
* @ len : the length of the name , if - 1 it is recomputed
2003-08-18 12:15:38 +00:00
*
2004-11-24 12:39:00 +00:00
* Add the @ name to the dictionnary @ dict if not present .
2003-08-18 12:15:38 +00:00
*
* Returns the internal copy of the name or NULL in case of internal error
*/
const xmlChar *
xmlDictLookup ( xmlDictPtr dict , const xmlChar * name , int len ) {
2004-01-23 13:15:13 +00:00
unsigned long key , okey , nbi = 0 ;
2003-08-18 12:15:38 +00:00
xmlDictEntryPtr entry ;
xmlDictEntryPtr insert ;
const xmlChar * ret ;
2003-09-07 09:14:37 +00:00
if ( ( dict = = NULL ) | | ( name = = NULL ) )
return ( NULL ) ;
if ( len < 0 )
len = xmlStrlen ( name ) ;
2003-08-18 12:15:38 +00:00
/*
* Check for duplicate and insertion location .
*/
2004-01-23 13:15:13 +00:00
okey = xmlDictComputeKey ( name , len ) ;
key = okey % dict - > size ;
2003-08-18 12:15:38 +00:00
if ( dict - > dict [ key ] . valid = = 0 ) {
insert = NULL ;
} else {
for ( insert = & ( dict - > dict [ key ] ) ; insert - > next ! = NULL ;
insert = insert - > next ) {
2004-01-12 16:24:34 +00:00
# ifdef __GNUC__
if ( insert - > len = = len ) {
2004-01-23 13:15:13 +00:00
if ( ! memcmp ( insert - > name , name , len ) )
2004-01-12 16:24:34 +00:00
return ( insert - > name ) ;
}
# else
2003-08-18 12:15:38 +00:00
if ( ( insert - > len = = len ) & &
( ! xmlStrncmp ( insert - > name , name , len ) ) )
return ( insert - > name ) ;
2004-01-12 16:24:34 +00:00
# endif
2003-08-18 12:15:38 +00:00
nbi + + ;
}
2004-01-12 16:24:34 +00:00
# ifdef __GNUC__
if ( insert - > len = = len ) {
2004-01-23 13:15:13 +00:00
if ( ! memcmp ( insert - > name , name , len ) )
2004-01-12 16:24:34 +00:00
return ( insert - > name ) ;
}
# else
2003-08-18 12:15:38 +00:00
if ( ( insert - > len = = len ) & &
( ! xmlStrncmp ( insert - > name , name , len ) ) )
return ( insert - > name ) ;
2004-01-12 16:24:34 +00:00
# endif
2003-08-18 12:15:38 +00:00
}
2004-01-23 13:15:13 +00:00
if ( dict - > subdict ) {
key = okey % dict - > subdict - > size ;
if ( dict - > subdict - > dict [ key ] . valid ! = 0 ) {
xmlDictEntryPtr tmp ;
for ( tmp = & ( dict - > subdict - > dict [ key ] ) ; tmp - > next ! = NULL ;
tmp = tmp - > next ) {
# ifdef __GNUC__
if ( tmp - > len = = len ) {
if ( ! memcmp ( tmp - > name , name , len ) )
return ( tmp - > name ) ;
}
# else
if ( ( tmp - > len = = len ) & &
( ! xmlStrncmp ( tmp - > name , name , len ) ) )
return ( tmp - > name ) ;
# endif
nbi + + ;
}
# ifdef __GNUC__
if ( tmp - > len = = len ) {
if ( ! memcmp ( tmp - > name , name , len ) )
return ( tmp - > name ) ;
}
# else
if ( ( tmp - > len = = len ) & &
( ! xmlStrncmp ( tmp - > name , name , len ) ) )
return ( tmp - > name ) ;
# endif
}
key = okey % dict - > size ;
}
2003-09-16 23:17:26 +00:00
ret = xmlDictAddString ( dict , name , len ) ;
if ( ret = = NULL )
return ( NULL ) ;
2003-08-18 12:15:38 +00:00
if ( insert = = NULL ) {
entry = & ( dict - > dict [ key ] ) ;
} else {
entry = xmlMalloc ( sizeof ( xmlDictEntry ) ) ;
if ( entry = = NULL )
return ( NULL ) ;
}
2003-09-16 23:17:26 +00:00
entry - > name = ret ;
2003-08-18 12:15:38 +00:00
entry - > len = len ;
entry - > next = NULL ;
entry - > valid = 1 ;
2003-09-19 12:44:05 +00:00
if ( insert ! = NULL )
insert - > next = entry ;
dict - > nbElems + + ;
if ( ( nbi > MAX_HASH_LEN ) & &
( dict - > size < = ( ( MAX_DICT_HASH / 2 ) / MAX_HASH_LEN ) ) )
xmlDictGrow ( dict , MAX_HASH_LEN * 2 * dict - > size ) ;
/* Note that entry may have been freed at this point by xmlDictGrow */
return ( ret ) ;
}
2004-11-24 12:39:00 +00:00
/**
* xmlDictExists :
* @ dict : the dictionnary
* @ name : the name of the userdata
* @ len : the length of the name , if - 1 it is recomputed
*
* Check if the @ name exists in the dictionnary @ dict .
*
* Returns the internal copy of the name or NULL if not found .
*/
const xmlChar *
xmlDictExists ( xmlDictPtr dict , const xmlChar * name , int len ) {
unsigned long key , okey , nbi = 0 ;
xmlDictEntryPtr insert ;
if ( ( dict = = NULL ) | | ( name = = NULL ) )
return ( NULL ) ;
if ( len < 0 )
len = xmlStrlen ( name ) ;
/*
* Check for duplicate and insertion location .
*/
okey = xmlDictComputeKey ( name , len ) ;
key = okey % dict - > size ;
if ( dict - > dict [ key ] . valid = = 0 ) {
insert = NULL ;
} else {
for ( insert = & ( dict - > dict [ key ] ) ; insert - > next ! = NULL ;
insert = insert - > next ) {
# ifdef __GNUC__
if ( insert - > len = = len ) {
if ( ! memcmp ( insert - > name , name , len ) )
return ( insert - > name ) ;
}
# else
if ( ( insert - > len = = len ) & &
( ! xmlStrncmp ( insert - > name , name , len ) ) )
return ( insert - > name ) ;
# endif
nbi + + ;
}
# ifdef __GNUC__
if ( insert - > len = = len ) {
if ( ! memcmp ( insert - > name , name , len ) )
return ( insert - > name ) ;
}
# else
if ( ( insert - > len = = len ) & &
( ! xmlStrncmp ( insert - > name , name , len ) ) )
return ( insert - > name ) ;
# endif
}
if ( dict - > subdict ) {
key = okey % dict - > subdict - > size ;
if ( dict - > subdict - > dict [ key ] . valid ! = 0 ) {
xmlDictEntryPtr tmp ;
for ( tmp = & ( dict - > subdict - > dict [ key ] ) ; tmp - > next ! = NULL ;
tmp = tmp - > next ) {
# ifdef __GNUC__
if ( tmp - > len = = len ) {
if ( ! memcmp ( tmp - > name , name , len ) )
return ( tmp - > name ) ;
}
# else
if ( ( tmp - > len = = len ) & &
( ! xmlStrncmp ( tmp - > name , name , len ) ) )
return ( tmp - > name ) ;
# endif
nbi + + ;
}
# ifdef __GNUC__
if ( tmp - > len = = len ) {
if ( ! memcmp ( tmp - > name , name , len ) )
return ( tmp - > name ) ;
}
# else
if ( ( tmp - > len = = len ) & &
( ! xmlStrncmp ( tmp - > name , name , len ) ) )
return ( tmp - > name ) ;
# endif
}
key = okey % dict - > size ;
}
/* not found */
return ( NULL ) ;
}
2003-09-19 12:44:05 +00:00
/**
* xmlDictQLookup :
* @ dict : the dictionnary
* @ prefix : the prefix
* @ name : the name
*
* Add the QName @ prefix : @ name to the hash @ dict if not present .
*
* Returns the internal copy of the QName or NULL in case of internal error
*/
const xmlChar *
xmlDictQLookup ( xmlDictPtr dict , const xmlChar * prefix , const xmlChar * name ) {
2004-01-23 13:15:13 +00:00
unsigned long okey , key , nbi = 0 ;
2003-09-19 12:44:05 +00:00
xmlDictEntryPtr entry ;
xmlDictEntryPtr insert ;
const xmlChar * ret ;
int len ;
if ( ( dict = = NULL ) | | ( name = = NULL ) )
return ( NULL ) ;
len = xmlStrlen ( name ) ;
if ( prefix ! = NULL )
len + = 1 + xmlStrlen ( prefix ) ;
/*
* Check for duplicate and insertion location .
*/
2004-01-23 13:15:13 +00:00
okey = xmlDictComputeQKey ( prefix , name , len ) ;
key = okey % dict - > size ;
2003-09-19 12:44:05 +00:00
if ( dict - > dict [ key ] . valid = = 0 ) {
insert = NULL ;
} else {
for ( insert = & ( dict - > dict [ key ] ) ; insert - > next ! = NULL ;
insert = insert - > next ) {
if ( ( insert - > len = = len ) & &
( xmlStrQEqual ( prefix , name , insert - > name ) ) )
return ( insert - > name ) ;
nbi + + ;
}
if ( ( insert - > len = = len ) & &
( xmlStrQEqual ( prefix , name , insert - > name ) ) )
return ( insert - > name ) ;
}
2004-01-23 13:15:13 +00:00
if ( dict - > subdict ) {
key = okey % dict - > subdict - > size ;
if ( dict - > subdict - > dict [ key ] . valid ! = 0 ) {
xmlDictEntryPtr tmp ;
for ( tmp = & ( dict - > subdict - > dict [ key ] ) ; tmp - > next ! = NULL ;
tmp = tmp - > next ) {
if ( ( tmp - > len = = len ) & &
( xmlStrQEqual ( prefix , name , tmp - > name ) ) )
return ( tmp - > name ) ;
nbi + + ;
}
if ( ( tmp - > len = = len ) & &
( xmlStrQEqual ( prefix , name , tmp - > name ) ) )
return ( tmp - > name ) ;
}
key = okey % dict - > size ;
}
2003-09-19 12:44:05 +00:00
ret = xmlDictAddQString ( dict , prefix , name , len ) ;
if ( ret = = NULL )
return ( NULL ) ;
if ( insert = = NULL ) {
entry = & ( dict - > dict [ key ] ) ;
} else {
entry = xmlMalloc ( sizeof ( xmlDictEntry ) ) ;
if ( entry = = NULL )
return ( NULL ) ;
}
entry - > name = ret ;
entry - > len = len ;
entry - > next = NULL ;
entry - > valid = 1 ;
2003-08-18 12:15:38 +00:00
if ( insert ! = NULL )
insert - > next = entry ;
dict - > nbElems + + ;
if ( ( nbi > MAX_HASH_LEN ) & &
( dict - > size < = ( ( MAX_DICT_HASH / 2 ) / MAX_HASH_LEN ) ) )
xmlDictGrow ( dict , MAX_HASH_LEN * 2 * dict - > size ) ;
/* Note that entry may have been freed at this point by xmlDictGrow */
return ( ret ) ;
}
2003-09-16 23:17:26 +00:00
/**
* xmlDictOwns :
* @ dict : the dictionnary
* @ str : the string
*
* check if a string is owned by the disctionary
*
* Returns 1 if true , 0 if false and - 1 in case of error
* - 1 in case of error
*/
int
xmlDictOwns ( xmlDictPtr dict , const xmlChar * str ) {
xmlDictStringsPtr pool ;
if ( ( dict = = NULL ) | | ( str = = NULL ) )
return ( - 1 ) ;
pool = dict - > strings ;
while ( pool ! = NULL ) {
2004-08-31 06:47:17 +00:00
if ( ( str > = & pool - > array [ 0 ] ) & & ( str < = pool - > free ) )
2003-09-16 23:17:26 +00:00
return ( 1 ) ;
pool = pool - > next ;
}
2004-01-23 13:15:13 +00:00
if ( dict - > subdict )
return ( xmlDictOwns ( dict - > subdict , str ) ) ;
2003-09-16 23:17:26 +00:00
return ( 0 ) ;
}
2003-09-24 21:23:56 +00:00
2003-08-18 12:15:38 +00:00
/**
* xmlDictSize :
* @ dict : the dictionnary
*
* Query the number of elements installed in the hash @ dict .
*
* Returns the number of elements in the dictionnary or
* - 1 in case of error
*/
int
xmlDictSize ( xmlDictPtr dict ) {
if ( dict = = NULL )
return ( - 1 ) ;
2004-01-23 13:15:13 +00:00
if ( dict - > subdict )
return ( dict - > nbElems + dict - > subdict - > nbElems ) ;
2003-08-18 12:15:38 +00:00
return ( dict - > nbElems ) ;
}