Collective Variables Module - Developer Documentation
Loading...
Searching...
No Matches
colvars_memstream.h
1// -*- c++ -*-
2
3// This file is part of the Collective Variables module (Colvars).
4// The original version of Colvars and its updates are located at:
5// https://github.com/Colvars/colvars
6// Please update all Colvars source files before making any changes.
7// If you wish to distribute your changes, please submit them to the
8// Colvars repository at GitHub.
9
10#ifndef MEMORY_STREAM_H
11#define MEMORY_STREAM_H
12
13#include <cstring>
14#include <string>
15#include <typeinfo>
16#include <vector>
17#include <iomanip>
18
19
20// Work around missing std::is_trivially_copyable in old GCC and Clang versions
21// TODO remove this after CentOS 7 has been beyond EOL for a while
22#if (defined(__GNUC__) && (__GNUC__ < 5) && !defined(__clang__)) || (defined(__clang__) && (__clang_major__ < 7))
23// Clang needs an exception, because it defines __GNUC__ as well
24#define IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
25#else
26#define IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
27#endif
28
29
31
32public:
33
36 memory_stream(size_t max_length = (static_cast<size_t>(1L) << 36)) : max_length_(max_length) {}
37
39 memory_stream(size_t n, unsigned char const *buf)
41 {
42 }
43
45 memory_stream(std::vector<unsigned char> &buf) : memory_stream()
46 {
48 }
49
51 inline size_t length() const { return data_length_; }
52
54 inline unsigned char *output_buffer()
55 {
57 }
58
60 inline unsigned char *output_location() { return output_buffer() + data_length_; }
61
63 inline unsigned char const *input_buffer() const
64 {
66 }
67
69 inline unsigned char const *input_location() const { return input_buffer() + read_pos_; }
70
72 inline explicit operator bool() const { return state_ == std::ios::goodbit; }
73
75 template <typename T> void write_object(T const &t);
76
78 template <typename T> friend memory_stream &operator<<(memory_stream &os, T const &t);
79
81 template <typename T> void write_vector(std::vector<T> const &t);
82
84 template <typename T>
85 friend memory_stream &operator<<(memory_stream &os, std::vector<T> const &t);
86
88 template <typename T> void read_object(T &t);
89
91 template <typename T> friend memory_stream &operator>>(memory_stream &is, T &t);
92
94 template <typename T> void read_vector(std::vector<T> &t);
95
97 template <typename T> friend memory_stream &operator>>(memory_stream &is, std::vector<T> &t);
98
99
100 // Compatibility with STL stream functions
101
103 inline size_t tellg() const { return read_pos_; }
104
106 inline memory_stream & seekg(size_t pos) { read_pos_ = pos; return *this; }
107
109 inline void setf(decltype(std::ios::fmtflags(0)), decltype(std::ios::floatfield)) {}
110
112 inline void setf(decltype(std::ios::fmtflags(0))) {}
113
115 inline void flags(decltype(std::ios::fmtflags(0))) {}
116
118 inline decltype(std::ios::fmtflags(0)) flags() const { return std::ios::fmtflags(0); }
119
121 inline std::ios::iostate rdstate() const { return state_; }
122
124 inline void setstate(std::ios::iostate new_state) { state_ |= new_state; }
125
127 inline void clear() { state_ = std::ios::goodbit; }
128
129protected:
130
132 std::vector<unsigned char> *external_output_buffer_ = nullptr;
133
135 unsigned char const *external_input_buffer_ = nullptr;
136
138 std::vector<unsigned char> internal_buffer_;
139
141 size_t data_length_ = 0L;
142
144 size_t const max_length_;
145
147 std::ios::iostate state_ = std::ios::goodbit;
148
150 bool expand_output_buffer(size_t add_bytes);
151
153 inline void incr_write_pos(size_t c) { data_length_ += c; }
154
156 size_t read_pos_ = 0L;
157
159 inline void begin_reading() { setstate(std::ios::eofbit); }
160
162 inline void done_reading() { clear(); }
163
165 inline void incr_read_pos(size_t c) { read_pos_ += c; }
166
169 inline bool has_remaining(size_t c) { return c <= (data_length_ - read_pos_); }
170 };
171
172template <typename T> void cvm::memory_stream::write_object(T const &t)
173{
174 static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use write_object() on complex type");
175 size_t const new_data_size = sizeof(T);
176 if (expand_output_buffer(new_data_size)) {
177 std::memcpy(output_location(), &t, sizeof(T));
178 incr_write_pos(new_data_size);
179 }
180}
181
182template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os, T const &t)
183{
184 os.write_object<T>(t);
185 return os;
186}
187
188template <typename T> void cvm::memory_stream::write_vector(std::vector<T> const &t)
189{
190 static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use write_vector() on complex type");
191 size_t const vector_length = t.size();
192 size_t const new_data_size = sizeof(size_t) + sizeof(T) * vector_length;
193 if (expand_output_buffer(new_data_size)) {
194 std::memcpy(output_location(), &vector_length, sizeof(size_t));
195 incr_write_pos(sizeof(T));
196 std::memcpy(output_location(), t.data(), t.size() * sizeof(T));
197 incr_write_pos(t.size() * sizeof(T));
198 }
199}
200
201template <typename T>
202cvm::memory_stream &operator<<(cvm::memory_stream &os, std::vector<T> const &t)
203{
204 os.write_vector<T>(t);
205 return os;
206}
207
208template <typename T> void cvm::memory_stream::read_object(T &t)
209{
210 static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use read_object() on complex type");
211 begin_reading();
212 if (has_remaining(sizeof(T))) {
213 std::memcpy(&t, input_location(), sizeof(T));
214 incr_read_pos(sizeof(T));
215 done_reading();
216 }
217}
218
219template <typename T> cvm::memory_stream &operator>>(cvm::memory_stream &is, T &t)
220{
221 is.read_object<T>(t);
222 return is;
223}
224
225template <typename T> void cvm::memory_stream::read_vector(std::vector<T> &t)
226{
227 static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use read_vector() on complex type");
228 begin_reading();
229 size_t vector_length = 0;
230 if (has_remaining(sizeof(size_t))) {
231 std::memcpy(&vector_length, input_location(), sizeof(size_t));
232 incr_read_pos(sizeof(size_t));
233 if (has_remaining(vector_length * sizeof(T))) {
234 t.resize(vector_length);
235 std::memcpy(t.data(), input_location(), vector_length * sizeof(T));
236 incr_read_pos(vector_length * sizeof(T));
237 done_reading();
238 } else {
239 setstate(std::ios::failbit);
240 }
241 }
242}
243
244template <typename T> cvm::memory_stream &operator>>(cvm::memory_stream &is, std::vector<T> &t)
245{
246 is.read_vector<T>(t);
247 return is;
248}
249
250template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os,
251 decltype(std::setprecision(10)) const &)
252{
253 return os;
254}
255
256#if !defined(_MSC_VER) && !defined(__SUNPRO_CC)
257// Visual Studio and MSVC use the same return type for both modifiers
258template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os,
259 decltype(std::setw(10)) const &)
260{
261 return os;
262}
263#endif
264
265// Declare specializations
266
267template <> void cvm::memory_stream::write_object(std::string const &t);
268
269template <> cvm::memory_stream &operator<<(cvm::memory_stream &os, std::string const &t);
270
271template <> void cvm::memory_stream::write_object(colvarvalue const &t);
272
273template <> cvm::memory_stream &operator<<(cvm::memory_stream &os, colvarvalue const &x);
274
276
277template <>
279
280template <> void cvm::memory_stream::read_object(std::string &t);
281
282template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, std::string &t);
283
285
286template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, colvarvalue &t);
287
289
290template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, cvm::vector1d<cvm::real> &t);
291
292#endif
Arbitrary size array (one dimensions) suitable for linear algebra operations (i.e....
Definition: colvartypes.h:37
Value of a collective variable: this is a metatype which can be set at runtime. By default it is set ...
Definition: colvarvalue.h:43
Definition: colvars_memstream.h:30
bool has_remaining(size_t c)
Definition: colvars_memstream.h:169
unsigned char * output_location()
Next location to write to.
Definition: colvars_memstream.h:60
std::ios::iostate state_
Error status.
Definition: colvars_memstream.h:147
void done_reading()
Mark the reading attempt succesful.
Definition: colvars_memstream.h:162
memory_stream(size_t n, unsigned char const *buf)
Set up a stream based on an external input buffer.
Definition: colvars_memstream.h:39
unsigned char * output_buffer()
Output buffer.
Definition: colvars_memstream.h:54
void write_object(T const &t)
Write a simple object to the output buffer.
Definition: colvars_memstream.h:172
std::ios::iostate rdstate() const
Get the error code.
Definition: colvars_memstream.h:121
void read_vector(std::vector< T > &t)
Read a vector of simple objects from the buffer.
Definition: colvars_memstream.h:225
void setf(decltype(std::ios::fmtflags(0)))
Ignore formatting operators.
Definition: colvars_memstream.h:112
std::vector< unsigned char > internal_buffer_
Internal buffer (may server for both input and output)
Definition: colvars_memstream.h:138
size_t read_pos_
Current position when reading from the buffer.
Definition: colvars_memstream.h:156
size_t length() const
Length of the buffer.
Definition: colvars_memstream.h:51
void write_vector(std::vector< T > const &t)
Write a vector of simple objects to the output buffer.
Definition: colvars_memstream.h:188
void incr_write_pos(size_t c)
Move the buffer position past the data just written.
Definition: colvars_memstream.h:153
void flags(decltype(std::ios::fmtflags(0)))
Ignore formatting operators.
Definition: colvars_memstream.h:115
void setstate(std::ios::iostate new_state)
Set the error code.
Definition: colvars_memstream.h:124
size_t data_length_
Length of the data buffer (either internal or external)
Definition: colvars_memstream.h:141
decltype(std::ios::fmtflags(0)) flags() const
Get the current formatting flags (i.e. none because this stream is unformatted)
Definition: colvars_memstream.h:118
unsigned char const * input_buffer() const
Input buffer.
Definition: colvars_memstream.h:63
memory_stream & seekg(size_t pos)
Report the current position in the buffer.
Definition: colvars_memstream.h:106
memory_stream(size_t max_length=(static_cast< size_t >(1L)<< 36))
Definition: colvars_memstream.h:36
size_t const max_length_
Largest allowed capacity of the data buffer.
Definition: colvars_memstream.h:144
unsigned char const * external_input_buffer_
External input buffer.
Definition: colvars_memstream.h:135
void incr_read_pos(size_t c)
Move the buffer position past the data just read.
Definition: colvars_memstream.h:165
std::vector< unsigned char > * external_output_buffer_
External output buffer.
Definition: colvars_memstream.h:132
unsigned char const * input_location() const
Next location to read from.
Definition: colvars_memstream.h:69
void read_object(T &t)
Read a simple object from the buffer.
Definition: colvars_memstream.h:208
void begin_reading()
Begin an attempt to read an object; assume EOF unless there is space remaining.
Definition: colvars_memstream.h:159
memory_stream(std::vector< unsigned char > &buf)
Set up a stream based on an external output buffer.
Definition: colvars_memstream.h:45
bool expand_output_buffer(size_t add_bytes)
Add the requester number of bytes to the array capacity; return false if buffer is external.
Definition: colvars_memstream.cpp:17
void setf(decltype(std::ios::fmtflags(0)), decltype(std::ios::floatfield))
Ignore formatting operators.
Definition: colvars_memstream.h:109
void clear()
Clear the error code.
Definition: colvars_memstream.h:127
size_t tellg() const
Report the current position in the buffer.
Definition: colvars_memstream.h:103