From 85a1a48b00df7f7a0bc419338e38f3bf585e70e2 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 23 Nov 2015 15:19:06 -0500 Subject: [PATCH] add serializeToVector --- src/misc/serialize.h | 13 +++++ src/misc/serializeHelper.cpp | 75 ++++++++++++++++++++++++++++- testApp/misc/testSerialization.cpp | 77 +++++++++++++++++++++++++++++- 3 files changed, 163 insertions(+), 2 deletions(-) diff --git a/src/misc/serialize.h b/src/misc/serialize.h index 0e30ba6..7797be6 100644 --- a/src/misc/serialize.h +++ b/src/misc/serialize.h @@ -10,6 +10,8 @@ #ifndef SERIALIZE_H #define SERIALIZE_H +#include + #include #include @@ -150,6 +152,17 @@ namespace epics { namespace pvData { DeserializableControl *flusher) = 0; }; + /** + * @brief Push serialize and append to the provided byte vector. + * No caching is done. Only complete serialization. + * + * @param S A Serializable object + * @param byteOrder Byte order to write (EPICS_ENDIAN_LITTLE or EPICS_ENDIAN_BIG) + * @param out The output vector. Results are appended + */ + void serializeToVector(const Serializable *S, + int byteOrder, + std::vector& out); /** * @brief Class for serializing bitSets. diff --git a/src/misc/serializeHelper.cpp b/src/misc/serializeHelper.cpp index 97de1b6..e51d592 100644 --- a/src/misc/serializeHelper.cpp +++ b/src/misc/serializeHelper.cpp @@ -14,6 +14,7 @@ #define epicsExportSharedSymbols #include +#include #include #include #include @@ -139,6 +140,78 @@ namespace epics { else return emptyStringtring; } - + } +} + +namespace { +using namespace epics::pvData; + +struct ToString : public epics::pvData::SerializableControl +{ + typedef std::vector buf_type; + buf_type buf; + buf_type& out; + ByteBuffer bufwrap; + + ToString(buf_type& out, int byteOrder = EPICS_BYTE_ORDER) + :buf(16*1024) + ,out(out) + ,bufwrap((char*)&buf[0], buf.size(), byteOrder) + {} + + virtual void flushSerializeBuffer() + { + size_t N = out.size(); + out.resize(out.size()+bufwrap.getPosition()); + std::copy(buf.begin(), + buf.begin()+bufwrap.getPosition(), + out.begin()+N); + bufwrap.clear(); + } + + virtual void ensureBuffer(std::size_t size) + { + flushSerializeBuffer(); + assert(bufwrap.getRemaining()>0); + } + + virtual void alignBuffer(std::size_t alignment) + { + if(bufwrap.getRemaining()=alignment); + bufwrap.align(alignment); + } + + virtual bool directSerialize( + ByteBuffer *existingBuffer, + const char* toSerialize, + std::size_t elementCount, + std::size_t elementSize) + { + return false; + } + + virtual void cachedSerialize( + std::tr1::shared_ptr const & field, + ByteBuffer* buffer) + { + field->serialize(buffer, this); + } +}; + +} // namespace + +namespace epics { + namespace pvData { + void serializeToVector(const Serializable *S, + int byteOrder, + std::vector& out) + { + ToString TS(out, byteOrder); + S->serialize(&TS.bufwrap, &TS); + TS.flushSerializeBuffer(); + assert(TS.bufwrap.getPosition()==0); + } } } diff --git a/testApp/misc/testSerialization.cpp b/testApp/misc/testSerialization.cpp index f00ded3..7edc6f2 100644 --- a/testApp/misc/testSerialization.cpp +++ b/testApp/misc/testSerialization.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include // for NELEMENTS @@ -761,11 +762,83 @@ void testStringCopy() { testDiag("implementation of string assignment operator does not share content"); } +static +void printbytes(size_t N, const epicsUInt8 *buf) +{ + bool needeol = false; + for(size_t i=0; icreateFieldBuilder() + ->add("X", pvInt)->add("Y", pvString) + ->createStructure(); + + PVStructurePtr _data = getPVDataCreate()->createPVStructure(_type); + + _data->getSubFieldT("X")->put(42); + _data->getSubFieldT("Y")->put("testing"); + + std::vector bytes; + serializeToVector(_data.get(), byteOrder, bytes); + + const char *expected; + size_t count; + if(byteOrder==EPICS_ENDIAN_LITTLE) { + expected = expected_le; + count = NELEMENTS(expected_le)-1; + } else if(byteOrder==EPICS_ENDIAN_BIG) { + expected = expected_be; + count = NELEMENTS(expected_be)-1; + } else { + throw std::logic_error("Unsupported mixed endian"); + } + + testOk(bytes.size()==count, + "%u == %u", (unsigned)bytes.size(), + (unsigned)count); + + size_t N = std::min(bytes.size(), count); + + testOk(memcmp(&bytes[0], expected, N)==0, "Match [0,%u)", (unsigned)N); + + testDiag("Expected (%u)", (unsigned)bytes.size()); + printbytes(count, (epicsUInt8*)expected); + + testDiag("Actual (%u)", (unsigned)count); + printbytes(bytes.size(), &bytes[0]); +} + } // end namespace MAIN(testSerialization) { - testPlan(226); + testPlan(230); flusher = new SerializableControlImpl(); control = new DeserializableControlImpl(); @@ -787,6 +860,8 @@ MAIN(testSerialization) { testArraySizeType(); testBoundedString(); + testToString(EPICS_ENDIAN_BIG); + testToString(EPICS_ENDIAN_LITTLE); delete buffer; delete control;