2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 #include "inmemoryserializer.h"
54 static constexpr size_t ValueSize = sizeof(T);
56 explicit CharBuffer(T value) { u.v = value; }
57 explicit CharBuffer(const char buffer[]) { std::copy(buffer, buffer + ValueSize, u.c); }
59 T value() const { return u.v; }
61 void appendTo(std::vector<char>* buffer)
63 buffer->insert(buffer->end(), u.c, u.c + ValueSize);
73 //! Return \c value with the byte order swapped.
75 T swapEndian(const T& value)
79 std::array<char, sizeof(T)> valueAsCharArray_;
80 } endianessSwappedValue;
82 endianessSwappedValue.value_ = value;
83 int hiByte = sizeof(T) - 1;
84 for (int loByte = 0; hiByte > loByte; loByte++, hiByte--)
86 std::swap(endianessSwappedValue.valueAsCharArray_[loByte],
87 endianessSwappedValue.valueAsCharArray_[hiByte]);
90 return endianessSwappedValue.value_;
93 //! \brief Change the host-dependent endian settings to either Swap or DoNotSwap.
95 // \param endianSwapBehavior input swap behavior, might depend on host.
97 // \return Host-independent setting, either Swap or DoNotSwap.
98 EndianSwapBehavior setEndianSwapBehaviorFromHost(EndianSwapBehavior endianSwapBehavior)
100 if (endianSwapBehavior == EndianSwapBehavior::SwapIfHostIsBigEndian)
102 return GMX_INTEGER_BIG_ENDIAN ? EndianSwapBehavior::Swap : EndianSwapBehavior::DoNotSwap;
104 else if (endianSwapBehavior == EndianSwapBehavior::SwapIfHostIsLittleEndian)
106 return GMX_INTEGER_BIG_ENDIAN ? EndianSwapBehavior::DoNotSwap : EndianSwapBehavior::Swap;
110 return endianSwapBehavior;
116 /********************************************************************
120 class InMemorySerializer::Impl
123 Impl(EndianSwapBehavior endianSwapBehavior) :
124 endianSwapBehavior_(setEndianSwapBehaviorFromHost(endianSwapBehavior))
129 void doValue(T value)
131 if (endianSwapBehavior_ == EndianSwapBehavior::Swap)
133 CharBuffer<T>(swapEndian(value)).appendTo(&buffer_);
137 CharBuffer<T>(value).appendTo(&buffer_);
140 void doString(const std::string& value)
142 doValue<uint64_t>(value.size());
143 buffer_.insert(buffer_.end(), value.begin(), value.end());
145 void doOpaque(const char* data, std::size_t size)
147 buffer_.insert(buffer_.end(), data, data + size);
150 std::vector<char> buffer_;
151 EndianSwapBehavior endianSwapBehavior_;
154 InMemorySerializer::InMemorySerializer(EndianSwapBehavior endianSwapBehavior) :
155 impl_(new Impl(endianSwapBehavior))
159 InMemorySerializer::~InMemorySerializer() = default;
161 std::vector<char> InMemorySerializer::finishAndGetBuffer()
163 return std::move(impl_->buffer_);
166 void InMemorySerializer::doBool(bool* value)
168 impl_->doValue(*value);
171 void InMemorySerializer::doUChar(unsigned char* value)
173 impl_->doValue(*value);
176 void InMemorySerializer::doChar(char* value)
178 impl_->doValue(*value);
181 void InMemorySerializer::doUShort(unsigned short* value)
183 impl_->doValue(*value);
186 void InMemorySerializer::doInt(int* value)
188 impl_->doValue(*value);
191 void InMemorySerializer::doInt32(int32_t* value)
193 impl_->doValue(*value);
196 void InMemorySerializer::doInt64(int64_t* value)
198 impl_->doValue(*value);
201 void InMemorySerializer::doFloat(float* value)
203 impl_->doValue(*value);
206 void InMemorySerializer::doDouble(double* value)
208 impl_->doValue(*value);
211 void InMemorySerializer::doReal(real* value)
213 impl_->doValue(*value);
216 void InMemorySerializer::doRvec(rvec* value)
218 for (int d = 0; d < DIM; d++)
220 doReal(&(*value)[d]);
224 void InMemorySerializer::doIvec(ivec* value)
226 for (int d = 0; d < DIM; d++)
232 void InMemorySerializer::doString(std::string* value)
234 impl_->doString(*value);
237 void InMemorySerializer::doOpaque(char* data, std::size_t size)
239 impl_->doOpaque(data, size);
242 /********************************************************************
243 * InMemoryDeserializer
246 class InMemoryDeserializer::Impl
249 explicit Impl(ArrayRef<const char> buffer, bool sourceIsDouble, EndianSwapBehavior endianSwapBehavior) :
251 sourceIsDouble_(sourceIsDouble),
253 endianSwapBehavior_(setEndianSwapBehaviorFromHost(endianSwapBehavior))
258 void doValue(T* value)
260 if (endianSwapBehavior_ == EndianSwapBehavior::Swap)
262 *value = swapEndian(CharBuffer<T>(&buffer_[pos_]).value());
266 *value = CharBuffer<T>(&buffer_[pos_]).value();
268 pos_ += CharBuffer<T>::ValueSize;
270 void doString(std::string* value)
273 doValue<uint64_t>(&size);
274 *value = std::string(&buffer_[pos_], size);
277 void doOpaque(char* data, std::size_t size)
279 std::copy(&buffer_[pos_], &buffer_[pos_ + size], data);
283 ArrayRef<const char> buffer_;
284 bool sourceIsDouble_;
286 EndianSwapBehavior endianSwapBehavior_;
289 InMemoryDeserializer::InMemoryDeserializer(ArrayRef<const char> buffer,
291 EndianSwapBehavior endianSwapBehavior) :
292 impl_(new Impl(buffer, sourceIsDouble, endianSwapBehavior))
296 InMemoryDeserializer::~InMemoryDeserializer() = default;
298 bool InMemoryDeserializer::sourceIsDouble() const
300 return impl_->sourceIsDouble_;
303 void InMemoryDeserializer::doBool(bool* value)
305 impl_->doValue(value);
308 void InMemoryDeserializer::doUChar(unsigned char* value)
310 impl_->doValue(value);
313 void InMemoryDeserializer::doChar(char* value)
315 impl_->doValue(value);
318 void InMemoryDeserializer::doUShort(unsigned short* value)
320 impl_->doValue(value);
323 void InMemoryDeserializer::doInt(int* value)
325 impl_->doValue(value);
328 void InMemoryDeserializer::doInt32(int32_t* value)
330 impl_->doValue(value);
333 void InMemoryDeserializer::doInt64(int64_t* value)
335 impl_->doValue(value);
338 void InMemoryDeserializer::doFloat(float* value)
340 impl_->doValue(value);
343 void InMemoryDeserializer::doDouble(double* value)
345 impl_->doValue(value);
348 void InMemoryDeserializer::doReal(real* value)
350 if (sourceIsDouble())
364 void InMemoryDeserializer::doRvec(rvec* value)
366 for (int d = 0; d < DIM; d++)
368 doReal(&(*value)[d]);
372 void InMemoryDeserializer::doIvec(ivec* value)
374 for (int d = 0; d < DIM; d++)
380 void InMemoryDeserializer::doString(std::string* value)
382 impl_->doString(value);
385 void InMemoryDeserializer::doOpaque(char* data, std::size_t size)
387 impl_->doOpaque(data, size);