2001-02-23 20:55:21 +03:00
/*
* hash . c : chained hash tables
*
* Reference : Your favorite introductory book on algorithms
*
2012-02-04 15:07:44 +04:00
* Copyright ( C ) 2000 , 2012 Bjorn Reese and Daniel Veillard .
2001-02-23 20:55:21 +03:00
*
* 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
2020-03-08 19:19:42 +03:00
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE . THE AUTHORS AND
2001-02-23 20:55:21 +03:00
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER .
*
2001-04-21 20:57:29 +04:00
* Author : breese @ users . sourceforge . net
2001-02-23 20:55:21 +03:00
*/
2002-03-18 22:37:11 +03:00
# define IN_LIBXML
2001-04-21 20:57:29 +04:00
# include "libxml.h"
2001-02-23 20:55:21 +03:00
# include <string.h>
2012-02-04 15:07:44 +04:00
# include <stdlib.h>
# include <time.h>
/*
* Following http : //www.ocert.org/advisories/ocert-2011-003.html
* it seems that having hash randomization might be a good idea
* when using XML with untrusted data
*/
2022-03-02 03:14:08 +03:00
# if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
2012-02-04 15:07:44 +04:00
# define HASH_RANDOMIZATION
# endif
2003-09-10 14:50:59 +04:00
# include <libxml/parser.h>
2001-02-23 20:55:21 +03:00
# include <libxml/hash.h>
# include <libxml/xmlmemory.h>
2001-04-18 17:09:01 +04:00
# include <libxml/xmlerror.h>
2001-10-17 19:58:35 +04:00
# include <libxml/globals.h>
2001-04-18 17:09:01 +04:00
2022-08-26 02:22:33 +03:00
# include "private/dict.h"
2001-04-18 17:09:01 +04:00
# define MAX_HASH_LEN 8
/* #define DEBUG_GROW */
2001-02-23 20:55:21 +03:00
/*
* A single entry in the hash table
*/
typedef struct _xmlHashEntry xmlHashEntry ;
typedef xmlHashEntry * xmlHashEntryPtr ;
struct _xmlHashEntry {
struct _xmlHashEntry * next ;
xmlChar * name ;
xmlChar * name2 ;
xmlChar * name3 ;
void * payload ;
2002-07-02 01:52:03 +04:00
int valid ;
2001-02-23 20:55:21 +03:00
} ;
/*
* The entire hash table
*/
struct _xmlHashTable {
2002-07-02 01:52:03 +04:00
struct _xmlHashEntry * table ;
2001-02-23 20:55:21 +03:00
int size ;
int nbElems ;
2005-01-24 01:56:39 +03:00
xmlDictPtr dict ;
2012-02-04 15:07:44 +04:00
# ifdef HASH_RANDOMIZATION
int random_seed ;
# endif
2001-02-23 20:55:21 +03:00
} ;
/*
* xmlHashComputeKey :
* Calculate the hash key
*/
2019-10-14 16:38:28 +03:00
# ifdef __clang__
2019-05-16 22:17:28 +03:00
ATTRIBUTE_NO_SANITIZE ( " unsigned-integer-overflow " )
2023-03-12 16:45:14 +03:00
ATTRIBUTE_NO_SANITIZE ( " unsigned-shift-base " )
2019-10-14 16:38:28 +03:00
# endif
2001-02-23 20:55:21 +03:00
static unsigned long
2001-04-18 17:09:01 +04:00
xmlHashComputeKey ( xmlHashTablePtr table , const xmlChar * name ,
const xmlChar * name2 , const xmlChar * name3 ) {
2001-02-23 20:55:21 +03:00
unsigned long value = 0L ;
2022-01-25 04:44:37 +03:00
unsigned long ch ;
2012-09-11 09:26:36 +04:00
2012-02-04 15:07:44 +04:00
# ifdef HASH_RANDOMIZATION
value = table - > random_seed ;
# endif
2001-04-18 17:09:01 +04:00
if ( name ! = NULL ) {
value + = 30 * ( * name ) ;
while ( ( ch = * name + + ) ! = 0 ) {
2022-01-25 04:44:37 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ch ) ;
2001-04-18 17:09:01 +04:00
}
}
2013-04-12 14:53:53 +04:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) ) ;
2001-04-18 17:09:01 +04:00
if ( name2 ! = NULL ) {
while ( ( ch = * name2 + + ) ! = 0 ) {
2022-01-25 04:44:37 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ch ) ;
2001-04-18 17:09:01 +04:00
}
}
2013-04-12 14:53:53 +04:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) ) ;
2001-04-18 17:09:01 +04:00
if ( name3 ! = NULL ) {
while ( ( ch = * name3 + + ) ! = 0 ) {
2022-01-25 04:44:37 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ch ) ;
2001-04-18 17:09:01 +04:00
}
2001-02-23 20:55:21 +03:00
}
return ( value % table - > size ) ;
}
2019-10-14 16:38:28 +03:00
# ifdef __clang__
2019-05-16 22:17:28 +03:00
ATTRIBUTE_NO_SANITIZE ( " unsigned-integer-overflow " )
2023-03-12 16:45:14 +03:00
ATTRIBUTE_NO_SANITIZE ( " unsigned-shift-base " )
2019-10-14 16:38:28 +03:00
# endif
2003-09-10 14:50:59 +04:00
static unsigned long
xmlHashComputeQKey ( xmlHashTablePtr table ,
2003-09-10 14:50:59 +04:00
const xmlChar * prefix , const xmlChar * name ,
const xmlChar * prefix2 , const xmlChar * name2 ,
const xmlChar * prefix3 , const xmlChar * name3 ) {
2003-09-10 14:50:59 +04:00
unsigned long value = 0L ;
2022-01-25 04:44:37 +03:00
unsigned long ch ;
2012-09-11 09:26:36 +04:00
2012-02-04 15:07:44 +04:00
# ifdef HASH_RANDOMIZATION
value = table - > random_seed ;
# endif
2003-09-10 14:50:59 +04:00
if ( prefix ! = NULL )
value + = 30 * ( * prefix ) ;
else
value + = 30 * ( * name ) ;
if ( prefix ! = NULL ) {
while ( ( ch = * prefix + + ) ! = 0 ) {
2022-01-25 04:44:37 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ch ) ;
2003-09-10 14:50:59 +04:00
}
2022-09-01 02:18:30 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ' : ' ) ;
2003-09-10 14:50:59 +04:00
}
if ( name ! = NULL ) {
while ( ( ch = * name + + ) ! = 0 ) {
2022-01-25 04:44:37 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ch ) ;
2003-09-10 14:50:59 +04:00
}
}
2013-04-12 14:53:53 +04:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) ) ;
2003-09-10 14:50:59 +04:00
if ( prefix2 ! = NULL ) {
while ( ( ch = * prefix2 + + ) ! = 0 ) {
2022-01-25 04:44:37 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ch ) ;
2003-09-10 14:50:59 +04:00
}
2022-09-01 02:18:30 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ' : ' ) ;
2003-09-10 14:50:59 +04:00
}
if ( name2 ! = NULL ) {
while ( ( ch = * name2 + + ) ! = 0 ) {
2022-01-25 04:44:37 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ch ) ;
2003-09-10 14:50:59 +04:00
}
}
2013-04-12 14:53:53 +04:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) ) ;
2003-09-10 14:50:59 +04:00
if ( prefix3 ! = NULL ) {
while ( ( ch = * prefix3 + + ) ! = 0 ) {
2022-01-25 04:44:37 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ch ) ;
2003-09-10 14:50:59 +04:00
}
2022-09-01 02:18:30 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ' : ' ) ;
2003-09-10 14:50:59 +04:00
}
if ( name3 ! = NULL ) {
while ( ( ch = * name3 + + ) ! = 0 ) {
2022-01-25 04:44:37 +03:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ch ) ;
2003-09-10 14:50:59 +04:00
}
}
return ( value % table - > size ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlHashCreate :
* @ size : the size of the hash table
*
* Create a new xmlHashTablePtr .
*
2017-06-17 17:15:09 +03:00
* Returns the newly created object , or NULL if an error occurred .
2001-02-23 20:55:21 +03:00
*/
xmlHashTablePtr
xmlHashCreate ( int size ) {
xmlHashTablePtr table ;
2012-09-11 09:26:36 +04:00
2023-05-06 16:28:13 +03:00
xmlInitParser ( ) ;
2001-02-23 20:55:21 +03:00
if ( size < = 0 )
size = 256 ;
2012-09-11 09:26:36 +04:00
2001-02-23 20:55:21 +03:00
table = xmlMalloc ( sizeof ( xmlHashTable ) ) ;
if ( table ) {
2005-01-24 01:56:39 +03:00
table - > dict = NULL ;
2001-02-23 20:55:21 +03:00
table - > size = size ;
table - > nbElems = 0 ;
2002-07-02 01:52:03 +04:00
table - > table = xmlMalloc ( size * sizeof ( xmlHashEntry ) ) ;
2001-02-23 20:55:21 +03:00
if ( table - > table ) {
2012-09-11 09:26:36 +04:00
memset ( table - > table , 0 , size * sizeof ( xmlHashEntry ) ) ;
2012-02-04 15:07:44 +04:00
# ifdef HASH_RANDOMIZATION
2012-05-18 11:41:31 +04:00
table - > random_seed = __xmlRandom ( ) ;
2012-02-04 15:07:44 +04:00
# endif
2012-09-11 09:26:36 +04:00
return ( table ) ;
2001-02-23 20:55:21 +03:00
}
xmlFree ( table ) ;
}
return ( NULL ) ;
}
2005-01-24 01:56:39 +03:00
/**
* xmlHashCreateDict :
* @ size : the size of the hash table
* @ dict : a dictionary to use for the hash
*
* Create a new xmlHashTablePtr which will use @ dict as the internal dictionary
*
2017-06-17 17:15:09 +03:00
* Returns the newly created object , or NULL if an error occurred .
2005-01-24 01:56:39 +03:00
*/
xmlHashTablePtr
xmlHashCreateDict ( int size , xmlDictPtr dict ) {
xmlHashTablePtr table ;
table = xmlHashCreate ( size ) ;
if ( table ! = NULL ) {
table - > dict = dict ;
xmlDictReference ( dict ) ;
}
return ( table ) ;
}
2001-04-18 17:09:01 +04:00
/**
* xmlHashGrow :
* @ table : the hash table
* @ size : the new size of the hash table
*
* resize the hash table
*
* Returns 0 in case of success , - 1 in case of failure
*/
2001-04-20 17:03:48 +04:00
static int
2001-04-18 17:09:01 +04:00
xmlHashGrow ( xmlHashTablePtr table , int size ) {
unsigned long key ;
int oldsize , i ;
xmlHashEntryPtr iter , next ;
2002-07-02 01:52:03 +04:00
struct _xmlHashEntry * oldtable ;
2001-04-18 17:09:01 +04:00
# ifdef DEBUG_GROW
unsigned long nbElem = 0 ;
# endif
2012-09-11 09:26:36 +04:00
2001-04-18 17:09:01 +04:00
if ( table = = NULL )
return ( - 1 ) ;
if ( size < 8 )
return ( - 1 ) ;
if ( size > 8 * 2048 )
return ( - 1 ) ;
oldsize = table - > size ;
oldtable = table - > table ;
if ( oldtable = = NULL )
return ( - 1 ) ;
2012-09-11 09:26:36 +04:00
2002-07-02 01:52:03 +04:00
table - > table = xmlMalloc ( size * sizeof ( xmlHashEntry ) ) ;
2001-04-18 17:09:01 +04:00
if ( table - > table = = NULL ) {
table - > table = oldtable ;
return ( - 1 ) ;
}
2002-07-02 01:52:03 +04:00
memset ( table - > table , 0 , size * sizeof ( xmlHashEntry ) ) ;
2001-04-18 17:09:01 +04:00
table - > size = size ;
2002-07-02 01:52:03 +04:00
/* If the two loops are merged, there would be situations where
2012-09-11 09:26:36 +04:00
a new entry needs to allocated and data copied into it from
2002-07-02 01:52:03 +04:00
the main table . 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 )
*/
2001-04-18 17:09:01 +04:00
for ( i = 0 ; i < oldsize ; i + + ) {
2012-09-11 09:26:36 +04:00
if ( oldtable [ i ] . valid = = 0 )
2002-07-02 01:52:03 +04:00
continue ;
key = xmlHashComputeKey ( table , oldtable [ i ] . name , oldtable [ i ] . name2 ,
oldtable [ i ] . name3 ) ;
memcpy ( & ( table - > table [ key ] ) , & ( oldtable [ i ] ) , sizeof ( xmlHashEntry ) ) ;
table - > table [ key ] . next = NULL ;
}
for ( i = 0 ; i < oldsize ; i + + ) {
iter = oldtable [ i ] . next ;
2001-04-18 17:09:01 +04:00
while ( iter ) {
next = iter - > next ;
/*
* put back the entry in the new table
*/
key = xmlHashComputeKey ( table , iter - > name , iter - > name2 ,
iter - > name3 ) ;
2002-07-02 01:52:03 +04:00
if ( table - > table [ key ] . valid = = 0 ) {
memcpy ( & ( table - > table [ key ] ) , iter , sizeof ( xmlHashEntry ) ) ;
table - > table [ key ] . next = NULL ;
xmlFree ( iter ) ;
} else {
2012-09-11 09:26:36 +04:00
iter - > next = table - > table [ key ] . next ;
table - > table [ key ] . next = iter ;
2002-07-02 01:52:03 +04:00
}
2001-04-18 17:09:01 +04:00
# ifdef DEBUG_GROW
nbElem + + ;
# endif
iter = next ;
}
}
xmlFree ( oldtable ) ;
# ifdef DEBUG_GROW
xmlGenericError ( xmlGenericErrorContext ,
" xmlHashGrow : from %d to %d, %d elems \n " , oldsize , size , nbElem ) ;
# endif
return ( 0 ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlHashFree :
* @ table : the hash table
* @ f : the deallocator function for items in the hash
*
2001-12-31 19:16:02 +03:00
* Free the hash @ table and its contents . The userdata is
* deallocated with @ f if provided .
2001-02-23 20:55:21 +03:00
*/
void
xmlHashFree ( xmlHashTablePtr table , xmlHashDeallocator f ) {
int i ;
xmlHashEntryPtr iter ;
xmlHashEntryPtr next ;
2002-07-02 01:52:03 +04:00
int inside_table = 0 ;
2003-08-19 19:01:28 +04:00
int nbElems ;
2001-02-23 20:55:21 +03:00
if ( table = = NULL )
return ;
if ( table - > table ) {
2003-08-19 19:01:28 +04:00
nbElems = table - > nbElems ;
for ( i = 0 ; ( i < table - > size ) & & ( nbElems > 0 ) ; i + + ) {
2002-07-02 01:52:03 +04:00
iter = & ( table - > table [ i ] ) ;
if ( iter - > valid = = 0 )
continue ;
inside_table = 1 ;
2001-02-23 20:55:21 +03:00
while ( iter ) {
next = iter - > next ;
2003-10-29 14:18:37 +03:00
if ( ( f ! = NULL ) & & ( iter - > payload ! = NULL ) )
2001-04-18 17:09:01 +04:00
f ( iter - > payload , iter - > name ) ;
2005-01-24 01:56:39 +03:00
if ( table - > dict = = NULL ) {
if ( iter - > name )
xmlFree ( iter - > name ) ;
if ( iter - > name2 )
xmlFree ( iter - > name2 ) ;
if ( iter - > name3 )
xmlFree ( iter - > name3 ) ;
}
2001-02-23 20:55:21 +03:00
iter - > payload = NULL ;
2002-07-02 01:52:03 +04:00
if ( ! inside_table )
xmlFree ( iter ) ;
2003-08-19 19:01:28 +04:00
nbElems - - ;
2002-07-02 01:52:03 +04:00
inside_table = 0 ;
2001-02-23 20:55:21 +03:00
iter = next ;
}
}
xmlFree ( table - > table ) ;
}
2005-01-24 01:56:39 +03:00
if ( table - > dict )
xmlDictFree ( table - > dict ) ;
2001-02-23 20:55:21 +03:00
xmlFree ( table ) ;
}
2017-11-09 18:42:47 +03:00
/**
* xmlHashDefaultDeallocator :
* @ entry : the hash table entry
* @ name : the entry ' s name
*
* Free a hash table entry with xmlFree .
*/
void
xmlHashDefaultDeallocator ( void * entry , const xmlChar * name ATTRIBUTE_UNUSED ) {
xmlFree ( entry ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlHashAddEntry :
* @ table : the hash table
* @ name : the name of the userdata
* @ userdata : a pointer to the userdata
*
2001-12-31 19:16:02 +03:00
* Add the @ userdata to the hash @ table . This can later be retrieved
* by using the @ name . Duplicate names generate errors .
2001-02-23 20:55:21 +03:00
*
* Returns 0 the addition succeeded and - 1 in case of error .
*/
int
xmlHashAddEntry ( xmlHashTablePtr table , const xmlChar * name , void * userdata ) {
return ( xmlHashAddEntry3 ( table , name , NULL , NULL , userdata ) ) ;
}
/**
* xmlHashAddEntry2 :
* @ table : the hash table
* @ name : the name of the userdata
* @ name2 : a second name of the userdata
* @ userdata : a pointer to the userdata
*
2001-12-31 19:16:02 +03:00
* Add the @ userdata to the hash @ table . This can later be retrieved
* by using the ( @ name , @ name2 ) tuple . Duplicate tuples generate errors .
2001-02-23 20:55:21 +03:00
*
* Returns 0 the addition succeeded and - 1 in case of error .
*/
int
xmlHashAddEntry2 ( xmlHashTablePtr table , const xmlChar * name ,
const xmlChar * name2 , void * userdata ) {
return ( xmlHashAddEntry3 ( table , name , name2 , NULL , userdata ) ) ;
}
/**
* xmlHashUpdateEntry :
* @ table : the hash table
* @ name : the name of the userdata
* @ userdata : a pointer to the userdata
* @ f : the deallocator function for replaced item ( if any )
*
2001-12-31 19:16:02 +03:00
* Add the @ userdata to the hash @ table . This can later be retrieved
* by using the @ name . Existing entry for this @ name will be removed
2001-02-23 20:55:21 +03:00
* and freed with @ f if found .
*
* Returns 0 the addition succeeded and - 1 in case of error .
*/
int
xmlHashUpdateEntry ( xmlHashTablePtr table , const xmlChar * name ,
void * userdata , xmlHashDeallocator f ) {
return ( xmlHashUpdateEntry3 ( table , name , NULL , NULL , userdata , f ) ) ;
}
/**
* xmlHashUpdateEntry2 :
* @ table : the hash table
* @ name : the name of the userdata
* @ name2 : a second name of the userdata
* @ userdata : a pointer to the userdata
* @ f : the deallocator function for replaced item ( if any )
*
2001-12-31 19:16:02 +03:00
* Add the @ userdata to the hash @ table . This can later be retrieved
* by using the ( @ name , @ name2 ) tuple . Existing entry for this tuple will
2001-02-23 20:55:21 +03:00
* be removed and freed with @ f if found .
*
* Returns 0 the addition succeeded and - 1 in case of error .
*/
int
xmlHashUpdateEntry2 ( xmlHashTablePtr table , const xmlChar * name ,
const xmlChar * name2 , void * userdata ,
xmlHashDeallocator f ) {
return ( xmlHashUpdateEntry3 ( table , name , name2 , NULL , userdata , f ) ) ;
}
/**
* xmlHashLookup :
* @ table : the hash table
* @ name : the name of the userdata
*
2001-12-31 19:16:02 +03:00
* Find the userdata specified by the @ name .
2001-02-23 20:55:21 +03:00
*
2001-07-18 23:30:27 +04:00
* Returns the pointer to the userdata
2001-02-23 20:55:21 +03:00
*/
void *
xmlHashLookup ( xmlHashTablePtr table , const xmlChar * name ) {
return ( xmlHashLookup3 ( table , name , NULL , NULL ) ) ;
}
/**
* xmlHashLookup2 :
* @ table : the hash table
* @ name : the name of the userdata
* @ name2 : a second name of the userdata
*
2001-12-31 19:16:02 +03:00
* Find the userdata specified by the ( @ name , @ name2 ) tuple .
2001-02-23 20:55:21 +03:00
*
2001-07-18 23:30:27 +04:00
* Returns the pointer to the userdata
2001-02-23 20:55:21 +03:00
*/
void *
xmlHashLookup2 ( xmlHashTablePtr table , const xmlChar * name ,
const xmlChar * name2 ) {
return ( xmlHashLookup3 ( table , name , name2 , NULL ) ) ;
}
2003-09-10 14:50:59 +04:00
/**
* xmlHashQLookup :
* @ table : the hash table
* @ prefix : the prefix of the userdata
* @ name : the name of the userdata
*
* Find the userdata specified by the QName @ prefix : @ name / @ name .
*
* Returns the pointer to the userdata
*/
void *
xmlHashQLookup ( xmlHashTablePtr table , const xmlChar * prefix ,
const xmlChar * name ) {
return ( xmlHashQLookup3 ( table , prefix , name , NULL , NULL , NULL , NULL ) ) ;
}
/**
2003-09-25 16:18:34 +04:00
* xmlHashQLookup2 :
2003-09-10 14:50:59 +04:00
* @ table : the hash table
* @ prefix : the prefix of the userdata
* @ name : the name of the userdata
2003-09-25 18:29:29 +04:00
* @ prefix2 : the second prefix of the userdata
2003-09-10 14:50:59 +04:00
* @ name2 : a second name of the userdata
*
* Find the userdata specified by the QNames tuple
*
* Returns the pointer to the userdata
*/
void *
xmlHashQLookup2 ( xmlHashTablePtr table , const xmlChar * prefix ,
const xmlChar * name , const xmlChar * prefix2 ,
const xmlChar * name2 ) {
return ( xmlHashQLookup3 ( table , prefix , name , prefix2 , name2 , NULL , NULL ) ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlHashAddEntry3 :
* @ table : the hash table
* @ name : the name of the userdata
* @ name2 : a second name of the userdata
* @ name3 : a third name of the userdata
* @ userdata : a pointer to the userdata
*
2001-12-31 19:16:02 +03:00
* Add the @ userdata to the hash @ table . This can later be retrieved
* by using the tuple ( @ name , @ name2 , @ name3 ) . Duplicate entries generate
2001-02-23 20:55:21 +03:00
* errors .
*
* Returns 0 the addition succeeded and - 1 in case of error .
*/
int
xmlHashAddEntry3 ( xmlHashTablePtr table , const xmlChar * name ,
const xmlChar * name2 , const xmlChar * name3 ,
void * userdata ) {
2001-04-18 17:09:01 +04:00
unsigned long key , len = 0 ;
2001-02-23 20:55:21 +03:00
xmlHashEntryPtr entry ;
xmlHashEntryPtr insert ;
2005-01-24 01:56:39 +03:00
if ( ( table = = NULL ) | | ( name = = NULL ) )
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
2005-01-24 01:56:39 +03:00
/*
* If using a dict internalize if needed
*/
if ( table - > dict ) {
if ( ! xmlDictOwns ( table - > dict , name ) ) {
name = xmlDictLookup ( table - > dict , name , - 1 ) ;
if ( name = = NULL )
return ( - 1 ) ;
}
if ( ( name2 ! = NULL ) & & ( ! xmlDictOwns ( table - > dict , name2 ) ) ) {
name2 = xmlDictLookup ( table - > dict , name2 , - 1 ) ;
if ( name2 = = NULL )
return ( - 1 ) ;
}
if ( ( name3 ! = NULL ) & & ( ! xmlDictOwns ( table - > dict , name3 ) ) ) {
name3 = xmlDictLookup ( table - > dict , name3 , - 1 ) ;
if ( name3 = = NULL )
return ( - 1 ) ;
}
}
2001-02-23 20:55:21 +03:00
/*
* Check for duplicate and insertion location .
*/
2001-04-18 17:09:01 +04:00
key = xmlHashComputeKey ( table , name , name2 , name3 ) ;
2002-07-02 01:52:03 +04:00
if ( table - > table [ key ] . valid = = 0 ) {
2001-02-23 20:55:21 +03:00
insert = NULL ;
} else {
2005-01-24 01:56:39 +03:00
if ( table - > dict ) {
for ( insert = & ( table - > table [ key ] ) ; insert - > next ! = NULL ;
insert = insert - > next ) {
if ( ( insert - > name = = name ) & &
( insert - > name2 = = name2 ) & &
( insert - > name3 = = name3 ) )
return ( - 1 ) ;
len + + ;
}
if ( ( insert - > name = = name ) & &
( insert - > name2 = = name2 ) & &
( insert - > name3 = = name3 ) )
return ( - 1 ) ;
} else {
for ( insert = & ( table - > table [ key ] ) ; insert - > next ! = NULL ;
insert = insert - > next ) {
if ( ( xmlStrEqual ( insert - > name , name ) ) & &
( xmlStrEqual ( insert - > name2 , name2 ) ) & &
( xmlStrEqual ( insert - > name3 , name3 ) ) )
return ( - 1 ) ;
len + + ;
}
2001-02-23 20:55:21 +03:00
if ( ( xmlStrEqual ( insert - > name , name ) ) & &
( xmlStrEqual ( insert - > name2 , name2 ) ) & &
( xmlStrEqual ( insert - > name3 , name3 ) ) )
return ( - 1 ) ;
}
}
2002-07-02 01:52:03 +04:00
if ( insert = = NULL ) {
entry = & ( table - > table [ key ] ) ;
} else {
entry = xmlMalloc ( sizeof ( xmlHashEntry ) ) ;
if ( entry = = NULL )
return ( - 1 ) ;
}
2005-01-24 01:56:39 +03:00
if ( table - > dict ! = NULL ) {
entry - > name = ( xmlChar * ) name ;
entry - > name2 = ( xmlChar * ) name2 ;
entry - > name3 = ( xmlChar * ) name3 ;
} else {
entry - > name = xmlStrdup ( name ) ;
2023-02-26 17:43:50 +03:00
if ( entry - > name = = NULL ) {
entry - > name2 = NULL ;
goto error ;
}
if ( name2 = = NULL ) {
entry - > name2 = NULL ;
} else {
entry - > name2 = xmlStrdup ( name2 ) ;
if ( entry - > name2 = = NULL )
goto error ;
}
if ( name3 = = NULL ) {
entry - > name3 = NULL ;
} else {
entry - > name3 = xmlStrdup ( name3 ) ;
if ( entry - > name3 = = NULL )
goto error ;
}
2005-01-24 01:56:39 +03:00
}
2001-02-23 20:55:21 +03:00
entry - > payload = userdata ;
entry - > next = NULL ;
2002-07-02 01:52:03 +04:00
entry - > valid = 1 ;
2001-02-23 20:55:21 +03:00
2012-09-11 09:26:36 +04:00
if ( insert ! = NULL )
2001-02-23 20:55:21 +03:00
insert - > next = entry ;
2002-07-02 01:52:03 +04:00
2001-02-23 20:55:21 +03:00
table - > nbElems + + ;
2001-04-18 17:09:01 +04:00
if ( len > MAX_HASH_LEN )
xmlHashGrow ( table , MAX_HASH_LEN * table - > size ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
2023-02-26 17:43:50 +03:00
error :
xmlFree ( entry - > name2 ) ;
xmlFree ( entry - > name ) ;
if ( insert ! = NULL )
xmlFree ( entry ) ;
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlHashUpdateEntry3 :
* @ table : the hash table
* @ name : the name of the userdata
* @ name2 : a second name of the userdata
* @ name3 : a third name of the userdata
* @ userdata : a pointer to the userdata
* @ f : the deallocator function for replaced item ( if any )
*
2001-12-31 19:16:02 +03:00
* Add the @ userdata to the hash @ table . This can later be retrieved
* by using the tuple ( @ name , @ name2 , @ name3 ) . Existing entry for this tuple
2001-02-23 20:55:21 +03:00
* will be removed and freed with @ f if found .
*
* Returns 0 the addition succeeded and - 1 in case of error .
*/
int
xmlHashUpdateEntry3 ( xmlHashTablePtr table , const xmlChar * name ,
const xmlChar * name2 , const xmlChar * name3 ,
void * userdata , xmlHashDeallocator f ) {
unsigned long key ;
xmlHashEntryPtr entry ;
xmlHashEntryPtr insert ;
if ( ( table = = NULL ) | | name = = NULL )
return ( - 1 ) ;
2005-01-24 01:56:39 +03:00
/*
* If using a dict internalize if needed
*/
if ( table - > dict ) {
if ( ! xmlDictOwns ( table - > dict , name ) ) {
name = xmlDictLookup ( table - > dict , name , - 1 ) ;
if ( name = = NULL )
return ( - 1 ) ;
}
if ( ( name2 ! = NULL ) & & ( ! xmlDictOwns ( table - > dict , name2 ) ) ) {
name2 = xmlDictLookup ( table - > dict , name2 , - 1 ) ;
if ( name2 = = NULL )
return ( - 1 ) ;
}
if ( ( name3 ! = NULL ) & & ( ! xmlDictOwns ( table - > dict , name3 ) ) ) {
name3 = xmlDictLookup ( table - > dict , name3 , - 1 ) ;
if ( name3 = = NULL )
return ( - 1 ) ;
}
}
2001-02-23 20:55:21 +03:00
/*
* Check for duplicate and insertion location .
*/
2001-04-18 17:09:01 +04:00
key = xmlHashComputeKey ( table , name , name2 , name3 ) ;
2002-07-02 01:52:03 +04:00
if ( table - > table [ key ] . valid = = 0 ) {
2001-02-23 20:55:21 +03:00
insert = NULL ;
} else {
2005-01-24 01:56:39 +03:00
if ( table - > dict ) {
for ( insert = & ( table - > table [ key ] ) ; insert - > next ! = NULL ;
insert = insert - > next ) {
if ( ( insert - > name = = name ) & &
( insert - > name2 = = name2 ) & &
( insert - > name3 = = name3 ) ) {
if ( f )
f ( insert - > payload , insert - > name ) ;
insert - > payload = userdata ;
return ( 0 ) ;
}
}
if ( ( insert - > name = = name ) & &
( insert - > name2 = = name2 ) & &
( insert - > name3 = = name3 ) ) {
if ( f )
f ( insert - > payload , insert - > name ) ;
insert - > payload = userdata ;
return ( 0 ) ;
}
} else {
for ( insert = & ( table - > table [ key ] ) ; insert - > next ! = NULL ;
insert = insert - > next ) {
if ( ( xmlStrEqual ( insert - > name , name ) ) & &
( xmlStrEqual ( insert - > name2 , name2 ) ) & &
( xmlStrEqual ( insert - > name3 , name3 ) ) ) {
if ( f )
f ( insert - > payload , insert - > name ) ;
insert - > payload = userdata ;
return ( 0 ) ;
}
}
2001-02-23 20:55:21 +03:00
if ( ( xmlStrEqual ( insert - > name , name ) ) & &
( xmlStrEqual ( insert - > name2 , name2 ) ) & &
( xmlStrEqual ( insert - > name3 , name3 ) ) ) {
if ( f )
f ( insert - > payload , insert - > name ) ;
insert - > payload = userdata ;
return ( 0 ) ;
}
}
}
2002-07-02 01:52:03 +04:00
if ( insert = = NULL ) {
entry = & ( table - > table [ key ] ) ;
} else {
entry = xmlMalloc ( sizeof ( xmlHashEntry ) ) ;
if ( entry = = NULL )
return ( - 1 ) ;
}
2005-01-24 01:56:39 +03:00
if ( table - > dict ! = NULL ) {
entry - > name = ( xmlChar * ) name ;
entry - > name2 = ( xmlChar * ) name2 ;
entry - > name3 = ( xmlChar * ) name3 ;
} else {
entry - > name = xmlStrdup ( name ) ;
2023-02-26 17:43:50 +03:00
if ( entry - > name = = NULL ) {
entry - > name2 = NULL ;
goto error ;
}
if ( name2 = = NULL ) {
entry - > name2 = NULL ;
} else {
entry - > name2 = xmlStrdup ( name2 ) ;
if ( entry - > name2 = = NULL )
goto error ;
}
if ( name3 = = NULL ) {
entry - > name3 = NULL ;
} else {
entry - > name3 = xmlStrdup ( name3 ) ;
if ( entry - > name3 = = NULL )
goto error ;
}
2005-01-24 01:56:39 +03:00
}
2001-02-23 20:55:21 +03:00
entry - > payload = userdata ;
entry - > next = NULL ;
2002-07-02 01:52:03 +04:00
entry - > valid = 1 ;
2001-02-23 20:55:21 +03:00
table - > nbElems + + ;
2002-07-02 01:52:03 +04:00
if ( insert ! = NULL ) {
2001-02-23 20:55:21 +03:00
insert - > next = entry ;
}
return ( 0 ) ;
2023-02-26 17:43:50 +03:00
error :
xmlFree ( entry - > name2 ) ;
xmlFree ( entry - > name ) ;
if ( insert ! = NULL )
xmlFree ( entry ) ;
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
/**
2001-07-18 23:30:27 +04:00
* xmlHashLookup3 :
2001-02-23 20:55:21 +03:00
* @ table : the hash table
* @ name : the name of the userdata
* @ name2 : a second name of the userdata
* @ name3 : a third name of the userdata
*
2001-12-31 19:16:02 +03:00
* Find the userdata specified by the ( @ name , @ name2 , @ name3 ) tuple .
2001-02-23 20:55:21 +03:00
*
* Returns the a pointer to the userdata
*/
void *
2012-09-11 09:26:36 +04:00
xmlHashLookup3 ( xmlHashTablePtr table , const xmlChar * name ,
2001-02-23 20:55:21 +03:00
const xmlChar * name2 , const xmlChar * name3 ) {
unsigned long key ;
xmlHashEntryPtr entry ;
if ( table = = NULL )
return ( NULL ) ;
if ( name = = NULL )
return ( NULL ) ;
2001-04-18 17:09:01 +04:00
key = xmlHashComputeKey ( table , name , name2 , name3 ) ;
2002-07-02 01:52:03 +04:00
if ( table - > table [ key ] . valid = = 0 )
return ( NULL ) ;
2005-01-24 01:56:39 +03:00
if ( table - > dict ) {
for ( entry = & ( table - > table [ key ] ) ; entry ! = NULL ; entry = entry - > next ) {
if ( ( entry - > name = = name ) & &
( entry - > name2 = = name2 ) & &
( entry - > name3 = = name3 ) )
return ( entry - > payload ) ;
}
}
2002-07-02 01:52:03 +04:00
for ( entry = & ( table - > table [ key ] ) ; entry ! = NULL ; entry = entry - > next ) {
2001-02-23 20:55:21 +03:00
if ( ( xmlStrEqual ( entry - > name , name ) ) & &
( xmlStrEqual ( entry - > name2 , name2 ) ) & &
( xmlStrEqual ( entry - > name3 , name3 ) ) )
return ( entry - > payload ) ;
}
return ( NULL ) ;
}
2003-09-10 14:50:59 +04:00
/**
* xmlHashQLookup3 :
* @ table : the hash table
* @ prefix : the prefix of the userdata
* @ name : the name of the userdata
* @ prefix2 : the second prefix of the userdata
* @ name2 : a second name of the userdata
* @ prefix3 : the third prefix of the userdata
* @ name3 : a third name of the userdata
*
* Find the userdata specified by the ( @ name , @ name2 , @ name3 ) tuple .
*
* Returns the a pointer to the userdata
*/
void *
xmlHashQLookup3 ( xmlHashTablePtr table ,
const xmlChar * prefix , const xmlChar * name ,
const xmlChar * prefix2 , const xmlChar * name2 ,
const xmlChar * prefix3 , const xmlChar * name3 ) {
unsigned long key ;
xmlHashEntryPtr entry ;
if ( table = = NULL )
return ( NULL ) ;
if ( name = = NULL )
return ( NULL ) ;
key = xmlHashComputeQKey ( table , prefix , name , prefix2 ,
name2 , prefix3 , name3 ) ;
if ( table - > table [ key ] . valid = = 0 )
return ( NULL ) ;
for ( entry = & ( table - > table [ key ] ) ; entry ! = NULL ; entry = entry - > next ) {
if ( ( xmlStrQEqual ( prefix , name , entry - > name ) ) & &
( xmlStrQEqual ( prefix2 , name2 , entry - > name2 ) ) & &
( xmlStrQEqual ( prefix3 , name3 , entry - > name3 ) ) )
return ( entry - > payload ) ;
}
return ( NULL ) ;
}
2002-06-18 11:58:35 +04:00
typedef struct {
xmlHashScanner hashscanner ;
void * data ;
} stubData ;
2012-09-11 09:26:36 +04:00
static void
stubHashScannerFull ( void * payload , void * data , const xmlChar * name ,
2002-09-13 18:48:12 +04:00
const xmlChar * name2 ATTRIBUTE_UNUSED ,
const xmlChar * name3 ATTRIBUTE_UNUSED ) {
2002-06-18 11:58:35 +04:00
stubData * stubdata = ( stubData * ) data ;
stubdata - > hashscanner ( payload , stubdata - > data , ( xmlChar * ) name ) ;
2012-09-11 09:26:36 +04:00
}
2002-12-10 18:19:08 +03:00
/**
* xmlHashScan :
* @ table : the hash table
* @ f : the scanner function for items in the hash
* @ data : extra data passed to f
*
* Scan the hash @ table and applied @ f to each value .
*/
2001-02-23 20:55:21 +03:00
void
xmlHashScan ( xmlHashTablePtr table , xmlHashScanner f , void * data ) {
2002-06-18 11:58:35 +04:00
stubData stubdata ;
stubdata . data = data ;
2012-09-11 09:26:36 +04:00
stubdata . hashscanner = f ;
2002-06-18 11:58:35 +04:00
xmlHashScanFull ( table , stubHashScannerFull , & stubdata ) ;
2001-07-22 07:54:15 +04:00
}
/**
* xmlHashScanFull :
* @ table : the hash table
* @ f : the scanner function for items in the hash
* @ data : extra data passed to f
*
2001-12-31 19:16:02 +03:00
* Scan the hash @ table and applied @ f to each value .
2001-07-22 07:54:15 +04:00
*/
void
xmlHashScanFull ( xmlHashTablePtr table , xmlHashScannerFull f , void * data ) {
2008-01-11 08:27:32 +03:00
int i , nb ;
2001-02-23 20:55:21 +03:00
xmlHashEntryPtr iter ;
xmlHashEntryPtr next ;
if ( table = = NULL )
return ;
if ( f = = NULL )
return ;
if ( table - > table ) {
for ( i = 0 ; i < table - > size ; i + + ) {
2012-09-11 09:26:36 +04:00
if ( table - > table [ i ] . valid = = 0 )
2002-07-02 01:52:03 +04:00
continue ;
iter = & ( table - > table [ i ] ) ;
2001-02-23 20:55:21 +03:00
while ( iter ) {
next = iter - > next ;
2008-01-11 08:27:32 +03:00
nb = table - > nbElems ;
2003-10-29 14:18:37 +03:00
if ( ( f ! = NULL ) & & ( iter - > payload ! = NULL ) )
2001-07-22 07:54:15 +04:00
f ( iter - > payload , data , iter - > name ,
iter - > name2 , iter - > name3 ) ;
2008-01-11 08:27:32 +03:00
if ( nb ! = table - > nbElems ) {
/* table was modified by the callback, be careful */
if ( iter = = & ( table - > table [ i ] ) ) {
if ( table - > table [ i ] . valid = = 0 )
iter = NULL ;
if ( table - > table [ i ] . next ! = next )
iter = & ( table - > table [ i ] ) ;
} else
iter = next ;
} else
iter = next ;
2001-02-23 20:55:21 +03:00
}
}
}
}
/**
* xmlHashScan3 :
* @ table : the hash table
* @ name : the name of the userdata or NULL
* @ name2 : a second name of the userdata or NULL
* @ name3 : a third name of the userdata or NULL
* @ f : the scanner function for items in the hash
* @ data : extra data passed to f
*
2001-12-31 19:16:02 +03:00
* Scan the hash @ table and applied @ f to each value matching
* ( @ name , @ name2 , @ name3 ) tuple . If one of the names is null ,
2001-02-23 20:55:21 +03:00
* the comparison is considered to match .
*/
void
2012-09-11 09:26:36 +04:00
xmlHashScan3 ( xmlHashTablePtr table , const xmlChar * name ,
2001-02-23 20:55:21 +03:00
const xmlChar * name2 , const xmlChar * name3 ,
xmlHashScanner f , void * data ) {
2017-11-09 18:42:47 +03:00
stubData stubdata ;
stubdata . data = data ;
stubdata . hashscanner = f ;
xmlHashScanFull3 ( table , name , name2 , name3 , stubHashScannerFull ,
& stubdata ) ;
2001-07-22 07:54:15 +04:00
}
/**
* xmlHashScanFull3 :
* @ table : the hash table
* @ name : the name of the userdata or NULL
* @ name2 : a second name of the userdata or NULL
* @ name3 : a third name of the userdata or NULL
* @ f : the scanner function for items in the hash
* @ data : extra data passed to f
*
2001-12-31 19:16:02 +03:00
* Scan the hash @ table and applied @ f to each value matching
* ( @ name , @ name2 , @ name3 ) tuple . If one of the names is null ,
2001-07-22 07:54:15 +04:00
* the comparison is considered to match .
*/
void
2012-09-11 09:26:36 +04:00
xmlHashScanFull3 ( xmlHashTablePtr table , const xmlChar * name ,
2001-07-22 07:54:15 +04:00
const xmlChar * name2 , const xmlChar * name3 ,
xmlHashScannerFull f , void * data ) {
2001-02-23 20:55:21 +03:00
int i ;
xmlHashEntryPtr iter ;
xmlHashEntryPtr next ;
if ( table = = NULL )
return ;
if ( f = = NULL )
return ;
if ( table - > table ) {
for ( i = 0 ; i < table - > size ; i + + ) {
2002-07-02 01:52:03 +04:00
if ( table - > table [ i ] . valid = = 0 )
continue ;
iter = & ( table - > table [ i ] ) ;
2001-02-23 20:55:21 +03:00
while ( iter ) {
next = iter - > next ;
if ( ( ( name = = NULL ) | | ( xmlStrEqual ( name , iter - > name ) ) ) & &
( ( name2 = = NULL ) | | ( xmlStrEqual ( name2 , iter - > name2 ) ) ) & &
2003-10-29 14:18:37 +03:00
( ( name3 = = NULL ) | | ( xmlStrEqual ( name3 , iter - > name3 ) ) ) & &
( iter - > payload ! = NULL ) ) {
2001-07-22 07:54:15 +04:00
f ( iter - > payload , data , iter - > name ,
iter - > name2 , iter - > name3 ) ;
2001-02-23 20:55:21 +03:00
}
iter = next ;
}
}
}
}
/**
* xmlHashCopy :
* @ table : the hash table
* @ f : the copier function for items in the hash
*
2001-12-31 19:16:02 +03:00
* Scan the hash @ table and applied @ f to each value .
2001-02-23 20:55:21 +03:00
*
* Returns the new table or NULL in case of error .
*/
xmlHashTablePtr
xmlHashCopy ( xmlHashTablePtr table , xmlHashCopier f ) {
int i ;
xmlHashEntryPtr iter ;
xmlHashEntryPtr next ;
xmlHashTablePtr ret ;
if ( table = = NULL )
return ( NULL ) ;
if ( f = = NULL )
return ( NULL ) ;
ret = xmlHashCreate ( table - > size ) ;
2014-07-14 13:50:27 +04:00
if ( ret = = NULL )
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
if ( table - > table ) {
for ( i = 0 ; i < table - > size ; i + + ) {
2002-07-02 01:52:03 +04:00
if ( table - > table [ i ] . valid = = 0 )
continue ;
iter = & ( table - > table [ i ] ) ;
2001-02-23 20:55:21 +03:00
while ( iter ) {
next = iter - > next ;
xmlHashAddEntry3 ( ret , iter - > name , iter - > name2 ,
iter - > name3 , f ( iter - > payload , iter - > name ) ) ;
iter = next ;
}
}
}
ret - > nbElems = table - > nbElems ;
return ( ret ) ;
}
/**
* xmlHashSize :
* @ table : the hash table
*
2001-12-31 19:16:02 +03:00
* Query the number of elements installed in the hash @ table .
2001-07-18 23:30:27 +04:00
*
2001-02-23 20:55:21 +03:00
* Returns the number of elements in the hash table or
* - 1 in case of error
*/
int
xmlHashSize ( xmlHashTablePtr table ) {
if ( table = = NULL )
return ( - 1 ) ;
return ( table - > nbElems ) ;
}
/**
2001-05-19 17:24:56 +04:00
* xmlHashRemoveEntry :
2001-02-23 20:55:21 +03:00
* @ table : the hash table
* @ name : the name of the userdata
* @ f : the deallocator function for removed item ( if any )
*
2001-12-31 19:16:02 +03:00
* Find the userdata specified by the @ name and remove
* it from the hash @ table . Existing userdata for this tuple will be removed
2001-02-23 20:55:21 +03:00
* and freed with @ f .
*
* Returns 0 if the removal succeeded and - 1 in case of error or not found .
*/
int xmlHashRemoveEntry ( xmlHashTablePtr table , const xmlChar * name ,
2001-04-18 17:09:01 +04:00
xmlHashDeallocator f ) {
return ( xmlHashRemoveEntry3 ( table , name , NULL , NULL , f ) ) ;
2001-02-23 20:55:21 +03:00
}
/**
2001-05-19 17:24:56 +04:00
* xmlHashRemoveEntry2 :
2001-02-23 20:55:21 +03:00
* @ table : the hash table
* @ name : the name of the userdata
* @ name2 : a second name of the userdata
* @ f : the deallocator function for removed item ( if any )
*
2001-12-31 19:16:02 +03:00
* Find the userdata specified by the ( @ name , @ name2 ) tuple and remove
* it from the hash @ table . Existing userdata for this tuple will be removed
2001-02-23 20:55:21 +03:00
* and freed with @ f .
*
* Returns 0 if the removal succeeded and - 1 in case of error or not found .
*/
2002-12-10 18:19:08 +03:00
int
xmlHashRemoveEntry2 ( xmlHashTablePtr table , const xmlChar * name ,
2001-04-18 17:09:01 +04:00
const xmlChar * name2 , xmlHashDeallocator f ) {
return ( xmlHashRemoveEntry3 ( table , name , name2 , NULL , f ) ) ;
2001-02-23 20:55:21 +03:00
}
/**
2002-12-10 18:19:08 +03:00
* xmlHashRemoveEntry3 :
2001-02-23 20:55:21 +03:00
* @ table : the hash table
* @ name : the name of the userdata
* @ name2 : a second name of the userdata
* @ name3 : a third name of the userdata
* @ f : the deallocator function for removed item ( if any )
*
2001-12-31 19:16:02 +03:00
* Find the userdata specified by the ( @ name , @ name2 , @ name3 ) tuple and remove
* it from the hash @ table . Existing userdata for this tuple will be removed
2001-02-23 20:55:21 +03:00
* and freed with @ f .
*
* Returns 0 if the removal succeeded and - 1 in case of error or not found .
*/
2002-12-10 18:19:08 +03:00
int
xmlHashRemoveEntry3 ( xmlHashTablePtr table , const xmlChar * name ,
2001-04-18 17:09:01 +04:00
const xmlChar * name2 , const xmlChar * name3 , xmlHashDeallocator f ) {
unsigned long key ;
xmlHashEntryPtr entry ;
xmlHashEntryPtr prev = NULL ;
2001-02-23 20:55:21 +03:00
2001-04-18 17:09:01 +04:00
if ( table = = NULL | | name = = NULL )
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
2001-04-18 17:09:01 +04:00
key = xmlHashComputeKey ( table , name , name2 , name3 ) ;
2002-07-02 01:52:03 +04:00
if ( table - > table [ key ] . valid = = 0 ) {
2001-04-18 17:09:01 +04:00
return ( - 1 ) ;
} else {
2002-07-02 01:52:03 +04:00
for ( entry = & ( table - > table [ key ] ) ; entry ! = NULL ; entry = entry - > next ) {
2001-04-18 17:09:01 +04:00
if ( xmlStrEqual ( entry - > name , name ) & &
xmlStrEqual ( entry - > name2 , name2 ) & &
xmlStrEqual ( entry - > name3 , name3 ) ) {
2003-10-29 14:18:37 +03:00
if ( ( f ! = NULL ) & & ( entry - > payload ! = NULL ) )
2001-04-18 17:09:01 +04:00
f ( entry - > payload , entry - > name ) ;
entry - > payload = NULL ;
2005-01-24 01:56:39 +03:00
if ( table - > dict = = NULL ) {
if ( entry - > name )
xmlFree ( entry - > name ) ;
if ( entry - > name2 )
xmlFree ( entry - > name2 ) ;
if ( entry - > name3 )
xmlFree ( entry - > name3 ) ;
}
2002-07-02 01:52:03 +04:00
if ( prev ) {
2001-04-18 17:09:01 +04:00
prev - > next = entry - > next ;
2002-07-02 01:52:03 +04:00
xmlFree ( entry ) ;
} else {
if ( entry - > next = = NULL ) {
entry - > valid = 0 ;
} else {
entry = entry - > next ;
memcpy ( & ( table - > table [ key ] ) , entry , sizeof ( xmlHashEntry ) ) ;
xmlFree ( entry ) ;
}
}
2001-04-18 17:09:01 +04:00
table - > nbElems - - ;
return ( 0 ) ;
}
prev = entry ;
}
return ( - 1 ) ;
}
2001-03-19 02:17:47 +03:00
}