16 #include <epicsEndian.h> 18 #include <epicsAssert.h> 19 #include <compilerDependencies.h> 21 #include <pv/templateMeta.h> 22 #include <pv/pvType.h> 23 #include <pv/epicsException.h> 26 #ifndef EPICS_ALWAYS_INLINE 27 # define EPICS_ALWAYS_INLINE inline 33 #if defined(__clang__
) 35 #if __has_builtin
(__builtin_bswap16) 36 #define _PVA_swap16(X) __builtin_bswap16(X) 38 #if __has_builtin
(__builtin_bswap32) 39 #define _PVA_swap32(X) __builtin_bswap32(X) 41 #if __has_builtin
(__builtin_bswap64) 42 #define _PVA_swap64(X) __builtin_bswap64(X) 45 #elif defined(__GNUC__) && ((__GNUC__>4
) || (__GNUC__==4
&& __GNUC_MINOR__>=3
)) 47 #if (__GNUC__>4
) || (__GNUC__==4
&& __GNUC_MINOR__>=8
) 48 #define _PVA_swap16(X) __builtin_bswap16(X) 51 #define _PVA_swap32(X) __builtin_bswap32(X) 52 #define _PVA_swap64(X) __builtin_bswap64(X) 54 #elif defined(_MSC_VER) 56 #define _PVA_swap16(X) _byteswap_ushort(X) 57 #define _PVA_swap32(X) _byteswap_ulong(X) 58 #define _PVA_swap64(X) _byteswap_uint64(X) 62 namespace epics {
namespace pvData {
109 return _PVA_swap16(v);
111 return (((v) >> 8) | ((v) << 8));
119 return _PVA_swap32(v);
121 return ((((v) & 0xff000000) >> 24) |
122 (((v) & 0x00ff0000) >> 8) |
123 (((v) & 0x0000ff00) << 8) |
124 (((v) & 0x000000ff) << 24));
132 return _PVA_swap64(v);
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)) |
165 char bytes[
sizeof(T)];
169 EPICS_ALWAYS_INLINE
void store_unaligned(
char *buf, T val)
173 for(
unsigned i=0, N=
sizeof(T); i<N; i++) {
179 EPICS_ALWAYS_INLINE T load_unaligned(
const char *buf)
182 for(
unsigned i=0, N=
sizeof(T); i<N; i++) {
193 *
reinterpret_cast<T*>(buf) = val;
199 return *
reinterpret_cast<
const T*>(buf);
211 return detail::
asInt<T>::from(
212 detail::swap<
sizeof(T)>::op(
213 detail::
asInt<T>::to(val)));
216 #define is_aligned(POINTER, BYTE_COUNT) 217 (((std::size_t)(POINTER)) % (BYTE_COUNT) == 0
) 219 #if defined (__GNUC__
) && (__GNUC__
< 3
) 220 #define GET(T) get((T*)0
) 222 #define GET(T) get<T>() 250 throw std::bad_alloc();
269 throw std::invalid_argument(
"ByteBuffer can't be constructed with NULL");
277 if (_buffer && !_wrapped) std::free(_buffer);
287 _reverseEndianess = (byteOrder != EPICS_BYTE_ORDER);
288 _reverseFloatEndianess = (byteOrder != EPICS_FLOAT_WORD_ORDER);
305 _limit = _buffer + _size;
348 return _position - _buffer;
360 _position = _buffer + pos;
361 assert(_position<=_limit);
370 return _limit - _buffer;
382 assert(limit<=_size);
383 _limit = _buffer + limit;
384 assert(_position<=_limit);
393 return _limit - _position;
410 inline void put(T value);
418 inline void put(std::size_t index, T value)
const;
425 #if defined (__GNUC__
) && (__GNUC__
< 3
) 427 inline T get(
const T*);
441 inline T
get(std::size_t index)
const;
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);
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);
478 inline void putArray(
const T* values, std::size_t count);
487 inline void getArray(T* values, std::size_t count);
495 return sizeof(T)>1 && _reverseEndianess;
692 const std::size_t _size;
693 bool _reverseEndianess;
694 bool _reverseFloatEndianess;
719 return _reverseFloatEndianess;
725 return _reverseFloatEndianess;
731 inline void ByteBuffer::
put(T value)
733 assert(
sizeof(T)<=getRemaining());
736 value = swap<T>(value);
738 detail::store_unaligned(_position, value);
739 _position +=
sizeof(T);
743 inline void ByteBuffer::
put(std::size_t index, T value)
const 745 assert(_buffer+index<=_limit);
748 value = swap<T>(value);
750 detail::store_unaligned(_buffer+index, value);
753 #if defined (__GNUC__
) && (__GNUC__
< 3
) 758 inline T ByteBuffer::
get()
761 assert(
sizeof(T)<=getRemaining());
763 T value = detail::load_unaligned<T>(_position);
764 _position +=
sizeof(T);
767 value = swap<T>(value);
772 inline T ByteBuffer::
get(std::size_t index)
const 774 assert(_buffer+index<=_limit);
776 T value = detail::load_unaligned<T>(_buffer + index);
779 value = swap<T>(value);
784 inline void ByteBuffer::
putArray(
const T* values, std::size_t count)
786 size_t n =
sizeof(T)*count;
787 assert(n<=getRemaining());
790 for(std::size_t i=0; i<count; i++) {
791 detail::store_unaligned(_position+i*
sizeof(T), swap<T>(values[i]));
794 memcpy(_position, values, n);
800 inline void ByteBuffer::
getArray(T* values, std::size_t count)
802 size_t n =
sizeof(T)*count;
803 assert(n<=getRemaining());
806 for(std::size_t i=0; i<count; i++) {
807 values[i] = swap<T>(detail::load_unaligned<T>(_position+i*
sizeof(T)));
810 memcpy(values, _position, n);
void putShort(std::size_t index, int16 value)
void putDouble(double value)
void putByte(std::size_t index, int8 value)
int8 getByte(std::size_t index)
T get(std::size_t index) const
void putFloat(std::size_t index, float value)
void putInt(std::size_t index, int32 value)
void put(std::size_t index, T value) const
void getArray(T *values, std::size_t count)
ByteBuffer(char *buffer, std::size_t size, int byteOrder=EPICS_BYTE_ORDER)
float getFloat(std::size_t index)
double getDouble(std::size_t index)
void putArray(const T *values, std::size_t count)
void setLimit(std::size_t limit)
void setEndianess(int byteOrder)
std::size_t getRemaining() const
std::size_t getLimit() const
void putDouble(std::size_t index, double value)
bool getBoolean(std::size_t index)
void putLong(std::size_t index, int64 value)
std::size_t getPosition() const
virtual void serialize(ByteBuffer *buffer, SerializableControl *flusher, std::size_t offset, std::size_t count) const =0
std::size_t getSize() const
#define EPICS_ALWAYS_INLINE
void putShort(int16 value)
void setPosition(std::size_t pos)
const char * getBuffer() const
void putBoolean(bool value)
int32 getInt(std::size_t index)
ByteBuffer(std::size_t size, int byteOrder=EPICS_BYTE_ORDER)
void putLong(int64 value)
int16 getShort(std::size_t index)
void get(char *dest, std::size_t dest_offset, std::size_t count)
void putFloat(float value)
void putBoolean(std::size_t index, bool value)
int64 getLong(std::size_t index)
void put(const char *src, std::size_t src_offset, std::size_t count)