GCC Code Coverage Report


Directory: gridformat/
File: gridformat/reader.hpp
Date: 2024-11-10 16:24:00
Exec Total Coverage
Lines: 87 96 90.6%
Functions: 66 72 91.7%
Branches: 27 52 51.9%

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 * \file
5 * \ingroup API
6 * \brief A generic reader providing access to the readers for all supported formats.
7 */
8 #ifndef GRIDFORMAT_READER_HPP_
9 #define GRIDFORMAT_READER_HPP_
10
11 #include <array>
12 #include <vector>
13 #include <memory>
14 #include <utility>
15 #include <concepts>
16 #include <functional>
17 #include <optional>
18 #include <algorithm>
19 #include <iterator>
20 #include <string>
21
22 #include <gridformat/common/type_traits.hpp>
23 #include <gridformat/parallel/concepts.hpp>
24 #include <gridformat/parallel/communication.hpp>
25 #include <gridformat/grid/reader.hpp>
26
27 namespace GridFormat {
28
29 namespace FileFormat { struct Any; }
30
31 template<typename FileFormat>
32 struct ReaderFactory;
33
34 // Forward declaration, implementation in main API header.
35 template<Concepts::Communicator C = NullCommunicator>
36 class AnyReaderFactory {
37 public:
38 AnyReaderFactory() requires(std::same_as<C, NullCommunicator>) = default;
39 90 explicit AnyReaderFactory(const C& comm) : _comm{comm} {}
40 std::unique_ptr<GridReader> make_for(const std::string& filename) const;
41 private:
42 C _comm;
43 };
44
45 #ifndef DOXYGEN
46 namespace ReaderDetail {
47
48 template<typename FileFormat>
49 concept SequentiallyConstructible
50 = is_complete<ReaderFactory<FileFormat>>
51 and requires(const FileFormat& f) {
52 { ReaderFactory<FileFormat>::make(f) } -> std::derived_from<GridReader>;
53 };
54
55 template<typename FileFormat, typename Communicator>
56 concept ParallelConstructible
57 = is_complete<ReaderFactory<FileFormat>>
58 and Concepts::Communicator<Communicator>
59 and requires(const FileFormat& f, const Communicator& comm) {
60 { ReaderFactory<FileFormat>::make(f, comm) } -> std::derived_from<GridReader>;
61 };
62
63 template<typename FieldNameStorage>
64 1348 void copy_field_names(const GridReader& reader, FieldNameStorage& names) {
65
2/4
✓ Branch 2 taken 1348 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1348 times.
✗ Branch 6 not taken.
1348 std::ranges::copy(cell_field_names(reader), std::back_inserter(names.cell_fields));
66
2/4
✓ Branch 2 taken 1348 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1348 times.
✗ Branch 6 not taken.
1348 std::ranges::copy(point_field_names(reader), std::back_inserter(names.point_fields));
67
2/4
✓ Branch 2 taken 1348 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1348 times.
✗ Branch 6 not taken.
1348 std::ranges::copy(meta_data_field_names(reader), std::back_inserter(names.meta_data_fields));
68 1348 }
69
70 using ReaderFactoryFunctor = std::function<std::unique_ptr<GridReader>(const std::string&)>;
71
72 template<Concepts::Communicator C = NullCommunicator>
73 469 ReaderFactoryFunctor default_reader_factory(const C& c = {}) {
74
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 239 times.
469 if (!std::same_as<C, NullCommunicator>)
75 144 return [fac = AnyReaderFactory<C>{c}] (const std::string& f) { return fac.make_for(f); };
76 618 return [fac = AnyReaderFactory<>{}] (const std::string& f) { return fac.make_for(f); };
77 }
78
79 } // namespace ReaderDetail
80 #endif // DOXYGEN
81
82 /*!
83 * \ingroup API
84 * \brief Interface to the readers for all supported file formats.
85 * \details Typically you would construct this class with one of the predefined
86 * file format instances. For example, with the .vtu file format:
87 * \code{.cpp}
88 * GridFormat::Reader reader{GridFormat::vtu};
89 * \endcode
90 * \note Unless you pass in a custom ReaderFactoryFunctor, this class requires the
91 * AnyReaderFactory to be defined. Thus, this header cannot be included
92 * without the general API header gridformat.hpp which defines all formats.
93 */
94 class Reader : public GridReader {
95 public:
96 using ReaderFactoryFunctor = ReaderDetail::ReaderFactoryFunctor;
97
98 293 Reader(ReaderFactoryFunctor f = ReaderDetail::default_reader_factory())
99
1/2
✓ Branch 3 taken 293 times.
✗ Branch 4 not taken.
293 : _reader_factory{f}
100 293 {}
101
102 228 explicit Reader(const FileFormat::Any&, ReaderFactoryFunctor f = ReaderDetail::default_reader_factory())
103
2/4
✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 228 times.
✗ Branch 5 not taken.
228 : Reader(f)
104 228 {}
105
106 template<Concepts::Communicator C>
107 62 explicit Reader(const FileFormat::Any&, const C& c)
108
2/4
✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 62 times.
✗ Branch 5 not taken.
62 : Reader(ReaderDetail::default_reader_factory(c))
109 62 {}
110
111 template<ReaderDetail::SequentiallyConstructible FileFormat>
112 544 explicit Reader(const FileFormat& f)
113
2/4
✓ Branch 2 taken 272 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 272 times.
✗ Branch 6 not taken.
544 : _reader{_make_unique(ReaderFactory<FileFormat>::make(f))}
114 544 {}
115
116 template<typename FileFormat,
117 Concepts::Communicator Communicator>
118 requires(ReaderDetail::ParallelConstructible<FileFormat, Communicator>)
119 100 explicit Reader(const FileFormat& f, const Communicator& c)
120
2/4
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 54 times.
✗ Branch 6 not taken.
100 : _reader{_make_unique(ReaderFactory<FileFormat>::make(f, c))}
121 100 {}
122
123 //! Construct a reader instance from the given arguments, while directly opening the given file
124 template<typename... ConstructorArgs>
125 528 static Reader from(const std::string& filename, ConstructorArgs&&... args) {
126
5/8
✓ Branch 2 taken 220 times.
✓ Branch 3 taken 44 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 220 times.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 110 times.
✗ Branch 9 not taken.
528 return Reader{std::forward<ConstructorArgs>(args)...}.with_opened(filename);
127 }
128
129 //! Read the data from the given file and return this reader
130 Reader& with_opened(const std::string& filename) & {
131 this->open(filename);
132 return *this;
133 }
134
135 //! Read the data from the given file and return this reader (lvalue references overload)
136 306 Reader&& with_opened(const std::string& filename) && {
137 306 this->open(filename);
138 306 return std::move(*this);
139 }
140
141 private:
142 template<typename ReaderImpl>
143 652 auto _make_unique(ReaderImpl&& reader) const {
144 652 return std::make_unique<std::remove_cvref_t<ReaderImpl>>(std::move(reader));
145 }
146
147 42 std::string _name() const override {
148
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 if (_reader_is_set())
149 42 return _access_reader().name();
150 return "undefined";
151 }
152
153 622 void _open(const std::string& filename, typename GridReader::FieldNames& names) override {
154
2/2
✓ Branch 1 taken 293 times.
✓ Branch 2 taken 329 times.
622 if (_reader_factory)
155
1/2
✓ Branch 2 taken 293 times.
✗ Branch 3 not taken.
293 _reader = (*_reader_factory)(filename);
156 622 _access_reader().close();
157 622 _access_reader().open(filename);
158 619 ReaderDetail::copy_field_names(_access_reader(), names);
159 619 };
160
161 void _close() override {
162 _access_reader().close();
163 }
164
165 1949 std::size_t _number_of_cells() const override {
166 1949 return _access_reader().number_of_cells();
167 }
168
169 1826 std::size_t _number_of_points() const override {
170 1826 return _access_reader().number_of_points();
171 }
172
173 34 std::size_t _number_of_pieces() const override {
174 34 return _access_reader().number_of_pieces();
175 }
176
177 3130 FieldPtr _cell_field(std::string_view name) const override {
178 3130 return _access_reader().cell_field(name);
179 }
180
181 3160 FieldPtr _point_field(std::string_view name) const override {
182 3160 return _access_reader().point_field(name);
183 }
184
185 FieldPtr _meta_data_field(std::string_view name) const override {
186 return _access_reader().meta_data_field(name);
187 }
188
189 1371 void _visit_cells(const CellVisitor& v) const override {
190 1371 _access_reader().visit_cells(v);
191 1371 }
192
193 591 FieldPtr _points() const override {
194 591 return _access_reader().points();
195 }
196
197 18 typename GridReader::PieceLocation _location() const override {
198 18 return _access_reader().location();
199 }
200
201 6 std::vector<double> _ordinates(unsigned int dir) const override {
202 6 return _access_reader().ordinates(dir);
203 }
204
205 6 std::array<double, 3> _spacing() const override {
206 6 return _access_reader().spacing();
207 }
208
209 6 std::array<double, 3> _origin() const override {
210 6 return _access_reader().origin();
211 }
212
213 std::array<double, 3> _basis_vector(unsigned int dir) const override {
214 return _access_reader().basis_vector(dir);
215 }
216
217 560 bool _is_sequence() const override {
218 560 return _access_reader().is_sequence();
219 }
220
221 138 std::size_t _number_of_steps() const override {
222 138 return _access_reader().number_of_steps();
223 }
224
225 465 double _time_at_step(std::size_t step) const override {
226 465 return _access_reader().time_at_step(step);
227 }
228
229 465 void _set_step(std::size_t step, typename GridReader::FieldNames& field_names) override {
230 465 _access_reader().set_step(step);
231 465 field_names.clear();
232 465 ReaderDetail::copy_field_names(_access_reader(), field_names);
233 465 }
234
235 13302 const GridReader& _access_reader() const {
236 13302 _check_reader_access();
237 13302 return *_reader;
238 }
239
240 2793 GridReader& _access_reader() {
241 2793 _check_reader_access();
242 2793 return *_reader;
243 }
244
245 16095 void _check_reader_access() const {
246
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16095 times.
16095 if (!_reader_is_set())
247 throw InvalidState("No file has been read");
248 16095 }
249
250 16137 bool _reader_is_set() const {
251 16137 return static_cast<bool>(_reader);
252 }
253
254 std::unique_ptr<GridReader> _reader;
255 std::optional<ReaderFactoryFunctor> _reader_factory;
256 };
257
258 } // namespace GridFormat
259
260 #endif // GRIDFORMAT_WRITER_HPP_
261