new ByteBuffer and faster/fixed array serialization support

This commit is contained in:
Matej Sekoranja
2011-09-08 10:59:56 +02:00
parent 688137dbbe
commit c762d94f7a
6 changed files with 548 additions and 785 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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);