Blame hash.c

Packit Service a31ea6
/*
Packit Service a31ea6
 * hash.c: chained hash tables
Packit Service a31ea6
 *
Packit Service a31ea6
 * Reference: Your favorite introductory book on algorithms
Packit Service a31ea6
 *
Packit Service a31ea6
 * Copyright (C) 2000,2012 Bjorn Reese and Daniel Veillard.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Permission to use, copy, modify, and distribute this software for any
Packit Service a31ea6
 * purpose with or without fee is hereby granted, provided that the above
Packit Service a31ea6
 * copyright notice and this permission notice appear in all copies.
Packit Service a31ea6
 *
Packit Service a31ea6
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
Packit Service a31ea6
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
Packit Service a31ea6
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
Packit Service a31ea6
 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Author: breese@users.sourceforge.net
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define IN_LIBXML
Packit Service a31ea6
#include "libxml.h"
Packit Service a31ea6
Packit Service a31ea6
#include <string.h>
Packit Service a31ea6
#ifdef HAVE_STDLIB_H
Packit Service a31ea6
#include <stdlib.h>
Packit Service a31ea6
#endif
Packit Service a31ea6
#ifdef HAVE_TIME_H
Packit Service a31ea6
#include <time.h>
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * Following http://www.ocert.org/advisories/ocert-2011-003.html
Packit Service a31ea6
 * it seems that having hash randomization might be a good idea
Packit Service a31ea6
 * when using XML with untrusted data
Packit Service a31ea6
 */
Packit Service a31ea6
#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME)
Packit Service a31ea6
#define HASH_RANDOMIZATION
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
#include <libxml/parser.h>
Packit Service a31ea6
#include <libxml/hash.h>
Packit Service a31ea6
#include <libxml/xmlmemory.h>
Packit Service a31ea6
#include <libxml/xmlerror.h>
Packit Service a31ea6
#include <libxml/globals.h>
Packit Service a31ea6
Packit Service a31ea6
#define MAX_HASH_LEN 8
Packit Service a31ea6
Packit Service a31ea6
/* #define DEBUG_GROW */
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * A single entry in the hash table
Packit Service a31ea6
 */
Packit Service a31ea6
typedef struct _xmlHashEntry xmlHashEntry;
Packit Service a31ea6
typedef xmlHashEntry *xmlHashEntryPtr;
Packit Service a31ea6
struct _xmlHashEntry {
Packit Service a31ea6
    struct _xmlHashEntry *next;
Packit Service a31ea6
    xmlChar *name;
Packit Service a31ea6
    xmlChar *name2;
Packit Service a31ea6
    xmlChar *name3;
Packit Service a31ea6
    void *payload;
Packit Service a31ea6
    int valid;
Packit Service a31ea6
};
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * The entire hash table
Packit Service a31ea6
 */
Packit Service a31ea6
struct _xmlHashTable {
Packit Service a31ea6
    struct _xmlHashEntry *table;
Packit Service a31ea6
    int size;
Packit Service a31ea6
    int nbElems;
Packit Service a31ea6
    xmlDictPtr dict;
Packit Service a31ea6
#ifdef HASH_RANDOMIZATION
Packit Service a31ea6
    int random_seed;
Packit Service a31ea6
#endif
Packit Service a31ea6
};
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * xmlHashComputeKey:
Packit Service a31ea6
 * Calculate the hash key
Packit Service a31ea6
 */
