]> git.sesse.net Git - vlc/commitdiff
Dynamic array with log allocation
authorClément Stenac <zorglub@videolan.org>
Thu, 19 Oct 2006 21:00:14 +0000 (21:00 +0000)
committerClément Stenac <zorglub@videolan.org>
Thu, 19 Oct 2006 21:00:14 +0000 (21:00 +0000)
include/vlc_arrays.h [new file with mode: 0644]
include/vlc_common.h
test/NativeAlgoTest.py
test/native/algo.c
test/native/init.c
test/native/tests.h
test/test.sh

diff --git a/include/vlc_arrays.h b/include/vlc_arrays.h
new file mode 100644 (file)
index 0000000..e8802c5
--- /dev/null
@@ -0,0 +1,247 @@
+/*****************************************************************************
+ * vlc_arrays.h : Arrays and data structures handling
+ *****************************************************************************
+ * Copyright (C) 1999-2004 the VideoLAN team
+ * $Id: vlc_playlist.h 17108 2006-10-15 15:28:34Z 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. *****************************************************************************/
+
+#ifndef _VLC_ARRAYS_H_
+#define _VLC_ARRAYS_H_
+
+/**
+ * Simple dynamic array handling. Array is realloced at each insert/removal
+ */
+#if defined( _MSC_VER ) && _MSC_VER < 1300 && !defined( UNDER_CE )
+#   define VLCCVP (void**) /* Work-around for broken compiler */
+#else
+#   define VLCCVP
+#endif
+#define INSERT_ELEM( p_ar, i_oldsize, i_pos, elem )                           \
+    do                                                                        \
+    {                                                                         \
+        if( !i_oldsize ) (p_ar) = NULL;                                       \
+        (p_ar) = VLCCVP realloc( p_ar, ((i_oldsize) + 1) * sizeof(*(p_ar)) ); \
+        if( (i_oldsize) - (i_pos) )                                           \
+        {                                                                     \
+            memmove( (p_ar) + (i_pos) + 1, (p_ar) + (i_pos),                  \
+                     ((i_oldsize) - (i_pos)) * sizeof( *(p_ar) ) );           \
+        }                                                                     \
+        (p_ar)[i_pos] = elem;                                                 \
+        (i_oldsize)++;                                                        \
+    }                                                                         \
+    while( 0 )
+
+#define REMOVE_ELEM( p_ar, i_oldsize, i_pos )                                 \
+    do                                                                        \
+    {                                                                         \
+        if( (i_oldsize) - (i_pos) - 1 )                                       \
+        {                                                                     \
+            memmove( (p_ar) + (i_pos),                                        \
+                     (p_ar) + (i_pos) + 1,                                    \
+                     ((i_oldsize) - (i_pos) - 1) * sizeof( *(p_ar) ) );       \
+        }                                                                     \
+        if( i_oldsize > 1 )                                                   \
+        {                                                                     \
+            (p_ar) = realloc( p_ar, ((i_oldsize) - 1) * sizeof( *(p_ar) ) );  \
+        }                                                                     \
+        else                                                                  \
+        {                                                                     \
+            free( p_ar );                                                     \
+            (p_ar) = NULL;                                                    \
+        }                                                                     \
+        (i_oldsize)--;                                                        \
+    }                                                                         \
+    while( 0 )
+
+
+#define TAB_APPEND( count, tab, p )             \
+    if( (count) > 0 )                           \
+    {                                           \
+        (tab) = realloc( tab, sizeof( void ** ) * ( (count) + 1 ) ); \
+    }                                           \
+    else                                        \
+    {                                           \
+        (tab) = malloc( sizeof( void ** ) );    \
+    }                                           \
+    (tab)[count] = (p);        \
+    (count)++
+
+#define TAB_FIND( count, tab, p, index )        \
+    {                                           \
+        int _i_;                                \
+        (index) = -1;                           \
+        for( _i_ = 0; _i_ < (count); _i_++ )    \
+        {                                       \
+            if( (tab)[_i_] == (p) )  \
+            {                                   \
+                (index) = _i_;                  \
+                break;                          \
+            }                                   \
+        }                                       \
+    }
+
+#define TAB_REMOVE( count, tab, p )             \
+    {                                           \
+        int _i_index_;                          \
+        TAB_FIND( count, tab, p, _i_index_ );   \
+        if( _i_index_ >= 0 )                    \
+        {                                       \
+            if( (count) > 1 )                     \
+            {                                   \
+                memmove( ((void**)(tab) + _i_index_),    \
+                         ((void**)(tab) + _i_index_+1),  \
+                         ( (count) - _i_index_ - 1 ) * sizeof( void* ) );\
+            }                                   \
+            (count)--;                          \
+            if( (count) == 0 )                  \
+            {                                   \
+                free( tab );                    \
+                (tab) = NULL;                   \
+            }                                   \
+        }                                       \
+    }
+
+/**
+ * Binary search in an array
+ * \param entries array of entries
+ * \param count number of entries
+ * \param elem key to check within an entry (like .id, or ->i_id)
+ * \param zetype type of the key
+ * \param key value of the key
+ * \param answer index of answer within the array. -1 if not found
+ */
+#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_int;
+    char     *psz_string;
+    uint64_t  i_hash;
+    void     *p_data;
+};
+
+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 * ) );
+
+
+/************************************************************************
+ * Dynamic arrays with progressive allocation
+ ************************************************************************/
+
+/* Internal functions */
+//printf("Realloc from %i to %i\n", array.i_alloc, newsize);
+#define _ARRAY_ALLOC(array, newsize) {                                      \
+    array.i_alloc = newsize;                                                \
+    array.p_elems = VLCCVP realloc( array.p_elems, array.i_alloc *          \
+                                    sizeof(*array.p_elems) );               \
+    assert(array.p_elems);                                                  \
+}
+
+#define _ARRAY_GROW1(array) {                                               \
+    if( array.i_alloc < 10 )                                                \
+        _ARRAY_ALLOC(array, 10 )                                            \
+    else if( array.i_alloc == array.i_size )                                \
+        _ARRAY_ALLOC(array, (int)(array.i_alloc * 1.5) )                    \
+}
+
+#define _ARRAY_GROW(array,additional) {                                     \
+     int i_first = array.i_alloc;                                           \
+     while( array.i_alloc - i_first < additional )                          \
+     {                                                                      \
+         if( array.i_alloc < 10 )                                           \
+            _ARRAY_ALLOC(array, 10 )                                        \
+        else if( array.i_alloc == array.i_size )                            \
+            _ARRAY_ALLOC(array, (int)(array.i_alloc * 1.5) )                \
+        else break;                                                         \
+     }                                                                      \
+}
+
+#define _ARRAY_SHRINK(array) {                                              \
+    if( array.i_size > 10 && array.i_size < (int)(array.i_alloc / 1.5) ) {  \
+        _ARRAY_ALLOC(array, array.i_size + 5);                              \
+    }                                                                       \
+}
+
+
+/* API */
+#define DECL_ARRAY(type) struct {                                           \
+    int i_alloc;                                                            \
+    int i_size;                                                             \
+    type *p_elems;                                                          \
+}
+
+#define TYPEDEF_ARRAY(type, name) typedef DECL_ARRAY(type) name;
+
+#define ARRAY_INIT(array)                                                   \
+    array.i_alloc = 0;                                                      \
+    array.i_size = 0;                                                       \
+    array.p_elems = NULL;
+
+#define ARRAY_APPEND(array, elem) {                                         \
+    _ARRAY_GROW1(array);                                                    \
+    array.p_elems[array.i_size] = elem;                                     \
+    array.i_size++;                                                         \
+}
+
+#define ARRAY_INSERT(array,elem,pos) {                                      \
+    _ARRAY_GROW1(array);                                                    \
+    if( array.i_size - pos ) {                                              \
+        memmove( array.p_elems + pos + 1, array.p_elems + pos,              \
+                 (array.i_size-pos) * sizeof(*array.p_elems) );             \
+    }                                                                       \
+    array.p_elems[pos] = elem;                                              \
+    array.i_size++;                                                         \
+}
+
+#define ARRAY_REMOVE(array,pos) {                                           \
+    if( array.i_size - (pos) - 1 )                                          \
+    {                                                                       \
+        memmove( array.p_elems + pos, array.p_elems + pos + 1,              \
+                 ( array.i_size - pos - 1 ) *sizeof(*array.p_elems) );      \
+    }                                                                       \
+    array.i_size--;                                                         \
+    _ARRAY_SHRINK(array);                                                   \
+}
+
+#endif
index 647b8c2f28910717ca102c79eb2b9caaf6c75027..7cbf35e13a213233158c98c338997effb1a98a2c 100644 (file)
@@ -633,135 +633,7 @@ static int64_t GCD( int64_t a, int64_t b )
 #define FREENULL(a) if( a ) { free( a ); a = NULL; }
 #define FREE(a) if( a ) { free( a ); }
 
