5 #include <doocs/EqCall.h>
7 #include <libxml++/libxml++.h>
9 #include <boost/algorithm/string.hpp>
10 #include <boost/filesystem.hpp>
21 static std::unique_ptr<xmlpp::DomParser> createDomParser(
const std::string& xmlfile);
22 static xmlpp::Element* getRootNode(xmlpp::DomParser& parser);
23 static unsigned int convertToUint(
const std::string& s,
int line);
24 static int convertToInt(
const std::string& s,
int line);
26 static unsigned int parseLength(xmlpp::Element
const* c);
27 static int parseTypeId(xmlpp::Element
const* c);
28 static ChimeraTK::AccessModeFlags parseAccessMode(xmlpp::Element
const* c);
35 auto parser = createDomParser(xmlfile);
36 auto registerList = getRootNode(*parser);
38 for(
auto const node : registerList->get_children()) {
39 auto reg =
dynamic_cast<const xmlpp::Element*
>(node);
43 parseRegister(reg, catalogue);
50 return f.peek() == std::ifstream::traits_type::eof();
62 auto rootNode = doc.create_root_node(
"catalogue");
63 rootNode->set_attribute(
"version",
"1.0");
65 for(
auto& doocsRegInfo : c) {
66 addRegInfoXmlNode(doocsRegInfo, rootNode);
69 const std::string pathTemplate =
"%%%%%%-doocs-backend-cache-%%%%%%.tmp";
70 boost::filesystem::path temporaryName;
73 temporaryName = boost::filesystem::unique_path(boost::filesystem::path(pathTemplate));
75 catch(boost::filesystem::filesystem_error& e) {
76 throw ChimeraTK::runtime_error(std::string{
"Failed to generate temporary path: "} + e.what());
80 auto stream = std::ofstream(temporaryName);
81 doc.write_to_stream_formatted(stream);
87 if(
is_empty(std::ifstream(temporaryName))) {
88 throw ChimeraTK::runtime_error(std::string{
"Failed to save cache File"});
92 boost::filesystem::rename(temporaryName, xmlfile);
94 catch(boost::filesystem::filesystem_error& e) {
95 throw ChimeraTK::runtime_error(std::string{
"Failed to replace cache file: "} + e.what());
105 ChimeraTK::DataDescriptor descriptor{};
106 ChimeraTK::AccessModeFlags flags{};
108 for(
auto& node : registerNode->get_children()) {
109 auto e =
dynamic_cast<const xmlpp::Element*
>(node);
113 std::string nodeName = e->get_name();
115 if(nodeName ==
"name") {
116 name = e->get_child_text()->get_content();
118 else if(nodeName ==
"length") {
119 len = parseLength(e);
121 else if(nodeName ==
"access_mode") {
122 flags = parseAccessMode(e);
124 else if(nodeName ==
"doocs_type_id") {
125 doocsTypeId = parseTypeId(e);
129 bool is_ifff = (doocsTypeId == DATA_IFFF);
135 name.erase(name.end() - pattern.length(), name.end());
139 catalogue.
addProperty(name, len, doocsTypeId, flags);
144 unsigned int parseLength(xmlpp::Element
const* c) {
145 return convertToUint(c->get_child_text()->get_content(), c->get_line());
150 int parseTypeId(xmlpp::Element
const* c) {
151 return convertToInt(c->get_child_text()->get_content(), c->get_line());
156 ChimeraTK::AccessModeFlags parseAccessMode(xmlpp::Element
const* c) {
157 std::string accessMode{};
158 auto t = c->get_child_text();
160 accessMode = t->get_content();
162 return ChimeraTK::AccessModeFlags::deserialize(accessMode);
167 std::unique_ptr<xmlpp::DomParser> createDomParser(
const std::string& xmlfile) {
169 return std::make_unique<xmlpp::DomParser>(xmlfile);
171 catch(std::exception& e) {
172 throw ChimeraTK::logic_error(
"Error opening " + xmlfile +
": " + e.what());
178 xmlpp::Element* getRootNode(xmlpp::DomParser& parser) {
180 auto root = parser.get_document()->get_root_node();
181 if(root->get_name() !=
"catalogue") {
182 ChimeraTK::logic_error(
"Expected tag 'catalog' got: " + root->get_name());
186 catch(std::exception& e) {
187 throw ChimeraTK::logic_error(e.what());
193 unsigned int convertToUint(
const std::string& s,
int line) {
195 return std::stoul(s);
197 catch(std::invalid_argument& e) {
198 throw ChimeraTK::logic_error(
"Failed to parse node at line " + std::to_string(line) +
":" + e.what());
200 catch(std::out_of_range& e) {
201 throw ChimeraTK::logic_error(
"Failed to parse node at line " + std::to_string(line) +
":" + e.what());
206 int convertToInt(
const std::string& s,
int line) {
210 catch(std::invalid_argument& e) {
211 throw ChimeraTK::logic_error(
"Failed to parse node at line " + std::to_string(line) +
":" + e.what());
213 catch(std::out_of_range& e) {
214 throw ChimeraTK::logic_error(
"Failed to parse node at line " + std::to_string(line) +
":" + e.what());
221 auto registerTag = rootNode->add_child(
"register");
223 auto nameTag = registerTag->add_child(
"name");
224 nameTag->set_child_text(
static_cast<std::string
>(r.
getRegisterName()));
226 auto lengthTag = registerTag->add_child(
"length");
229 auto accessMode = registerTag->add_child(
"access_mode");
232 auto typeId = registerTag->add_child(
"doocs_type_id");
233 typeId->set_child_text(std::to_string(r.
doocsTypeId));
235 std::string comment_text = std::string(
"doocs id: ") + doocs::EqData().type_string(r.
doocsTypeId);
236 registerTag->add_child_comment(comment_text);