NGen
Loading...
Searching...
No Matches
record.hpp
1/*
2Author: Nels Frazier
3Copyright (C) 2025 Lynker
4------------------------------------------------------------------------
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16------------------------------------------------------------------------
17The value-type contract shared between record producers and
18record-storage backends.
19
20A `Record` (in the `ngen::serialization` namespace) is the
21engine-agnostic interchange unit between code that *produces* a
22piece of saved state (e.g. a BMI adapter capturing a model's
23bytes) and code that *stores* that state (e.g. a file backend
24that lays it out on disk, an HDF5 backend that stores it as a
25dataset + attributes, or any future storage).
26
27This header defines only the value type and a small parse helper.
28It does NOT prescribe a wire format — backends are free to encode
29the fields however suits their storage.
30*/
31#pragma once
32
33#include <boost/core/span.hpp>
34
35#include <cctype>
36#include <cstdint>
37#include <ctime>
38#include <exception>
39#include <limits>
40#include <string>
41#include <vector>
42
43namespace ngen{ namespace serialization{
54constexpr const char* TIMESTAMP_STRPTIME_FORMAT = "%Y-%m-%d %T";
55
63 = (std::numeric_limits<int64_t>::min)();
64
74inline int64_t parse_epoch_string(const std::string& s) {
75 try {
76 std::size_t consumed = 0;
77 const long long v = std::stoll(s, &consumed);
78 while (consumed < s.size()
79 && std::isspace(static_cast<unsigned char>(s[consumed]))) {
80 ++consumed;
81 }
82 if (consumed == s.size()) {
83 return static_cast<int64_t>(v);
84 }
85 } catch (const std::exception&) {
86 // std::out_of_range / std::invalid_argument — fall through
87 // to the sentinel.
88 }
90}
91
99inline int64_t parse_formatted_time(const std::string& s) {
100 std::tm tm = {};
101 const char* end = ::strptime(s.c_str(), TIMESTAMP_STRPTIME_FORMAT, &tm);
102 if (end != nullptr) {
103 while (*end != '\0' && std::isspace(static_cast<unsigned char>(*end))) {
104 ++end;
105 }
106 if (*end == '\0') {
107 return static_cast<int64_t>(::timegm(&tm));
108 }
109 }
111}
112
120inline int64_t parse_timestamp(const std::string& s) {
121 if (s.empty()) return UNPARSEABLE_TIMESTAMP_SENTINEL;
122 const int64_t epoch = parse_epoch_string(s);
123 if (epoch != UNPARSEABLE_TIMESTAMP_SENTINEL) return epoch;
124 return parse_formatted_time(s);
125}
126
144namespace detail {
145
146// Shared field set for the two public checkpoint-record types
147// (`Record` and `RecordView`, below). Implementation alignment
148// mechanism only — adding or changing a metadata field touches
149// one definition and both aliases inherit the change.
150template <typename PayloadT>
151struct RecordT {
152 std::string id;
153 int64_t time_step = 0;
155 int64_t checkpoint_epoch = 0;
156 PayloadT payload{};
157
158 RecordT() = default;
159 RecordT(std::string id_,
160 int64_t time_step_,
161 int64_t simulation_timestamp_,
162 PayloadT payload_,
163 int64_t checkpoint_epoch_ = 0)
164 : id(std::move(id_))
165 , time_step(time_step_)
166 , simulation_timestamp(simulation_timestamp_)
167 , checkpoint_epoch(checkpoint_epoch_)
168 , payload(std::move(payload_)) {}
169};
170
171} // namespace detail
172
183
193
194}} // namespace ngen::serialization
int64_t parse_epoch_string(const std::string &s)
Parse s as a whole-string signed integer interpreted as Unix epoch seconds (e.g.
Definition record.hpp:74
int64_t parse_timestamp(const std::string &s)
Parse s as seconds-since-Unix-epoch.
Definition record.hpp:120
constexpr const char * TIMESTAMP_STRPTIME_FORMAT
Tests in parse_timestamp_Test.cpp pin both TIMESTAMP_STRPTIME_FORMAT and UNPARSEABLE_TIMESTAMP_SENTIN...
Definition record.hpp:54
constexpr int64_t UNPARSEABLE_TIMESTAMP_SENTINEL
Out-of-band value returned by parse_timestamp and its helpers when the input string cannot be resolve...
Definition record.hpp:63
int64_t parse_formatted_time(const std::string &s)
Parse s as a formatted timestamp matching TIMESTAMP_STRPTIME_FORMAT.
Definition record.hpp:99
Definition DomainLayer.hpp:13
STL namespace.
Definition record.hpp:151
int64_t time_step
Definition record.hpp:153
int64_t checkpoint_epoch
Definition record.hpp:155
std::string id
Definition record.hpp:152
PayloadT payload
Definition record.hpp:156
RecordT(std::string id_, int64_t time_step_, int64_t simulation_timestamp_, PayloadT payload_, int64_t checkpoint_epoch_=0)
Definition record.hpp:159
int64_t simulation_timestamp
Definition record.hpp:154