Commit 64a70c8e authored by Pierre d'Herbemont's avatar Pierre d'Herbemont

include/vlc_arrays.h: Transform the dictionary macro to static inline, and...

include/vlc_arrays.h: Transform the dictionary macro to static inline, and publish a vlc_dictionary_t type.
parent 52676b52
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#ifndef _VLC_ARRAYS_H_ #ifndef _VLC_ARRAYS_H_
#define _VLC_ARRAYS_H_ #define _VLC_ARRAYS_H_
#include <assert.h>
/** /**
* Simple dynamic array handling. Array is realloced at each insert/removal * Simple dynamic array handling. Array is realloced at each insert/removal
*/ */
...@@ -187,7 +189,7 @@ ...@@ -187,7 +189,7 @@
* fast and not suck too much. This one is pretty fast and did 0 collisions * fast and not suck too much. This one is pretty fast and did 0 collisions
* in wenglish's dictionary. * 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; uint64_t i_hash = 0;
if( psz_string ) if( psz_string )
...@@ -199,139 +201,126 @@ static inline uint64_t DictHash( const char *psz_string, int i_int ) ...@@ -199,139 +201,126 @@ static inline uint64_t DictHash( const char *psz_string, int i_int )
i_hash ^= i_hash >> 8; i_hash ^= i_hash >> 8;
} }
} }
return i_hash + ( (uint64_t)i_int << 32 ); return i_hash;
} }
#define DICT_TYPE(name,type) \ typedef struct vlc_dictionary_t
typedef struct dict_entry_##name##_t { \ {
int i_int; \ struct vlc_dictionary_entries_t
char *psz_string; \ {
uint64_t i_hash; \ char * psz_key;
type data; \ uint64_t i_hash;
} dict_entry_##name##_t; \ void * p_value;
typedef struct dict_##name##_t { \ } * p_entries;
dict_entry_##name##_t *p_entries; \ int i_entries;
int i_entries; \ } vlc_dictionary_t;
} dict_##name##_t;
static void * const kVLCDictionaryNotFound = (void *)-1;
#define DICT_NEW( p_dict ) { \
p_dict = malloc( sizeof(int)+sizeof(void*) ); \ static inline void vlc_dictionary_init( vlc_dictionary_t * p_dict )
p_dict->i_entries = 0; \ {
p_dict->p_entries = NULL; \ p_dict->i_entries = 0;
p_dict->p_entries = NULL;
} }
#define DICT_CLEAR( zdict ) { \ static inline void vlc_dictionary_clear( vlc_dictionary_t * p_dict )
int _i_dict = 0; \ {
for ( _i_dict = 0; _i_dict < zdict->i_entries; _i_dict++ ) \ int i;
{ \ for ( i = 0; i < p_dict->i_entries; i++ )
FREE( zdict->p_entries[_i_dict].psz_string ); \ {
} \ free( p_dict->p_entries[i].psz_key );
FREE( zdict->p_entries ); \ }
free( zdict ); \ 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) ); \ static inline void *
int i_new; \ vlc_dictionary_value_for_key( vlc_dictionary_t * p_dict, const char * psz_key )
/* Find a free slot */ \ {
if( zdict->i_entries == 0 || i_hash <= zdict->p_entries[0].i_hash ) \ uint64_t i_hash;
i_new = 0; \ int i, i_pos;
else if( i_hash >= zdict->p_entries[zdict->i_entries-1].i_hash ) \
i_new = zdict->i_entries;\ if( p_dict->i_entries == 0 )
else \ return kVLCDictionaryNotFound;
{ \
int i_low = 0, i_high = zdict->i_entries - 1; \ i_hash = DictHash( psz_key );
while( i_high - i_low > 1 ) \ BSEARCH( p_dict->p_entries, p_dict->i_entries, .i_hash, uint64_t,
{ \ i_hash, i_pos );
int i_mid = (i_low + i_high)/2; \ if( i_pos == -1 )
fprintf(stderr, "Low %i, high %i\n", i_low, i_high); \ return kVLCDictionaryNotFound;
if( zdict->p_entries[i_mid].i_hash < i_hash ) { \
i_low = i_mid; \ /* Hash found, let's check it looks like the entry */
} else if( zdict->p_entries[i_mid].i_hash > i_hash ) { \ if( !strcmp( psz_key, p_dict->p_entries[i_pos].psz_key ) )
i_high = i_mid; \ return p_dict->p_entries[i_pos].p_value;
} \
} \ /* Hash collision! This should be very rare, but we cannot guarantee
if( zdict->p_entries[i_low].i_hash < i_hash ) \ * it will never happen. Just do an exhaustive search amongst all
i_new = i_high; \ * entries with the same hash. */
else \ for( i = i_pos - 1 ; i > 0 && i_hash == p_dict->p_entries[i].i_hash ; i-- )
i_new = i_low; \ {
} \ if( !strcmp( psz_key, p_dict->p_entries[i].psz_key ) )
zdict->p_entries = realloc( zdict->p_entries, (zdict->i_entries + 1) * \ return p_dict->p_entries[i_pos].p_value;
( sizeof(zdata) + sizeof(int) + sizeof(void*) + sizeof(uint64_t) ) ); \ }
zdict->i_entries++; \ for( i = i_pos + 1 ; i < p_dict->i_entries &&
if( i_new != zdict->i_entries -1 ) \ i_hash == p_dict->p_entries[i].i_hash ; i++ )
memmove( &zdict->p_entries[i_new+1], &zdict->p_entries[i_new], \ {
( zdict->i_entries - i_new - 1 ) * \ if( !strcmp( psz_key, p_dict->p_entries[i].psz_key ))
( sizeof(zdata) + sizeof(int) + sizeof(void*) + sizeof(uint64_t) ) );\ return p_dict->p_entries[i_pos].p_value;
\ }
zdict->p_entries[i_new].i_hash = i_hash; \ /* Hash found, but entry not found (shouldn't happen!) */
zdict->p_entries[i_new].i_int = (zint); \ return kVLCDictionaryNotFound;
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; \
} }
#define DICT_LOOKUP( zdict, zint, zstring, answer ) do { \ static inline void
uint64_t i_hash; \ vlc_dictionary_insert( vlc_dictionary_t * p_dict, const char * psz_key, void * p_value )
int i, i_pos; \ {
vlc_bool_t b_found = VLC_FALSE; \ uint64_t i_hash = DictHash( psz_key );
if( zdict->i_entries == 0 ) { \ int i_new;
answer = -1; \
break; \ /* 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 );
i_hash = DictHash( (zstring), (zint) ); \
BSEARCH( zdict->p_entries, zdict->i_entries, .i_hash, uint64_t, \ /* Find a free slot */
i_hash, i_pos ); \ if( p_dict->i_entries == 0 || i_hash <= p_dict->p_entries[0].i_hash )
if( i_pos == -1 ) { \ i_new = 0;
answer = -1; \ else if( i_hash >= p_dict->p_entries[p_dict->i_entries-1].i_hash )
break; \ i_new = p_dict->i_entries;
} \ else
\ {
/* Hash found, let's check it looks like the entry */ \ int i_low = 0, i_high = p_dict->i_entries - 1;
if( !strcmp( (zstring), zdict->p_entries[i_pos].psz_string ) ) { \ while( i_high - i_low > 1 )
answer = i_pos; \ {
break; \ int i_mid = (i_low + i_high)/2;
} \ if( p_dict->p_entries[i_mid].i_hash < i_hash ) {
\ i_low = i_mid;
/* Hash collision! This should be very rare, but we cannot guarantee \ } else if( p_dict->p_entries[i_mid].i_hash > i_hash ) {
* it will never happen. Just do an exhaustive search amongst all \ i_high = i_mid;
* entries with the same hash. */ \ }
for( i = i_pos - 1 ; i > 0 && i_hash == zdict->p_entries[i].i_hash ; i-- )\ }
{ \ if( p_dict->p_entries[i_low].i_hash < i_hash )
if( !strcmp( (zstring), zdict->p_entries[i].psz_string ) && \ i_new = i_high;
zdict->p_entries[i].i_int == (zint) ) { \ else
b_found = VLC_TRUE; \ i_new = i_low;
answer = i; \ }
break; \ 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( b_found == VLC_TRUE ) \ if( i_new != p_dict->i_entries -1 )
break; \ {
for( i = i_pos + 1 ; i < zdict->i_entries && \ memmove( &p_dict->p_entries[i_new+1], &p_dict->p_entries[i_new],
i_hash == zdict->p_entries[i].i_hash ; i++ ) \ ( p_dict->i_entries - i_new - 1 ) *
{ \ sizeof(struct vlc_dictionary_entries_t) );
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)
#define DICT_GET( zdict, i_int, psz_string, answer ) { \ p_dict->p_entries[i_new].i_hash = i_hash;
int int_answer; \ p_dict->p_entries[i_new].psz_key = strdup( psz_key );
DICT_LOOKUP( zdict, i_int, psz_string, int_answer ); \ p_dict->p_entries[i_new].p_value = p_value;
if( int_answer >= 0 ) \
answer = zdict->p_entries[int_answer].data; \
} }
/************************************************************************ /************************************************************************
* Dynamic arrays with progressive allocation * Dynamic arrays with progressive allocation
************************************************************************/ ************************************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment