SENSEI
A frame work for generic in situ analytics
XMLUtils.h
Go to the documentation of this file.
1 #ifndef sensei_XMLUtils_h
2 #define sensei_XMLUtils_h
3 
4 /// @file
5 
6 #include "Error.h"
7 
8 #include <mpi.h>
9 #include <string>
10 #include <vector>
11 #include <array>
12 #include <pugixml.hpp>
13 
14 namespace sensei
15 {
16 
17 /// a collection of functions for parsing XML.
18 namespace XMLUtils
19 {
20 
21 /** check that an attribute of the passed in name exists return of 0 indicates
22  * that it does. if not non-zero value is returned and an error message is sent
23  * to stderr.
24  */
25 SENSEI_EXPORT
26 int RequireAttribute(const pugi::xml_node &node, const char *attributeName);
27 
28 /** check that a child element of the passed in name exists return of 0
29  * indicates that it does. if not non-zero value is returned and an error
30  * message is sent to stderr.
31  */
32 SENSEI_EXPORT
33 int RequireChild(const pugi::xml_node &node, const char *childName);
34 
35 /** Parallel collective read, parse, and distribute the XML file. Rank 0 does
36  * the I/O and parse and will broadcast to the other ranks in the communicator.
37  * return of 0 indicates success.
38  */
39 SENSEI_EXPORT
40 int Parse(MPI_Comm comm, const std::string &filename, pugi::xml_document &doc);
41 
42 
43 /// @cond
44 
45 /// helper for string to numeric type conversions
46 template <typename num_t> struct numeric_traits;
47 
48 #define declare_numeric_traits(cpp_t, func) \
49 template <> struct numeric_traits<cpp_t> \
50 { \
51  static \
52  cpp_t convert(const std::string &str) \
53  { return (cpp_t)func(str); } \
54 };
55 
56 declare_numeric_traits(int, std::stol)
57 declare_numeric_traits(unsigned int, std::stoul)
58 declare_numeric_traits(long, std::stol)
59 declare_numeric_traits(unsigned long, std::stoul)
60 declare_numeric_traits(long long, std::stol)
61 declare_numeric_traits(unsigned long long, std::stoul)
62 declare_numeric_traits(float, std::stof)
63 declare_numeric_traits(double, std::stod)
64 
65 /// @endcond
66 
67 /** parse text data in the node of unknown length, return in the vector. return
68  * 0 if successful
69  */
70 template <typename num_t>
71 int ParseNumeric(const pugi::xml_node &node, std::vector<num_t> &numData)
72 {
73  std::string strData = node.text().as_string();
74  std::string delims = " ,\t\n";
75 
76  std::size_t curr = strData.find_first_not_of(delims, 0);
77  std::size_t next = std::string::npos;
78 
79  while (curr != std::string::npos)
80  {
81  next = strData.find_first_of(delims, curr + 1);
82  std::string tmp = strData.substr(curr, next - curr);
83  numData.push_back(numeric_traits<num_t>::convert(tmp));
84  curr = strData.find_first_not_of(delims, next);
85  }
86 
87  return 0;
88 }
89 
90 /// parse text data in the node of specific length
91 template <typename num_t, unsigned long n>
92 int ParseNumeric(const pugi::xml_node &node, std::array<num_t,n> &numData)
93 {
94  std::string strData = node.text().as_string();
95  std::string delims = " ,\t";
96 
97  std::size_t curr = strData.find_first_not_of(delims, 0);
98  std::size_t next = std::string::npos;
99 
100  unsigned long i = 0;
101  while ((curr != std::string::npos) && (i < n))
102  {
103  next = strData.find_first_of(delims, curr + 1);
104  std::string tmp = strData.substr(curr, next - curr);
105  numData[i] = numeric_traits<num_t>::convert(tmp);
106  curr = strData.find_first_not_of(delims, next);
107  ++i;
108  }
109 
110  if (i != n)
111  {
112  SENSEI_ERROR(<< "Missmatch in the nuber of values detected. "
113  << node.name() << " requires " << n << " values")
114  return -1;
115  }
116 
117  return 0;
118 }
119 
120 /// process a sequence of "name = value" pairs in a node's text.
121 int ParseNameValuePairs(const pugi::xml_node &node,
122  std::vector<std::string> &names, std::vector<std::string> &values);
123 
124 /** process a list in a node's text. List elements should be
125  * space or comma delimited. Give the following XML
126  *
127  * ```XML
128  * <some_elem>
129  * list1, list2, ... , listN
130  * </some_elem>
131  * ```
132  *
133  * extract list1 ... listN and return as a vector of strings. returns the number
134  * of elements found or < 0 on error.
135  */
136 int ParseList(pugi::xml_node node, std::vector<std::string> &listOut);
137 
138 }
139 }
140 #endif
int ParseNameValuePairs(const pugi::xml_node &node, std::vector< std::string > &names, std::vector< std::string > &values)
process a sequence of "name = value" pairs in a node&#39;s text.
int ParseNumeric(const pugi::xml_node &node, std::vector< num_t > &numData)
parse text data in the node of unknown length, return in the vector.
Definition: XMLUtils.h:71
SENSEI_EXPORT int RequireChild(const pugi::xml_node &node, const char *childName)
check that a child element of the passed in name exists return of 0 indicates that it does...
SENSEI_EXPORT int RequireAttribute(const pugi::xml_node &node, const char *attributeName)
check that an attribute of the passed in name exists return of 0 indicates that it does...
SENSEI.
Definition: ADIOS2AnalysisAdaptor.h:27
SENSEI_EXPORT int Parse(MPI_Comm comm, const std::string &filename, pugi::xml_document &doc)
Parallel collective read, parse, and distribute the XML file.
int ParseList(pugi::xml_node node, std::vector< std::string > &listOut)
process a list in a node&#39;s text.