00001
00002
00003 #ifndef _BCP_PARAMETERS_H
00004 #define _BCP_PARAMETERS_H
00005
00006
00007
00008
00009 #include <utility>
00010 #include <iostream>
00011 #include <fstream>
00012 #include <string>
00013 #include <algorithm>
00014
00015 #if defined(__GNUC__) && (__GNUC__ >= 3)
00016 # include <sstream>
00017 # include <locale>
00018 # define BCP_STRINGSTREAM std::istringstream
00019 #else
00020 # include <strstream>
00021 # include <cctype>
00022 # define BCP_STRINGSTREAM std::istrstream
00023 #endif
00024
00025 #include "BCP_error.hpp"
00026 #include "BCP_string.hpp"
00027 #include "BCP_vector.hpp"
00028 #include "BCP_buffer.hpp"
00029
00031 enum BCP_parameter_t{
00034 BCP_NoPar,
00036 BCP_CharPar,
00038 BCP_IntPar,
00040 BCP_DoublePar,
00042 BCP_StringPar,
00045 BCP_StringArrayPar
00046 };
00047
00048
00049
00052 class BCP_parameter {
00053
00054 private:
00058 BCP_parameter_t _type;
00060 int _index;
00063 public:
00064
00068 BCP_parameter() : _type(BCP_NoPar), _index(0) {}
00070 BCP_parameter(const BCP_parameter_t t, const int i) :
00071 _type(t), _index(i) {}
00073 ~BCP_parameter() {}
00079 BCP_parameter_t type() const { return _type; }
00082 int index() const { return _index; }
00084 };
00085
00086
00087
00113 template <class Par> class BCP_parameter_set : public Par {
00114 private:
00121 void create_keyword_list();
00123 void set_default_entries();
00125
00126
00127 public:
00128
00129 typedef typename Par::chr_params chr_params;
00130 typedef typename Par::int_params int_params;
00131 typedef typename Par::dbl_params dbl_params;
00132 typedef typename Par::str_params str_params;
00133 typedef typename Par::str_array_params str_array_params;
00134
00135 private:
00140 BCP_vec< std::pair<BCP_string, BCP_parameter> > keys;
00143 BCP_vec<BCP_string> obsolete_keys;
00145 char* cpar;
00147 int* ipar;
00149 double* dpar;
00151 BCP_string* spar;
00153 BCP_vec<BCP_string>* sapar;
00155
00156
00157 public:
00166
00167 inline char
00168 entry(const chr_params key) const { return cpar[key]; }
00170 inline int
00171 entry(const int_params key) const { return ipar[key]; }
00173 inline double
00174 entry(const dbl_params key) const { return dpar[key]; }
00176 inline const BCP_string&
00177 entry(const str_params key) const { return spar[key]; }
00179 inline const BCP_vec<BCP_string>&
00180 entry(const str_array_params key) const { return sapar[key]; }
00182
00183
00195
00196 BCP_parameter_set<Par>& operator=(const BCP_parameter_set<Par>& x) {
00197
00198
00199
00200
00201 std::copy(x.cpar, x.cpar + static_cast<int>(Par::end_of_chr_params),
00202 cpar);
00203 std::copy(x.ipar, x.ipar + static_cast<int>(Par::end_of_int_params),
00204 ipar);
00205 std::copy(x.dpar, x.dpar + static_cast<int>(Par::end_of_dbl_params),
00206 dpar);
00207 std::copy(x.spar, x.spar + static_cast<int>(Par::end_of_str_params),
00208 spar);
00209 std::copy(x.sapar,
00210 x.sapar + static_cast<int>(Par::end_of_str_array_params),
00211 sapar);
00212 return *this;
00213 }
00215 void set_entry(const chr_params key, const char val) {
00216 cpar[key] = val; }
00218 void set_entry(const chr_params key, const bool val) {
00219 cpar[key] = val; }
00221 void set_entry(const int_params key, const int val) {
00222 ipar[key] = val; }
00224 void set_entry(const dbl_params key, const double val) {
00225 dpar[key] = val; }
00227 void set_entry(const str_params key, const char * val) {
00228 spar[key] = val; }
00230 void set_entry(const str_array_params key, const char *val) {
00231 sapar[key].push_back(val); }
00233 void set_entry(const BCP_parameter key, const char * val) {
00234 switch (key.type()){
00235 case BCP_NoPar: break;
00236 case BCP_CharPar: cpar [key.index()] = atoi(val); break;
00237 case BCP_IntPar: ipar [key.index()] = atoi(val); break;
00238 case BCP_DoublePar: dpar [key.index()] = atof(val); break;
00239 case BCP_StringPar: spar [key.index()] = val; break;
00240 case BCP_StringArrayPar: sapar[key.index()].push_back(val); break;
00241 }
00242 }
00244
00245
00262 void read_from_stream(std::istream& parstream) {
00263
00264
00265 const int MAX_PARAM_LINE_LENGTH = 1024;
00266 char line[MAX_PARAM_LINE_LENGTH], *end_of_line, *keyword, *ctmp;
00267 char value[MAX_PARAM_LINE_LENGTH];
00268 bool quiet = true;
00269
00270 BCP_vec< std::pair<BCP_string, BCP_parameter> >::const_iterator ind;
00271 BCP_vec<BCP_string>::const_iterator obs_ind;
00272 printf("\
00273 BCP_parameters::read_from_stream Scanning parameter stream.\n");
00274 while (!parstream.eof()) {
00275 parstream.getline(line, MAX_PARAM_LINE_LENGTH);
00276 const int len = strlen(line);
00277 if (len == MAX_PARAM_LINE_LENGTH - 1) {
00278 sprintf(line, "\
00279 There's a too long (>= %i characters) line in the parameter file.\n\
00280 This is absurd.\n", MAX_PARAM_LINE_LENGTH);
00281 throw BCP_fatal_error(line);
00282 }
00283
00284 end_of_line = line + len;
00285
00286
00287
00288 for (keyword = line; keyword < end_of_line; ++keyword) {
00289 if (isgraph(*keyword))
00290 break;
00291 }
00292 if (keyword == end_of_line)
00293 continue;
00294
00295 for (ctmp = keyword; ctmp < end_of_line; ++ctmp) {
00296 if (isspace(*ctmp))
00297 break;
00298 }
00299 *ctmp = 0;
00300
00301 for ( ; ctmp < end_of_line; ++ctmp) {
00302 if (isgraph(*ctmp))
00303 break;
00304 }
00305 if (ctmp == end_of_line)
00306 continue;
00307
00308 int i;
00309 if (*ctmp == '"') {
00310 ++ctmp;
00311 for (i = 0; ctmp < end_of_line; ++ctmp) {
00312 if (*ctmp == '\\') {
00313 if (++ctmp == end_of_line)
00314 break;
00315 value[i++] = *ctmp;
00316 continue;
00317 }
00318 if (*ctmp != '"') {
00319 value[i++] = *ctmp;
00320 } else {
00321 ++ctmp;
00322 break;
00323 }
00324 }
00325 } else {
00326 for (i = 0; ctmp < end_of_line; ++ctmp) {
00327 if (!isspace(*ctmp)) {
00328 value[i++] = *ctmp;
00329 } else {
00330 break;
00331 }
00332 }
00333 }
00334 value[i] = 0;
00335
00336
00337 if (strcmp(keyword, "ParamFile") == 0) {
00338 read_from_file(value);
00339 }
00340
00341
00342 if (strcmp(keyword, "Quiet") == 0) {
00343 int val = atoi(value);
00344 quiet = (val != 0);
00345 }
00346
00347
00348 std::string value_expanded = expand(value);
00349
00350
00351 for (ind = keys.begin(); ind != keys.end(); ++ind) {
00352 if (ind->first == keyword) {
00353
00354
00355 if (!quiet) {
00356 printf("%s %s\n", keyword, value_expanded.c_str());
00357 }
00358 set_entry((*ind).second, value_expanded.c_str());
00359 break;
00360 }
00361 }
00362
00363 for (obs_ind = obsolete_keys.begin();
00364 obs_ind != obsolete_keys.end();
00365 ++obs_ind) {
00366 if (*obs_ind == keyword) {
00367
00368 printf("***WARNING*** : Obsolete keyword `%s' is found.\n",
00369 keyword);
00370 break;
00371 }
00372 }
00373 }
00374 if (!quiet) {
00375 printf("\
00376 BCP_parameters::read_from_stream Finished scanning parameter stream.\n\n");
00377 }
00378 }
00379
00380
00382
00385 std::string expand(const char* value){
00386
00387
00388
00389 const int MAX_PARAM_LINE_LENGTH = 1024;
00390 char valueBuf[MAX_PARAM_LINE_LENGTH];
00391 bool bDollar = false;
00392 int j = 0;
00393 for(int i = 0; value[i] != '\0'; i++){
00394 char cval = value[i];
00395 if(!bDollar){
00396 if(cval == '$'){
00397 bDollar = true;
00398 continue;
00399 }
00400 valueBuf[j++] = cval;
00401 continue;
00402 }
00403 else{
00404 if(cval == '('){
00405 char envBuf[MAX_PARAM_LINE_LENGTH];
00406
00407 int k=0;
00408 char c;
00409 i++;
00410 while((c = value[i++]) != ')' && c != '\0')
00411 envBuf[k++] = c;
00412 envBuf[k] = '\0';
00413 char* eVal = getenv(envBuf);
00414 if(eVal != NULL){
00415 while(*eVal != '\0')
00416 valueBuf[j++] = *eVal++;
00417 }
00418 bDollar = false;
00419 i--;
00420 } else {
00421 valueBuf[j++] = '$';
00422 valueBuf[j++] = cval;
00423 bDollar = false;
00424 }
00425 }
00426 }
00427 valueBuf[j] = '\0';
00428 std::string sExpand(valueBuf);
00429
00430
00431
00432 return sExpand;
00433 }
00434
00436
00437
00441 void read_from_file(const char * paramfile) {
00442
00443 std::ifstream parstream(paramfile);
00444 if (!parstream)
00445 throw BCP_fatal_error("Cannot open parameter file");
00446 read_from_stream(parstream);
00447 }
00449
00450
00454 void read_from_arglist(const int argnum, const char * const * arglist) {
00455
00456 std::string argstring;
00457 for (int i = 1; i < argnum; i += 2) {
00458 argstring += arglist[i];
00459 argstring += " ";
00460 if (i+1 < argnum) {
00461 argstring += arglist[i+1];
00462 }
00463 argstring += "\n";
00464 }
00465 BCP_STRINGSTREAM parstream(argstring.c_str());
00466 read_from_stream(parstream);
00467 }
00469
00476 void write_to_stream(std::ostream& outstream) const {
00477
00478 const int size = keys.size();
00479 for (int i = 0; i < size; ++i) {
00480 const BCP_string& key = keys[i].first;
00481 const BCP_parameter& par = keys[i].second;
00482 switch (par.type()) {
00483 case BCP_CharPar:
00484 outstream << key.c_str() << " "
00485 << static_cast<int>(cpar[par.index()]) << "\n";
00486 break;
00487 case BCP_IntPar:
00488 outstream << key.c_str() << " "
00489 << ipar[par.index()] << "\n";
00490 break;
00491 case BCP_DoublePar:
00492 outstream << key.c_str() << " "
00493 << dpar[par.index()] << "\n";
00494 break;
00495 case BCP_StringPar:
00496 outstream << key.c_str() << " "
00497 << spar[par.index()].c_str() << "\n";
00498 break;
00499 case BCP_StringArrayPar:
00500 for (size_t j = 0; j < sapar[par.index()].size(); ++j) {
00501 outstream << key.c_str() << " "
00502 << sapar[par.index()][j].c_str() << "\n";
00503 }
00504 break;
00505 case BCP_NoPar:
00506 default:
00507
00508 throw BCP_fatal_error("\
00509 BCP_parameters::write_to_stream ERROR: Unrecognized parameter type!\n");
00510 break;
00511 }
00512
00513 }
00514
00515 }
00516
00517
00518
00522 void pack(BCP_buffer& buf) {
00523 buf.pack(cpar, Par::end_of_chr_params)
00524 .pack(ipar, Par::end_of_int_params)
00525 .pack(dpar, Par::end_of_dbl_params);
00526 for (int i = 0; i < Par::end_of_str_params; ++i)
00527 buf.pack(spar[i]);
00528 for (int i = 0; i < Par::end_of_str_array_params; ++i) {
00529 buf.pack(sapar[i].size());
00530 for (size_t j = 0; j < sapar[i].size(); ++j)
00531 buf.pack(sapar[i][j]);
00532 }
00533 }
00535 void unpack(BCP_buffer& buf) {
00536 int dummy;
00537
00538 dummy = static_cast<int>(Par::end_of_chr_params);
00539 buf.unpack(cpar, dummy, false);
00540 dummy = static_cast<int>(Par::end_of_int_params);
00541 buf.unpack(ipar, dummy, false);
00542 dummy = static_cast<int>(Par::end_of_dbl_params);
00543 buf.unpack(dpar, dummy, false);
00544 for (int i = 0; i < Par::end_of_str_params; ++i)
00545 buf.unpack(spar[i]);
00546 for (int i = 0; i < Par::end_of_str_array_params; ++i) {
00547 size_t str_size;
00548 buf.unpack(str_size);
00549 sapar[i].reserve(str_size);
00550 for (size_t j = 0; j < str_size; ++j){
00551 sapar[i].unchecked_push_back(BCP_string());
00552 buf.unpack(sapar[i].back());
00553 }
00554 }
00555 }
00557
00558
00564 BCP_parameter_set() :
00565 keys(),
00566 cpar(new char[static_cast<int>(Par::end_of_chr_params)]),
00567 ipar(new int[static_cast<int>(Par::end_of_int_params)]),
00568 dpar(new double[static_cast<int>(Par::end_of_dbl_params)]),
00569 spar(new BCP_string[static_cast<int>(Par::end_of_str_params)]),
00570 sapar(new BCP_vec<BCP_string>[static_cast<int>(Par::end_of_str_array_params)])
00571 {
00572 create_keyword_list();
00573 set_default_entries();
00574 }
00576 ~BCP_parameter_set() {
00577 delete[] cpar;
00578 delete[] ipar;
00579 delete[] dpar;
00580 delete[] spar;
00581 delete[] sapar;
00582 }
00584 };
00585
00586 #endif