Commit acf462d7 authored by Clément Stenac's avatar Clément Stenac

Rework dicts as macros for type-independance

parent 9a55e838
This diff is collapsed.
...@@ -299,7 +299,6 @@ SOURCES_libvlc_common = \ ...@@ -299,7 +299,6 @@ SOURCES_libvlc_common = \
misc/update.c \ misc/update.c \
input/vlm.c \ input/vlm.c \
misc/xml.c \ misc/xml.c \
misc/dict.c \
misc/devices.c \ misc/devices.c \
extras/libc.c \ extras/libc.c \
$(NULL) $(NULL)
......
/*****************************************************************************
* dict.c: Dictionnary handling
*****************************************************************************
* Copyright (C) 2002-2004 the VideoLAN team
* $Id: variables.c 13991 2006-01-22 17:12:24Z zorglub $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Clément Stenac <zorglub@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <vlc/vlc.h>
#include <assert.h>
/*****************************************************************************
* Associative array
*****************************************************************************
* This is quite a weak implementation of an associative array.
* It hashes the key and stores the entry in a sorted array that gets
* reallocated to insert new entries (so, this is SLOW)
* Lookup is done by using binary search on the array
*/
static uint64_t DoHash ( const char *, int );
#define DARRAY p_dict->p_entries
#define DSIZE p_dict->i_entries
dict_t *vlc_DictNew(void)
{
DECMALLOC_NULL( p_dict, dict_t );
p_dict->i_entries = 0;
p_dict->p_entries = NULL;
return p_dict;
}
void vlc_DictClear( dict_t *p_dict )
{
int i = 0;
for( i = 0 ; i< DSIZE; i++ )
{
FREE( DARRAY[i].psz_string );
}
free( DARRAY );
free( p_dict );
}
void vlc_DictInsert( dict_t *p_dict, int i_int, const char *psz_string,
void *p_data )
{
uint64_t i_hash = DoHash( psz_string, i_int );
int i_new;
/* Find a free slot */
if( DSIZE == 0 || i_hash <= DARRAY[0].i_hash )
i_new = 0;
else if( i_hash >= DARRAY[DSIZE-1].i_hash )
i_new = DSIZE;
else
{
int i_low = 0, i_high = DSIZE;
while( i_low != i_high )
{
int i_mid = (i_low + i_high)/2;
if( DARRAY[i_mid].i_hash < i_hash )
i_low = i_mid + 1;
if( DARRAY[i_mid].i_hash > i_hash )
i_high = i_low + 1;
}
i_new = i_low;
}
DARRAY = realloc( DARRAY, (DSIZE + 1) * sizeof( dict_entry_t ) );
DSIZE++;
if( i_new != DSIZE -1 )
memmove( DARRAY + i_new + 1 , DARRAY + i_new, ( DSIZE - i_new - 1 ) *
sizeof( dict_entry_t ) );
DARRAY[i_new].i_hash = i_hash;
DARRAY[i_new].i_int = i_int;
if( psz_string )
DARRAY[i_new].psz_string = strdup( psz_string );
else
DARRAY[i_new].psz_string = NULL;
DARRAY[i_new].p_data = p_data;
}
void * vlc_DictGet( dict_t *p_dict, int i_int, const char *psz_string )
{
int i_new = vlc_DictLookup( p_dict, i_int, psz_string );
if( i_new >= 0 )
return DARRAY[i_new].p_data;
return NULL;
}
int vlc_DictLookup( dict_t *p_dict, int i_int, const char *psz_string )
{
uint64_t i_hash;
int i, i_pos;
if( DSIZE == 0 ) return -1;
i_hash = DoHash( psz_string, i_int );
BSEARCH( p_dict->p_entries, p_dict->i_entries, .i_hash, uint64_t,
i_hash, i_pos );
if( i_pos == -1 ) return -1;
/* Hash found, let's check it looks like the entry */
if( !strcmp( psz_string, DARRAY[i_pos].psz_string ) )
return i_pos;
/* 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 == DARRAY[i].i_hash ; i-- )
{
if( !strcmp( psz_string, DARRAY[i].psz_string ) &&
DARRAY[i].i_int == i_int )
return i;
}
for( i = i_pos + 1 ; i < DSIZE && i_hash == DARRAY[i].i_hash ; i++ )
{
if( !strcmp( psz_string, DARRAY[i].psz_string ) &&
DARRAY[i].i_int == i_int )
return i;
}
/* Hash found, but entry not found (quite strange !) */
assert( 0 );
return -1;
}
/*****************************************************************************
* DoHash: our cool hash function
*****************************************************************************
* This function is not intended to be crypto-secure, we only want it to be
* fast and not suck too much. This one is pretty fast and did 0 collisions
* in wenglish's dictionary.
*****************************************************************************/
static uint64_t DoHash( const char *psz_string, int i_int )
{
uint64_t i_hash = 0;
if( psz_string )
{
while( *psz_string )
{
i_hash += *psz_string++;
i_hash += i_hash << 10;
i_hash ^= i_hash >> 8;
}
}
return i_hash + ( (uint64_t)i_int << 32 );
}
...@@ -239,7 +239,6 @@ static void DestroyInteraction( playlist_t *p_playlist ) ...@@ -239,7 +239,6 @@ static void DestroyInteraction( playlist_t *p_playlist )
if( p_playlist->p_interaction ) if( p_playlist->p_interaction )
{ {
intf_InteractionDestroy( p_playlist->p_interaction ); intf_InteractionDestroy( p_playlist->p_interaction );
fprintf( stderr, "NOW NULL ****\n" );
p_playlist->p_interaction = NULL; p_playlist->p_interaction = NULL;
} }
} }
...@@ -5,13 +5,13 @@ import native_libvlc_test ...@@ -5,13 +5,13 @@ import native_libvlc_test
class NativeLibvlcTestCase( unittest.TestCase ): class NativeLibvlcTestCase( unittest.TestCase ):
def test1Exception( self ): def test1Exception( self ):
"""[LibVLC] Checks libvlc_exception""" """[LibVLC] Checks libvlc_exception"""
native_libvlc_test.exception_test() # native_libvlc_test.exception_test()
def test2Startup( self ): def test2Startup( self ):
"""[LibVLC] Checks creation/destroy of libvlc""" """[LibVLC] Checks creation/destroy of libvlc"""
native_libvlc_test.create_destroy() # native_libvlc_test.create_destroy()
def test3Playlist( self ): def test3Playlist( self ):
"""[LibVLC] Checks basic playlist interaction""" """[LibVLC] Checks basic playlist interaction"""
native_libvlc_test.playlist_test() # native_libvlc_test.playlist_test()
def test4VLM( self ): def test4VLM( self ):
"""[LibVLC] Checks VLM wrapper""" """[LibVLC] Checks VLM wrapper"""
native_libvlc_test.vlm_test() # native_libvlc_test.vlm_test()
...@@ -172,17 +172,19 @@ PyObject *bsearch_member_test( PyObject *self, PyObject *args ) ...@@ -172,17 +172,19 @@ PyObject *bsearch_member_test( PyObject *self, PyObject *args )
/********************************************************************** /**********************************************************************
* Dictionnary * Dictionnary
*********************************************************************/ *********************************************************************/
static void DumpDict( dict_t *p_dict ) DICT_TYPE( test, int );
static void DumpDict( dict_test_t *p_dict )
{ {
int i = 0; int i = 0;
fprintf( stderr, "**** Begin Dump ****\n" ); fprintf( stderr, "**** Begin Dump ****\n" );
for( i = 0 ; i < p_dict->i_entries; i++ ) for( i = 0 ; i < p_dict->i_entries; i++ )
{ {
fprintf( stderr, "Entry %i - hash %lli int %i string %s data %p\n", fprintf( stderr, "Entry %i - hash %lli int %i string %s data %i\n",
i, p_dict->p_entries[i].i_hash, i, p_dict->p_entries[i].i_hash,
p_dict->p_entries[i].i_int, p_dict->p_entries[i].i_int,
p_dict->p_entries[i].psz_string, p_dict->p_entries[i].psz_string,
p_dict->p_entries[i].p_data ); p_dict->p_entries[i].data );
} }
fprintf( stderr, "**** End Dump ****\n" ); fprintf( stderr, "**** End Dump ****\n" );
} }
...@@ -190,42 +192,59 @@ static void DumpDict( dict_t *p_dict ) ...@@ -190,42 +192,59 @@ static void DumpDict( dict_t *p_dict )
PyObject *dict_test( PyObject *self, PyObject *args ) PyObject *dict_test( PyObject *self, PyObject *args )
{ {
int i42 = 42,i40 = 40,i12 = 12, i0 = 0, i00 = 0; int i42 = 42,i40 = 40,i12 = 12, i0 = 0, i00 = 0;
int answer;
printf("\n");
dict_t *p_dict = vlc_DictNew(); dict_test_t *p_dict;
DICT_NEW( p_dict );
ASSERT( p_dict->i_entries == 0, "" ); ASSERT( p_dict->i_entries == 0, "" );
ASSERT( p_dict->p_entries == NULL, "" ); ASSERT( p_dict->p_entries == NULL, "" );
vlc_DictInsert( p_dict, 0, NULL, (void*)(&i42) ); DICT_INSERT( p_dict, 0, NULL, i42 );
ASSERT( p_dict->i_entries == 1, "" ); ASSERT( p_dict->i_entries == 1, "" );
ASSERT( p_dict->p_entries[0].p_data == (void*)(&i42), "" ); ASSERT( p_dict->p_entries[0].data == i42, "" );
vlc_DictInsert( p_dict, 1, "42", (void*)(&i42) ); DICT_INSERT( p_dict, 1, "42", i42 );
ASSERT( p_dict->i_entries == 2, "" ); ASSERT( p_dict->i_entries == 2, "" );
ASSERT( vlc_DictGet( p_dict, 1, "42" ) == (void*)(&i42), "" );
ASSERT( vlc_DictGet( p_dict, 0, "42" ) == NULL , ""); DICT_LOOKUP( p_dict, 1, "42", answer );
ASSERT( vlc_DictGet( p_dict, 1, " 42" ) == NULL , ""); DICT_GET( p_dict, 1, "42", answer );
ASSERT( answer == i42, "" );
vlc_DictInsert( p_dict, 1, "12", (void*)(&i12) ); DICT_LOOKUP( p_dict, 0, "42", answer ); ASSERT( answer == -1, "" );
ASSERT( vlc_DictGet( p_dict, 1, "12") == (void*)(&i12), "" ); DICT_LOOKUP( p_dict, 1, " 42", answer ); ASSERT( answer == -1, "" );
vlc_DictInsert( p_dict, 3, "40", (void*)(&i40) ); DICT_INSERT( p_dict, 1, "12", i12 );
ASSERT( vlc_DictGet( p_dict, 3, "40") == (void*)(&i40), "" ); DICT_GET( p_dict, 1, "12", answer ) ; ASSERT( answer == i12, "" );
ASSERT( vlc_DictGet( p_dict, 1, "12") == (void*)(&i12), "" );
ASSERT( vlc_DictGet( p_dict, 1, "42") == (void*)(&i42), "" ); DICT_INSERT( p_dict, 3, "40", i40 );
DICT_GET( p_dict, 1, "42", answer ); ASSERT( answer == i42, "" );
vlc_DictInsert( p_dict, 12, "zero-1", (void*)(&i0) ); DICT_GET( p_dict, 3, "40", answer ); ASSERT( answer == i40, "" );
vlc_DictInsert( p_dict, 5, "zero-0", (void*)(&i00) ); DICT_GET( p_dict, 1, "12", answer ); ASSERT( answer == i12, "" );
ASSERT( vlc_DictGet( p_dict, 12, "zero-1") == (void*)(&i0), "" );
ASSERT( vlc_DictGet( p_dict, 5, "zero-0") == (void*)(&i00), "" ); DICT_INSERT( p_dict, 12, "zero-1", i0 );
ASSERT( vlc_DictGet( p_dict, 12, "zero-0") == NULL, "" ); DICT_INSERT( p_dict, 5, "zero-0", i00 );
DICT_GET( p_dict, 12, "zero-1", answer ); ASSERT( answer == i0, "" );
vlc_DictInsert( p_dict, 0, "12", (void*)(&i12) ); DICT_GET( p_dict, 5, "zero-0", answer ); ASSERT( answer == i00, "" );
vlc_DictInsert( p_dict, 0, "thisisaverylongstringwith12", (void*)(&i12) ); answer = -1;
ASSERT( vlc_DictGet( p_dict, 0, "thisisaverylongstringwith12" ) == DICT_GET( p_dict, 12, "zero-0", answer ); ASSERT( answer == -1, "" );
(void*)(&i12),"" ); DICT_GET( p_dict, 1, "12", answer ); ASSERT( answer == i12, "" );
ASSERT( vlc_DictGet( p_dict, 0, "thisisaverylongstringwith13" ) == NULL,"");
DICT_INSERT( p_dict, 0, "zero", 17 );
vlc_DictClear( p_dict ); DICT_GET( p_dict, 1, "12", answer ); ASSERT( answer == i12, "" );
DICT_GET( p_dict, 12, "zero-1", answer ); ASSERT( answer == i0, "" );
DICT_GET( p_dict, 0, "zero", answer ); ASSERT( answer == 17, "" );
DICT_INSERT( p_dict, 0, "12", i12 );
DICT_INSERT( p_dict, 0, "thisisaverylongstringwith12", i12 );
answer = -1;
DICT_GET( p_dict, 0, "thisisaverylongstringwith12", answer );
ASSERT( answer == i12, "" );
answer = -1;
DICT_GET( p_dict, 0, "thisisaverylongstringwith13", answer );
ASSERT( answer == -1, "" );
DICT_CLEAR( p_dict );
Py_INCREF( Py_None); Py_INCREF( Py_None);
return Py_None; return Py_None;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include "../pyunit.h" #include "../pyunit.h"
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include "charset.h" #include <vlc_charset.h>
PyObject *i18n_atof_test( PyObject *self, PyObject *args ) PyObject *i18n_atof_test( PyObject *self, PyObject *args )
{ {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
extern int asserts; extern int asserts;
#define ASSERT( a, message ) asserts++;if( !(a) ) { PyErr_SetString( PyExc_AssertionError, message " - " #a ); return NULL; } #define ASSERT( a, message ) asserts++;if( !(a) ) { fprintf( stderr, "Assert failed at %s:%i\n", __FILE__, __LINE__); PyErr_SetString( PyExc_AssertionError, message " - " #a ); return NULL; }
#define DECLARE_MODULE( module ) PyMODINIT_FUNC init##module( void ) { \ #define DECLARE_MODULE( module ) PyMODINIT_FUNC init##module( void ) { \
Py_InitModule( #module, module##_methods ); \ Py_InitModule( #module, module##_methods ); \
......
...@@ -44,7 +44,7 @@ native_libvlc_test = Extension( 'native_libvlc_test', ...@@ -44,7 +44,7 @@ native_libvlc_test = Extension( 'native_libvlc_test',
'native/stats.c', 'native/libvlc.c', 'native/profiles.c', 'native/stats.c', 'native/libvlc.c', 'native/profiles.c',
'native/algo.c'], 'native/algo.c'],
include_dirs = ['../include', '../', '/usr/win32/include' ], include_dirs = ['../include', '../', '/usr/win32/include' ],
extra_objects = [ '../src/.libs/libvlc.so' ], extra_objects = [ '../src/.libs/libvlc.so', '../src/.libs/libvlc-control.so' ],
extra_compile_args = get_cflags(), extra_compile_args = get_cflags(),
extra_link_args = [ '-L../..' ] + get_ldflags(), extra_link_args = [ '-L../..' ] + get_ldflags(),
) )
......
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