/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/utils/eh_key_file.c

Go to the documentation of this file.
00001 #include <eh_utils.h>
00002 
00003 CLASS( Eh_key_file )
00004 {
00005    GHashTable* t; //< A hash table that holds all of the group lists
00006    GList*      l; //< A list of the groups in the order they appear in the file
00007 };
00008 
00009 GQuark
00010 eh_key_file_error_quark( void )
00011 {
00012    return g_quark_from_static_string( "eh-key-file-error-quark" );
00013 }
00014 
00026 void destroy_hash_table_list( gpointer key , gpointer value , gpointer user_data )
00027 {
00028    GList* l;
00029    for ( l=value ; l ; l = l->next )
00030       eh_symbol_table_destroy( (Eh_symbol_table)(l->data) );
00031    g_list_free( value );
00032 }
00033 
00044 void dup_key( gpointer key , gpointer value , gpointer user_data )
00045 {
00046    gchar** s = (gchar**)(user_data);
00047    gchar* new_str;
00048 
00049    if ( (*s)[0] == '\0' )
00050       new_str = g_strdup( key );
00051    else
00052       new_str = g_strjoin( "\n" , (*s) , key , NULL );
00053 
00054    eh_free( *s );
00055    (*s) = new_str;
00056 
00057 }
00058 
00069 gchar** eh_key_file_list_to_array( GList* l , gpointer key )
00070 {
00071    gchar** ans;
00072    guint len = g_list_length( l );
00073    guint i;
00074 
00075    ans = g_new( gchar* , len+1 );
00076    for ( i=0 ; l ; i++, l=l->next )
00077       ans[i] = g_strdup( eh_symbol_table_lookup(l->data,key) );
00078    ans[len] = NULL;
00079 
00080    return ans;
00081 }
00082 
00096 Eh_symbol_table eh_key_file_add_group( Eh_key_file f ,
00097                                        const gchar* group_name ,
00098                                        gboolean replace )
00099 {
00100    /* Find the group in the GHashTable */
00101    GList* group_list = g_hash_table_lookup( f->t , group_name );
00102    Eh_symbol_table group;
00103 
00104    /* If the group doesn't exist or it does but replace is off */
00105    if ( !group_list || (group_list&&!replace) )
00106    {
00107       Eh_symbol_table new_tab = eh_symbol_table_new();
00108 
00109       /* prepend a new symbol table to the list. */
00110       group_list = g_list_prepend(group_list,new_tab);
00111 
00112       /* add the group to the GHashTable of the key-file */
00113       g_hash_table_insert( f->t                   ,
00114                            g_strdup( group_name ) ,
00115                            group_list );
00116 
00117       /* Add the group name to the end of the list */
00118       f->l = g_list_append( f->l , g_strdup( group_name ));
00119 
00120       group = new_tab;
00121    }
00122    else
00123       group = g_list_first(group_list)->data;
00124 
00125    eh_require( group );
00126 
00127    /* The symbol table of the specified group. */
00128    return group;
00129 }
00130 
00140 void add_record_value( gpointer key , gpointer value , gpointer user_data )
00141 {
00142    Eh_key_file f          = ((gpointer*)user_data)[0];
00143    gchar*      group_name = ((gpointer*)user_data)[1];
00144    eh_key_file_set_value( f , group_name , key , value );
00145 }
00146 
00152 Eh_key_file eh_key_file_new( )
00153 {
00154    Eh_key_file f;
00155 
00156    NEW_OBJECT( Eh_key_file , f );
00157 
00158    f->t = g_hash_table_new_full( &g_str_hash                  ,
00159                                  &g_str_equal                 ,
00160                                  (GDestroyNotify)&eh_free_mem ,
00161                                  NULL );
00162    f->l = NULL;
00163 
00164    return f;
00165 }
00166 
00173 Eh_key_file eh_key_file_destroy( Eh_key_file f )
00174 {
00175    if ( f )
00176    {
00177       GList* link;
00178 
00179       g_hash_table_foreach( f->t , (GHFunc)&destroy_hash_table_list , NULL );
00180       g_hash_table_destroy( f->t );
00181 
00182       for ( link=f->l ; link ; link=link->next )
00183          eh_free( link->data );
00184       g_list_free( f->l );
00185 
00186       eh_free( f );
00187    }
00188    return NULL;
00189 }
00190 
00198 gboolean eh_key_file_has_group( Eh_key_file f , const gchar* group_name )
00199 {
00200    if ( f && g_hash_table_lookup( f->t , group_name ) )
00201       return TRUE;
00202    else
00203       return FALSE;
00204 }
00205 
00214 gboolean eh_key_file_has_key( Eh_key_file f , const gchar* group_name , const gchar* key )
00215 {
00216    if ( f )
00217    {
00218       GList* group = g_hash_table_lookup( f->t , group_name );
00219       if ( group && eh_symbol_table_lookup( group->data , key ) )
00220          return TRUE;
00221       else
00222          return FALSE;
00223    }
00224    else
00225       return FALSE;
00226 }
00227 
00234 gchar** eh_key_file_get_groups( Eh_key_file f )
00235 {
00236    gchar** groups = NULL;
00237 
00238    if ( f )
00239    {
00240       gchar* group_name_list = g_strdup( "\0");
00241 
00242       g_hash_table_foreach( f->t , &dup_key , &group_name_list );
00243 
00244       groups = g_strsplit( group_name_list , "\n" , 0 );
00245 
00246       eh_free( group_name_list );
00247    }
00248 
00249    return groups;
00250 }
00251 
00259 gint eh_key_file_group_size( Eh_key_file f ,
00260                              const gchar* group_name )
00261 {
00262    GList* group = g_hash_table_lookup( f->t , group_name );
00263    return g_list_length( group );
00264 }
00265 
00275 gint eh_key_file_size( Eh_key_file f )
00276 {
00277    gint len = 0;
00278    if ( f )
00279    {
00280       len = g_list_length( f->l );
00281    }
00282    return len;
00283 }
00284 
00295 gchar** eh_key_file_get_keys( Eh_key_file f , const gchar* group_name )
00296 {
00297    gchar** keys = NULL;
00298 
00299    if ( f )
00300    {
00301       GList* group = g_hash_table_lookup( f->t , group_name );
00302 
00303       if ( group )
00304       {
00305          Eh_symbol_table first_group = group->data;
00306          gchar* key_list = "";
00307 
00308          eh_symbol_table_foreach( first_group , &dup_key , &key_list );
00309 
00310          keys = g_strsplit( key_list , "\n" , -1 );
00311 
00312          eh_free( key_list );
00313       }
00314    }
00315 
00316    return keys;
00317 }
00318 
00330 gchar** eh_key_file_get_all_values( Eh_key_file f , const gchar* group_name , const gchar* key )
00331 {
00332    gchar** value = NULL;
00333 
00334    if ( f )
00335    {
00336       GList* group = g_hash_table_lookup( f->t , group_name );
00337       if ( group )
00338          value = eh_key_file_list_to_array( group , (gchar*)key );
00339    }
00340 
00341    return value;
00342 }
00343 
00356 gchar*
00357 eh_key_file_get_value( Eh_key_file f , const gchar* group_name , const gchar* key )
00358 {
00359    gchar* value = NULL;
00360 
00361    if ( f )
00362    {
00363       GList* group = g_hash_table_lookup( f->t , group_name );
00364       if ( group )
00365          value = g_strdup( eh_symbol_table_lookup( group->data , (gchar*)key ) );
00366    }
00367 
00368    return value;
00369 }
00370 
00384 gchar*
00385 eh_key_file_get_str_value( Eh_key_file f , const gchar* group_name , const gchar* key )
00386 {
00387    return eh_key_file_get_value( f , group_name , key );
00388 }
00389 
00401 gchar**
00402 eh_key_file_get_str_values( Eh_key_file f , const gchar* group_name , const gchar* key )
00403 {
00404    return eh_key_file_get_all_values(f,group_name,key);
00405 }
00406 
00415 gboolean eh_key_file_get_bool_value( Eh_key_file f           ,
00416                                      const gchar* group_name ,
00417                                      const gchar* key )
00418 {
00419    gchar*   str = eh_key_file_get_value(f,group_name,key);
00420    gboolean ans = eh_str_to_boolean( str , NULL );
00421 
00422    eh_free( str );
00423 
00424    return ans;
00425 }
00426 
00437 gboolean* eh_key_file_get_bool_values( Eh_key_file f           ,
00438                                        const gchar* group_name ,
00439                                        const gchar* key )
00440 {
00441    guint     len = eh_key_file_group_size(f,group_name);
00442    gchar**   str = eh_key_file_get_all_values(f,group_name,key);
00443    gboolean* ans = eh_new( gboolean , len );
00444    guint i;
00445 
00446    for ( i=0 ; i<len ; i++ )
00447       ans[i] = eh_str_to_boolean( str[i] , NULL );
00448 
00449    g_strfreev( str );
00450 
00451    return ans;
00452 }
00453 
00462 double eh_key_file_get_dbl_value( Eh_key_file f ,
00463                                   const gchar* group_name ,
00464                                   const gchar* key )
00465 {
00466    double ans;
00467    gchar* str = eh_key_file_get_value(f,group_name,key);
00468 
00469    if ( str ) ans = g_strtod( str , NULL );
00470    else       ans = eh_nan();
00471 
00472    eh_free( str );
00473 
00474    return ans;
00475 }
00476 
00486 double*
00487 eh_key_file_get_dbl_array( Eh_key_file  f          ,
00488                            const gchar* group_name ,
00489                            const gchar* key        ,
00490                            gint*        len )
00491 {
00492    double* d_array = NULL;
00493 
00494    eh_require( key        );
00495    eh_require( group_name );
00496    eh_require( len        );
00497 
00498    if ( f )
00499    {
00500       gchar*  str       = eh_key_file_get_value( f , group_name , key );
00501       gchar** str_array = g_strsplit_set( str , ",;" , -1 );
00502 
00503       *len = g_strv_length( str_array );
00504 
00505       if ( *len > 0 )
00506       {
00507          gint i;
00508          d_array = eh_new( double , *len );
00509          for ( i=0 ; i<*len ; i++ )
00510             d_array[i] = g_strtod( str_array[i] , NULL );
00511       }
00512 
00513       eh_free( str );
00514       g_strfreev( str_array );
00515    }
00516 
00517    return d_array;
00518 }
00519 
00530 double* eh_key_file_get_dbl_values( Eh_key_file f           ,
00531                                     const gchar* group_name ,
00532                                     const gchar* key )
00533 {
00534    guint   len = eh_key_file_group_size(f,group_name);
00535    gchar** str = eh_key_file_get_all_values(f,group_name,key);
00536    double* ans = eh_new( double , len );
00537    guint i;
00538 
00539    for ( i=0 ; i<len ; i++ )
00540       ans[i] = g_strtod( str[i] , NULL );
00541 
00542    g_strfreev( str );
00543 
00544    return ans;
00545 }
00546 
00547 gint
00548 eh_key_file_get_int_value( Eh_key_file f ,
00549                            const gchar* group_name ,
00550                            const gchar* key )
00551 {
00552    gint ans;
00553    gchar* str = eh_key_file_get_value(f,group_name,key);
00554 
00555    if ( str ) ans = g_ascii_strtoll( str , NULL , 10 );
00556    else       ans = G_MAXINT;
00557 
00558    eh_free( str );
00559 
00560    return ans;
00561 }
00562 
00578 void eh_key_file_set_value( Eh_key_file f           ,
00579                             const gchar* group_name ,
00580                             const gchar* key        ,
00581                             const gchar* value )
00582 {
00583    eh_require( f );
00584 
00585    {
00586       Eh_symbol_table group;
00587 
00588       /* If the group doesn't exist, or the key is alreay present, add a new group */
00589       if ( !eh_key_file_has_group( f , group_name )
00590            || eh_key_file_has_key( f , group_name , key ) )
00591          group = eh_key_file_add_group( f , group_name , FALSE );
00592       else
00593          group = g_list_first(g_hash_table_lookup( f->t , group_name ))->data;
00594       /* We are now sure that the key is not present in this table. */
00595 
00596       eh_require( group );
00597 
00598       /* We duplicate the strings and add them to the table */
00599       eh_symbol_table_insert( group , g_strdup( key ) , g_strdup( value ) );
00600    }
00601 }
00602 
00618 void eh_key_file_reset_value( Eh_key_file f           ,
00619                               const gchar* group_name ,
00620                               const gchar* key        ,
00621                               const gchar* value )
00622 {
00623    Eh_symbol_table group;
00624 
00625    eh_require( f );
00626 
00627    group = eh_key_file_add_group( f , group_name , TRUE );
00628 
00629    eh_symbol_table_insert( group , g_strdup( key ) , g_strdup( value ) );
00630 }
00631 
00632 
00644 Eh_symbol_table eh_key_file_get_symbol_table( Eh_key_file f ,
00645                                               const gchar* group_name )
00646 {
00647    GList* group = g_hash_table_lookup( f->t , group_name );
00648    return eh_symbol_table_dup( group->data );
00649 }
00650 
00663 Eh_symbol_table*
00664 eh_key_file_get_symbol_tables( Eh_key_file f , const gchar* group_name )
00665 {
00666    Eh_symbol_table* value = NULL;
00667 
00668    if ( f )
00669    {
00670       GList* group = g_hash_table_lookup( f->t , group_name );
00671       if ( group )
00672       {
00673          GList* l;
00674          guint i;
00675          guint len = eh_key_file_group_size( f , group_name );
00676 
00677          value = g_new( Eh_symbol_table , len+1 );
00678          for ( i=0,l=group ; l ; i++, l=l->next )
00679             value[i] = eh_symbol_table_dup( l->data );
00680          value[len] = NULL;
00681       }
00682    }
00683    return value;
00684 }
00685 
00692 void print_keys( gpointer key , gpointer value , gpointer user_data )
00693 {
00694    eh_message( "KEY = %s" , (gchar*)key );
00695 }
00696 
00707 Eh_key_file
00708 eh_key_file_scan( const char* file , GError** error )
00709 {
00710    Eh_key_file f = NULL;
00711 
00712    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00713 
00714    f = eh_key_file_new();
00715 
00716    if ( f )
00717    {
00718       GError*   tmp_err = NULL;
00719       GScanner* s;
00720 
00721       s = eh_open_scanner( file , &tmp_err );
00722 
00723       if ( s )
00724       {
00725          gboolean        done = FALSE;
00726          gchar*          group_name;
00727          Eh_symbol_table symbol_table;
00728          gpointer        user_data[2];
00729 
00730          while( !done && !g_scanner_eof(s) )
00731          {
00732             symbol_table = eh_symbol_table_new();
00733             group_name = eh_scan_next_record( s , symbol_table );
00734 
00735             if ( group_name )
00736             {
00737                user_data[0] = f;
00738                user_data[1] = group_name;
00739 
00740                eh_symbol_table_foreach( symbol_table , &add_record_value , user_data );
00741             }
00742             else
00743                done = TRUE;
00744 
00745             eh_symbol_table_destroy( symbol_table );
00746             eh_free( group_name );
00747          }
00748 
00749          eh_close_scanner( s );
00750       }
00751       else
00752       {
00753          f = eh_key_file_destroy( f );
00754          g_propagate_error( error , tmp_err );
00755       }
00756    }
00757 
00758    return f;
00759 }
00760 
00761 gint
00762 eh_key_file_scan_from_template( const gchar* file       ,
00763                                 const gchar* group_name ,
00764                                 Eh_key_file_entry t[]   ,
00765                                 GError** error )
00766 {
00767    gint n_entries = 0;
00768 
00769    eh_return_val_if_fail( error==NULL || *error==NULL , 0 );
00770 
00771    if ( file )
00772    {
00773       GError*     tmp_error       = NULL;
00774       Eh_key_file f               = NULL;
00775       gchar**     missing_entries = NULL;
00776       gint*       len;
00777       gint        i;
00778 
00779       for ( n_entries=0 ; t[n_entries].label ; n_entries++ );
00780 
00781       for ( i=0 ; i<n_entries ; i++ )
00782          if ( t[i].arg == EH_ARG_DARRAY )
00783          {
00784             eh_require( t[i].arg_data_len );
00785             eh_return_val_if_fail( t[i].arg_data_len , 0 );
00786 
00787             *(t[i].arg_data_len) = 0;
00788          }
00789 
00790       len = eh_new( gint , n_entries );
00791 
00792       f = eh_key_file_scan( file , &tmp_error );
00793 
00794       for ( i=0 ; i<n_entries && !tmp_error ; i++ )
00795       {
00796          if ( eh_key_file_has_key( f , group_name , t[i].label ) )
00797          {
00798             switch ( t[i].arg )
00799             {
00800                case EH_ARG_DBL:
00801                   *(double* )(t[i].arg_data) = eh_key_file_get_dbl_value( f , group_name , t[i].label );
00802                   break;
00803                case EH_ARG_INT:
00804                   *(gint* )(t[i].arg_data) = eh_key_file_get_dbl_value( f , group_name , t[i].label );
00805                   break;
00806                case EH_ARG_DARRAY:
00807                   *(double**)(t[i].arg_data) = eh_key_file_get_dbl_array( f , group_name , t[i].label , &(len[i]) );
00808 
00809                   if ( *(t[i].arg_data_len)==0 || *(t[i].arg_data_len)==len[i] )
00810                      *(t[i].arg_data_len) = len[i];
00811                   else
00812                      g_set_error( &tmp_error ,
00813                                   EH_KEY_FILE_ERROR ,
00814                                   EH_KEY_FILE_ERROR_ARRAY_LEN_MISMATCH ,
00815                                   "%s: Array length mismatch (%d!=%d): %s\n" ,
00816                                   file , len[i] , *(t[i].arg_data_len) , t[i].label );
00817 
00818                   break;
00819                case EH_ARG_FILENAME:
00820                   *(gchar**)(t[i].arg_data)  = eh_key_file_get_value( f , group_name , t[i].label );
00821                   break;
00822             }
00823          }
00824          else
00825             eh_strv_append( &missing_entries , g_strconcat(file , ": Missing required entry: " , t[i].label , NULL ) );
00826 
00827       }
00828 
00829       if ( !tmp_error && missing_entries )
00830       {
00831          gchar* missing_list = g_strjoinv( "\n" , missing_entries );
00832 
00833          g_set_error( &tmp_error ,
00834                       EH_KEY_FILE_ERROR ,
00835                       EH_KEY_FILE_ERROR_MISSING_ENTRY ,
00836                       "%s\n" , missing_list );
00837 
00838          eh_free( missing_list );
00839       }
00840 
00841       if ( tmp_error )
00842          g_propagate_error( error , tmp_error );
00843 
00844       g_strfreev( missing_entries );
00845       eh_free( len );
00846       eh_key_file_destroy( f );
00847    }
00848 
00849    return n_entries;
00850 }
00851 
00852 gssize
00853 eh_key_file_fprint_template( FILE* fp                ,
00854                              const gchar* group_name ,
00855                              Eh_key_file_entry entry[] )
00856 {
00857    gint n = 0;
00858 
00859    if ( fp )
00860    {
00861       gint        n_entries;
00862       gint        max_len = 0;
00863       gchar*      pad;
00864       gint        i;
00865 
00866       for ( n_entries=0 ; entry[n_entries].label ; n_entries++ );
00867 
00868       for ( i=0 ; i<n_entries ; i++ )
00869          if ( strlen( entry[i].label ) > max_len )
00870             max_len = strlen( entry[i].label );
00871 
00872       pad = g_strnfill( max_len , ' ' );
00873 
00874       fprintf( fp , "[ %s ]" , group_name );
00875 
00876       for ( i=0 ; i<n_entries ; i++ )
00877       {
00878          n += fprintf( fp , "%s :%s" , entry[i].label , pad + strlen( entry[i].label ) );
00879 
00880          switch ( entry[i].arg )
00881          {
00882             case EH_ARG_DBL:
00883                n += fprintf( fp , "%s\n" , "<double-scalar>" );
00884                break;
00885             case EH_ARG_INT:
00886                n += fprintf( fp , "%s\n" , "<int-scalar>" );
00887                break;
00888             case EH_ARG_DARRAY:
00889                n += fprintf( fp , "%s\n" , "<double-array>" );
00890                break;
00891             case EH_ARG_FILENAME:
00892                n += fprintf( fp , "%s\n" , "<filename>" );
00893                break;
00894          }
00895       }
00896 
00897       eh_free( pad );
00898    }
00899 
00900    return n;
00901 }
00902 
00919 Eh_symbol_table
00920 eh_key_file_scan_for( const gchar* file ,
00921                       const gchar* name ,
00922                       Eh_symbol_table tab ,
00923                       GError** error )
00924 {
00925    Eh_symbol_table new_tab = NULL;
00926 
00927    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00928 
00929    //---
00930    // Open the key-file and scan in all of the entries.
00931    //
00932    // Add each key-value pair (of the specified group) to the symbol table.
00933    //---
00934    {
00935       GError*     tmp_err  = NULL;
00936       Eh_key_file key_file = eh_key_file_scan( file , &tmp_err );
00937    
00938       if ( key_file )
00939       {
00940          if ( eh_key_file_has_group( key_file , name ) )
00941             new_tab = eh_key_file_get_symbol_table( key_file , name );
00942          else
00943             new_tab = NULL;
00944       }
00945       else
00946          g_propagate_error( error , tmp_err );
00947 
00948       eh_key_file_destroy( key_file );
00949    }
00950 
00951    if ( tab && new_tab )
00952    {
00953       eh_symbol_table_copy   ( tab , new_tab );
00954       eh_symbol_table_destroy( new_tab );
00955 
00956       new_tab = tab;
00957    }
00958 
00959    return new_tab;
00960 }
00961 
00972 Eh_symbol_table eh_key_file_pop_group( Eh_key_file f )
00973 {
00974    Eh_symbol_table new_table = NULL;
00975 
00976    if ( f && f->l )
00977    {
00978       gchar* group_name = g_list_first(f->l)->data;
00979       GList* group_list = g_hash_table_lookup( f->t , group_name );
00980 
00981       eh_require( group_list );
00982 
00983       /* Pop the next group in the list */
00984       new_table = g_list_first( group_list )->data;
00985 
00986       /* Delete the link to this group */
00987       group_list = g_list_delete_link( group_list , group_list );
00988 
00989       if ( group_list )
00990          /* If the list isn't empty, insert the new start of the list into the hash table */
00991          g_hash_table_replace( f->t , g_strdup(group_name) , group_list );
00992       else
00993          /* Otherwise, remove the group from the hash table */
00994          g_hash_table_remove( f->t , group_name );
00995 
00996       /* Delete the first link in the list and free the data */
00997       eh_free( group_name );
00998       f->l = g_list_delete_link( f->l , f->l );
00999    }
01000 
01001    return new_table;
01002 }
01003 

Generated on Fri Jan 4 18:04:16 2008 for sedflux by  doxygen 1.5.2