evio  6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
EvioSwap.h
Go to the documentation of this file.
1 //
2 // Copyright 2020, Jefferson Science Associates, LLC.
3 // Subject to the terms in the LICENSE file found in the top-level directory.
4 //
5 // EPSCI Group
6 // Thomas Jefferson National Accelerator Facility
7 // 12000, Jefferson Ave, Newport News, VA 23606
8 // (757)-269-7100
9 
10 
11 #ifndef EVIO_6_0_EVIOSWAP_H
12 #define EVIO_6_0_EVIOSWAP_H
13 
14 
15 #include <cstdio>
16 #include <memory>
17 
18 
19 #include "ByteOrder.h"
20 #include "ByteBuffer.h"
21 #include "DataType.h"
22 #include "EvioNode.h"
23 #include "CompositeData.h"
24 #include "BaseStructure.h"
25 
26 
27 namespace evio {
28 
29 
35  class EvioSwap {
36 
37  public:
38 
51  static void swapEvent(uint32_t *buf, int tolocal, uint32_t *dest) {
52  swapBank(buf, tolocal, dest);
53  }
54 
55 
69  static void swapBank(uint32_t *buf, bool toLocal, uint32_t *dest) {
70  if (buf == nullptr) return;
71 
72  uint32_t dataLength, dataType;
73  uint32_t *p = buf;
74 
75  // Swap header to get length and contained type if buf NOT local endian
76  if (toLocal) {
77  p = ByteOrder::byteSwap32(buf, 2, dest);
78  }
79 
80  dataLength = p[0] - 1;
81  dataType = (p[1] >> 8) & 0x3f; // padding info in top 2 bits of type byte
82 
83  // Swap header if buf is local endian
84  if (!toLocal) {
85  ByteOrder::byteSwap32(buf, 2, dest);
86  }
87 
88  // Swap non-header bank data
89  swapData(&buf[2], dataType, dataLength, toLocal, ((dest == nullptr) ? nullptr : &dest[2]));
90  }
91 
92 
106  static void swapSegment(uint32_t *buf, bool toLocal, uint32_t *dest) {
107  if (buf == nullptr) return;
108 
109  uint32_t dataLength, dataType;
110  uint32_t *p = buf;
111 
112  // Swap header to get length and contained type if buf NOT local endian
113  if (toLocal) {
114  p = ByteOrder::byteSwap32(buf, 1, dest);
115  }
116 
117  dataLength = p[0] & 0xffff;
118  dataType = (p[0] >> 16) & 0x3f; /* padding info in top 2 bits of type byte */
119 
120  // Swap header if buf is local endian
121  if (!toLocal) {
122  ByteOrder::byteSwap32(buf, 1, dest);
123  }
124 
125  // Swap non-header segment data
126  swapData(&buf[1], dataType, dataLength, toLocal, ((dest == nullptr) ? nullptr : &dest[1]));
127  }
128 
129 
143  static void swapTagsegment(uint32_t *buf, bool toLocal, uint32_t *dest) {
144  if (buf == nullptr) return;
145 
146  uint32_t dataLength, dataType;
147  uint32_t *p = buf;
148 
149  // Swap header to get length and contained type if buf NOT local endian
150  if (toLocal) {
151  p = ByteOrder::byteSwap32(buf, 1, dest);
152  }
153 
154  dataLength = p[0] & 0xffff;
155  dataType = (p[0] >> 16) & 0xf; // no padding info in tagsegments
156 
157  // Swap header if buf is local endian
158  if (!toLocal) {
159  ByteOrder::byteSwap32(buf, 1, dest);
160  }
161 
162  // Swap non-header tagsegment data
163  swapData(&buf[1], dataType, dataLength, toLocal, ((dest == nullptr) ? nullptr : &dest[1]));
164  }
165 
166 // TODO: look at when exception are thrown for javadoc
167 
184  static void swapLeafData(DataType const & type,
185  std::shared_ptr<ByteBuffer> & srcBuf,
186  std::shared_ptr<ByteBuffer> & destBuf,
187  size_t srcPos, size_t destPos, size_t len) {
188  swapLeafData(type, *(srcBuf.get()), *(destBuf.get()), srcPos, destPos, len);
189  }
190 
191 
208  static void swapLeafData(DataType const & type, ByteBuffer & srcBuf,
209  ByteBuffer & destBuf, size_t srcPos, size_t destPos,
210  size_t len) {
211 
212  // We end here
213  size_t endPos = srcPos + 4*len;
214 
215  // 64 bit swap
216  if (type == DataType::LONG64 ||
217  type == DataType::ULONG64 ||
218  type == DataType::DOUBLE64) {
219 
220  // When only swapping, no need to convert to double & back
221  for (; srcPos < endPos; srcPos += 8, destPos += 8) {
222  destBuf.putLong(destPos, srcBuf.getLong(srcPos));
223  }
224 
225  }
226  // 32 bit swap
227  else if (type == DataType::INT32 ||
228  type == DataType::UINT32 ||
229  type == DataType::FLOAT32) {
230  // When only swapping, no need to convert to float & back
231  for (; srcPos < endPos; srcPos += 4, destPos += 4) {
232  destBuf.putInt(destPos, srcBuf.getInt(srcPos));
233  }
234  }
235  // 16 bit swap
236  else if (type == DataType::SHORT16 ||
237  type == DataType::USHORT16) {
238  for (; srcPos < endPos; srcPos += 2, destPos += 2) {
239  destBuf.putShort(destPos, srcBuf.getShort(srcPos));
240  }
241  }
242  // no swap
243  else if (type == DataType::UNKNOWN32 ||
244  type == DataType::CHAR8 ||
245  type == DataType::UCHAR8 ||
246  type == DataType::CHARSTAR8) {
247  // 8 bit swap - no swap needed, but need to copy if destBuf != srcBuf
248  for (; srcPos < endPos; srcPos++, destPos++) {
249  destBuf.put(destPos, srcBuf.getByte(srcPos));
250  }
251  }
252  else if (type == DataType::COMPOSITE) {
253  // new composite type
254  CompositeData::swapAll(srcBuf, destBuf, srcPos, destPos, len);
255  }
256  }
257 
258 
277  static void swapData(uint32_t *src, uint32_t type, uint32_t length, bool toLocal, uint32_t *dst) {
278  if (src == nullptr) return;
279 
280  uint32_t fraglen, l = 0;
281 
282  // Swap the data or call swap_fragment
283  switch (type) {
284 
285  // 32-bit types: uint, float, or int
286  case 0x1:
287  case 0x2:
288  case 0xb:
289  ByteOrder::byteSwap32(src, length, dst);
290  break;
291 
292  // unknown or 8-bit types: string array, char, or uchar ... no swap
293  case 0x0:
294  case 0x3:
295  case 0x6:
296  case 0x7:
297  ByteOrder::byteNoSwap32(src, length, dst);
298  break;
299 
300  // 16-bit types: short or ushort
301  case 0x4:
302  case 0x5:
303  ByteOrder::byteSwap16(reinterpret_cast<uint16_t *>(src), 2 * length,
304  reinterpret_cast<uint16_t *>(dst));
305  break;
306 
307  // 64-bit types: double, int, or uint
308  case 0x8:
309  case 0x9:
310  case 0xa:
311  ByteOrder::byteSwap64(reinterpret_cast<uint64_t *>(src), length / 2,
312  reinterpret_cast<uint64_t *>(dst));
313  break;
314 
315  // Composite type
316  case 0xf:
317  CompositeData::swapAll(reinterpret_cast<uint8_t *>(src),
318  reinterpret_cast<uint8_t *>(dst),
319  length, !toLocal);
320  break;
321 
322  // Bank
323  case 0xe:
324  case 0x10:
325  while (l < length) {
326  // src is opposite local endian
327  if (toLocal) {
328  // swap bank
329  swapBank(&src[l], toLocal, (dst == nullptr) ? nullptr : &dst[l]);
330  // bank was this long (32 bit words) including header
331  fraglen = (dst == nullptr) ? src[l] + 1 : dst[l] + 1;
332  }
333  else {
334  fraglen = src[l] + 1;
335  swapBank(&src[l], toLocal, (dst == nullptr) ? nullptr : &dst[l]);
336  }
337  l += fraglen;
338  }
339  break;
340 
341  // Segment
342  case 0xd:
343  case 0x20:
344  while (l < length) {
345  if (toLocal) {
346  swapSegment(&src[l], toLocal, (dst == nullptr) ? nullptr : &dst[l]);
347  fraglen = (dst == nullptr) ? (src[l] & 0xffff) + 1 : (dst[l] & 0xffff) + 1;
348  }
349  else {
350  fraglen = (src[l] & 0xffff) + 1;
351  swapSegment(&src[l], toLocal, (dst == nullptr) ? nullptr : &dst[l]);
352  }
353  l += fraglen;
354  }
355  break;
356 
357  // Tagsegment
358  case 0xc:
359  while (l < length) {
360  if (toLocal) {
361  swapTagsegment(&src[l], toLocal, (dst == nullptr) ? nullptr : &dst[l]);
362  fraglen = (dst == nullptr) ? (src[l] & 0xffff) + 1 : (dst[l] & 0xffff) + 1;
363  }
364  else {
365  fraglen = (src[l] & 0xffff) + 1;
366  swapTagsegment(&src[l], toLocal, (dst == nullptr) ? nullptr : &dst[l]);
367  }
368  l += fraglen;
369  }
370  break;
371 
372  // unknown type, just copy
373  default:
374  ByteOrder::byteNoSwap32(src, length, dst);
375  break;
376  }
377  }
378 
379 
394  static void swapData(std::shared_ptr<BaseStructure> strc) {
395  auto type = strc->getHeader()->getDataType();
396  uint32_t length = strc->getHeader()->getDataLength();
397  bool srcIsLocal = strc->getByteOrder().isLocalEndian();
398 
399  if (type == DataType::UINT32) {
400  auto & vec = strc->getUIntData();
401  ByteOrder::byteSwap32(vec.data(), length, nullptr);
402  strc->updateUIntData();
403  }
404  else if (type == DataType::INT32) {
405  auto & vec = strc->getIntData();
406  ByteOrder::byteSwap32(reinterpret_cast<uint32_t*>(vec.data()), length, nullptr);
407  strc->updateIntData();
408  }
409  else if (type == DataType::FLOAT32) {
410  auto & vec = strc->getFloatData();
411  ByteOrder::byteSwap32(reinterpret_cast<uint32_t*>(vec.data()), length, nullptr);
412  strc->updateFloatData();
413  }
414  else if (type == DataType::SHORT16) {
415  auto & vec = strc->getShortData();
416  ByteOrder::byteSwap16(reinterpret_cast<uint16_t*>(vec.data()), length, nullptr);
417  strc->updateShortData();
418  }
419  else if (type == DataType::USHORT16) {
420  auto & vec = strc->getUShortData();
421  ByteOrder::byteSwap16(vec.data(), length, nullptr);
422  strc->updateUShortData();
423  }
424  else if (type == DataType::LONG64) {
425  auto & vec = strc->getLongData();
426  ByteOrder::byteSwap64(reinterpret_cast<uint64_t*>(vec.data()), length, nullptr);
427  strc->updateLongData();
428  }
429  else if (type == DataType::ULONG64) {
430  auto & vec = strc->getULongData();
431  ByteOrder::byteSwap64(vec.data(), length, nullptr);
432  strc->updateULongData();
433  }
434  else if (type == DataType::DOUBLE64) {
435  auto & vec = strc->getDoubleData();
436  ByteOrder::byteSwap64(reinterpret_cast<uint64_t*>(vec.data()), length, nullptr);
437  strc->updateDoubleData();
438  }
439 // else if (type == DataType::COMPOSITE) {
440 // }
441  // For containers, just iterate over their children recursively
442  else if (type.isBank() || type.isSegment() || type.isTagSegment()) {
443  for (auto kid : strc->getChildren()) {
444  swapData(kid);
445  }
446  }
447 
448  }
449 
450 
451  };
452 
453 
454 }
455 
456 #endif //EVIO_6_0_EVIOSWAP_H
ByteBuffer & putShort(uint16_t val)
Relative put method for writing a short value.
Definition: ByteBuffer.cpp:1525
This class is copied from one of the same name in the Java programming language.
Definition: ByteBuffer.h:42
static const DataType LONG64
64 bit int.
Definition: DataType.h:45
static const DataType UCHAR8
Unsigned 8 bit int.
Definition: DataType.h:43
static const DataType INT32
32 bit int.
Definition: DataType.h:47
static void swapAll(uint8_t *src, uint8_t *dest, size_t length, bool srcIsLocal)
This method converts (swaps) a buffer of EVIO composite type between big &amp; little endian...
Definition: CompositeData.cpp:1018
static void swapLeafData(DataType const &type, std::shared_ptr< ByteBuffer > &srcBuf, std::shared_ptr< ByteBuffer > &destBuf, size_t srcPos, size_t destPos, size_t len)
This method swaps the data of an evio leaf structure.
Definition: EvioSwap.h:184
ByteBuffer & put(const ByteBuffer &src)
Relative bulk put method.
Definition: ByteBuffer.cpp:1325
ByteBuffer & putLong(uint64_t val)
Relative put method for writing a long long value.
Definition: ByteBuffer.cpp:1615
static uint64_t * byteSwap64(uint64_t *src, size_t elements, uint64_t *dst)
This method swaps an array of 8-byte data.
Definition: ByteOrder.cpp:132
static const DataType CHARSTAR8
ASCII characters.
Definition: DataType.h:39
static void swapSegment(uint32_t *buf, bool toLocal, uint32_t *dest)
Routine to swap the endianness of an evio segment.
Definition: EvioSwap.h:106
static void swapData(std::shared_ptr< BaseStructure > strc)
Routine to swap the endianness of an evio structure&#39;s (bank, seg, tagseg) data in place...
Definition: EvioSwap.h:394
ByteBuffer & putInt(uint32_t val)
Relative put method for writing an int value.
Definition: ByteBuffer.cpp:1570
static void swapLeafData(DataType const &type, ByteBuffer &srcBuf, ByteBuffer &destBuf, size_t srcPos, size_t destPos, size_t len)
This method swaps the data of an evio leaf structure.
Definition: EvioSwap.h:208
static const DataType DOUBLE64
64 bit double.
Definition: DataType.h:44
static const DataType COMPOSITE
Composite data type.
Definition: DataType.h:51
Class to hold static methods used to swap evio data.
Definition: EvioSwap.h:35
static const DataType FLOAT32
32 bit float.
Definition: DataType.h:38
static void swapEvent(uint32_t *buf, int tolocal, uint32_t *dest)
Method to swap the endianness of an evio event (bank).
Definition: EvioSwap.h:51
static void byteNoSwap32(const uint32_t *src, size_t elements, uint32_t *dst)
This routine swaps nothing, it just copies the given number of 32 bit ints.
Definition: ByteOrder.cpp:155
static const DataType SHORT16
16 bit int.
Definition: DataType.h:40
static const DataType UINT32
Unsigned 32 bit int.
Definition: DataType.h:37
static const DataType CHAR8
8 bit int.
Definition: DataType.h:42
int64_t getLong() const
Relative get method for reading a long long value.
Definition: ByteBuffer.cpp:1156
int32_t getInt() const
Relative get method for reading an int value.
Definition: ByteBuffer.cpp:1074
static void swapTagsegment(uint32_t *buf, bool toLocal, uint32_t *dest)
Routine to swap the endianness of an evio tagsegment.
Definition: EvioSwap.h:143
Numerical values associated with evio data types.
Definition: DataType.h:32
static uint32_t * byteSwap32(uint32_t *src, size_t elements, uint32_t *dst)
This method swaps an array of 4-byte data.
Definition: ByteOrder.cpp:109
static const DataType UNKNOWN32
Unknown data type.
Definition: DataType.h:36
static void swapData(uint32_t *src, uint32_t type, uint32_t length, bool toLocal, uint32_t *dst)
Routine to swap any type of evio data.
Definition: EvioSwap.h:277
static const DataType USHORT16
Unsigned 16 bit int.
Definition: DataType.h:41
uint8_t getByte() const
Relative get method.
Definition: ByteBuffer.cpp:936
static void swapBank(uint32_t *buf, bool toLocal, uint32_t *dest)
Routine to swap the endianness of an evio bank.
Definition: EvioSwap.h:69
static uint16_t * byteSwap16(uint16_t *src, size_t elements, uint16_t *dst)
This method swaps an array of 2-byte data.
Definition: ByteOrder.cpp:86
static const DataType ULONG64
Unsigned 64 bit int.
Definition: DataType.h:46
int16_t getShort() const
Relative get method for reading a short value.
Definition: ByteBuffer.cpp:989