Bcp 1.4.4
Loading...
Searching...
No Matches
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
47
48//-----------------------------------------------------------------------------
49
53
54private:
58 BCP_parameter_t _type;
60 int _index;
63public:
64 // default copy constructor and assignment operator are fine
68 BCP_parameter() : _type(BCP_NoPar), _index(0) {}
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
113template <class Par> class BCP_parameter_set : public Par {
114private:
121 void create_keyword_list();
123 void set_default_entries();
125 //---------------------------------------------------------------------------
126
127public:
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
135private:
143 BCP_vec<BCP_string> obsolete_keys;
145 char* cpar;
147 int* ipar;
149 double* dpar;
151 BCP_string* spar;
153 BCP_vec<BCP_string>* sapar;
155 //---------------------------------------------------------------------------
156
157public:
167 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
272 printf("\
273BCP_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, "\
279There's a too long (>= %i characters) line in the parameter file.\n\
280This 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("\
376BCP_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;
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("\
509BCP_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 {
572 create_keyword_list();
573 set_default_entries();
574 }
577 delete[] cpar;
578 delete[] ipar;
579 delete[] dpar;
580 delete[] spar;
581 delete[] sapar;
582 }
584};
585
586#endif
BCP_parameter_t
This enumerative constant describes the possible parameter types.
@ BCP_NoPar
The type is not yet specified.
@ BCP_StringArrayPar
The parameter is an array of strings.
@ BCP_StringPar
String parameter.
@ BCP_IntPar
Integer parameter.
@ BCP_CharPar
Character parameter.
@ BCP_DoublePar
Double parameter.
#define BCP_STRINGSTREAM
This class describes the message buffer used for all processes of BCP.
BCP_buffer & pack(const T &value)
Pack a single object of type T.
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
Currently there isn't any error handling in BCP.
Definition BCP_error.hpp:20
This is the class serves as a holder for a set of parameters.
void set_entry(const int_params key, const int val)
void read_from_file(const char *paramfile)
Simply invoke reading from a stream.
BCP_parameter_set< Par > & operator=(const BCP_parameter_set< Par > &x)
void pack(BCP_buffer &buf)
Pack the parameter set into the buffer.
Par::chr_params chr_params
Par::dbl_params dbl_params
void write_to_stream(std::ostream &outstream) const
Write keyword-value pairs to the stream specified in the argument.
double entry(const dbl_params key) const
BCP_parameter_set()
The default constructor creates a parameter set with from the template argument structure.
std::string expand(const char *value)
void read_from_stream(std::istream &parstream)
Read the parameters from the stream specified in the argument.
Par::int_params int_params
void set_entry(const str_array_params key, const char *val)
void set_entry(const str_params key, const char *val)
const BCP_string & entry(const str_params key) const
~BCP_parameter_set()
The destructor deletes all data members.
char entry(const chr_params key) const
void set_entry(const chr_params key, const char val)
const BCP_vec< BCP_string > & entry(const str_array_params key) const
Par::str_array_params str_array_params
Par::str_params str_params
void unpack(BCP_buffer &buf)
Unpack the parameter set from the buffer.
void set_entry(const chr_params key, const bool val)
void set_entry(const dbl_params key, const double val)
int entry(const int_params key) const
void set_entry(const BCP_parameter key, const char *val)
void read_from_arglist(const int argnum, const char *const *arglist)
Simply invoke reading from a stream.
This parameter indeintifies a single parameter entry.
~BCP_parameter()
The destructor.
BCP_parameter()
The default constructor creates a phony parameter.
int index() const
Return the index of the parameter within all parameters of the same type.
BCP_parameter(const BCP_parameter_t t, const int i)
Constructor where members are specified.
BCP_parameter_t type() const
Return the type of the parameter.
This class is a very simple impelementation of a constant length string.
const char * c_str() const
Abstract base class that defines members common to all types of variables.
Definition BCP_var.hpp:28
The class BCP_vec serves the same purpose as the vector class in the standard template library.
void push_back(const_reference x)
Append x to the end of the vector.
void unchecked_push_back(const_reference x)
Append x to the end of the vector.
iterator end()
Return an iterator to the end of the object.
size_t size() const
Return the current number of entries.
iterator begin()
Return an iterator to the beginning of the object.
void reserve(const size_t n)
Reallocate the object to make space for n entries.