diff --git a/pvDataApp/factory/BasePVBoolean.h b/pvDataApp/factory/BasePVBoolean.h index 674124c..0ce3e55 100644 --- a/pvDataApp/factory/BasePVBoolean.h +++ b/pvDataApp/factory/BasePVBoolean.h @@ -9,6 +9,7 @@ #include "convert.h" #include "factory.h" #include "AbstractPVField.h" +#include "byteBuffer.h" namespace epics { namespace pvData { @@ -21,13 +22,13 @@ namespace epics { namespace pvData { virtual bool get(); virtual void put(bool val); virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) ; + SerializableControl *pflusher); virtual void deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher); virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: bool value; }; @@ -43,33 +44,34 @@ namespace epics { namespace pvData { void BasePVBoolean::put(bool val){value = val;} void BasePVBoolean::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + pflusher->ensureBuffer(1); + pbuffer->putBoolean(value); } void BasePVBoolean::deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher) { - throw std::logic_error(notImplemented); + pflusher->ensureData(1); + value = pbuffer->getBoolean(); } void BasePVBoolean::toString(StringBuilder buf) {toString(buf,0);} - void BasePVBoolean::toString(StringBuilder buf,int indentLevel) + void BasePVBoolean::toString(StringBuilder buf,int indentLevel) { getConvert()->getString(buf,this,indentLevel); PVField::toString(buf,indentLevel); } - bool BasePVBoolean::operator==(PVField *pvField) + bool BasePVBoolean::operator==(PVField& pvField) { - return getConvert()->equals(this,pvField); + return getConvert()->equals(this, &pvField); } - bool BasePVBoolean::operator!=(PVField *pvField) + bool BasePVBoolean::operator!=(PVField& pvField) { - return !(getConvert()->equals(this,pvField)); + return !(getConvert()->equals(this, &pvField)); } }} diff --git a/pvDataApp/factory/BasePVBooleanArray.h b/pvDataApp/factory/BasePVBooleanArray.h index 306f837..6d14259 100644 --- a/pvDataApp/factory/BasePVBooleanArray.h +++ b/pvDataApp/factory/BasePVBooleanArray.h @@ -8,6 +8,9 @@ #include "pvData.h" #include "factory.h" #include "AbstractPVScalarArray.h" +#include "serializeHelper.h" + +using std::min; namespace epics { namespace pvData { @@ -32,8 +35,8 @@ namespace epics { namespace pvData { SerializableControl *pflusher, int offset, int count) ; virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: bool *value; }; @@ -41,7 +44,7 @@ namespace epics { namespace pvData { BasePVBooleanArray::BasePVBooleanArray(PVStructure *parent, ScalarArrayConstPtr scalarArray) : PVBooleanArray(parent,scalarArray),value(new bool[0]) - { } + { } BasePVBooleanArray::~BasePVBooleanArray() { @@ -58,14 +61,14 @@ namespace epics { namespace pvData { } int length = PVArray::getLength(); if(length>capacity) length = capacity; - bool *newValue = new bool[capacity]; + bool *newValue = new bool[capacity]; for(int i=0; i=0) { + // prepare array, if necessary + if(size>getCapacity()) setCapacity(size); + // retrieve value from the buffer + int i = 0; + while(true) { + int maxIndex = min(size-i, pbuffer->getRemaining())+i; + for(; igetBoolean(); + if(iensureData(1); // // TODO is there a better way to ensureData? + else + break; + } + // set new length + setLength(size); + postPut(); + } + // TODO null arrays (size == -1) not supported } void BasePVBooleanArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher, int offset, int count) { + // cache + int length = getLength(); + + // check bounds + if(offset<0) + offset = 0; + else if(offset>length) offset = length; + if(count<0) count = length; + + int maxCount = length-offset; + if(count>maxCount) count = maxCount; + + // write + SerializeHelper::writeSize(count, pbuffer, pflusher); + int end = offset+count; + int i = offset; + while(true) { + int maxIndex = min(end-i, pbuffer->getRemaining())+i; + for(; iputBoolean(value[i]); + if(iflushSerializeBuffer(); + else + break; + } } void BasePVBooleanArray::toString(StringBuilder buf) @@ -144,14 +187,14 @@ namespace epics { namespace pvData { PVField::toString(buf,indentLevel); } - bool BasePVBooleanArray::operator==(PVField *pv) + bool BasePVBooleanArray::operator==(PVField& pv) { - return getConvert()->equals(this,pv); + return getConvert()->equals(this, &pv); } - bool BasePVBooleanArray::operator!=(PVField *pv) + bool BasePVBooleanArray::operator!=(PVField& pv) { - return !(getConvert()->equals(this,pv)); + return !(getConvert()->equals(this, &pv)); } }} #endif /* BASEPVBOOLEANARRAY_H */ diff --git a/pvDataApp/factory/BasePVByte.h b/pvDataApp/factory/BasePVByte.h index 1c9ab6e..bb74d4a 100644 --- a/pvDataApp/factory/BasePVByte.h +++ b/pvDataApp/factory/BasePVByte.h @@ -9,6 +9,7 @@ #include "convert.h" #include "factory.h" #include "AbstractPVField.h" +#include "byteBuffer.h" namespace epics { namespace pvData { @@ -26,14 +27,14 @@ namespace epics { namespace pvData { DeserializableControl *pflusher); virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: int8 value; }; BasePVByte::BasePVByte(PVStructure *parent,ScalarConstPtr scalar) - : PVByte(parent,scalar),value(0.0) + : PVByte(parent,scalar),value(0) {} BasePVByte::~BasePVByte() {} @@ -43,33 +44,33 @@ namespace epics { namespace pvData { void BasePVByte::put(int8 val){value = val;} void BasePVByte::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + pflusher->ensureBuffer(1); + pbuffer->putByte(value); } void BasePVByte::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pflusher) { + pflusher->ensureData(1); + value = pbuffer->getByte(); } void BasePVByte::toString(StringBuilder buf) {toString(buf,0);} - void BasePVByte::toString(StringBuilder buf,int indentLevel) + void BasePVByte::toString(StringBuilder buf,int indentLevel) { getConvert()->getString(buf,this,indentLevel); PVField::toString(buf,indentLevel); } - bool BasePVByte::operator==(PVField *pvField) + bool BasePVByte::operator==(PVField& pvField) { - return getConvert()->equals(this,pvField); + return getConvert()->equals(this, &pvField); } - bool BasePVByte::operator!=(PVField *pvField) + bool BasePVByte::operator!=(PVField& pvField) { - return !(getConvert()->equals(this,pvField)); + return !(getConvert()->equals(this, &pvField)); } }} diff --git a/pvDataApp/factory/BasePVByteArray.h b/pvDataApp/factory/BasePVByteArray.h index a86c8ee..14f168b 100644 --- a/pvDataApp/factory/BasePVByteArray.h +++ b/pvDataApp/factory/BasePVByteArray.h @@ -8,6 +8,9 @@ #include "pvData.h" #include "factory.h" #include "AbstractPVScalarArray.h" +#include "serializeHelper.h" + +using std::min; namespace epics { namespace pvData { @@ -32,8 +35,8 @@ namespace epics { namespace pvData { SerializableControl *pflusher, int offset, int count) ; virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: int8 *value; }; @@ -65,7 +68,7 @@ namespace epics { namespace pvData { PVArray::setCapacityLength(capacity,length); } - int BasePVByteArray::get(int offset, int len, ByteArrayData *data) + int BasePVByteArray::get(int offset, int len, ByteArrayData *data) { int n = len; int length = PVArray::getLength(); @@ -104,7 +107,7 @@ namespace epics { namespace pvData { } PVArray::setLength(length); PVField::postPut(); - return len; + return len; } void BasePVByteArray::shareData(ByteArray shareValue,int capacity,int length) @@ -115,21 +118,61 @@ namespace epics { namespace pvData { } void BasePVByteArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + serialize(pbuffer, pflusher, 0, getLength()); } void BasePVByteArray::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pcontrol) { + int size = SerializeHelper::readSize(pbuffer, pcontrol); + if(size>=0) { + // prepare array, if necessary + if(size>getCapacity()) setCapacity(size); + // retrieve value from the buffer + int i = 0; + while(true) { + int toRead = min(size-i, pbuffer->getRemaining()); + pbuffer->get((char *)value, i, toRead); + i += toRead; + if(iensureData(1); // TODO: is there a better way to ensureData? + else + break; + } + // set new length + setLength(size); + postPut(); + } + // TODO null arrays (size == -1) not supported } void BasePVByteArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher, int offset, int count) { + // cache + int length = getLength(); + + // check bounds + if(offset<0) + offset = 0; + else if(offset>length) offset = length; + if(count<0) count = length; + + int maxCount = length-offset; + if(count>maxCount) count = maxCount; + + // write + SerializeHelper::writeSize(count, pbuffer, pflusher); + int end = offset+count; + int i = offset; + while(true) { + int maxIndex = min(end-i, pbuffer->getRemaining())+i; + for(; iputByte(value[i]); + if(iflushSerializeBuffer(); + else + break; + } } void BasePVByteArray::toString(StringBuilder buf) @@ -144,14 +187,14 @@ namespace epics { namespace pvData { PVField::toString(buf,indentLevel); } - bool BasePVByteArray::operator==(PVField *pv) + bool BasePVByteArray::operator==(PVField& pv) { - return getConvert()->equals(this,pv); + return getConvert()->equals(this, &pv); } - bool BasePVByteArray::operator!=(PVField *pv) + bool BasePVByteArray::operator!=(PVField& pv) { - return !(getConvert()->equals(this,pv)); + return !(getConvert()->equals(this, &pv)); } }} #endif /* BASEPVBYTEARRAY_H */ diff --git a/pvDataApp/factory/BasePVDouble.h b/pvDataApp/factory/BasePVDouble.h index dd9988b..518d9c4 100644 --- a/pvDataApp/factory/BasePVDouble.h +++ b/pvDataApp/factory/BasePVDouble.h @@ -9,6 +9,7 @@ #include "convert.h" #include "factory.h" #include "AbstractPVField.h" +#include "byteBuffer.h" namespace epics { namespace pvData { @@ -26,8 +27,8 @@ namespace epics { namespace pvData { DeserializableControl *pflusher); virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: double value; }; @@ -43,33 +44,33 @@ namespace epics { namespace pvData { void BasePVDouble::put(double val){value = val;} void BasePVDouble::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + pflusher->ensureBuffer(sizeof(double)); + pbuffer->putDouble(value); } void BasePVDouble::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pflusher) { + pflusher->ensureData(sizeof(double)); + value = pbuffer->getDouble(); } void BasePVDouble::toString(StringBuilder buf) {toString(buf,0);} - void BasePVDouble::toString(StringBuilder buf,int indentLevel) + void BasePVDouble::toString(StringBuilder buf,int indentLevel) { getConvert()->getString(buf,this,indentLevel); PVField::toString(buf,indentLevel); } - bool BasePVDouble::operator==(PVField *pvField) + bool BasePVDouble::operator==(PVField& pvField) { - return getConvert()->equals(this,pvField); + return getConvert()->equals(this, &pvField); } - bool BasePVDouble::operator!=(PVField *pvField) + bool BasePVDouble::operator!=(PVField& pvField) { - return !(getConvert()->equals(this,pvField)); + return !(getConvert()->equals(this, &pvField)); } }} diff --git a/pvDataApp/factory/BasePVDoubleArray.h b/pvDataApp/factory/BasePVDoubleArray.h index 29d751b..060f604 100644 --- a/pvDataApp/factory/BasePVDoubleArray.h +++ b/pvDataApp/factory/BasePVDoubleArray.h @@ -8,6 +8,9 @@ #include "pvData.h" #include "factory.h" #include "AbstractPVScalarArray.h" +#include "serializeHelper.h" + +using std::min; namespace epics { namespace pvData { @@ -32,8 +35,8 @@ namespace epics { namespace pvData { SerializableControl *pflusher, int offset, int count) ; virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: double *value; }; @@ -41,7 +44,7 @@ namespace epics { namespace pvData { BasePVDoubleArray::BasePVDoubleArray(PVStructure *parent, ScalarArrayConstPtr scalarArray) : PVDoubleArray(parent,scalarArray),value(new double[0]) - { } + { } BasePVDoubleArray::~BasePVDoubleArray() { @@ -58,14 +61,14 @@ namespace epics { namespace pvData { } int length = PVArray::getLength(); if(length>capacity) length = capacity; - double *newValue = new double[capacity]; + double *newValue = new double[capacity]; for(int i=0; i=0) { + // prepare array, if necessary + if(size>getCapacity()) setCapacity(size); + // retrieve value from the buffer + int i = 0; + while(true) { + int maxIndex = min(size-i, (int)(pbuffer->getRemaining() + /sizeof(double)))+i; + for(; igetDouble(); + if(iensureData(sizeof(double)); + else + break; + } + // set new length + setLength(size); + postPut(); + } + // TODO null arrays (size == -1) not supported } void BasePVDoubleArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher, int offset, int count) { + // cache + int length = getLength(); + + // check bounds + if(offset<0) + offset = 0; + else if(offset>length) offset = length; + if(count<0) count = length; + + int maxCount = length-offset; + if(count>maxCount) count = maxCount; + + // write + SerializeHelper::writeSize(count, pbuffer, pflusher); + int end = offset+count; + int i = offset; + while(true) { + int maxIndex = min(end-i, (int)(pbuffer->getRemaining() + /sizeof(double)))+i; + for(; iputDouble(value[i]); + if(iflushSerializeBuffer(); + else + break; + } } void BasePVDoubleArray::toString(StringBuilder buf) @@ -145,14 +190,14 @@ namespace epics { namespace pvData { PVField::toString(buf,indentLevel); } - bool BasePVDoubleArray::operator==(PVField *pv) + bool BasePVDoubleArray::operator==(PVField& pv) { - return getConvert()->equals(this,pv); + return getConvert()->equals(this, &pv); } - bool BasePVDoubleArray::operator!=(PVField *pv) + bool BasePVDoubleArray::operator!=(PVField& pv) { - return !(getConvert()->equals(this,pv)); + return !(getConvert()->equals(this, &pv)); } }} #endif /* BASEPVDOUBLEARRAY_H */ diff --git a/pvDataApp/factory/BasePVFloat.h b/pvDataApp/factory/BasePVFloat.h index 961b04c..3a6e6ce 100644 --- a/pvDataApp/factory/BasePVFloat.h +++ b/pvDataApp/factory/BasePVFloat.h @@ -9,6 +9,7 @@ #include "convert.h" #include "factory.h" #include "AbstractPVField.h" +#include "byteBuffer.h" namespace epics { namespace pvData { @@ -26,8 +27,8 @@ namespace epics { namespace pvData { DeserializableControl *pflusher); virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: float value; }; @@ -43,33 +44,33 @@ namespace epics { namespace pvData { void BasePVFloat::put(float val){value = val;} void BasePVFloat::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + pflusher->ensureBuffer(sizeof(float)); + pbuffer->putFloat(value); } void BasePVFloat::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pflusher) { + pflusher->ensureData(sizeof(float)); + value = pbuffer->getFloat(); } void BasePVFloat::toString(StringBuilder buf) {toString(buf,0);} - void BasePVFloat::toString(StringBuilder buf,int indentLevel) + void BasePVFloat::toString(StringBuilder buf,int indentLevel) { getConvert()->getString(buf,this,indentLevel); PVField::toString(buf,indentLevel); } - bool BasePVFloat::operator==(PVField *pvField) + bool BasePVFloat::operator==(PVField& pvField) { - return getConvert()->equals(this,pvField); + return getConvert()->equals(this, &pvField); } - bool BasePVFloat::operator!=(PVField *pvField) + bool BasePVFloat::operator!=(PVField& pvField) { - return !(getConvert()->equals(this,pvField)); + return !(getConvert()->equals(this, &pvField)); } }} diff --git a/pvDataApp/factory/BasePVFloatArray.h b/pvDataApp/factory/BasePVFloatArray.h index 3c8fbc2..0da1e0a 100644 --- a/pvDataApp/factory/BasePVFloatArray.h +++ b/pvDataApp/factory/BasePVFloatArray.h @@ -8,9 +8,12 @@ #include "pvData.h" #include "factory.h" #include "AbstractPVScalarArray.h" +#include "serializeHelper.h" namespace epics { namespace pvData { + using std::min; + PVFloatArray::~PVFloatArray() {} PVFloatArray::PVFloatArray(PVStructure *parent,ScalarArrayConstPtr scalar) @@ -32,8 +35,8 @@ namespace epics { namespace pvData { SerializableControl *pflusher, int offset, int count) ; virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: float *value; }; @@ -41,7 +44,7 @@ namespace epics { namespace pvData { BasePVFloatArray::BasePVFloatArray(PVStructure *parent, ScalarArrayConstPtr scalarArray) : PVFloatArray(parent,scalarArray),value(new float[0]) - { } + { } BasePVFloatArray::~BasePVFloatArray() { @@ -58,14 +61,14 @@ namespace epics { namespace pvData { } int length = PVArray::getLength(); if(length>capacity) length = capacity; - float *newValue = new float[capacity]; + float *newValue = new float[capacity]; for(int i=0; i=0) { + // prepare array, if necessary + if(size>getCapacity()) setCapacity(size); + // retrieve value from the buffer + int i = 0; + while(true) { + int maxIndex = min(size-i, (int)(pbuffer->getRemaining() + /sizeof(float)))+i; + for(; igetFloat(); + if(iensureData(sizeof(float)); // TODO: is there a better way to ensureData? + else + break; + } + // set new length + setLength(size); + postPut(); + } + // TODO null arrays (size == -1) not supported } void BasePVFloatArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher, int offset, int count) { + // cache + int length = getLength(); + + // check bounds + if(offset<0) + offset = 0; + else if(offset>length) offset = length; + if(count<0) count = length; + + int maxCount = length-offset; + if(count>maxCount) count = maxCount; + + // write + SerializeHelper::writeSize(count, pbuffer, pflusher); + int end = offset+count; + int i = offset; + while(true) { + int maxIndex = min(end-i, (int)(pbuffer->getRemaining() + /sizeof(float)))+i; + for(; iputFloat(value[i]); + if(iflushSerializeBuffer(); + else + break; + } } void BasePVFloatArray::toString(StringBuilder buf) @@ -145,14 +190,14 @@ namespace epics { namespace pvData { PVField::toString(buf,indentLevel); } - bool BasePVFloatArray::operator==(PVField *pv) + bool BasePVFloatArray::operator==(PVField& pv) { - return getConvert()->equals(this,pv); + return getConvert()->equals(this, &pv); } - bool BasePVFloatArray::operator!=(PVField *pv) + bool BasePVFloatArray::operator!=(PVField& pv) { - return !(getConvert()->equals(this,pv)); + return !(getConvert()->equals(this, &pv)); } }} #endif /* BASEPVFLOATARRAY_H */ diff --git a/pvDataApp/factory/BasePVInt.h b/pvDataApp/factory/BasePVInt.h index be8207f..51a5d99 100644 --- a/pvDataApp/factory/BasePVInt.h +++ b/pvDataApp/factory/BasePVInt.h @@ -9,6 +9,7 @@ #include "convert.h" #include "factory.h" #include "AbstractPVField.h" +#include "byteBuffer.h" namespace epics { namespace pvData { @@ -26,14 +27,14 @@ namespace epics { namespace pvData { DeserializableControl *pflusher); virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: int32 value; }; BasePVInt::BasePVInt(PVStructure *parent,ScalarConstPtr scalar) - : PVInt(parent,scalar),value(0.0) + : PVInt(parent,scalar),value(0) {} BasePVInt::~BasePVInt() {} @@ -43,33 +44,33 @@ namespace epics { namespace pvData { void BasePVInt::put(int32 val){value = val;} void BasePVInt::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + pflusher->ensureBuffer(sizeof(int32)); + pbuffer->putInt(value); } void BasePVInt::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pflusher) { + pflusher->ensureData(sizeof(int32)); + value = pbuffer->getInt(); } void BasePVInt::toString(StringBuilder buf) {toString(buf,0);} - void BasePVInt::toString(StringBuilder buf,int indentLevel) + void BasePVInt::toString(StringBuilder buf,int indentLevel) { getConvert()->getString(buf,this,indentLevel); PVField::toString(buf,indentLevel); } - bool BasePVInt::operator==(PVField *pvField) + bool BasePVInt::operator==(PVField& pvField) { - return getConvert()->equals(this,pvField); + return getConvert()->equals(this, &pvField); } - bool BasePVInt::operator!=(PVField *pvField) + bool BasePVInt::operator!=(PVField& pvField) { - return !(getConvert()->equals(this,pvField)); + return !(getConvert()->equals(this, &pvField)); } }} diff --git a/pvDataApp/factory/BasePVIntArray.h b/pvDataApp/factory/BasePVIntArray.h index e2b83ff..3006a1e 100644 --- a/pvDataApp/factory/BasePVIntArray.h +++ b/pvDataApp/factory/BasePVIntArray.h @@ -8,6 +8,9 @@ #include "pvData.h" #include "factory.h" #include "AbstractPVScalarArray.h" +#include "serializeHelper.h" + +using std::min; namespace epics { namespace pvData { @@ -32,8 +35,8 @@ namespace epics { namespace pvData { SerializableControl *pflusher, int offset, int count) ; virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: int32 *value; }; @@ -65,7 +68,7 @@ namespace epics { namespace pvData { PVArray::setCapacityLength(capacity,length); } - int BasePVIntArray::get(int offset, int len, IntArrayData *data) + int BasePVIntArray::get(int offset, int len, IntArrayData *data) { int n = len; int length = PVArray::getLength(); @@ -104,7 +107,7 @@ namespace epics { namespace pvData { } PVArray::setLength(length); PVField::postPut(); - return len; + return len; } void BasePVIntArray::shareData( @@ -116,21 +119,63 @@ namespace epics { namespace pvData { } void BasePVIntArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + serialize(pbuffer, pflusher, 0, getLength()); } void BasePVIntArray::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pcontrol) { + int size = SerializeHelper::readSize(pbuffer, pcontrol); + if(size>=0) { + // prepare array, if necessary + if(size>getCapacity()) setCapacity(size); + // retrieve value from the buffer + int i = 0; + while(true) { + int maxIndex = min(size-i, (int)(pbuffer->getRemaining() + /sizeof(int32)))+i; + for(; igetInt(); + if(iensureData(sizeof(int32)); // TODO: is there a better way to ensureData? + else + break; + } + // set new length + setLength(size); + postPut(); + } + // TODO null arrays (size == -1) not supported } void BasePVIntArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher, int offset, int count) { + // cache + int length = getLength(); + + // check bounds + if(offset<0) + offset = 0; + else if(offset>length) offset = length; + if(count<0) count = length; + + int maxCount = length-offset; + if(count>maxCount) count = maxCount; + + // write + SerializeHelper::writeSize(count, pbuffer, pflusher); + int end = offset+count; + int i = offset; + while(true) { + int maxIndex = min(end-i, (int)(pbuffer->getRemaining() + /sizeof(int32)))+i; + for(; iputInt(value[i]); + if(iflushSerializeBuffer(); + else + break; + } } void BasePVIntArray::toString(StringBuilder buf) @@ -145,14 +190,14 @@ namespace epics { namespace pvData { PVField::toString(buf,indentLevel); } - bool BasePVIntArray::operator==(PVField *pv) + bool BasePVIntArray::operator==(PVField& pv) { - return getConvert()->equals(this,pv); + return getConvert()->equals(this, &pv); } - bool BasePVIntArray::operator!=(PVField *pv) + bool BasePVIntArray::operator!=(PVField& pv) { - return !(getConvert()->equals(this,pv)); + return !(getConvert()->equals(this, &pv)); } }} #endif /* BASEPVINTARRAY_H */ diff --git a/pvDataApp/factory/BasePVLong.h b/pvDataApp/factory/BasePVLong.h index 7270833..0544715 100644 --- a/pvDataApp/factory/BasePVLong.h +++ b/pvDataApp/factory/BasePVLong.h @@ -9,6 +9,7 @@ #include "convert.h" #include "factory.h" #include "AbstractPVField.h" +#include "byteBuffer.h" namespace epics { namespace pvData { @@ -26,14 +27,14 @@ namespace epics { namespace pvData { DeserializableControl *pflusher); virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: int64 value; }; BasePVLong::BasePVLong(PVStructure *parent,ScalarConstPtr scalar) - : PVLong(parent,scalar),value(0.0) + : PVLong(parent,scalar),value(0) {} BasePVLong::~BasePVLong() {} @@ -43,33 +44,33 @@ namespace epics { namespace pvData { void BasePVLong::put(int64 val){value = val;} void BasePVLong::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + pflusher->ensureBuffer(sizeof(int64)); + pbuffer->putLong(value); } void BasePVLong::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pflusher) { + pflusher->ensureData(sizeof(int64)); + value = pbuffer->getLong(); } void BasePVLong::toString(StringBuilder buf) {toString(buf,0);} - void BasePVLong::toString(StringBuilder buf,int indentLevel) + void BasePVLong::toString(StringBuilder buf,int indentLevel) { getConvert()->getString(buf,this,indentLevel); PVField::toString(buf,indentLevel); } - bool BasePVLong::operator==(PVField *pvField) + bool BasePVLong::operator==(PVField& pvField) { - return getConvert()->equals(this,pvField); + return getConvert()->equals(this, &pvField); } - bool BasePVLong::operator!=(PVField *pvField) + bool BasePVLong::operator!=(PVField& pvField) { - return !(getConvert()->equals(this,pvField)); + return !(getConvert()->equals(this, &pvField)); } }} diff --git a/pvDataApp/factory/BasePVLongArray.h b/pvDataApp/factory/BasePVLongArray.h index 8848985..2a3da0a 100644 --- a/pvDataApp/factory/BasePVLongArray.h +++ b/pvDataApp/factory/BasePVLongArray.h @@ -8,6 +8,9 @@ #include "pvData.h" #include "factory.h" #include "AbstractPVScalarArray.h" +#include "serializeHelper.h" + +using std::min; namespace epics { namespace pvData { @@ -32,8 +35,8 @@ namespace epics { namespace pvData { SerializableControl *pflusher, int offset, int count) ; virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: int64 *value; }; @@ -65,7 +68,7 @@ namespace epics { namespace pvData { PVArray::setCapacityLength(capacity,length); } - int BasePVLongArray::get(int offset, int len, LongArrayData *data) + int BasePVLongArray::get(int offset, int len, LongArrayData *data) { int n = len; int length = PVArray::getLength(); @@ -104,7 +107,7 @@ namespace epics { namespace pvData { } PVArray::setLength(length); PVField::postPut(); - return len; + return len; } void BasePVLongArray::shareData( @@ -116,21 +119,63 @@ namespace epics { namespace pvData { } void BasePVLongArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + serialize(pbuffer, pflusher, 0, getLength()); } void BasePVLongArray::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pcontrol) { + int size = SerializeHelper::readSize(pbuffer, pcontrol); + if(size>=0) { + // prepare array, if necessary + if(size>getCapacity()) setCapacity(size); + // retrieve value from the buffer + int i = 0; + while(true) { + int maxIndex = min(size-i, (int)(pbuffer->getRemaining() + /sizeof(int64)))+i; + for(; igetLong(); + if(iensureData(sizeof(int64)); // TODO: is there a better way to ensureData? + else + break; + } + // set new length + setLength(size); + postPut(); + } + // TODO null arrays (size == -1) not supported } void BasePVLongArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher, int offset, int count) { + // cache + int length = getLength(); + + // check bounds + if(offset<0) + offset = 0; + else if(offset>length) offset = length; + if(count<0) count = length; + + int maxCount = length-offset; + if(count>maxCount) count = maxCount; + + // write + SerializeHelper::writeSize(count, pbuffer, pflusher); + int end = offset+count; + int i = offset; + while(true) { + int maxIndex = min(end-i, (int)(pbuffer->getRemaining() + /sizeof(int64)))+i; + for(; iputLong(value[i]); + if(iflushSerializeBuffer(); + else + break; + } } void BasePVLongArray::toString(StringBuilder buf) @@ -145,14 +190,14 @@ namespace epics { namespace pvData { PVField::toString(buf,indentLevel); } - bool BasePVLongArray::operator==(PVField *pv) + bool BasePVLongArray::operator==(PVField& pv) { - return getConvert()->equals(this,pv); + return getConvert()->equals(this, &pv); } - bool BasePVLongArray::operator!=(PVField *pv) + bool BasePVLongArray::operator!=(PVField& pv) { - return !(getConvert()->equals(this,pv)); + return !(getConvert()->equals(this, &pv)); } }} #endif /* BASEPVLONGARRAY_H */ diff --git a/pvDataApp/factory/BasePVShort.h b/pvDataApp/factory/BasePVShort.h index ef701a9..72a8a11 100644 --- a/pvDataApp/factory/BasePVShort.h +++ b/pvDataApp/factory/BasePVShort.h @@ -9,6 +9,7 @@ #include "convert.h" #include "factory.h" #include "AbstractPVField.h" +#include "byteBuffer.h" namespace epics { namespace pvData { @@ -26,14 +27,14 @@ namespace epics { namespace pvData { DeserializableControl *pflusher); virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: int16 value; }; BasePVShort::BasePVShort(PVStructure *parent,ScalarConstPtr scalar) - : PVShort(parent,scalar),value(0.0) + : PVShort(parent,scalar),value(0) {} BasePVShort::~BasePVShort() {} @@ -43,33 +44,33 @@ namespace epics { namespace pvData { void BasePVShort::put(int16 val){value = val;} void BasePVShort::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + pflusher->ensureBuffer(sizeof(int16)); + pbuffer->putShort(value); } void BasePVShort::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pflusher) { + pflusher->ensureData(sizeof(int16)); + value = pbuffer->getShort(); } void BasePVShort::toString(StringBuilder buf) {toString(buf,0);} - void BasePVShort::toString(StringBuilder buf,int indentLevel) + void BasePVShort::toString(StringBuilder buf,int indentLevel) { getConvert()->getString(buf,this,indentLevel); PVField::toString(buf,indentLevel); } - bool BasePVShort::operator==(PVField *pvField) + bool BasePVShort::operator==(PVField& pvField) { - return getConvert()->equals(this,pvField); + return getConvert()->equals(this, &pvField); } - bool BasePVShort::operator!=(PVField *pvField) + bool BasePVShort::operator!=(PVField& pvField) { - return !(getConvert()->equals(this,pvField)); + return !(getConvert()->equals(this, &pvField)); } }} diff --git a/pvDataApp/factory/BasePVShortArray.h b/pvDataApp/factory/BasePVShortArray.h index c09c8d3..2913a81 100644 --- a/pvDataApp/factory/BasePVShortArray.h +++ b/pvDataApp/factory/BasePVShortArray.h @@ -8,6 +8,9 @@ #include "pvData.h" #include "factory.h" #include "AbstractPVScalarArray.h" +#include "serializeHelper.h" + +using std::min; namespace epics { namespace pvData { @@ -32,8 +35,8 @@ namespace epics { namespace pvData { SerializableControl *pflusher, int offset, int count) ; virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: int16 *value; }; @@ -65,7 +68,7 @@ namespace epics { namespace pvData { PVArray::setCapacityLength(capacity,length); } - int BasePVShortArray::get(int offset, int len, ShortArrayData *data) + int BasePVShortArray::get(int offset, int len, ShortArrayData *data) { int n = len; int length = PVArray::getLength(); @@ -104,7 +107,7 @@ namespace epics { namespace pvData { } PVArray::setLength(length); PVField::postPut(); - return len; + return len; } void BasePVShortArray::shareData( @@ -116,21 +119,63 @@ namespace epics { namespace pvData { } void BasePVShortArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + serialize(pbuffer, pflusher, 0, getLength()); } void BasePVShortArray::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pcontrol) { + int size = SerializeHelper::readSize(pbuffer, pcontrol); + if(size>=0) { + // prepare array, if necessary + if(size>getCapacity()) setCapacity(size); + // retrieve value from the buffer + int i = 0; + while(true) { + int maxIndex = min(size-i, (int)(pbuffer->getRemaining() + /sizeof(int16)))+i; + for(; igetShort(); + if(iensureData(sizeof(int16)); // TODO: is there a better way to ensureData? + else + break; + } + // set new length + setLength(size); + postPut(); + } + // TODO null arrays (size == -1) not supported } void BasePVShortArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher, int offset, int count) { + // cache + int length = getLength(); + + // check bounds + if(offset<0) + offset = 0; + else if(offset>length) offset = length; + if(count<0) count = length; + + int maxCount = length-offset; + if(count>maxCount) count = maxCount; + + // write + SerializeHelper::writeSize(count, pbuffer, pflusher); + int end = offset+count; + int i = offset; + while(true) { + int maxIndex = min(end-i, (int)(pbuffer->getRemaining() + /sizeof(int16)))+i; + for(; iputShort(value[i]); + if(iflushSerializeBuffer(); + else + break; + } } void BasePVShortArray::toString(StringBuilder buf) @@ -145,14 +190,14 @@ namespace epics { namespace pvData { PVField::toString(buf,indentLevel); } - bool BasePVShortArray::operator==(PVField *pv) + bool BasePVShortArray::operator==(PVField& pv) { - return getConvert()->equals(this,pv); + return getConvert()->equals(this, &pv); } - bool BasePVShortArray::operator!=(PVField *pv) + bool BasePVShortArray::operator!=(PVField& pv) { - return !(getConvert()->equals(this,pv)); + return !(getConvert()->equals(this, &pv)); } }} #endif /* BASEPVSHORTARRAY_H */ diff --git a/pvDataApp/factory/BasePVString.h b/pvDataApp/factory/BasePVString.h index 52b57f7..e0d6093 100644 --- a/pvDataApp/factory/BasePVString.h +++ b/pvDataApp/factory/BasePVString.h @@ -9,6 +9,8 @@ #include "convert.h" #include "factory.h" #include "AbstractPVField.h" +#include "byteBuffer.h" +#include "serializeHelper.h" namespace epics { namespace pvData { @@ -26,8 +28,8 @@ namespace epics { namespace pvData { DeserializableControl *pflusher); virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: String value; }; @@ -43,33 +45,31 @@ namespace epics { namespace pvData { void BasePVString::put(String val){value = val;} void BasePVString::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher) { + SerializeHelper::serializeString(value, pbuffer, pflusher); } void BasePVString::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + DeserializableControl *pflusher) { + value = SerializeHelper::deserializeString(pbuffer, pflusher); } void BasePVString::toString(StringBuilder buf) {toString(buf,0);} - void BasePVString::toString(StringBuilder buf,int indentLevel) + void BasePVString::toString(StringBuilder buf,int indentLevel) { getConvert()->getString(buf,this,indentLevel); PVField::toString(buf,indentLevel); } - bool BasePVString::operator==(PVField *pvField) + bool BasePVString::operator==(PVField& pvField) { - return getConvert()->equals(this,pvField); + return getConvert()->equals(this, &pvField); } - bool BasePVString::operator!=(PVField *pvField) + bool BasePVString::operator!=(PVField& pvField) { - return !(getConvert()->equals(this,pvField)); + return !(getConvert()->equals(this, &pvField)); } }} diff --git a/pvDataApp/factory/BasePVStringArray.h b/pvDataApp/factory/BasePVStringArray.h index 0c66fb9..6c15c07 100644 --- a/pvDataApp/factory/BasePVStringArray.h +++ b/pvDataApp/factory/BasePVStringArray.h @@ -8,6 +8,7 @@ #include "pvData.h" #include "factory.h" #include "AbstractPVScalarArray.h" +#include "serializeHelper.h" namespace epics { namespace pvData { @@ -32,8 +33,8 @@ namespace epics { namespace pvData { SerializableControl *pflusher, int offset, int count) ; virtual void toString(StringBuilder buf); virtual void toString(StringBuilder buf,int indentLevel); - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField& pv) ; + virtual bool operator!=(PVField& pv) ; private: String *value; }; @@ -41,7 +42,7 @@ namespace epics { namespace pvData { BasePVStringArray::BasePVStringArray(PVStructure *parent, ScalarArrayConstPtr scalarArray) : PVStringArray(parent,scalarArray),value(new String[0]) - { } + { } BasePVStringArray::~BasePVStringArray() { @@ -58,14 +59,14 @@ namespace epics { namespace pvData { } int length = PVArray::getLength(); if(length>capacity) length = capacity; - String *newValue = new String[capacity]; + String *newValue = new String[capacity]; for(int i=0; i=0) { + // prepare array, if necessary + if(size>getCapacity()) setCapacity(size); + // retrieve value from the buffer + for(int i = 0; ilength) offset = length; + if(count<0) count = length; + + int maxCount = length-offset; + if(count>maxCount) count = maxCount; + + // write + SerializeHelper::writeSize(count, pbuffer, pflusher); + int end = offset+count; + for(int i = offset; iequals(this,pv); + return getConvert()->equals(this, &pv); } - bool BasePVStringArray::operator!=(PVField *pv) + bool BasePVStringArray::operator!=(PVField& pv) { - return !(getConvert()->equals(this,pv)); + return !(getConvert()->equals(this, &pv)); } }} #endif /* BASEPVSTRINGARRAY_H */ diff --git a/pvDataApp/factory/BasePVStructure.h b/pvDataApp/factory/BasePVStructure.h index d74124d..12137c6 100644 --- a/pvDataApp/factory/BasePVStructure.h +++ b/pvDataApp/factory/BasePVStructure.h @@ -30,7 +30,7 @@ namespace epics { namespace pvData { for(int i=0; inumberFields; i++) + pImpl->pvFields[i]->serialize(pbuffer, pflusher); } void PVStructure::deserialize(ByteBuffer *pbuffer, - DeserializableControl*pflusher,BitSet *pbitSet) - { + DeserializableControl *pcontrol) { + for(int i = 0; inumberFields; i++) + pImpl->pvFields[i]->deserialize(pbuffer, pcontrol); + + } + + void PVStructure::serialize(ByteBuffer *pbuffer, + SerializableControl *pflusher, int offset, int count) { throw std::logic_error(notImplemented); } - bool PVStructure::operator==(PVField *obj) + void PVStructure::serialize(ByteBuffer *pbuffer, + SerializableControl *pflusher, BitSet *pbitSet) { + int offset = getFieldOffset(); + int numberFields = getNumberFields(); + int next = pbitSet->nextSetBit(offset); + + // no more changes or no changes in this structure + if(next<0||next>=offset+numberFields) return; + + // entire structure + if(offset==next) { + serialize(pbuffer, pflusher); + return; + } + + for(int i = 0; inumberFields; i++) { + PVField* pvField = pImpl->pvFields[i]; + offset = pvField->getFieldOffset(); + numberFields = pvField->getNumberFields(); + next = pbitSet->nextSetBit(offset); + // no more changes + if(next<0) return; + // no change in this pvField + if(next>=offset+numberFields) continue; + + // serialize field or fields + if(numberFields==1) + pvField->serialize(pbuffer, pflusher); + else + ((PVStructure*)pvField)->serialize(pbuffer, pflusher, + pbitSet); + } + } + + void PVStructure::deserialize(ByteBuffer *pbuffer, + DeserializableControl *pcontrol, BitSet *pbitSet) { + int offset = getFieldOffset(); + int numberFields = getNumberFields(); + int next = pbitSet->nextSetBit(offset); + + // no more changes or no changes in this structure + if(next<0||next>=offset+numberFields) return; + + // entire structure + if(offset==next) { + deserialize(pbuffer, pcontrol); + return; + } + + for(int i = 0; inumberFields; i++) { + PVField* pvField = pImpl->pvFields[i]; + offset = pvField->getFieldOffset(); + numberFields = pvField->getNumberFields(); + next = pbitSet->nextSetBit(offset); + // no more changes + if(next<0) return; + // no change in this pvField + if(next>=offset+numberFields) continue; + + // deserialize field or fields + if(numberFields==1) + pvField->deserialize(pbuffer, pcontrol); + else + ((PVStructure*)pvField)->deserialize(pbuffer, pcontrol, + pbitSet); + } + } + + + bool PVStructure::operator==(PVField &obj) { - PVStructure *b = dynamic_cast(obj); - if(b==0) return false; - PVFieldPtrArray bFields = b->getPVFields(); + PVStructure &b = dynamic_cast(obj); + PVFieldPtrArray bFields = b.pImpl->pvFields; PVFieldPtrArray pvFields = pImpl->pvFields; - int len = b->getNumberFields(); + int len = b.pImpl->numberFields; if(len!=pImpl->numberFields) return false; for (int i = 0; i < len; i++) { - if (!(pvFields[i]==bFields[i])) return false; + if (!(*pvFields[i]==*bFields[i])) return false; } return true; } - bool PVStructure::operator!=(PVField *pv) + bool PVStructure::operator!=(PVField &pv) { - return !(this==pv); + return !(*this==pv); } static PVField *findSubField(String fieldName,PVStructure *pvStructure) { diff --git a/pvDataApp/factory/BasePVStructureArray.h b/pvDataApp/factory/BasePVStructureArray.h index 55290ca..460a1bf 100644 --- a/pvDataApp/factory/BasePVStructureArray.h +++ b/pvDataApp/factory/BasePVStructureArray.h @@ -7,6 +7,7 @@ #include #include "pvData.h" #include "factory.h" +#include "serializeHelper.h" namespace epics { namespace pvData { @@ -30,8 +31,8 @@ namespace epics { namespace pvData { PVStructurePtrArray from, int fromOffset); virtual void toString(StringBuilder buf) ; virtual void toString(StringBuilder buf,int indentLevel) ; - virtual bool operator==(PVField *pv); - virtual bool operator!=(PVField *pv); + virtual bool operator==(PVField &pv); + virtual bool operator!=(PVField &pv); virtual void shareData( PVStructurePtrArray value,int capacity,int length); virtual void serialize(ByteBuffer *pbuffer, SerializableControl *pflusher); @@ -72,21 +73,21 @@ namespace epics { namespace pvData { int limit = length; if(length>capacity) limit = capacity; for(int i=0; icapacity) length = capacity; delete[] value; value = newValue; setCapacityLength(capacity,length); } - - StructureArrayConstPtr BasePVStructureArray::getStructureArray() + + StructureArrayConstPtr BasePVStructureArray::getStructureArray() { return structureArray; } int BasePVStructureArray::get( - int offset, int len, StructureArrayData *data) + int offset, int len, StructureArrayData *data) { int n = len; int length = getLength(); @@ -135,7 +136,7 @@ namespace epics { namespace pvData { value[i+offset] = frompv; } postPut(); - return len; + return len; } void BasePVStructureArray::shareData( @@ -148,38 +149,79 @@ namespace epics { namespace pvData { void BasePVStructureArray::toString(StringBuilder buf) {toString(buf,0);} - void BasePVStructureArray::toString(StringBuilder buf,int indentLevel) + void BasePVStructureArray::toString(StringBuilder buf,int indentLevel) { getConvert()->getString(buf,this,indentLevel); PVField::toString(buf,indentLevel); } - void BasePVStructureArray::serialize( - ByteBuffer *pbuffer,SerializableControl *pflusher) - { - throw std::logic_error(notImplemented); + void BasePVStructureArray::serialize(ByteBuffer *pbuffer, + SerializableControl *pflusher) { + serialize(pbuffer, pflusher, 0, getLength()); } - void BasePVStructureArray::deserialize( - ByteBuffer *pbuffer,DeserializableControl *pflusher) - { - throw std::logic_error(notImplemented); + void BasePVStructureArray::deserialize(ByteBuffer *pbuffer, + DeserializableControl *pcontrol) { + int size = SerializeHelper::readSize(pbuffer, pcontrol); + if(size>=0) { + // prepare array, if necessary + if(size>getCapacity()) setCapacity(size); + for(int i = 0; iensureData(1); + int8 temp = pbuffer->getByte(); + if(temp==0) { + value[i] = NULL; + } + else { + if(value[i]==NULL) { + value[i] = getPVDataCreate()->createPVStructure( + NULL, structureArray->getStructure()); + } + value[i]->deserialize(pbuffer, pcontrol); + } + } + setLength(size); + postPut(); + } } void BasePVStructureArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) - { - throw std::logic_error(notImplemented); + SerializableControl *pflusher, int offset, int count) { + // cache + int length = getLength(); + + // check bounds + if(offset<0) + offset = 0; + else if(offset>length) offset = length; + if(count<0) count = length; + + int maxCount = length-offset; + if(count>maxCount) count = maxCount; + + // write + SerializeHelper::writeSize(count, pbuffer, pflusher); + for(int i = 0; igetRemaining()<1) pflusher->flushSerializeBuffer(); + PVStructure* pvStructure = value[i+offset]; + if(pvStructure==NULL) { + pbuffer->putByte(0); + } + else { + pbuffer->putByte(1); + pvStructure->serialize(pbuffer, pflusher); + } + } } - bool BasePVStructureArray::operator==(PVField *pvField) + bool BasePVStructureArray::operator==(PVField &pvField) { - return getConvert()->equals(this,pvField); + return getConvert()->equals(this,&pvField); } - bool BasePVStructureArray::operator!=(PVField *pvField) + bool BasePVStructureArray::operator!=(PVField &pvField) { - return !(getConvert()->equals(this,pvField)); + return !(getConvert()->equals(this,&pvField)); } }} diff --git a/pvDataApp/factory/Makefile b/pvDataApp/factory/Makefile index 259c822..7899b2f 100644 --- a/pvDataApp/factory/Makefile +++ b/pvDataApp/factory/Makefile @@ -37,6 +37,7 @@ LIBSRCS += StandardPVField.cpp LIBRARY=pvFactory pvFactory_LIBS += Com +pvFactory_LIBS += pvMisc include $(TOP)/configure/RULES #---------------------------------------- diff --git a/pvDataApp/misc/Makefile b/pvDataApp/misc/Makefile index 250a5ce..d91e177 100644 --- a/pvDataApp/misc/Makefile +++ b/pvDataApp/misc/Makefile @@ -2,6 +2,7 @@ TOP=../.. include $(TOP)/configure/CONFIG +INC += pvTypes.h INC += noDefaultMethods.h INC += lock.h INC += requester.h diff --git a/pvDataApp/misc/bitSet.cpp b/pvDataApp/misc/bitSet.cpp index 2dd29bb..9e07622 100644 --- a/pvDataApp/misc/bitSet.cpp +++ b/pvDataApp/misc/bitSet.cpp @@ -8,7 +8,7 @@ namespace epics { namespace pvData { initWords(BITS_PER_WORD); } - BitSet::BitSet(epicsUInt32 nbits) : words(0), wordsLength(0), wordsInUse(0) { + BitSet::BitSet(uint32 nbits) : words(0), wordsLength(0), wordsInUse(0) { initWords(nbits); } @@ -16,11 +16,11 @@ namespace epics { namespace pvData { delete words; } - void BitSet::initWords(epicsUInt32 nbits) { - epicsUInt32 length = (nbits <= 0) ? 1 : wordIndex(nbits-1) + 1; + void BitSet::initWords(uint32 nbits) { + uint32 length = (nbits <= 0) ? 1 : wordIndex(nbits-1) + 1; if (words) delete words; - words = new epicsUInt64[length]; - bzero(words, sizeof(epicsUInt64)*length); + words = new uint64[length]; + bzero(words, sizeof(uint64)*length); wordsLength = length; } @@ -30,7 +30,7 @@ namespace epics { namespace pvData { return; // Traverse the bitset until a used word is found - epicsUInt32 i; + uint32 i; for (i = wordsInUse-1; i >= 0; i--) if (words[i] != 0) break; @@ -38,67 +38,67 @@ namespace epics { namespace pvData { wordsInUse = i+1; // The new logical size } - void BitSet::ensureCapacity(epicsUInt32 wordsRequired) { + void BitSet::ensureCapacity(uint32 wordsRequired) { if (wordsLength < wordsRequired) { // create and copy - epicsUInt64* newwords = new epicsUInt64[wordsRequired]; - bzero(newwords, sizeof(epicsUInt64)*wordsRequired); - memcpy(newwords, words, sizeof(epicsUInt64)*wordsLength); + uint64* newwords = new uint64[wordsRequired]; + bzero(newwords, sizeof(uint64)*wordsRequired); + memcpy(newwords, words, sizeof(uint64)*wordsLength); if (words) delete words; words = newwords; wordsLength = wordsRequired; } } - void BitSet::expandTo(epicsUInt32 wordIndex) { - epicsUInt32 wordsRequired = wordIndex+1; + void BitSet::expandTo(uint32 wordIndex) { + uint32 wordsRequired = wordIndex+1; if (wordsInUse < wordsRequired) { ensureCapacity(wordsRequired); wordsInUse = wordsRequired; } } - void BitSet::flip(epicsUInt32 bitIndex) { + void BitSet::flip(uint32 bitIndex) { - epicsUInt32 wordIdx = wordIndex(bitIndex); + uint32 wordIdx = wordIndex(bitIndex); expandTo(wordIdx); - words[wordIdx] ^= (((epicsUInt64)1) << (bitIndex % BITS_PER_WORD)); + words[wordIdx] ^= (((uint64)1) << (bitIndex % BITS_PER_WORD)); recalculateWordsInUse(); } - void BitSet::set(epicsUInt32 bitIndex) { + void BitSet::set(uint32 bitIndex) { - epicsUInt32 wordIdx = wordIndex(bitIndex); + uint32 wordIdx = wordIndex(bitIndex); expandTo(wordIdx); - words[wordIdx] |= (((epicsUInt64)1) << (bitIndex % BITS_PER_WORD)); + words[wordIdx] |= (((uint64)1) << (bitIndex % BITS_PER_WORD)); } - void BitSet::clear(epicsUInt32 bitIndex) { + void BitSet::clear(uint32 bitIndex) { - epicsUInt32 wordIdx = wordIndex(bitIndex); + uint32 wordIdx = wordIndex(bitIndex); if (wordIdx >= wordsInUse) return; - words[wordIdx] &= ~(((epicsUInt64)1) << (bitIndex % BITS_PER_WORD)); + words[wordIdx] &= ~(((uint64)1) << (bitIndex % BITS_PER_WORD)); recalculateWordsInUse(); } - void BitSet::set(epicsUInt32 bitIndex, bool value) { + void BitSet::set(uint32 bitIndex, bool value) { if (value) set(bitIndex); else clear(bitIndex); } - bool BitSet::get(epicsUInt32 bitIndex) const { - epicsUInt32 wordIdx = wordIndex(bitIndex); + bool BitSet::get(uint32 bitIndex) const { + uint32 wordIdx = wordIndex(bitIndex); return ((wordIdx < wordsInUse) - && ((words[wordIdx] & (((epicsUInt64)1) << (bitIndex % BITS_PER_WORD))) != 0)); + && ((words[wordIdx] & (((uint64)1) << (bitIndex % BITS_PER_WORD))) != 0)); } void BitSet::clear() { @@ -106,12 +106,12 @@ namespace epics { namespace pvData { words[--wordsInUse] = 0; } - epicsUInt32 BitSet::numberOfTrailingZeros(epicsUInt64 i) { + uint32 BitSet::numberOfTrailingZeros(uint64 i) { // HD, Figure 5-14 - epicsUInt32 x, y; + uint32 x, y; if (i == 0) return 64; - epicsUInt32 n = 63; - y = (epicsUInt32)i; if (y != 0) { n = n -32; x = y; } else x = (epicsUInt32)(i>>32); + uint32 n = 63; + y = (uint32)i; if (y != 0) { n = n -32; x = y; } else x = (uint32)(i>>32); y = x <<16; if (y != 0) { n = n -16; x = y; } y = x << 8; if (y != 0) { n = n - 8; x = y; } y = x << 4; if (y != 0) { n = n - 4; x = y; } @@ -119,7 +119,7 @@ namespace epics { namespace pvData { return n - ((x << 1) >> 31); } - epicsUInt32 BitSet::bitCount(epicsUInt64 i) { + uint32 BitSet::bitCount(uint64 i) { // HD, Figure 5-14 i = i - ((i >> 1) & 0x5555555555555555LL); i = (i & 0x3333333333333333LL) + ((i >> 2) & 0x3333333333333333LL); @@ -127,16 +127,16 @@ namespace epics { namespace pvData { i = i + (i >> 8); i = i + (i >> 16); i = i + (i >> 32); - return (epicsUInt32)(i & 0x7f); + return (uint32)(i & 0x7f); } - epicsInt32 BitSet::nextSetBit(epicsUInt32 fromIndex) const { + int32 BitSet::nextSetBit(uint32 fromIndex) const { - epicsUInt32 u = wordIndex(fromIndex); + uint32 u = wordIndex(fromIndex); if (u >= wordsInUse) return -1; - epicsUInt64 word = words[u] & (WORD_MASK << (fromIndex % BITS_PER_WORD)); + uint64 word = words[u] & (WORD_MASK << (fromIndex % BITS_PER_WORD)); while (true) { if (word != 0) @@ -147,14 +147,14 @@ namespace epics { namespace pvData { } } - epicsInt32 BitSet::nextClearBit(epicsUInt32 fromIndex) const { + int32 BitSet::nextClearBit(uint32 fromIndex) const { // Neither spec nor implementation handle bitsets of maximal length. - epicsUInt32 u = wordIndex(fromIndex); + uint32 u = wordIndex(fromIndex); if (u >= wordsInUse) return fromIndex; - epicsUInt64 word = ~words[u] & (WORD_MASK << (fromIndex % BITS_PER_WORD)); + uint64 word = ~words[u] & (WORD_MASK << (fromIndex % BITS_PER_WORD)); while (true) { if (word != 0) @@ -169,9 +169,9 @@ namespace epics { namespace pvData { return (wordsInUse == 0); } - epicsUInt32 BitSet::cardinality() const { - epicsUInt32 sum = 0; - for (epicsUInt32 i = 0; i < wordsInUse; i++) + uint32 BitSet::cardinality() const { + uint32 sum = 0; + for (uint32 i = 0; i < wordsInUse; i++) sum += bitCount(words[i]); return sum; } @@ -182,7 +182,7 @@ namespace epics { namespace pvData { words[--wordsInUse] = 0; // Perform logical AND on words in common - for (epicsUInt32 i = 0; i < wordsInUse; i++) + for (uint32 i = 0; i < wordsInUse; i++) words[i] &= set.words[i]; recalculateWordsInUse(); @@ -192,7 +192,7 @@ namespace epics { namespace pvData { BitSet& BitSet::operator|=(const BitSet& set) { - epicsUInt32 wordsInCommon; + uint32 wordsInCommon; if (wordsInUse < set.wordsInUse) { wordsInCommon = wordsInUse; //ensureCapacity(set.wordsInUse); @@ -202,7 +202,7 @@ namespace epics { namespace pvData { wordsInCommon = set.wordsInUse; // Perform logical OR on words in common - epicsUInt32 i = 0; + uint32 i = 0; for (; i < wordsInCommon; i++) words[i] |= set.words[i]; @@ -215,7 +215,7 @@ namespace epics { namespace pvData { BitSet& BitSet::operator^=(const BitSet& set) { - epicsUInt32 wordsInCommon; + uint32 wordsInCommon; if (wordsInUse < set.wordsInUse) { wordsInCommon = wordsInUse; //ensureCapacity(set.wordsInUse); @@ -225,7 +225,7 @@ namespace epics { namespace pvData { wordsInCommon = set.wordsInUse; // Perform logical XOR on words in common - epicsUInt32 i = 0; + uint32 i = 0; for (; i < wordsInCommon; i++) words[i] ^= set.words[i]; @@ -238,7 +238,7 @@ namespace epics { namespace pvData { BitSet& BitSet::operator-=(const BitSet& set) { - epicsUInt32 wordsInCommon; + uint32 wordsInCommon; if (wordsInUse < set.wordsInUse) { wordsInCommon = wordsInUse; //ensureCapacity(set.wordsInUse); @@ -248,7 +248,7 @@ namespace epics { namespace pvData { wordsInCommon = set.wordsInUse; // Perform logical (a & !b) on words in common - epicsUInt32 i = 0; + uint32 i = 0; for (; i < wordsInCommon; i++) words[i] &= ~set.words[i]; @@ -266,23 +266,23 @@ namespace epics { namespace pvData { if (wordsLength < set.wordsLength) { if (words) delete words; - words = new epicsUInt64[set.wordsLength]; + words = new uint64[set.wordsLength]; wordsLength = set.wordsLength; } - memcpy(words, set.words, sizeof(epicsUInt64)*set.wordsInUse); + memcpy(words, set.words, sizeof(uint64)*set.wordsInUse); wordsInUse = set.wordsInUse; return *this; } void BitSet::or_and(const BitSet& set1, const BitSet& set2) { - epicsUInt32 inUse = (set1.wordsInUse < set2.wordsInUse) ? set1.wordsInUse : set2.wordsInUse; + uint32 inUse = (set1.wordsInUse < set2.wordsInUse) ? set1.wordsInUse : set2.wordsInUse; ensureCapacity(inUse); wordsInUse = inUse; // Perform logical AND on words in common - for (epicsUInt32 i = 0; i < inUse; i++) + for (uint32 i = 0; i < inUse; i++) words[i] |= (set1.words[i] & set2.words[i]); // recalculateWordsInUse()... @@ -297,7 +297,7 @@ namespace epics { namespace pvData { return false; // Check words in use by both BitSets - for (epicsUInt32 i = 0; i < wordsInUse; i++) + for (uint32 i = 0; i < wordsInUse; i++) if (words[i] != set.words[i]) return false; @@ -314,12 +314,12 @@ namespace epics { namespace pvData { void BitSet::toString(StringBuilder buffer, int indentLevel) const { *buffer += '{'; - epicsInt32 i = nextSetBit(0); + int32 i = nextSetBit(0); char tmp[30]; if (i != -1) { sprintf(tmp,"%d",i); *buffer += tmp; for (i = nextSetBit(i+1); i >= 0; i = nextSetBit(i+1)) { - epicsInt32 endOfRun = nextClearBit(i); + int32 endOfRun = nextClearBit(i); do { *buffer += ", "; sprintf(tmp,"%d",i); *buffer += tmp; } while (++i < endOfRun); } } diff --git a/pvDataApp/misc/bitSet.h b/pvDataApp/misc/bitSet.h index d20d00c..4360a94 100644 --- a/pvDataApp/misc/bitSet.h +++ b/pvDataApp/misc/bitSet.h @@ -2,13 +2,13 @@ #ifndef BITSET_H #define BITSET_H #include -#include +#include //#include "byteBuffer.h" //#include "serialize.h" namespace epics { namespace pvData { // TODO !!! - typedef unsigned long long epicsUInt64; + typedef unsigned long long uint64; typedef std::string * StringBuilder; /** @@ -49,7 +49,7 @@ namespace epics { namespace pvData { * * @param nbits the initial size of the bit set */ - BitSet(epicsUInt32 nbits); + BitSet(uint32 nbits); /** * Destructor. @@ -62,21 +62,21 @@ namespace epics { namespace pvData { * * @param bitIndex the index of the bit to flip */ - void flip(epicsUInt32 bitIndex); + void flip(uint32 bitIndex); /** * Sets the bit at the specified index to {@code true}. * * @param bitIndex a bit index */ - void set(epicsUInt32 bitIndex); + void set(uint32 bitIndex); /** * Sets the bit specified by the index to {@code false}. * * @param bitIndex the index of the bit to be cleared */ - void clear(epicsUInt32 bitIndex); + void clear(uint32 bitIndex); /** * Sets the bit at the specified index to the specified value. @@ -84,7 +84,7 @@ namespace epics { namespace pvData { * @param bitIndex a bit index * @param value a boolean value to set */ - void set(epicsUInt32 bitIndex, bool value); + void set(uint32 bitIndex, bool value); /** * Returns the value of the bit with the specified index. The value @@ -95,7 +95,7 @@ namespace epics { namespace pvData { * @param bitIndex the bit index * @return the value of the bit with the specified index */ - bool get(epicsUInt32 bitIndex) const; + bool get(uint32 bitIndex) const; /** * Sets all of the bits in this BitSet to {@code false}. @@ -119,7 +119,7 @@ namespace epics { namespace pvData { * @return the index of the next set bit, or {@code -1} if there * is no such bit */ - epicsInt32 nextSetBit(epicsUInt32 fromIndex) const; + int32 nextSetBit(uint32 fromIndex) const; /** * Returns the index of the first bit that is set to {@code false} @@ -128,7 +128,7 @@ namespace epics { namespace pvData { * @param fromIndex the index to start checking from (inclusive) * @return the index of the next clear bit */ - epicsInt32 nextClearBit(epicsUInt32 fromIndex) const; + int32 nextClearBit(uint32 fromIndex) const; /** * Returns true if this {@code BitSet} contains no bits that are set @@ -143,7 +143,7 @@ namespace epics { namespace pvData { * * @return the number of bits set to {@code true} in this {@code BitSet} */ - epicsUInt32 cardinality() const; + uint32 cardinality() const; /** * Performs a logical AND of this target bit set with the @@ -223,21 +223,21 @@ namespace epics { namespace pvData { * a long, which consists of 64 bits, requiring 6 address bits. * The choice of word size is determined purely by performance concerns. */ - static const epicsUInt32 ADDRESS_BITS_PER_WORD = 6; - static const epicsUInt32 BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD; - static const epicsUInt32 BIT_INDEX_MASK = BITS_PER_WORD - 1; + static const uint32 ADDRESS_BITS_PER_WORD = 6; + static const uint32 BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD; + static const uint32 BIT_INDEX_MASK = BITS_PER_WORD - 1; /** Used to shift left or right for a partial word mask */ - static const epicsUInt64 WORD_MASK = ~((epicsUInt64)0); + static const uint64 WORD_MASK = ~((uint64)0); /** The internal field corresponding to the serialField "bits". */ - epicsUInt64* words; + uint64* words; /** The internal field corresponding to the size of words[] array. */ - epicsUInt32 wordsLength; + uint32 wordsLength; /** The number of words in the logical size of this BitSet. */ - epicsUInt32 wordsInUse; + uint32 wordsInUse; private: @@ -245,14 +245,14 @@ namespace epics { namespace pvData { /** * Given a bit index, return word index containing it. */ - static inline epicsUInt32 wordIndex(epicsUInt32 bitIndex) { + static inline uint32 wordIndex(uint32 bitIndex) { return bitIndex >> ADDRESS_BITS_PER_WORD; } /** * Creates a new word array. */ - void initWords(epicsUInt32 nbits); + void initWords(uint32 nbits); /** * Sets the field wordsInUse to the logical size in words of the bit set. @@ -265,7 +265,7 @@ namespace epics { namespace pvData { * Ensures that the BitSet can hold enough words. * @param wordsRequired the minimum acceptable number of words. */ - void ensureCapacity(epicsUInt32 wordsRequired); + void ensureCapacity(uint32 wordsRequired); /** * Ensures that the BitSet can accommodate a given wordIndex, @@ -274,7 +274,7 @@ namespace epics { namespace pvData { * possibly using recalculateWordsInUse(). * @param wordIndex the index to be accommodated. */ - void expandTo(epicsUInt32 wordIndex); + void expandTo(uint32 wordIndex); /** * Returns the number of zero bits following the lowest-order ("rightmost") @@ -288,7 +288,7 @@ namespace epics { namespace pvData { * specified long value, or 64 if the value is equal * to zero. */ - static epicsUInt32 numberOfTrailingZeros(epicsUInt64 i); + static uint32 numberOfTrailingZeros(uint64 i); /** * Returns the number of one-bits in the two's complement binary @@ -298,7 +298,7 @@ namespace epics { namespace pvData { * @return the number of one-bits in the two's complement binary * representation of the specified long value. */ - static epicsUInt32 bitCount(epicsUInt64 i); + static uint32 bitCount(uint64 i); }; diff --git a/pvDataApp/misc/byteBuffer.cpp b/pvDataApp/misc/byteBuffer.cpp index 731d0aa..c5acf31 100644 --- a/pvDataApp/misc/byteBuffer.cpp +++ b/pvDataApp/misc/byteBuffer.cpp @@ -54,34 +54,34 @@ namespace epics { throw EpicsException("buffer underflow"); } - epicsInt8 ByteBuffer::getByte() { + int8 ByteBuffer::getByte() { if(_position<_limit) - return (epicsInt8)_buffer[_position++]; + return (int8)_buffer[_position++]; else throw EpicsException("buffer underflow"); } - epicsInt16 ByteBuffer::getShort() { - if(_limit-_position<(int)sizeof(epicsInt16)) + int16 ByteBuffer::getShort() { + if(_limit-_position<(int)sizeof(int16)) throw EpicsException("buffer underflow"); - epicsInt16 val; - getWithEndianness((char*)&val, sizeof(epicsInt16)); // store short into val + int16 val; + getWithEndianness((char*)&val, sizeof(int16)); // store short into val return val; } - epicsInt32 ByteBuffer::getInt() { - if(_limit-_position<(int)sizeof(epicsInt32)) + int32 ByteBuffer::getInt() { + if(_limit-_position<(int)sizeof(int32)) throw EpicsException("buffer underflow"); - epicsInt32 val; - getWithEndianness((char*)&val, sizeof(epicsInt32)); // store int into val + int32 val; + getWithEndianness((char*)&val, sizeof(int32)); // store int into val return val; } - epicsInt64 ByteBuffer::getLong() { - if(_limit-_position<(int)sizeof(epicsInt64)) + int64 ByteBuffer::getLong() { + if(_limit-_position<(int)sizeof(int64)) throw EpicsException("buffer underflow"); - epicsInt64 val; - getWithEndianness((char*)&val, sizeof(epicsInt64)); // store long into val + int64 val; + getWithEndianness((char*)&val, sizeof(int64)); // store long into val return val; } @@ -101,17 +101,17 @@ 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"); + for(int i = 0; igetRemaining()) throw EpicsException("buffer underflow"); - strncpy(&dst[offset], &_buffer[_position], count); - _position += count; + ByteBuffer* ByteBuffer::put(const char* src, int offset, int count) { + if(count>getRemaining()) throw EpicsException("buffer overflow"); + for(int i = 0; i -#include +#include #include namespace epics { namespace pvData { - // not sure why I have to define epicsInt64 - typedef long long epicsInt64; /** @brief A buffer of bytes. * @@ -81,7 +79,7 @@ namespace epics { * @throws EpicsException - Buffer underflow if there are no bytes * remaining in the buffer. */ - epicsInt8 getByte(); + int8 getByte(); /** * Relative Int16 read, {@code position} is incremented by @@ -91,7 +89,7 @@ namespace epics { * @throws EpicsException - Buffer underflow if there are less than * 2 bytes remaining in the buffer. */ - epicsInt16 getShort(); + int16 getShort(); /** * Relative Int32 read, {@code position} is incremented by @@ -101,7 +99,7 @@ namespace epics { * @throws EpicsException - Buffer underflow if there are less than * 4 bytes remaining in the buffer. */ - epicsInt32 getInt(); + int32 getInt(); /** * Relative Int64 read, {@code position} is incremented by @@ -111,7 +109,7 @@ namespace epics { * @throws EpicsException - Buffer underflow if there are less than * 8 bytes remaining in the buffer. */ - epicsInt64 getLong(); + int64 getLong(); /** * Relative float read, {@code position} is incremented by @@ -180,7 +178,7 @@ namespace epics { * @throws EpicsException - Buffer overflow if there are no * bytes remaining in the buffer. */ - ByteBuffer* putByte(epicsInt8 value); + ByteBuffer* putByte(int8 value); /** * Relative Int16 write, {@code position} is incremented by @@ -190,7 +188,7 @@ namespace epics { * @throws EpicsException - Buffer overflow if there are less than * 2 bytes remaining in the buffer. */ - ByteBuffer* putShort(epicsInt16 value); + ByteBuffer* putShort(int16 value); /** * Relative Int32 write, {@code position} is incremented by @@ -200,7 +198,7 @@ namespace epics { * @throws EpicsException - Buffer overflow if there are less than * 4 bytes remaining in the buffer. */ - ByteBuffer* putInt(epicsInt32 value); + ByteBuffer* putInt(int32 value); /** * Relative Int64 write, {@code position} is incremented by @@ -210,7 +208,7 @@ namespace epics { * @throws EpicsException - Buffer overflow if there are less than * 8 bytes remaining in the buffer. */ - ByteBuffer* putLong(epicsInt64 value); + ByteBuffer* putLong(int64 value); /** * Relative float write, {@code position} is incremented by diff --git a/pvDataApp/misc/pvTypes.h b/pvDataApp/misc/pvTypes.h new file mode 100644 index 0000000..c1669ba --- /dev/null +++ b/pvDataApp/misc/pvTypes.h @@ -0,0 +1,18 @@ +/* pvTypes.h */ +#ifndef PVTYPES_H +#define PVTYPES_H + +namespace epics { namespace pvData { + + typedef signed char int8; + typedef short int16; + typedef int int32; + typedef long long int64; + typedef unsigned int uint32; + typedef unsigned long long uint64; + +}} +#endif /* PVTYPES_H */ + + + diff --git a/pvDataApp/misc/serializeHelper.cpp b/pvDataApp/misc/serializeHelper.cpp index d946a00..7428ec4 100644 --- a/pvDataApp/misc/serializeHelper.cpp +++ b/pvDataApp/misc/serializeHelper.cpp @@ -6,7 +6,7 @@ */ #include -#include +#include #include "epicsException.h" #include "byteBuffer.h" @@ -20,7 +20,7 @@ namespace epics { void SerializeHelper::writeSize(int s, ByteBuffer* buffer, SerializableControl* flusher) { - flusher->ensureBuffer(sizeof(epicsInt64)+1); + flusher->ensureBuffer(sizeof(int64)+1); SerializeHelper::writeSize(s, buffer); } @@ -36,12 +36,12 @@ namespace epics { int SerializeHelper::readSize(ByteBuffer* buffer, DeserializableControl* control) { control->ensureData(1); - epicsInt8 b = buffer->getByte(); + int8 b = buffer->getByte(); if(b==-1) return -1; else if(b==-2) { - control->ensureData(sizeof(epicsInt32)); - epicsInt32 s = buffer->getInt(); + control->ensureData(sizeof(int32)); + int32 s = buffer->getInt(); if(s<0) throw EpicsException("negative array size"); return s; } diff --git a/pvDataApp/pv/pvData.h b/pvDataApp/pv/pvData.h index f3fd8bc..204d2a9 100644 --- a/pvDataApp/pv/pvData.h +++ b/pvDataApp/pv/pvData.h @@ -84,8 +84,8 @@ namespace epics { namespace pvData { void setPostHandler(PostHandler *postHandler); virtual void toString(StringBuilder buf) ; virtual void toString(StringBuilder buf,int indentLevel) ; - virtual bool operator==(PVField *pv) = 0; - virtual bool operator!=(PVField *pv) = 0; + virtual bool operator==(PVField &pv) = 0; + virtual bool operator!=(PVField &pv) = 0; protected: PVField(PVStructure *parent,FieldConstPtr field); void replaceStructure(PVStructure *pvStructure); @@ -210,8 +210,8 @@ namespace epics { namespace pvData { String extendsStructureName); virtual void toString(StringBuilder buf) ; virtual void toString(StringBuilder buf,int indentLevel) ; - virtual bool operator==(PVField *pv) ; - virtual bool operator!=(PVField *pv) ; + virtual bool operator==(PVField &pv) ; + virtual bool operator!=(PVField &pv) ; virtual void serialize( ByteBuffer *pbuffer,SerializableControl *pflusher) ; virtual void deserialize( diff --git a/pvDataApp/pv/pvIntrospect.h b/pvDataApp/pv/pvIntrospect.h index 3806317..1ca4844 100644 --- a/pvDataApp/pv/pvIntrospect.h +++ b/pvDataApp/pv/pvIntrospect.h @@ -4,13 +4,9 @@ #ifndef PVINTROSPECT_H #define PVINTROSPECT_H #include "noDefaultMethods.h" +#include "pvTypes.h" namespace epics { namespace pvData { - typedef signed char int8; - typedef short int16; - typedef int int32; - typedef long long int64; - class Field; class Scalar; class ScalarArray; diff --git a/pvDataApp/pvTest/testIntTypes.cpp b/pvDataApp/pvTest/testIntTypes.cpp index 4682d59..0fea2f4 100644 --- a/pvDataApp/pvTest/testIntTypes.cpp +++ b/pvDataApp/pvTest/testIntTypes.cpp @@ -10,7 +10,7 @@ #include #include "requester.h" -#include "pvIntrospect.h" +#include "pvTypes.h" using namespace epics::pvData; @@ -26,6 +26,8 @@ int main(int argc,char *argv[]) assert(sizeof(int16)==2); assert(sizeof(int32)==4); assert(sizeof(int64)==8); + assert(sizeof(uint32)==4); + assert(sizeof(uint64)==8); int intValue; int8 byteInt; diff --git a/pvDataApp/test/Makefile b/pvDataApp/test/Makefile index 04deebf..66a83cb 100644 --- a/pvDataApp/test/Makefile +++ b/pvDataApp/test/Makefile @@ -31,6 +31,10 @@ PROD_HOST += testBaseException testBaseException_SRCS += testBaseException.cpp testBaseException_LIBS += pvMisc +PROD_HOST += testSerialization +testSerialization_SRCS += testSerialization.cpp +testSerialization_LIBS += pvMisc pvFactory Com + include $(TOP)/configure/RULES #---------------------------------------- # ADD RULES AFTER THIS LINE diff --git a/pvDataApp/test/testSerialization.cpp b/pvDataApp/test/testSerialization.cpp new file mode 100644 index 0000000..8e30303 --- /dev/null +++ b/pvDataApp/test/testSerialization.cpp @@ -0,0 +1,634 @@ +/* + * testSerialization.cpp + * + * Created on: Oct 25, 2010 + * Author: Miha Vitorovic + */ +#include + +#include + +#include "pvIntrospect.h" +#include "pvData.h" +#include "serialize.h" +#include "noDefaultMethods.h" +#include "byteBuffer.h" + +#define BYTE_MAX_VALUE 127 +#define BYTE_MIN_VALUE -128 +#define SHORT_MAX_VALUE 32767 +#define SHORT_MIN_VALUE -32768 +#define INT_MAX_VALUE 2147483647 +#define INT_MIN_VALUE -2147483648 +#define LONG_MAX_VALUE 9223372036854775807LL +#define LONG_MIN_VALUE -9223372036854775808LL +#define FLOAT_MAX_VALUE 3.4028235E38 +#define FLOAT_MIN_VALUE 1.4E-45 +#define DOUBLE_MAX_VALUE 1.7976931348623157E308 +#define DOUBLE_MIN_VALUE 4.9E-324 + +using namespace epics::pvData; +using std::cout; + +namespace epics { + namespace pvData { + + class SerializableControlImpl : public SerializableControl, + public NoDefaultMethods { + public: + virtual void flushSerializeBuffer() { + } + + virtual void ensureBuffer(int size) { + } + + SerializableControlImpl() { + } + + virtual ~SerializableControlImpl() { + } + }; + + class DeserializableControlImpl : public DeserializableControl, + public NoDefaultMethods { + public: + virtual void ensureData(int size) { + } + + DeserializableControlImpl() { + } + + virtual ~DeserializableControlImpl() { + } + }; + + } +} + +static SerializableControl* flusher; +static DeserializableControl* control; +static ByteBuffer* buffer; + +void serializationTest(PVField* field) { + buffer->clear(); + + // serialize + field->serialize(buffer, flusher); + + buffer->flip(); + + // create new instance and deserialize + PVField* deserializedField = getPVDataCreate()->createPVField(NULL, + field->getField()); + deserializedField->deserialize(buffer, control); + + // must equal + assert((*field)==(*deserializedField)); + + delete deserializedField; // clean up +} + +void testScalar() { + cout<<"Testing scalars...\n"; + PVDataCreate* factory = getPVDataCreate(); + assert(factory!=NULL); + + cout<<"\tPVBoolean\n"; + PVBoolean* pvBoolean = (PVBoolean*)factory->createPVScalar(NULL, + "pvBoolean", epics::pvData::pvBoolean); + pvBoolean->put(false); + serializationTest(pvBoolean); + pvBoolean->put(true); + serializationTest(pvBoolean); + delete pvBoolean; + + cout<<"\tPVByte\n"; + PVByte* pvByte = (PVByte*)factory->createPVScalar(NULL, "pvByte", + epics::pvData::pvByte); + pvByte->put(0); + serializationTest(pvByte); + pvByte->put(12); + serializationTest(pvByte); + pvByte->put(BYTE_MAX_VALUE); + serializationTest(pvByte); + pvByte->put(BYTE_MIN_VALUE); + serializationTest(pvByte); + delete pvByte; + + cout<<"\tPVShort\n"; + PVShort* pvShort = (PVShort*)factory->createPVScalar(NULL, "pvShort", + epics::pvData::pvShort); + pvShort->put(0); + serializationTest(pvShort); + pvShort->put(123); + serializationTest(pvShort); + pvShort->put(BYTE_MAX_VALUE); + serializationTest(pvShort); + pvShort->put(BYTE_MIN_VALUE); + serializationTest(pvShort); + pvShort->put(SHORT_MAX_VALUE); + serializationTest(pvShort); + pvShort->put(SHORT_MIN_VALUE); + serializationTest(pvShort); + delete pvShort; + + cout<<"\tPVInt\n"; + PVInt* pvInt = (PVInt*)factory->createPVScalar(NULL, "pvInt", + epics::pvData::pvInt); + pvInt->put(0); + serializationTest(pvInt); + pvInt->put(123456); + serializationTest(pvInt); + pvInt->put(BYTE_MAX_VALUE); + serializationTest(pvInt); + pvInt->put(BYTE_MIN_VALUE); + serializationTest(pvInt); + pvInt->put(SHORT_MAX_VALUE); + serializationTest(pvInt); + pvInt->put(SHORT_MIN_VALUE); + serializationTest(pvInt); + pvInt->put(INT_MAX_VALUE); + serializationTest(pvInt); + pvInt->put(INT_MIN_VALUE); + serializationTest(pvInt); + delete pvInt; + + cout<<"\tPVLong\n"; + PVLong* pvLong = (PVLong*)factory->createPVScalar(NULL, "pvLong", + epics::pvData::pvLong); + pvLong->put(0); + serializationTest(pvLong); + pvLong->put(12345678901LL); + serializationTest(pvLong); + pvLong->put(BYTE_MAX_VALUE); + serializationTest(pvLong); + pvLong->put(BYTE_MIN_VALUE); + serializationTest(pvLong); + pvLong->put(SHORT_MAX_VALUE); + serializationTest(pvLong); + pvLong->put(SHORT_MIN_VALUE); + serializationTest(pvLong); + pvLong->put(INT_MAX_VALUE); + serializationTest(pvLong); + pvLong->put(INT_MIN_VALUE); + serializationTest(pvLong); + pvLong->put(LONG_MAX_VALUE); + serializationTest(pvLong); + pvLong->put(LONG_MIN_VALUE); + serializationTest(pvLong); + delete pvLong; + + cout<<"\tPVFloat\n"; + PVFloat* pvFloat = (PVFloat*)factory->createPVScalar(NULL, "pvFloat", + epics::pvData::pvFloat); + pvFloat->put(0); + serializationTest(pvFloat); + pvFloat->put(12.345); + serializationTest(pvFloat); + pvFloat->put(FLOAT_MAX_VALUE); + serializationTest(pvFloat); + pvFloat->put(FLOAT_MIN_VALUE); + serializationTest(pvFloat); + delete pvFloat; + + cout<<"\tPVDouble\n"; + PVDouble* pvDouble = (PVDouble*)factory->createPVScalar(NULL, "pvDouble", + epics::pvData::pvDouble); + pvDouble->put(0); + serializationTest(pvDouble); + pvDouble->put(12.345); + serializationTest(pvDouble); + pvDouble->put(DOUBLE_MAX_VALUE); + serializationTest(pvDouble); + pvDouble->put(DOUBLE_MIN_VALUE); + serializationTest(pvDouble); + delete pvDouble; + + cout<<"\tPVString\n"; + PVString* pvString = (PVString*)factory->createPVScalar(NULL, "pvString", + epics::pvData::pvString); + pvString->put(""); + serializationTest(pvString); + pvString->put("s"); + serializationTest(pvString); + pvString->put("string"); + serializationTest(pvString); + pvString->put("string with spaces"); + serializationTest(pvString); + pvString->put("string with spaces and special characters\f\n"); + serializationTest(pvString); + + // huge string test + pvString->put(String(10000, 'a')); + serializationTest(pvString); + + delete pvString; + + cout<<"!!! PASSED\n\n"; +} + +void testArray() { + cout<<"Testing arrays...\n"; + + PVDataCreate* factory = getPVDataCreate(); + assert(factory!=NULL); + + cout<<"\tPVBooleanArray\n"; + bool boolEmpty[] = { }; + bool bv[] = { false, true, false, true, true }; + PVBooleanArray* pvBoolean = (PVBooleanArray*)factory->createPVScalarArray( + NULL, "pvBooleanArray", epics::pvData::pvBoolean); + pvBoolean->put(0, 0, boolEmpty, 0); + serializationTest(pvBoolean); + pvBoolean->put(0, 5, bv, 0); + serializationTest(pvBoolean); + delete pvBoolean; + + cout<<"\tPVByteArray\n"; + int8 byteEmpty[] = { }; + int8 byv[] = { 0, 1, 2, -1, BYTE_MAX_VALUE, BYTE_MAX_VALUE-1, + BYTE_MIN_VALUE+1, BYTE_MIN_VALUE }; + PVByteArray* pvByte = (PVByteArray*)factory->createPVScalarArray(NULL, + "pvByteArray", epics::pvData::pvByte); + pvByte->put(0, 0, byteEmpty, 0); + serializationTest(pvByte); + pvByte->put(0, 8, byv, 0); + serializationTest(pvByte); + delete pvByte; + + cout<<"\tPVShortArray\n"; + int16 shortEmpty[] = { }; + int16 sv[] = { 0, 1, 2, -1, SHORT_MAX_VALUE, SHORT_MAX_VALUE-1, + SHORT_MIN_VALUE+1, SHORT_MIN_VALUE }; + PVShortArray* pvShort = (PVShortArray*)factory->createPVScalarArray(NULL, + "pvShortArray", epics::pvData::pvShort); + pvShort->put(0, 0, shortEmpty, 0); + serializationTest(pvShort); + pvShort->put(0, 8, sv, 0); + serializationTest(pvShort); + delete pvShort; + + cout<<"\tPVIntArray\n"; + int32 intEmpty[] = { }; + int32 iv[] = { 0, 1, 2, -1, INT_MAX_VALUE, INT_MAX_VALUE-1, + INT_MIN_VALUE+1, INT_MIN_VALUE }; + PVIntArray* pvInt = (PVIntArray*)factory->createPVScalarArray(NULL, + "pvIntArray", epics::pvData::pvInt); + pvInt->put(0, 0, intEmpty, 0); + serializationTest(pvInt); + pvInt->put(0, 8, iv, 0); + serializationTest(pvInt); + delete pvInt; + + cout<<"\tPVLongArray\n"; + int64 longEmpty[] = { }; + int64 lv[] = { 0, 1, 2, -1, LONG_MAX_VALUE, LONG_MAX_VALUE-1, + LONG_MIN_VALUE+1, LONG_MIN_VALUE }; + PVLongArray* pvLong = (PVLongArray*)factory->createPVScalarArray(NULL, + "pvLongArray", epics::pvData::pvLong); + pvLong->put(0, 0, longEmpty, 0); + serializationTest(pvLong); + pvLong->put(0, 8, lv, 0); + serializationTest(pvLong); + delete pvLong; + + cout<<"\tPVFloatArray\n"; + float floatEmpty[] = { }; + float fv[] = { (float)0.0, (float)1.1, (float)2.3, (float)-1.4, + FLOAT_MAX_VALUE, FLOAT_MAX_VALUE-(float)123456.789, FLOAT_MIN_VALUE + +(float)1.1, FLOAT_MIN_VALUE }; + PVFloatArray* pvFloat = (PVFloatArray*)factory->createPVScalarArray(NULL, + "pvFloatArray", epics::pvData::pvFloat); + pvFloat->put(0, 0, floatEmpty, 0); + serializationTest(pvFloat); + pvFloat->put(0, 8, fv, 0); + serializationTest(pvFloat); + delete pvFloat; + + cout<<"\tPVDoubleArray\n"; + double doubleEmpty[] = { }; + double dv[] = { (double)0.0, (double)1.1, (double)2.3, (double)-1.4, + DOUBLE_MAX_VALUE, DOUBLE_MAX_VALUE-(double)123456.789, + DOUBLE_MIN_VALUE+(double)1.1, DOUBLE_MIN_VALUE }; + PVDoubleArray* pvDouble = (PVDoubleArray*)factory->createPVScalarArray( + NULL, "pvDoubleArray", epics::pvData::pvDouble); + pvDouble->put(0, 0, doubleEmpty, 0); + serializationTest(pvDouble); + pvDouble->put(0, 8, dv, 0); + serializationTest(pvDouble); + delete pvDouble; + + cout<<"\tPVStringArray\n"; + String stringEmpty[] = { }; + String + strv[] = + { + "", + "a", + "a b", + " ", + "test", + "smile", + "this is a little longer string... maybe a little but longer... this makes test better" }; + PVStringArray* pvString = (PVStringArray*)factory->createPVScalarArray( + NULL, "pvStringArray", epics::pvData::pvString); + pvString->put(0, 0, stringEmpty, 0); + serializationTest(pvString); + pvString->put(0, 7, strv, 0); + serializationTest(pvString); + delete pvString; + + cout<<"!!! PASSED\n\n"; +} + +void testScalarEquals() { + cout<<"Testing scalar equals...\n"; + PVDataCreate* factory = getPVDataCreate(); + assert(factory!=NULL); + + PVScalar *scalar1, *scalar2; + + scalar1 = factory->createPVScalar(NULL, "pvBoolean", + epics::pvData::pvBoolean); + scalar2 = factory->createPVScalar(NULL, "pvBoolean", + epics::pvData::pvBoolean); + assert((*scalar1)==(*scalar2)); + delete scalar1; + delete scalar2; + + scalar1 = factory->createPVScalar(NULL, "pvByte", epics::pvData::pvByte); + scalar2 = factory->createPVScalar(NULL, "pvByte", epics::pvData::pvByte); + assert((*scalar1)==(*scalar2)); + delete scalar1; + delete scalar2; + + scalar1 = factory->createPVScalar(NULL, "pvShort", epics::pvData::pvShort); + scalar2 = factory->createPVScalar(NULL, "pvShort", epics::pvData::pvShort); + assert((*scalar1)==(*scalar2)); + delete scalar1; + delete scalar2; + + scalar1 = factory->createPVScalar(NULL, "pvInt", epics::pvData::pvInt); + scalar2 = factory->createPVScalar(NULL, "pvInt", epics::pvData::pvInt); + assert((*scalar1)==(*scalar2)); + delete scalar1; + delete scalar2; + + scalar1 = factory->createPVScalar(NULL, "pvLong", epics::pvData::pvLong); + scalar2 = factory->createPVScalar(NULL, "pvLong", epics::pvData::pvLong); + assert((*scalar1)==(*scalar2)); + delete scalar1; + delete scalar2; + + scalar1 = factory->createPVScalar(NULL, "pvFloat", epics::pvData::pvFloat); + scalar2 = factory->createPVScalar(NULL, "pvFloat", epics::pvData::pvFloat); + assert((*scalar1)==(*scalar2)); + delete scalar1; + delete scalar2; + + scalar1 + = factory->createPVScalar(NULL, "pvDouble", epics::pvData::pvDouble); + scalar2 + = factory->createPVScalar(NULL, "pvDouble", epics::pvData::pvDouble); + assert((*scalar1)==(*scalar2)); + delete scalar1; + delete scalar2; + + scalar1 + = factory->createPVScalar(NULL, "pvString", epics::pvData::pvString); + scalar2 + = factory->createPVScalar(NULL, "pvString", epics::pvData::pvString); + assert((*scalar1)==(*scalar2)); + delete scalar1; + delete scalar2; + + FieldCreate* fieldCreate = getFieldCreate(); + FieldConstPtr fields[2]; + fields[0] = fieldCreate->createScalar("secondsSinceEpoch", + epics::pvData::pvLong); + fields[1] = fieldCreate->createScalar("nanoSeconds", epics::pvData::pvInt); + StructureConstPtr structure = fieldCreate->createStructure("timeStamp", 2, + fields); + + PVStructure* pvStruct1 = factory->createPVStructure(NULL, structure); + PVStructure* pvStruct2 = factory->createPVStructure(NULL, structure); + assert((*pvStruct1)==(*pvStruct2)); + delete pvStruct2; + delete pvStruct1; + // 'structure' and 'fields' are deleted implicitly + + cout<<"!!! PASSED\n\n"; +} + +void testScalarNonInitialized() { + cout<<"Testing scalar non-initialized...\n"; + PVDataCreate* factory = getPVDataCreate(); + assert(factory!=NULL); + + PVScalar* scalar; + + scalar = factory->createPVScalar(NULL, "pvBoolean", + epics::pvData::pvBoolean); + serializationTest(scalar); + delete scalar; + + scalar = factory->createPVScalar(NULL, "pvByte", epics::pvData::pvByte); + serializationTest(scalar); + delete scalar; + + scalar = factory->createPVScalar(NULL, "pvShort", epics::pvData::pvShort); + serializationTest(scalar); + delete scalar; + + scalar = factory->createPVScalar(NULL, "pvInt", epics::pvData::pvInt); + serializationTest(scalar); + delete scalar; + + scalar = factory->createPVScalar(NULL, "pvLong", epics::pvData::pvLong); + serializationTest(scalar); + delete scalar; + + scalar = factory->createPVScalar(NULL, "pvFloat", epics::pvData::pvFloat); + serializationTest(scalar); + delete scalar; + + scalar = factory->createPVScalar(NULL, "pvDouble", epics::pvData::pvDouble); + serializationTest(scalar); + delete scalar; + + scalar = factory->createPVScalar(NULL, "pvString", epics::pvData::pvString); + serializationTest(scalar); + delete scalar; + + FieldCreate* fieldCreate = getFieldCreate(); + FieldConstPtr fields[2]; + fields[0] = fieldCreate->createScalar("secondsSinceEpoch", + epics::pvData::pvLong); + fields[1] = fieldCreate->createScalar("nanoSeconds", epics::pvData::pvInt); + StructureConstPtr structure = fieldCreate->createStructure("timeStamp", 2, + fields); + + PVStructure* pvStruct = factory->createPVStructure(NULL, structure); + serializationTest(pvStruct); + delete pvStruct; // 'structure' and 'fields' are deleted implicitly + + cout<<"!!! PASSED\n\n"; +} + +void testArrayNonInitialized() { + cout<<"Testing array non-initialized...\n"; + PVDataCreate* factory = getPVDataCreate(); + assert(factory!=NULL); + + PVArray* array; + + array = factory->createPVScalarArray(NULL, "pvBooleanArray", + epics::pvData::pvBoolean); + serializationTest(array); + delete array; + + array = factory->createPVScalarArray(NULL, "pvByteArray", + epics::pvData::pvByte); + serializationTest(array); + delete array; + + array = factory->createPVScalarArray(NULL, "pvShortArray", + epics::pvData::pvShort); + serializationTest(array); + delete array; + + array = factory->createPVScalarArray(NULL, "pvIntArray", + epics::pvData::pvInt); + serializationTest(array); + delete array; + + array = factory->createPVScalarArray(NULL, "pvLongArray", + epics::pvData::pvLong); + serializationTest(array); + delete array; + + array = factory->createPVScalarArray(NULL, "pvFloatArray", + epics::pvData::pvFloat); + serializationTest(array); + delete array; + + array = factory->createPVScalarArray(NULL, "pvDoubleArray", + epics::pvData::pvDouble); + serializationTest(array); + delete array; + + array = factory->createPVScalarArray(NULL, "pvStringArray", + epics::pvData::pvString); + serializationTest(array); + delete array; + + FieldCreate* fieldCreate = getFieldCreate(); + FieldConstPtr fields[2]; + fields[0] = fieldCreate->createScalar("secondsSinceEpoch", + epics::pvData::pvLong); + fields[1] = fieldCreate->createScalar("nanoSeconds", epics::pvData::pvInt); + StructureConstPtr structure = fieldCreate->createStructure("timeStamp", 2, + fields); + + StructureArrayConstPtr structureArray = fieldCreate->createStructureArray( + "timeStampArray", structure); + PVStructureArray* pvStructArray = factory->createPVStructureArray(NULL, + structureArray); + serializationTest(pvStructArray); + delete pvStructArray; // also deletes 'structureArray', + //'structureArray' also deletes 'structure' + //'structure' also deletes 'fields' + + cout<<"!!! PASSED\n\n"; +} + +void testStructure() { + cout<<"Testing structure...\n"; + + FieldCreate* fieldCreate = getFieldCreate(); + PVDataCreate* pvDataCreate = getPVDataCreate(); + assert(fieldCreate!=NULL); + assert(pvDataCreate!=NULL); + + cout<<"\tSimple structure serialization\n"; + FieldConstPtr fields[2]; + fields[0] = fieldCreate->createScalar("secondsSinceEpoch", + epics::pvData::pvLong); + fields[1] = fieldCreate->createScalar("nanoSeconds", epics::pvData::pvInt); + PVStructure* pvStructure = pvDataCreate->createPVStructure(NULL, + "timestamp", 2, fields); + pvStructure->getLongField(fields[0]->getFieldName())->put(123); + pvStructure->getIntField(fields[1]->getFieldName())->put(456); + + serializationTest(pvStructure); + //serializationTest(pvStructure->getStructure()); + + cout<<"\tComplex structure serialization\n"; + // and more complex :) + FieldConstPtr fields2[4]; + fields2[0] = fieldCreate->createScalar("longVal", epics::pvData::pvLong); + fields2[1] = fieldCreate->createScalar("intVal", epics::pvData::pvInt); + fields2[2] = fieldCreate->createScalarArray("values", epics::pvData::pvDouble); + fields2[3] = fieldCreate->createStructure("timeStamp", 2, fields); + PVStructure* pvStructure2 = pvDataCreate->createPVStructure(NULL, + "complexStructure", 4, fields2); + pvStructure2->getLongField(fields2[0]->getFieldName())->put(1234); + pvStructure2->getIntField(fields2[1]->getFieldName())->put(4567); + PVDoubleArray* da = (PVDoubleArray*)pvStructure2->getScalarArrayField( + fields2[2]->getFieldName(), epics::pvData::pvDouble); + double dd[] = { 1.2, 3.4, 4.5 }; + da->put(0, 3, dd, 0); + + PVStructure* ps = pvStructure2->getStructureField( + fields2[3]->getFieldName()); + ps->getLongField(fields[0]->getFieldName())->put(789); + ps->getIntField(fields[1]->getFieldName())->put(1011); + + serializationTest(pvStructure2); + //serializationTest(pvStructure2->getStructure()); + delete pvStructure2; + delete pvStructure; + + cout<<"!!! PASSED\n\n"; +} + +/* + void testIntrospectionSerialization() { + cout<<"Testing introspection serialization...\n"; + FieldCreate* factory = getFieldCreate(); + assert(factory!=NULL); + + ScalarConstPtr scalar = factory->createScalar("scalar", epics::pvData::pvDouble); + serializatioTest(scalar); + delete scalar; + + ScalarArrayConstPtr array = factory->createScalarArray("array", epics::pvData::pvDouble); + serializatioTest(array); + delete array; + + cout<<"!!! PASSED\n\n"; + } + */ + +int main(int argc, char *argv[]) { + flusher = new SerializableControlImpl(); + control = new DeserializableControlImpl(); + buffer = new ByteBuffer(1<<16); + + testScalarEquals(); + testScalar(); + testArray(); + testScalarNonInitialized(); + testArrayNonInitialized(); + testStructure(); + //testIntrospectionSerialization(); + + delete buffer; + delete control; + delete flusher; + + cout<<"\nDone!\n"; + + return (0); +} +