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)