GCC Code Coverage Report


Directory: gridformat/
File: gridformat/xml/tag.hpp
Date: 2024-11-20 14:41:59
Exec Total Coverage
Lines: 40 42 95.2%
Functions: 44 44 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 1808557 auto _attr_find_lambda(std::string_view name) {
28 5551508 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 260114 explicit XMLTag(std::string name)
48 260114 : _name(std::move(name))
49 260114 {}
50
51 2166125 const std::string& name() const noexcept {
52 2166125 return _name;
53 }
54
55 3 std::size_t number_of_attributes() const noexcept {
56 3 return _attributes.size();
57 }
58
59 62501 bool has_attribute(std::string_view name) const {
60
1/2
✓ Branch 2 taken 62501 times.
✗ Branch 3 not taken.
62501 return _find(name) != _attributes.end();
61 }
62
63 template<Detail::RepresentableAsString ValueType>
64 1714222 void set_attribute(std::string attr_name, ValueType&& value) {
65
2/4
✓ Branch 2 taken 857113 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 857113 times.
1714222 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 722166 times.
✓ Branch 3 taken 120647 times.
✓ Branch 4 taken 14300 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 842813 times.
✗ Branch 7 not taken.
1714222 _attributes.emplace_back(Attribute{std::move(attr_name), as_string(value)});
69 1714222 }
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 866566 T get_attribute(std::string_view attr_name) const {
89
4/6
✓ Branch 1 taken 866558 times.
✓ Branch 2 taken 1 times.
✓ Branch 4 taken 866558 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 866554 times.
1733122 if (auto result = _get_attribute<T>(attr_name); result)
90 1733120 return *std::move(result);
91 throw InvalidState("No attribute with name '" + std::string(attr_name) + "'");
92 }
93
94 template<typename T = std::string>
95 44764 T get_attribute_or(T fallback, std::string_view attr_name) const {
96
2/4
✓ Branch 1 taken 22382 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10504 times.
✗ Branch 5 not taken.
44764 return _get_attribute<T>(attr_name).value_or(fallback);
97 }
98
99 217564 friend decltype(auto) attributes(const XMLTag& tag) {
100 217564 return std::views::keys(tag._attributes);
101 }
102
103 private:
104 template<typename T>
105 1094053 std::optional<T> _get_attribute(std::string_view attr_name) const {
106
3/4
✓ Branch 1 taken 888941 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 885487 times.
✓ Branch 6 taken 3454 times.
1094053 if (const auto it = _find(attr_name); it != _attributes.end())
107
2/2
✓ Branch 2 taken 885486 times.
✓ Branch 3 taken 1 times.
1087145 return from_string<T>(it->second);
108 6908 return {};
109 }
110
111 951442 typename std::vector<Attribute>::const_iterator _find(std::string_view n) const {
112 951442 return std::ranges::find_if(_attributes, Detail::_attr_find_lambda<Attribute>(n));
113 }
114 857113 typename std::vector<Attribute>::iterator _find(std::string_view n) {
115 857113 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