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 flags(decltype(std::ios::fmtflags(0))) {}
113
115 inline decltype(std::ios::fmtflags(0)) flags() const { return std::ios::fmtflags(0); }
116
118 inline std::ios::iostate rdstate() const { return state_; }
119
121 inline void setstate(std::ios::iostate new_state) { state_ |= new_state; }
122
124 inline void clear() { state_ = std::ios::goodbit; }
125
126protected:
127
129 std::vector<unsigned char> *external_output_buffer_ = nullptr;
130
132 unsigned char const *external_input_buffer_ = nullptr;
133
135 std::vector<unsigned char> internal_buffer_;
136
138 size_t data_length_ = 0L;
139
141 size_t const max_length_;
142
144 std::ios::iostate state_ = std::ios::goodbit;
145
147 bool expand_output_buffer(size_t add_bytes);
148
150 inline void incr_write_pos(size_t c) { data_length_ += c; }
151
153 size_t read_pos_ = 0L;
154
156 inline void begin_reading() { setstate(std::ios::eofbit); }
157
159 inline void done_reading() { clear(); }
160
162 inline void incr_read_pos(size_t c) { read_pos_ += c; }
163
166 inline bool has_remaining(size_t c) { return c <= (data_length_ - read_pos_); }
167 };
168
169template <typename T> void cvm::memory_stream::write_object(T const &t)
170{
171 static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use write_object() on complex type");
172 size_t const new_data_size = sizeof(T);
173 if (expand_output_buffer(new_data_size)) {
174 std::memcpy(output_location(), &t, sizeof(T));
175 incr_write_pos(new_data_size);
176 }
177}
178
179template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os, T const &t)
180{
181 os.write_object<T>(t);
182 return os;
183}
184
185template <typename T> void cvm::memory_stream::write_vector(std::vector<T> const &t)
186{
187 static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use write_vector() on complex type");
188 size_t const vector_length = t.size();
189 size_t const new_data_size = sizeof(size_t) + sizeof(T) * vector_length;
190 if (expand_output_buffer(new_data_size)) {
191 std::memcpy(output_location(), &vector_length, sizeof(size_t));
192 incr_write_pos(sizeof(T));
193 std::memcpy(output_location(), t.data(), t.size() * sizeof(T));
194 incr_write_pos(t.size() * sizeof(T));
195 }
196}
197
198template <typename T>
199cvm::memory_stream &operator<<(cvm::memory_stream &os, std::vector<T> const &t)
200{
201 os.write_vector<T>(t);
202 return os;
203}
204
205template <typename T> void cvm::memory_stream::read_object(T &t)
206{
207 static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use read_object() on complex type");
208 begin_reading();
209 if (has_remaining(sizeof(T))) {
210 std::memcpy(&t, input_location(), sizeof(T));
211 incr_read_pos(sizeof(T));
212 done_reading();
213 }
214}
215
216template <typename T> cvm::memory_stream &operator>>(cvm::memory_stream &is, T &t)
217{
218 is.read_object<T>(t);
219 return is;
220}
221
222template <typename T> void cvm::memory_stream::read_vector(std::vector<T> &t)
223{
224 static_assert(IS_TRIVIALLY_COPYABLE(T), "Cannot use read_vector() on complex type");
225 begin_reading();
226 size_t vector_length = 0;
227 if (has_remaining(sizeof(size_t))) {
228 std::memcpy(&vector_length, input_location(), sizeof(size_t));
229 incr_read_pos(sizeof(size_t));
230 if (has_remaining(vector_length * sizeof(T))) {
231 t.resize(vector_length);
232 std::memcpy(t.data(), input_location(), vector_length * sizeof(T));
233 incr_read_pos(vector_length * sizeof(T));
234 done_reading();
235 } else {
236 setstate(std::ios::failbit);
237 }
238 }
239}
240
241template <typename T> cvm::memory_stream &operator>>(cvm::memory_stream &is, std::vector<T> &t)
242{
243 is.read_vector<T>(t);
244 return is;
245}
246
247template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os,
248 decltype(std::setprecision(10)) const &)
249{
250 return os;
251}
252
253#if !defined(_MSC_VER) && !defined(__SUNPRO_CC)
254// Visual Studio and MSVC use the same return type for both modifiers
255template <typename T> cvm::memory_stream &operator<<(cvm::memory_stream &os,
256 decltype(std::setw(10)) const &)
257{
258 return os;
259}
260#endif
261
262// Declare specializations
263
264template <> void cvm::memory_stream::write_object(std::string const &t);
265
266template <> cvm::memory_stream &operator<<(cvm::memory_stream &os, std::string const &t);
267
268template <> void cvm::memory_stream::write_object(colvarvalue const &t);
269
270template <> cvm::memory_stream &operator<<(cvm::memory_stream &os, colvarvalue const &x);
271
273
274template <>
276
277template <> void cvm::memory_stream::read_object(std::string &t);
278
279template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, std::string &t);
280
282
283template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, colvarvalue &t);
284
286
287template <> cvm::memory_stream &operator>>(cvm::memory_stream &is, cvm::vector1d<cvm::real> &t);
288
289#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:166
unsigned char * output_location()
Next location to write to.
Definition: colvars_memstream.h:60
std::ios::iostate state_
Error status.
Definition: colvars_memstream.h:144
void done_reading()
Mark the reading attempt succesful.
Definition: colvars_memstream.h:159
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:169
std::ios::iostate rdstate() const
Get the error code.
Definition: colvars_memstream.h:118
void read_vector(std::vector< T > &t)
Read a vector of simple objects from the buffer.
Definition: colvars_memstream.h:222
std::vector< unsigned char > internal_buffer_
Internal buffer (may server for both input and output)
Definition: colvars_memstream.h:135
size_t read_pos_
Current position when reading from the buffer.
Definition: colvars_memstream.h:153
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:185
void incr_write_pos(size_t c)
Move the buffer position past the data just written.
Definition: colvars_memstream.h:150
void flags(decltype(std::ios::fmtflags(0)))
Ignore formatting operators.
Definition: colvars_memstream.h:112
void setstate(std::ios::iostate new_state)
Set the error code.
Definition: colvars_memstream.h:121
size_t data_length_
Length of the data buffer (either internal or external)
Definition: colvars_memstream.h:138
decltype(std::ios::fmtflags(0)) flags() const
Get the current formatting flags (i.e. none because this stream is unformatted)
Definition: colvars_memstream.h:115
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:141
unsigned char const * external_input_buffer_
External input buffer.
Definition: colvars_memstream.h:132
void incr_read_pos(size_t c)
Move the buffer position past the data just read.
Definition: colvars_memstream.h:162
std::vector< unsigned char > * external_output_buffer_
External output buffer.
Definition: colvars_memstream.h:129
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:205
void begin_reading()
Begin an attempt to read an object; assume EOF unless there is space remaining.
Definition: colvars_memstream.h:156
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:124
size_t tellg() const
Report the current position in the buffer.
Definition: colvars_memstream.h:103