-/* Dynamic array handling: realloc array, move data, increment position */
-#if defined( _MSC_VER ) && _MSC_VER < 1300 && !defined( UNDER_CE )
-#   define VLCCVP (void**) /* Work-around for broken compiler */
-#else
-#   define VLCCVP
-#endif
-#define INSERT_ELEM( p_ar, i_oldsize, i_pos, elem )                           \
-    do                                                                        \
-    {                                                                         \
-        if( !i_oldsize ) (p_ar) = NULL;                                       \
-        (p_ar) = VLCCVP realloc( p_ar, ((i_oldsize) + 1) * sizeof(*(p_ar)) ); \
-        if( (i_oldsize) - (i_pos) )                                           \
-        {                                                                     \
-            memmove( (p_ar) + (i_pos) + 1, (p_ar) + (i_pos),                  \
-                     ((i_oldsize) - (i_pos)) * sizeof( *(p_ar) ) );           \
-        }                                                                     \
-        (p_ar)[i_pos] = elem;                                                 \
-        (i_oldsize)++;                                                        \
-    }                                                                         \
-    while( 0 )
-
-#define REMOVE_ELEM( p_ar, i_oldsize, i_pos )                                 \
-    do                                                                        \
-    {                                                                         \
-        if( (i_oldsize) - (i_pos) - 1 )                                       \
-        {                                                                     \
-            memmove( (p_ar) + (i_pos),                                        \
-                     (p_ar) + (i_pos) + 1,                                    \
-                     ((i_oldsize) - (i_pos) - 1) * sizeof( *(p_ar) ) );       \
-        }                                                                     \
-        if( i_oldsize > 1 )                                                   \
-        {                                                                     \
-            (p_ar) = realloc( p_ar, ((i_oldsize) - 1) * sizeof( *(p_ar) ) );  \
-        }                                                                     \
-        else                                                                  \
-        {                                                                     \
-            free( p_ar );                                                     \
-            (p_ar) = NULL;                                                    \
-        }                                                                     \
-        (i_oldsize)--;                                                        \
-    }                                                                         \
-    while( 0 )
-
-
-#define TAB_APPEND( count, tab, p )             \
-    if( (count) > 0 )                           \
-    {                                           \
-        (tab) = realloc( tab, sizeof( void ** ) * ( (count) + 1 ) ); \
-    }                                           \
-    else                                        \
-    {                                           \
-        (tab) = malloc( sizeof( void ** ) );    \
-    }                                           \
-    (tab)[count] = (p);        \
-    (count)++
-
-#define TAB_FIND( count, tab, p, index )        \
-    {                                           \
-        int _i_;                                \
-        (index) = -1;                           \
-        for( _i_ = 0; _i_ < (count); _i_++ )    \
-        {                                       \
-            if( (tab)[_i_] == (p) )  \
-            {                                   \
-                (index) = _i_;                  \
-                break;                          \
-            }                                   \
-        }                                       \
-    }
-
-#define TAB_REMOVE( count, tab, p )             \
-    {                                           \
-        int _i_index_;                          \
-        TAB_FIND( count, tab, p, _i_index_ );   \
-        if( _i_index_ >= 0 )                    \
-        {                                       \
-            if( (count) > 1 )                     \
-            {                                   \
-                memmove( ((void**)(tab) + _i_index_),    \
-                         ((void**)(tab) + _i_index_+1),  \
-                         ( (count) - _i_index_ - 1 ) * sizeof( void* ) );\
-            }                                   \
-            (count)--;                          \
-            if( (count) == 0 )                  \
-            {                                   \
-                free( tab );                    \
-                (tab) = NULL;                   \
-            }                                   \
-        }                                       \
-    }
-
-/* 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_int;
-    char     *psz_string;
-    uint64_t  i_hash;
-    void     *p_data;
-};
-
-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 * ) );
+#include <vlc_arrays.h>
 
 /* MSB (big endian)/LSB (little endian) conversions - network order is always
  * MSB, and should be used for both network communications and files. Note that
index b707e27b84c0e243af4effec1b22e68b1d4909ea..51c95415d14419272b207e35788baf857972c650 100644 (file)
@@ -3,6 +3,9 @@ import unittest
 import native_libvlc_test
 
 class NativeAlgoTestCase( unittest.TestCase ):
+    def test_arrays( self ):
+        """[Algo] Check dynamic arrays"""
+        native_libvlc_test.arrays_test()
     def test_bsearch_direct( self ):
         """[Algo] Check Bsearch with simple types"""
        native_libvlc_test.bsearch_direct_test()
index 28c9f12581cfc5ce96a2d13d33079bbf315b395f..f1dcd3a3da5e2f8a4c8c7ff4fde1bacaaf8b03b7 100644 (file)
 #include "../pyunit.h"
 #include <vlc/vlc.h>
 
+/**********************************************************************
+ * Arrays
+ *********************************************************************/
+
+TYPEDEF_ARRAY(long,long_array_t);
+
+PyObject *arrays_test( PyObject *self, PyObject *args )
+{
+    mtime_t one, two;
+    int number = 1000000;
+    int number2 = 50000; /* For slow with memmove */
+    printf("\n");
+    {
+        int i_items = 0;
+        int *p_items = NULL;
+        int i;
+        one = mdate();
+        for( i = 0 ; i<number;i++) {
+            INSERT_ELEM(p_items,i_items, i_items, i+50);
+        }
+        two = mdate();
+        printf( " Std array %i items appended in "I64Fi" µs\n", number,
+                (two-one) );
+        for( i = number-1 ; i>=0; i--) {
+            REMOVE_ELEM( p_items, i_items, i );
+        }
+        one = mdate();
+        printf( " Std array %i items removed in  "I64Fi" µs\n", number,
+                (one-two) );
+
+        for( i = 0 ; i<number2;i++) {
+            int pos = i_items == 0  ? 0 : rand() % i_items;
+            INSERT_ELEM(p_items, i_items, pos, pos + 50);
+        }
+        two = mdate();
+        printf( " Std array %i items inserted in  "I64Fi" µs\n", number2,
+                (two-one) );
+    }
+    {
+        DECL_ARRAY(int) int_array;
+        int i = 0;
+        ARRAY_INIT(int_array);
+        ASSERT(int_array.i_size == 0, "" );
+        ASSERT(int_array.i_alloc == 0, "" );
+        ASSERT(int_array.p_elems == 0, "" );
+
+        ARRAY_APPEND(int_array, 42 );
+        ASSERT(int_array.i_size == 1, "" );
+        ASSERT(int_array.i_alloc > 1, "" );
+        ASSERT(int_array.p_elems[0] == 42, "" );
+        ARRAY_REMOVE(int_array,0);
+        ASSERT(int_array.i_size == 0, "" );
+
+        one = mdate();
+        for( i = 0 ; i<number;i++) {
+            ARRAY_APPEND(int_array, i+50);
+        }
+        two = mdate();
+        printf( " New array %i items appended in "I64Fi" µs\n", number,
+                (two-one) );
+        ASSERT(int_array.p_elems[1242] == 1292 , "");
+        for( i = number-1 ; i>=0; i--) {
+            ARRAY_REMOVE(int_array,i);
+        }
+        one = mdate();
+        printf( " New array %i items removed in  "I64Fi" µs\n", number,
+                (one-two) );
+
+        /* Now random inserts */
+        for( i = 0 ; i<number2;i++) {
+            int pos = int_array.i_size == 0  ? 0 : rand() % int_array.i_size;
+            ARRAY_INSERT(int_array, pos+50, pos);
+        }
+        two = mdate();
+        printf( " New array %i items inserted in  "I64Fi" µs\n", number2,
+                (two-one) );
+    }
+    {
+        long_array_t larray;
+        ARRAY_INIT(larray);
+    }
+    Py_INCREF( Py_None);
+    return Py_None;
+}
+
 /**********************************************************************
  * Binary search
  *********************************************************************/
