30template <
typename ValueType>
void write_scalar(std::ostream& stream,
const ValueType& value) {
31 stream.write(
reinterpret_cast<const char*
>(&value),
sizeof(ValueType));
34template <
typename ValueType> ValueType
read_scalar(std::istream& stream) {
36 stream.read(
reinterpret_cast<char*
>(&value),
sizeof(ValueType));
38 throw std::runtime_error(
"interpolation record: the file ended early; it is truncated.");
50 const std::streampos position = stream.tellg();
51 stream.seekg(0, std::ios::end);
52 const std::streampos end = stream.tellg();
53 stream.seekg(position);
54 if (position < 0 || end < position ||
static_cast<std::uint64_t
>(end - position) < bytes) {
55 throw std::runtime_error(
"interpolation record: a length field exceeds the bytes left in "
56 "the file; it is corrupt or truncated.");
60inline void write_string(std::ostream& stream,
const std::string& text) {
61 write_scalar<int64_t>(stream,
static_cast<int64_t
>(text.size()));
62 stream.write(text.data(),
static_cast<std::streamsize
>(text.size()));
66 const int64_t length = read_scalar<int64_t>(stream);
67 if (length < 0 || length > 1024) {
68 throw std::runtime_error(
"interpolation record: implausible string length; the file is "
71 std::string text(
static_cast<std::size_t
>(length),
'\0');
72 stream.read(text.data(), length);
74 throw std::runtime_error(
"interpolation record: the file ended early; it is truncated.");
80 write_scalar<double>(stream, vector.
x);
81 write_scalar<double>(stream, vector.
y);
82 write_scalar<double>(stream, vector.
z);
87 vector.
x = read_scalar<double>(stream);
88 vector.
y = read_scalar<double>(stream);
89 vector.
z = read_scalar<double>(stream);
94 for (
int row = 0; row < 3; row++) {
101 for (
int row = 0; row < 3; row++) {
108template <
typename ValueType>
109void write_array(std::ostream& stream,
const std::vector<ValueType>& values) {
110 write_scalar<int64_t>(stream,
static_cast<int64_t
>(values.size()));
111 if (!values.empty()) {
112 stream.write(
reinterpret_cast<const char*
>(values.data()),
113 static_cast<std::streamsize
>(values.size() *
sizeof(ValueType)));
117template <
typename ValueType> std::vector<ValueType>
read_array(std::istream& stream) {
118 const int64_t count = read_scalar<int64_t>(stream);
120 throw std::runtime_error(
"interpolation record: negative array length; the file is "
124 std::vector<ValueType> values(
static_cast<std::size_t
>(count));
126 stream.read(
reinterpret_cast<char*
>(values.data()),
127 static_cast<std::streamsize
>(values.size() *
sizeof(ValueType)));
129 throw std::runtime_error(
130 "interpolation record: the file ended early; it is truncated.");
136template <
typename ValueType>
138 write_scalar<int64_t>(stream,
static_cast<int64_t
>(rows.size()));
139 for (
const std::vector<ValueType>& row : rows) {
144template <
typename ValueType>
146 const int64_t count = read_scalar<int64_t>(stream);
148 throw std::runtime_error(
"interpolation record: negative array count; the file is "
152 std::vector<std::vector<ValueType>> rows(
static_cast<std::size_t
>(count));
153 for (std::vector<ValueType>& row : rows) {
154 row = read_array<ValueType>(stream);
void write_nested_arrays(std::ostream &stream, const std::vector< std::vector< ValueType > > &rows)
Vector3D read_vector3d(std::istream &stream)
std::vector< ValueType > read_array(std::istream &stream)
void write_matrix(std::ostream &stream, const Matrix3x3 &matrix)
std::string read_string(std::istream &stream)
void write_scalar(std::ostream &stream, const ValueType &value)
std::vector< std::vector< ValueType > > read_nested_arrays(std::istream &stream)
Matrix3x3 read_matrix(std::istream &stream)
ValueType read_scalar(std::istream &stream)
void require_bytes_available(std::istream &stream, std::uint64_t bytes)
void write_string(std::ostream &stream, const std::string &text)
void write_vector3d(std::ostream &stream, const Vector3D &vector)
void write_array(std::ostream &stream, const std::vector< ValueType > &values)
Length-prefixed array of trivially copyable values.
3×3 matrix stored row-major: row i = mat[i]