FEDEM Solver  R8.0
Source code of the dynamics solver
FFaCmdLineArg.H
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2023 SAP SE
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 //
5 // This file is part of FEDEM - https://openfedem.org
7 
13 #ifndef FFA_CMD_LINE_ARG_H
14 #define FFA_CMD_LINE_ARG_H
15 
16 #include <string>
17 #include <vector>
18 #include <map>
19 #include <iostream>
20 #include <sstream>
21 #include <cstdlib>
22 #include <cctype>
23 
24 
30 {
31 protected:
33  FFaCmdLineEntryBase(const std::string& text, bool showToAll)
34  : myHelpText(text), iAmSetOnCmdLine(false), isPublic(showToAll) {}
35 
36 public:
38  virtual ~FFaCmdLineEntryBase() {}
40  virtual bool hasValue() const = 0;
42  virtual bool hasDefault() const = 0;
44  virtual int convertOption(const std::string&) = 0;
46  virtual std::string getDefaultString() const = 0;
48  virtual std::string getValueString(bool = false) const = 0;
50  virtual void reset() = 0;
51 
52 protected:
53  std::string myHelpText;
55  bool isPublic;
56 
57  friend class FFaCmdLineArg;
58 };
59 
60 
65 template<class T> class FFaCmdLineEntry : public FFaCmdLineEntryBase
66 {
67 public:
69  FFaCmdLineEntry(const std::string& text, const T& value, bool showToAll)
70  : FFaCmdLineEntryBase(text,showToAll), myValue(value), myDefault(value) {}
72  virtual ~FFaCmdLineEntry() {}
73 
75  virtual bool hasValue() const { return true; }
77  virtual bool hasDefault() const { return true; }
78 
80  virtual int convertOption(const std::string&) { return -1; }
81 
83  virtual std::string getDefaultString() const
84  {
85  return this->toString(myDefault);
86  }
87 
89  virtual std::string getValueString(bool noDefaults) const
90  {
91  if (noDefaults && !iAmSetOnCmdLine)
92  return std::string();
93 
94  return this->toString(myValue);
95  }
96 
98  const T& getValue() const { return myValue; }
99 
101  virtual void reset() { myValue = myDefault; iAmSetOnCmdLine = false; }
102 
103 protected:
105  virtual std::string toString(const T& value) const
106  {
107  std::stringstream sval;
108  sval << value;
109  return sval.str();
110  }
111 
112 private:
115 };
116 
117 
123 {
125  typedef std::map<std::string,FFaCmdLineEntryBase*> OptionMap;
126 
127 private:
129  FFaCmdLineArg();
131  ~FFaCmdLineArg();
132 
133 public:
135  static void init(int argc, char** argv) { instance()->initArgs(argc,argv); }
137  static bool empty();
139  static FFaCmdLineArg* instance();
141  static void removeInstance();
142 
148  template<class T> void addOption(const std::string& identifier,
149  const T& value,
150  const std::string& helpText,
151  bool showToAll = true)
152  {
153  // In case the same option is defined twice, avoid memory leak
154  OptionMap::iterator it = myOptions.find(identifier);
155  if (it != myOptions.end()) delete it->second;
156 
157  myOptions[identifier] = new FFaCmdLineEntry<T>(helpText,value,showToAll);
158  }
159 
165  void addOption(const std::string& identifier,
166  const char* value,
167  const std::string& helpText,
168  bool showToAll = true)
169  {
170  this->addOption(identifier,std::string(value),helpText,showToAll);
171  }
172 
177  template<class T> bool getValue(const std::string& identifier, T& aVal)
178  {
179  this->evaluate();
180 
181  OptionMap::const_iterator opIt = myOptions.find(identifier);
182  if (opIt != myOptions.end())
183  {
184  FFaCmdLineEntry<T>* obj = dynamic_cast<FFaCmdLineEntry<T>*>(opIt->second);
185  if (obj)
186  {
187  aVal = obj->getValue();
188  return true;
189  }
190  }
191 
192  if (!mute)
193  std::cerr <<" *** Could not evaluate command-line option \""
194  << identifier <<"\""<< std::endl;
195  return false;
196  }
197 
202  bool setValue(const std::string& identifier, const std::string& value);
203 
207  void composeHelpText(std::string& report, bool all = false) const;
209  void composeSingleLineHelpText(std::string& report, bool all = false) const;
212  void listOptions(bool noDefaults = false) const;
214  bool isOptionSetOnCmdLine(const std::string& identifier);
216  bool readOptionsFile(const std::string& fileName);
217 
219  static std::string additionalHelpText;
220 
221  static bool mute;
222 
223 private:
225  void initArgs(int argc, char** argv);
227  void evaluate();
228 
229  std::vector<std::string> myArgs;
231 
233 };
234 
235 
237 // Template specializations
239 
240 typedef std::vector<int> IntVec;
241 typedef std::vector<double> DoubleVec;
242 
243 
248 template<> inline
250 {
251  return !myValue.empty();
252 }
253 
258 template<> inline
260 {
261  return !myDefault.empty();
262 }
263 
264 
270 template<> inline
272 {
273  return !myDefault.empty();
274 }
275 
276 
282 template<> inline
284 {
285  return !myDefault.empty();
286 }
287 
288 
293 template<> inline
295 {
296  return myDefault;
297 }
298 
303 template<> inline
304 std::string FFaCmdLineEntry<std::string>::getValueString(bool noDefaults) const
305 {
306  if (noDefaults && myValue == myDefault)
307  return std::string();
308 
309  return myValue;
310 }
311 
312 
317 template<> inline
319 {
320  return std::string(myDefault ? "+ (true)" : "- (false)");
321 }
322 
323 
328 template<> inline
329 std::string FFaCmdLineEntry<bool>::getValueString(bool noDefaults) const
330 {
331  if (noDefaults && myValue == myDefault)
332  return std::string();
333 
334  return std::string(myValue ? "+ (true)" : "- (false)");
335 }
336 
337 
342 template<> inline
343 int FFaCmdLineEntry<int>::convertOption(const std::string& value)
344 {
345  if (value.empty())
346  return 0;
347 
348  char* endPtr;
349  long int aval = strtol(value.c_str(),&endPtr,10);
350  if (*endPtr) return 1 + (endPtr - value.c_str());
351 
352  myValue = (int)aval;
353  iAmSetOnCmdLine = true;
354  return 0;
355 }
356 
357 
362 template<> inline
363 int FFaCmdLineEntry<float>::convertOption(const std::string& value)
364 {
365  if (value.empty())
366  return 0;
367 
368  char* endPtr;
369  float aval = strtof(value.c_str(),&endPtr);
370  if (*endPtr) return 1 + (endPtr - value.c_str());
371 
372  myValue = aval;
373  iAmSetOnCmdLine = true;
374  return 0;
375 }
376 
377 
382 template<> inline
383 int FFaCmdLineEntry<double>::convertOption(const std::string& value)
384 {
385  if (value.empty())
386  return 0;
387 
388  char* endPtr;
389  double aval = strtod(value.c_str(),&endPtr);
390  if (*endPtr) return 1 + (endPtr - value.c_str());
391 
392  myValue = aval;
393  iAmSetOnCmdLine = true;
394  return 0;
395 }
396 
397 
402 template<> inline
403 int FFaCmdLineEntry<IntVec>::convertOption(const std::string& value)
404 {
405  myValue.clear();
406  if (value.empty())
407  return 0;
408 
409  char* endPtr;
410  long int aval = strtol(value.c_str(),&endPtr,10);
411  while (*endPtr)
412  {
413  char* next = endPtr;
414  if (!isdigit(next[0]) && !isspace(next[0]) &&
415  next[0] != '-' && next[0] != '+')
416  return 1 + (endPtr - value.c_str());
417 
418  myValue.push_back((int)aval);
419  aval = strtol(next,&endPtr,10);
420  }
421 
422  myValue.push_back(aval);
423  iAmSetOnCmdLine = true;
424  return 0;
425 }
426 
427 
432 template<> inline
433 int FFaCmdLineEntry<DoubleVec>::convertOption(const std::string& value)
434 {
435  myValue.clear();
436  if (value.empty())
437  return 0;
438 
439  char* endPtr;
440  double aval = strtod(value.c_str(),&endPtr);
441  while (*endPtr)
442  {
443  char* next = endPtr;
444  if (!isdigit(next[0]) && !isspace(next[0]) &&
445  next[0] != '-' && next[0] != '+' && next[0] != '.')
446  return 1 + (endPtr - value.c_str());
447 
448  myValue.push_back(aval);
449  aval = strtod(next,&endPtr);
450  }
451 
452  myValue.push_back(aval);
453  iAmSetOnCmdLine = true;
454  return 0;
455 }
456 
457 
462 template<class T> inline
463 std::string vec2string(const std::vector<T>& value)
464 {
465  if (value.empty())
466  return "";
467 
468  std::stringstream sval;
469  sval << value.front();
470  for (size_t i = 1; i < value.size(); i++)
471  sval <<" "<< value[i];
472 
473  return sval.str();
474 }
475 
480 template<> inline
481 std::string FFaCmdLineEntry<IntVec>::toString(const IntVec& value) const
482 {
483  return vec2string(value);
484 }
485 
490 template<> inline
491 std::string FFaCmdLineEntry<DoubleVec>::toString(const DoubleVec& value) const
492 {
493  return vec2string(value);
494 }
495 
496 
501 template<> inline
502 int FFaCmdLineEntry<std::string>::convertOption(const std::string& value)
503 {
504  if (value.empty())
505  return 0;
506 
507  myValue = value;
508  if (myValue.size() > 1)
509  {
510  // remove fnutts if they are first and last in the string:
511  if (*myValue.begin() == '"') myValue.erase(myValue.begin());
512  if (*myValue.rbegin() == '"') myValue.erase(myValue.end()-1);
513  }
514  iAmSetOnCmdLine = true;
515  return 0;
516 }
517 
518 
523 template<> inline
524 int FFaCmdLineEntry<bool>::convertOption(const std::string& value)
525 {
526  if (value.empty())
527  myValue = true;
528  else if (value.size() != 1)
529  return false;
530  else if (value == "+")
531  myValue = true;
532  else if (value == "-")
533  myValue = false;
534  else
535  return 1;
536 
537  iAmSetOnCmdLine = true;
538  return 0;
539 }
540 
541 
546 template<class T> inline
547 const std::vector<T>& complDefault(const std::vector<T>& value,
548  const std::vector<T>& defval)
549 {
550  if (value.empty())
551  return defval;
552  else if (value.size() >= defval.size())
553  return value;
554 
555  static std::vector<T> tmp;
556  tmp.assign(value.begin(),value.end());
557  tmp.insert(tmp.end(),defval.begin()+value.size(),defval.end());
558  return tmp;
559 }
560 
565 template<> inline
567 {
568  return complDefault(myValue,myDefault);
569 }
570 
575 template<> inline
577 {
578  return complDefault(myValue,myDefault);
579 }
580 
581 #endif
std::vector< double > DoubleVec
Convenience type definition.
Definition: FFaCmdLineArg.H:241
std::vector< int > IntVec
Convenience type definition.
Definition: FFaCmdLineArg.H:240
std::string vec2string(const std::vector< T > &value)
Helper function converting a vector of something to a string.
Definition: FFaCmdLineArg.H:463
const std::vector< T > & complDefault(const std::vector< T > &value, const std::vector< T > &defval)
Helper function completing a vector-valued option value from defaults.
Definition: FFaCmdLineArg.H:547
Singleton class for management of command-line options.
Definition: FFaCmdLineArg.H:123
bool readOptionsFile(const std::string &fileName)
Reads command-line option values from the file fileName.
Definition: FFaCmdLineArgImplementation.C:334
static std::string additionalHelpText
This text is printed after the option list itself when using "-help".
Definition: FFaCmdLineArg.H:219
static FFaCmdLineArg * instance()
Returns the one and only instance of this class.
Definition: FFaCmdLineArgImplementation.C:89
std::vector< std::string > myArgs
Temporary command-line option storage.
Definition: FFaCmdLineArg.H:229
static void init(int argc, char **argv)
Initializes the command-line options singleton object.
Definition: FFaCmdLineArg.H:135
static bool empty()
Returns true if no command-line options have been defined.
Definition: FFaCmdLineArgImplementation.C:83
bool setValue(const std::string &identifier, const std::string &value)
Assigns a new value to the specified command-line option.
Definition: FFaCmdLineArgImplementation.C:115
OptionMap myOptions
Command-line options container.
Definition: FFaCmdLineArg.H:230
static void removeInstance()
Deletes the dynamically allocated instance.
Definition: FFaCmdLineArgImplementation.C:98
~FFaCmdLineArg()
The destructor deletes the allocated FFaCmdLineEntry objects.
Definition: FFaCmdLineArgImplementation.C:73
static bool mute
If true, error messages are muted.
Definition: FFaCmdLineArg.H:221
static FFaCmdLineArg * myInstance
The actual instance of this class.
Definition: FFaCmdLineArg.H:232
void addOption(const std::string &identifier, const T &value, const std::string &helpText, bool showToAll=true)
Defines a new command-line option of arbitrary type.
Definition: FFaCmdLineArg.H:148
std::map< std::string, FFaCmdLineEntryBase * > OptionMap
Data type for the command-line options container.
Definition: FFaCmdLineArg.H:125
FFaCmdLineArg()
The default constructor is private to avoid other instances.
Definition: FFaCmdLineArgImplementation.C:65
void listOptions(bool noDefaults=false) const
Prints out all specified command-line options.
Definition: FFaCmdLineArgImplementation.C:288
void composeSingleLineHelpText(std::string &report, bool all=false) const
Same as composeHelpText(), but with each option as a single line.
Definition: FFaCmdLineArgImplementation.C:251
bool isOptionSetOnCmdLine(const std::string &identifier)
Checks if an option identifier is specified on the command-line.
Definition: FFaCmdLineArgImplementation.C:319
void addOption(const std::string &identifier, const char *value, const std::string &helpText, bool showToAll=true)
Defines a new command-line option of string type.
Definition: FFaCmdLineArg.H:165
void initArgs(int argc, char **argv)
Copies all command-line arguments into a temporary container.
Definition: FFaCmdLineArgImplementation.C:105
bool getValue(const std::string &identifier, T &aVal)
Returns the actual value of the specified command-line option.
Definition: FFaCmdLineArg.H:177
void evaluate()
Processes the temporary command-line option list myArgs.
Definition: FFaCmdLineArgImplementation.C:134
void composeHelpText(std::string &report, bool all=false) const
Creates a multi-line string with a list of all defined options.
Definition: FFaCmdLineArgImplementation.C:208
Abstract interface for command-line options.
Definition: FFaCmdLineArg.H:30
virtual void reset()=0
Resets the option to its default value.
virtual bool hasValue() const =0
Checks if this option has been assigned a non-empty value.
bool iAmSetOnCmdLine
true if this option has been specified
Definition: FFaCmdLineArg.H:54
virtual std::string getValueString(bool=false) const =0
Returns a string representation of the command-line option value.
virtual int convertOption(const std::string &)=0
Converts the command-line option value from the given string.
virtual bool hasDefault() const =0
Checks if this option has been assigned a non-empty default value.
std::string myHelpText
Text description of this command-line option.
Definition: FFaCmdLineArg.H:53
virtual ~FFaCmdLineEntryBase()
Empty destructor.
Definition: FFaCmdLineArg.H:38
FFaCmdLineEntryBase(const std::string &text, bool showToAll)
The constructor initializes the class attributes.
Definition: FFaCmdLineArg.H:33
bool isPublic
true unless this option is hidden
Definition: FFaCmdLineArg.H:55
virtual std::string getDefaultString() const =0
Composes the default section of the help text for this option.
Template class for command-line options of arbitrary value type.
Definition: FFaCmdLineArg.H:66
virtual void reset()
Resets the option to its default value.
Definition: FFaCmdLineArg.H:101
virtual bool hasValue() const
Checks if this option has been assigned a non-empty value.
Definition: FFaCmdLineArg.H:75
virtual std::string getValueString(bool noDefaults) const
Returns a string representation of the command-line option value.
Definition: FFaCmdLineArg.H:89
T myValue
The assigned value of this command-line option.
Definition: FFaCmdLineArg.H:113
FFaCmdLineEntry(const std::string &text, const T &value, bool showToAll)
The constructor initializes the class attributes and option values.
Definition: FFaCmdLineArg.H:69
virtual ~FFaCmdLineEntry()
Empty destructor.
Definition: FFaCmdLineArg.H:72
virtual std::string getDefaultString() const
Composes the default section of the help text for this option.
Definition: FFaCmdLineArg.H:83
const T & getValue() const
Returns the actual command-line option value.
Definition: FFaCmdLineArg.H:98
virtual int convertOption(const std::string &)
Converts the command-line option value from the given string.
Definition: FFaCmdLineArg.H:80
virtual std::string toString(const T &value) const
Returns the string representation of the specified value.
Definition: FFaCmdLineArg.H:105
T myDefault
The default value of this command-line option.
Definition: FFaCmdLineArg.H:114
virtual bool hasDefault() const
Checks if this option has been assigned a non-empty default value.
Definition: FFaCmdLineArg.H:77