goptions
goption.cc
Go to the documentation of this file.
1 // goptions
2 #include "goption.h"
3 #include "goptionsConventions.h"
4 
5 // gemc
6 #include "gutilities.h"
7 
8 // c++
9 #include <iostream>
10 
11 using namespace std;
12 
21  void GOption::set_scalar_value(const string &v) {
22 
23  if (v.empty()) return;
24 
25  string value_to_set = gutilities::replaceCharInStringWithChars(v, ",", "");
26 
27  string key = value.begin()->first.as<string>();
28  value[key] = value_to_set;
29 }
30 
31 void GOption::set_value(const YAML::Node &v) {
40 
41  // if the option is cumulative,
42  if (isCumulative) {
43 
44  // Sequence of maps: checks for missing mandatory values
45  for (const auto &element: v) {
46  if (!does_the_option_set_all_necessary_values(element)) {
47  cerr << FATALERRORL << "Trying to set " << YELLOWHHL << name << RSTHHR << " but missing mandatory values." << endl;
48  cerr << " Use the option: " << YELLOWHHL << " help " << name << " " << RSTHHR << " for details." << endl << endl;
50  }
51  }
52 
53  value[name] = v;
54 
55  // Copy keys from the defaultValue map to the value map if they do not exist
56  auto default_value_node = defaultValue.begin()->second;
57 
58  for (const auto &map_element_in_default_value: default_value_node) {
59  for (YAML::const_iterator default_value_iterator = map_element_in_default_value.begin();
60  default_value_iterator != map_element_in_default_value.end(); ++default_value_iterator) {
61 
62  string default_key = default_value_iterator->first.as<string>();
63  auto default_value = default_value_iterator->second;
64 
65  for (auto map_element_in_value: value[name]) {
66  bool key_found = false;
67  // checking if the key is already in the value
68  for (YAML::const_iterator value_iterator = map_element_in_value.begin();
69  value_iterator != map_element_in_value.end(); ++value_iterator) {
70  string value_key = value_iterator->first.as<string>();
71 
72  if (default_key == value_key) {
73  key_found = true;
74  break;
75  }
76  }
77  if (!key_found) {
78  map_element_in_value[default_key] = default_value;
79  }
80  }
81  }
82  }
83 
84  } else {
85 
86  // Update non-cumulative option values
87  for (const auto &map_element_in_desired_value: v) {
88 
89  for (YAML::const_iterator desired_value_iterator = map_element_in_desired_value.begin();
90  desired_value_iterator != map_element_in_desired_value.end(); ++desired_value_iterator) {
91 
92  for (auto existing_map: value[name]) {
93  for (YAML::const_iterator existing_map_iterator = existing_map.begin();
94  existing_map_iterator != existing_map.end(); ++existing_map_iterator) {
95 
96  string first_key = existing_map_iterator->first.as<string>();
97  string second_key = desired_value_iterator->first.as<string>();
98 
99  if (first_key == second_key) {
100  existing_map[existing_map_iterator->first] = desired_value_iterator->second;
101  }
102  }
103  }
104  }
105  }
106  }
107 }
108 
117  bool GOption::does_the_option_set_all_necessary_values(YAML::Node v) {
118  vector <string> this_keys;
119 
120  switch (v.Type()) {
121  case YAML::NodeType::Map:
122  for (const auto &it : v) {
123  this_keys.push_back(it.first.as<string>());
124  }
125  break;
126  default:
127  break;
128  }
129 
130  for (const auto &key : mandatory_keys) {
131  if (find(this_keys.begin(), this_keys.end(), key) == this_keys.end()) {
132  return false;
133  }
134  }
135  return true;
136 }
137 
145  void GOption::saveOption(std::ofstream *yamlConf) const {
146 
147  // setting style to block
148  // this does not work with command line passed values
149  YAML::Node mutableValue = value;
150  mutableValue.SetStyle(YAML::EmitterStyle::Block);
151 
152  *yamlConf << mutableValue << std::endl;
153 
154 }
155 
156 
164  void GOption::printHelp(bool detailed) const {
165 
166  if (name == GVERSION_STRING) return;
167 
168  long int fill_width = string(HELPFILLSPACE).size() + 1;
169  cout.fill('.');
170 
171  string helpString = "-" + name + RST;
172 
173  bool is_sequence = defaultValue.begin()->second.IsSequence();
174 
175  if (is_sequence) {
176  helpString += "=<sequence>";
177  } else {
178  helpString += "=<value>";
179  }
180  helpString += " ";
181 
182  cout << KGRN << " " << left;
183  cout.width(fill_width);
184 
185  if (detailed) {
186  cout << helpString << ": " << description << endl;
187  cout << endl;
188  cout << detailedHelp() << endl;
189  } else {
190  cout << helpString << ": " << description << endl;
191  }
192 }
193 
202 string GOption::detailedHelp() const {
203  string newHelp = "";
204 
205  YAML::Node yvalues = defaultValue.begin()->second;
206  if (yvalues.IsSequence()) {
207  newHelp += "\n";
208 
209  for (unsigned i = 0; i < (unsigned) yvalues.size(); i++) {
210  YAML::Node this_node = yvalues[i];
211 
212  for (YAML::const_iterator it = this_node.begin(); it != this_node.end(); ++it) {
213  cout << TGREENPOINTITEM << KGRN << it->first.as<string>() << RST
214  << ": " << gvar_descs[i] << ". Default value: " << it->second.as<string>() << endl;
215  }
216  }
217  }
218  newHelp += "\n";
219 
220  vector <string> help_lines = gutilities::getStringVectorFromStringWithDelimiter(help, "\n");
221 
222  for (auto line: help_lines) {
223  newHelp += GTAB + line + "\n";
224  }
225  return newHelp;
226 
227 }
#define HELPFILLSPACE
#define GVERSION_STRING
#define EC__MANDATORY_NOT_FILLED