From: Pierre d'Herbemont Date: Thu, 9 Aug 2007 18:38:48 +0000 (+0000) Subject: include/vlc_arrays.h: Transform the dictionary macro to static inline, and publish... X-Git-Tag: 0.9.0-test0~6601 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=64a70c8e36a8f65566cadcd47fb9821102c81303;p=vlc include/vlc_arrays.h: Transform the dictionary macro to static inline, and publish a vlc_dictionary_t type. --- diff --git a/include/vlc_arrays.h b/include/vlc_arrays.h index cb3cbecb94..5ee988e9d4 100644 --- a/include/vlc_arrays.h +++ b/include/vlc_arrays.h @@ -28,6 +28,8 @@ #ifndef _VLC_ARRAYS_H_ #define _VLC_ARRAYS_H_ +#include + /** * Simple dynamic array handling. Array is realloced at each insert/removal */ @@ -187,7 +189,7 @@ * fast and not suck too much. This one is pretty fast and did 0 collisions * in wenglish's dictionary. */ -static inline uint64_t DictHash( const char *psz_string, int i_int ) +static inline uint64_t DictHash( const char *psz_string ) { uint64_t i_hash = 0; if( psz_string ) @@ -199,139 +201,126 @@ static inline uint64_t DictHash( const char *psz_string, int i_int ) i_hash ^= i_hash >> 8; } } - return i_hash + ( (uint64_t)i_int << 32 ); + return i_hash; } -#define DICT_TYPE(name,type) \ - typedef struct dict_entry_##name##_t { \ - int i_int; \ - char *psz_string; \ - uint64_t i_hash; \ - type data; \ - } dict_entry_##name##_t; \ - typedef struct dict_##name##_t { \ - dict_entry_##name##_t *p_entries; \ - int i_entries; \ - } dict_##name##_t; - -#define DICT_NEW( p_dict ) { \ - p_dict = malloc( sizeof(int)+sizeof(void*) ); \ - p_dict->i_entries = 0; \ - p_dict->p_entries = NULL; \ +typedef struct vlc_dictionary_t +{ + struct vlc_dictionary_entries_t + { + char * psz_key; + uint64_t i_hash; + void * p_value; + } * p_entries; + int i_entries; +} vlc_dictionary_t; + +static void * const kVLCDictionaryNotFound = (void *)-1; + +static inline void vlc_dictionary_init( vlc_dictionary_t * p_dict ) +{ + p_dict->i_entries = 0; + p_dict->p_entries = NULL; } -#define DICT_CLEAR( zdict ) { \ - int _i_dict = 0; \ - for ( _i_dict = 0; _i_dict < zdict->i_entries; _i_dict++ ) \ - { \ - FREE( zdict->p_entries[_i_dict].psz_string ); \ - } \ - FREE( zdict->p_entries ); \ - free( zdict ); \ +static inline void vlc_dictionary_clear( vlc_dictionary_t * p_dict ) +{ + int i; + for ( i = 0; i < p_dict->i_entries; i++ ) + { + free( p_dict->p_entries[i].psz_key ); + } + free( p_dict->p_entries ); + p_dict->i_entries = 0; + p_dict->p_entries = NULL; } -#define DICT_INSERT( zdict, zint, zstring, zdata ) { \ - uint64_t i_hash = DictHash( (zstring), (zint) ); \ - int i_new; \ - /* Find a free slot */ \ - if( zdict->i_entries == 0 || i_hash <= zdict->p_entries[0].i_hash ) \ - i_new = 0; \ - else if( i_hash >= zdict->p_entries[zdict->i_entries-1].i_hash ) \ - i_new = zdict->i_entries;\ - else \ - { \ - int i_low = 0, i_high = zdict->i_entries - 1; \ - while( i_high - i_low > 1 ) \ - { \ - int i_mid = (i_low + i_high)/2; \ - fprintf(stderr, "Low %i, high %i\n", i_low, i_high); \ - if( zdict->p_entries[i_mid].i_hash < i_hash ) { \ - i_low = i_mid; \ - } else if( zdict->p_entries[i_mid].i_hash > i_hash ) { \ - i_high = i_mid; \ - } \ - } \ - if( zdict->p_entries[i_low].i_hash < i_hash ) \ - i_new = i_high; \ - else \ - i_new = i_low; \ - } \ - zdict->p_entries = realloc( zdict->p_entries, (zdict->i_entries + 1) * \ - ( sizeof(zdata) + sizeof(int) + sizeof(void*) + sizeof(uint64_t) ) ); \ - zdict->i_entries++; \ - if( i_new != zdict->i_entries -1 ) \ - memmove( &zdict->p_entries[i_new+1], &zdict->p_entries[i_new], \ - ( zdict->i_entries - i_new - 1 ) * \ - ( sizeof(zdata) + sizeof(int) + sizeof(void*) + sizeof(uint64_t) ) );\ - \ - zdict->p_entries[i_new].i_hash = i_hash; \ - zdict->p_entries[i_new].i_int = (zint); \ - if( (zstring) ) { \ - zdict->p_entries[i_new].psz_string = strdup( (zstring) ); \ - } else { \ - zdict->p_entries[i_new].psz_string = NULL; \ - } \ - zdict->p_entries[i_new].data = zdata; \ + +static inline void * +vlc_dictionary_value_for_key( vlc_dictionary_t * p_dict, const char * psz_key ) +{ + uint64_t i_hash; + int i, i_pos; + + if( p_dict->i_entries == 0 ) + return kVLCDictionaryNotFound; + + i_hash = DictHash( psz_key ); + BSEARCH( p_dict->p_entries, p_dict->i_entries, .i_hash, uint64_t, + i_hash, i_pos ); + if( i_pos == -1 ) + return kVLCDictionaryNotFound; + + /* Hash found, let's check it looks like the entry */ + if( !strcmp( psz_key, p_dict->p_entries[i_pos].psz_key ) ) + return p_dict->p_entries[i_pos].p_value; + + /* Hash collision! This should be very rare, but we cannot guarantee + * it will never happen. Just do an exhaustive search amongst all + * entries with the same hash. */ + for( i = i_pos - 1 ; i > 0 && i_hash == p_dict->p_entries[i].i_hash ; i-- ) + { + if( !strcmp( psz_key, p_dict->p_entries[i].psz_key ) ) + return p_dict->p_entries[i_pos].p_value; + } + for( i = i_pos + 1 ; i < p_dict->i_entries && + i_hash == p_dict->p_entries[i].i_hash ; i++ ) + { + if( !strcmp( psz_key, p_dict->p_entries[i].psz_key )) + return p_dict->p_entries[i_pos].p_value; + } + /* Hash found, but entry not found (shouldn't happen!) */ + return kVLCDictionaryNotFound; } -#define DICT_LOOKUP( zdict, zint, zstring, answer ) do { \ - uint64_t i_hash; \ - int i, i_pos; \ - vlc_bool_t b_found = VLC_FALSE; \ - if( zdict->i_entries == 0 ) { \ - answer = -1; \ - break; \ - } \ - \ - i_hash = DictHash( (zstring), (zint) ); \ - BSEARCH( zdict->p_entries, zdict->i_entries, .i_hash, uint64_t, \ - i_hash, i_pos ); \ - if( i_pos == -1 ) { \ - answer = -1; \ - break; \ - } \ - \ - /* Hash found, let's check it looks like the entry */ \ - if( !strcmp( (zstring), zdict->p_entries[i_pos].psz_string ) ) { \ - answer = i_pos; \ - break; \ - } \ - \ - /* Hash collision! This should be very rare, but we cannot guarantee \ - * it will never happen. Just do an exhaustive search amongst all \ - * entries with the same hash. */ \ - for( i = i_pos - 1 ; i > 0 && i_hash == zdict->p_entries[i].i_hash ; i-- )\ - { \ - if( !strcmp( (zstring), zdict->p_entries[i].psz_string ) && \ - zdict->p_entries[i].i_int == (zint) ) { \ - b_found = VLC_TRUE; \ - answer = i; \ - break; \ - } \ - } \ - if( b_found == VLC_TRUE ) \ - break; \ - for( i = i_pos + 1 ; i < zdict->i_entries && \ - i_hash == zdict->p_entries[i].i_hash ; i++ ) \ - { \ - if( !strcmp( (zstring), zdict->p_entries[i].psz_string ) && \ - zdict->p_entries[i].i_int == (zint) ) { \ - b_found = VLC_TRUE; \ - answer = i; \ - break; \ - } \ - } \ - /* Hash found, but entry not found (quite strange !) */ \ - assert( 0 ); \ -} while(0) +static inline void +vlc_dictionary_insert( vlc_dictionary_t * p_dict, const char * psz_key, void * p_value ) +{ + uint64_t i_hash = DictHash( psz_key ); + int i_new; + + /* First, caller should take care not to insert twice the same key */ + /* This could be removed for optimization */ + assert( vlc_dictionary_value_for_key( p_dict, psz_key ) == kVLCDictionaryNotFound ); + + /* Find a free slot */ + if( p_dict->i_entries == 0 || i_hash <= p_dict->p_entries[0].i_hash ) + i_new = 0; + else if( i_hash >= p_dict->p_entries[p_dict->i_entries-1].i_hash ) + i_new = p_dict->i_entries; + else + { + int i_low = 0, i_high = p_dict->i_entries - 1; + while( i_high - i_low > 1 ) + { + int i_mid = (i_low + i_high)/2; + if( p_dict->p_entries[i_mid].i_hash < i_hash ) { + i_low = i_mid; + } else if( p_dict->p_entries[i_mid].i_hash > i_hash ) { + i_high = i_mid; + } + } + if( p_dict->p_entries[i_low].i_hash < i_hash ) + i_new = i_high; + else + i_new = i_low; + } + p_dict->p_entries = realloc( p_dict->p_entries, (p_dict->i_entries + 1) * + sizeof( struct vlc_dictionary_entries_t ) ); + p_dict->i_entries++; + if( i_new != p_dict->i_entries -1 ) + { + memmove( &p_dict->p_entries[i_new+1], &p_dict->p_entries[i_new], + ( p_dict->i_entries - i_new - 1 ) * + sizeof(struct vlc_dictionary_entries_t) ); + } -#define DICT_GET( zdict, i_int, psz_string, answer ) { \ - int int_answer; \ - DICT_LOOKUP( zdict, i_int, psz_string, int_answer ); \ - if( int_answer >= 0 ) \ - answer = zdict->p_entries[int_answer].data; \ + p_dict->p_entries[i_new].i_hash = i_hash; + p_dict->p_entries[i_new].psz_key = strdup( psz_key ); + p_dict->p_entries[i_new].p_value = p_value; } + /************************************************************************ * Dynamic arrays with progressive allocation ************************************************************************/