coin-Bcp
BCP_parameters.hpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 #ifndef _BCP_PARAMETERS_H
4 #define _BCP_PARAMETERS_H
5 
6 // This file is fully docified.
7 
8 
9 #include <utility> // for 'pair'
10 #include <iostream>
11 #include <fstream>
12 #include <string>
13 #include <algorithm>
14 
15 #if defined(__GNUC__) && (__GNUC__ >= 3)
16 # include <sstream>
17 # include <locale>
18 # define BCP_STRINGSTREAM std::istringstream
19 #else
20 # include <strstream>
21 # include <cctype>
22 # define BCP_STRINGSTREAM std::istrstream
23 #endif
24 
25 #include "BCP_error.hpp"
26 #include "BCP_string.hpp"
27 #include "BCP_vector.hpp"
28 #include "BCP_buffer.hpp"
29 
46 };
47 
48 //-----------------------------------------------------------------------------
49 
53 
54 private:
60  int _index;
63 public:
64  // default copy constructor and assignment operator are fine
70  BCP_parameter(const BCP_parameter_t t, const int i) :
71  _type(t), _index(i) {}
79  BCP_parameter_t type() const { return _type; }
82  int index() const { return _index; }
84 };
85 
86 //-----------------------------------------------------------------------------
87 
113 template <class Par> class BCP_parameter_set : public Par {
114 private:
121  void create_keyword_list();
123  void set_default_entries();
125  //---------------------------------------------------------------------------
126 
127 public:
128  /* Type definitions. Just to make it easier to refer to types. */
129  typedef typename Par::chr_params chr_params;
130  typedef typename Par::int_params int_params;
131  typedef typename Par::dbl_params dbl_params;
132  typedef typename Par::str_params str_params;
133  typedef typename Par::str_array_params str_array_params;
134 
135 private:
145  char* cpar;
147  int* ipar;
149  double* dpar;
155  //---------------------------------------------------------------------------
156 
157 public:
166  inline char
168  entry(const chr_params key) const { return cpar[key]; }
170  inline int
171  entry(const int_params key) const { return ipar[key]; }
173  inline double
174  entry(const dbl_params key) const { return dpar[key]; }
176  inline const BCP_string&
177  entry(const str_params key) const { return spar[key]; }
179  inline const BCP_vec<BCP_string>&
180  entry(const str_array_params key) const { return sapar[key]; }
182  //---------------------------------------------------------------------------
183 
197  // no need to delete anything, since the size of (almost) everything is
198  // the same, just copy over
199  // -- The static_cast is needed to satisfy the more picky IBM Visual Age
200  // C++ compiler
201  std::copy(x.cpar, x.cpar + static_cast<int>(Par::end_of_chr_params),
202  cpar);
203  std::copy(x.ipar, x.ipar + static_cast<int>(Par::end_of_int_params),
204  ipar);
205  std::copy(x.dpar, x.dpar + static_cast<int>(Par::end_of_dbl_params),
206  dpar);
207  std::copy(x.spar, x.spar + static_cast<int>(Par::end_of_str_params),
208  spar);
209  std::copy(x.sapar,
210  x.sapar + static_cast<int>(Par::end_of_str_array_params),
211  sapar);
212  return *this;
213  }
215  void set_entry(const chr_params key, const char val) {
216  cpar[key] = val; }
218  void set_entry(const chr_params key, const bool val) {
219  cpar[key] = val; }
221  void set_entry(const int_params key, const int val) {
222  ipar[key] = val; }
224  void set_entry(const dbl_params key, const double val) {
225  dpar[key] = val; }
227  void set_entry(const str_params key, const char * val) {
228  spar[key] = val; }
230  void set_entry(const str_array_params key, const char *val) {
231  sapar[key].push_back(val); }
233  void set_entry(const BCP_parameter key, const char * val) {
234  switch (key.type()){
235  case BCP_NoPar: break;
236  case BCP_CharPar: cpar [key.index()] = atoi(val); break;
237  case BCP_IntPar: ipar [key.index()] = atoi(val); break;
238  case BCP_DoublePar: dpar [key.index()] = atof(val); break;
239  case BCP_StringPar: spar [key.index()] = val; break;
240  case BCP_StringArrayPar: sapar[key.index()].push_back(val); break;
241  }
242  }
244  //---------------------------------------------------------------------------
245 
262  void read_from_stream(std::istream& parstream) {
263  // Get the lines of the parameter file one-by-one and if a line contains
264  // a (keyword, value) pair set the appropriate parameter
265  const int MAX_PARAM_LINE_LENGTH = 1024;
266  char line[MAX_PARAM_LINE_LENGTH], *end_of_line, *keyword, *ctmp;
267  char value[MAX_PARAM_LINE_LENGTH];
268  bool quiet = true;
269 
270  BCP_vec< std::pair<BCP_string, BCP_parameter> >::const_iterator ind;
272  printf("\
273 BCP_parameters::read_from_stream Scanning parameter stream.\n");
274  while (!parstream.eof()) {
275  parstream.getline(line, MAX_PARAM_LINE_LENGTH);
276  const int len = strlen(line);
277  if (len == MAX_PARAM_LINE_LENGTH - 1) {
278  sprintf(line, "\
279 There's a too long (>= %i characters) line in the parameter file.\n\
280 This is absurd.\n", MAX_PARAM_LINE_LENGTH);
281  throw BCP_fatal_error(line);
282  }
283 
284  end_of_line = line + len;
285 
286  //------------------------ First separate the keyword and value ------
287  // keyword = std::find_if(line, end_of_line, isgraph);
288  for (keyword = line; keyword < end_of_line; ++keyword) {
289  if (isgraph(*keyword))
290  break;
291  }
292  if (keyword == end_of_line) // empty line
293  continue;
294  // ctmp = std::find_if(keyword, end_of_line, isspace);
295  for (ctmp = keyword; ctmp < end_of_line; ++ctmp) {
296  if (isspace(*ctmp))
297  break;
298  }
299  *ctmp = 0; // terminate the keyword with a 0 character
300  // ctmp = std::find_if(ctmp, end_of_line, isgraph);
301  for ( ; ctmp < end_of_line; ++ctmp) {
302  if (isgraph(*ctmp))
303  break;
304  }
305  if (ctmp == end_of_line) // line is just one word. must be a comment
306  continue;
307 
308  int i;
309  if (*ctmp == '"') {
310  ++ctmp;
311  for (i = 0; ctmp < end_of_line; ++ctmp) {
312  if (*ctmp == '\\') {
313  if (++ctmp == end_of_line)
314  break;
315  value[i++] = *ctmp;
316  continue;
317  }
318  if (*ctmp != '"') {
319  value[i++] = *ctmp;
320  } else {
321  ++ctmp;
322  break;
323  }
324  }
325  } else {
326  for (i = 0; ctmp < end_of_line; ++ctmp) {
327  if (!isspace(*ctmp)) {
328  value[i++] = *ctmp;
329  } else {
330  break;
331  }
332  }
333  }
334  value[i] = 0;
335 
336  //--------------- Check if the keyword is a param file ---------------
337  if (strcmp(keyword, "ParamFile") == 0) {
338  read_from_file(value);
339  }
340 
341  //--------------- Check if we need to be quiet -----------------------
342  if (strcmp(keyword, "Quiet") == 0) {
343  int val = atoi(value);
344  quiet = (val != 0);
345  }
346 
347  //--------------- Expand the value (look for keywords) ---------------
348  std::string value_expanded = expand(value);
349 
350  //--------------- Find the parameter corresponding to the keyword ---
351  for (ind = keys.begin(); ind != keys.end(); ++ind) {
352  if (ind->first == keyword) {
353  // The keyword does exists
354  // set_param(ind->second, value); should work
355  if (!quiet) {
356  printf("%s %s\n", keyword, value_expanded.c_str());
357  }
358  set_entry((*ind).second, value_expanded.c_str());
359  break;
360  }
361  }
362 
363  for (obs_ind = obsolete_keys.begin();
364  obs_ind != obsolete_keys.end();
365  ++obs_ind) {
366  if (*obs_ind == keyword) {
367  // The keyword does exists but is obsolete
368  printf("***WARNING*** : Obsolete keyword `%s' is found.\n",
369  keyword);
370  break;
371  }
372  }
373  }
374  if (!quiet) {
375  printf("\
376 BCP_parameters::read_from_stream Finished scanning parameter stream.\n\n");
377  }
378  }
379 
380 
382  //---------------------------------------------------------------------------
385  std::string expand(const char* value){
386 
387  // std::cout << "expand( " << value << " ) : ";
388 
389  const int MAX_PARAM_LINE_LENGTH = 1024;
390  char valueBuf[MAX_PARAM_LINE_LENGTH];
391  bool bDollar = false;
392  int j = 0;
393  for(int i = 0; value[i] != '\0'; i++){
394  char cval = value[i];
395  if(!bDollar){
396  if(cval == '$'){
397  bDollar = true;
398  continue;
399  }
400  valueBuf[j++] = cval;
401  continue;
402  }
403  else{
404  if(cval == '('){
405  char envBuf[MAX_PARAM_LINE_LENGTH];
406  //const char *ptr = &value[i+1];
407  int k=0;
408  char c;
409  i++;
410  while((c = value[i++]) != ')' && c != '\0')
411  envBuf[k++] = c;
412  envBuf[k] = '\0';
413  char* eVal = getenv(envBuf);
414  if(eVal != NULL){
415  while(*eVal != '\0')
416  valueBuf[j++] = *eVal++;
417  }
418  bDollar = false;
419  i--;
420  } else {
421  valueBuf[j++] = '$';
422  valueBuf[j++] = cval;
423  bDollar = false;
424  }
425  }
426  }
427  valueBuf[j] = '\0';
428  std::string sExpand(valueBuf);
429 
430  // std::cout << sExpand << std::endl;
431 
432  return sExpand;
433  }
434 
436  //---------------------------------------------------------------------------
437 
441  void read_from_file(const char * paramfile) {
442  // Open the parameter file
443  std::ifstream parstream(paramfile);
444  if (!parstream)
445  throw BCP_fatal_error("Cannot open parameter file");
446  read_from_stream(parstream);
447  }
449  //---------------------------------------------------------------------------
450 
454  void read_from_arglist(const int argnum, const char * const * arglist) {
455  // create a stream
456  std::string argstring;
457  for (int i = 1; i < argnum; i += 2) {
458  argstring += arglist[i];
459  argstring += " ";
460  if (i+1 < argnum) {
461  argstring += arglist[i+1];
462  }
463  argstring += "\n";
464  }
465  BCP_STRINGSTREAM parstream(argstring.c_str());
466  read_from_stream(parstream);
467  }
469  //---------------------------------------------------------------------------
476  void write_to_stream(std::ostream& outstream) const {
477 
478  const int size = keys.size();
479  for (int i = 0; i < size; ++i) {
480  const BCP_string& key = keys[i].first;
481  const BCP_parameter& par = keys[i].second;
482  switch (par.type()) {
483  case BCP_CharPar:
484  outstream << key.c_str() << " "
485  << static_cast<int>(cpar[par.index()]) << "\n";
486  break;
487  case BCP_IntPar:
488  outstream << key.c_str() << " "
489  << ipar[par.index()] << "\n";
490  break;
491  case BCP_DoublePar:
492  outstream << key.c_str() << " "
493  << dpar[par.index()] << "\n";
494  break;
495  case BCP_StringPar:
496  outstream << key.c_str() << " "
497  << spar[par.index()].c_str() << "\n";
498  break;
499  case BCP_StringArrayPar:
500  for (size_t j = 0; j < sapar[par.index()].size(); ++j) {
501  outstream << key.c_str() << " "
502  << sapar[par.index()][j].c_str() << "\n";
503  }
504  break;
505  case BCP_NoPar:
506  default:
507  // error
508  throw BCP_fatal_error("\
509 BCP_parameters::write_to_stream ERROR: Unrecognized parameter type!\n");
510  break;
511  }
512 
513  }
514 
515  }
516 
517  //---------------------------------------------------------------------------
518 
522  void pack(BCP_buffer& buf) {
523  buf.pack(cpar, Par::end_of_chr_params)
524  .pack(ipar, Par::end_of_int_params)
525  .pack(dpar, Par::end_of_dbl_params);
526  for (int i = 0; i < Par::end_of_str_params; ++i)
527  buf.pack(spar[i]);
528  for (int i = 0; i < Par::end_of_str_array_params; ++i) {
529  buf.pack(sapar[i].size());
530  for (size_t j = 0; j < sapar[i].size(); ++j)
531  buf.pack(sapar[i][j]);
532  }
533  }
535  void unpack(BCP_buffer& buf) {
536  int dummy;
537  // No need to allocate the arrays, they are of fixed length
538  dummy = static_cast<int>(Par::end_of_chr_params);
539  buf.unpack(cpar, dummy, false);
540  dummy = static_cast<int>(Par::end_of_int_params);
541  buf.unpack(ipar, dummy, false);
542  dummy = static_cast<int>(Par::end_of_dbl_params);
543  buf.unpack(dpar, dummy, false);
544  for (int i = 0; i < Par::end_of_str_params; ++i)
545  buf.unpack(spar[i]);
546  for (int i = 0; i < Par::end_of_str_array_params; ++i) {
547  size_t str_size;
548  buf.unpack(str_size);
549  sapar[i].reserve(str_size);
550  for (size_t j = 0; j < str_size; ++j){
552  buf.unpack(sapar[i].back());
553  }
554  }
555  }
557  //---------------------------------------------------------------------------
558 
565  keys(),
566  cpar(new char[static_cast<int>(Par::end_of_chr_params)+1]),
567  ipar(new int[static_cast<int>(Par::end_of_int_params)+1]),
568  dpar(new double[static_cast<int>(Par::end_of_dbl_params)+1]),
569  spar(new BCP_string[static_cast<int>(Par::end_of_str_params)+1]),
570  sapar(new BCP_vec<BCP_string>[static_cast<int>(Par::end_of_str_array_params)+1])
571  {
574  }
577  delete[] cpar;
578  delete[] ipar;
579  delete[] dpar;
580  delete[] spar;
581  delete[] sapar;
582  }
584 };
585 
586 #endif
Par::dbl_params dbl_params
const BCP_vec< BCP_string > & entry(const str_array_params key) const
BCP_vec< BCP_string > obsolete_keys
list of obsolete keywords.
BCP_buffer & pack(const T &value)
Pack a single object of type T.
Definition: BCP_buffer.hpp:177
std::string expand(const char *value)
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
Definition: BCP_buffer.hpp:186
Character parameter.
void create_keyword_list()
Method for creating the list of keyword looked for in the parameter file.
Double parameter.
dbl_params
Double parameters.
char entry(const chr_params key) const
const char * c_str() const
Definition: BCP_string.hpp:19
void set_entry(const BCP_parameter key, const char *val)
The parameter is an array of strings.
Par::str_params str_params
iterator begin()
Return an iterator to the beginning of the object.
Definition: BCP_vector.hpp:99
BCP_parameter_set()
The default constructor creates a parameter set with from the template argument structure.
void set_entry(const dbl_params key, const double val)
#define BCP_STRINGSTREAM
int * ipar
The integer parameters.
void set_default_entries()
Method for setting the default values for the parameters.
void reserve(const size_t n)
Reallocate the object to make space for n entries.
void read_from_arglist(const int argnum, const char *const *arglist)
Simply invoke reading from a stream.
BCP_vec< std::pair< BCP_string, BCP_parameter > > keys
The keyword, parameter pairs.
This class is a very simple impelementation of a constant length string.
Definition: BCP_string.hpp:13
void write_to_stream(std::ostream &outstream) const
Write keyword-value pairs to the stream specified in the argument.
String parameter.
void push_back(const_reference x)
Append x to the end of the vector.
chr_params
Character parameters.
BCP_string * spar
The string (actually, BCP_string) parameters.
void set_entry(const int_params key, const int val)
void read_from_stream(std::istream &parstream)
Read the parameters from the stream specified in the argument.
This is the class serves as a holder for a set of parameters.
Par::int_params int_params
int entry(const int_params key) const
const BCP_string & entry(const str_params key) const
~BCP_parameter_set()
The destructor deletes all data members.
BCP_vec< BCP_string > * sapar
The string array parameters.
Par::str_array_params str_array_params
void read_from_file(const char *paramfile)
Simply invoke reading from a stream.
void set_entry(const str_params key, const char *val)
void set_entry(const chr_params key, const char val)
BCP_parameter_t type() const
Return the type of the parameter.
str_array_params
???
int _index
The index of this parameter within all parameters of the same type.
BCP_parameter_t _type
The type of the parameter (e.g., BCP_IntPar).
This parameter indeintifies a single parameter entry.
BCP_parameter(const BCP_parameter_t t, const int i)
Constructor where members are specified.
BCP_parameter()
The default constructor creates a phony parameter.
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
char * cpar
The character parameters.
int_params
Integer parameters.
void set_entry(const chr_params key, const bool val)
size_t size() const
Return the current number of entries.
Definition: BCP_vector.hpp:116
iterator end()
Return an iterator to the end of the object.
Definition: BCP_vector.hpp:104
The class BCP_vec serves the same purpose as the vector class in the standard template library...
Definition: BCP_vector.hpp:24
This class describes the message buffer used for all processes of BCP.
Definition: BCP_buffer.hpp:39
void unchecked_push_back(const_reference x)
Append x to the end of the vector.
BCP_parameter_t
This enumerative constant describes the possible parameter types.
~BCP_parameter()
The destructor.
void unpack(BCP_buffer &buf)
Unpack the parameter set from the buffer.
Integer parameter.
double entry(const dbl_params key) const
int index() const
Return the index of the parameter within all parameters of the same type.
Par::chr_params chr_params
void pack(BCP_buffer &buf)
Pack the parameter set into the buffer.
void set_entry(const str_array_params key, const char *val)
str_params
String parameters.
The type is not yet specified.
double * dpar
The double parameters.
BCP_parameter_set< Par > & operator=(const BCP_parameter_set< Par > &x)