PVData C++  8.0.2
byteBuffer.h
1 /* byteBuffer.h */
2 /*
3  * Copyright information and license terms for this software can be
4  * found in the file LICENSE that is included with the distribution
5  */
6 /**
7  * @author mse
8  */
9 #ifndef BYTEBUFFER_H
10 #define BYTEBUFFER_H
11 
12 #include <string>
13 #include <cstring>
14 #include <cstdlib>
15 
16 #include <epicsEndian.h>
17 #include <shareLib.h>
18 #include <epicsAssert.h>
19 #include <compilerDependencies.h>
20 
21 #include <pv/templateMeta.h>
22 #include <pv/pvType.h>
23 #include <pv/epicsException.h>
24 
25 
26 #ifndef EPICS_ALWAYS_INLINE
27 # define EPICS_ALWAYS_INLINE inline
28 #endif
29 
30 /* various compilers provide builtins for byte order swaps.
31  * conditions based on boost endian library
32  */
33 #if defined(__clang__)
34 
35 #if __has_builtin(__builtin_bswap16)
36 #define _PVA_swap16(X) __builtin_bswap16(X)
37 #endif
38 #if __has_builtin(__builtin_bswap32)
39 #define _PVA_swap32(X) __builtin_bswap32(X)
40 #endif
41 #if __has_builtin(__builtin_bswap64)
42 #define _PVA_swap64(X) __builtin_bswap64(X)
43 #endif
44 
45 #elif defined(__GNUC__) && ((__GNUC__>4) || (__GNUC__==4 && __GNUC_MINOR__>=3))
46 
47 #if (__GNUC__>4) || (__GNUC__==4 && __GNUC_MINOR__>=8)
48 #define _PVA_swap16(X) __builtin_bswap16(X)
49 #endif
50 
51 #define _PVA_swap32(X) __builtin_bswap32(X)
52 #define _PVA_swap64(X) __builtin_bswap64(X)
53 
54 #elif defined(_MSC_VER)
55 
56 #define _PVA_swap16(X) _byteswap_ushort(X)
57 #define _PVA_swap32(X) _byteswap_ulong(X)
58 #define _PVA_swap64(X) _byteswap_uint64(X)
59 
60 #endif
61 
62 namespace epics {namespace pvData {
63 
64 namespace detail {
65 template<typename T>
66 struct asInt {
67  static EPICS_ALWAYS_INLINE T from(T v) { return v; }
68  static EPICS_ALWAYS_INLINE T to(T v) { return v; }
69 };
70 template<>
71 struct asInt<float> {
72  union pun {float f; uint32 i;};
73  static EPICS_ALWAYS_INLINE float from(uint32 v) {
74  pun P;
75  P.i = v;
76  return P.f;
77  }
78  static EPICS_ALWAYS_INLINE uint32 to(float v) {
79  pun P;
80  P.f = v;
81  return P.i;
82  }
83 };
84 template<>
85 struct asInt<double> {
86  union pun {double f; uint64 i;};
87  static EPICS_ALWAYS_INLINE double from(uint64 v) {
88  pun P;
89  P.i = v;
90  return P.f;
91  }
92  static EPICS_ALWAYS_INLINE uint64 to(double v) {
93  pun P;
94  P.f = v;
95  return P.i;
96  }
97 };
98 
99 template<int N>
100 struct swap; // no default
101 template<>
102 struct swap<1> {
103  static EPICS_ALWAYS_INLINE uint8 op(uint8 v) { return v; }
104 };
105 template<>
106 struct swap<2> {
107  static EPICS_ALWAYS_INLINE uint16 op(uint16 v) {
108 #ifdef _PVA_swap16
109  return _PVA_swap16(v);
110 #else
111  return (((v) >> 8) | ((v) << 8));
112 #endif
113  }
114 };
115 template<>
116 struct swap<4> {
117  static EPICS_ALWAYS_INLINE uint32 op(uint32 v) {
118 #ifdef _PVA_swap32
119  return _PVA_swap32(v);
120 #else
121  return ((((v) & 0xff000000) >> 24) |
122  (((v) & 0x00ff0000) >> 8) |
123  (((v) & 0x0000ff00) << 8) |
124  (((v) & 0x000000ff) << 24));
125 #endif
126  }
127 };
128 template<>
129 struct swap<8> {
130 #ifdef _PVA_swap64
131  static EPICS_ALWAYS_INLINE uint64 op(uint64 v) {
132  return _PVA_swap64(v);
133  }
134 #else
135  static inline uint64 op(uint64 v) {
136  return (((v) >> 56) |
137  (((v) >> 40) & 0x0000ff00) |
138  (((v) >> 24) & 0x00ff0000) |
139  (((v) >> 8) & 0xff000000) |
140  (((v) << 8) & ((uint64_t)0xff << 32)) |
141  (((v) << 24) & ((uint64_t)0xff << 40)) |
142  (((v) << 40) & ((uint64_t)0xff << 48)) |
143  (((v) << 56)));
144  }
145 #endif
146 };
147 
148 #undef _PVA_swap16
149 #undef _PVA_swap32
150 #undef _PVA_swap64
151 
152 /* PVD serialization doesn't pay attention to alignement,
153  * which some targets really care about and treat unaligned
154  * access as a fault, or with a heavy penalty (~= to a syscall).
155  *
156  * For those targets,, we will have to live with the increase
157  * in execution time and/or object code size of byte-wise copy.
158  */
159 
160 #ifdef _ARCH_PPC
161 
162 template<typename T>
163 union alignu {
164  T val;
165  char bytes[sizeof(T)];
166 };
167 
168 template<typename T>
169 EPICS_ALWAYS_INLINE void store_unaligned(char *buf, T val)
170 {
171  alignu<T> A;
172  A.val = val;
173  for(unsigned i=0, N=sizeof(T); i<N; i++) {
174  buf[i] = A.bytes[i];
175  }
176 }
177 
178 template<typename T>
179 EPICS_ALWAYS_INLINE T load_unaligned(const char *buf)
180 {
181  alignu<T> A;
182  for(unsigned i=0, N=sizeof(T); i<N; i++) {
183  A.bytes[i] = buf[i];
184  }
185  return A.val;
186 }
187 
188 #else /* alignement */
189 
190 template<typename T>
191 EPICS_ALWAYS_INLINE void store_unaligned(char *buf, T val)
192 {
193  *reinterpret_cast<T*>(buf) = val;
194 }
195 
196 template<typename T>
197 EPICS_ALWAYS_INLINE T load_unaligned(const char *buf)
198 {
199  return *reinterpret_cast<const T*>(buf);
200 }
201 
202 #endif /* alignement */
203 
204 } // namespace detail
205 
206 //! Unconditional byte order swap.
207 //! defined for integer and floating point types
208 template<typename T>
210 {
211  return detail::asInt<T>::from(
212  detail::swap<sizeof(T)>::op(
213  detail::asInt<T>::to(val)));
214 }
215 
216 #define is_aligned(POINTER, BYTE_COUNT)
217  (((std::size_t)(POINTER)) % (BYTE_COUNT) == 0)
218 
219 #if defined (__GNUC__) && (__GNUC__ < 3)
220 #define GET(T) get((T*)0)
221 #else
222 #define GET(T) get<T>()
223 #endif
224 
225 /**
226  * @brief This class implements a Bytebuffer that is like the java.nio.ByteBuffer.
227  *
228  * <p>A @c BitSet is not safe for multithreaded use without
229  * external synchronization.
230  *
231  * Based on Java implementation.
232  */
233 class ByteBuffer
234 {
235 public:
236  /**
237  * Constructor.
238  *
239  * @param size The number of bytes.
240  * @param byteOrder The byte order.
241  * Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG.
242  */
243  ByteBuffer(std::size_t size, int byteOrder = EPICS_BYTE_ORDER) :
244  _buffer((char*)std::malloc(size)), _size(size),
247  _wrapped(false)
248  {
249  if(!_buffer)
250  throw std::bad_alloc();
251  clear();
252  }
253 
254  /**
255  * Constructor for wrapping an existing buffer.
256  * Given buffer will not be released by the ByteBuffer instance.
257  * @param buffer Existing buffer. May not be NULL.
258  * @param size The number of bytes.
259  * @param byteOrder The byte order.
260  * Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG.
261  */
262  ByteBuffer(char* buffer, std::size_t size, int byteOrder = EPICS_BYTE_ORDER) :
263  _buffer(buffer), _size(size),
266  _wrapped(true)
267  {
268  if(!_buffer)
269  throw std::invalid_argument("ByteBuffer can't be constructed with NULL");
270  clear();
271  }
272  /**
273  * Destructor
274  */
276  {
277  if (_buffer && !_wrapped) std::free(_buffer);
278  }
279  /**
280  * Set the byte order.
281  *
282  * @param byteOrder The byte order.
283  * Must be one of EPICS_BYTE_ORDER,EPICS_ENDIAN_LITTLE,EPICS_ENDIAN_BIG,
284  */
285  inline void setEndianess(int byteOrder)
286  {
287  _reverseEndianess = (byteOrder != EPICS_BYTE_ORDER);
288  _reverseFloatEndianess = (byteOrder != EPICS_FLOAT_WORD_ORDER);
289  }
290  /**
291  * Get the raw buffer data.
292  * @return the raw buffer data.
293  */
294  inline const char* getBuffer() const
295  {
296  return _buffer;
297  }
298  /**
299  * Makes a buffer ready for a new sequence of channel-read or relative put operations:
300  * It sets the limit to the capacity and the position to zero.
301  */
302  inline void clear()
303  {
304  _position = _buffer;
305  _limit = _buffer + _size;
306  }
307  /**
308  * Makes a buffer ready to read out previously written values.
309  *
310  * Typically _limit==_buffer+_size is the initial state, but this is not
311  * required.
312  *
313  * V _buffer V _position V _limit V _buffer+_size
314  * |_______written_______|____uninitialized___|____allocated___|
315  *
316  * becomes
317  *
318  * V _buffer/_position V _limit V _buffer+size
319  * |_______written_______|________________allocated____________|
320  */
321  inline void flip() {
322  _limit = _position;
323  _position = _buffer;
324  }
325  /**
326  * Makes a buffer ready for re-reading the data that it already contains:
327  * It leaves the limit unchanged and sets the position to zero.
328  *
329  * Note that this may allow reading of uninitialized values. flip() should be considered
330  *
331  * V _buffer V _position V _limit V _buffer+_size
332  * |_______written_______|____uninitialized___|____allocated___|
333  *
334  * becomes
335  *
336  * V _buffer/_position V _limit V _buffer+size
337  * |_______written_______|____uninitialized___|____allocated___|
338  */
339  inline void rewind() {
340  _position = _buffer;
341  }
342  /**
343  * Returns the current position.
344  * @return The current position in the raw data.
345  */
346  inline std::size_t getPosition() const
347  {
348  return _position - _buffer;
349  }
350  /**
351  * Sets the buffer position.
352  * If the mark is defined and larger than the new position then it is discarded.
353  *
354  * @param pos The offset into the raw buffer.
355  * The new position value; must be no larger than the current limit
356  */
357  inline void setPosition(std::size_t pos)
358  {
359  assert(pos<=_size);
360  _position = _buffer + pos;
361  assert(_position<=_limit);
362  }
363  /**
364  * Returns this buffer's limit.
365  *
366  * @return The offset into the raw buffer.
367  */
368  inline std::size_t getLimit() const
369  {
370  return _limit - _buffer;
371  }
372  /**
373  * Sets this buffer's limit.
374  * If the position is larger than the new limit then it is set to the new limit.s
375  * If the mark is defined and larger than the new limit then it is discarded.
376  *
377  * @param limit The new position value;
378  * must be no larger than the current limit
379  */
380  inline void setLimit(std::size_t limit)
381  {
382  assert(limit<=_size);
383  _limit = _buffer + limit;
384  assert(_position<=_limit);
385  }
386  /**
387  * Returns the number of elements between the current position and the limit.
388  *
389  * @return The number of elements remaining in this buffer.
390  */
391  inline std::size_t getRemaining() const
392  {
393  return _limit - _position;
394  }
395  /**
396  * Returns The size, i.e. capacity of the raw data buffer in bytes.
397  *
398  * @return The size of the raw data buffer.
399  */
400  EPICS_ALWAYS_INLINE std::size_t getSize() const
401  {
402  return _size;
403  }
404  /**
405  * Put the value into the raw buffer as a byte stream in the current byte order.
406  *
407  * @param value The value to be put into the byte buffer.
408  */
409  template<typename T>
410  inline void put(T value);
411  /**
412  * Put the value into the raw buffer at the specified index as a byte stream in the current byte order.
413  *
414  * @param index Offset in the byte buffer.
415  * @param value The value to be put into the byte buffer.
416  */
417  template<typename T>
418  inline void put(std::size_t index, T value) const;
419  /**
420  * Get the new object from the byte buffer. The item MUST have type @c T.
421  * The position is adjusted based on the type.
422  *
423  * @return The object.
424  */
425 #if defined (__GNUC__) && (__GNUC__ < 3)
426  template<typename T>
427  inline T get(const T*);
428 #else
429  template<typename T>
430  inline T get();
431 #endif
432  /**
433  * Get the new object from the byte buffer at the specified index.
434  * The item MUST have type @c T.
435  * The position is adjusted based on the type.
436  *
437  * @param index The location in the byte buffer.
438  * @return The object.
439  */
440  template<typename T>
441  inline T get(std::size_t index) const;
442  /**
443  * Put a sub-array of bytes into the byte buffer.
444  * The position is increased by the count.
445  *
446  * @param src The source array.
447  * @param src_offset The starting position within src.
448  * @param count The number of bytes to put into the byte buffer.
449  * Must be less than getRemaining()
450  */
451  inline void put(const char* src, std::size_t src_offset, std::size_t count) {
452  assert(count<=getRemaining());
453  memcpy(_position, src + src_offset, count);
454  _position += count;
455  }
456  /**
457  * Get a sub-array of bytes from the byte buffer.
458  * The position is increased by the count.
459  *
460  * @param dest The destination array.
461  * @param dest_offset The starting position within src.
462  * @param count The number of bytes to put into the byte buffer.
463  * Must be less than getRemaining()
464  */
465  inline void get(char* dest, std::size_t dest_offset, std::size_t count) {
466  assert(count<=getRemaining());
467  memcpy(dest + dest_offset, _position, count);
468  _position += count;
469  }
470  /**
471  * Put an array of type @c T into the byte buffer.
472  * The position is adjusted.
473  *
474  * @param values The input array.
475  * @param count The number of elements.
476  */
477  template<typename T>
478  inline void putArray(const T* values, std::size_t count);
479  /**
480  * Get an array of type @c T from the byte buffer.
481  * The position is adjusted.
482  *
483  * @param values The destination array.
484  * @param count The number of elements.
485  */
486  template<typename T>
487  inline void getArray(T* values, std::size_t count);
488  /**
489  * Is the byte order the EPICS_BYTE_ORDER
490  * @return (false,true) if (is, is not) the EPICS_BYTE_ORDER
491  */
492  template<typename T>
494  {
495  return sizeof(T)>1 && _reverseEndianess;
496  }
497  /**
498  * Adjust position to the next multiple of 'size.
499  * @param size The alignment requirement, must be a power of 2. (unchecked)
500  * @param fill value to use for padding bytes (default '\0').
501  *
502  * @note This alignment is absolute, not necessarily with respect to _buffer.
503  */
504  inline void align(std::size_t size, char fill='\0')
505  {
506  const std::size_t k = size - 1, bufidx = (std::size_t)_position;
507  if(bufidx&k) {
508  std::size_t npad = size-(bufidx&k);
509  assert(npad<=getRemaining());
510  std::fill(_position, _position+npad, fill);
511  _position += npad;
512  }
513  }
514  /**
515  * Put a boolean value into the byte buffer.
516  *
517  * @param value The value.
518  */
519  EPICS_ALWAYS_INLINE void putBoolean( bool value) { put< int8>(value ? 1 : 0); }
520  /**
521  * Put a byte value into the byte buffer.
522  *
523  * @param value The value.
524  */
525  EPICS_ALWAYS_INLINE void putByte ( int8 value) { put< int8>(value); }
526  /**
527  * Put a short value into the byte buffer.
528  *
529  * @param value The value.
530  */
531  EPICS_ALWAYS_INLINE void putShort ( int16 value) { put< int16>(value); }
532  /**
533  * Put an int value into the byte buffer.
534  *
535  * @param value The value.
536  */
537  EPICS_ALWAYS_INLINE void putInt ( int32 value) { put< int32>(value); }
538  /**
539  * Put a long value into the byte buffer.
540  *
541  * @param value The value.
542  */
543  EPICS_ALWAYS_INLINE void putLong ( int64 value) { put< int64>(value); }
544  /**
545  * Put a float value into the byte buffer.
546  *
547  * @param value The value.
548  */
549  EPICS_ALWAYS_INLINE void putFloat ( float value) { put< float>(value); }
550  /**
551  * Put a double value into the byte buffer.
552  *
553  * @param value The value.
554  */
555  EPICS_ALWAYS_INLINE void putDouble (double value) { put<double>(value); }
556 
557  /**
558  * Put a boolean value into the byte buffer at the specified index.
559  *
560  * @param index The offset in the byte buffer,
561  * @param value The value.
562  */
563  EPICS_ALWAYS_INLINE void putBoolean(std::size_t index, bool value) { put< int8>(index, value); }
564  /**
565  * Put a byte value into the byte buffer at the specified index.
566  *
567  * @param index The offset in the byte buffer,
568  * @param value The value.
569  */
570  EPICS_ALWAYS_INLINE void putByte (std::size_t index, int8 value) { put< int8>(index, value); }
571  /**
572  * Put a short value into the byte buffer at the specified index.
573  *
574  * @param index The offset in the byte buffer,
575  * @param value The value.
576  */
577  EPICS_ALWAYS_INLINE void putShort (std::size_t index, int16 value) { put< int16>(index, value); }
578  /**
579  * Put an int value into the byte buffer at the specified index.
580  *
581  * @param index The offset in the byte buffer,
582  * @param value The value.
583  */
584  EPICS_ALWAYS_INLINE void putInt (std::size_t index, int32 value) { put< int32>(index, value); }
585  /**
586  * Put a long value into the byte buffer at the specified index.
587  *
588  * @param index The offset in the byte buffer,
589  * @param value The value.
590  */
591  EPICS_ALWAYS_INLINE void putLong (std::size_t index, int64 value) { put< int64>(index, value); }
592  /**
593  * Put a float value into the byte buffer at the specified index.
594  *
595  * @param index The offset in the byte buffer,
596  * @param value The value.
597  */
598  EPICS_ALWAYS_INLINE void putFloat (std::size_t index, float value) { put< float>(index, value); }
599  /**
600  * Put a double value into the byte buffer at the specified index.
601  *
602  * @param index The offset in the byte buffer,
603  * @param value The value.
604  */
605  EPICS_ALWAYS_INLINE void putDouble (std::size_t index, double value) { put<double>(index, value); }
606  /**
607  * Get a boolean value from the byte buffer.
608  *
609  * @return The value.
610  */
611  EPICS_ALWAYS_INLINE bool getBoolean() { return GET( int8) != 0; }
612  /**
613  * Get a byte value from the byte buffer.
614  *
615  * @return The value.
616  */
617  EPICS_ALWAYS_INLINE int8 getByte () { return GET( int8); }
618  /**
619  * Get a short value from the byte buffer.
620  *
621  * @return The value.
622  */
623  EPICS_ALWAYS_INLINE int16 getShort () { return GET( int16); }
624  /**
625  * Get a int value from the byte buffer.
626  *
627  * @return The value.
628  */
629  EPICS_ALWAYS_INLINE int32 getInt () { return GET( int32); }
630  /**
631  * Get a long value from the byte buffer.
632  *
633  * @return The value.
634  */
635  EPICS_ALWAYS_INLINE int64 getLong () { return GET( int64); }
636  /**
637  * Get a float value from the byte buffer.
638  *
639  * @return The value.
640  */
641  EPICS_ALWAYS_INLINE float getFloat () { return GET( float); }
642  /**
643  * Get a double value from the byte buffer.
644  *
645  * @return The value.
646  */
647  EPICS_ALWAYS_INLINE double getDouble () { return GET(double); }
648  /**
649  * Get a boolean value from the byte buffer at the specified index.
650  *
651  * @param index The offset in the byte buffer.
652  * @return The value.
653  */
654  EPICS_ALWAYS_INLINE bool getBoolean(std::size_t index) { return get< int8>(index) != 0; }
655  /**
656  * Get a byte value from the byte buffer at the specified index.
657  *
658  * @param index The offset in the byte buffer.
659  * @return The value.
660  */
661  EPICS_ALWAYS_INLINE int8 getByte (std::size_t index) { return get< int8>(index); }
662  /**
663  * Get a short value from the byte buffer at the specified index.
664  *
665  * @param index The offset in the byte buffer.
666  * @return The value.
667  */
668  EPICS_ALWAYS_INLINE int16 getShort (std::size_t index) { return get< int16>(index); }
669  /**
670  * Get an int value from the byte buffer at the specified index.
671  *
672  * @param index The offset in the byte buffer.
673  * @return The value.
674  */
675  EPICS_ALWAYS_INLINE int32 getInt (std::size_t index) { return get< int32>(index); }
676  /**
677  * Get a long value from the byte buffer at the specified index.
678  *
679  * @param index The offset in the byte buffer.
680  * @return The value.
681  */
682  EPICS_ALWAYS_INLINE int64 getLong (std::size_t index) { return get< int64>(index); }
683  /**
684  * Get a float value from the byte buffer at the specified index.
685  *
686  * @param index The offset in the byte buffer.
687  * @return The value.
688  */
689  EPICS_ALWAYS_INLINE float getFloat (std::size_t index) { return get< float>(index); }
690  /**
691  * Get a boolean value from the byte buffer at the specified index.
692  *
693  * @param index The offset in the byte buffer.
694  * @return The value.
695  */
696  EPICS_ALWAYS_INLINE double getDouble (std::size_t index) { return get<double>(index); }
697 
698  // TODO remove
699  EPICS_ALWAYS_INLINE const char* getArray() const EPICS_DEPRECATED
700  {
701  return _buffer;
702  }
703 
704 
705 private:
706  char* const _buffer;
707  char* _position;
708  char* _limit;
709  const std::size_t _size;
710  bool _reverseEndianess;
711  bool _reverseFloatEndianess;
712  const bool _wrapped;
713 };
714 
715  template<>
716  EPICS_ALWAYS_INLINE bool ByteBuffer::reverse<bool>() const
717  {
718  return false;
719  }
720 
721  template<>
722  EPICS_ALWAYS_INLINE bool ByteBuffer::reverse<int8>() const
723  {
724  return false;
725  }
726 
727  template<>
728  EPICS_ALWAYS_INLINE bool ByteBuffer::reverse<uint8>() const
729  {
730  return false;
731  }
732 
733  template<>
734  EPICS_ALWAYS_INLINE bool ByteBuffer::reverse<float>() const
735  {
736  return _reverseFloatEndianess;
737  }
738 
739  template<>
740  EPICS_ALWAYS_INLINE bool ByteBuffer::reverse<double>() const
741  {
742  return _reverseFloatEndianess;
743  }
744 
745  // the following methods must come after the specialized reverse<>() methods to make pre-gcc3 happy
746 
747  template<typename T>
748  inline void ByteBuffer::put(T value)
749  {
750  assert(sizeof(T)<=getRemaining());
751 
752  if(reverse<T>())
753  value = swap<T>(value);
754 
755  detail::store_unaligned(_position, value);
756  _position += sizeof(T);
757  }
758 
759  template<typename T>
760  inline void ByteBuffer::put(std::size_t index, T value) const
761  {
762  assert(_buffer+index<=_limit);
763 
764  if(reverse<T>())
765  value = swap<T>(value);
766 
767  detail::store_unaligned(_buffer+index, value);
768  }
769 
770 #if defined (__GNUC__) && (__GNUC__ < 3)
771  template<typename T>
772  inline T ByteBuffer::get(const T*)
773 #else
774  template<typename T>
775  inline T ByteBuffer::get()
776 #endif
777  {
778  assert(sizeof(T)<=getRemaining());
779 
780  T value = detail::load_unaligned<T>(_position);
781  _position += sizeof(T);
782 
783  if(reverse<T>())
784  value = swap<T>(value);
785  return value;
786  }
787 
788  template<typename T>
789  inline T ByteBuffer::get(std::size_t index) const
790  {
791  assert(_buffer+index<=_limit);
792 
793  T value = detail::load_unaligned<T>(_buffer + index);
794 
795  if(reverse<T>())
796  value = swap<T>(value);
797  return value;
798  }
799 
800  template<typename T>
801  inline void ByteBuffer::putArray(const T* values, std::size_t count)
802  {
803  size_t n = sizeof(T)*count; // bytes
804  assert(n<=getRemaining());
805 
806  if (reverse<T>()) {
807  for(std::size_t i=0; i<count; i++) {
808  detail::store_unaligned(_position+i*sizeof(T), swap<T>(values[i]));
809  }
810  } else {
811  memcpy(_position, values, n);
812  }
813  _position += n;
814  }
815 
816  template<typename T>
817  inline void ByteBuffer::getArray(T* values, std::size_t count)
818  {
819  size_t n = sizeof(T)*count; // bytes
820  assert(n<=getRemaining());
821 
822  if (reverse<T>()) {
823  for(std::size_t i=0; i<count; i++) {
824  values[i] = swap<T>(detail::load_unaligned<T>(_position+i*sizeof(T)));
825  }
826  } else {
827  memcpy(values, _position, n);
828  }
829  _position += n;
830  }
831 
832 }}
833 #endif /* BYTEBUFFER_H */
void putShort(std::size_t index, int16 value)
Definition: byteBuffer.h:577
void putDouble(double value)
Definition: byteBuffer.h:555
void putByte(std::size_t index, int8 value)
Definition: byteBuffer.h:570
int8 getByte(std::size_t index)
Definition: byteBuffer.h:661
T get(std::size_t index) const
Definition: byteBuffer.h:789
void putInt(int32 value)
Definition: byteBuffer.h:537
void putFloat(std::size_t index, float value)
Definition: byteBuffer.h:598
void putInt(std::size_t index, int32 value)
Definition: byteBuffer.h:584
void put(std::size_t index, T value) const
Definition: byteBuffer.h:760
void getArray(T *values, std::size_t count)
Definition: byteBuffer.h:817
ByteBuffer(char *buffer, std::size_t size, int byteOrder=EPICS_BYTE_ORDER)
Definition: byteBuffer.h:262
float getFloat(std::size_t index)
Definition: byteBuffer.h:689
double getDouble(std::size_t index)
Definition: byteBuffer.h:696
void putArray(const T *values, std::size_t count)
Definition: byteBuffer.h:801
uint32_t uint32
Definition: pvType.h:99
void setLimit(std::size_t limit)
Definition: byteBuffer.h:380
uint8_t uint8
Definition: pvType.h:91
int16_t int16
Definition: pvType.h:79
void setEndianess(int byteOrder)
Definition: byteBuffer.h:285
std::size_t getRemaining() const
Definition: byteBuffer.h:391
T swap(T val)
Definition: byteBuffer.h:209
std::size_t getLimit() const
Definition: byteBuffer.h:368
void putDouble(std::size_t index, double value)
Definition: byteBuffer.h:605
bool getBoolean(std::size_t index)
Definition: byteBuffer.h:654
void putLong(std::size_t index, int64 value)
Definition: byteBuffer.h:591
std::size_t getPosition() const
Definition: byteBuffer.h:346
virtual void serialize(ByteBuffer *buffer, SerializableControl *flusher, std::size_t offset, std::size_t count) const =0
void align(std::size_t size, char fill='\0')
Definition: byteBuffer.h:504
std::size_t getSize() const
Definition: byteBuffer.h:400
#define EPICS_ALWAYS_INLINE
Definition: byteBuffer.h:27
void putByte(int8 value)
Definition: byteBuffer.h:525
int64_t int64
Definition: pvType.h:87
void putShort(int16 value)
Definition: byteBuffer.h:531
void setPosition(std::size_t pos)
Definition: byteBuffer.h:357
const char * getBuffer() const
Definition: byteBuffer.h:294
int32_t int32
Definition: pvType.h:83
void putBoolean(bool value)
Definition: byteBuffer.h:519
int32 getInt(std::size_t index)
Definition: byteBuffer.h:675
ByteBuffer(std::size_t size, int byteOrder=EPICS_BYTE_ORDER)
Definition: byteBuffer.h:243
uint16_t uint16
Definition: pvType.h:95
#define GET(T)
Definition: byteBuffer.h:222
int8_t int8
Definition: pvType.h:75
void putLong(int64 value)
Definition: byteBuffer.h:543
int16 getShort(std::size_t index)
Definition: byteBuffer.h:668
void get(char *dest, std::size_t dest_offset, std::size_t count)
Definition: byteBuffer.h:465
void putFloat(float value)
Definition: byteBuffer.h:549
uint64_t uint64
Definition: pvType.h:103
void putBoolean(std::size_t index, bool value)
Definition: byteBuffer.h:563
int64 getLong(std::size_t index)
Definition: byteBuffer.h:682
void put(const char *src, std::size_t src_offset, std::size_t count)
Definition: byteBuffer.h:451