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)) |
163 #if !(defined(__x86_64__
) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) 168 char bytes[
sizeof(T)];
172 EPICS_ALWAYS_INLINE
void store_unaligned(
char *buf, T val)
176 for(
unsigned i=0, N=
sizeof(T); i<N; i++) {
182 EPICS_ALWAYS_INLINE T load_unaligned(
const char *buf)
185 for(
unsigned i=0, N=
sizeof(T); i<N; i++) {
196 *
reinterpret_cast<T*>(buf) = val;
202 return *
reinterpret_cast<
const T*>(buf);
214 return detail::
asInt<T>::from(
215 detail::swap<
sizeof(T)>::op(
216 detail::
asInt<T>::to(val)));
219 #define is_aligned(POINTER, BYTE_COUNT) 220 (((std::size_t)(POINTER)) % (BYTE_COUNT) == 0
) 222 #if defined (__GNUC__
) && (__GNUC__
< 3
) 223 #define GET(T) get((T*)0
) 225 #define GET(T) get<T>() 253 throw std::bad_alloc();
272 throw std::invalid_argument(
"ByteBuffer can't be constructed with NULL");
280 if (_buffer && !_wrapped) std::free(_buffer);
290 _reverseEndianess = (byteOrder != EPICS_BYTE_ORDER);
291 _reverseFloatEndianess = (byteOrder != EPICS_FLOAT_WORD_ORDER);
308 _limit = _buffer + _size;
351 return _position - _buffer;
363 _position = _buffer + pos;
364 assert(_position<=_limit);
373 return _limit - _buffer;
385 assert(limit<=_size);
386 _limit = _buffer + limit;
387 assert(_position<=_limit);
396 return _limit - _position;
413 inline void put(T value);
421 inline void put(std::size_t index, T value)
const;
428 #if defined (__GNUC__
) && (__GNUC__
< 3
) 430 inline T get(
const T*);
444 inline T
get(std::size_t index)
const;
454 inline void put(
const char* src, std::size_t src_offset, std::size_t count) {
455 assert(count<=getRemaining());
456 memcpy(_position, src + src_offset, count);
468 inline void get(
char* dest, std::size_t dest_offset, std::size_t count) {
469 assert(count<=getRemaining());
470 memcpy(dest + dest_offset, _position, count);
481 inline void putArray(
const T* values, std::size_t count);
490 inline void getArray(T* values, std::size_t count);
498 return sizeof(T)>1 && _reverseEndianess;
695 const std::size_t _size;
696 bool _reverseEndianess;
697 bool _reverseFloatEndianess;
722 return _reverseFloatEndianess;
728 return _reverseFloatEndianess;
734 inline void ByteBuffer::
put(T value)
736 assert(
sizeof(T)<=getRemaining());
739 value = swap<T>(value);
741 detail::store_unaligned(_position, value);
742 _position +=
sizeof(T);
746 inline void ByteBuffer::
put(std::size_t index, T value)
const 748 assert(_buffer+index<=_limit);
751 value = swap<T>(value);
753 detail::store_unaligned(_buffer+index, value);
756 #if defined (__GNUC__
) && (__GNUC__
< 3
) 761 inline T ByteBuffer::
get()
764 assert(
sizeof(T)<=getRemaining());
766 T value = detail::load_unaligned<T>(_position);
767 _position +=
sizeof(T);
770 value = swap<T>(value);
775 inline T ByteBuffer::
get(std::size_t index)
const 777 assert(_buffer+index<=_limit);
779 T value = detail::load_unaligned<T>(_buffer + index);
782 value = swap<T>(value);
787 inline void ByteBuffer::
putArray(
const T* values, std::size_t count)
789 size_t n =
sizeof(T)*count;
790 assert(n<=getRemaining());
793 for(std::size_t i=0; i<count; i++) {
794 detail::store_unaligned(_position+i*
sizeof(T), swap<T>(values[i]));
797 memcpy(_position, values, n);
803 inline void ByteBuffer::
getArray(T* values, std::size_t count)
805 size_t n =
sizeof(T)*count;
806 assert(n<=getRemaining());
809 for(std::size_t i=0; i<count; i++) {
810 values[i] = swap<T>(detail::load_unaligned<T>(_position+i*
sizeof(T)));
813 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)