vlc_arrays.h
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:22k
源码类别:

midi

开发平台:

Unix_Linux

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