@@ -66,7 +151,7 @@ PyObject *bsearch_member_test( PyObject *self, PyObject *args )
 {
     struct bsearch_tester array[] =
     {
-        { 0, 12 }, { 1, 22 } , { 2, 33 } , { 3, 68 } , { 4, 56 } 
+        { 0, 12 }, { 1, 22 } , { 2, 33 } , { 3, 68 } , { 4, 56 }
     };
 #define MEMBCHECK( checked, expected ) { \
     int answer = -1;  \
index 21c2805d98dccc7d8970484e6332666ef255c245..f74379f9bbbf38d622070a9ee122c119f6b6a1a4 100644 (file)
@@ -20,6 +20,7 @@ static PyMethodDef native_libvlc_test_methods[] = {
    DEF_METHOD( chains_test, "Test building of chains" )
    DEF_METHOD( gui_chains_test, "Test interactions between chains and GUI" )
    DEF_METHOD( psz_chains_test, "Test building of chain strings" )
+   DEF_METHOD( arrays_test, "Test arrays")
    DEF_METHOD( bsearch_direct_test, "Test Bsearch without structure" )
    DEF_METHOD( bsearch_member_test, "Test Bsearch with structure" )
    DEF_METHOD( dict_test, "Test dictionnaries" )
index 73f6d606a09bfd9515cf0ee980b27d35c9367284..7f47cbb7e6c387a3c1fb76baf79ad74699ea0ebc 100644 (file)
@@ -19,6 +19,7 @@ PyObject *gui_chains_test( PyObject *self, PyObject *args );
 PyObject *psz_chains_test( PyObject *self, PyObject *args );
 
 /* Algo */
+PyObject *arrays_test( PyObject *self, PyObject *args );
 PyObject *bsearch_direct_test( PyObject *self, PyObject *args );
 PyObject *bsearch_member_test( PyObject *self, PyObject *args );
 PyObject *dict_test( PyObject *self, PyObject *args );
index 88c849924001f8b96ed802189351c3a05ed64148..a74708184769a205ea0f07362920f1e2839fd0d1 100755 (executable)
@@ -12,7 +12,11 @@ export LD_LIBRARY_PATH=src/.libs/
 # Always dump core
 ulimit -c unlimited
 
-python test/test.py -v 2>&1|perl  -e \
+if [ "x$1" = "xdebug" ]
+then
+  gdb python "test/test.sh"
+else
+  python test/test.py -v 2>&1|perl  -e \
 '$bold = "\033[1m";
 $grey  = "\033[37m";
 $green  = "\033[32m";
@@ -42,4 +46,4 @@ while(<STDIN>)
         print $grey.$line."\n";
      }
 }'
-
+fi