2001-02-23 20:55:21 +03:00
/*
* hash . c : chained hash tables
*
* Reference : Your favorite introductory book on algorithms
*
* Copyright ( C ) 2000 Bjorn Reese and 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 .
*
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>
# include <libxml/hash.h>
# include <libxml/xmlmemory.h>
# include <libxml/parser.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
# 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 ;
} ;
/*
* xmlHashComputeKey :
* Calculate the hash key
*/
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 ;
char ch ;
2001-04-18 17:09:01 +04:00
if ( name ! = NULL ) {
value + = 30 * ( * name ) ;
while ( ( ch = * name + + ) ! = 0 ) {
2002-06-17 21:03:00 +04:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ( unsigned long ) ch ) ;
2001-04-18 17:09:01 +04:00
}
}
if ( name2 ! = NULL ) {
while ( ( ch = * name2 + + ) ! = 0 ) {
2002-06-17 21:03:00 +04:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ( unsigned long ) ch ) ;
2001-04-18 17:09:01 +04:00
}
}
if ( name3 ! = NULL ) {
while ( ( ch = * name3 + + ) ! = 0 ) {
2002-06-17 21:03:00 +04:00
value = value ^ ( ( value < < 5 ) + ( value > > 3 ) + ( unsigned long ) ch ) ;
2001-04-18 17:09:01 +04:00
}
2001-02-23 20:55:21 +03:00
}
return ( value % table - > size ) ;
}
/**
* xmlHashCreate :
* @ size : the size of the hash table
*
* Create a new xmlHashTablePtr .
*
* Returns the newly created object , or NULL if an error occured .
*/
xmlHashTablePtr
xmlHashCreate ( int size ) {
xmlHashTablePtr table ;
if ( size < = 0 )
size = 256 ;
table = xmlMalloc ( sizeof ( xmlHashTable ) ) ;
if ( table ) {
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 ) {
2002-07-02 01:52:03 +04:00
memset ( table - > table , 0 , size * sizeof ( xmlHashEntry ) ) ;
2001-02-23 20:55:21 +03:00
return ( table ) ;
}
xmlFree ( table ) ;
}
return ( NULL ) ;
}
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
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 ) ;
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
a new entry needs to allocated and data copied into it from
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 + + ) {
2002-07-02 01:52:03 +04:00
if ( oldtable [ i ] . valid = = 0 )
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 {
iter - > next = table - > table [ key ] . next ;
table - > table [ key ] . next = iter ;
}
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 ;
2001-02-23 20:55:21 +03:00
if ( table = = NULL )
return ;
if ( table - > table ) {
for ( i = 0 ; i < table - > size ; 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 ;
2001-04-18 17:09:01 +04:00
if ( f )
f ( iter - > payload , iter - > name ) ;
2001-02-23 20:55:21 +03:00
if ( iter - > name )
xmlFree ( iter - > name ) ;
if ( iter - > name2 )
xmlFree ( iter - > name2 ) ;
if ( iter - > name3 )
xmlFree ( iter - > name3 ) ;
iter - > payload = NULL ;
2002-07-02 01:52:03 +04:00
if ( ! inside_table )
xmlFree ( iter ) ;
inside_table = 0 ;
2001-02-23 20:55:21 +03:00
iter = next ;
}
2002-07-02 01:52:03 +04:00
inside_table = 0 ;
2001-02-23 20:55:21 +03:00
}
xmlFree ( table - > table ) ;
}
xmlFree ( table ) ;
}
/**
* 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 ) ) ;
}
/**
* 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 ;
if ( ( table = = NULL ) | | name = = NULL )
return ( - 1 ) ;
/*
* 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 {
2002-07-02 01:52:03 +04:00
for ( insert = & ( table - > table [ key ] ) ; insert - > next ! = NULL ;
2001-02-23 20:55:21 +03:00
insert = insert - > next ) {
if ( ( xmlStrEqual ( insert - > name , name ) ) & &
( xmlStrEqual ( insert - > name2 , name2 ) ) & &
( xmlStrEqual ( insert - > name3 , name3 ) ) )
return ( - 1 ) ;
2001-04-18 17:09:01 +04:00
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 ) ;
}
2001-02-23 20:55:21 +03:00
entry - > name = xmlStrdup ( name ) ;
entry - > name2 = xmlStrdup ( name2 ) ;
entry - > name3 = xmlStrdup ( name3 ) ;
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
2002-07-02 01:52:03 +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 ) ;
}
/**
* 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 ) ;
/*
* 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 {
2002-07-02 01:52:03 +04:00
for ( insert = & ( table - > table [ key ] ) ; insert - > next ! = NULL ;
2001-02-23 20:55:21 +03:00
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 ) ;
}
}
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 ) ;
}
2001-02-23 20:55:21 +03:00
entry - > name = xmlStrdup ( name ) ;
entry - > name2 = xmlStrdup ( name2 ) ;
entry - > name3 = xmlStrdup ( name3 ) ;
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 ) ;
}
/**
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 *
xmlHashLookup3 ( xmlHashTablePtr table , const xmlChar * name ,
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 ) ;
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 ) ;
}
2002-06-18 11:58:35 +04:00
typedef struct {
xmlHashScanner hashscanner ;
void * data ;
} stubData ;
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 ) ;
}
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 ;
stubdata . hashscanner = f ;
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 ) {
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 ( f )
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 ;
}
}
}
}
/**
* 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
xmlHashScan3 ( xmlHashTablePtr table , const xmlChar * name ,
const xmlChar * name2 , const xmlChar * name3 ,
xmlHashScanner f , void * data ) {
2001-07-22 07:54:15 +04:00
xmlHashScanFull3 ( table , name , name2 , name3 ,
( xmlHashScannerFull ) f , data ) ;
}
/**
* 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
xmlHashScanFull3 ( xmlHashTablePtr table , const xmlChar * name ,
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 ) ) ) & &
( ( name3 = = NULL ) | | ( xmlStrEqual ( name3 , iter - > name3 ) ) ) ) {
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 ) ;
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 ) ) {
if ( f )
f ( entry - > payload , entry - > name ) ;
entry - > payload = 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
}