GCC Code Coverage Report


Directory: gridformat/
File: gridformat/xml/tag.hpp
Date: 2026-10-12 17:50:57
Exec Total Coverage
Lines: 40 42 95.2%
Functions: 46 46 100.0%
Branches: 18 39 46.2%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de>
2 // SPDX-License-Identifier: MIT
3 /*!
4 * \ingroup XML
5 * \copydoc GridFormat::XMLTag
6 */
7 #ifndef GRIDFORMAT_XML_TAG_HPP_
8 #define GRIDFORMAT_XML_TAG_HPP_
9
10 #include <ranges>
11 #include <concepts>
12 #include <string>
13 #include <string_view>
14 #include <utility>
15 #include <vector>
16 #include <algorithm>
17
18 #include <gridformat/common/exceptions.hpp>
19 #include <gridformat/common/string_conversion.hpp>
20
21 namespace GridFormat {
22
23 #ifndef DOXYGEN
24 namespace Detail {
25
26 template<typename Attribute>
27 1901300 auto _attr_find_lambda(std::string_view name) {
28 5844378 return [name] (const Attribute& attr) { return attr.first == name; };
29 }
30
31 template<typename T>
32 concept RepresentableAsString = requires(const T& t) {
33 { as_string(t) } -> std::convertible_to<std::string>;
34 };
35
36 } // end namespace Detail
37 #endif // DOXYGEN
38
39 /*!
40 * \ingroup XML
41 * \brief Class to represent an XML tag consisting of a name and attributes.
42 */
43 class XMLTag {
44 public:
45 using Attribute = std::pair<std::string, std::string>;
46
47 269132 explicit XMLTag(std::string name)
48 269132 : _name(std::move(name))
49 269132 {}
50
51 2204265 const std::string& name() const noexcept {
52 2204265 return _name;
53 }
54
55 3 std::size_t number_of_attributes() const noexcept {
56 3 return _attributes.size();
57 }
58
59 66528 bool has_attribute(std::string_view name) const {
60
1/2
✓ Branch 2 taken 66528 times.
✗ Branch 3 not taken.
66528 return _find(name) != _attributes.end();
61 }
62
63 template<Detail::RepresentableAsString ValueType>
64 1794058 void set_attribute(std::string attr_name, ValueType&& value) {
65
2/4
✓ Branch 2 taken 897029 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 897029 times.
1794058 if (auto it = _find(attr_name); it != _attributes.end())
66 ✗ *it = Attribute{std::move(attr_name), as_string(value)};
67 else
68
4/6
✓ Branch 2 taken 767900 times.
✓ Branch 3 taken 129115 times.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 897015 times.
✗ Branch 7 not taken.
1794058 _attributes.emplace_back(Attribute{std::move(attr_name), as_string(value)});
69 1794058 }
70
71 2 bool remove_attribute(std::string_view attr_name) {
72 2 return std::erase_if(_attributes, Detail::_attr_find_lambda<Attribute>(attr_name));
73 }
74
75 template<std::ranges::input_range R>
76 requires(std::convertible_to<std::ranges::range_value_t<R>, std::string_view>)
77 1 std::size_t remove_attributes(R&& attrs_to_remove) {
78 1 return std::erase_if(_attributes,
79 2 [&] (const Attribute& attr) {
80 2 return std::ranges::any_of(attrs_to_remove,
81 3 [&] (std::string_view attr_to_remove) {
82 3 return attr_to_remove == attr.first;
83 2 });
84 1 });
85 }
86
87 template<typename T = std::string>
88 913544 T get_attribute(std::string_view attr_name) const {
89
4/6
✓ Branch 1 taken 913536 times.
✓ Branch 2 taken 1 times.
✓ Branch 4 taken 913536 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 913532 times.
1827078 if (auto result = _get_attribute<T>(attr_name); result)
90 1827076 return *std::move(result);
91 ✗ throw InvalidState("No attribute with name '" + std::string(attr_name) + "'");
92 }
93
94 template<typename T = std::string>
95 48408 T get_attribute_or(T fallback, std::string_view attr_name) const {
96
2/4
✓ Branch 1 taken 24204 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11328 times.
✗ Branch 5 not taken.
48408 return _get_attribute<T>(attr_name).value_or(fallback);
97 }
98
99 226286 friend decltype(auto) attributes(const XMLTag& tag) {
100 226286 return std::views::keys(tag._attributes);
101 }
102
103 private:
104 template<typename T>
105 1158314 std::optional<T> _get_attribute(std::string_view attr_name) const {
106
3/4
✓ Branch 1 taken 937741 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 933441 times.
✓ Branch 6 taken 4300 times.
1158314 if (const auto it = _find(attr_name); it != _attributes.end())
107
2/2
✓ Branch 2 taken 933440 times.
✓ Branch 3 taken 1 times.
1149714 return from_string<T>(it->second);
108 8600 return {};
109 }
110
111 1004269 typename std::vector<Attribute>::const_iterator _find(std::string_view n) const {
112 1004269 return std::ranges::find_if(_attributes, Detail::_attr_find_lambda<Attribute>(n));
113 }
114 897029 typename std::vector<Attribute>::iterator _find(std::string_view n) {
115 897029 return std::ranges::find_if(_attributes, Detail::_attr_find_lambda<Attribute>(n));
116 }
117
118 std::string _name;
119 std::vector<Attribute> _attributes;
120 };
121
122 } // end namespace GridFormat
123
124 #endif // GRIDFORMAT_XML_TAG_HPP_
125