xml_parse_utils.h
Go to the documentation of this file.
1 // Copyright (C) 2018-2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4 
5 /**
6  * @brief Basic functions to safely extract values from `pugi::xml_node` and open `pugi::xml_document`
7  * @file xml_parse_utils.h
8  */
9 
10 #pragma once
11 
12 #include <cstdlib>
13 #include <fstream>
14 #include <memory>
15 #include <sstream>
16 #include <string>
17 #include <utility>
18 
19 #include <pugixml.hpp>
20 
21 #include "ie_api.h"
22 #include "ie_precision.hpp"
23 #include "ie_common.h"
24 #include "file_utils.h"
25 
26 /**
27  * @ingroup ie_dev_api_xml
28  * @brief Defines convinient for-each based cycle to iterate over node childs
29  *
30  * @param c Child node name
31  * @param p Parent node name
32  * @param tag The tag represented as a string value
33  */
34 #define FOREACH_CHILD(c, p, tag) for (auto c = p.child(tag); !c.empty(); c = c.next_sibling(tag))
35 
36 /**
37  * @brief XML helpers function to extract values from `pugi::xml_node`
38  * @ingroup ie_dev_api_xml
39  */
40 namespace XMLParseUtils {
41 
42 /**
43  * @brief Gets the integer attribute from `pugi::xml_node`
44  * @ingroup ie_dev_api_xml
45  *
46  * @param[in] node The node
47  * @param[in] str The string
48  * @return An integer value
49  */
50 INFERENCE_ENGINE_API_CPP(int) GetIntAttr(const pugi::xml_node& node, const char* str);
51 
52 /**
53  * @brief Gets the integer attribute from `pugi::xml_node`
54  *
55  * @param[in] node The node
56  * @param[in] str The string identifying value name
57  * @param[in] defVal The default value
58  * @return An integer value
59  */
60 INFERENCE_ENGINE_API_CPP(int) GetIntAttr(const pugi::xml_node& node, const char* str, int defVal);
61 
62 /**
63  * @brief Gets the `int64_t` attribute from `pugi::xml_node`
64  * @ingroup ie_dev_api_xml
65  *
66  * @param[in] node The node
67  * @param[in] str The string identifying value name
68  * @return An `int64_t` value
69  */
70 INFERENCE_ENGINE_API_CPP(int64_t) GetInt64Attr(const pugi::xml_node& node, const char* str);
71 
72 /**
73  * @brief Gets the `int64_t` attribute from `pugi::xml_node`
74  * @ingroup ie_dev_api_xml
75  *
76  * @param[in] node The node
77  * @param[in] str The string identifying value name
78  * @param[in] defVal The default value
79  * @return An `int64_t` value
80  */
81 INFERENCE_ENGINE_API_CPP(int64_t) GetInt64Attr(const pugi::xml_node& node, const char* str, int64_t defVal);
82 
83 /**
84  * @brief Gets the `uint64_t` attribute from `pugi::xml_node`
85  * @ingroup ie_dev_api_xml
86  *
87  * @param[in] node The node
88  * @param[in] str The string identifying value name
89  * @return An `uint64_t` value
90  */
91 INFERENCE_ENGINE_API_CPP(uint64_t) GetUInt64Attr(const pugi::xml_node& node, const char* str);
92 
93 /**
94  * @brief Gets the `uint64_t` attribute from `pugi::xml_node`
95  * @ingroup ie_dev_api_xml
96  *
97  * @param[in] node The node
98  * @param[in] str The string identifying value name
99  * @param[in] defVal The default value
100  * @return An `uint64_t` value
101  */
102 INFERENCE_ENGINE_API_CPP(uint64_t) GetUInt64Attr(const pugi::xml_node& node, const char* str, uint64_t defVal);
103 
104 /**
105  * @brief Gets the unsigned integer attribute from `pugi::xml_node`
106  * @ingroup ie_dev_api_xml
107  *
108  * @param[in] node The node
109  * @param[in] str The string identifying value name
110  * @return An unsigned integer value
111  */
112 INFERENCE_ENGINE_API_CPP(unsigned int) GetUIntAttr(const pugi::xml_node& node, const char* str);
113 
114 /**
115  * @brief Gets the unsigned integer attribute from `pugi::xml_node`
116  * @ingroup ie_dev_api_xml
117  *
118  * @param[in] node The node
119  * @param[in] str The string identifying value name
120  * @param[in] defVal The default value
121  * @return An unsigned integer value
122  */
123 INFERENCE_ENGINE_API_CPP(unsigned int) GetUIntAttr(const pugi::xml_node& node, const char* str, unsigned int defVal);
124 
125 /**
126  * @brief Gets the string attribute from `pugi::xml_node`
127  * @ingroup ie_dev_api_xml
128  *
129  * @param[in] node The node
130  * @param[in] str The string identifying value name
131  * @return A string value
132  */
133 INFERENCE_ENGINE_API_CPP(std::string) GetStrAttr(const pugi::xml_node& node, const char* str);
134 
135 /**
136  * @brief Gets the string attribute from `pugi::xml_node`
137  * @ingroup ie_dev_api_xml
138  *
139  * @param[in] node The node
140  * @param[in] str The string identifying value name
141  * @param[in] def The default value
142  * @return A string value
143  */
144 INFERENCE_ENGINE_API_CPP(std::string) GetStrAttr(const pugi::xml_node& node, const char* str, const char* def);
145 
146 /**
147  * @brief Gets the bool attribute from `pugi::xml_node`
148  * @ingroup ie_dev_api_xml
149  *
150  * @param[in] node The node
151  * @param[in] str The string identifying value name
152  * @return A boolean value
153  */
154 INFERENCE_ENGINE_API_CPP(bool) GetBoolAttr(const pugi::xml_node& node, const char* str);
155 
156 /**
157  * @brief Gets the bool attribute from `pugi::xml_node`
158  * @ingroup ie_dev_api_xml
159  *
160  * @param[in] node The node
161  * @param[in] str The string identifying value name
162  * @param[in] def The default value
163  * @return A boolean value
164  */
165 INFERENCE_ENGINE_API_CPP(bool) GetBoolAttr(const pugi::xml_node& node, const char* str, const bool def);
166 
167 /**
168  * @brief Gets the float attribute from `pugi::xml_node`
169  * @ingroup ie_dev_api_xml
170  *
171  * @param[in] node The node
172  * @param[in] str The string identifying value name
173  * @return A single-precision floating point value
174  */
175 INFERENCE_ENGINE_API_CPP(float) GetFloatAttr(const pugi::xml_node& node, const char* str);
176 
177 /**
178  * @brief Gets the float attribute from `pugi::xml_node`
179  * @ingroup ie_dev_api_xml
180  *
181  * @param[in] node The node
182  * @param[in] str The string identifying value name
183  * @param[in] defVal The default value
184  * @return A single-precision floating point value
185  */
186 INFERENCE_ENGINE_API_CPP(float) GetFloatAttr(const pugi::xml_node& node, const char* str, float defVal);
187 
188 /**
189  * @brief Gets the Precision attribute from `pugi::xml_node`
190  * @ingroup ie_dev_api_xml
191  *
192  * @param[in] node The node
193  * @param[in] str The string identifying value name
194  * @return A Precision value
195  */
196 INFERENCE_ENGINE_API_CPP(InferenceEngine::Precision) GetPrecisionAttr(const pugi::xml_node& node, const char* str);
197 
198 /**
199  * @brief Gets the Precision attribute from `pugi::xml_node`
200  * @ingroup ie_dev_api_xml
201  *
202  * @param[in] node The node
203  * @param[in] str The string identifying value name
204  * @param[in] def The default value
205  * @return A Precision value
206  */
207 INFERENCE_ENGINE_API_CPP(InferenceEngine::Precision)
208 GetPrecisionAttr(const pugi::xml_node& node, const char* str, InferenceEngine::Precision def);
209 
210 /**
211  * @brief Gets the integer value located in a child node.
212  * @ingroup ie_dev_api_xml
213  *
214  * @param[in] node The node
215  * @param[in] str The string value identifying a child node
216  * @param[in] defVal The default value
217  * @return An ingeter value located in a child node, @p devVal otherwise.
218  */
219 INFERENCE_ENGINE_API_CPP(int) GetIntChild(const pugi::xml_node& node, const char* str, int defVal);
220 
221 } // namespace XMLParseUtils
222 
223 /**
224  * @brief A XML parse result structure with an error message and the `pugi::xml_document` document.
225  * @ingroup ie_dev_api_xml
226  */
227 struct parse_result {
228  /**
229  * @brief Constructs parse_result with `pugi::xml_document` and an error message
230  *
231  * @param xml The `pugi::xml_document`
232  * @param[in] error_msg The error message
233  */
234  parse_result(std::unique_ptr<pugi::xml_document>&& xml, std::string error_msg)
235  : xml(std::move(xml)), error_msg(std::move(error_msg)) {}
236 
237  /**
238  * @brief A XML document.
239  */
240  std::unique_ptr<pugi::xml_document> xml;
241 
242  /**
243  * @brief An error message
244  */
245  std::string error_msg {};
246 };
247 
248 /**
249  * @brief Parses a file and returns parse_result
250  * @ingroup ie_dev_api_xml
251  *
252  * @param[in] file_path The file path
253  *
254  * @return The parse_result.
255  */
256 inline parse_result ParseXml(const char* file_path) {
257 #ifdef ENABLE_UNICODE_PATH_SUPPORT
258  std::wstring wFilePath = FileUtils::multiByteCharToWString(file_path);
259  const wchar_t* resolvedFilepath = wFilePath.c_str();
260 #else
261  const char* resolvedFilepath = file_path;
262 #endif
263 
264  try {
265  auto xml = std::unique_ptr<pugi::xml_document> {new pugi::xml_document {}};
266  const auto load_result = xml->load_file(resolvedFilepath);
267 
268  const auto error_msg = [&]() -> std::string {
269  if (load_result.status == pugi::status_ok) return {};
270 
271  std::ifstream file_stream(file_path);
272  const auto file = std::string(std::istreambuf_iterator<char> {file_stream}, std::istreambuf_iterator<char> {});
273 
274  const auto error_offset = std::next(file.rbegin(), file.size() - load_result.offset);
275  const auto line_begin = std::find(error_offset, file.rend(), '\n');
276  const auto line = 1 + std::count(line_begin, file.rend(), '\n');
277  const auto pos = std::distance(error_offset, line_begin);
278 
279  std::stringstream ss;
280  ss << "Error loading XML file: " << file_path << ":" << line << ":" << pos << ": " << load_result.description();
281  return ss.str();
282  }();
283 
284  return {std::move(xml), error_msg};
285  } catch(std::exception& e) {
286  return {std::move(nullptr), std::string("Error loading XML file: ") + e.what()};
287  }
288 }
Basic function to work with file system and UNICODE symbols.
bool GetBoolAttr(const pugi::xml_node &node, const char *str)
Gets the bool attribute from pugi::xml_node
uint64_t GetUInt64Attr(const pugi::xml_node &node, const char *str)
Gets the uint64_t attribute from pugi::xml_node
int GetIntChild(const pugi::xml_node &node, const char *str, int defVal)
Gets the integer value located in a child node.
int64_t GetInt64Attr(const pugi::xml_node &node, const char *str)
Gets the int64_t attribute from pugi::xml_node
std::string GetStrAttr(const pugi::xml_node &node, const char *str)
Gets the string attribute from pugi::xml_node
int GetIntAttr(const pugi::xml_node &node, const char *str)
Gets the integer attribute from pugi::xml_node
unsigned int GetUIntAttr(const pugi::xml_node &node, const char *str)
Gets the unsigned integer attribute from pugi::xml_node
InferenceEngine::Precision GetPrecisionAttr(const pugi::xml_node &node, const char *str)
Gets the Precision attribute from pugi::xml_node
float GetFloatAttr(const pugi::xml_node &node, const char *str)
Gets the float attribute from pugi::xml_node
parse_result ParseXml(const char *file_path)
Parses a file and returns parse_result.
Definition: xml_parse_utils.h:256
Inference Engine Plugin API namespace.
XML helpers function to extract values from pugi::xml_node
Definition: xml_parse_utils.h:40
A XML parse result structure with an error message and the pugi::xml_document document.
Definition: xml_parse_utils.h:227
std::unique_ptr< pugi::xml_document > xml
A XML document.
Definition: xml_parse_utils.h:240
parse_result(std::unique_ptr< pugi::xml_document > &&xml, std::string error_msg)
Constructs parse_result with pugi::xml_document and an error message.
Definition: xml_parse_utils.h:234