SENSEI
A frame work for generic in situ analytics
BinaryStream.h
1 #ifndef BinaryStream_H
2 #define BinaryStream_H
3 
4 #include "senseiConfig.h"
5 #include "Error.h"
6 
7 #include <cstdlib>
8 #include <cstring>
9 #include <string>
10 #include <map>
11 #include <vector>
12 #include <array>
13 #include <type_traits>
14 
15 namespace sensei
16 {
17 
18 // Serialize objects into a binary stream.
19 class SENSEI_EXPORT BinaryStream
20 {
21 public:
22  // construct
23  BinaryStream();
24  ~BinaryStream() noexcept;
25 
26  // copy
27  BinaryStream(const BinaryStream &s);
28  const BinaryStream &operator=(const BinaryStream &other);
29 
30  // move
31  BinaryStream(BinaryStream &&s) noexcept;
32  const BinaryStream &operator=(BinaryStream &&other) noexcept;
33 
34  // evaluate to true when the stream is not empty.
35  operator bool()
36  { return mSize != 0; }
37 
38  // Release all resources, set to a uninitialized
39  // state.
40  void Clear() noexcept;
41 
42  // Allocate nBytes for the stream.
43  void Resize(unsigned long nBytes);
44 
45  // ensures space for nBytes more to the stream.
46  void Grow(unsigned long nBytes);
47 
48  // Get a pointer to the stream internal representation.
49  unsigned char *GetData() noexcept
50  { return mData; }
51 
52  const unsigned char *GetData() const noexcept
53  { return mData; }
54 
55  // Get the size of the valid data in the stream.
56  // note: the internal buffer may be larger.
57  unsigned long Size() const noexcept
58  { return mWritePtr - mData; }
59 
60  // Get the sise of the internal buffer allocated
61  // for the stream.
62  unsigned long Capacity() const noexcept
63  { return mSize; }
64 
65  // set the stream position to n bytes from the head
66  // of the stream
67  void SetReadPos(unsigned long n) noexcept
68  { mReadPtr = mData + n; }
69 
70  void SetWritePos(unsigned long n) noexcept
71  { mWritePtr = mData + n; }
72 
73  // swap the two objects
74  void Swap(BinaryStream &other) noexcept;
75 
76  // Insert/Extract to/from the stream.
77  template <typename T> void Pack(T *val);
78 
79  template <typename T> void Pack(const T &val, typename std::enable_if<!std::is_class<T>::value>::type* = 0);
80  template <typename T> void Unpack(T &val, typename std::enable_if<!std::is_class<T>::value>::type* = 0);
81 
82  template <typename T> void Pack(const T *val, unsigned long n);
83  template <typename T> void Unpack(T *val, unsigned long n);
84 
85  // specializations
86  void Pack(const std::string &str);
87  void Unpack(std::string &str);
88 
89  template <typename T, unsigned long N> void Pack(const std::array<T,N> &arr);
90  template <typename T, unsigned long N> void Unpack(std::array<T,N> &arr);
91 
92  template <typename K, typename V> void Pack(const std::map<K,V> &amap);
93  template <typename K, typename V> void Unpack(std::map<K,V> &amap);
94 
95  template<typename T> void Pack(const std::vector<T> &v,
96  typename std::enable_if<std::is_class<T>::value>::type* = 0);
97 
98  template<typename T> void Unpack(std::vector<T> &v,
99  typename std::enable_if<std::is_class<T>::value>::type* = 0);
100 
101 #if !defined(SWIG)
102  template<typename T> void Pack(const std::vector<T> &v,
103  typename std::enable_if<!std::is_class<T>::value>::type* = 0);
104 
105  template<typename T> void Unpack(std::vector<T> &v,
106  typename std::enable_if<!std::is_class<T>::value>::type* = 0);
107 #endif
108 
109  // broadcast the stream from the root process to all other processes
110  int Broadcast(int rootRank=0);
111 
112 private:
113  // re-allocation size
114  static
115  constexpr unsigned int GetBlockSize()
116  { return 512; }
117 
118 private:
119  unsigned long mSize;
120  unsigned char *mData;
121  unsigned char *mReadPtr;
122  unsigned char *mWritePtr;
123 };
124 
125 //-----------------------------------------------------------------------------
126 template <typename T>
127 void BinaryStream::Pack(T *val)
128 {
129  (void)val;
130  SENSEI_ERROR("You con't pack a pointer.");
131 }
132 
133 //-----------------------------------------------------------------------------
134 template <typename T>
135 void BinaryStream::Pack(const T &val, typename std::enable_if<!std::is_class<T>::value>::type*)
136 {
137  this->Grow(sizeof(T));
138  *((T *)mWritePtr) = val;
139  mWritePtr += sizeof(T);
140 }
141 
142 //-----------------------------------------------------------------------------
143 template <typename T>
144 void BinaryStream::Unpack(T &val, typename std::enable_if<!std::is_class<T>::value>::type*)
145 {
146  val = *((T *)mReadPtr);
147  mReadPtr += sizeof(T);
148 }
149 
150 //-----------------------------------------------------------------------------
151 template <typename T>
152 void BinaryStream::Pack(const T *val, unsigned long n)
153 {
154  unsigned long nBytes = n*sizeof(T);
155  this->Grow(nBytes);
156 
157  unsigned long nn = n*sizeof(T);
158  memcpy(mWritePtr, val, nn);
159  mWritePtr += nn;
160 }
161 
162 //-----------------------------------------------------------------------------
163 template <typename T>
164 void BinaryStream::Unpack(T *val, unsigned long n)
165 {
166  unsigned long nn = n*sizeof(T);
167  memcpy(val, mReadPtr, nn);
168  mReadPtr += nn;
169 }
170 
171 //-----------------------------------------------------------------------------
172 inline
173 void BinaryStream::Pack(const std::string &str)
174 {
175  unsigned long slen = str.size();
176  this->Pack(slen);
177  this->Pack(str.c_str(), slen);
178 }
179 
180 //-----------------------------------------------------------------------------
181 inline
182 void BinaryStream::Unpack(std::string &str)
183 {
184  unsigned long slen = 0;
185  this->Unpack(slen);
186 
187  str.resize(slen);
188  str.assign(reinterpret_cast<char*>(mReadPtr), slen);
189 
190  mReadPtr += slen;
191 }
192 
193 //-----------------------------------------------------------------------------
194 template <typename T, unsigned long N>
195 void BinaryStream::Pack(const std::array<T,N> &arr)
196 {
197  this->Pack(arr.data(), N);
198 }
199 
200 //-----------------------------------------------------------------------------
201 template <typename T, unsigned long N>
202 void BinaryStream::Unpack(std::array<T,N> &arr)
203 {
204  this->Unpack(arr.data(), N);
205 }
206 
207 //-----------------------------------------------------------------------------
208 template <typename K, typename V>
209 void BinaryStream::Pack(const std::map<K,V> &amap)
210 {
211  unsigned long len = amap.size();
212  this->Pack(len);
213 
214  typename std::map<K,V>::const_iterator it = amap.begin();
215  for (unsigned long i = 0; i < len; ++i, ++it)
216  {
217  this->Pack(it->first);
218  this->Pack(it->second);
219  }
220 }
221 
222 //-----------------------------------------------------------------------------
223 template <typename K, typename V>
224 void BinaryStream::Unpack(std::map<K,V> &amap)
225 {
226  unsigned long len = 0;
227  this->Unpack(len);
228 
229  for (unsigned long i = 0; i < len; ++i)
230  {
231  K key;
232  V val;
233 
234  this->Unpack(key);
235  this->Unpack(val);
236 
237  amap[key] = std::move(val);
238  }
239 }
240 
241 //-----------------------------------------------------------------------------
242 template<typename T>
243 void BinaryStream::Pack(const std::vector<T> &v, typename std::enable_if<std::is_class<T>::value>::type*)
244 {
245  unsigned long vlen = v.size();
246  this->Pack(vlen);
247  for (unsigned long i = 0; i < vlen; ++i)
248  this->Pack(v[i]);
249 }
250 
251 //-----------------------------------------------------------------------------
252 template<typename T>
253 void BinaryStream::Unpack(std::vector<T> &v, typename std::enable_if<std::is_class<T>::value>::type*)
254 {
255  unsigned long vlen;
256  this->Unpack(vlen);
257 
258  v.resize(vlen);
259  for (unsigned long i = 0; i < vlen; ++i)
260  this->Unpack(v[i]);
261 }
262 
263 //-----------------------------------------------------------------------------
264 template<typename T>
265 void BinaryStream::Pack(const std::vector<T> &v, typename std::enable_if<!std::is_class<T>::value>::type*)
266 {
267  const unsigned long vlen = v.size();
268  this->Pack(vlen);
269  this->Pack(v.data(), vlen);
270 }
271 
272 //-----------------------------------------------------------------------------
273 template<typename T>
274 void BinaryStream::Unpack(std::vector<T> &v, typename std::enable_if<!std::is_class<T>::value>::type*)
275 {
276  unsigned long vlen;
277  this->Unpack(vlen);
278 
279  v.resize(vlen);
280  this->Unpack(v.data(), vlen);
281 }
282 
283 
284 }
285 
286 #endif
Definition: BinaryStream.h:19
SENSEI_EXPORT unsigned int Size(int svtkt)
given a SVTK type enum returns the sizeof that type
SENSEI.
Definition: ADIOS2AnalysisAdaptor.h:27