new ByteBuffer and faster/fixed array serialization support
This commit is contained in:
@@ -29,7 +29,7 @@ INC += status.h
|
||||
INC += sharedPtr.h
|
||||
|
||||
LIBSRCS += CDRMonitor.cpp
|
||||
LIBSRCS += byteBuffer.cpp
|
||||
#LIBSRCS += byteBuffer.cpp
|
||||
LIBSRCS += bitSet.cpp
|
||||
LIBSRCS += epicsException.cpp
|
||||
LIBSRCS += requester.cpp
|
||||
|
||||
@@ -261,17 +261,24 @@ template<typename T>
|
||||
void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
int size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
// if (size>0) { pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T)); }
|
||||
if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>this->getCapacity()) this->setCapacity(size);
|
||||
// retrieve value from the buffer
|
||||
int i = 0;
|
||||
while(true) {
|
||||
int maxIndex = std::min(size-i, pbuffer->getRemaining())+i;
|
||||
/*
|
||||
int maxIndex = std::min(size-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
|
||||
for(; i<maxIndex; i++)
|
||||
value[i] = pbuffer->get<T>();
|
||||
*/
|
||||
int maxCount = std::min(size-i, (int)(pbuffer->getRemaining()/sizeof(T)));
|
||||
pbuffer->getArray<T>(&value[i], maxCount);
|
||||
i += maxCount;
|
||||
|
||||
if(i<size)
|
||||
pcontrol->ensureData(1); // // TODO is there a better way to ensureData?
|
||||
pcontrol->ensureData(sizeof(T)); // this is not OK since can exceen max local buffer (size-i)*sizeof(T));
|
||||
else
|
||||
break;
|
||||
}
|
||||
@@ -299,12 +306,21 @@ void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
//if (count == 0) return; pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T));
|
||||
int end = offset+count;
|
||||
int i = offset;
|
||||
while(true) {
|
||||
int maxIndex = std::min<int>(end-i, pbuffer->getRemaining())+i;
|
||||
|
||||
/*
|
||||
int maxIndex = std::min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
|
||||
for(; i<maxIndex; i++)
|
||||
pbuffer->put(value[i]);
|
||||
pbuffer->put<T>(value[i]);
|
||||
*/
|
||||
|
||||
int maxCount = std::min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)));
|
||||
pbuffer->putArray<T>(&value[i], maxCount);
|
||||
i += maxCount;
|
||||
|
||||
if(i<end)
|
||||
pflusher->flushSerializeBuffer();
|
||||
else
|
||||
|
||||
@@ -3,308 +3,3 @@
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/*
|
||||
* byteBuffer.cpp
|
||||
*
|
||||
* Created on: Oct 18, 2010
|
||||
* Author: Miha Vitorovic
|
||||
*/
|
||||
#include <cstring>
|
||||
#include <pv/byteBuffer.h>
|
||||
#include <pv/epicsException.h>
|
||||
|
||||
// TODO optimize, avoid so many checks (endianness, positions), allow wrapping of external buffer, chance of endianess
|
||||
namespace epics {
|
||||
namespace pvData {
|
||||
|
||||
using std::stringstream;
|
||||
|
||||
ByteBuffer::ByteBuffer(int size, int byteOrder) :
|
||||
_bufferByteOrder(byteOrder), _size(size), _position(0),
|
||||
_limit(size), _buffer(0) {
|
||||
|
||||
if(size<0) THROW_BASE_EXCEPTION("negative size");
|
||||
|
||||
if (byteOrder!=EPICS_ENDIAN_BIG && byteOrder!=EPICS_ENDIAN_LITTLE)
|
||||
THROW_BASE_EXCEPTION("invalid endianness");
|
||||
|
||||
_buffer = new char[_size];
|
||||
}
|
||||
|
||||
ByteBuffer::~ByteBuffer() {
|
||||
if (_buffer) delete[] _buffer;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::clear() {
|
||||
_position = 0;
|
||||
_limit = _size;
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::flip() {
|
||||
_limit = _position;
|
||||
_position = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::rewind() {
|
||||
_position = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
bool ByteBuffer::getBoolean() {
|
||||
return getBoolean(_position++);
|
||||
}
|
||||
|
||||
bool ByteBuffer::getBoolean(int index) {
|
||||
if(index>=0&&index<_limit)
|
||||
return _buffer[index]==0 ? false : true;
|
||||
else
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
}
|
||||
|
||||
int8 ByteBuffer::getByte() {
|
||||
return getByte(_position++);
|
||||
}
|
||||
|
||||
int8 ByteBuffer::getByte(int index) {
|
||||
if(index>=0&&index<_limit)
|
||||
return (int8)_buffer[index];
|
||||
else
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
}
|
||||
|
||||
int16 ByteBuffer::getShort() {
|
||||
if(_limit-_position<(int)sizeof(int16))
|
||||
THROW_BASE_EXCEPTION("buffer underflow");
|
||||
int16 val;
|
||||
getWithEndianness((char*)&val, sizeof(int16)); // store short into val
|
||||
return val;
|
||||
}
|
||||
|
||||
int16 ByteBuffer::getShort(int index) {
|
||||
if(index<0||_limit-index<(int)sizeof(int16))
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
int16 val;
|
||||
getWithEndianness(index, (char*)&val, sizeof(int16)); // store short into val
|
||||
return val;
|
||||
|
||||
}
|
||||
|
||||
int32 ByteBuffer::getInt() {
|
||||
if(_limit-_position<(int)sizeof(int32))
|
||||
THROW_BASE_EXCEPTION("buffer underflow");
|
||||
int32 val;
|
||||
getWithEndianness((char*)&val, sizeof(int32)); // store int into val
|
||||
return val;
|
||||
}
|
||||
|
||||
int32 ByteBuffer::getInt(int index) {
|
||||
if(index<0||_limit-index<(int)sizeof(int32))
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
int32 val;
|
||||
getWithEndianness(index, (char*)&val, sizeof(int32)); // store int into val
|
||||
return val;
|
||||
}
|
||||
|
||||
int64 ByteBuffer::getLong() {
|
||||
if(_limit-_position<(int)sizeof(int64))
|
||||
THROW_BASE_EXCEPTION("buffer underflow");
|
||||
int64 val;
|
||||
getWithEndianness((char*)&val, sizeof(int64)); // store long into val
|
||||
return val;
|
||||
}
|
||||
|
||||
int64 ByteBuffer::getLong(int index) {
|
||||
if(index<0||_limit-index<(int)sizeof(int64))
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
int64 val;
|
||||
getWithEndianness(index, (char*)&val, sizeof(int64)); // store long into val
|
||||
return val;
|
||||
}
|
||||
|
||||
float ByteBuffer::getFloat() {
|
||||
if(_limit-_position<(int)sizeof(float))
|
||||
THROW_BASE_EXCEPTION("buffer underflow");
|
||||
float val;
|
||||
getWithEndianness((char*)&val, sizeof(float)); // store float into val
|
||||
return val;
|
||||
}
|
||||
|
||||
float ByteBuffer::getFloat(int index) {
|
||||
if(index<0||_limit-index<(int)sizeof(float))
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
float val;
|
||||
getWithEndianness(index, (char*)&val, sizeof(float)); // store float into val
|
||||
return val;
|
||||
}
|
||||
|
||||
double ByteBuffer::getDouble() {
|
||||
if(_limit-_position<(int)sizeof(double))
|
||||
THROW_BASE_EXCEPTION("buffer underflow");
|
||||
double val;
|
||||
getWithEndianness((char*)&val, sizeof(double)); // store double into val
|
||||
return val;
|
||||
}
|
||||
|
||||
double ByteBuffer::getDouble(int index) {
|
||||
if(index>=0&&_limit-index<(int)sizeof(double)) THROW_BASE_EXCEPTION(
|
||||
"index out of bounds");
|
||||
double val;
|
||||
getWithEndianness(index, (char*)&val, sizeof(double)); // store double into val
|
||||
return val;
|
||||
}
|
||||
|
||||
void ByteBuffer::get(char* dst, int offset, int count) {
|
||||
if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer underflow");
|
||||
for(int i = 0; i<count; i++)
|
||||
dst[offset+i] = _buffer[_position++];
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::put(const char* src, int offset, int count) {
|
||||
if(count>getRemaining()) THROW_BASE_EXCEPTION("buffer overflow");
|
||||
for(int i = 0; i<count; i++)
|
||||
_buffer[_position++] = src[offset+i];
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putBoolean(bool value) {
|
||||
return putByte(_position++, value ? 1 : 0);
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putBoolean(int index, bool value) {
|
||||
return putByte(index, value ? 1 : 0);
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putByte(int8 value) {
|
||||
return putByte(_position++, value);
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putByte(int index, int8 value) {
|
||||
if(index>=0&&index<_limit)
|
||||
_buffer[index] = (char)value;
|
||||
else
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putShort(int16 value) {
|
||||
if(_limit-_position<(int)sizeof(int16))
|
||||
THROW_BASE_EXCEPTION("buffer overflow");
|
||||
putWithEndianness((char*)&value, sizeof(int16)); // store short into buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putShort(int index, int16 value) {
|
||||
if(index<0||_limit-index<(int)sizeof(int16))
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
putWithEndianness(index, (char*)&value, sizeof(int16)); // store short into buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putInt(int32 value) {
|
||||
if(_limit-_position<(int)sizeof(int32))
|
||||
THROW_BASE_EXCEPTION("buffer overflow");
|
||||
putWithEndianness((char*)&value, sizeof(int32)); // store int into buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putInt(int index, int32 value) {
|
||||
if(index<0||_limit-index<(int)sizeof(int32))
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
putWithEndianness(index, (char*)&value, sizeof(int32)); // store int into buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putLong(int64 value) {
|
||||
if(_limit-_position<(int)sizeof(int64))
|
||||
THROW_BASE_EXCEPTION("buffer overflow");
|
||||
putWithEndianness((char*)&value, sizeof(int64)); // store long into buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putLong(int index, int64 value) {
|
||||
if(index<0||_limit-index<(int)sizeof(int64))
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
putWithEndianness(index, (char*)&value, sizeof(int64)); // store long into buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putFloat(float value) {
|
||||
if(_limit-_position<(int)sizeof(float))
|
||||
THROW_BASE_EXCEPTION("buffer overflow");
|
||||
putWithEndianness((char*)&value, sizeof(float)); // store float into buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putFloat(int index, float value) {
|
||||
if(index<0||_limit-index<(int)sizeof(float))
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
putWithEndianness(index, (char*)&value, sizeof(float)); // store float into buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putDouble(double value) {
|
||||
if(_limit-_position<(int)sizeof(double))
|
||||
THROW_BASE_EXCEPTION("buffer overflow");
|
||||
putWithEndianness((char*)&value, sizeof(double)); // store double into buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
ByteBuffer* ByteBuffer::putDouble(int index, double value) {
|
||||
if(index<0||_limit-index<(int)sizeof(double))
|
||||
THROW_BASE_EXCEPTION("index out of bounds");
|
||||
putWithEndianness(index, (char*)&value, sizeof(double)); // store double into buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Buffer underflow or overflow checks are performed in the caller.
|
||||
*/
|
||||
void ByteBuffer::getWithEndianness(char* dest, size_t size) {
|
||||
if(_bufferByteOrder==EPICS_BYTE_ORDER)
|
||||
for(size_t i = 0; i<size; i++)
|
||||
dest[i] = _buffer[_position++];
|
||||
else
|
||||
for(int i = (int)size-1; i>=0; i--)
|
||||
dest[i] = _buffer[_position++];
|
||||
}
|
||||
|
||||
/**
|
||||
* Buffer underflow or overflow checks are performed in the caller.
|
||||
*/
|
||||
void ByteBuffer::putWithEndianness(char* src, size_t size) {
|
||||
if(_bufferByteOrder==EPICS_BYTE_ORDER)
|
||||
for(size_t i = 0; i<size; i++)
|
||||
_buffer[_position++] = src[i];
|
||||
else
|
||||
for(int i = (int)size-1; i>=0; i--)
|
||||
_buffer[_position++] = src[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Buffer underflow or overflow checks are performed in the caller.
|
||||
*/
|
||||
void ByteBuffer::putWithEndianness(int index, char* src, size_t size) {
|
||||
if(_bufferByteOrder==EPICS_BYTE_ORDER)
|
||||
for(size_t i = 0; i<size; i++)
|
||||
_buffer[index++] = src[i];
|
||||
else
|
||||
for(int i = (int)size-1; i>=0; i--)
|
||||
_buffer[index++] = src[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Buffer underflow or overflow checks are performed in the caller.
|
||||
*/
|
||||
void ByteBuffer::getWithEndianness(int index, char* dest, size_t size) {
|
||||
if(_bufferByteOrder==EPICS_BYTE_ORDER)
|
||||
for(size_t i = 0; i<size; i++)
|
||||
dest[i] = _buffer[index++];
|
||||
else
|
||||
for(int i = (int)size-1; i>=0; i--)
|
||||
dest[i] = _buffer[index++];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -63,7 +63,7 @@ namespace epics {
|
||||
SerializeHelper::writeSize(len, buffer, flusher);
|
||||
int i = 0;
|
||||
while(true) {
|
||||
int maxToWrite = min(len-i, buffer->getRemaining());
|
||||
int maxToWrite = min(len-i, (int)buffer->getRemaining());
|
||||
buffer->put(value.data(), i, maxToWrite); // UTF-8
|
||||
i += maxToWrite;
|
||||
if(i<len)
|
||||
@@ -85,7 +85,7 @@ namespace epics {
|
||||
SerializeHelper::writeSize(count, buffer, flusher);
|
||||
int i = 0;
|
||||
while(true) {
|
||||
int maxToWrite = min(count-i, buffer->getRemaining());
|
||||
int maxToWrite = min(count-i, (int)buffer->getRemaining());
|
||||
buffer->put(value.data(), offset+i, maxToWrite); // UTF-8
|
||||
i += maxToWrite;
|
||||
if(i<count)
|
||||
@@ -103,7 +103,7 @@ namespace epics {
|
||||
int size = SerializeHelper::readSize(buffer, control);
|
||||
if(size>0)
|
||||
{
|
||||
if (buffer->getRemaining()>=size)
|
||||
if ((int)buffer->getRemaining()>=size)
|
||||
{
|
||||
// entire string is in buffer, simply create a string out of it (copy)
|
||||
int pos = buffer->getPosition();
|
||||
@@ -118,7 +118,7 @@ namespace epics {
|
||||
try {
|
||||
int i = 0;
|
||||
while(true) {
|
||||
int toRead = min(size-i, buffer->getRemaining());
|
||||
int toRead = min(size-i, (int)buffer->getRemaining());
|
||||
int pos = buffer->getPosition();
|
||||
str.append(buffer->getArray()+pos, toRead);
|
||||
buffer->setPosition(pos+toRead);
|
||||
|
||||
@@ -25,9 +25,9 @@ using namespace epics::pvData;
|
||||
void testBasicOperations(std::ostream& ofile) {
|
||||
ofile<<"Basic operation tests...\n";
|
||||
|
||||
ByteBuffer* buff = new ByteBuffer();
|
||||
ByteBuffer* buff = new ByteBuffer(32);
|
||||
assert(buff->getSize()==32);
|
||||
assert(buff->getByteOrder()==EPICS_BYTE_ORDER);
|
||||
// assert(buff->getByteOrder()==EPICS_BYTE_ORDER);
|
||||
assert(buff->getPosition()==0);
|
||||
assert(buff->getLimit()==32);
|
||||
assert(buff->getRemaining()==32);
|
||||
@@ -70,6 +70,18 @@ void testBasicOperations(std::ostream& ofile) {
|
||||
assert(buff->getLong(8)==2345678123LL);
|
||||
assert(buff->getFloat(16)==testFloat);
|
||||
assert(buff->getDouble(20)==testDouble);
|
||||
/*
|
||||
uintptr_t sp = buff->getPosition();
|
||||
buff->setPosition(0);
|
||||
assert(buff->getBoolean()==true);
|
||||
assert(buff->getByte()==-12);
|
||||
assert(buff->getShort()==10516);
|
||||
assert(buff->getInt()==0x1937628B);
|
||||
assert(buff->getLong()==2345678123LL);
|
||||
assert(buff->getFloat()==testFloat);
|
||||
assert(buff->getDouble()==testDouble);
|
||||
buff->setPosition(sp);
|
||||
*/
|
||||
|
||||
buff->flip();
|
||||
assert(buff->getLimit()==28);
|
||||
@@ -122,7 +134,19 @@ void testBasicOperations(std::ostream& ofile) {
|
||||
buff->putLong(8, 2345678123LL);
|
||||
buff->putFloat(16, testFloat);
|
||||
buff->putDouble(20, testDouble);
|
||||
|
||||
/*
|
||||
buff->clear();
|
||||
buff->setPosition(28);
|
||||
sp = buff->getPosition();
|
||||
buff->putBoolean(true);
|
||||
buff->putByte(-12);
|
||||
buff->putShort(10516);
|
||||
buff->putInt(0x1937628B);
|
||||
buff->putLong(2345678123LL);
|
||||
buff->putFloat(testFloat);
|
||||
buff->putDouble(testDouble);
|
||||
buff->setPosition(sp);
|
||||
*/
|
||||
buff->flip();
|
||||
assert(buff->getLimit()==28);
|
||||
assert(buff->getPosition()==0);
|
||||
|
||||
Reference in New Issue
Block a user