/** * create a new hash table * * @return pblHashTable_t * retptr != NULL: pointer to new hash table * @return pblHashTable_t * retptr == NULL: OUT OF MEMORY */ pblHashTable_t * pblHtCreate( void ) { pbl_hashtable_t * ht; ht = pbl_malloc0( "pblHtCreate hashtable", sizeof( pbl_hashtable_t ) ); if( !ht ) { return( 0 ); } ht->buckets = pbl_malloc0( "pblHtCreate buckets", sizeof( pbl_hashbucket_t ) * PBL_HASHTABLE_SIZE); if( !ht->buckets ) { PBL_FREE( ht ); return( 0 ); } /* * set the magic marker of the hashtable */ ht->magic = rcsid; return( ( pblHashTable_t * )ht ); }
int pblHtInsert( pblHashTable_t * h, /** hash table to insert to */ void * key, /** key to insert */ size_t keylen, /** length of that key */ void * dataptr /** dataptr to insert */ ) { pbl_hashtable_t * ht = ( pbl_hashtable_t * )h; pbl_hashbucket_t * bucket = 0; pbl_hashitem_t * item = 0; int hashval = hash( key, keylen ); bucket = ht->buckets + hashval; if( keylen < (size_t)1 ) { /* * the length of the key can not be smaller than 1 */ pbl_errno = PBL_ERROR_EXISTS; return( -1 ); } for( item = bucket->head; item; item = item->bucketnext ) { if(( item->keylen == keylen ) && !memcmp( item->key, key, keylen )) { snprintf( pbl_errstr, PBL_ERRSTR_LEN, "insert of duplicate item in hashtable\n" ); pbl_errno = PBL_ERROR_EXISTS; return( -1 ); } } item = pbl_malloc0( "pblHtInsert hashitem", sizeof( pbl_hashitem_t ) ); if( !item ) { return( -1 ); } item->key = pbl_memdup( "pblHtInsert item->key", key, keylen ); if( !item->key ) { PBL_FREE( item ); return( -1 ); } item->keylen = keylen; item->data = dataptr; /* * link the item */ PBL_LIST_APPEND( bucket->head, bucket->tail, item, bucketnext, bucketprev ); PBL_LIST_APPEND( ht->head, ht->tail, item, next, prev ); ht->current = item; return( 0 ); }
/** * Removes the mapping for this key from this map if it is present. * * More formally, if this map contains a mapping from a key k to a value v such that * (key==null ? k==null : memcmp( key, k, keyLength ) == 0, * that mapping is removed. * (The map can contain at most one such mapping.) * * Returns the previous value associated with key, * NULL if there was no mapping for key * or (void*)-1 in case of an error. * * Note: If a valid pointer to a value is returned, the value returned is * malloced on the heap. It is the caller's responsibility to free that memory * once it is no longer needed. * * For hash maps this method has a time complexity of O(1). * For tree maps this method has a time complexity of O(Log N). * * @return void * retptr != (void*)-1: The previously associated value. * @return void * retptr == (void*)-1: An error, see pbl_errno: * * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ void * pblMapRemove( /* */ PblMap * map, /** The map to remove from */ void * key, /** Key whose association is removed */ size_t keyLength, /** Length of the key */ size_t * valueLengthPtr /** Out: Length of the value returned */ ) { PblMapEntry * mapEntry; void * retptr = NULL; PblMapKey mapKey; mapKey.tag = PBL_MAP_KEY_TAG; mapKey.keyLength = keyLength; mapKey.key = key; mapEntry = (PblMapEntry *)pblSetGetElement( map->entrySet, &mapKey ); if( !mapEntry ) { if( valueLengthPtr ) { *valueLengthPtr = 0; } return NULL; } if( mapEntry->valueLength > 0 ) { retptr = pbl_memdup( "pblMapRemove", mapEntry->buffer + mapEntry->keyLength, mapEntry->valueLength ); } else { retptr = pbl_malloc0( "pblMapRemove0", 1 ); } if( !retptr ) { if( valueLengthPtr ) { *valueLengthPtr = 0; } return (void*)-1; } if( valueLengthPtr ) { *valueLengthPtr = mapEntry->valueLength; } pblSetRemoveElement( map->entrySet, mapEntry ); PBL_FREE( mapEntry ); return retptr; }
/** * Creates a new hash map. * * This method has a time complexity of O(1). * * @return PblMap * retPtr != NULL: A pointer to the new map. * @return PblMap * retPtr == NULL: An error, see pbl_errno: * * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory. */ PblMap * pblMapNewHashMap( void ) { PblMap * pblMap = (PblMap *)pbl_malloc0( "pblMapNewHashMap", sizeof(PblMap) ); if( !pblMap ) { return NULL; } pblMap->entrySet = pblSetNewHashSet(); if( !pblMap->entrySet ) { PBL_FREE( pblMap ); return NULL; } pblSetSetCompareFunction( pblMap->entrySet, pblMapEntryCompareFunction ); pblSetSetHashValueFunction( pblMap->entrySet, pblMapEntryHashValue ); return pblMap; }
/** * Associates the specified value with the specified key in this map. * * If the map previously contained a mapping for the key, the old value is replaced by the specified value. * (A map m is said to contain a mapping for a key k if and only if pblMapContainsKey(k) would return true.) * * Returns the previous value associated with key, NULL if there was no mapping for key * or (void*)-1 in case of an error. * * Note: If a valid pointer to a value is returned, the value returned is * malloced on the heap. It is the caller's responsibility to free that memory * once it is no longer needed. * * For hash maps this method has a time complexity of O(1). * For tree maps this method has a time complexity of O(Log N). * * @return void * retptr != (void*)-1: The previously associated value. * @return void * retptr == NULL: There was no previously associated value. * @return void * retptr == (void*)-1: An error, see pbl_errno: * * <BR>PBL_ERROR_OUT_OF_MEMORY - Out of memory. * <BR>PBL_ERROR_OUT_OF_BOUNDS - Maximum capacity of the hash set exceeded. */ void * pblMapPut( /* */ PblMap * map, /** The map to add to */ void * key, /** Key to add a mapping for */ size_t keyLength, /** Length of the key */ void * value, /** Value of the new mapping */ size_t valueLength, /** Length of the value */ size_t * valueLengthPtr /** Out: Length of the value returned */ ) { int rc; PblMapEntry * mapEntry; PblMapEntry * newEntry = pblMapEntryNew( key, keyLength, value, valueLength ); if( !newEntry ) { return (void*)-1; } mapEntry = (PblMapEntry *)pblSetReplaceElement( map->entrySet, newEntry ); if( mapEntry ) { void * retptr; if( mapEntry->valueLength > 0 ) { retptr = pbl_memdup( "pblMapPut", mapEntry->buffer + mapEntry->keyLength, mapEntry->valueLength ); } else { retptr = pbl_malloc0( "pblMapPut0", 1 ); } if( !retptr ) { if( valueLengthPtr ) { *valueLengthPtr = 0; } pblSetReplaceElement( map->entrySet, mapEntry ); PBL_FREE( newEntry ); return (void*)-1; } if( valueLengthPtr ) { *valueLengthPtr = mapEntry->valueLength; } PBL_FREE( mapEntry ); return retptr; } if( valueLengthPtr ) { *valueLengthPtr = 0; } rc = pblSetAdd( map->entrySet, newEntry ); if( rc < 0 ) { PBL_FREE(newEntry); return (void*)-1; } return NULL; }