home *** CD-ROM | disk | FTP | other *** search
/ mail.altrad.com / 2015.02.mail.altrad.com.tar / mail.altrad.com / TEST / vlc-2-0-5-win32.exe / sdk / include / vlc / plugins / vlc_arrays.h < prev    next >
C/C++ Source or Header  |  2012-12-12  |  23KB  |  628 lines

  1. /*****************************************************************************
  2.  * vlc_arrays.h : Arrays and data structures handling
  3.  *****************************************************************************
  4.  * Copyright (C) 1999-2004 VLC authors and VideoLAN
  5.  * $Id: 6643197707faf62a22b3ab4313676e8e40cf8355 $
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *          Cl├⌐ment Stenac <zorglub@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify it
  11.  * under the terms of the GNU Lesser General Public License as published by
  12.  * the Free Software Foundation; either version 2.1 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18.  * GNU Lesser General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU Lesser General Public License
  21.  * along with this program; if not, write to the Free Software Foundation,
  22.  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24.  
  25. #ifndef VLC_ARRAYS_H_
  26. #define VLC_ARRAYS_H_
  27.  
  28. /**
  29.  * \file
  30.  * This file defines functions, structures and macros for handling arrays in vlc
  31.  */
  32.  
  33. /* realloc() that never fails *if* downsizing */
  34. static inline void *realloc_down( void *ptr, size_t size )
  35. {
  36.     void *ret = realloc( ptr, size );
  37.     return ret ? ret : ptr;
  38. }
  39.  
  40. /**
  41.  * Simple dynamic array handling. Array is realloced at each insert/removal
  42.  */
  43. #if defined( _MSC_VER ) && _MSC_VER < 1300 && !defined( UNDER_CE )
  44. #   define VLCCVP (void**) /* Work-around for broken compiler */
  45. #else
  46. #   define VLCCVP
  47. #endif
  48. #define INSERT_ELEM( p_ar, i_oldsize, i_pos, elem )                           \
  49.     do                                                                        \
  50.     {                                                                         \
  51.         if( !(i_oldsize) ) (p_ar) = NULL;                                       \
  52.         (p_ar) = VLCCVP realloc( p_ar, ((i_oldsize) + 1) * sizeof(*(p_ar)) ); \
  53.         if( !(p_ar) ) abort();                                                \
  54.         if( (i_oldsize) - (i_pos) )                                           \
  55.         {                                                                     \
  56.             memmove( (p_ar) + (i_pos) + 1, (p_ar) + (i_pos),                  \
  57.                      ((i_oldsize) - (i_pos)) * sizeof( *(p_ar) ) );           \
  58.         }                                                                     \
  59.         (p_ar)[(i_pos)] = elem;                                                 \
  60.         (i_oldsize)++;                                                        \
  61.     }                                                                         \
  62.     while( 0 )
  63.  
  64. #define REMOVE_ELEM( p_ar, i_size, i_pos )                                    \
  65.     do                                                                        \
  66.     {                                                                         \
  67.         if( (i_size) - (i_pos) - 1 )                                          \
  68.         {                                                                     \
  69.             memmove( (p_ar) + (i_pos),                                        \
  70.                      (p_ar) + (i_pos) + 1,                                    \
  71.                      ((i_size) - (i_pos) - 1) * sizeof( *(p_ar) ) );          \
  72.         }                                                                     \
  73.         if( i_size > 1 )                                                      \
  74.             (p_ar) = realloc_down( p_ar, ((i_size) - 1) * sizeof( *(p_ar) ) );\
  75.         else                                                                  \
  76.         {                                                                     \
  77.             free( p_ar );                                                     \
  78.             (p_ar) = NULL;                                                    \
  79.         }                                                                     \
  80.         (i_size)--;                                                           \
  81.     }                                                                         \
  82.     while( 0 )
  83.  
  84. #define TAB_INIT( count, tab )                  \
  85.   do {                                          \
  86.     (count) = 0;                                \
  87.     (tab) = NULL;                               \
  88.   } while(0)
  89.  
  90. #define TAB_CLEAN( count, tab )                 \
  91.   do {                                          \
  92.     free( tab );                                \
  93.     (count)= 0;                                 \
  94.     (tab)= NULL;                                \
  95.   } while(0)
  96.  
  97. #define TAB_APPEND_CAST( cast, count, tab, p )             \
  98.   do {                                          \
  99.     if( (count) > 0 )                           \
  100.         (tab) = cast realloc( tab, sizeof( void ** ) * ( (count) + 1 ) ); \
  101.     else                                        \
  102.         (tab) = cast malloc( sizeof( void ** ) );    \
  103.     if( !(tab) ) abort();                       \
  104.     (tab)[count] = (p);                         \
  105.     (count)++;                                  \
  106.   } while(0)
  107.  
  108. #define TAB_APPEND( count, tab, p )             \
  109.     TAB_APPEND_CAST( , count, tab, p )
  110.  
  111. #define TAB_FIND( count, tab, p, index )        \
  112.   do {                                          \
  113.     (index) = -1;                               \
  114.     for( int i = 0; i < (count); i++ )          \
  115.         if( (tab)[i] == (p) )                   \
  116.         {                                       \
  117.             (index) = i;                        \
  118.             break;                              \
  119.         }                                       \
  120.   } while(0)
  121.  
  122.  
  123. #define TAB_REMOVE( count, tab, p )             \
  124.   do {                                          \
  125.         int i_index;                            \
  126.         TAB_FIND( count, tab, p, i_index );     \
  127.         if( i_index >= 0 )                      \
  128.         {                                       \
  129.             if( (count) > 1 )                   \
  130.             {                                   \
  131.                 memmove( ((void**)(tab) + i_index),    \
  132.                          ((void**)(tab) + i_index+1),  \
  133.                          ( (count) - i_index - 1 ) * sizeof( void* ) );\
  134.             }                                   \
  135.             (count)--;                          \
  136.             if( (count) == 0 )                  \
  137.             {                                   \
  138.                 free( tab );                    \
  139.                 (tab) = NULL;                   \
  140.             }                                   \
  141.         }                                       \
  142.   } while(0)
  143.  
  144. #define TAB_INSERT_CAST( cast, count, tab, p, index ) do { \
  145.     if( (count) > 0 )                           \
  146.         (tab) = cast realloc( tab, sizeof( void ** ) * ( (count) + 1 ) ); \
  147.     else                                        \
  148.         (tab) = cast malloc( sizeof( void ** ) );       \
  149.     if( !(tab) ) abort();                       \
  150.     if( (count) - (index) > 0 )                 \
  151.         memmove( (void**)(tab) + (index) + 1,   \
  152.                  (void**)(tab) + (index),       \
  153.                  ((count) - (index)) * sizeof(*(tab)) );\
  154.     (tab)[(index)] = (p);                       \
  155.     (count)++;                                  \
  156. } while(0)
  157.  
  158. #define TAB_INSERT( count, tab, p, index )      \
  159.     TAB_INSERT_CAST( , count, tab, p, index )
  160.  
  161. /**
  162.  * Binary search in a sorted array. The key must be comparable by < and >
  163.  * \param entries array of entries
  164.  * \param count number of entries
  165.  * \param elem key to check within an entry (like .id, or ->i_id)
  166.  * \param zetype type of the key
  167.  * \param key value of the key
  168.  * \param answer index of answer within the array. -1 if not found
  169.  */
  170. #define BSEARCH( entries, count, elem, zetype, key, answer ) \
  171.    do {  \
  172.     int low = 0, high = count - 1;   \
  173.     answer = -1; \
  174.     while( low <= high ) {\
  175.         int mid = (low + high ) / 2; /* Just don't care about 2^30 tables */ \
  176.         zetype mid_val = entries[mid] elem;\
  177.         if( mid_val < key ) \
  178.             low = mid + 1; \
  179.         else if ( mid_val > key ) \
  180.             high = mid -1;  \
  181.         else    \
  182.         {   \
  183.             answer = mid;  break;   \
  184.         }\
  185.     } \
  186.  } while(0)
  187.  
  188.  
  189. /************************************************************************
  190.  * Dynamic arrays with progressive allocation
  191.  ************************************************************************/
  192.  
  193. /* Internal functions */
  194. #define _ARRAY_ALLOC(array, newsize) {                                      \
  195.     (array).i_alloc = newsize;                                              \
  196.     (array).p_elems = VLCCVP realloc( (array).p_elems, (array).i_alloc *    \
  197.                                     sizeof(*(array).p_elems) );             \
  198.     if( !(array).p_elems ) abort();                                         \
  199. }
  200.  
  201. #define _ARRAY_GROW1(array) {                                               \
  202.     if( (array).i_alloc < 10 )                                              \
  203.         _ARRAY_ALLOC(array, 10 )                                            \
  204.     else if( (array).i_alloc == (array).i_size )                            \
  205.         _ARRAY_ALLOC(array, (int)(array.i_alloc * 1.5) )                    \
  206. }
  207.  
  208. #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  209.  
  210. /* API */
  211. #define DECL_ARRAY(type) struct {                                           \
  212.     int i_alloc;                                                            \
  213.     int i_size;                                                             \
  214.     type *p_elems;                                                          \
  215. }
  216.  
  217. #define TYPEDEF_ARRAY(type, name) typedef DECL_ARRAY(type) name;
  218.  
  219. #define ARRAY_INIT(array)                                                   \
  220.   do {                                                                      \
  221.     (array).i_alloc = 0;                                                    \
  222.     (array).i_size = 0;                                                     \
  223.     (array).p_elems = NULL;                                                 \
  224.   } while(0)
  225.  
  226. #define ARRAY_RESET(array)                                                  \
  227.   do {                                                                      \
  228.     (array).i_alloc = 0;                                                    \
  229.     (array).i_size = 0;                                                     \
  230.     free( (array).p_elems ); (array).p_elems = NULL;                        \
  231.   } while(0)
  232.  
  233. #define ARRAY_APPEND(array, elem)                                           \
  234.   do {                                                                      \
  235.     _ARRAY_GROW1(array);                                                    \
  236.     (array).p_elems[(array).i_size] = elem;                                 \
  237.     (array).i_size++;                                                       \
  238.   } while(0)
  239.  
  240. #define ARRAY_INSERT(array,elem,pos)                                        \
  241.   do {                                                                      \
  242.     _ARRAY_GROW1(array);                                                    \
  243.     if( (array).i_size - pos ) {                                            \
  244.         memmove( (array).p_elems + pos + 1, (array).p_elems + pos,          \
  245.                  ((array).i_size-pos) * sizeof(*(array).p_elems) );         \
  246.     }                                                                       \
  247.     (array).p_elems[pos] = elem;                                            \
  248.     (array).i_size++;                                                       \
  249.   } while(0)
  250.  
  251. #define _ARRAY_SHRINK(array) {                                              \
  252.     if( (array).i_size > 10 && (array).i_size < (int)((array).i_alloc / 1.5) ) {  \
  253.         _ARRAY_ALLOC(array, (array).i_size + 5);                            \
  254.     }                                                                       \
  255. }
  256.  
  257. #define ARRAY_REMOVE(array,pos)                                             \
  258.   do {                                                                      \
  259.     if( (array).i_size - (pos) - 1 )                                        \
  260.     {                                                                       \
  261.         memmove( (array).p_elems + pos, (array).p_elems + pos + 1,          \
  262.                  ( (array).i_size - pos - 1 ) *sizeof(*(array).p_elems) );  \
  263.     }                                                                       \
  264.     (array).i_size--;                                                       \
  265.     _ARRAY_SHRINK(array);                                                   \
  266.   } while(0)
  267.  
  268. #define ARRAY_VAL(array, pos) array.p_elems[pos]
  269.  
  270. #define ARRAY_BSEARCH(array, elem, zetype, key, answer) \
  271.     BSEARCH( (array).p_elems, (array).i_size, elem, zetype, key, answer)
  272.  
  273. #define FOREACH_ARRAY( item, array ) { \
  274.     int fe_idx; \
  275.     for( fe_idx = 0 ; fe_idx < (array).i_size ; fe_idx++ ) \
  276.     { \
  277.         item = (array).p_elems[fe_idx];
  278.  
  279. #define FOREACH_END() } }
  280.  
  281.  
  282. /************************************************************************
  283.  * Dynamic arrays with progressive allocation (Preferred API)
  284.  ************************************************************************/
  285. typedef struct vlc_array_t
  286. {
  287.     int i_count;
  288.     void ** pp_elems;
  289. } vlc_array_t;
  290.  
  291. static inline void vlc_array_init( vlc_array_t * p_array )
  292. {
  293.     memset( p_array, 0, sizeof(vlc_array_t) );
  294. }
  295.  
  296. static inline void vlc_array_clear( vlc_array_t * p_array )
  297. {
  298.     free( p_array->pp_elems );
  299.     memset( p_array, 0, sizeof(vlc_array_t) );
  300. }
  301.  
  302. static inline vlc_array_t * vlc_array_new( void )
  303. {
  304.     vlc_array_t * ret = (vlc_array_t *)malloc( sizeof(vlc_array_t) );
  305.     if( ret ) vlc_array_init( ret );
  306.     return ret;
  307. }
  308.  
  309. static inline void vlc_array_destroy( vlc_array_t * p_array )
  310. {
  311.     if( !p_array )
  312.         return;
  313.     vlc_array_clear( p_array );
  314.     free( p_array );
  315. }
  316.  
  317.  
  318. /* Read */
  319. static inline int
  320. vlc_array_count( vlc_array_t * p_array )
  321. {
  322.     return p_array->i_count;
  323. }
  324.  
  325. static inline void *
  326. vlc_array_item_at_index( vlc_array_t * p_array, int i_index )
  327. {
  328.     return p_array->pp_elems[i_index];
  329. }
  330.  
  331. static inline int
  332. vlc_array_index_of_item( vlc_array_t * p_array, void * item )
  333. {
  334.     int i;
  335.     for( i = 0; i < p_array->i_count; i++)
  336.     {
  337.         if( p_array->pp_elems[i] == item )
  338.             return i;
  339.     }
  340.     return -1;
  341. }
  342.  
  343. /* Write */
  344. static inline void
  345. vlc_array_insert( vlc_array_t * p_array, void * p_elem, int i_index )
  346. {
  347.     TAB_INSERT_CAST( (void **), p_array->i_count, p_array->pp_elems, p_elem, i_index );
  348. }
  349.  
  350. static inline void
  351. vlc_array_append( vlc_array_t * p_array, void * p_elem )
  352. {
  353.     vlc_array_insert( p_array, p_elem, p_array->i_count );
  354. }
  355.  
  356. static inline void
  357. vlc_array_remove( vlc_array_t * p_array, int i_index )
  358. {
  359.     if( i_index >= 0 )
  360.     {
  361.         if( p_array->i_count > 1 )
  362.         {
  363.             memmove( p_array->pp_elems + i_index,
  364.                      p_array->pp_elems + i_index+1,
  365.                      ( p_array->i_count - i_index - 1 ) * sizeof( void* ) );
  366.         }
  367.         p_array->i_count--;
  368.         if( p_array->i_count == 0 )
  369.         {
  370.             free( p_array->pp_elems );
  371.             p_array->pp_elems = NULL;
  372.         }
  373.     }
  374. }
  375.  
  376.  
  377. /************************************************************************
  378.  * Dictionaries
  379.  ************************************************************************/
  380.  
  381. /* This function is not intended to be crypto-secure, we only want it to be
  382.  * fast and not suck too much. This one is pretty fast and did 0 collisions
  383.  * in wenglish's dictionary.
  384.  */
  385. static inline uint64_t DictHash( const char *psz_string, int hashsize )
  386. {
  387.     uint64_t i_hash = 0;
  388.     if( psz_string )
  389.     {
  390.         while( *psz_string )
  391.         {
  392.             i_hash += *psz_string++;
  393.             i_hash += i_hash << 10;
  394.             i_hash ^= i_hash >> 8;
  395.         }
  396.     }
  397.     return i_hash % hashsize;
  398. }
  399.  
  400. typedef struct vlc_dictionary_entry_t
  401. {
  402.     char *   psz_key;
  403.     void *   p_value;
  404.     struct vlc_dictionary_entry_t * p_next;
  405. } vlc_dictionary_entry_t;
  406.  
  407. typedef struct vlc_dictionary_t
  408. {
  409.     int i_size;
  410.     vlc_dictionary_entry_t ** p_entries;
  411. } vlc_dictionary_t;
  412.  
  413. static void * const kVLCDictionaryNotFound = NULL;
  414.  
  415. static inline void vlc_dictionary_init( vlc_dictionary_t * p_dict, int i_size )
  416. {
  417.     p_dict->p_entries = NULL;
  418.  
  419.     if( i_size > 0 )
  420.     {
  421.         p_dict->p_entries = (vlc_dictionary_entry_t **)calloc( i_size, sizeof(*p_dict->p_entries) );
  422.         if( !p_dict->p_entries )
  423.             i_size = 0;
  424.     }
  425.     p_dict->i_size = i_size;
  426. }
  427.  
  428. static inline void vlc_dictionary_clear( vlc_dictionary_t * p_dict,
  429.                                          void ( * pf_free )( void * p_data, void * p_obj ),
  430.                                          void * p_obj )
  431. {
  432.     if( p_dict->p_entries )
  433.     {
  434.         for( int i = 0; i < p_dict->i_size; i++ )
  435.         {
  436.             vlc_dictionary_entry_t * p_current, * p_next;
  437.             p_current = p_dict->p_entries[i];
  438.             while( p_current )
  439.             {
  440.                 p_next = p_current->p_next;
  441.                 if( pf_free != NULL )
  442.                     ( * pf_free )( p_current->p_value, p_obj );
  443.                 free( p_current->psz_key );
  444.                 free( p_current );
  445.                 p_current = p_next;
  446.             }
  447.         }
  448.         free( p_dict->p_entries );
  449.         p_dict->p_entries = NULL;
  450.     }
  451.     p_dict->i_size = 0;
  452. }
  453.  
  454. static inline int
  455. vlc_dictionary_has_key( const vlc_dictionary_t * p_dict, const char * psz_key )
  456. {
  457.     if( !p_dict->p_entries )
  458.         return 0;
  459.  
  460.     int i_pos = DictHash( psz_key, p_dict->i_size );
  461.     return p_dict->p_entries[i_pos] != NULL;
  462. }
  463.  
  464. static inline void *
  465. vlc_dictionary_value_for_key( const vlc_dictionary_t * p_dict, const char * psz_key )
  466. {
  467.     if( !p_dict->p_entries )
  468.         return kVLCDictionaryNotFound;
  469.  
  470.     int i_pos = DictHash( psz_key, p_dict->i_size );
  471.     vlc_dictionary_entry_t * p_entry = p_dict->p_entries[i_pos];
  472.  
  473.     if( !p_entry )
  474.         return kVLCDictionaryNotFound;
  475.  
  476.     /* Make sure we return the right item. (Hash collision) */
  477.     do {
  478.         if( !strcmp( psz_key, p_entry->psz_key ) )
  479.             return p_entry->p_value;
  480.         p_entry = p_entry->p_next;
  481.     } while( p_entry );
  482.  
  483.     return kVLCDictionaryNotFound;
  484. }
  485.  
  486. static inline int
  487. vlc_dictionary_keys_count( const vlc_dictionary_t * p_dict )
  488. {
  489.     vlc_dictionary_entry_t * p_entry;
  490.     int i, count = 0;
  491.  
  492.     if( !p_dict->p_entries )
  493.         return 0;
  494.  
  495.     for( i = 0; i < p_dict->i_size; i++ )
  496.     {
  497.         for( p_entry = p_dict->p_entries[i]; p_entry; p_entry = p_entry->p_next ) count++;
  498.     }
  499.     return count;
  500. }
  501.  
  502. static inline char **
  503. vlc_dictionary_all_keys( const vlc_dictionary_t * p_dict )
  504. {
  505.     vlc_dictionary_entry_t * p_entry;
  506.     char ** ppsz_ret;
  507.     int i, count = vlc_dictionary_keys_count( p_dict );
  508.  
  509.     ppsz_ret = (char**)malloc(sizeof(char *) * (count + 1));
  510.  
  511.     count = 0;
  512.     for( i = 0; i < p_dict->i_size; i++ )
  513.     {
  514.         for( p_entry = p_dict->p_entries[i]; p_entry; p_entry = p_entry->p_next )
  515.             ppsz_ret[count++] = strdup( p_entry->psz_key );
  516.     }
  517.     ppsz_ret[count] = NULL;
  518.     return ppsz_ret;
  519. }
  520.  
  521. static inline void
  522. __vlc_dictionary_insert( vlc_dictionary_t * p_dict, const char * psz_key,
  523.                          void * p_value, bool rebuild )
  524. {
  525.     if( !p_dict->p_entries )
  526.         vlc_dictionary_init( p_dict, 1 );
  527.  
  528.     int i_pos = DictHash( psz_key, p_dict->i_size );
  529.     vlc_dictionary_entry_t * p_entry;
  530.  
  531.     p_entry = (vlc_dictionary_entry_t *)malloc(sizeof(*p_entry));
  532.     p_entry->psz_key = strdup( psz_key );
  533.     p_entry->p_value = p_value;
  534.     p_entry->p_next = p_dict->p_entries[i_pos];
  535.     p_dict->p_entries[i_pos] = p_entry;
  536.     if( rebuild )
  537.     {
  538.         /* Count how many items there was */
  539.         int count;
  540.         for( count = 1; p_entry->p_next; count++ )
  541.             p_entry = p_entry->p_next;
  542.         if( count > 3 ) /* XXX: this need tuning */
  543.         {
  544.             /* Here it starts to be not good, rebuild a bigger dictionary */
  545.             struct vlc_dictionary_t new_dict;
  546.             int i_new_size = ( (p_dict->i_size+2) * 3) / 2; /* XXX: this need tuning */
  547.             int i;
  548.             vlc_dictionary_init( &new_dict, i_new_size );
  549.             for( i = 0; i < p_dict->i_size; i++ )
  550.             {
  551.                 p_entry = p_dict->p_entries[i];
  552.                 while( p_entry )
  553.                 {
  554.                     __vlc_dictionary_insert( &new_dict, p_entry->psz_key,
  555.                                              p_entry->p_value,
  556.                                              false /* To avoid multiple rebuild loop */);
  557.                     p_entry = p_entry->p_next;
  558.                 }
  559.             }
  560.  
  561.             vlc_dictionary_clear( p_dict, NULL, NULL );
  562.             p_dict->i_size = new_dict.i_size;
  563.             p_dict->p_entries = new_dict.p_entries;
  564.         }
  565.     }
  566. }
  567.  
  568. static inline void
  569. vlc_dictionary_insert( vlc_dictionary_t * p_dict, const char * psz_key, void * p_value )
  570. {
  571.     __vlc_dictionary_insert( p_dict, psz_key, p_value, true );
  572. }
  573.  
  574. static inline void
  575. vlc_dictionary_remove_value_for_key( const vlc_dictionary_t * p_dict, const char * psz_key,
  576.                                      void ( * pf_free )( void * p_data, void * p_obj ),
  577.                                      void * p_obj )
  578. {
  579.     if( !p_dict->p_entries )
  580.         return;
  581.  
  582.     int i_pos = DictHash( psz_key, p_dict->i_size );
  583.     vlc_dictionary_entry_t * p_entry = p_dict->p_entries[i_pos];
  584.     vlc_dictionary_entry_t * p_prev;
  585.  
  586.     if( !p_entry )
  587.         return; /* Not found, nothing to do */
  588.  
  589.     /* Hash collision */
  590.     p_prev = NULL;
  591.     do {
  592.         if( !strcmp( psz_key, p_entry->psz_key ) )
  593.         {
  594.             if( pf_free != NULL )
  595.                 ( * pf_free )( p_entry->p_value, p_obj );
  596.             if( !p_prev )
  597.                 p_dict->p_entries[i_pos] = p_entry->p_next;
  598.             else
  599.                 p_prev->p_next = p_entry->p_next;
  600.             free( p_entry->psz_key );
  601.             free( p_entry );
  602.             return;
  603.         }
  604.         p_prev = p_entry;
  605.         p_entry = p_entry->p_next;
  606.     } while( p_entry );
  607.  
  608.     /* No key was found */
  609. }
  610.  
  611. #ifdef __cplusplus
  612. // C++ helpers
  613. template <typename T>
  614. void vlc_delete_all( T &container )
  615. {
  616.     typename T::iterator it = container.begin();
  617.     while ( it != container.end() )
  618.     {
  619.         delete *it;
  620.         ++it;
  621.     }
  622.     container.clear();
  623. }
  624.  
  625. #endif
  626.  
  627. #endif
  628.