Bridge++  Version 1.5.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
parameterManager_YAML.cpp
Go to the documentation of this file.
1 
14 #include "parameterManager_YAML.h"
15 
16 #include <iostream>
17 #include <fstream>
18 #include <sstream>
19 #include <cstring>
20 #include <map>
21 #include <vector>
22 #include <stack>
23 
24 #ifdef USE_YAMLCPPLIB
25 #include <yaml-cpp/yaml.h>
26 #endif
27 
28 #include "IO/bridgeIO.h"
29 using Bridge::vout;
30 
31 using std::string;
32 using std::vector;
33 using std::map;
34 using std::pair;
35 
36 const std::string ParameterManager_YAML::class_name = "ParameterManager_YAML";
37 
38 //====================================================================
39 #ifdef USE_YAMLCPPLIB
40 
41 //====================================================================
42 class Parser_yamlcpp
43 {
44  public:
45  static const string class_name;
46 
47  public:
48  void parse(std::istream& fin, Parameters& params);
49 
50  Parser_yamlcpp()
51  : m_vl(CommonParameters::Vlevel()) {}
52 
53  private:
54 
55  int store_map_data(const YAML::Node&, Parameters&);
56 
57  int store_vector_data(const YAML::Node&, vector<string>&);
58 
59  string type_string(const YAML::Node&) const;
60  int traverse(const YAML::Node&, const string& indent = "") const;
61 
63 };
64 
65 //--------------------------------------------------------------------
66 const string Parser_yamlcpp::class_name = "ParameterManager_YAML::Parser_yamlcpp";
67 
68 //--------------------------------------------------------------------
69 void Parser_yamlcpp::parse(std::istream& fin, Parameters& params)
70 {
71  YAML::Node node = YAML::Load(fin);
72 
73  int result = store_map_data(node, params);
74 
75  if (result != EXIT_SUCCESS) {
76  vout.crucial(m_vl, "%s: parse failed.\n", class_name.c_str());
77  exit(EXIT_FAILURE);
78  }
79 }
80 
81 
82 //--------------------------------------------------------------------
83 int Parser_yamlcpp::store_map_data(const YAML::Node& node, Parameters& params)
84 {
85  if (!node.IsMap()) {
86  vout.general(m_vl, "Error: map expected. found %s\n", type_string(node).c_str());
87  return EXIT_FAILURE;
88  }
89 
90  int retv = EXIT_SUCCESS;
91 
92  for (YAML::const_iterator p = node.begin(); p != node.end(); ++p) {
93  string key = p->first.as<string>();
94 
95  if (p->second.IsScalar()) {
96  string value = p->second.as<string>();
97 
98  params.set_string(key, value);
99  } else if (p->second.IsSequence()) {
100  vector<string> v;
101 
102  if (store_vector_data(p->second, v) != EXIT_SUCCESS) {
103  retv = EXIT_FAILURE;
104  }
105 
106  params.set_string_vector(key, v);
107  } else if (p->second.IsMap()) {
108  Parameters pp;
109  store_map_data(p->second, pp);
110 
111  params.set_Parameters(key, pp);
112  } else {
113  vout.general(m_vl, "Error: unexpected type %s\n", type_string(p->second).c_str());
114  retv = EXIT_FAILURE;
115  }
116  }
117 
118  return retv;
119 }
120 
121 
122 //--------------------------------------------------------------------
123 int Parser_yamlcpp::store_vector_data(const YAML::Node& node, vector<string>& v)
124 {
125  int retv = EXIT_SUCCESS;
126 
127  if (!node.IsSequence()) {
128  vout.general(m_vl, "Error: vector expected. found %s\n", type_string(node).c_str());
129  return EXIT_FAILURE;
130  }
131 
132  for (size_t i = 0; i < node.size(); ++i) {
133  if (!node[i].IsScalar()) {
134  vout.general(m_vl, "Error: item[%zu] scalar expected. found %s\n", i, type_string(node).c_str());
135  retv = EXIT_FAILURE;
136  } else {
137  v.push_back(node[i].as<string>());
138  }
139  }
140 
141  return retv;
142 }
143 
144 
145 //--------------------------------------------------------------------
146 string Parser_yamlcpp::type_string(const YAML::Node& node) const
147 {
148  switch (node.Type())
149  {
150  case YAML::NodeType::Undefined:
151  return "UndefinedType";
152 
153  case YAML::NodeType::Null:
154  return "NullType";
155 
156  case YAML::NodeType::Scalar:
157  return "Scalar";
158 
159  case YAML::NodeType::Sequence:
160  return "Sequence";
161 
162  case YAML::NodeType::Map:
163  return "Map";
164 
165  default:
166  return "(Unknown)";
167  }
168  return "(ERROR)";
169 }
170 
171 
172 //--------------------------------------------------------------------
173 int Parser_yamlcpp::traverse(const YAML::Node& node, const string& indent) const
174 {
175  switch (node.Type())
176  {
177  case YAML::NodeType::Null:
178  vout.general("%sNull type\n", indent.c_str());
179  break;
180 
181  case YAML::NodeType::Scalar:
182  vout.general("%sScalar type \"%s\"\n", indent.c_str(), node.as<string>().c_str());
183  break;
184 
185  case YAML::NodeType::Sequence:
186  vout.general("%sSequence type\n", indent.c_str());
187  for (size_t i = 0; i < node.size(); ++i) {
188  vout.general("%s%zu:\n", indent.c_str(), i);
189  traverse(node[i], indent + string(" "));
190  }
191  break;
192 
193  case YAML::NodeType::Map:
194  vout.general("%sMap type\n", indent.c_str());
195  for (YAML::const_iterator p = node.begin(); p != node.end(); ++p) {
196  vout.general("%s%s:\n", indent.c_str(), p->first.as<string>().c_str());
197  traverse(p->second, indent + string(" "));
198  }
199  break;
200 
201  default:
202  vout.general("%sUnknown type\n", indent.c_str());
203  }
204 
205  return 0;
206 }
207 
208 
209 //====================================================================
210 #else
211 //====================================================================
212 
214 {
215  public:
216  static const string class_name;
217 
218  public:
220  : m_vl(CommonParameters::Vlevel()) {}
221 
222  void parse(std::istream& iss, Parameters& params);
223 
224  private:
225  int parse_stream(std::istream& iss, Parameters& params);
226 
227  int parse_line(char *buf, string& key, string& value);
228  int parse_vector(char *buf, vector<string>& vec);
229 
231 };
232 
233 //--------------------------------------------------------------------
234 const string Parser_bridge::class_name = "ParameterManger_YAML::Parser_bridge";
235 
236 //--------------------------------------------------------------------
237 void Parser_bridge::parse(std::istream& iss, Parameters& params)
238 {
239  int result = parse_stream(iss, params);
240 
241  if (result != EXIT_SUCCESS) {
242  vout.crucial(m_vl, "%s: parse failed.\n", class_name.c_str());
243  exit(EXIT_FAILURE);
244  }
245 }
246 
247 
248 //--------------------------------------------------------------------
249 int Parser_bridge::parse_vector(char *buf, vector<string>& vec)
250 {
251  // N.B. buf modified on exit.
252  const char sep = ',';
253 
254  int count = 0;
255 
256  if ((buf[0] != '[') || (buf[strlen(buf) - 1] != ']')) {
257  return -1;
258  }
259 
260  buf[strlen(buf) - 1] = '\0';
261 
262  char *p = buf + 1;
263 
264  while (p && *p)
265  {
266  // skip heading spaces
267  while (*p == ' ')
268  {
269  ++p;
270  }
271 
272  // find separator
273  char *q = strchr(p, sep);
274 
275  if (q) {
276  // eliminate separator
277  *q = '\0';
278 
279  // eliminate trailing spaces of the item
280  char *r = q - 1;
281  while (*r == ' ')
282  {
283  *r-- = '\0';
284  }
285 
286  vec.push_back(string(p));
287  ++count;
288 
289  // go to next item
290  p = q + 1;
291  } else {
292  // separator is not found; maybe last item in the sequence.
293 
294  // eliminate trailing spaces;
295  char *r = p + strlen(p) - 1;
296  while (r >= p && *r == ' ')
297  {
298  *r-- = '\0';
299  }
300 
301  if (strlen(p) > 0) {
302  vec.push_back(string(p));
303  ++count;
304  } else {
305  // discard
306  }
307 
308  p = q;
309  }
310  }
311 
312  return count;
313 }
314 
315 
316 //--------------------------------------------------------------------
317 int Parser_bridge::parse_line(char *buf, string& key, string& value)
318 {
319  // N.B. buf modified on exit.
320 
321  const char delim = ':';
322 
323  // remove comments
324  if (char *q = strchr(buf, '#')) { *q = '\0'; }
325 
326  // remove trailing spaces
327  char *s = buf + strlen(buf) - 1;
328  while (*s == ' ')
329  {
330  *s-- = '\0';
331  }
332 
333  // find indent
334  int indent = 0;
335 
336  char *p = buf;
337  while (*p == ' ')
338  {
339  ++p;
340  ++indent;
341  }
342 
343  // find key-value separator
344  char *q = strchr(buf, delim);
345 
346  if (!q) {
347  key = string();
348  value = string();
349 
350  return -1;
351  }
352 
353  // find key
354  char *r = q;
355 
356  *r = '\0';
357  --r;
358  while (r >= p && *r == ' ')
359  {
360  *r-- = '\0';
361  }
362 
363  key = string(p);
364 
365  // find value
366  ++q;
367  while (*q == ' ')
368  {
369  ++q;
370  }
371 
372  value = string(q);
373 
374  // return indent
375  return indent;
376 }
377 
378 
379 //--------------------------------------------------------------------
380 int Parser_bridge::parse_stream(std::istream& iss, Parameters& params)
381 {
382  int retv = EXIT_SUCCESS;
383 
384  const size_t buf_size = 1024;
385  char buf[buf_size];
386 
387  typedef pair<string, Parameters *> env_t;
388  typedef pair<int, env_t> level_t;
389  typedef std::stack<level_t> stack_t;
390 
391  stack_t levels;
392 
393  Parameters *current_params = &params;
394  int current_indent = 0;
395 
396  bool expect_map = false;
397 
398  while (iss.getline(buf, buf_size))
399  {
400  string key, value;
401 
402  int indent = parse_line(buf, key, value);
403 
404  if (indent < 0) {
405  vout.paranoiac(m_vl, "%s: empty line. skip.\n", class_name.c_str());
406  continue;
407  }
408 
409  // level up/down
410  if (indent > current_indent) {
411  if (!expect_map) {
412  vout.general(m_vl, "%s: Error: unexpected nest level.\n", class_name.c_str());
413  retv = EXIT_FAILURE;
414  continue;
415  }
416 
417  // start new level
418  current_params = new Parameters;
419  current_indent = indent;
420 
421  expect_map = false;
422  } else {
423  if (expect_map) {
424  // open key in the previous line actually correspond to empty value
425 
426  level_t lv = levels.top();
427  levels.pop();
428 
429  string key = lv.second.first;
430  Parameters *stored_params = lv.second.second;
431 
432  stored_params->set_string(key, string()); // null string.
433 
434  // current_params is yet not newly created. no need to delete.
435 
436  // restore upper level -- maybe unnecessary.
437  current_params = stored_params;
438  current_indent = lv.first;
439 
440  expect_map = false;
441  }
442 
443  if (indent < current_indent) {
444  while (indent < current_indent)
445  {
446  level_t lv = levels.top();
447  levels.pop();
448 
449  string key = lv.second.first;
450  Parameters *stored_params = lv.second.second;
451 
452  stored_params->set_Parameters(key, *current_params);
453  delete current_params;
454 
455  // restore upper level
456  current_params = stored_params;
457  current_indent = lv.first;
458  }
459  } else { // indent == current_indent
460  //
461  }
462  }
463 
464  // store key-value
465  if (value.length() > 0) {
466  if (value[0] == '[') {
467  memset(buf, '\0', buf_size);
468  value.copy(buf, buf_size); // reuse buffer
469 
470  vector<string> v;
471 
472  int nvalues = parse_vector(buf, v);
473 
474  if (nvalues < 0) {
475  vout.general(m_vl, "%s: ERROR: parse_vector failed.\n", class_name.c_str());
476  continue;
477  }
478 
479  // store key - vector value.
480  current_params->set_string_vector(key, v);
481  } else {
482  // store key - scalar value.
483  current_params->set_string(key, value);
484  }
485  } else {
486  // key for a map in subsequent lines
487  expect_map = true;
488 
489  // push current environment to stack
490  levels.push(level_t(indent, env_t(key, current_params)));
491  }
492  }
493 
494  while (current_indent > 0)
495  {
496  level_t lv = levels.top();
497  levels.pop();
498 
499  string key = lv.second.first;
500  Parameters *stored_params = lv.second.second;
501 
502  stored_params->set_Parameters(key, *current_params);
503  delete current_params;
504 
505  // restore upper level
506  current_params = stored_params;
507  current_indent = lv.first;
508  }
509 
510  return retv;
511 }
512 
513 
514 #endif
515 
516 //====================================================================
517 void ParameterManager_YAML::read_params(std::istream& fin, Parameters& params)
518 {
519 #ifdef USE_YAMLCPPLIB
520  Parser_yamlcpp().parse(fin, params);
521 #else
522  Parser_bridge().parse(fin, params);
523 #endif
524 }
525 
526 
527 //====================================================================
528 void ParameterManager_YAML::read_params(const std::string& params_file, Parameters& params)
529 {
530  const int io_node = 0; // node id for file i/o.
531 
532  int filesize = 0;
533  char *buf = 0;
534 
535  if (Communicator::nodeid() == io_node) {
536  // load and distribute
537  std::ifstream fin(params_file.c_str());
538  if (!fin) {
539  vout.crucial(m_vl, "Error at %s: unable to read parameter file: %s.\n", class_name.c_str(), params_file.c_str());
540 
542  }
543 
544  fin.seekg(0, std::ios::end);
545  filesize = fin.tellg();
546  fin.seekg(0, std::ios::beg);
547 
548  int padding = 8 - (filesize % 8);
549 
550  vout.paranoiac(m_vl, "%s::read_params: filesize = %d, padding = %d\n", class_name.c_str(), filesize, padding);
551 
552  filesize += padding;
553 
554  Communicator::broadcast(1, &filesize, io_node);
555 
556  buf = new char [filesize];
557  memset(buf, 0, filesize);
558 
559  fin.read(buf, filesize - padding);
560 
561  Communicator::Base::broadcast(filesize, buf, io_node);
562  } else {
563  // receive from io_node
564 
565  Communicator::broadcast(1, &filesize, io_node);
566 
567  buf = new char [filesize];
568  memset(buf, 0, filesize);
569 
570  Communicator::Base::broadcast(filesize, buf, io_node);
571  }
572 
573  std::istringstream iss(buf);
574  read_params(iss, params);
575 
576  delete [] buf;
577 }
578 
579 
580 //====================================================================
581 //============================================================END=====
void set_Parameters(const string &key, const Parameters &value)
Definition: parameters.cpp:51
BridgeIO vout
Definition: bridgeIO.cpp:503
int parse_stream(std::istream &iss, Parameters &params)
static void abort()
terminate communicator
void general(const char *format,...)
Definition: bridgeIO.cpp:197
int parse_line(char *buf, string &key, string &value)
void parse(std::istream &iss, Parameters &params)
static int broadcast(size_t size, void *data, int sender)
Class for parameters.
Definition: parameters.h:46
int parse_vector(char *buf, vector< string > &vec)
static const std::string class_name
void set_string(const string &key, const string &value)
Definition: parameters.cpp:39
Common parameter class: provides parameters as singleton.
void paranoiac(const char *format,...)
Definition: bridgeIO.cpp:235
static const string class_name
void crucial(const char *format,...)
Definition: bridgeIO.cpp:178
void read_params(const std::string &params_file, Parameters &params)
read parameters from file.
VerboseLevel
Definition: bridgeIO.h:42
Bridge::VerboseLevel m_vl
Bridge::VerboseLevel m_vl
static int broadcast(int count, double *data, int sender)
broadcast array of double from sender.
static int nodeid()
alternative name for self().
Definition: communicator.h:105
void set_string_vector(const string &key, const vector< string > &value)
Definition: parameters.cpp:48