QMCPACK
XmlRep.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois / NCSA Open Source License.
3 // See LICENSE file in top directory for details .
4 //
5 // Copyright ( c ) 2018 QMCPACK developers
6 //
7 // File developed by : Luke Shulenburger, lshulen@sandia.gov, Sandia National Laboratories
8 //
9 // File created by : Luke Shulenburger, lshulen@sandia.gov, Sandia National Laboratories
10 /////////////////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef XML_REP_H
13 #define XML_REP_H
14 #include <vector>
15 #include <string>
16 #include <sstream>
17 #include <iostream>
18 #include <utility>
19 
20 // perhaps a project for the future would be to create a global xmlTree structure
21 // where everything here would be members of it. It could handle the istream
22 // using RAII and could take a fair amount of complexity out of XmlNode
23 
24 enum class tagType
25 {
26  opening,
27  closing,
29  pod
30 };
31 
32 // helper class, stores a few things about each XmlElement, whether
33 // it be a tag or POD
35 {
36 public:
37  std::streampos startLoc;
38  std::streampos endLoc;
39  std::string name;
43  {
44  startLoc = e.startLoc;
45  endLoc = e.endLoc;
46  name = e.name;
47  type = e.type;
48  }
49 };
50 
51 // stream that will build up a sequential list of where all
52 // tags and POD are in the filestream that contains the xml file
53 // this is used to create an XmlNode structure
54 class XmlStream
55 {
56 private:
57  int addNextTag();
58  std::string getTagName(const std::string& tag, tagType type) const;
59  int checkForPOD(const XmlElement& before, const XmlElement& after) const;
60  int startComment(long position, long length) const;
61  int endComment(long position, long length) const;
62 
63 public:
64  XmlStream(std::istream* is);
65  std::string getTag(const XmlElement& e) const;
66  std::string getTag(int i) const;
67  std::string getStreamSection(const std::streampos& start, const std::streampos& end) const;
68  void findChildElements(int start, std::vector<int>& childIndices, int& podIndex) const;
69  void listAll() const;
70 
71 private:
72  std::istream* stream_;
73 
74 public:
75  std::vector<XmlElement> elements;
76 };
77 
78 
79 // structure that holds information about an XmlNode
80 // knows its name, attributes and holds its children XmlNodes
81 class XmlNode
82 {
83 public:
84  using attrpair = std::pair<std::string, std::string>;
85 
86 private:
87  // private information about how we store our state
89  std::string name_;
90  std::vector<attrpair> attributes_;
91  bool valInline_; // true for inline, false for putting the value on the next line
92  std::string value_;
93  bool valueDeferred_; // if true, need to look into the stream to get the value,
94  // if false it is stored in value
95  std::streampos podStart_;
96  std::streampos podEnd_;
97  std::vector<XmlNode> children_;
98  std::istream* stream_;
99 
100 private:
101  // private helper functions
102  void readToString(std::string& s) const; // make s = to this XmlNode's POD
103  void createFromStream(const XmlStream& stream, int start = 0, bool deferValue = true);
104  std::string getInStr(int is) const; // get whitespace to indent by is characters
105  std::string trimWhitespace(const std::string& str) const;
106  size_t getPosNextLiveChar(const std::string& str, char c) const;
107  void getNextKeyVal(std::string& contentstr, std::string& key, std::string& val) const;
108  void handleTagString(const XmlStream& xs, int loc); // populate name and attributes from loc of XmlStream
109 
110 public:
111  // public functions to interact with the xml data
112 
113  // deal with the name
114  std::string getName() const { return name_; }
115  // be careful here, it is illegal to start a name with a number,
116  // but this would allow you to screw that up...
117  template<typename T>
118  void setName(const T& val);
119 
120  // deal with attributes
121  int getAttributeIndex(const std::string& name, int strict = 0) const;
122  // note this is somewhat dangerous.
123  // If the conversion to the specified type using a stringstream is not good, you will get garbage
124  // You are protected in that if an attribute with that name is not found, the program will die
125  template<typename T>
126  void getAttribute(const std::string& name, T& result) const;
127  template<typename T>
128  void getAttribute(const char* name, T& result) const;
129  std::string getAttribute(const std::string& name) const;
130  std::string getAttribute(const char* name) const;
131  std::string getAttribute(int index) const;
132  std::string getAttributeName(int index) const;
133  int getNumAttributes() const { return attributes_.size(); }
134  template<typename T, typename TT>
135  void addAttribute(const T& n, const TT& v);
136  template<typename T>
137  void addYesNoAttribute(const T& n, int i);
138 
139  // deal with the value (POD)
140  template<typename T>
141  void getValue(T& result) const;
142  template<typename T>
143  void getValue(std::vector<T>& result) const;
144  std::string getValue() const;
145  int getValueSize() const; // gives the number of characters in the value
146  template<typename T>
147  void setValue(const T& v);
148 
149  // deal with children nodes
150  int getNumChildren() const { return children_.size(); }
151  int getChildIndex(const std::string& name, int strict = 0) const;
152  XmlNode& getChild(const std::string& name);
153  const XmlNode& getChild(const std::string& name) const;
154  const XmlNode& getChild(int i) const;
155  XmlNode& getChild(int i);
156  XmlNode& addChild(const XmlNode& nd); // add nd to this's XmlNodes' list of children
157  XmlNode& addChild(); // add a blank XmlNode to this XmlNode's list of children
158  template<typename T, typename TT>
159  void addParameterChild(const T& n, const TT& v);
160  template<typename T>
161  void addYesNoParameterChild(const T& n, int v);
162 
163  // constructors
164  XmlNode() : stream_(NULL)
165  {
166  isSelfClosing_ = false;
167  valueDeferred_ = false;
168  valInline_ = false;
169  }
170 
171  XmlNode(std::istream* stream, int start = 0, bool deferValue = false);
172  XmlNode(const XmlStream& xstream, std::istream* const stream, int start, bool deferValue = false);
173  XmlNode(const XmlNode& c);
174 
175  // methods to write out the whole hierarchy
176  void write(std::ostream& os, int indentLevel = 0) const;
177  std::string getString(int indentLevel = 0) const;
178 };
179 
180 
181 // implemenation of templates here
182 template<typename T>
183 void XmlNode::setName(const T& val)
184 {
185  std::stringstream ss;
186  ss << val;
187  name_ = ss.str();
188 }
189 
190 template<typename T>
191 void XmlNode::getAttribute(const std::string& name, T& result) const
192 {
193  std::string value = attributes_[getAttributeIndex(name, 1)].second;
194  std::stringstream ss(value);
195  ss >> result;
196 }
197 
198 template<typename T>
199 void XmlNode::getAttribute(const char* name, T& result) const
200 {
201  std::string sname(name);
202  return getAttribute(sname, result);
203 }
204 
205 template<typename T>
206 void XmlNode::getValue(T& result) const
207 {
208  if (valueDeferred_)
209  {
210  std::string val;
211  readToString(val);
212  std::stringstream ss(val);
213  ss >> result;
214  }
215  else
216  {
217  std::stringstream ss(value_);
218  ss >> result;
219  }
220 }
221 template<typename T>
222 void XmlNode::getValue(std::vector<T>& result) const
223 {
224  std::stringstream ss;
225  if (valueDeferred_)
226  {
227  std::string val;
228  readToString(val);
229  ss << val;
230  }
231  else
232  {
233  ss << value_;
234  }
235  T temp;
236  while (ss >> temp)
237  {
238  result.push_back(temp);
239  }
240 }
241 
242 template<typename T>
243 void XmlNode::setValue(const T& v)
244 {
245  valueDeferred_ = false;
246  std::stringstream ss;
247  ss << v;
248  value_ = ss.str();
249 }
250 
251 template<typename T, typename TT>
252 void XmlNode::addAttribute(const T& n, const TT& v)
253 {
254  std::stringstream ss1;
255  ss1 << n;
256  std::stringstream ss2;
257  ss2 << v;
258  attrpair ap(ss1.str(), ss2.str());
259  attributes_.push_back(ap);
260 }
261 
262 template<typename T>
263 void XmlNode::addYesNoAttribute(const T& n, int i)
264 {
265  std::stringstream ss;
266  ss << n;
267  attrpair ap;
268  ap.first = ss.str();
269  if (i == 0)
270  {
271  ap.second = "no";
272  }
273  else
274  {
275  ap.second = "yes";
276  }
277  attributes_.push_back(ap);
278 }
279 
280 template<typename T, typename TT>
281 void XmlNode::addParameterChild(const T& n, const TT& v)
282 {
283  XmlNode nd;
284  nd.setName("parameter");
285  nd.addAttribute("name", n);
286  nd.valInline_ = true;
287  nd.setValue(v);
288  addChild(nd);
289 }
290 
291 template<typename T>
292 void XmlNode::addYesNoParameterChild(const T& n, int v)
293 {
294  std::string vstr;
295  if (v == 0)
296  {
297  vstr = "no";
298  }
299  else
300  {
301  vstr = "yes";
302  }
303  addParameterChild(n, vstr);
304 }
305 
306 
307 #endif
XmlNode & addChild()
Definition: XmlRep.cpp:547
void getNextKeyVal(std::string &contentstr, std::string &key, std::string &val) const
Definition: XmlRep.cpp:600
void handleTagString(const XmlStream &xs, int loc)
Definition: XmlRep.cpp:566
int startComment(long position, long length) const
Definition: XmlRep.cpp:58
Definition: XmlRep.h:81
int checkForPOD(const XmlElement &before, const XmlElement &after) const
Definition: XmlRep.cpp:92
std::vector< attrpair > attributes_
Definition: XmlRep.h:90
std::vector< XmlElement > elements
Definition: XmlRep.h:75
int getChildIndex(const std::string &name, int strict=0) const
Definition: XmlRep.cpp:440
size_t getPosNextLiveChar(const std::string &str, char c) const
Definition: XmlRep.cpp:626
std::string trimWhitespace(const std::string &str) const
Definition: XmlRep.cpp:555
std::string getName() const
Definition: XmlRep.h:114
void listAll() const
Definition: XmlRep.cpp:333
std::string getValue() const
Definition: XmlRep.cpp:521
std::streampos podStart_
Definition: XmlRep.h:95
int addNextTag()
Definition: XmlRep.cpp:146
int getValueSize() const
Definition: XmlRep.cpp:532
void addYesNoParameterChild(const T &n, int v)
Definition: XmlRep.h:292
void setValue(const T &v)
Definition: XmlRep.h:243
bool isSelfClosing_
Definition: XmlRep.h:88
std::istream * stream_
Definition: XmlRep.h:98
void setName(const T &val)
Definition: XmlRep.h:183
XmlNode()
Definition: XmlRep.h:164
int getNumAttributes() const
Definition: XmlRep.h:133
std::string getInStr(int is) const
Definition: XmlRep.cpp:647
std::pair< std::string, std::string > attrpair
Definition: XmlRep.h:84
std::string name
Definition: XmlRep.h:39
tagType
Definition: XmlRep.h:24
XmlElement()
Definition: XmlRep.h:41
std::string value_
Definition: XmlRep.h:92
std::streampos endLoc
Definition: XmlRep.h:38
void addYesNoAttribute(const T &n, int i)
Definition: XmlRep.h:263
std::istream * stream_
Definition: XmlRep.h:72
std::streampos startLoc
Definition: XmlRep.h:37
tagType type
Definition: XmlRep.h:40
std::vector< XmlNode > children_
Definition: XmlRep.h:97
void write(std::ostream &os, int indentLevel=0) const
Definition: XmlRep.cpp:657
void createFromStream(const XmlStream &stream, int start=0, bool deferValue=true)
Definition: XmlRep.cpp:727
bool valInline_
Definition: XmlRep.h:91
void findChildElements(int start, std::vector< int > &childIndices, int &podIndex) const
Definition: XmlRep.cpp:290
std::string name_
Definition: XmlRep.h:89
XmlNode & getChild(const std::string &name)
Definition: XmlRep.cpp:458
std::string getTagName(const std::string &tag, tagType type) const
Definition: XmlRep.cpp:18
void addAttribute(const T &n, const TT &v)
Definition: XmlRep.h:252
std::string getStreamSection(const std::streampos &start, const std::streampos &end) const
Definition: XmlRep.cpp:276
int endComment(long position, long length) const
Definition: XmlRep.cpp:75
std::string getTag(const XmlElement &e) const
Definition: XmlRep.cpp:384
std::string getString(int indentLevel=0) const
Definition: XmlRep.cpp:663
int getNumChildren() const
Definition: XmlRep.h:150
int getAttributeIndex(const std::string &name, int strict=0) const
Definition: XmlRep.cpp:482
std::string getAttributeName(int index) const
Definition: XmlRep.cpp:500
std::streampos podEnd_
Definition: XmlRep.h:96
XmlElement(const XmlElement &e)
Definition: XmlRep.h:42
void getAttribute(const std::string &name, T &result) const
Definition: XmlRep.h:191
void readToString(std::string &s) const
Definition: XmlRep.cpp:396
void addParameterChild(const T &n, const TT &v)
Definition: XmlRep.h:281
bool valueDeferred_
Definition: XmlRep.h:93
XmlStream(std::istream *is)
Definition: XmlRep.cpp:358