15 #ifndef OPENSCENARIO_INTERPRETER__READER__ELEMENT_HPP_
16 #define OPENSCENARIO_INTERPRETER__READER__ELEMENT_HPP_
24 #include <pugixml.hpp>
26 #include <type_traits>
27 #include <unordered_map>
39 inline namespace reader
42 typename std::iterator_traits<typename pugi::xml_node::iterator>::difference_type;
44 constexpr
auto unbounded = std::numeric_limits<Cardinality>::max();
46 template <Cardinality MinOccurs, Cardinality MaxOccurs,
typename F>
49 const auto children = parent.children(name.c_str());
52 if (MinOccurs != 0 and
size < MinOccurs) {
54 parent.name(),
" requires class ", name,
" at least ", MinOccurs,
" element",
55 (1 < MinOccurs ?
"s" :
""),
", but ",
size,
" element", (1 <
size ?
"s" :
""),
57 }
else if (MaxOccurs <
size) {
59 parent.name(),
" requires class ", name,
" at most ", MaxOccurs,
" element",
60 (1 < MaxOccurs ?
"s" :
""),
", but ",
size,
" element", (1 <
size ?
"s" :
""),
63 for (
const auto & child : children) {
67 }
else if (MinOccurs != 0) {
69 parent.name(),
" requires class ", name,
" at least ", MinOccurs,
" element",
70 (1 < MinOccurs ?
"s" :
""),
", but there is no specification");
74 template <
typename T,
typename Scope>
77 if (
const auto child = parent.child(name.c_str())) {
78 return T(child, scope);
88 parent.name(),
" requires class ", name,
" as element, but there is no declaration"));
92 template <
typename T,
typename U,
typename Scope>
95 if constexpr (std::is_same<T,
typename std::decay<U>::type>::value) {
98 if (
const auto child = parent.child(name.c_str())) {
99 return T(child, scope);
105 if (
const auto child = parent.child(name.c_str())) {
106 return T(child, scope, value);
109 parent.name(),
" requires class ", name,
" as element, but there is no declaration"));
117 std::list<T> elements;
119 traverse<MinOccurs, MaxOccurs>(node, name, [&](
auto && x) {
120 elements.emplace_back(std::forward<decltype(x)>(x), std::forward<decltype(
xs)>(
xs)...);
129 std::list<GroupT> groups;
131 for (
auto child = node.begin(); child != node.end(); ++child) {
133 groups.template emplace_back(
134 std::forward<decltype(*child)>(*child), std::forward<decltype(
xs)>(
xs)...);
139 if (MinOccurs != 0 and groups.size() < MinOccurs) {
141 node.name(),
" requires Group ",
demangle(
typeid(GroupT)),
" at least ", MinOccurs,
142 " element", (1 < MinOccurs ?
"s" :
""),
", but ", groups.size(),
" element",
143 (1 < groups.size() ?
"s" :
""),
" specified");
146 if (MaxOccurs < groups.size()) {
148 node.name(),
" requires Group ",
demangle(
typeid(GroupT)),
" at most ", MaxOccurs,
" element",
149 (1 < MaxOccurs ?
"s" :
""),
", but ", groups.size(),
" element",
150 (1 < groups.size() ?
"s" :
""),
" specified");
156 template <
typename... Ts>
157 auto choice(
const pugi::xml_node & node, Ts &&...
xs) -> decltype(
auto)
159 const std::unordered_map<
std::string, std::function<
Object(
const pugi::xml_node &)>> callees{
160 std::forward<decltype(xs)>(
xs)...};
162 std::unordered_map<std::string, pugi::xml_node> specs{};
164 for (
const auto & each : callees) {
165 if (
const auto child = node.child(std::get<0>(each).c_str())) {
166 specs.emplace(std::get<0>(each), child);
170 auto print_keys_to = [&](
auto & os,
const auto &
xs) -> decltype(
auto) {
171 if (not
xs.empty()) {
172 for (
auto iter = std::begin(
xs); iter != std::end(
xs); ++iter) {
173 os << std::get<0>(*iter);
194 std::stringstream what;
195 what <<
"Class " << node.name() <<
" requires one of following elements: ";
197 what <<
". But no element specified";
198 throw SyntaxError(what.str());
199 }
else if (1 < specs.size()) {
200 std::stringstream what;
201 what <<
"Class " << node.name() <<
" requires just one of following elements: ";
203 what <<
". But " << specs.size() <<
" element" << (1 < specs.size() ?
"s" :
"") <<
" (";
205 what <<
") specified";
206 throw SyntaxError(what.str());
208 const auto iter = std::cbegin(specs);
209 return callees.at(std::get<0>(*iter))(std::get<1>(*iter));
Definition: scope.hpp:154
auto size(const T &range)
Definition: size.hpp:25
auto choice(const pugi::xml_node &node, Ts &&... xs) -> decltype(auto)
Definition: element.hpp:157
auto readElements(const std::string &name, const pugi::xml_node &node, Ts &&... xs)
Definition: element.hpp:115
auto traverse(const pugi::xml_node &parent, const std::string &name, F &&f) -> void
Definition: element.hpp:47
typename std::iterator_traits< typename pugi::xml_node::iterator >::difference_type Cardinality
Definition: element.hpp:42
auto readElement(const std::string &name, const pugi::xml_node &parent, Scope &scope)
Definition: element.hpp:75
constexpr auto unbounded
Definition: element.hpp:44
auto readGroups(const pugi::xml_node &node, Ts &&... xs)
Definition: element.hpp:127
auto demangle(const char *name) -> std::string
Definition: demangle.cpp:26
auto print_keys_to
Definition: print.hpp:49
Definition: escape_sequence.hpp:22
Pointer< Expression > Object
Definition: object.hpp:26
auto distance(const geometry_msgs::Pose &pose1, const geometry_msgs::Pose &pose2)
Definition: detection_sensor.cpp:34
Definition: junit5.hpp:25
std::string string
Definition: junit5.hpp:26
Definition: must_be_default_constructible.hpp:27