OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
CompletedSourceArchive.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2
11
12#pragma once
13#include <array>
14#include <cstdint>
15#include <cstring>
16#include <stdexcept>
17#include <string>
18#include <type_traits>
19#include <utility>
20#include <vector>
21
22namespace openswmm::detail {
23// Internal, same-platform, versioned source-boundary archive. Explicit fields
24// only: no object padding, pointers, streams or raw solver objects on disk.
26public:
40 explicit CompletedSourceArchive(std::string bytes) : bytes_(std::move(bytes)), reading_(true) {}
45 bool reading() const { return reading_; }
51 const std::string& bytes() const { return bytes_; }
59 void finish() const {
60 if (reading_ && offset_ != bytes_.size())
61 fail();
62 }
63
72 template <class... T> void operator()(T&... values) { (field(values), ...); }
82 template <class... T> void fixed(T&... values) { (fixedOne(values), ...); }
90 void fixedStrided(std::vector<double>& value, std::size_t extent,
91 std::size_t first, std::size_t stride) {
92 uint64_t size = extent;
93 field(size);
94 allocate(size, sizeof(double));
95 if (reading_) {
96 if (size > bytes_.size() - offset_)
97 fail();
98 if (size != extent)
99 throw std::runtime_error(
100 "Checkpoint vector shape differs: saved " + std::to_string(size) + ", model " +
101 std::to_string(extent) + ", offset " + std::to_string(offset_) + ".");
102 }
103 for (std::size_t i = 0; i < extent; ++i)
104 field(value[first + i * stride]);
105 }
106
112 void fixedColumnMajor(std::vector<double>& value, std::size_t columns) {
113 if (value.empty() || columns < 2) {
114 fixed(value);
115 return;
116 }
117 uint64_t size = value.size();
118 field(size);
119 allocate(size, sizeof(double));
120 if (reading_) {
121 if (size > bytes_.size() - offset_)
122 fail();
123 if (size != value.size())
124 throw std::runtime_error(
125 "Checkpoint vector shape differs: saved " + std::to_string(size) + ", model " +
126 std::to_string(value.size()) + ", offset " + std::to_string(offset_) + ".");
127 }
128 const std::size_t rows = value.size() / columns;
129 for (std::size_t column = 0; column < columns; ++column)
130 for (std::size_t row = 0; row < rows; ++row)
131 field(value[row * columns + column]);
132 }
133
139 void fixedColumnMajorBlocks(std::vector<double>& value, std::size_t blocks,
140 std::size_t columns) {
141 if (value.empty() || columns < 2) {
142 fixed(value);
143 return;
144 }
145 uint64_t size = value.size();
146 field(size);
147 allocate(size, sizeof(double));
148 if (reading_) {
149 if (size > bytes_.size() - offset_)
150 fail();
151 if (size != value.size())
152 throw std::runtime_error(
153 "Checkpoint vector shape differs: saved " + std::to_string(size) + ", model " +
154 std::to_string(value.size()) + ", offset " + std::to_string(offset_) + ".");
155 }
156 const std::size_t rows = value.size() / (blocks * columns);
157 for (std::size_t block = 0; block < blocks; ++block)
158 for (std::size_t column = 0; column < columns; ++column)
159 for (std::size_t row = 0; row < rows; ++row)
160 field(value[(block * rows + row) * columns + column]);
161 }
162 template <class T, class F>
179 void sequence(std::vector<T>& value, F visit, bool fixed_size = false) {
180 uint64_t size = value.size();
181 field(size);
182 allocate(size, sizeof(T));
183 if (reading_) {
184 if (size > bytes_.size() - offset_)
185 fail();
186 if (fixed_size && size != value.size())
187 throw std::runtime_error(
188 "Checkpoint vector shape differs: saved " + std::to_string(size) + ", model " +
189 std::to_string(value.size()) + ", offset " + std::to_string(offset_) + ".");
190 value.resize(static_cast<std::size_t>(size));
191 }
192 for (auto& element : value)
193 visit(element);
194 }
195
196private:
197 std::string bytes_;
198 std::size_t offset_ = 0;
199 bool reading_ = false;
200 uint64_t allocation_remaining_ = 64 * 1024 * 1024;
211 void allocate(uint64_t count, uint64_t width) {
212 if (count > allocation_remaining_ / width)
213 fail();
214 allocation_remaining_ -= count * width;
215 }
221 [[noreturn]] static void fail() {
222 throw std::runtime_error("Invalid completed-source checkpoint record.");
223 }
224 template <class T>
237 void field(T& value)
238 requires(std::is_arithmetic_v<T> || std::is_enum_v<T>)
239 {
240 if (reading_) {
241 if (sizeof(T) > bytes_.size() - offset_)
242 fail();
243 // Invalid bool representations must not enter a C++ object.
244 if constexpr (std::is_same_v<T, bool>) {
245 const auto v = static_cast<unsigned char>(bytes_[offset_]);
246 if (v > 1)
247 fail();
248 value = v != 0;
249 } else
250 std::memcpy(&value, bytes_.data() + offset_, sizeof(T));
251 offset_ += sizeof(T);
252 } else
253 bytes_.append(reinterpret_cast<const char*>(&value), sizeof(T));
254 }
265 void field(std::string& value) {
266 uint64_t size = value.size();
267 field(size);
268 allocate(size, 1);
269 if (reading_) {
270 if (size > bytes_.size() - offset_)
271 fail();
272 value.assign(bytes_.data() + offset_, static_cast<std::size_t>(size));
273 offset_ += size;
274 } else
275 bytes_.append(value);
276 }
286 template <class T> void fixedOne(std::vector<T>& value) {
287 sequence(value, [&](auto& element) { field(element); }, true);
288 }
299 void fixedOne(std::vector<bool>& value) {
300 uint64_t size = value.size();
301 field(size);
302 if (reading_ && (size != value.size() || size > bytes_.size() - offset_))
303 fail();
304 for (std::size_t i = 0; i < value.size(); ++i) {
305 bool element = value[i];
306 field(element);
307 if (reading_)
308 value[i] = element;
309 }
310 }
320 template <class T> void field(std::vector<T>& value) {
321 sequence(value, [&](auto& element) { field(element); });
322 }
332 void field(std::vector<bool>& value) {
333 uint64_t size = value.size();
334 field(size);
335 allocate(size, 1);
336 if (reading_) {
337 if (size > bytes_.size() - offset_)
338 fail();
339 value.resize(size);
340 }
341 for (std::size_t i = 0; i < value.size(); ++i) {
342 bool element = value[i];
343 field(element);
344 if (reading_)
345 value[i] = element;
346 }
347 }
357 template <class T, std::size_t N> void field(std::array<T, N>& value) {
358 for (auto& element : value)
359 field(element);
360 }
369 template <class A, class B> void field(std::pair<A, B>& value) {
370 field(value.first);
371 field(value.second);
372 }
373};
374}
CompletedSourceArchive()=default
Create an empty write-mode same-platform byte archive.
void finish() const
Reject trailing unconsumed bytes after read-mode field visitation.
Definition CompletedSourceArchive.hpp:59
const std::string & bytes() const
Borrow the complete owned byte buffer.
Definition CompletedSourceArchive.hpp:51
void fixedColumnMajorBlocks(std::vector< double > &value, std::size_t blocks, std::size_t columns)
Stream equal owned row-major matrix blocks in legacy block/column/row order. blocks and columns are s...
Definition CompletedSourceArchive.hpp:139
void sequence(std::vector< T > &value, F visit, bool fixed_size=false)
Visit a vector count and then each element through a supplied visitor.
Definition CompletedSourceArchive.hpp:179
void fixedColumnMajor(std::vector< double > &value, std::size_t columns)
Stream a row-major owned double matrix in legacy column-major wire order. columns is the stable model...
Definition CompletedSourceArchive.hpp:112
CompletedSourceArchive(std::string bytes)
Own a byte string and enter read mode at offset zero.
Definition CompletedSourceArchive.hpp:40
void fixed(T &... values)
Visit vectors while requiring saved lengths to match current destination shapes.
Definition CompletedSourceArchive.hpp:82
void fixedStrided(std::vector< double > &value, std::size_t extent, std::size_t first, std::size_t stride)
Visit one fixed logical double vector inside interleaved owned storage.
Definition CompletedSourceArchive.hpp:90
void operator()(T &... values)
Visit fields in argument order using their supported archive encodings.
Definition CompletedSourceArchive.hpp:72
bool reading() const
Test archive direction.
Definition CompletedSourceArchive.hpp:45
Definition OutfallExchange.hpp:17
long value(FvCounter counter) noexcept
Read one process-global completed FV counter total.
Definition PerfTimers.hpp:136