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 {
67 static EPICS_ALWAYS_INLINE T from(T v) {
return v; }
68 static EPICS_ALWAYS_INLINE T to(T v) {
return v; }
73 static EPICS_ALWAYS_INLINE
float from(
uint32 v) {
78 static EPICS_ALWAYS_INLINE
uint32 to(
float v) {
87 static EPICS_ALWAYS_INLINE
double from(
uint64 v) {
92 static EPICS_ALWAYS_INLINE
uint64 to(
double v) {
103 static EPICS_ALWAYS_INLINE
uint8 op(
uint8 v) {
return v; }
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);
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++) {
194 EPICS_ALWAYS_INLINE
void store_unaligned(
char *buf, T val)
196 *
reinterpret_cast<T*
>(buf) = val;
200 EPICS_ALWAYS_INLINE T load_unaligned(
const char *buf)
202 return *
reinterpret_cast<const T*
>(buf);
212 EPICS_ALWAYS_INLINE T
swap(T 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>()
247 _buffer((char*)std::malloc(size)), _size(size),
248 _reverseEndianess(byteOrder != EPICS_BYTE_ORDER),
249 _reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER),
266 _buffer(buffer), _size(size),
267 _reverseEndianess(byteOrder != EPICS_BYTE_ORDER),
268 _reverseFloatEndianess(byteOrder != EPICS_FLOAT_WORD_ORDER),
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;
403 EPICS_ALWAYS_INLINE std::size_t
getSize()
const
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) {
456 memcpy(_position, src + src_offset, count);
468 inline void get(
char* dest, std::size_t dest_offset, std::size_t
count) {
470 memcpy(dest + dest_offset, _position,
count);
490 inline void getArray(T* values, std::size_t
count);
498 return sizeof(T)>1 && _reverseEndianess;
505 EPICS_ALWAYS_INLINE
void putBoolean(
bool value) { put< int8>(value ? 1 : 0); }
511 EPICS_ALWAYS_INLINE
void putByte (
int8 value) { put< int8>(value); }
523 EPICS_ALWAYS_INLINE
void putInt (
int32 value) { put< int32>(value); }
529 EPICS_ALWAYS_INLINE
void putLong (
int64 value) { put< int64>(value); }
535 EPICS_ALWAYS_INLINE
void putFloat (
float value) { put< float>(value); }
541 EPICS_ALWAYS_INLINE
void putDouble (
double value) { put<double>(value); }
549 EPICS_ALWAYS_INLINE
void putBoolean(std::size_t index,
bool value) { put< int8>(index, value); }
556 EPICS_ALWAYS_INLINE
void putByte (std::size_t index,
int8 value) { put< int8>(index, value); }
563 EPICS_ALWAYS_INLINE
void putShort (std::size_t index,
int16 value) { put< int16>(index, value); }
570 EPICS_ALWAYS_INLINE
void putInt (std::size_t index,
int32 value) { put< int32>(index, value); }
577 EPICS_ALWAYS_INLINE
void putLong (std::size_t index,
int64 value) { put< int64>(index, value); }
584 EPICS_ALWAYS_INLINE
void putFloat (std::size_t index,
float value) { put< float>(index, value); }
591 EPICS_ALWAYS_INLINE
void putDouble (std::size_t index,
double value) { put<double>(index, value); }
627 EPICS_ALWAYS_INLINE
float getFloat () {
return GET(
float); }
633 EPICS_ALWAYS_INLINE
double getDouble () {
return GET(
double); }
640 EPICS_ALWAYS_INLINE
bool getBoolean(std::size_t index) {
return get< int8>(index) != 0; }
647 EPICS_ALWAYS_INLINE
int8 getByte (std::size_t index) {
return get< int8>(index); }
654 EPICS_ALWAYS_INLINE
int16 getShort (std::size_t index) {
return get< int16>(index); }
661 EPICS_ALWAYS_INLINE
int32 getInt (std::size_t index) {
return get< int32>(index); }
668 EPICS_ALWAYS_INLINE
int64 getLong (std::size_t index) {
return get< int64>(index); }
675 EPICS_ALWAYS_INLINE
float getFloat (std::size_t index) {
return get< float>(index); }
682 EPICS_ALWAYS_INLINE
double getDouble (std::size_t index) {
return get<double>(index); }
685 EPICS_ALWAYS_INLINE
const char* getArray() const EPICS_DEPRECATED
695 const std::size_t _size;
696 bool _reverseEndianess;
697 bool _reverseFloatEndianess;
702 EPICS_ALWAYS_INLINE
bool ByteBuffer::reverse<bool>()
const
708 EPICS_ALWAYS_INLINE
bool ByteBuffer::reverse<int8>()
const
714 EPICS_ALWAYS_INLINE
bool ByteBuffer::reverse<uint8>()
const
720 EPICS_ALWAYS_INLINE
bool ByteBuffer::reverse<float>()
const
722 return _reverseFloatEndianess;
726 EPICS_ALWAYS_INLINE
bool ByteBuffer::reverse<double>()
const
728 return _reverseFloatEndianess;
739 value = swap<T>(value);
741 detail::store_unaligned(_position, value);
742 _position +=
sizeof(T);
748 assert(_buffer+index<=_limit);
751 value = swap<T>(value);
753 detail::store_unaligned(_buffer+index, value);
756 #if defined (__GNUC__) && (__GNUC__ < 3)
764 assert(
sizeof(T)<=getRemaining());
766 T value = detail::load_unaligned<T>(_position);
767 _position +=
sizeof(T);
770 value = swap<T>(value);
777 assert(_buffer+index<=_limit);
779 T value = detail::load_unaligned<T>(_buffer + index);
782 value = swap<T>(value);
789 size_t n =
sizeof(T)*count;
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;
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)
void putFloat(std::size_t index, float value)
void putInt(std::size_t index, int32 value)
valarray< size_t > size() const
ByteBuffer(char *buffer, std::size_t size, int byteOrder=EPICS_BYTE_ORDER)
float getFloat(std::size_t index)
std::size_t getSize() const
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)
void putDouble(std::size_t index, double value)
bool getBoolean(std::size_t index)
void putLong(std::size_t index, int64 value)
This class implements a Bytebuffer that is like the java.nio.ByteBuffer.
std::size_t getLimit() const
std::size_t getPosition() const
constexpr iterator_traits< _InputIterator >::difference_type count(_InputIterator __first, _InputIterator __last, const _Tp &__value)
const char * getBuffer() const
void putShort(int16 value)
void setPosition(std::size_t pos)
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 putFloat(float value)
std::size_t getRemaining() const
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)