ParFile.cc
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <errno.h>
00026 #include <stdlib.h>
00027 #include <string>
00028 #include <fstream>
00029
00030 #include <getline/getline.h>
00031 #include <suplib/str.h>
00032 #include <suplibxx/io.h>
00033
00034 #include "ParFile.h"
00035 #include "ParTxt.h"
00036 #include "NameAttributeValue.h"
00037 #include "BoolPar.h"
00038 #include "CommentPar.h"
00039 #include "LongPar.h"
00040 #include "RealPar.h"
00041 #include "StringPar.h"
00042
00043 using namespace std;
00044
00045 #define MODE "mode"
00046
00047 ParFile::~ParFile( ) {
00048 if ( parameters ) {
00049 size_t count = 0;
00050 while( parameters[ count ] ) {
00051 delete parameters[ count ];
00052 ++count;
00053 }
00054 delete [] parameters;
00055 parameters = NULL;
00056 }
00057 }
00058
00059 ParFile::ParFile( int argc, char** argv, const char* file )
00060 throw ( ParFileException, Exception ) : parameters( NULL ) {
00061
00062 try {
00063
00064 init_ParFile( argc, argv, file );
00065
00066 } catch( ParFileException& pfe ) {
00067 throw;
00068 }
00069
00070 }
00071
00072 void ParFile::pget( const char* name, bool& result ) const
00073 throw ( ParFileException ) {
00074
00075 try {
00076 result = pgetb( name );
00077 } catch ( ParFileException& pfe ) {
00078 throw;
00079 }
00080
00081 }
00082
00083 void ParFile::pget( const char* name, double& result ) const
00084 throw ( ParFileException ) {
00085
00086 try {
00087 result = pgetd( name );
00088 } catch ( ParFileException& pfe ) {
00089 throw;
00090 }
00091
00092 }
00093
00094 void ParFile::pget( const char* name, int& result ) const
00095 throw ( ParFileException ) {
00096
00097 try {
00098 result = pgeti( name );
00099 } catch ( ParFileException& pfe ) {
00100 throw;
00101 }
00102
00103 }
00104
00105 void ParFile::pget( const char* name, long& result ) const
00106 throw ( ParFileException ) {
00107
00108 try {
00109 result = pgetl( name );
00110 } catch ( ParFileException& pfe ) {
00111 throw;
00112 }
00113
00114 }
00115
00116 void ParFile::pget( const char* name, char result[], size_t size ) const
00117 throw ( ParFileException ) {
00118
00119 try {
00120 pgetstr( name, result, size );
00121 } catch ( ParFileException& pfe ) {
00122 throw;
00123 }
00124
00125 }
00126
00127 void ParFile::pget( const char* name, string& result ) const
00128 throw ( ParFileException ) {
00129
00130 try {
00131 result = pgetstring( name );
00132 } catch ( ParFileException& pfe ) {
00133 throw;
00134 }
00135
00136 }
00137
00138 bool ParFile::pgetb( const char* name ) const throw ( ParFileException ) {
00139
00140 try {
00141 Par* par = get_par( name );
00142 return par->pgetb( );
00143 } catch ( ParFileException& pfe ) {
00144 throw;
00145 }
00146
00147 }
00148
00149 double ParFile::pgetd( const char* name ) const throw ( ParFileException ) {
00150
00151 try {
00152 Par* par = get_par( name );
00153 return par->pgetd( );
00154 } catch ( ParFileException& pfe ) {
00155 throw;
00156 }
00157
00158 }
00159
00160 int ParFile::pgeti( const char* name ) const throw ( ParFileException ) {
00161
00162 try {
00163 Par* par = get_par( name );
00164 return par->pgeti( );
00165 } catch ( ParFileException& pfe ) {
00166 throw;
00167 }
00168
00169 }
00170
00171 long ParFile::pgetl( const char* name ) const throw ( ParFileException ) {
00172
00173 try {
00174 Par* par = get_par( name );
00175 return par->pgetl( );
00176 } catch ( ParFileException& pfe ) {
00177 throw;
00178 }
00179
00180 }
00181
00182 void ParFile::pgetstr( const char* name, char result[], size_t size ) const
00183 throw ( ParFileException ) {
00184
00185 try {
00186 Par* par = get_par( name );
00187 string str = par->pgetstring( );
00188 strncpy( result, str.c_str( ), size );
00189 result[ size - 1 ] = '\0';
00190 return;
00191 } catch ( ParFileException& pfe ) {
00192 throw;
00193 }
00194
00195 }
00196
00197 string ParFile::pgetstring( const char* name ) const
00198 throw ( ParFileException ) {
00199
00200 try {
00201 Par* par = get_par( name );
00202 return par->pgetstring( );
00203 } catch ( ParFileException& pfe ) {
00204 throw;
00205 }
00206
00207 }
00208
00209
00210
00211
00212
00213 void ParFile::get_mode_of_parameter_file( int argc, char** argv )
00214 throw ( ParFileException ) {
00215
00216 try {
00217
00218
00219 Par* par = search_name( MODE );
00220
00221 } catch( ParFileException& pfe ) {
00222
00223 return;
00224
00225 }
00226
00227 try {
00228
00229 Par* par = search_name( MODE );
00230
00231
00232
00233 set_return_on_error( par->get_mode( ) );
00234
00235
00236 for ( int i = 1; i < argc; i++ ) {
00237
00238 NameAttributeValue cmdline_mode( argv[ i ] );
00239
00240 if ( cmdline_mode.get_name( ) == MODE )
00241 set_return_on_error( cmdline_mode.get_value( ) );
00242
00243 }
00244
00245 } catch( ParFileException& pfe ) {
00246
00247 throw;
00248
00249 }
00250
00251 return;
00252
00253 }
00254
00255 Par* ParFile::get_par( const char* str ) const throw ( ParFileException ) {
00256
00257 try {
00258
00259 const char* original_name = str;
00260
00261
00262
00263 size_t max_count = 0;
00264 while( parameters[ max_count ] )
00265 ++max_count;
00266
00267 for ( size_t ii = 0; ii < max_count; ii++ ) {
00268
00269 Par* par = search_name( str );
00270
00271 string new_value = par->get_value( );
00272
00273 if ( Par::is_indirrect( new_value ) ) {
00274 str = new_value.c_str( );
00275 ++str;
00276 } else
00277 return par;
00278
00279 }
00280
00281
00282 const char* format =
00283 "ParFile::get_par( %s ) : Encountered an infinite loop\n";
00284 char tmp[ 256 ];
00285 sprintf( tmp, format, original_name );
00286 throw ParFileException( tmp );
00287
00288 } catch ( ParFileException& pfe ) {
00289 throw;
00290 }
00291
00292 }
00293
00294 void ParFile::init_ParFile( int argc, char** argv, const char* file )
00295 throw ( ParFileException, Exception ) {
00296
00297 try {
00298
00299
00300 return_on_error = true;
00301
00302 read_ParFile( argc, argv, file );
00303
00304
00305
00306
00307 get_mode_of_parameter_file( argc, argv );
00308
00309 is_duplicate_cmdline_args( argc, argv );
00310
00311 for ( int ii = 1; ii < argc; ii++ )
00312 setpar( argv[ ii ] );
00313
00314 } catch( ParFileException& pfe ) {
00315
00316 throw;
00317
00318 } catch( Exception& e ) {
00319
00320 throw;
00321
00322 }
00323
00324 }
00325
00326 bool ParFile::is_parlist( string& cmdline_name, string& cmdline_value ) {
00327
00328 if ( parameters ) {
00329 for ( size_t count = 0; NULL != parameters[ count ]; count++ )
00330 if ( parameters[ count ]->get_name( ) == cmdline_name )
00331 return false;
00332 }
00333
00334 if ( 0 == cmdline_value.compare( "" ) )
00335 return true;
00336 else
00337 return false;
00338
00339 }
00340
00341 bool ParFile::is_duplicate_cmdline_args( int argc, char** argv )
00342 throw( ParFileException ) {
00343
00344 vector< string > cmdline_options;
00345
00346
00347 for ( int i = 1; i < argc; i++ ) {
00348
00349 NameAttributeValue arg( argv[ i ] );
00350 string name = arg.get_name( );
00351
00352 vector< string >::const_iterator iter_begin = cmdline_options.begin( );
00353 vector< string >::const_iterator iter_end = cmdline_options.end( );
00354 for ( vector< string >::const_iterator iter = iter_begin;
00355 iter != iter_end; iter++ )
00356 if ( *iter == name ) {
00357 string msg( "ParFile::is_duplicate_cmdline_args( ) : Duplicate " );
00358 msg += name;
00359 throw ParFileException( msg );
00360 }
00361
00362 }
00363
00364 return false;
00365
00366 }
00367
00368 void ParFile::print( ostream& os ) const {
00369
00370 if ( parameters ) {
00371 size_t count = 0;
00372 while( parameters[ count ] ) {
00373 parameters[ count ]->print( os );
00374 if ( parameters[ ++count ] )
00375 os << '\n';
00376 }
00377 }
00378
00379 }
00380
00381 void ParFile::querry_user( Par* item, char* str ) {
00382
00383 if ( return_on_error )
00384 return;
00385
00386 const char* format = "%s (%s) : ";
00387
00388 string prompt = item->get_prompt();
00389
00390
00391 gl_histadd( str );
00392
00393 do {
00394
00395 size_t length =
00396 strlen( format ) + prompt.size( ) + strlen( str ) + 10;
00397 char* ptr = new char[ length ];
00398
00399 sprintf( ptr, format, prompt.c_str( ), str );
00400
00401 str = gl_getline( ptr );
00402 gl_histadd( str );
00403 delete [] ptr;
00404 ptr = NULL;
00405
00406 if ( ! is_comment( str ) )
00407 str_prune( str );
00408
00409 } while( EXIT_FAILURE == item->check_value( str ) );
00410
00411 item->set_val( str );
00412
00413 return;
00414
00415 }
00416
00417 void ParFile::set_return_on_error( const string& mode_of_parfile ) {
00418
00419 if ( string::npos == mode_of_parfile.find( "b" ) )
00420
00421 return_on_error = false;
00422 else
00423
00424 return_on_error = true;
00425
00426 }
00427
00428 static char mytmp[ 512 ];
00429
00430 void ParFile::read_ParFile( int argc, char** argv, const char* file )
00431 throw ( ParFileException ) {
00432
00433 try {
00434
00435 parFilename.init_ParFilename( argc, argv, file );
00436 string fname( parFilename.get_filename( ) );
00437
00438 ifstream input( fname.c_str( ), ios::in );
00439 if ( ! input ) {
00440 string msg( "ParFile::read_Parfile( ) : Unable to open file '" +
00441 fname +"'\n" );
00442 throw ParFileException( msg );
00443 }
00444
00445 parameters = new Par* [ 512 ];
00446 size_t count = 0;
00447
00448 string mytxt;
00449 while( suplib::getrecord( input, mytxt, suplib::READ_LOGICAL |
00450 suplib::STRIP | suplib::CLEAN ) ) {
00451
00452 ParTxt parTxt( (char*) mytxt.c_str( ) );
00453 char** buffer_argv = (char**) parTxt;
00454
00455 if ( NULL == buffer_argv ) {
00456
00457 parameters[ count ] = new CommentPar( parTxt );
00458
00459 } else if ( Par::BOOLEAN == buffer_argv[ Par::PARTYPE ][ 0 ] ) {
00460
00461 parameters[ count ] = new BoolPar( parTxt );
00462
00463 } else if ( Par::INTEGER == buffer_argv[ Par::PARTYPE ][ 0 ] ) {
00464
00465 parameters[ count ] = new LongPar( parTxt );
00466
00467 } else if ( Par::REAL == buffer_argv[ Par::PARTYPE ][ 0 ] ) {
00468
00469 parameters[ count ] = new RealPar( parTxt );
00470
00471 } else if ( Par::STRING == buffer_argv[ Par::PARTYPE ][ 0 ] ) {
00472
00473 parameters[ count ] = new StringPar( parTxt );
00474
00475 }
00476
00477 count++;
00478
00479
00480
00481 }
00482
00483 parameters[ count ] = NULL;
00484
00485 } catch( ParFileException& pfe ) {
00486 throw;
00487 }
00488
00489 }
00490
00491 Par* ParFile::search_name( const char* str ) const
00492 throw ( ParFileException ) {
00493
00494 if ( parameters ) {
00495 for ( size_t count = 0; NULL != parameters[ count ]; count++ )
00496 if ( parameters[ count ]->get_name( ) == str )
00497 return parameters[ count ];
00498 }
00499
00500 string msg( "ParFile::search_name( " );
00501 msg.append( str );
00502 msg.append( " ) : Unable to find the parameter\n" );
00503
00504 throw ParFileException( msg );
00505
00506 }
00507
00508
00509 void ParFile::setpar( char* str ) throw ( ParFileException, Exception ) {
00510
00511 try {
00512
00513 NameAttributeValue cmdline( str );
00514
00515 string cmdline_name( cmdline.get_name( ) );
00516
00517
00518
00519
00520 if ( cmdline_name == PFILE )
00521 return;
00522
00523 string cmdline_value( cmdline.get_value( ) );
00524
00525
00526
00527
00528
00529
00530
00531
00532 if ( is_parlist( cmdline_name, cmdline_value ) )
00533 return;
00534
00535 Par* par = search_name( cmdline_name.c_str( ) );
00536
00537 if ( return_on_error )
00538
00539 par->set_val( cmdline_value.c_str( ) );
00540 else {
00541
00542 if ( EXIT_FAILURE == par->check_value( cmdline_value.c_str( ) ) ) {
00543 querry_user( par, (char*) cmdline_value.c_str( ) );
00544 } else {
00545 par->set_val( cmdline_value.c_str( ) );
00546 }
00547 }
00548
00549 } catch( ParFileException& pfe ) {
00550
00551 throw;
00552
00553 } catch( Exception& e ) {
00554
00555 throw;
00556
00557 }
00558
00559 }
00560
00561 int ParFile::traverse( int (*fct)( Par* ) ) const {
00562
00563 if ( parameters ) {
00564 size_t count = 0;
00565 while( parameters[ count ] ) {
00566 int status = (*fct)( parameters[ count++ ] );
00567 if ( 0 != status )
00568 return status;
00569 }
00570 }
00571
00572 return 0;
00573
00574 }
00575
00576 int ParFile::is_blank( const char *str ) {
00577
00578 while( isspace( *str++ ) )
00579 ;
00580
00581 return ! (*--str);
00582
00583 }
00584
00585 int ParFile::is_comment( const char* str, char delimit ) {
00586
00587
00588 while ( isspace( *str ) )
00589 str++;
00590
00595 return str[0] == delimit || ParFile::is_blank( str );
00596
00597 }
00598
00599 #undef MODE