hash.c revision e0e0c19eefceaf5d4ec40f9466b58a771f50e799
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/* Copyright (c) 2001, Stanford University
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * All rights reserved
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * See the file LICENSE.txt for information on redistributing this software.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynctypedef struct FreeElemRec {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynctypedef struct CRHashIdPoolRec {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynctypedef struct CRHashNode {
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync unsigned long key;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync unsigned int num_elements;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRHashIdPool *pool = (CRHashIdPool *) crCalloc(sizeof(CRHashIdPool));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync pool->freeList = (FreeElem *) crCalloc(sizeof(FreeElem));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Allocate a block of <count> IDs. Return index of first one.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Return 0 if we fail.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic GLuint crHashIdPoolAllocBlock( CRHashIdPool *pool, GLuint count )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* found a sufficiently large enough block */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* remove this block from linked list */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* remove from head */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* remove from elsewhere */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* make sure the IDs really are allocated */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (i = 0; i < count; i++)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync //CRASSERT(crHashIdPoolIsIdUsed(pool, ret + i));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* failed to find free block */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Free a block of <count> IDs starting at <first>.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic void crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint count )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /*********************************/
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Add the name to the freeList */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Find the bracketing sequences */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (i = pool->freeList; i && i->next && i->next->min < first; i = i->next)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* EMPTY BODY */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* j will always be valid */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Case: j:(~,first-1) */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Collapse */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Case: j->next: (first+1, ~) */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Collapse */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Case: j: (first+1, ~) j->next: null */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* allocate a new FreeElem node */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Case: j: (~,first-(2+)) j->next: (first+(2+), ~) or null */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Case: j: (first+(2+), ~) */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Can only happen if j = t->freeList! */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Mark the given Id as being allocated.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic void crHashIdPoolAllocId( CRHashIdPool *pool, GLuint id )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* found the block */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* somewhere in the middle - split the block */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync FreeElem *newelem = (FreeElem *) crCalloc(sizeof(FreeElem));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* if we get here, the ID was already allocated - that's OK */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Determine if the given id is free. Return GL_TRUE if so.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic GLboolean crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* First find which region it fits in */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (i = pool->freeList; i && !(i->min <= id && id <= i->max); i=i->next)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* EMPTY BODY */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRHashTable *hash = (CRHashTable *) crCalloc( sizeof( CRHashTable )) ;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (i = 0 ; i < CR_NUM_BUCKETS ; i++)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid crFreeHashtable( CRHashTable *hash, CRHashtableCallback deleteFunc )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if ( !hash) return;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for ( i = 0; i < CR_NUM_BUCKETS; i++ )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Clear the key in case crHashtableDelete() is called
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * from this callback.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid crHashtableWalk( CRHashTable *hash, CRHashtableWalkCallback walkFunc , void *dataPtr2)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for (i = 0; i < CR_NUM_BUCKETS; i++)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* save next ptr here, in case walkFunc deletes this entry */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid crHashtableAdd( CRHashTable *h, unsigned long key, void *data )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync CRHashNode *node = (CRHashNode *) crCalloc( sizeof( CRHashNode ) );
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncGLuint crHashtableAllocKeys( CRHashTable *h, GLsizei range)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for ( i = 0; i < range; i++)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid crHashtableDelete( CRHashTable *h, unsigned long key, CRHashtableCallback deleteFunc )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for ( temp = h->buckets[index]; temp; temp = temp->next )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return; /* not an error */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid crHashtableDeleteBlock( CRHashTable *h, unsigned long key, GLsizei range, CRHashtableCallback deleteFunc )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* XXX optimize someday */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid *crHashtableSearch( const CRHashTable *h, unsigned long key )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for ( temp = h->buckets[index]; temp; temp = temp->next )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncvoid crHashtableReplace( CRHashTable *h, unsigned long key, void *data,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync for ( temp = h->buckets[index]; temp; temp = temp->next )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncunsigned int crHashtableNumElements( const CRHashTable *h)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Determine if the given key is used. Return GL_TRUE if so.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncGLboolean crHashtableIsKeyUsed( const CRHashTable *h, GLuint id )
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return (GLboolean) !crHashIdPoolIsIdFree( h->idPool, id);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncGLboolean crHashtableGetDataKey(CRHashTable *pHash, void *pData, unsigned long *pKey)