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
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
00665
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
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
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
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