Packit Service a31ea6
static unsigned long
Packit Service a31ea6
xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
	          const xmlChar *name2, const xmlChar *name3) {
Packit Service a31ea6
    unsigned long value = 0L;
Packit Service a31ea6
    char ch;
Packit Service a31ea6
Packit Service a31ea6
#ifdef HASH_RANDOMIZATION
Packit Service a31ea6
    value = table->random_seed;
Packit Service a31ea6
#endif
Packit Service a31ea6
    if (name != NULL) {
Packit Service a31ea6
	value += 30 * (*name);
Packit Service a31ea6
	while ((ch = *name++) != 0) {
Packit Service a31ea6
	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    value = value ^ ((value << 5) + (value >> 3));
Packit Service a31ea6
    if (name2 != NULL) {
Packit Service a31ea6
	while ((ch = *name2++) != 0) {
Packit Service a31ea6
	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    value = value ^ ((value << 5) + (value >> 3));
Packit Service a31ea6
    if (name3 != NULL) {
Packit Service a31ea6
	while ((ch = *name3++) != 0) {
Packit Service a31ea6
	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    return (value % table->size);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
static unsigned long
Packit Service a31ea6
xmlHashComputeQKey(xmlHashTablePtr table,
Packit Service a31ea6
		   const xmlChar *prefix, const xmlChar *name,
Packit Service a31ea6
		   const xmlChar *prefix2, const xmlChar *name2,
Packit Service a31ea6
		   const xmlChar *prefix3, const xmlChar *name3) {
Packit Service a31ea6
    unsigned long value = 0L;
Packit Service a31ea6
    char ch;
Packit Service a31ea6
Packit Service a31ea6
#ifdef HASH_RANDOMIZATION
Packit Service a31ea6
    value = table->random_seed;
Packit Service a31ea6
#endif
Packit Service a31ea6
    if (prefix != NULL)
Packit Service a31ea6
	value += 30 * (*prefix);
Packit Service a31ea6
    else
Packit Service a31ea6
	value += 30 * (*name);
Packit Service a31ea6
Packit Service a31ea6
    if (prefix != NULL) {
Packit Service a31ea6
	while ((ch = *prefix++) != 0) {
Packit Service a31ea6
	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Packit Service a31ea6
	}
Packit Service a31ea6
	value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
Packit Service a31ea6
    }
Packit Service a31ea6
    if (name != NULL) {
Packit Service a31ea6
	while ((ch = *name++) != 0) {
Packit Service a31ea6
	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    value = value ^ ((value << 5) + (value >> 3));
Packit Service a31ea6
    if (prefix2 != NULL) {
Packit Service a31ea6
	while ((ch = *prefix2++) != 0) {
Packit Service a31ea6
	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Packit Service a31ea6
	}
Packit Service a31ea6
	value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
Packit Service a31ea6
    }
Packit Service a31ea6
    if (name2 != NULL) {
Packit Service a31ea6
	while ((ch = *name2++) != 0) {
Packit Service a31ea6
	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    value = value ^ ((value << 5) + (value >> 3));
Packit Service a31ea6
    if (prefix3 != NULL) {
Packit Service a31ea6
	while ((ch = *prefix3++) != 0) {
Packit Service a31ea6
	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Packit Service a31ea6
	}
Packit Service a31ea6
	value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
Packit Service a31ea6
    }
Packit Service a31ea6
    if (name3 != NULL) {
Packit Service a31ea6
	while ((ch = *name3++) != 0) {
Packit Service a31ea6
	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    return (value % table->size);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashCreate:
Packit Service a31ea6
 * @size: the size of the hash table
Packit Service a31ea6
 *
Packit Service a31ea6
 * Create a new xmlHashTablePtr.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the newly created object, or NULL if an error occurred.
Packit Service a31ea6
 */
Packit Service a31ea6
xmlHashTablePtr
Packit Service a31ea6
xmlHashCreate(int size) {
Packit Service a31ea6
    xmlHashTablePtr table;
Packit Service a31ea6
Packit Service a31ea6
    if (size <= 0)
Packit Service a31ea6
        size = 256;
Packit Service a31ea6
Packit Service a31ea6
    table = xmlMalloc(sizeof(xmlHashTable));
Packit Service a31ea6
    if (table) {
Packit Service a31ea6
        table->dict = NULL;
Packit Service a31ea6
        table->size = size;
Packit Service a31ea6
	table->nbElems = 0;
Packit Service a31ea6
        table->table = xmlMalloc(size * sizeof(xmlHashEntry));
Packit Service a31ea6
        if (table->table) {
Packit Service a31ea6
	    memset(table->table, 0, size * sizeof(xmlHashEntry));
Packit Service a31ea6
#ifdef HASH_RANDOMIZATION
Packit Service a31ea6
            table->random_seed = __xmlRandom();
Packit Service a31ea6
#endif
Packit Service a31ea6
	    return(table);
Packit Service a31ea6
        }
Packit Service a31ea6
        xmlFree(table);
Packit Service a31ea6
    }
Packit Service a31ea6
    return(NULL);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashCreateDict:
Packit Service a31ea6
 * @size: the size of the hash table
Packit Service a31ea6
 * @dict: a dictionary to use for the hash
Packit Service a31ea6
 *
Packit Service a31ea6
 * Create a new xmlHashTablePtr which will use @dict as the internal dictionary
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the newly created object, or NULL if an error occurred.
Packit Service a31ea6
 */
Packit Service a31ea6
xmlHashTablePtr
Packit Service a31ea6
xmlHashCreateDict(int size, xmlDictPtr dict) {
Packit Service a31ea6
    xmlHashTablePtr table;
Packit Service a31ea6
Packit Service a31ea6
    table = xmlHashCreate(size);
Packit Service a31ea6
    if (table != NULL) {
Packit Service a31ea6
        table->dict = dict;
Packit Service a31ea6
	xmlDictReference(dict);
Packit Service a31ea6
    }
Packit Service a31ea6
    return(table);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashGrow:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @size: the new size of the hash table
Packit Service a31ea6
 *
Packit Service a31ea6
 * resize the hash table
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 in case of success, -1 in case of failure
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlHashGrow(xmlHashTablePtr table, int size) {
Packit Service a31ea6
    unsigned long key;
Packit Service a31ea6
    int oldsize, i;
Packit Service a31ea6
    xmlHashEntryPtr iter, next;
Packit Service a31ea6
    struct _xmlHashEntry *oldtable;
Packit Service a31ea6
#ifdef DEBUG_GROW
Packit Service a31ea6
    unsigned long nbElem = 0;
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
    if (table == NULL)
Packit Service a31ea6
	return(-1);
Packit Service a31ea6
    if (size < 8)
Packit Service a31ea6
        return(-1);
Packit Service a31ea6
    if (size > 8 * 2048)
Packit Service a31ea6
	return(-1);
Packit Service a31ea6
Packit Service a31ea6
    oldsize = table->size;
Packit Service a31ea6
    oldtable = table->table;
Packit Service a31ea6
    if (oldtable == NULL)
Packit Service a31ea6
        return(-1);
Packit Service a31ea6
Packit Service a31ea6
    table->table = xmlMalloc(size * sizeof(xmlHashEntry));
Packit Service a31ea6
    if (table->table == NULL) {
Packit Service a31ea6
	table->table = oldtable;
Packit Service a31ea6
	return(-1);
Packit Service a31ea6
    }
Packit Service a31ea6
    memset(table->table, 0, size * sizeof(xmlHashEntry));
Packit Service a31ea6
    table->size = size;
Packit Service a31ea6
Packit Service a31ea6
    /*	If the two loops are merged, there would be situations where
Packit Service a31ea6
	a new entry needs to allocated and data copied into it from
Packit Service a31ea6
	the main table. So instead, we run through the array twice, first
Packit Service a31ea6
	copying all the elements in the main array (where we can't get
Packit Service a31ea6
	conflicts) and then the rest, so we only free (and don't allocate)
Packit Service a31ea6
    */
Packit Service a31ea6
    for (i = 0; i < oldsize; i++) {
Packit Service a31ea6
	if (oldtable[i].valid == 0)
Packit Service a31ea6
	    continue;
Packit Service a31ea6
	key = xmlHashComputeKey(table, oldtable[i].name, oldtable[i].name2,
Packit Service a31ea6
				oldtable[i].name3);
Packit Service a31ea6
	memcpy(&(table->table[key]), &(oldtable[i]), sizeof(xmlHashEntry));
Packit Service a31ea6
	table->table[key].next = NULL;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    for (i = 0; i < oldsize; i++) {
Packit Service a31ea6
	iter = oldtable[i].next;
Packit Service a31ea6
	while (iter) {
Packit Service a31ea6
	    next = iter->next;
Packit Service a31ea6
Packit Service a31ea6
	    /*
Packit Service a31ea6
	     * put back the entry in the new table
Packit Service a31ea6
	     */
Packit Service a31ea6
Packit Service a31ea6
	    key = xmlHashComputeKey(table, iter->name, iter->name2,
Packit Service a31ea6
		                    iter->name3);
Packit Service a31ea6
	    if (table->table[key].valid == 0) {
Packit Service a31ea6
		memcpy(&(table->table[key]), iter, sizeof(xmlHashEntry));
Packit Service a31ea6
		table->table[key].next = NULL;
Packit Service a31ea6
		xmlFree(iter);
Packit Service a31ea6
	    } else {
Packit Service a31ea6
		iter->next = table->table[key].next;
Packit Service a31ea6
		table->table[key].next = iter;
Packit Service a31ea6
	    }
Packit Service a31ea6
Packit Service a31ea6
#ifdef DEBUG_GROW
Packit Service a31ea6
	    nbElem++;
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
	    iter = next;
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    xmlFree(oldtable);
Packit Service a31ea6
Packit Service a31ea6
#ifdef DEBUG_GROW
Packit Service a31ea6
    xmlGenericError(xmlGenericErrorContext,
Packit Service a31ea6
	    "xmlHashGrow : from %d to %d, %d elems\n", oldsize, size, nbElem);
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashFree:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @f:  the deallocator function for items in the hash
Packit Service a31ea6
 *
Packit Service a31ea6
 * Free the hash @table and its contents. The userdata is
Packit Service a31ea6
 * deallocated with @f if provided.
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) {
Packit Service a31ea6
    int i;
Packit Service a31ea6
    xmlHashEntryPtr iter;
Packit Service a31ea6
    xmlHashEntryPtr next;
Packit Service a31ea6
    int inside_table = 0;
Packit Service a31ea6
    int nbElems;
Packit Service a31ea6
Packit Service a31ea6
    if (table == NULL)
Packit Service a31ea6
	return;
Packit Service a31ea6
    if (table->table) {
Packit Service a31ea6
	nbElems = table->nbElems;
Packit Service a31ea6
	for(i = 0; (i < table->size) && (nbElems > 0); i++) {
Packit Service a31ea6
	    iter = &(table->table[i]);
Packit Service a31ea6
	    if (iter->valid == 0)
Packit Service a31ea6
		continue;
Packit Service a31ea6
	    inside_table = 1;
Packit Service a31ea6
	    while (iter) {
Packit Service a31ea6
		next = iter->next;
Packit Service a31ea6
		if ((f != NULL) && (iter->payload != NULL))
Packit Service a31ea6
		    f(iter->payload, iter->name);
Packit Service a31ea6
		if (table->dict == NULL) {
Packit Service a31ea6
		    if (iter->name)
Packit Service a31ea6
			xmlFree(iter->name);
Packit Service a31ea6
		    if (iter->name2)
Packit Service a31ea6
			xmlFree(iter->name2);
Packit Service a31ea6
		    if (iter->name3)
Packit Service a31ea6
			xmlFree(iter->name3);
Packit Service a31ea6
		}
Packit Service a31ea6
		iter->payload = NULL;
Packit Service a31ea6
		if (!inside_table)
Packit Service a31ea6
		    xmlFree(iter);
Packit Service a31ea6
		nbElems--;
Packit Service a31ea6
		inside_table = 0;
Packit Service a31ea6
		iter = next;
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
	xmlFree(table->table);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (table->dict)
Packit Service a31ea6
        xmlDictFree(table->dict);
Packit Service a31ea6
    xmlFree(table);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashAddEntry:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @userdata: a pointer to the userdata
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add the @userdata to the hash @table. This can later be retrieved
Packit Service a31ea6
 * by using the @name. Duplicate names generate errors.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 the addition succeeded and -1 in case of error.
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata) {
Packit Service a31ea6
    return(xmlHashAddEntry3(table, name, NULL, NULL, userdata));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashAddEntry2:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @name2: a second name of the userdata
Packit Service a31ea6
 * @userdata: a pointer to the userdata
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add the @userdata to the hash @table. This can later be retrieved
Packit Service a31ea6
 * by using the (@name, @name2) tuple. Duplicate tuples generate errors.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 the addition succeeded and -1 in case of error.
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
	        const xmlChar *name2, void *userdata) {
Packit Service a31ea6
    return(xmlHashAddEntry3(table, name, name2, NULL, userdata));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashUpdateEntry:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @userdata: a pointer to the userdata
Packit Service a31ea6
 * @f: the deallocator function for replaced item (if any)
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add the @userdata to the hash @table. This can later be retrieved
Packit Service a31ea6
 * by using the @name. Existing entry for this @name will be removed
Packit Service a31ea6
 * and freed with @f if found.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 the addition succeeded and -1 in case of error.
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlHashUpdateEntry(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
	           void *userdata, xmlHashDeallocator f) {
Packit Service a31ea6
    return(xmlHashUpdateEntry3(table, name, NULL, NULL, userdata, f));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashUpdateEntry2:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @name2: a second name of the userdata
Packit Service a31ea6
 * @userdata: a pointer to the userdata
Packit Service a31ea6
 * @f: the deallocator function for replaced item (if any)
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add the @userdata to the hash @table. This can later be retrieved
Packit Service a31ea6
 * by using the (@name, @name2) tuple. Existing entry for this tuple will
Packit Service a31ea6
 * be removed and freed with @f if found.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 the addition succeeded and -1 in case of error.
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlHashUpdateEntry2(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
	           const xmlChar *name2, void *userdata,
Packit Service a31ea6
		   xmlHashDeallocator f) {
Packit Service a31ea6
    return(xmlHashUpdateEntry3(table, name, name2, NULL, userdata, f));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashLookup:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 *
Packit Service a31ea6
 * Find the userdata specified by the @name.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the pointer to the userdata
Packit Service a31ea6
 */
Packit Service a31ea6
void *
Packit Service a31ea6
xmlHashLookup(xmlHashTablePtr table, const xmlChar *name) {
Packit Service a31ea6
    return(xmlHashLookup3(table, name, NULL, NULL));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashLookup2:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @name2: a second name of the userdata
Packit Service a31ea6
 *
Packit Service a31ea6
 * Find the userdata specified by the (@name, @name2) tuple.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the pointer to the userdata
Packit Service a31ea6
 */
Packit Service a31ea6
void *
Packit Service a31ea6
xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
	      const xmlChar *name2) {
Packit Service a31ea6
    return(xmlHashLookup3(table, name, name2, NULL));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashQLookup:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @prefix: the prefix of the userdata
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 *
Packit Service a31ea6
 * Find the userdata specified by the QName @prefix:@name/@name.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the pointer to the userdata
Packit Service a31ea6
 */
Packit Service a31ea6
void *
Packit Service a31ea6
xmlHashQLookup(xmlHashTablePtr table, const xmlChar *prefix,
Packit Service a31ea6
               const xmlChar *name) {
Packit Service a31ea6
    return(xmlHashQLookup3(table, prefix, name, NULL, NULL, NULL, NULL));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashQLookup2:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @prefix: the prefix of the userdata
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @prefix2: the second prefix of the userdata
Packit Service a31ea6
 * @name2: a second name of the userdata
Packit Service a31ea6
 *
Packit Service a31ea6
 * Find the userdata specified by the QNames tuple
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the pointer to the userdata
Packit Service a31ea6
 */
Packit Service a31ea6
void *
Packit Service a31ea6
xmlHashQLookup2(xmlHashTablePtr table, const xmlChar *prefix,
Packit Service a31ea6
                const xmlChar *name, const xmlChar *prefix2,
Packit Service a31ea6
	        const xmlChar *name2) {
Packit Service a31ea6
    return(xmlHashQLookup3(table, prefix, name, prefix2, name2, NULL, NULL));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashAddEntry3:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @name2: a second name of the userdata
Packit Service a31ea6
 * @name3: a third name of the userdata
Packit Service a31ea6
 * @userdata: a pointer to the userdata
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add the @userdata to the hash @table. This can later be retrieved
Packit Service a31ea6
 * by using the tuple (@name, @name2, @name3). Duplicate entries generate
Packit Service a31ea6
 * errors.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 the addition succeeded and -1 in case of error.
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
	         const xmlChar *name2, const xmlChar *name3,
Packit Service a31ea6
		 void *userdata) {
Packit Service a31ea6
    unsigned long key, len = 0;
Packit Service a31ea6
    xmlHashEntryPtr entry;
Packit Service a31ea6
    xmlHashEntryPtr insert;
Packit Service a31ea6
Packit Service a31ea6
    if ((table == NULL) || (name == NULL))
Packit Service a31ea6
	return(-1);
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * If using a dict internalize if needed
Packit Service a31ea6
     */
Packit Service a31ea6
    if (table->dict) {
Packit Service a31ea6
        if (!xmlDictOwns(table->dict, name)) {
Packit Service a31ea6
	    name = xmlDictLookup(table->dict, name, -1);
Packit Service a31ea6
	    if (name == NULL)
Packit Service a31ea6
	        return(-1);
Packit Service a31ea6
	}
Packit Service a31ea6
        if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) {
Packit Service a31ea6
	    name2 = xmlDictLookup(table->dict, name2, -1);
Packit Service a31ea6
	    if (name2 == NULL)
Packit Service a31ea6
	        return(-1);
Packit Service a31ea6
	}
Packit Service a31ea6
        if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) {
Packit Service a31ea6
	    name3 = xmlDictLookup(table->dict, name3, -1);
Packit Service a31ea6
	    if (name3 == NULL)
Packit Service a31ea6
	        return(-1);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Check for duplicate and insertion location.
Packit Service a31ea6
     */
Packit Service a31ea6
    key = xmlHashComputeKey(table, name, name2, name3);
Packit Service a31ea6
    if (table->table[key].valid == 0) {
Packit Service a31ea6
	insert = NULL;
Packit Service a31ea6
    } else {
Packit Service a31ea6
        if (table->dict) {
Packit Service a31ea6
	    for (insert = &(table->table[key]); insert->next != NULL;
Packit Service a31ea6
		 insert = insert->next) {
Packit Service a31ea6
		if ((insert->name == name) &&
Packit Service a31ea6
		    (insert->name2 == name2) &&
Packit Service a31ea6
		    (insert->name3 == name3))
Packit Service a31ea6
		    return(-1);
Packit Service a31ea6
		len++;
Packit Service a31ea6
	    }
Packit Service a31ea6
	    if ((insert->name == name) &&
Packit Service a31ea6
		(insert->name2 == name2) &&
Packit Service a31ea6
		(insert->name3 == name3))
Packit Service a31ea6
		return(-1);
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    for (insert = &(table->table[key]); insert->next != NULL;
Packit Service a31ea6
		 insert = insert->next) {
Packit Service a31ea6
		if ((xmlStrEqual(insert->name, name)) &&
Packit Service a31ea6
		    (xmlStrEqual(insert->name2, name2)) &&
Packit Service a31ea6
		    (xmlStrEqual(insert->name3, name3)))
Packit Service a31ea6
		    return(-1);
Packit Service a31ea6
		len++;
Packit Service a31ea6
	    }
Packit Service a31ea6
	    if ((xmlStrEqual(insert->name, name)) &&
Packit Service a31ea6
		(xmlStrEqual(insert->name2, name2)) &&
Packit Service a31ea6
		(xmlStrEqual(insert->name3, name3)))
Packit Service a31ea6
		return(-1);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (insert == NULL) {
Packit Service a31ea6
	entry = &(table->table[key]);
Packit Service a31ea6
    } else {
Packit Service a31ea6
	entry = xmlMalloc(sizeof(xmlHashEntry));
Packit Service a31ea6
	if (entry == NULL)
Packit Service a31ea6
	     return(-1);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (table->dict != NULL) {
Packit Service a31ea6
        entry->name = (xmlChar *) name;
Packit Service a31ea6
        entry->name2 = (xmlChar *) name2;
Packit Service a31ea6
        entry->name3 = (xmlChar *) name3;
Packit Service a31ea6
    } else {
Packit Service a31ea6
	entry->name = xmlStrdup(name);
Packit Service a31ea6
	entry->name2 = xmlStrdup(name2);
Packit Service a31ea6
	entry->name3 = xmlStrdup(name3);
Packit Service a31ea6
    }
Packit Service a31ea6
    entry->payload = userdata;
Packit Service a31ea6
    entry->next = NULL;
Packit Service a31ea6
    entry->valid = 1;
Packit Service a31ea6
Packit Service a31ea6
Packit Service a31ea6
    if (insert != NULL)
Packit Service a31ea6
	insert->next = entry;
Packit Service a31ea6
Packit Service a31ea6
    table->nbElems++;
Packit Service a31ea6
Packit Service a31ea6
    if (len > MAX_HASH_LEN)
Packit Service a31ea6
	xmlHashGrow(table, MAX_HASH_LEN * table->size);
Packit Service a31ea6
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashUpdateEntry3:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @name2: a second name of the userdata
Packit Service a31ea6
 * @name3: a third name of the userdata
Packit Service a31ea6
 * @userdata: a pointer to the userdata
Packit Service a31ea6
 * @f: the deallocator function for replaced item (if any)
Packit Service a31ea6
 *
Packit Service a31ea6
 * Add the @userdata to the hash @table. This can later be retrieved
Packit Service a31ea6
 * by using the tuple (@name, @name2, @name3). Existing entry for this tuple
Packit Service a31ea6
 * will be removed and freed with @f if found.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 the addition succeeded and -1 in case of error.
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
	           const xmlChar *name2, const xmlChar *name3,
Packit Service a31ea6
		   void *userdata, xmlHashDeallocator f) {
Packit Service a31ea6
    unsigned long key;
Packit Service a31ea6
    xmlHashEntryPtr entry;
Packit Service a31ea6
    xmlHashEntryPtr insert;
Packit Service a31ea6
Packit Service a31ea6
    if ((table == NULL) || name == NULL)
Packit Service a31ea6
	return(-1);
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * If using a dict internalize if needed
Packit Service a31ea6
     */
Packit Service a31ea6
    if (table->dict) {
Packit Service a31ea6
        if (!xmlDictOwns(table->dict, name)) {
Packit Service a31ea6
	    name = xmlDictLookup(table->dict, name, -1);
Packit Service a31ea6
	    if (name == NULL)
Packit Service a31ea6
	        return(-1);
Packit Service a31ea6
	}
Packit Service a31ea6
        if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) {
Packit Service a31ea6
	    name2 = xmlDictLookup(table->dict, name2, -1);
Packit Service a31ea6
	    if (name2 == NULL)
Packit Service a31ea6
	        return(-1);
Packit Service a31ea6
	}
Packit Service a31ea6
        if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) {
Packit Service a31ea6
	    name3 = xmlDictLookup(table->dict, name3, -1);
Packit Service a31ea6
	    if (name3 == NULL)
Packit Service a31ea6
	        return(-1);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Check for duplicate and insertion location.
Packit Service a31ea6
     */
Packit Service a31ea6
    key = xmlHashComputeKey(table, name, name2, name3);
Packit Service a31ea6
    if (table->table[key].valid == 0) {
Packit Service a31ea6
	insert = NULL;
Packit Service a31ea6
    } else {
Packit Service a31ea6
        if (table ->dict) {
Packit Service a31ea6
	    for (insert = &(table->table[key]); insert->next != NULL;
Packit Service a31ea6
		 insert = insert->next) {
Packit Service a31ea6
		if ((insert->name == name) &&
Packit Service a31ea6
		    (insert->name2 == name2) &&
Packit Service a31ea6
		    (insert->name3 == name3)) {
Packit Service a31ea6
		    if (f)
Packit Service a31ea6
			f(insert->payload, insert->name);
Packit Service a31ea6
		    insert->payload = userdata;
Packit Service a31ea6
		    return(0);
Packit Service a31ea6
		}
Packit Service a31ea6
	    }
Packit Service a31ea6
	    if ((insert->name == name) &&
Packit Service a31ea6
		(insert->name2 == name2) &&
Packit Service a31ea6
		(insert->name3 == name3)) {
Packit Service a31ea6
		if (f)
Packit Service a31ea6
		    f(insert->payload, insert->name);
Packit Service a31ea6
		insert->payload = userdata;
Packit Service a31ea6
		return(0);
Packit Service a31ea6
	    }
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    for (insert = &(table->table[key]); insert->next != NULL;
Packit Service a31ea6
		 insert = insert->next) {
Packit Service a31ea6
		if ((xmlStrEqual(insert->name, name)) &&
Packit Service a31ea6
		    (xmlStrEqual(insert->name2, name2)) &&
Packit Service a31ea6
		    (xmlStrEqual(insert->name3, name3))) {
Packit Service a31ea6
		    if (f)
Packit Service a31ea6
			f(insert->payload, insert->name);
Packit Service a31ea6
		    insert->payload = userdata;
Packit Service a31ea6
		    return(0);
Packit Service a31ea6
		}
Packit Service a31ea6
	    }
Packit Service a31ea6
	    if ((xmlStrEqual(insert->name, name)) &&
Packit Service a31ea6
		(xmlStrEqual(insert->name2, name2)) &&
Packit Service a31ea6
		(xmlStrEqual(insert->name3, name3))) {
Packit Service a31ea6
		if (f)
Packit Service a31ea6
		    f(insert->payload, insert->name);
Packit Service a31ea6
		insert->payload = userdata;
Packit Service a31ea6
		return(0);
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (insert == NULL) {
Packit Service a31ea6
	entry =  &(table->table[key]);
Packit Service a31ea6
    } else {
Packit Service a31ea6
	entry = xmlMalloc(sizeof(xmlHashEntry));
Packit Service a31ea6
	if (entry == NULL)
Packit Service a31ea6
	     return(-1);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (table->dict != NULL) {
Packit Service a31ea6
        entry->name = (xmlChar *) name;
Packit Service a31ea6
        entry->name2 = (xmlChar *) name2;
Packit Service a31ea6
        entry->name3 = (xmlChar *) name3;
Packit Service a31ea6
    } else {
Packit Service a31ea6
	entry->name = xmlStrdup(name);
Packit Service a31ea6
	entry->name2 = xmlStrdup(name2);
Packit Service a31ea6
	entry->name3 = xmlStrdup(name3);
Packit Service a31ea6
    }
Packit Service a31ea6
    entry->payload = userdata;
Packit Service a31ea6
    entry->next = NULL;
Packit Service a31ea6
    entry->valid = 1;
Packit Service a31ea6
    table->nbElems++;
Packit Service a31ea6
Packit Service a31ea6
Packit Service a31ea6
    if (insert != NULL) {
Packit Service a31ea6
	insert->next = entry;
Packit Service a31ea6
    }
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashLookup3:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @name2: a second name of the userdata
Packit Service a31ea6
 * @name3: a third name of the userdata
Packit Service a31ea6
 *
Packit Service a31ea6
 * Find the userdata specified by the (@name, @name2, @name3) tuple.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the a pointer to the userdata
Packit Service a31ea6
 */
Packit Service a31ea6
void *
Packit Service a31ea6
xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
	       const xmlChar *name2, const xmlChar *name3) {
Packit Service a31ea6
    unsigned long key;
Packit Service a31ea6
    xmlHashEntryPtr entry;
Packit Service a31ea6
Packit Service a31ea6
    if (table == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    if (name == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    key = xmlHashComputeKey(table, name, name2, name3);
Packit Service a31ea6
    if (table->table[key].valid == 0)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    if (table->dict) {
Packit Service a31ea6
	for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
Packit Service a31ea6
	    if ((entry->name == name) &&
Packit Service a31ea6
		(entry->name2 == name2) &&
Packit Service a31ea6
		(entry->name3 == name3))
Packit Service a31ea6
		return(entry->payload);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
Packit Service a31ea6
	if ((xmlStrEqual(entry->name, name)) &&
Packit Service a31ea6
	    (xmlStrEqual(entry->name2, name2)) &&
Packit Service a31ea6
	    (xmlStrEqual(entry->name3, name3)))
Packit Service a31ea6
	    return(entry->payload);
Packit Service a31ea6
    }
Packit Service a31ea6
    return(NULL);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashQLookup3:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @prefix: the prefix of the userdata
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @prefix2: the second prefix of the userdata
Packit Service a31ea6
 * @name2: a second name of the userdata
Packit Service a31ea6
 * @prefix3: the third prefix of the userdata
Packit Service a31ea6
 * @name3: a third name of the userdata
Packit Service a31ea6
 *
Packit Service a31ea6
 * Find the userdata specified by the (@name, @name2, @name3) tuple.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the a pointer to the userdata
Packit Service a31ea6
 */
Packit Service a31ea6
void *
Packit Service a31ea6
xmlHashQLookup3(xmlHashTablePtr table,
Packit Service a31ea6
                const xmlChar *prefix, const xmlChar *name,
Packit Service a31ea6
		const xmlChar *prefix2, const xmlChar *name2,
Packit Service a31ea6
		const xmlChar *prefix3, const xmlChar *name3) {
Packit Service a31ea6
    unsigned long key;
Packit Service a31ea6
    xmlHashEntryPtr entry;
Packit Service a31ea6
Packit Service a31ea6
    if (table == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    if (name == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    key = xmlHashComputeQKey(table, prefix, name, prefix2,
Packit Service a31ea6
                             name2, prefix3, name3);
Packit Service a31ea6
    if (table->table[key].valid == 0)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
Packit Service a31ea6
	if ((xmlStrQEqual(prefix, name, entry->name)) &&
Packit Service a31ea6
	    (xmlStrQEqual(prefix2, name2, entry->name2)) &&
Packit Service a31ea6
	    (xmlStrQEqual(prefix3, name3, entry->name3)))
Packit Service a31ea6
	    return(entry->payload);
Packit Service a31ea6
    }
Packit Service a31ea6
    return(NULL);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
typedef struct {
Packit Service a31ea6
    xmlHashScanner hashscanner;
Packit Service a31ea6
    void *data;
Packit Service a31ea6
} stubData;
Packit Service a31ea6
Packit Service a31ea6
static void
Packit Service a31ea6
stubHashScannerFull (void *payload, void *data, const xmlChar *name,
Packit Service a31ea6
                     const xmlChar *name2 ATTRIBUTE_UNUSED,
Packit Service a31ea6
		     const xmlChar *name3 ATTRIBUTE_UNUSED) {
Packit Service a31ea6
    stubData *stubdata = (stubData *) data;
Packit Service a31ea6
    stubdata->hashscanner (payload, stubdata->data, (xmlChar *) name);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashScan:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @f:  the scanner function for items in the hash
Packit Service a31ea6
 * @data:  extra data passed to f
Packit Service a31ea6
 *
Packit Service a31ea6
 * Scan the hash @table and applied @f to each value.
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data) {
Packit Service a31ea6
    stubData stubdata;
Packit Service a31ea6
    stubdata.data = data;
Packit Service a31ea6
    stubdata.hashscanner = f;
Packit Service a31ea6
    xmlHashScanFull (table, stubHashScannerFull, &stubdata);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashScanFull:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @f:  the scanner function for items in the hash
Packit Service a31ea6
 * @data:  extra data passed to f
Packit Service a31ea6
 *
Packit Service a31ea6
 * Scan the hash @table and applied @f to each value.
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data) {
Packit Service a31ea6
    int i, nb;
Packit Service a31ea6
    xmlHashEntryPtr iter;
Packit Service a31ea6
    xmlHashEntryPtr next;
Packit Service a31ea6
Packit Service a31ea6
    if (table == NULL)
Packit Service a31ea6
	return;
Packit Service a31ea6
    if (f == NULL)
Packit Service a31ea6
	return;
Packit Service a31ea6
Packit Service a31ea6
    if (table->table) {
Packit Service a31ea6
	for(i = 0; i < table->size; i++) {
Packit Service a31ea6
	    if (table->table[i].valid == 0)
Packit Service a31ea6
		continue;
Packit Service a31ea6
	    iter = &(table->table[i]);
Packit Service a31ea6
	    while (iter) {
Packit Service a31ea6
		next = iter->next;
Packit Service a31ea6
                nb = table->nbElems;
Packit Service a31ea6
		if ((f != NULL) && (iter->payload != NULL))
Packit Service a31ea6
		    f(iter->payload, data, iter->name,
Packit Service a31ea6
		      iter->name2, iter->name3);
Packit Service a31ea6
                if (nb != table->nbElems) {
Packit Service a31ea6
                    /* table was modified by the callback, be careful */
Packit Service a31ea6
                    if (iter == &(table->table[i])) {
Packit Service a31ea6
                        if (table->table[i].valid == 0)
Packit Service a31ea6
                            iter = NULL;
Packit Service a31ea6
                        if (table->table[i].next != next)
Packit Service a31ea6
			    iter = &(table->table[i]);
Packit Service a31ea6
                    } else
Packit Service a31ea6
		        iter = next;
Packit Service a31ea6
                } else
Packit Service a31ea6
		    iter = next;
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashScan3:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata or NULL
Packit Service a31ea6
 * @name2: a second name of the userdata or NULL
Packit Service a31ea6
 * @name3: a third name of the userdata or NULL
Packit Service a31ea6
 * @f:  the scanner function for items in the hash
Packit Service a31ea6
 * @data:  extra data passed to f
Packit Service a31ea6
 *
Packit Service a31ea6
 * Scan the hash @table and applied @f to each value matching
Packit Service a31ea6
 * (@name, @name2, @name3) tuple. If one of the names is null,
Packit Service a31ea6
 * the comparison is considered to match.
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlHashScan3(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
	     const xmlChar *name2, const xmlChar *name3,
Packit Service a31ea6
	     xmlHashScanner f, void *data) {
Packit Service a31ea6
    xmlHashScanFull3 (table, name, name2, name3,
Packit Service a31ea6
		      (xmlHashScannerFull) f, data);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashScanFull3:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata or NULL
Packit Service a31ea6
 * @name2: a second name of the userdata or NULL
Packit Service a31ea6
 * @name3: a third name of the userdata or NULL
Packit Service a31ea6
 * @f:  the scanner function for items in the hash
Packit Service a31ea6
 * @data:  extra data passed to f
Packit Service a31ea6
 *
Packit Service a31ea6
 * Scan the hash @table and applied @f to each value matching
Packit Service a31ea6
 * (@name, @name2, @name3) tuple. If one of the names is null,
Packit Service a31ea6
 * the comparison is considered to match.
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlHashScanFull3(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
		 const xmlChar *name2, const xmlChar *name3,
Packit Service a31ea6
		 xmlHashScannerFull f, void *data) {
Packit Service a31ea6
    int i;
Packit Service a31ea6
    xmlHashEntryPtr iter;
Packit Service a31ea6
    xmlHashEntryPtr next;
Packit Service a31ea6
Packit Service a31ea6
    if (table == NULL)
Packit Service a31ea6
	return;
Packit Service a31ea6
    if (f == NULL)
Packit Service a31ea6
	return;
Packit Service a31ea6
Packit Service a31ea6
    if (table->table) {
Packit Service a31ea6
	for(i = 0; i < table->size; i++) {
Packit Service a31ea6
	    if (table->table[i].valid == 0)
Packit Service a31ea6
		continue;
Packit Service a31ea6
	    iter = &(table->table[i]);
Packit Service a31ea6
	    while (iter) {
Packit Service a31ea6
		next = iter->next;
Packit Service a31ea6
		if (((name == NULL) || (xmlStrEqual(name, iter->name))) &&
Packit Service a31ea6
		    ((name2 == NULL) || (xmlStrEqual(name2, iter->name2))) &&
Packit Service a31ea6
		    ((name3 == NULL) || (xmlStrEqual(name3, iter->name3))) &&
Packit Service a31ea6
		    (iter->payload != NULL)) {
Packit Service a31ea6
		    f(iter->payload, data, iter->name,
Packit Service a31ea6
		      iter->name2, iter->name3);
Packit Service a31ea6
		}
Packit Service a31ea6
		iter = next;
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashCopy:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @f:  the copier function for items in the hash
Packit Service a31ea6
 *
Packit Service a31ea6
 * Scan the hash @table and applied @f to each value.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the new table or NULL in case of error.
Packit Service a31ea6
 */
Packit Service a31ea6
xmlHashTablePtr
Packit Service a31ea6
xmlHashCopy(xmlHashTablePtr table, xmlHashCopier f) {
Packit Service a31ea6
    int i;
Packit Service a31ea6
    xmlHashEntryPtr iter;
Packit Service a31ea6
    xmlHashEntryPtr next;
Packit Service a31ea6
    xmlHashTablePtr ret;
Packit Service a31ea6
Packit Service a31ea6
    if (table == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    if (f == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    ret = xmlHashCreate(table->size);
Packit Service a31ea6
    if (ret == NULL)
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    if (table->table) {
Packit Service a31ea6
	for(i = 0; i < table->size; i++) {
Packit Service a31ea6
	    if (table->table[i].valid == 0)
Packit Service a31ea6
		continue;
Packit Service a31ea6
	    iter = &(table->table[i]);
Packit Service a31ea6
	    while (iter) {
Packit Service a31ea6
		next = iter->next;
Packit Service a31ea6
		xmlHashAddEntry3(ret, iter->name, iter->name2,
Packit Service a31ea6
			         iter->name3, f(iter->payload, iter->name));
Packit Service a31ea6
		iter = next;
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    ret->nbElems = table->nbElems;
Packit Service a31ea6
    return(ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashSize:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 *
Packit Service a31ea6
 * Query the number of elements installed in the hash @table.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the number of elements in the hash table or
Packit Service a31ea6
 * -1 in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlHashSize(xmlHashTablePtr table) {
Packit Service a31ea6
    if (table == NULL)
Packit Service a31ea6
	return(-1);
Packit Service a31ea6
    return(table->nbElems);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashRemoveEntry:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @f: the deallocator function for removed item (if any)
Packit Service a31ea6
 *
Packit Service a31ea6
 * Find the userdata specified by the @name and remove
Packit Service a31ea6
 * it from the hash @table. Existing userdata for this tuple will be removed
Packit Service a31ea6
 * and freed with @f.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 if the removal succeeded and -1 in case of error or not found.
Packit Service a31ea6
 */
Packit Service a31ea6
int xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
		       xmlHashDeallocator f) {
Packit Service a31ea6
    return(xmlHashRemoveEntry3(table, name, NULL, NULL, f));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashRemoveEntry2:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @name2: a second name of the userdata
Packit Service a31ea6
 * @f: the deallocator function for removed item (if any)
Packit Service a31ea6
 *
Packit Service a31ea6
 * Find the userdata specified by the (@name, @name2) tuple and remove
Packit Service a31ea6
 * it from the hash @table. Existing userdata for this tuple will be removed
Packit Service a31ea6
 * and freed with @f.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 if the removal succeeded and -1 in case of error or not found.
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
			const xmlChar *name2, xmlHashDeallocator f) {
Packit Service a31ea6
    return(xmlHashRemoveEntry3(table, name, name2, NULL, f));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlHashRemoveEntry3:
Packit Service a31ea6
 * @table: the hash table
Packit Service a31ea6
 * @name: the name of the userdata
Packit Service a31ea6
 * @name2: a second name of the userdata
Packit Service a31ea6
 * @name3: a third name of the userdata
Packit Service a31ea6
 * @f: the deallocator function for removed item (if any)
Packit Service a31ea6
 *
Packit Service a31ea6
 * Find the userdata specified by the (@name, @name2, @name3) tuple and remove
Packit Service a31ea6
 * it from the hash @table. Existing userdata for this tuple will be removed
Packit Service a31ea6
 * and freed with @f.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 if the removal succeeded and -1 in case of error or not found.
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name,
Packit Service a31ea6
    const xmlChar *name2, const xmlChar *name3, xmlHashDeallocator f) {
Packit Service a31ea6
    unsigned long key;
Packit Service a31ea6
    xmlHashEntryPtr entry;
Packit Service a31ea6
    xmlHashEntryPtr prev = NULL;
Packit Service a31ea6
Packit Service a31ea6
    if (table == NULL || name == NULL)
Packit Service a31ea6
        return(-1);
Packit Service a31ea6
Packit Service a31ea6
    key = xmlHashComputeKey(table, name, name2, name3);
Packit Service a31ea6
    if (table->table[key].valid == 0) {
Packit Service a31ea6
        return(-1);
Packit Service a31ea6
    } else {
Packit Service a31ea6
        for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
Packit Service a31ea6
            if (xmlStrEqual(entry->name, name) &&
Packit Service a31ea6
                    xmlStrEqual(entry->name2, name2) &&
Packit Service a31ea6
                    xmlStrEqual(entry->name3, name3)) {
Packit Service a31ea6
                if ((f != NULL) && (entry->payload != NULL))
Packit Service a31ea6
                    f(entry->payload, entry->name);
Packit Service a31ea6
                entry->payload = NULL;
Packit Service a31ea6
		if (table->dict == NULL) {
Packit Service a31ea6
		    if(entry->name)
Packit Service a31ea6
			xmlFree(entry->name);
Packit Service a31ea6
		    if(entry->name2)
Packit Service a31ea6
			xmlFree(entry->name2);
Packit Service a31ea6
		    if(entry->name3)
Packit Service a31ea6
			xmlFree(entry->name3);
Packit Service a31ea6
		}
Packit Service a31ea6
                if(prev) {
Packit Service a31ea6
                    prev->next = entry->next;
Packit Service a31ea6
		    xmlFree(entry);
Packit Service a31ea6
		} else {
Packit Service a31ea6
		    if (entry->next == NULL) {
Packit Service a31ea6
			entry->valid = 0;
Packit Service a31ea6
		    } else {
Packit Service a31ea6
			entry = entry->next;
Packit Service a31ea6
			memcpy(&(table->table[key]), entry, sizeof(xmlHashEntry));
Packit Service a31ea6
			xmlFree(entry);
Packit Service a31ea6
		    }
Packit Service a31ea6
		}
Packit Service a31ea6
                table->nbElems--;
Packit Service a31ea6
                return(0);
Packit Service a31ea6
            }
Packit Service a31ea6
            prev = entry;
Packit Service a31ea6
        }
Packit Service a31ea6
        return(-1);
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
#define bottom_hash
Packit Service a31ea6
#include "elfgcchack.h"