6#include <doocs/EqCall.h>
7#include <libxml++/libxml++.h>
9#include <boost/algorithm/string.hpp>
10#include <boost/filesystem.hpp>
23 static std::unique_ptr<xmlpp::DomParser> createDomParser(
const std::string& xmlfile);
24 static xmlpp::Element* getRootNode(xmlpp::DomParser& parser);
25 static unsigned int convertToUint(
const std::string& s,
int line);
26 static int convertToInt(
const std::string& s,
int line);
28 static unsigned int parseLength(xmlpp::Element
const* c);
29 static int parseTypeId(xmlpp::Element
const* c);
30 static ChimeraTK::AccessModeFlags parseAccessMode(xmlpp::Element
const* c);
37 auto parser = createDomParser(xmlfile);
38 auto registerList = getRootNode(*parser);
40 for(
auto const node : registerList->get_children()) {
41 auto reg =
dynamic_cast<const xmlpp::Element*
>(node);
45 parseRegister(reg, catalogue);
52 return f.peek() == std::ifstream::traits_type::eof();
64 auto rootNode = doc.create_root_node(
"catalogue");
65 rootNode->set_attribute(
"version",
"1.0");
67 for(
auto& doocsRegInfo : c) {
68 addRegInfoXmlNode(doocsRegInfo, rootNode);
71 const std::string pathTemplate =
"%%%%%%-doocs-backend-cache-%%%%%%.tmp";
72 boost::filesystem::path temporaryName;
75 temporaryName = boost::filesystem::unique_path(boost::filesystem::path(pathTemplate));
77 catch(boost::filesystem::filesystem_error& e) {
78 throw ChimeraTK::runtime_error(std::string{
"Failed to generate temporary path: "} + e.what());
82 auto stream = std::ofstream(temporaryName);
83 doc.write_to_stream_formatted(stream);
89 if(
is_empty(std::ifstream(temporaryName))) {
90 throw ChimeraTK::runtime_error(std::string{
"Failed to save cache File"});
94 boost::filesystem::rename(temporaryName, xmlfile);
96 catch(boost::filesystem::filesystem_error& e) {
97 throw ChimeraTK::runtime_error(std::string{
"Failed to replace cache file: "} + e.what());
107 ChimeraTK::DataDescriptor descriptor{};
108 ChimeraTK::AccessModeFlags flags{};
110 for(
auto& node : registerNode->get_children()) {
111 auto e =
dynamic_cast<const xmlpp::Element*
>(node);
115 std::string nodeName = e->get_name();
117 if(nodeName ==
"name") {
118 name = e->get_child_text()->get_content();
120 else if(nodeName ==
"length") {
121 len = parseLength(e);
123 else if(nodeName ==
"access_mode") {
124 flags = parseAccessMode(e);
126 else if(nodeName ==
"doocs_type_id") {
127 doocsTypeId = parseTypeId(e);
131 bool is_ifff = (doocsTypeId == DATA_IFFF);
137 name.erase(name.end() - pattern.length(), name.end());
141 catalogue.
addProperty(name, len, doocsTypeId, flags);
146 unsigned int parseLength(xmlpp::Element
const* c) {
147 return convertToUint(c->get_child_text()->get_content(), c->get_line());
152 int parseTypeId(xmlpp::Element
const* c) {
153 return convertToInt(c->get_child_text()->get_content(), c->get_line());
158 ChimeraTK::AccessModeFlags parseAccessMode(xmlpp::Element
const* c) {
159 std::string accessMode{};
160 auto t = c->get_child_text();
162 accessMode = t->get_content();
164 return ChimeraTK::AccessModeFlags::deserialize(accessMode);
169 std::unique_ptr<xmlpp::DomParser> createDomParser(
const std::string& xmlfile) {
171 return std::make_unique<xmlpp::DomParser>(xmlfile);
173 catch(std::exception& e) {
174 throw ChimeraTK::logic_error(
"Error opening " + xmlfile +
": " + e.what());
180 xmlpp::Element* getRootNode(xmlpp::DomParser& parser) {
182 auto root = parser.get_document()->get_root_node();
183 if(root->get_name() !=
"catalogue") {
184 ChimeraTK::logic_error(
"Expected tag 'catalog' got: " + root->get_name());
188 catch(std::exception& e) {
189 throw ChimeraTK::logic_error(e.what());
195 unsigned int convertToUint(
const std::string& s,
int line) {
197 return std::stoul(s);
199 catch(std::invalid_argument& e) {
200 throw ChimeraTK::logic_error(
"Failed to parse node at line " + std::to_string(line) +
":" + e.what());
202 catch(std::out_of_range& e) {
203 throw ChimeraTK::logic_error(
"Failed to parse node at line " + std::to_string(line) +
":" + e.what());
208 int convertToInt(
const std::string& s,
int line) {
212 catch(std::invalid_argument& e) {
213 throw ChimeraTK::logic_error(
"Failed to parse node at line " + std::to_string(line) +
":" + e.what());
215 catch(std::out_of_range& e) {
216 throw ChimeraTK::logic_error(
"Failed to parse node at line " + std::to_string(line) +
":" + e.what());
223 auto registerTag = rootNode->add_child(
"register");
225 auto nameTag = registerTag->add_child(
"name");
226 nameTag->set_child_text(
static_cast<std::string
>(r.
getRegisterName()));
228 auto lengthTag = registerTag->add_child(
"length");
231 auto accessMode = registerTag->add_child(
"access_mode");
234 auto typeId = registerTag->add_child(
"doocs_type_id");
235 typeId->set_child_text(std::to_string(r.
doocsTypeId));
237 std::string comment_text = std::string(
"doocs id: ") + doocs::EqData().type_string(r.
doocsTypeId);
238 registerTag->add_child_comment(comment_text);
void addProperty(const std::string &name, unsigned int length, int doocsType, ChimeraTK::AccessModeFlags flags)
ChimeraTK::RegisterPath getRegisterName() const override
ChimeraTK::AccessModeFlags accessModeFlags
unsigned int getNumberOfElements() const override
bool is_empty(std::ifstream &f)
DoocsBackendRegisterCatalogue readCatalogue(const std::string &xmlfile)
void saveCatalogue(const DoocsBackendRegisterCatalogue &c, const std::string &xmlfile)
std::pair< bool, std::string > endsWith(std::string const &s, const std::vector< std::string > &patterns)