/home/coin/SVN-release/CoinAll-1.1.0/Bcp/src/include/BCP_parameters.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 #ifndef _BCP_PARAMETERS_H
00004 #define _BCP_PARAMETERS_H
00005 
00006 // This file is fully docified.
00007 
00008 
00009 #include <utility> // for 'pair'
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   // default copy constructor and assignment operator are fine 
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   /* Type definitions. Just to make it easier to refer to types. */
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       // no need to delete anything, since the size of (almost) everything is
00198       // the same, just copy over
00199       // -- The static_cast is needed to satisfy the more picky IBM Visual Age
00200       //    C++ compiler
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       // Get the lines of the parameter file one-by-one and if a line contains
00264       // a (keyword, value) pair set the appropriate parameter
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          //------------------------ First separate the keyword and value ------
00287          // keyword = std::find_if(line, end_of_line, isgraph);
00288          for (keyword = line; keyword < end_of_line; ++keyword) {
00289             if (isgraph(*keyword))
00290                break;
00291          }
00292          if (keyword == end_of_line) // empty line
00293             continue;
00294          // ctmp = std::find_if(keyword, end_of_line, isspace);
00295          for (ctmp = keyword; ctmp < end_of_line; ++ctmp) {
00296             if (isspace(*ctmp))
00297                break;
00298          }
00299          *ctmp = 0; // terminate the keyword with a 0 character
00300          // ctmp = std::find_if(ctmp, end_of_line, isgraph);
00301          for ( ; ctmp < end_of_line; ++ctmp) {
00302             if (isgraph(*ctmp))
00303                break;
00304          }
00305          if (ctmp == end_of_line) // line is just one word. must be a comment
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          //--------------- Check if the keyword is a param file ---------------
00337          if (strcmp(keyword, "ParamFile") == 0) {
00338             read_from_file(value);
00339          }
00340 
00341          //--------------- Check if we need to be quiet -----------------------
00342          if (strcmp(keyword, "Quiet") == 0) {
00343             int val = atoi(value);
00344             quiet = (val != 0);
00345          }
00346          
00347          //--------------- Expand the value (look for keywords) ---------------
00348          std::string value_expanded = expand(value);
00349 
00350          //--------------- Find the parameter corresponding to  the keyword ---
00351          for (ind = keys.begin(); ind != keys.end(); ++ind) {
00352             if (ind->first == keyword) {
00353                // The keyword does exists
00354                // set_param(ind->second, value);    should work
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                // The keyword does exists but is obsolete
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     // std::cout << "expand( " << value << " ) : ";
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           //const char *ptr = &value[i+1];
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     // std::cout << sExpand << std::endl;
00431 
00432     return sExpand;
00433   }
00434 
00436   //---------------------------------------------------------------------------
00437 
00441     void read_from_file(const char * paramfile) {
00442       // Open the parameter file
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        // create a stream
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             // error
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       // No need to allocate the arrays, they are of fixed length
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

Generated on Sun Nov 14 14:06:29 2010 for Coin-All by  doxygen 1.4.7