ATLAS Offline Software
Loading...
Searching...
No Matches
libxml2Helper.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include <libxml/parser.h>
6#include <string>
7#include <string_view>
8#include <charconv>
9#include <type_traits>
10#include <stdexcept>
12
14
15//Note you will need to include the package LibXml2 in your package to use these methods.
16
17namespace CxxUtils{
18
19template <typename T>
20[[nodiscard]] T GetXmlAttr(xmlNodePtr node, const char* attrName, const T &defaultValue = T{})
21 noexcept(std::is_arithmetic_v<T>) // ← conditional on type
22{
23 // 1. Grab the raw property
24 xmlChar* raw = xmlGetProp(node, BAD_CAST attrName);
25 if (!raw) {
26 return defaultValue;
27 }
28
29 // Convert to a string_view for easy handling without extra copies
30 std::string_view sv(reinterpret_cast<const char*>(raw));
31 T result = defaultValue;
32
33 // 2. Handle conversion based on type
34 if constexpr (std::is_same_v<T, std::string>) {
35 result = std::string(sv);
36 } else if constexpr (std::is_arithmetic_v<T>) {
37 // std::from_chars requires a pointer range [first, last)
38 auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), result);
39
40 // If parsing fails (e.g. non-numeric string), result remains defaultValue
41 if (ec != std::errc{}) {
42 result = defaultValue;
43 }
44 } else
45 {
46 static_assert(false, "Type not implemented");
47 }
48
49 // 3. The most important part: Free the libxml2 memory!
50 xmlFree(raw);
51
52 return result;
53}
54
55template <typename T>
56void GetXmlAttrIfThere(xmlNodePtr node, const char* attrName, T &value)
57{
58 // 1. Grab the raw property
59 xmlChar* raw = xmlGetProp(node, BAD_CAST attrName);
60 if (!raw) {
61 return;
62 }
63
64 // Convert to a string_view for easy handling without extra copies
65 std::string_view sv(reinterpret_cast<const char*>(raw));
66
67 // 2. Handle conversion based on type
68 if constexpr (std::is_same_v<T, std::string>) {
69 value = std::string(sv);
70 } else if constexpr (std::is_arithmetic_v<T>) {
71 // std::from_chars requires a pointer range [first, last)
72 auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), value);
73 if (ec != std::errc{}){
74 xmlFree(raw);
75 throw std::runtime_error("Cannot read value");
76 }
77 } else
78 {
79 static_assert(false, "Type not implemented");
80 }
81
82 // 3. The most important part: Free the libxml2 memory!
83 xmlFree(raw);
84
85}
86
87template <typename X, typename COL>
88void AddXmlToCollectionMap(xmlNodePtr node, const char* attrName, COL &collection)
89{
90 // 1. Grab the raw property
91 xmlChar* raw = xmlGetProp(node, BAD_CAST attrName);
92 if (!raw) {
93 return;
94 }
95
96 // Convert to a string_view for easy handling without extra copies
97 std::string_view sv(reinterpret_cast<const char*>(raw));
98 X result{};
99 // 2. Handle conversion based on type
100 if constexpr (std::is_same_v<X, std::string>) {
101 result = std::string(sv);
102 } else if constexpr (std::is_arithmetic_v<X>) {
103 // std::from_chars requires a pointer range [first, last)
104 auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), result);
105 if (ec != std::errc{}){
106 xmlFree(raw);
107 throw std::runtime_error("Cannot read value");
108 }
109 } else
110 {
111 static_assert(false, "Type not implemented");
112 }
113
114 // 3. The most important part: Free the libxml2 memory!
115 xmlFree(raw);
116 collection.emplace(attrName, std::move(result));
117}
118
119template <typename X, typename COL>
120void AddXmlToCollection(xmlNodePtr node, const char* attrName, COL &collection)
121{
122 // 1. Grab the raw property
123 xmlChar* raw = xmlGetProp(node, BAD_CAST attrName);
124 if (!raw) {
125 return;
126 }
127
128 // Convert to a string_view for easy handling without extra copies
129 std::string_view sv(reinterpret_cast<const char*>(raw));
130 X result{};
131 // 2. Handle conversion based on type
132 if constexpr (std::is_same_v<X, std::string>) {
133 result = std::string(sv);
134 } else if constexpr (std::is_arithmetic_v<X>) {
135 // std::from_chars requires a pointer range [first, last)
136 auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), result);
137 if (ec != std::errc{}){
138 xmlFree(raw);
139 throw std::runtime_error("Cannot read value");
140 }
141 } else
142 {
143 static_assert(false, "Type not implemented");
144 }
145
146 // 3. The most important part: Free the libxml2 memory!
147 xmlFree(raw);
148 collection.emplace_back(std::move(result));
149}
150
151};
unsigned char xmlChar
Define macros for attributes used to control the static checker.
#define ATLAS_NO_CHECK_FILE_THREAD_SAFETY
Definition node.h:24
void AddXmlToCollectionMap(xmlNodePtr node, const char *attrName, COL &collection)
void AddXmlToCollection(xmlNodePtr node, const char *attrName, COL &collection)
void GetXmlAttrIfThere(xmlNodePtr node, const char *attrName, T &value)
T GetXmlAttr(xmlNodePtr node, const char *attrName, const T &defaultValue=T{}) noexcept(std::is_arithmetic_v< T >)
unsigned long long T
void * ptr(T *p)
Definition SGImplSvc.cxx:74