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

Go to the documentation of this file.
00001 #include <eh_utils.h>
00002 #include <strings.h>
00003 #include <errno.h>
00004 
00005 GQuark
00006 eh_str_error_quark( void )
00007 {
00008    return g_quark_from_static_string( "eh-str-error-quark" );
00009 }
00010 
00011 double**
00012 eh_str_to_time_range_piecewise( const gchar* s , GError** error )
00013 {
00014    double** range = NULL;
00015 
00016    eh_require( s );
00017    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00018 
00019    if ( s )
00020    {
00021       gchar** pieces = g_strsplit( s , ";" , 0 );
00022       GError* tmp_e  = NULL;
00023       gchar** p;
00024       double* this_range;
00025       double  last_top = -G_MAXDOUBLE;
00026 
00027       for ( p=pieces ; *p && !tmp_e ; p++ )
00028       {
00029          this_range = eh_str_to_time_range( *p , &tmp_e );
00030 
00031          if ( !tmp_e )
00032          {
00033             eh_strv_append( (gchar***)&range , (gchar*)this_range );
00034 
00035             if ( this_range[1] < last_top )
00036             {
00037                g_set_error( &tmp_e ,
00038                             EH_STR_ERROR ,
00039                             EH_STR_ERROR_RANGE_OVERLAP ,
00040                             "Overlapping ranges" );
00041             }
00042 
00043             last_top = this_range[1];
00044          }
00045       }
00046 
00047       g_strfreev( pieces );
00048 
00049       if ( tmp_e )
00050       {
00051          g_propagate_error( error , tmp_e );
00052          g_strfreev( (gchar**)range );
00053          range = NULL;
00054       }
00055    }
00056 
00057    return range;
00058 }
00059 
00060 double**
00061 eh_str_to_dbl_range_piecewise( const gchar* s , GError** error )
00062 {
00063    double** range = NULL;
00064 
00065    eh_require( s );
00066    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00067 
00068    if ( s )
00069    {
00070       gchar** pieces = g_strsplit( s , ";" , 0 );
00071       GError* tmp_e  = NULL;
00072       gchar** p;
00073       double* this_range;
00074       double  last_top = -G_MAXDOUBLE;
00075 
00076       for ( p=pieces ; *p && !tmp_e ; p++ )
00077       {
00078          this_range = eh_str_to_dbl_range( *p , &tmp_e );
00079 
00080          if ( !tmp_e )
00081          {
00082             eh_strv_append( (gchar***)&range , (gchar*)this_range );
00083 
00084             if ( this_range[1] < last_top )
00085             {
00086                g_set_error( &tmp_e ,
00087                             EH_STR_ERROR ,
00088                             EH_STR_ERROR_RANGE_OVERLAP ,
00089                             "Overlapping ranges" );
00090             }
00091 
00092             last_top = this_range[1];
00093          }
00094       }
00095 
00096       g_strfreev( pieces );
00097 
00098       if ( tmp_e )
00099       {
00100          g_propagate_error( error , tmp_e );
00101          g_strfreev( (gchar**)range );
00102          range = NULL;
00103       }
00104    }
00105 
00106    return range;
00107 }
00108 
00109 double*
00110 eh_str_to_dbl_range( const gchar* s , GError** error )
00111 {
00112    double* range = NULL;
00113 
00114    eh_require( s );
00115    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00116 
00117    if ( s )
00118    {
00119       gchar** end_s = g_strsplit( s , "->" , 0 );
00120       gint    len   = g_strv_length( end_s );
00121       GError* tmp_e = NULL;
00122 
00123       if ( len>=2 )
00124       {
00125          range    = eh_new( double , 2 );
00126 
00127          range[0] = eh_str_to_dbl( end_s[0    ] , &tmp_e );
00128          range[1] = eh_str_to_dbl( end_s[len-1] , &tmp_e );
00129 
00130          if ( !tmp_e && range[0] > range[1] )
00131          {
00132             g_set_error( &tmp_e ,
00133                          EH_STR_ERROR ,
00134                          EH_STR_ERROR_BAD_RANGE ,
00135                          "Upper bound not greater than lower bound" );
00136          }
00137 
00138          if ( tmp_e )
00139             eh_free( range );
00140       }
00141       else
00142       {
00143          g_set_error( &tmp_e ,
00144                       EH_STR_ERROR ,
00145                       EH_STR_ERROR_NO_RANGE ,
00146                       "Range specifier ('->') not found" );
00147       }
00148       
00149       g_strfreev( end_s );
00150 
00151       if ( tmp_e )
00152       {
00153          g_propagate_error( error , tmp_e );
00154          range = NULL;
00155       }
00156    }
00157 
00158    return range;
00159 }
00160 
00161 double*
00162 eh_str_to_time_range( const gchar* s , GError** error )
00163 {
00164    double* range = NULL;
00165 
00166    eh_require( s );
00167    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00168 
00169    if ( s )
00170    {
00171       gchar** end_s = g_strsplit( s , "->" , 0 );
00172       gint    len   = g_strv_length( end_s );
00173       GError* tmp_e = NULL;
00174 
00175       if ( len>=2 )
00176       {
00177          range    = eh_new( double , 2 );
00178 
00179          if ( !tmp_e ) range[0] = eh_str_to_time_in_years( end_s[0    ] , &tmp_e );
00180          if ( !tmp_e ) range[1] = eh_str_to_time_in_years( end_s[len-1] , &tmp_e );
00181          if ( !tmp_e && range[0] > range[1] )
00182          {
00183             g_set_error( &tmp_e ,
00184                          EH_STR_ERROR ,
00185                          EH_STR_ERROR_BAD_RANGE ,
00186                          "Upper bound not greater than lower bound" );
00187          }
00188 
00189          if ( tmp_e )
00190             eh_free( range );
00191       }
00192       else
00193       {
00194          g_set_error( &tmp_e ,
00195                       EH_STR_ERROR ,
00196                       EH_STR_ERROR_NO_RANGE ,
00197                       "Range specifier ('->') not found" );
00198       }
00199       
00200       g_strfreev( end_s );
00201 
00202       if ( tmp_e )
00203       {
00204          g_propagate_error( error , tmp_e );
00205          range = NULL;
00206       }
00207    }
00208 
00209    return range;
00210 }
00211 
00212 double
00213 eh_str_to_dbl( const gchar* s , GError** error )
00214 {
00215    double dbl_val;
00216 
00217    eh_require( s );
00218    eh_return_val_if_fail( error==NULL || *error==NULL , eh_nan() );
00219 
00220    if ( s )
00221    {
00222       GError* tmp_e = NULL;
00223       gchar*  p;
00224 
00225       dbl_val = g_strtod( s , &p );
00226 
00227       if ( p==s )
00228       {
00229          g_set_error( &tmp_e ,
00230                       EH_STR_ERROR ,
00231                       EH_STR_ERROR_BAD_STRING ,
00232                       "Failed to convert string to double: %s" , g_strerror( errno ) );
00233          g_propagate_error( error , tmp_e );
00234          dbl_val = eh_nan();
00235       }
00236    }
00237 
00238    return dbl_val;
00239 }
00240 
00241 gint64
00242 eh_str_to_int( const gchar* s , GError** error )
00243 {
00244    gint64 int_val;
00245 
00246    eh_require( s );
00247    eh_return_val_if_fail( error==NULL || *error==NULL , eh_nan() );
00248 
00249    if ( s )
00250    {
00251       GError* tmp_e = NULL;
00252       gchar*  p;
00253 
00254       int_val = g_ascii_strtoull( s , &p , 10 );
00255 
00256       if (      p==s 
00257            || ( errno==ERANGE && ( int_val==G_MAXINT64 || int_val==G_MININT64 ) )
00258            || ( errno==EINVAL &&   int_val==0 ) )
00259       {
00260          g_set_error( &tmp_e ,
00261                       EH_STR_ERROR ,
00262                       EH_STR_ERROR_BAD_STRING ,
00263                       "Failed to convert string to int: %s" , g_strerror( errno ) );
00264          g_propagate_error( error , tmp_e );
00265          int_val = G_MININT;
00266       }
00267    }
00268 
00269    return int_val;
00270 }
00271 
00272 double
00273 eh_str_to_time_in_years( const gchar* s , GError** error )
00274 {
00275    double t;
00276 
00277    eh_require( s );
00278    eh_return_val_if_fail( error==NULL || *error==NULL , eh_nan() );
00279 
00280    if ( s )
00281    {
00282       GError*   tmp_e  = NULL;
00283       char      unit_c = 0;
00284       GString*  str    = g_string_new(s);
00285       Eh_date_t time   = {0,0,0};
00286       int       n;
00287       double    val;
00288 
00289       eh_string_remove_white_space( str );
00290 
00291       while (    !tmp_e
00292               && ( n=sscanf(eh_string_c_str(str),"%lf%c",&val,&unit_c) ) > 0 )
00293       {
00294          /* It's an error if both values are not scanned. */
00295          if ( n == 2 )
00296          {
00297             switch ( unit_c )
00298             {
00299                case 'd': time.day   = val; break;
00300                case 'm': time.month = val; break;
00301                case 'y': time.year  = val; break;
00302 
00303                default:
00304                   g_set_error( &tmp_e ,
00305                                EH_STR_ERROR ,
00306                                EH_STR_ERROR_BAD_UNIT ,
00307                                "Invalid unit: %c" , unit_c );
00308             }
00309          }
00310          else
00311          {
00312             g_set_error( &tmp_e ,
00313                          EH_STR_ERROR ,
00314                          EH_STR_ERROR_NO_UNIT ,
00315                          "Missing time unit [dmy]" );
00316          }
00317 
00318          g_string_erase(str,0,eh_string_find_first_of(str,unit_c)+1);
00319       }
00320 
00321       if ( !tmp_e )
00322          t = eh_date_to_years( &time );
00323       else
00324       {
00325          t = eh_nan();
00326          g_propagate_error( error , tmp_e );
00327       }
00328 
00329       g_string_free( str , TRUE );
00330    }
00331 
00332    return t;
00333 }
00334 
00335 gboolean
00336 eh_str_is_boolean( const gchar* s )
00337 {
00338    gboolean is_boolean = FALSE;
00339 
00340    eh_require( s );
00341 
00342    if ( s )
00343    {
00344       GError* error = NULL;
00345 
00346       eh_str_to_boolean( s , &error );
00347 
00348       if ( error )
00349       {
00350          is_boolean = FALSE;
00351          g_error_free( error );
00352       }
00353       else
00354          is_boolean = TRUE;
00355    }
00356 
00357    return is_boolean;
00358 }
00359 
00360 gboolean
00361 eh_str_to_boolean( const gchar* s , GError** error )
00362 {
00363    gboolean val = FALSE;
00364 
00365    eh_require( s );
00366    eh_return_val_if_fail( error==NULL || *error==NULL , FALSE );
00367 
00368    if ( s )
00369    {
00370       GError* tmp_e = NULL;
00371       gchar*  str   = g_strstrip( g_strdup( s ) );
00372 
00373       if      ( g_ascii_strcasecmp(str,"YES"  ) == 0 ||
00374                 g_ascii_strcasecmp(str,"ON"   ) == 0 ||
00375                 g_ascii_strcasecmp(str,"TRUE" ) == 0 ||
00376                 g_ascii_strcasecmp(str,"OUI"  ) == 0 )
00377          val = TRUE;
00378       else if ( g_ascii_strcasecmp(str,"NO"   ) == 0 ||
00379                 g_ascii_strcasecmp(str,"OFF"  ) == 0 ||
00380                 g_ascii_strcasecmp(str,"FALSE") == 0 ||
00381                 g_ascii_strcasecmp(str,"NON"  ) == 0 )
00382          val = FALSE;
00383       else
00384       {
00385          g_set_error( &tmp_e ,
00386                       EH_STR_ERROR ,
00387                       EH_STR_ERROR_BAD_LOGICAL_VAL ,
00388                       "Invalid logical value: %s" , str );
00389          g_propagate_error( error , tmp_e );
00390          val = FALSE;
00391       }
00392 
00393       eh_free( str );
00394    }
00395 
00396    return val;
00397 }
00398 
00410 gchar**
00411 eh_strv_append( gchar*** str_l , gchar* new_str )
00412 {
00413    if ( str_l && new_str )
00414    {
00415       if ( *str_l==NULL )
00416       {
00417          *str_l = eh_new( gchar* , 2 );
00418 
00419          (*str_l)[0] = new_str;
00420          (*str_l)[1] = NULL;
00421       }
00422       else
00423       {
00424          gint len = g_strv_length(*str_l)+1;
00425 
00426          *str_l = eh_renew( gchar* , *str_l , len+1 );
00427 
00428          (*str_l)[len-1] = new_str;
00429          (*str_l)[len]   = NULL;
00430       }
00431    }
00432 
00433    return *str_l;
00434 }
00435 
00436 gchar**
00437 eh_strv_concat( gchar*** str_l , gchar** new_l )
00438 {
00439    if ( str_l && new_l )
00440    {
00441       gchar** s;
00442 
00443       for ( s=new_l ; *s ; s++ )
00444          *str_l = eh_strv_append( str_l , *s );
00445    }
00446 
00447    return *str_l;
00448 }
00449 
00450 gint
00451 eh_strv_find( const gchar** str_l , const gchar* needle )
00452 {
00453    gint i = -1;
00454 
00455    eh_require( str_l );
00456 
00457    if ( str_l && needle )
00458    {
00459       gchar** s;
00460       gint    n;
00461       for ( s=(gchar**)str_l,n=0 ; *s && i<0 ; s++,n++ )
00462          if ( g_ascii_strcasecmp( *s , needle )==0 )
00463             i = n;
00464    }
00465 
00466    return i;
00467 }
00468 
00469 gchar*
00470 eh_str_replace( gchar* str , gchar old_c , gchar new_c )
00471 {
00472    if ( str )
00473    {
00474       gchar* pos;
00475       for ( pos=strchr(str  , old_c ) ;
00476             pos ;
00477             pos=strchr(pos+1, old_c ) )
00478          pos[0] = new_c;
00479    }
00480    return str;
00481 }
00482 
00483 gchar*
00484 eh_str_remove( gchar* str , gchar* start , gint n )
00485 {
00486    if ( str )
00487    {
00488       gchar* tail = start+n;
00489       g_memmove( start , tail , strlen(tail)+1 );
00490    }
00491    return str;
00492 }
00493 
00494 gchar*
00495 eh_str_remove_blocks( gchar* str , gchar** block_start , gchar** block_end )
00496 {
00497    if ( str && block_start && block_start[0] )
00498    {
00499       gchar* tail;
00500       gint i, n;
00501       gint len = g_strv_length( block_start );
00502 
00503       block_start[len] = block_end[len-1] + strlen(block_end[len-1])+1;
00504 
00505       tail = block_start[0];
00506       for ( i=0 ; i<len ; i++ )
00507       {
00508          n = block_start[i+1] - block_end[i];
00509          g_memmove( tail , block_end[i] , n );
00510          tail += n;
00511       }
00512 
00513       block_start[len] = NULL;
00514    }
00515    return str;
00516 }
00517 
00530 Eh_symbol_table
00531 eh_str_parse_key_value( gchar* str , gchar* delim_1 , gchar* delim_2 )
00532 {
00533    Eh_symbol_table tab = NULL;
00534 
00535    if ( str )
00536    {
00537       gchar** key_value;
00538       gchar** pairs;
00539       gint i, n_pairs;
00540 
00541       tab = eh_symbol_table_new( );
00542 
00543       pairs = g_strsplit( str , delim_2 , -1 );
00544       n_pairs = g_strv_length( pairs );
00545       for ( i=0 ; i<n_pairs ; i++ )
00546       {
00547          key_value = g_strsplit( pairs[i] , delim_1 , 2 );
00548 
00549          eh_require( g_strv_length(key_value)==2 )
00550          {
00551             eh_str_remove_comments( key_value[0] , "(" , ")" , NULL );
00552             g_strstrip( key_value[0] );
00553             g_strstrip( key_value[1] );
00554 
00555             eh_symbol_table_insert( tab , key_value[0] , key_value[1] );
00556          }
00557 
00558          g_strfreev( key_value );
00559       }
00560       g_strfreev( pairs );
00561 
00562       if ( eh_symbol_table_size(tab)==0 )
00563          tab = eh_symbol_table_destroy(tab);
00564    }
00565 
00566    return tab;
00567 }
00568 
00580 gint
00581 eh_str_count_chr( gchar* str , gchar* end , gint delim )
00582 {
00583    gint n = 0;
00584 
00585    if ( str )
00586    {   
00587       gchar* pos;
00588       for ( pos=strchr(str  , delim ),n=0 ;
00589             pos && pos<=end ;
00590             pos=strchr(pos+1, delim ),n++ );
00591    }
00592 
00593    return n;
00594 }
00595 
00608 gchar*
00609 eh_str_remove_to_eol_comments( gchar* str , gchar* com_start )
00610 {
00611    return eh_str_remove_comments( str , com_start , NULL , NULL );
00612 }
00613 
00625 gchar*
00626 eh_str_remove_c_style_comments( gchar* str )
00627 {
00628    return eh_str_remove_comments( str , "/*" , "*/" , NULL );
00629 }
00630 
00652 gchar*
00653 eh_str_remove_comments( gchar* str             ,
00654                         const gchar* start_str ,
00655                         const gchar* end_str   ,
00656                         gchar*** comments )
00657 {
00658    gint end_len;
00659 
00660    eh_require( start_str );
00661 
00662    if ( !end_str )
00663    {
00664       /* This is a special case where the comment ends at the end of the
00665          line but we don't want to remove the EOL character */
00666       end_str = "\n";
00667       end_len = 0;
00668    }
00669    else
00670       end_len = strlen(end_str);
00671 
00672    if ( comments )
00673       *comments = NULL;
00674 
00675    if ( str )
00676    {
00677       gchar* pos_0;
00678       gchar* pos_1;
00679       gchar* str_end = str+strlen(str);
00680       gint   start_len = strlen(start_str);
00681       gint   len = 1;
00682 
00683       pos_0 = strstr( str , start_str );
00684       while ( pos_0 )
00685       {
00686          pos_1 = strstr( pos_0 , end_str );
00687 
00688          if ( !pos_1 )
00689             pos_1 = str_end-end_len;
00690 
00691          if ( comments )
00692          {
00693             len             += 1;
00694             *comments        = eh_renew( gchar* , *comments , len );
00695             *comments[len-2] = g_strndup( pos_0 + start_len ,
00696                                           pos_1 - (pos_0+start_len) );
00697             *comments[len-1] = NULL;
00698          }
00699 
00700          g_memmove( pos_0 ,
00701                     pos_1+end_len ,
00702                     str_end - (pos_1+end_len)+1 );
00703          str_end -= pos_1+end_len - pos_0;
00704 
00705          pos_0 = strstr( pos_0 , start_str );
00706       }
00707    }
00708 
00709    return str;
00710 }
00711 
00712 #include <string.h>
00713 
00714 #define WHITE_SPACE " \t\n"
00715 
00716 gchar*
00717 eh_str_trim_left( gchar *str )
00718 {
00719    char *ptr;
00720 
00721 //   ptr = (char*)malloc1D(sizeof(char)*(strlen(str)+1));
00722    ptr = eh_new( char , strlen(str)+1 );
00723    strcpy(ptr,str);
00724    while ( strchr(WHITE_SPACE,ptr[0])!=0 && ptr!='\0' )
00725       ptr++;
00726    strcpy(str,ptr);
00727    return str;
00728 }
00729 
00730 gchar*
00731 eh_str_trim_right( gchar *str )
00732 {
00733    char *ptr;
00734    int len;
00735 
00736 //   ptr = (char*)malloc1D(sizeof(char)*(strlen(str)+1));
00737    ptr = eh_new( char , strlen(str)+1 );
00738    strcpy(ptr,str);
00739    len = strlen(ptr);
00740    while ( strchr(WHITE_SPACE,ptr[len-1])!=0 && len>0 )
00741    {
00742       ptr[len-1]='\0';
00743       len--;
00744    }
00745    strcpy(str,ptr);
00746    return str;
00747 }
00748 
00749 gchar*
00750 eh_str_remove_white_space( gchar *str )
00751 {
00752    int i, j;
00753    char *str_temp;
00754 // Add one for the terminating null character.
00755    str_temp = eh_new( char , strlen(str)+1 );
00756    strcpy(str_temp,str);
00757    for (i=0,j=0;i<strlen(str_temp);i++)
00758       if ( strchr(WHITE_SPACE,str_temp[i]) == NULL )
00759       {
00760          str[j] = str_temp[i];
00761          j++;
00762       }
00763    str[j] = '\0';
00764    eh_free(str_temp);
00765    return str;
00766 }
00767 

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