Bridge++  Version 1.5.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
parameterManager_XML.cpp
Go to the documentation of this file.
1 
14 #ifdef USE_XML
15 #ifdef USE_TINYXML2LIB
16 
17 #include "parameterManager_XML.h"
18 
19 #include "Tools/evalexpr.h"
20 
21 #include <fstream>
22 #include <sstream>
23 #include <map>
24 #include <vector>
25 
26 #include "tinyxml2.h"
27 using namespace tinyxml2;
28 
29 #include "IO/bridgeIO.h"
30 using Bridge::vout;
31 
32 using std::string;
33 using std::vector;
34 using std::map;
35 
36 const std::string ParameterManager_XML::class_name = "ParameterManager_XML";
37 
38 //====================================================================
39 class Parser_tinyxml
40 {
41  public:
42  static const string class_name;
43 
44  public:
45  int parse(const char *buf, Parameters& params);
46 
47  Parser_tinyxml()
48  : m_vl(CommonParameters::Vlevel()) {}
49 
50  private:
51 
52  int store_map_data(const XMLElement *, Parameters&);
53  int store_vector_data(const XMLElement *, vector<string>&);
54 
55  void traverse(const XMLElement *, const string& indent = "") const;
56 
57  protected:
59 };
60 
61 //--------------------------------------------------------------------
62 const string Parser_tinyxml::class_name = "ParameterManager_XML::Parser_tinyxml";
63 
64 //--------------------------------------------------------------------
65 int Parser_tinyxml::parse(const char *buf, Parameters& params)
66 {
67  if (!buf) return EXIT_FAILURE;
68 
69  XMLDocument doc;
70 
71  XMLError err = doc.Parse(buf);
72 
73  if (err != XML_NO_ERROR) {
74  vout.crucial(m_vl, "Error at %s: parse failed: %s\n", class_name.c_str(), doc.ErrorName());
75 
76  const char *err_str1 = doc.GetErrorStr1();
77  if (err_str1) {
78  vout.crucial(m_vl, " %s\n", err_str1);
79  }
80  const char *err_str2 = doc.GetErrorStr2();
81  if (err_str2) {
82  vout.crucial(m_vl, " %s\n", err_str2);
83  }
84 
85  exit(EXIT_FAILURE);
86  }
87 
88  XMLElement *root = doc.FirstChildElement("Parameters");
89  if (!root) {
90  vout.crucial(m_vl, "Error at %s: tag \"Parameters\" not found.\n", class_name.c_str());
91  exit(EXIT_FAILURE);
92  }
93 
94  // traverse(root); // for debug
95 
96  for (const XMLElement *e = root->FirstChildElement(); e; e = e->NextSiblingElement()) {
97  int retv = store_map_data(e, params);
98 
99  if (retv != EXIT_SUCCESS) {
100  vout.crucial(m_vl, "Error at %s: parse failed.\n", class_name.c_str());
101  return EXIT_FAILURE;
102  }
103  }
104 
105  return EXIT_SUCCESS;
106 }
107 
108 
109 //--------------------------------------------------------------------
110 int Parser_tinyxml::store_vector_data(const XMLElement *elem, vector<string>& v)
111 {
112  if (!elem) return EXIT_FAILURE;
113 
114  const XMLElement *ee = elem->FirstChildElement();
115  if (!ee) return EXIT_FAILURE;
116 
117  map<int, string> mm;
118  int max_index = 0;
119 
120  if (strcmp(ee->Name(), "value") == 0) { // <value id="n">item</value>
121  int count = 0;
122 
123  for (const XMLElement *e = elem->FirstChildElement(); e; e = e->NextSiblingElement()) {
124  int id = 0;
125 
126  if (e->QueryIntAttribute("id", &id) == XML_SUCCESS) {
127  --id; // id = 1, 2, 3, ...
128  } else {
129  id = count;
130  }
131 
132  if (id < 0) {
133  fprintf(stderr, "Error. inappropriate id\n");
134  return EXIT_FAILURE;
135  }
136 
137  if (id > max_index) max_index = id;
138 
139  mm[id] = e->GetText();
140  ++count;
141  }
142  } else { // <x>item</x> <y>item</y> ...
143  for (const XMLElement *e = elem->FirstChildElement(); e; e = e->NextSiblingElement()) {
144  int id = 0;
145 
146  string tag = e->Name();
147 
148  if (tag == "x") {
149  id = 0;
150  } else if (tag == "y") {
151  id = 1;
152  } else if (tag == "z") {
153  id = 2;
154  } else if (tag == "t") {
155  id = 3;
156  } else if (tag == "w") {
157  id = 4;
158  } else {
159  fprintf(stderr, "unknown tag.\n");
160  return EXIT_FAILURE;
161  }
162 
163  if (id > max_index) max_index = id;
164 
165  mm[id] = e->GetText();
166  }
167  }
168 
169  vector<string> vv(max_index + 1);
170 
171  for (map<int, string>::const_iterator p = mm.begin(); p != mm.end(); ++p) {
172  vv[p->first] = p->second;
173  }
174 
175  v = vv;
176 
177  return EXIT_SUCCESS;
178 }
179 
180 
181 //--------------------------------------------------------------------
182 int Parser_tinyxml::store_map_data(const XMLElement *elem, Parameters& params)
183 {
184  if (!elem) return EXIT_FAILURE;
185 
186  const char *elem_name = elem->Name();
187  const char *elem_value = elem->GetText();
188 
189  if (elem_value != NULL) { /* assume leaf node */
190  // store to scalar map
191  params.set_string(elem_name, elem_value);
192 
193  return EXIT_SUCCESS;
194  }
195 
196  const char *elem_attr = elem->Attribute("type");
197 
198  if (elem_attr && (strcmp(elem_attr, "sequence") == 0)) { /* sequence */
199  vector<string> v;
200  int retv = store_vector_data(elem, v);
201 
202  if (retv == EXIT_SUCCESS) {
203  // store to sequence map
204  params.set_string_vector(elem_name, v);
205  }
206 
207  return retv;
208  }
209 
210  Parameters pp;
211 
212  for (const XMLElement *e = elem->FirstChildElement(); e; e = e->NextSiblingElement()) {
213  int retv = store_map_data(e, pp);
214 
215  if (retv != EXIT_SUCCESS) {
216  return EXIT_FAILURE;
217  }
218  }
219 
220  // store to map map
221  params.set_Parameters(elem_name, pp);
222 
223  return EXIT_SUCCESS;
224 }
225 
226 
227 //--------------------------------------------------------------------
228 void Parser_tinyxml::traverse(const XMLElement *elem, const string& indent) const
229 {
230  if (!elem) return;
231 
232  const char *elem_name = elem->Name();
233  const char *elem_value = elem->GetText();
234 
235  if (elem_value != NULL) { /* assume leaf node */
236  vout.general(m_vl, "%sElementName = %s, value = %s\n", indent.c_str(), elem_name, elem_value);
237  return;
238  } else {
239  vout.general(m_vl, "%sElementName = %s\n", indent.c_str(), elem_name);
240 
241  const char *elem_attr = elem->Attribute("type");
242  if (elem_attr && (strcmp(elem_attr, "sequence") == 0)) {
243  vout.general(m_vl, "%s- is a sequence.\n", indent.c_str());
244  }
245 
246  for (const XMLElement *e = elem->FirstChildElement(); e; e = e->NextSiblingElement()) {
247  traverse(e, indent + " ");
248  }
249  }
250 }
251 
252 
253 //--------------------------------------------------------------------
254 
255 //====================================================================
256 void ParameterManager_XML::read_params(const std::string& params_file, Parameters& params)
257 {
258  const int io_node = 0; // node id for file i/o.
259 
260  int filesize = 0;
261  char *buf = 0;
262 
263  if (Communicator::nodeid() == io_node) {
264  // load and distribute
265  std::ifstream fin(params_file.c_str());
266  if (!fin) {
267  vout.crucial(m_vl, "Error at %s: unable to read parameter file: %s.\n", class_name.c_str(), params_file.c_str());
268 
270  }
271 
272  fin.seekg(0, std::ios::end);
273  filesize = fin.tellg();
274  fin.seekg(0, std::ios::beg);
275 
276  int padding = 8 - (filesize % 8);
277 
278  vout.paranoiac(m_vl, "%s::%s: filesize = %d, padding = %d\n", class_name.c_str(), __func__, filesize, padding);
279 
280  filesize += padding;
281 
282  Communicator::broadcast(1, &filesize, io_node);
283 
284  buf = new char [filesize];
285  memset(buf, 0, filesize);
286 
287  fin.read(buf, filesize - padding);
288 
289  Communicator::Base::broadcast(filesize, buf, io_node);
290  } else {
291  // receive from io_node
292 
293  Communicator::broadcast(1, &filesize, io_node);
294 
295  buf = new char [filesize];
296  memset(buf, 0, filesize);
297 
298  Communicator::Base::broadcast(filesize, buf, io_node);
299  }
300 
301  Parser_tinyxml().parse(buf, params);
302 
303  // params.print(); // for debug
304 
305  delete [] buf;
306 }
307 
308 #endif /* USE_TINYXML2LIB */
309 #endif /* USE_XML */
310 //====================================================================
311 //============================================================END=====
void set_Parameters(const string &key, const Parameters &value)
Definition: parameters.cpp:51
BridgeIO vout
Definition: bridgeIO.cpp:503
static void abort()
terminate communicator
void general(const char *format,...)
Definition: bridgeIO.cpp:197
static int broadcast(size_t size, void *data, int sender)
Class for parameters.
Definition: parameters.h:46
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
void crucial(const char *format,...)
Definition: bridgeIO.cpp:178
VerboseLevel
Definition: bridgeIO.h:42
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