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;
504 inline void align(std::size_t size,
char fill=
'\0')
506 const std::size_t k = size - 1, bufidx = (std::size_t)_position;
508 std::size_t npad = size-(bufidx&k);
509 assert(npad<=getRemaining());
510 std::fill(_position, _position+npad, fill);
709 const std::size_t _size;
710 bool _reverseEndianess;
711 bool _reverseFloatEndianess;
736 return _reverseFloatEndianess;
742 return _reverseFloatEndianess;
748 inline void ByteBuffer::
put(T value)
750 assert(
sizeof(T)<=getRemaining());
753 value = swap<T>(value);
755 detail::store_unaligned(_position, value);
756 _position +=
sizeof(T);
760 inline void ByteBuffer::
put(std::size_t index, T value)
const 762 assert(_buffer+index<=_limit);
765 value = swap<T>(value);
767 detail::store_unaligned(_buffer+index, value);
770 #if defined (__GNUC__
) && (__GNUC__
< 3
) 775 inline T ByteBuffer::
get()
778 assert(
sizeof(T)<=getRemaining());
780 T value = detail::load_unaligned<T>(_position);
781 _position +=
sizeof(T);
784 value = swap<T>(value);
789 inline T ByteBuffer::
get(std::size_t index)
const 791 assert(_buffer+index<=_limit);
793 T value = detail::load_unaligned<T>(_buffer + index);
796 value = swap<T>(value);
801 inline void ByteBuffer::
putArray(
const T* values, std::size_t count)
803 size_t n =
sizeof(T)*count;
804 assert(n<=getRemaining());
807 for(std::size_t i=0; i<count; i++) {
808 detail::store_unaligned(_position+i*
sizeof(T), swap<T>(values[i]));
811 memcpy(_position, values, n);
817 inline void ByteBuffer::
getArray(T* values, std::size_t count)
819 size_t n =
sizeof(T)*count;
820 assert(n<=getRemaining());
823 for(std::size_t i=0; i<count; i++) {
824 values[i] = swap<T>(detail::load_unaligned<T>(_position+i*
sizeof(T)));
827 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
void align(std::size_t size, char fill='\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)