Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
23d27c9c
Commit
23d27c9c
authored
Aug 19, 2006
by
Clément Stenac
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* B-search macro
* Redo dictionnary handling to remove recursion and bugs
parent
2c2ebc9c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
220 additions
and
19 deletions
+220
-19
include/vlc_common.h
include/vlc_common.h
+34
-8
include/vlc_symbols.h
include/vlc_symbols.h
+21
-9
src/Makefile.am
src/Makefile.am
+1
-1
src/input/item.c
src/input/item.c
+1
-1
src/misc/dict.c
src/misc/dict.c
+163
-0
No files found.
include/vlc_common.h
View file @
23d27c9c
...
...
@@ -203,7 +203,8 @@ typedef struct libvlc_t libvlc_t;
typedef
struct
vlc_t
vlc_t
;
typedef
struct
variable_t
variable_t
;
typedef
struct
date_t
date_t
;
typedef
struct
hashtable_entry_t
hashtable_entry_t
;
typedef
struct
dict_entry_t
dict_entry_t
;
typedef
struct
dict_t
dict_t
;
typedef
struct
gc_object_t
gc_object_t
;
/* Messages */
...
...
@@ -717,19 +718,44 @@ static int64_t GCD( int64_t a, int64_t b )
} \
}
/* Hash tables handling */
struct
hashtable_entry_t
/* Binary search in an array */
#define BSEARCH( entries, count, elem, zetype, key, answer ) { \
int low = 0, high = count - 1; \
answer = -1; \
while( low <= high ) {\
int mid = (low + high ) / 2;
/* Just don't care about 2^30 tables */
\
zetype mid_val = entries[mid] elem;\
if( mid_val < key ) \
low = mid + 1; \
else if ( mid_val > key ) \
high = mid -1; \
else \
{ \
answer = mid; break; \
}\
} \
}
/* Dictionnary handling */
struct
dict_entry_t
{
int
i_i
d
;
char
*
psz_
name
;
int
i_i
nt
;
char
*
psz_
string
;
uint64_t
i_hash
;
void
*
p_data
;
};
VLC_EXPORT
(
void
,
vlc_HashInsert
,
(
hashtable_entry_t
**
,
int
*
,
int
,
const
char
*
,
void
*
));
VLC_EXPORT
(
void
*
,
vlc_HashRetrieve
,
(
hashtable_entry_t
*
,
int
,
int
,
const
char
*
)
);
VLC_EXPORT
(
int
,
vlc_HashLookup
,
(
hashtable_entry_t
*
,
int
,
int
,
const
char
*
)
);
struct
dict_t
{
dict_entry_t
*
p_entries
;
int
i_entries
;
};
VLC_EXPORT
(
dict_t
*
,
vlc_DictNew
,
(
void
)
);
VLC_EXPORT
(
void
,
vlc_DictClear
,
(
dict_t
*
)
);
VLC_EXPORT
(
void
,
vlc_DictInsert
,
(
dict_t
*
,
int
,
const
char
*
,
void
*
)
);
VLC_EXPORT
(
void
*
,
vlc_DictGet
,
(
dict_t
*
,
int
,
const
char
*
)
);
VLC_EXPORT
(
int
,
vlc_DictLookup
,
(
dict_t
*
,
int
,
const
char
*
)
);
/* MSB (big endian)/LSB (little endian) conversions - network order is always
* MSB, and should be used for both network communications and files. Note that
...
...
include/vlc_symbols.h
View file @
23d27c9c
...
...
@@ -463,9 +463,9 @@ struct module_symbols_t
unsigned
int
(
*
update_iterator_ChooseMirrorAndFile_inner
)
(
update_iterator_t
*
,
int
,
int
,
int
);
update_t
*
(
*
__update_New_inner
)
(
vlc_object_t
*
);
void
(
*
update_download_inner
)
(
update_iterator_t
*
,
char
*
);
void
(
*
vlc_HashInsert_inner
)
(
hashtable_entry_t
**
,
int
*
,
int
,
const
char
*
,
void
*
)
;
int
(
*
vlc_HashLookup_inner
)
(
hashtable_entry_t
*
,
int
,
int
,
const
char
*
)
;
void
*
(
*
vlc_HashRetrieve_inner
)
(
hashtable_entry_t
*
,
int
,
int
,
const
char
*
)
;
void
*
vlc_HashInsert_deprecated
;
void
*
vlc_HashLookup_deprecated
;
void
*
vlc_HashRetrieve_deprecated
;
void
*
(
*
utf8_opendir_inner
)
(
const
char
*
dirname
);
FILE
*
(
*
utf8_fopen_inner
)
(
const
char
*
filename
,
const
char
*
mode
);
const
char
*
(
*
utf8_readdir_inner
)
(
void
*
dir
);
...
...
@@ -525,6 +525,11 @@ struct module_symbols_t
int
(
*
__intf_Progress_inner
)
(
vlc_object_t
*
,
const
char
*
,
const
char
*
,
float
,
int
);
void
(
*
__intf_ProgressUpdate_inner
)
(
vlc_object_t
*
,
int
,
const
char
*
,
float
,
int
);
int
(
*
playlist_AddInput_inner
)
(
playlist_t
*
,
input_item_t
*
,
int
,
int
,
vlc_bool_t
);
void
(
*
vlc_DictInsert_inner
)
(
dict_t
*
,
int
,
const
char
*
,
void
*
);
void
*
(
*
vlc_DictGet_inner
)
(
dict_t
*
,
int
,
const
char
*
);
int
(
*
vlc_DictLookup_inner
)
(
dict_t
*
,
int
,
const
char
*
);
void
(
*
vlc_DictClear_inner
)
(
dict_t
*
);
dict_t
*
(
*
vlc_DictNew_inner
)
(
void
);
};
# if defined (__PLUGIN__)
# define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner
...
...
@@ -936,9 +941,6 @@ struct module_symbols_t
# define update_iterator_ChooseMirrorAndFile (p_symbols)->update_iterator_ChooseMirrorAndFile_inner
# define __update_New (p_symbols)->__update_New_inner
# define update_download (p_symbols)->update_download_inner
# define vlc_HashInsert (p_symbols)->vlc_HashInsert_inner
# define vlc_HashLookup (p_symbols)->vlc_HashLookup_inner
# define vlc_HashRetrieve (p_symbols)->vlc_HashRetrieve_inner
# define utf8_opendir (p_symbols)->utf8_opendir_inner
# define utf8_fopen (p_symbols)->utf8_fopen_inner
# define utf8_readdir (p_symbols)->utf8_readdir_inner
...
...
@@ -988,6 +990,11 @@ struct module_symbols_t
# define __intf_Progress (p_symbols)->__intf_Progress_inner
# define __intf_ProgressUpdate (p_symbols)->__intf_ProgressUpdate_inner
# define playlist_AddInput (p_symbols)->playlist_AddInput_inner
# define vlc_DictInsert (p_symbols)->vlc_DictInsert_inner
# define vlc_DictGet (p_symbols)->vlc_DictGet_inner
# define vlc_DictLookup (p_symbols)->vlc_DictLookup_inner
# define vlc_DictClear (p_symbols)->vlc_DictClear_inner
# define vlc_DictNew (p_symbols)->vlc_DictNew_inner
# elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__)
/******************************************************************
* STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access.
...
...
@@ -1402,9 +1409,6 @@ struct module_symbols_t
((p_symbols)->update_iterator_ChooseMirrorAndFile_inner) = update_iterator_ChooseMirrorAndFile; \
((p_symbols)->__update_New_inner) = __update_New; \
((p_symbols)->update_download_inner) = update_download; \
((p_symbols)->vlc_HashInsert_inner) = vlc_HashInsert; \
((p_symbols)->vlc_HashLookup_inner) = vlc_HashLookup; \
((p_symbols)->vlc_HashRetrieve_inner) = vlc_HashRetrieve; \
((p_symbols)->utf8_opendir_inner) = utf8_opendir; \
((p_symbols)->utf8_fopen_inner) = utf8_fopen; \
((p_symbols)->utf8_readdir_inner) = utf8_readdir; \
...
...
@@ -1454,6 +1458,11 @@ struct module_symbols_t
((p_symbols)->__intf_Progress_inner) = __intf_Progress; \
((p_symbols)->__intf_ProgressUpdate_inner) = __intf_ProgressUpdate; \
((p_symbols)->playlist_AddInput_inner) = playlist_AddInput; \
((p_symbols)->vlc_DictInsert_inner) = vlc_DictInsert; \
((p_symbols)->vlc_DictGet_inner) = vlc_DictGet; \
((p_symbols)->vlc_DictLookup_inner) = vlc_DictLookup; \
((p_symbols)->vlc_DictClear_inner) = vlc_DictClear; \
((p_symbols)->vlc_DictNew_inner) = vlc_DictNew; \
(p_symbols)->net_ConvertIPv4_deprecated = NULL; \
(p_symbols)->__playlist_ItemNew_deprecated = NULL; \
(p_symbols)->__playlist_ItemCopy_deprecated = NULL; \
...
...
@@ -1489,6 +1498,9 @@ struct module_symbols_t
(p_symbols)->__stats_CounterGet_deprecated = NULL; \
(p_symbols)->stats_HandlerDestroy_deprecated = NULL; \
(p_symbols)->__stats_TimerDumpAll_deprecated = NULL; \
(p_symbols)->vlc_HashInsert_deprecated = NULL; \
(p_symbols)->vlc_HashLookup_deprecated = NULL; \
(p_symbols)->vlc_HashRetrieve_deprecated = NULL; \
(p_symbols)->playlist_ItemNewFromInput_deprecated = NULL; \
(p_symbols)->playlist_PlaylistAdd_deprecated = NULL; \
(p_symbols)->playlist_PlaylistAddExt_deprecated = NULL; \
...
...
src/Makefile.am
View file @
23d27c9c
...
...
@@ -325,7 +325,7 @@ SOURCES_libvlc_common = \
misc/update.c
\
misc/vlm.c
\
misc/xml.c
\
misc/
hashtables
.c
\
misc/
dict
.c
\
misc/devices.c
\
extras/libc.c
\
control/core.c
\
...
...
src/input/item.c
View file @
23d27c9c
...
...
@@ -70,7 +70,7 @@ char *vlc_input_item_GetInfo( input_item_t *p_i,
static
void
vlc_input_item_Destroy
(
gc_object_t
*
p_this
)
{
vlc_object_t
*
p_obj
=
(
vlc_object_t
*
)
p_this
->
p_destructor_arg
;
int
i
,
i_top
,
i_bottom
;
int
i
;
input_item_t
*
p_input
=
(
input_item_t
*
)
p_this
;
playlist_t
*
p_playlist
=
(
playlist_t
*
)
vlc_object_find
(
p_obj
,
...
...
src/misc/
hashtables
.c
→
src/misc/
dict
.c
View file @
23d27c9c
/*****************************************************************************
*
hashtables.c: Hash tables
handling
*
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>
* Clment Stenac <zorglub@videolan.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
...
...
@@ -22,202 +22,142 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <assert.h>
static
uint64_t
HashString
(
const
char
*
,
int
);
static
int
FindSlot
(
hashtable_entry_t
*
,
int
,
uint64_t
);
static
int
LookupInner
(
hashtable_entry_t
*
,
int
,
uint64_t
);
/*****************************************************************************
* 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
void
vlc_HashInsert
(
hashtable_entry_t
**
pp_array
,
int
*
pi_count
,
int
i_id
,
const
char
*
psz_name
,
void
*
p_data
)
dict_t
*
vlc_DictNew
()
{
hashtable_entry_t
*
p_new
;
int64_t
i_hash
=
HashString
(
psz_name
,
i_id
);
int
i_new
=
FindSlot
(
*
pp_array
,
*
pi_count
,
i_hash
);
*
pp_array
=
realloc
(
*
pp_array
,
(
*
pi_count
+
2
)
*
sizeof
(
hashtable_entry_t
)
);
memmove
(
*
pp_array
+
i_new
+
1
,
*
pp_array
+
i_new
,
(
*
pi_count
-
i_new
)
*
sizeof
(
hashtable_entry_t
)
);
(
*
pi_count
)
++
;
p_new
=
&
((
*
pp_array
)[
i_new
]);
p_new
->
i_hash
=
i_hash
;
p_new
->
i_id
=
i_id
;
p_new
->
psz_name
=
strdup
(
psz_name
);
p_new
->
p_data
=
p_data
;
DECMALLOC_NULL
(
p_dict
,
dict_t
);
p_dict
->
i_entries
=
0
;
p_dict
->
p_entries
=
NULL
;
return
p_dict
;
}
void
*
vlc_HashRetrieve
(
hashtable_entry_t
*
p_array
,
int
i_count
,
int
i_id
,
const
char
*
psz_name
)
void
vlc_DictClear
(
dict_t
*
p_dict
)
{
int
i_new
=
vlc_HashLookup
(
p_array
,
i_count
,
i_id
,
psz_name
);
if
(
i_new
>=
0
&&
i_new
<
i_count
)
int
i
=
0
;
for
(
i
=
0
;
i
<
DSIZE
;
i
++
)
{
return
p_array
[
i_new
].
p_data
;
FREE
(
DARRAY
[
i
].
psz_string
)
;
}
return
NULL
;
free
(
DARRAY
);
free
(
p_dict
);
}
/*****************************************************************************
* FindSlot: find an empty slot to insert a new variable
*****************************************************************************
* We use a recursive inner function indexed on the hash. This function does
* nothing in the rare cases where a collision may occur, see Lookup()
* to see how we handle them.
* XXX: does this really need to be written recursively?
*****************************************************************************/
static
int
FindSlot
(
hashtable_entry_t
*
p_array
,
int
i_count
,
uint64_t
i_hash
)
void
vlc_DictInsert
(
dict_t
*
p_dict
,
int
i_int
,
const
char
*
psz_string
,
void
*
p_data
)
{
int
i_middle
;
if
(
i_count
==
0
||
i_hash
<=
p_array
[
0
].
i_hash
)
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
{
return
0
;
}
if
(
i_hash
>=
p_array
[
i_count
-
1
].
i_hash
)
{
return
i_count
;
}
i_middle
=
i_count
/
2
;
/* We know that 0 < i_middle */
if
(
i_hash
<
p_array
[
i_middle
].
i_hash
)
{
return
FindSlot
(
p_array
,
i_middle
,
i_hash
);
}
/* We know that i_middle + 1 < i_count */
if
(
i_hash
>
p_array
[
i_middle
+
1
].
i_hash
)
{
return
i_middle
+
1
+
FindSlot
(
p_array
+
i_middle
+
1
,
i_count
-
i_middle
-
1
,
i_hash
);
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
;
}
return
i_middle
+
1
;
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
;
}
/*****************************************************************************
* Lookup: find an existing variable given its name and id
*****************************************************************************
* We use a recursive inner function indexed on the hash. Care is taken of
* possible hash collisions.
* XXX: does this really need to be written recursively?
*****************************************************************************/
int
vlc_HashLookup
(
hashtable_entry_t
*
p_array
,
int
i_count
,
int
i_id
,
const
char
*
psz_name
)
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
;
if
(
i_count
==
0
)
{
return
-
1
;
}
i_hash
=
HashString
(
psz_name
,
i_id
);
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
;
i_pos
=
LookupInner
(
p_array
,
i_count
,
i_hash
);
/* Hash not found */
if
(
i_hash
!=
p_array
[
i_pos
].
i_hash
)
{
return
-
1
;
}
/* Hash found, let's check it looks like the entry
* We don't check the whole entry, this could lead to bad surprises :( */
if
(
psz_name
[
0
]
==
p_array
[
i_pos
].
psz_name
[
0
]
)
{
/* 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
==
p_array
[
i
].
i_hash
;
i
--
)
for
(
i
=
i_pos
-
1
;
i
>
0
&&
i_hash
==
DARRAY
[
i
].
i_hash
;
i
--
)
{
if
(
!
strcmp
(
psz_
name
,
p_array
[
i
].
psz_name
)
&&
p_array
[
i
].
i_id
==
i_id
)
{
if
(
!
strcmp
(
psz_
string
,
DARRAY
[
i
].
psz_string
)
&&
DARRAY
[
i
].
i_int
==
i_int
)
return
i
;
}
}
for
(
i
=
i_pos
+
1
;
i
<
i_count
&&
i_hash
==
p_array
[
i
].
i_hash
;
i
++
)
for
(
i
=
i_pos
+
1
;
i
<
DSIZE
&&
i_hash
==
DARRAY
[
i
].
i_hash
;
i
++
)
{
if
(
!
strcmp
(
psz_name
,
p_array
[
i
].
psz_name
)
&&
p_array
[
i
].
i_id
==
i_id
)
{
if
(
!
strcmp
(
psz_string
,
DARRAY
[
i
].
psz_string
)
&&
DARRAY
[
i
].
i_int
==
i_int
)
return
i
;
}
}
/* Hash found, but entry not found */
/* Hash found, but entry not found (quite strange !) */
assert
(
0
);
return
-
1
;
}
static
int
LookupInner
(
hashtable_entry_t
*
p_array
,
int
i_count
,
uint64_t
i_hash
)
{
int
i_middle
;
if
(
i_hash
<=
p_array
[
0
].
i_hash
)
{
return
0
;
}
if
(
i_hash
>=
p_array
[
i_count
-
1
].
i_hash
)
{
return
i_count
-
1
;
}
i_middle
=
i_count
/
2
;
/* We know that 0 < i_middle */
if
(
i_hash
<
p_array
[
i_middle
].
i_hash
)
{
return
LookupInner
(
p_array
,
i_middle
,
i_hash
);
}
/* We know that i_middle + 1 < i_count */
if
(
i_hash
>
p_array
[
i_middle
].
i_hash
)
{
return
i_middle
+
LookupInner
(
p_array
+
i_middle
,
i_count
-
i_middle
,
i_hash
);
}
return
i_middle
;
}
/*****************************************************************************
*
HashString
: our cool hash function
*
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
HashString
(
const
char
*
psz_string
,
int
i_id
)
static
uint64_t
DoHash
(
const
char
*
psz_string
,
int
i_int
)
{
uint64_t
i_hash
=
0
;
while
(
*
psz_string
)
if
(
psz_string
)
{
i_hash
+=
*
psz_string
++
;
i_hash
+=
i_hash
<<
10
;
i_hash
^=
i_hash
>>
8
;
while
(
*
psz_string
)
{
i_hash
+=
*
psz_string
++
;
i_hash
+=
i_hash
<<
10
;
i_hash
^=
i_hash
>>
8
;
}
}
i_hash
+=
(
(
uint64_t
)
i_id
<<
32
);
return
i_hash
;
return
i_hash
+
(
(
uint64_t
)
i_int
<<
32
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment