pull from sourceforge

This commit is contained in:
Marty Kraimer
2010-10-26 09:14:17 -04:00
8 changed files with 356 additions and 72 deletions

View File

@@ -80,3 +80,5 @@ pvDataApp/misc/bitSet.cpp
pvDataApp/test/testByteBuffer.cpp
pvDataApp/test/testBitSet.cpp
pvDataApp/test/testBaseException.cpp
pvDataApp/misc/serializeHelper.h
pvDataApp/misc/serializeHelper.cpp

View File

@@ -9,9 +9,11 @@ INC += serialize.h
INC += bitSet.h
INC += byteBuffer.h
INC += epicsException.h
INC += serializeHelper.h
LIBSRCS += byteBuffer.cpp
LIBSRCS += bitSet.cpp
LIBSRCS += serializeHelper.cpp
LIBRARY=pvMisc

View File

@@ -101,6 +101,19 @@ namespace epics {
return val;
}
ByteBuffer* ByteBuffer::put(const char* src, int offset, int count) {
if(count>getRemaining()) throw EpicsException("buffer overflow");
strncpy(&_buffer[_position], &src[offset], count);
_position += count;
return this;
}
void ByteBuffer::get(char*dst, int offset, int count) {
if(count>getRemaining()) throw EpicsException("buffer underflow");
strncpy(&dst[offset], &_buffer[_position], count);
_position += count;
}
ByteBuffer* ByteBuffer::putBoolean(bool value) {
if(_position<_limit)
_buffer[_position++] = value ? 1 : 0;

View File

@@ -133,9 +133,34 @@ namespace epics {
*/
double getDouble();
/**
* Relative bulk @em get method. It transfers {@code count} bytes
* from the buffer into the {@code dst}.
*
* @param[out] dst Destination buffer
* @param[in] offset Offset in the destination buffer
* @param[in] count The number of bytes to copy
* @throws EpicsException - Buffer underflow if there are fewer
* than count bytes remaining in the buffer.
*/
void get(char* dst, int offset, int count);
//virtual String getString() = 0; // TODO
/**
* Relative bulk @em put method. It transfers {@code count} bytes
* from the {@code src} into the the buffer.
*
* @param[in] src Source buffer
* @param[in] offset Offset in the source buffer
* @param[in] count The number of bytes to copy
* @returns Pointer to this ByteBuffer instance.
* @throws EpicsException - Buffer overflow if there are not
* enough bytes remaining in the buffer.
*/
ByteBuffer* put(const char* src, int offset, int count);
/**
* Relative boolean write, {@code position} is incremented by
* {@code 1}.

View File

@@ -12,11 +12,13 @@ namespace epics { namespace pvData {
class SerializableArray;
class SerializableControl {
public:
virtual void flushSerializeBuffer() =0;
virtual void ensureBuffer(int size) =0;
};
class DeserializableControl {
public:
virtual void ensureData(int size) =0;
};

View File

@@ -0,0 +1,120 @@
/*
* serializeHelper.cpp
*
* Created on: Oct 22, 2010
* Author: Miha vitorovic
*/
#include <algorithm>
#include <epicsTypes.h>
#include "epicsException.h"
#include "byteBuffer.h"
#include "serializeHelper.h"
using namespace std;
namespace epics {
namespace pvData {
void SerializeHelper::writeSize(int s, ByteBuffer* buffer,
SerializableControl* flusher) {
flusher->ensureBuffer(sizeof(epicsInt64)+1);
SerializeHelper::writeSize(s, buffer);
}
void SerializeHelper::writeSize(int s, ByteBuffer* buffer) {
if(s==-1) // null
buffer->putByte(-1);
else if(s<254)
buffer->putByte(s);
else
buffer->putByte(-2)->putInt(s); // (byte)-2 + size
}
int SerializeHelper::readSize(ByteBuffer* buffer,
DeserializableControl* control) {
control->ensureData(1);
epicsInt8 b = buffer->getByte();
if(b==-1)
return -1;
else if(b==-2) {
control->ensureData(sizeof(epicsInt32));
epicsInt32 s = buffer->getInt();
if(s<0) throw EpicsException("negative array size");
return s;
}
else
return (int)(b<0 ? b+256 : b);
}
void SerializeHelper::serializeString(const String& value,
ByteBuffer* buffer, SerializableControl* flusher) {
int len = value.length();
SerializeHelper::writeSize(len, buffer, flusher);
int i = 0;
while(true) {
int maxToWrite = min(len-i, buffer->getRemaining());
buffer->put(value.data(), i, maxToWrite); // UTF-8
i += maxToWrite;
if(i<len)
flusher->flushSerializeBuffer();
else
break;
}
}
void SerializeHelper::serializeSubstring(const String& value,
int offset, int count, ByteBuffer* buffer,
SerializableControl* flusher) {
if(offset<0)
offset = 0;
else if(offset>(int)value.length()) offset = value.length();
if(offset+count>(int)value.length()) count = value.length()-offset;
SerializeHelper::writeSize(count, buffer, flusher);
int i = 0;
while(true) {
int maxToWrite = min(count-i, buffer->getRemaining());
buffer->put(value.data(), offset+i, maxToWrite); // UTF-8
i += maxToWrite;
if(i<count)
flusher->flushSerializeBuffer();
else
break;
}
}
String SerializeHelper::deserializeString(ByteBuffer* buffer,
DeserializableControl* control) {
int size = SerializeHelper::readSize(buffer, control);
if(size>=0) {
char* retBuffer = new char[size]; // get the return buffer
try {
int i = 0;
while(true) {
int toRead = min(size-i, buffer->getRemaining());
buffer->get(retBuffer, i, toRead);
i += toRead;
if(i<size)
control->ensureData(1);
else
break;
}
String s = String(retBuffer, size);
delete retBuffer;
return s;
} catch(...) {
delete retBuffer; // remove the buffer
throw;
}
}
else
return String("");
}
}
}

View File

@@ -0,0 +1,98 @@
/*
* serializeHelper.h
*
* Created on: Oct 21, 2010
* Author: Miha Vitorovic
*/
#ifndef SERIALIZEHELPER_H_
#define SERIALIZEHELPER_H_
#include "serialize.h"
#include "byteBuffer.h"
#include "noDefaultMethods.h"
#include "../pv/pvIntrospect.h"
namespace epics {
namespace pvData {
class SerializeHelper : public NoDefaultMethods {
public:
/**
* Serialize array size.
*
* @param[in] s size to encode
* @param[in] buffer serialization buffer
* @param[in] flusher flusher
*/
static void writeSize(int s, ByteBuffer* buffer,
SerializableControl* flusher);
/**
* Deserialize array size.
*
* @param[in] buffer deserialization buffer.
* @returns array size.
*/
static int readSize(ByteBuffer* buffer,
DeserializableControl* control);
/**
* String serialization helper method.
*
* @param[in] value String to serialize
* @param[in] buffer serialization buffer
* @param[in] flusher flusher
*/
static void serializeString(const String& value, ByteBuffer* buffer,
SerializableControl* flusher);
/**
* String serialization helper method.
*
* @param[in] value String to serialize
* @param[in] offset start of the substring in {@code value}
* @param[in] count the number of characters to write
* @param[in] buffer serialization buffer
* @param[in] flusher flusher
*/
static void serializeSubstring(const String& value, int offset,
int count, ByteBuffer* buffer,
SerializableControl* flusher);
/**
* String deserialization helper method.
* TODO This method cannot return "null", but Java implementation
* could have serialized "null" value as well. We need to decide
* how to deserialize "null".
*
* @param[in] buffer deserialization buffer
* @param[in] control control
* @returns deserialized string
*
* @todo This method cannot return "null", but Java implementation
* could have serialized "null" value as well. We need to decide
* how to deserialize "null".
*/
static String deserializeString(ByteBuffer* buffer,
DeserializableControl* control);
private:
SerializeHelper() {};
~SerializeHelper() {};
/**
* Serialize array size.
*
* @param[in] s size to encode
* @param[in] buffer serialization buffer
*/
static void writeSize(int s, ByteBuffer* buffer);
};
}
}
#endif /* SERIALIZEHELPER_H_ */

View File

@@ -12,115 +12,137 @@
#include <epicsEndian.h>
#include "byteBuffer.h"
#include "pvIntrospect.h"
using namespace epics::pvData;
using std::cout;
void testBasicOperations() {
cout<<"Basic operation tests...\n";
cout<<"Basic operation tests...\n";
ByteBuffer* buff = new ByteBuffer();
assert(buff->getSize()==32);
assert(buff->getByteOrder()==EPICS_BYTE_ORDER);
assert(buff->getPosition()==0);
assert(buff->getLimit()==32);
assert(buff->getRemaining()==32);
ByteBuffer* buff = new ByteBuffer();
assert(buff->getSize()==32);
assert(buff->getByteOrder()==EPICS_BYTE_ORDER);
assert(buff->getPosition()==0);
assert(buff->getLimit()==32);
assert(buff->getRemaining()==32);
buff->putBoolean(true);
assert(buff->getPosition()==1);
assert(buff->getRemaining()==31);
buff->putBoolean(true);
assert(buff->getPosition()==1);
assert(buff->getRemaining()==31);
buff->putByte(-12);
assert(buff->getPosition()==2);
assert(buff->getRemaining()==30);
buff->putByte(-12);
assert(buff->getPosition()==2);
assert(buff->getRemaining()==30);
buff->putShort(10516);
assert(buff->getPosition()==4);
assert(buff->getRemaining()==28);
buff->putShort(10516);
assert(buff->getPosition()==4);
assert(buff->getRemaining()==28);
buff->putInt(0x1937628B);
assert(buff->getPosition()==8);
assert(buff->getRemaining()==24);
buff->putInt(0x1937628B);
assert(buff->getPosition()==8);
assert(buff->getRemaining()==24);
buff->putLong(2345678123LL);
assert(buff->getPosition()==16);
assert(buff->getRemaining()==16);
buff->putLong(2345678123LL);
assert(buff->getPosition()==16);
assert(buff->getRemaining()==16);
float testFloat = 34.67;
buff->putFloat(testFloat);
assert(buff->getPosition()==20);
assert(buff->getRemaining()==12);
float testFloat = 34.67;
buff->putFloat(testFloat);
assert(buff->getPosition()==20);
assert(buff->getRemaining()==12);
double testDouble = -512.23974;
buff->putDouble(testDouble);
assert(buff->getPosition()==28);
assert(buff->getRemaining()==4);
double testDouble = -512.23974;
buff->putDouble(testDouble);
assert(buff->getPosition()==28);
assert(buff->getRemaining()==4);
buff->flip();
assert(buff->getLimit()==28);
assert(buff->getPosition()==0);
assert(buff->getRemaining()==28);
buff->flip();
assert(buff->getLimit()==28);
assert(buff->getPosition()==0);
assert(buff->getRemaining()==28);
assert(buff->getBoolean()==true);
assert(buff->getPosition()==1);
assert(buff->getBoolean()==true);
assert(buff->getPosition()==1);
assert(buff->getByte()==-12);
assert(buff->getPosition()==2);
assert(buff->getByte()==-12);
assert(buff->getPosition()==2);
assert(buff->getShort()==10516);
assert(buff->getPosition()==4);
assert(buff->getShort()==10516);
assert(buff->getPosition()==4);
assert(buff->getInt()==0x1937628B);
assert(buff->getPosition()==8);
assert(buff->getInt()==0x1937628B);
assert(buff->getPosition()==8);
assert(buff->getLong()==2345678123LL);
assert(buff->getPosition()==16);
assert(buff->getLong()==2345678123LL);
assert(buff->getPosition()==16);
assert(buff->getFloat()==testFloat);
assert(buff->getPosition()==20);
assert(buff->getFloat()==testFloat);
assert(buff->getPosition()==20);
assert(buff->getDouble()==testDouble);
assert(buff->getPosition()==28);
assert(buff->getDouble()==testDouble);
assert(buff->getPosition()==28);
buff->clear();
assert(buff->getPosition()==0);
assert(buff->getLimit()==32);
assert(buff->getRemaining()==32);
buff->clear();
assert(buff->getPosition()==0);
assert(buff->getLimit()==32);
assert(buff->getRemaining()==32);
delete buff;
char src[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm' };
char dst[] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ' };
cout<<" PASSED\n";
buff->put(src, 2, 6);
assert(buff->getPosition()==6);
assert(strncmp(buff->getArray(),&src[2],6)==0);
buff->flip();
assert(buff->getLimit()==6);
assert(buff->getPosition()==0);
assert(buff->getRemaining()==6);
buff->get(dst, 2, 6);
assert(buff->getLimit()==6);
assert(buff->getPosition()==6);
assert(strncmp(&src[2],&dst[2],6)==0);
cout<<" First 10 characters of destination: >>"<<String(dst, 10)<<"<<\n";
delete buff;
cout<<"!!! PASSED\n";
}
void testInverseEndianness() {
cout<<"Testing inverse endianness...\n";
cout<<"Testing inverse endianness...\n";
#if EPICS_BYTE_ORDER==EPICS_ENDIAN_BIG
ByteBuffer* buff = new ByteBuffer(32,EPICS_ENDIAN_LITTLE);
char refBuffer[] =
{ (char)0x02, (char)0x01, (char)0x0D, (char)0x0C, (char)0x0B, (char)0x0A};
ByteBuffer* buff = new ByteBuffer(32,EPICS_ENDIAN_LITTLE);
char refBuffer[] =
{ (char)0x02, (char)0x01, (char)0x0D, (char)0x0C, (char)0x0B, (char)0x0A};
#else
ByteBuffer* buff = new ByteBuffer(32, EPICS_ENDIAN_BIG);
char refBuffer[] = { (char)0x01, (char)0x02, (char)0x0A, (char)0x0B,
(char)0x0C, (char)0x0D };
ByteBuffer* buff = new ByteBuffer(32, EPICS_ENDIAN_BIG);
char refBuffer[] = { (char)0x01, (char)0x02, (char)0x0A, (char)0x0B,
(char)0x0C, (char)0x0D };
#endif
buff->putShort(0x0102);
buff->putInt(0x0A0B0C0D);
buff->putShort(0x0102);
buff->putInt(0x0A0B0C0D);
assert(strncmp(buff->getArray(),refBuffer,6)==0);
assert(strncmp(buff->getArray(),refBuffer,6)==0);
buff->flip();
buff->flip();
assert(buff->getShort()==0x0102);
assert(buff->getInt()==0x0A0B0C0D);
assert(buff->getShort()==0x0102);
assert(buff->getInt()==0x0A0B0C0D);
delete buff;
cout<<" PASSED\n";
delete buff;
cout<<"!!! PASSED\n";
}
int main(int argc, char *argv[]) {
testBasicOperations();
testInverseEndianness();
return (0);
testBasicOperations();
testInverseEndianness();
return (0);
}