From 1bc4fe5f28c33d0f86cac1599abfc4aa354fc03e Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 25 Mar 2017 19:01:32 +0100 Subject: [PATCH] polished serialisation prototype --- .../src/serialization/rsserializable.h | 35 ++ .../src/serialization/rsserializer.h | 97 ++++++ .../src/serialization/rstypeserializer.h | 195 +++++++++++ .../src/serialization/serial_test.cc | 54 ++- libretroshare/src/serialization/serializer.h | 328 ------------------ 5 files changed, 371 insertions(+), 338 deletions(-) create mode 100644 libretroshare/src/serialization/rsserializable.h create mode 100644 libretroshare/src/serialization/rsserializer.h create mode 100644 libretroshare/src/serialization/rstypeserializer.h delete mode 100644 libretroshare/src/serialization/serializer.h diff --git a/libretroshare/src/serialization/rsserializable.h b/libretroshare/src/serialization/rsserializable.h new file mode 100644 index 000000000..3351e0147 --- /dev/null +++ b/libretroshare/src/serialization/rsserializable.h @@ -0,0 +1,35 @@ +#pragma once + +#include "serialiser/rsserial.h" + +class RsItem ; +class SerializeContext; + +#define SERIALIZE_ERROR() std::cerr << __PRETTY_FUNCTION__ << " : " + +class RsSerializable: public RsItem +{ +public: + typedef enum { SIZE_ESTIMATE = 0x01, SERIALIZE = 0x02, DESERIALIZE = 0x03} SerializeJob ; + + RsSerializable(uint8_t version,uint16_t service,uint8_t id) + : RsItem(version,service,id) + { + } + + /** + * @brief serialize this object to the given buffer + * @param Job to do: serialise or deserialize. + * @param data Chunk of memory were to dump the serialized data + * @param size Size of memory chunk + * @param offset Readed to determine at witch offset start writing data, + * written to inform caller were written data ends, the updated value + * is usually passed by the caller to serialize of another + * RsSerializable so it can write on the same chunk of memory just + * after where this RsSerializable has been serialized. + * @return true if serialization successed, false otherwise + */ + + virtual void serial_process(SerializeJob j,SerializeContext& ctx) = 0; +}; + diff --git a/libretroshare/src/serialization/rsserializer.h b/libretroshare/src/serialization/rsserializer.h new file mode 100644 index 000000000..706ee3be4 --- /dev/null +++ b/libretroshare/src/serialization/rsserializer.h @@ -0,0 +1,97 @@ +#pragma once + +#include +#include +#include +#include + +#include "rsserializable.h" + +class SerializeContext +{ + public: + + SerializeContext(uint8_t *data,uint32_t size) + : mData(data),mSize(size),mOffset(0),mOk(true) {} + + unsigned char *mData ; + uint32_t mSize ; + uint32_t mOffset ; + bool mOk ; +}; + +class RsSerializer +{ + public: + /*! create_item + * should be overloaded to create the correct type of item depending on the data + */ + virtual RsSerializable *create_item(uint16_t service, uint8_t item_sub_id) + { + return NULL ; + } + + RsSerializable *deserialize_item(const uint8_t *data,uint32_t size) + { + uint32_t rstype = getRsItemId(const_cast((const void*)data)) ; + + RsSerializable *item = create_item(getRsItemService(rstype),getRsItemSubType(rstype)) ; + + if(!item) + { + std::cerr << "(EE) cannot deserialise: unknown item type " << std::hex << rstype << std::dec << std::endl; + return NULL ; + } + + SerializeContext ctx(const_cast(data),size); + ctx.mOffset = 8 ; + + item->serial_process(RsSerializable::DESERIALIZE, ctx) ; + + if(ctx.mOk) + return item ; + + delete item ; + return NULL ; + } + + bool serialize_item(const RsSerializable *item,uint8_t *const data,uint32_t size) + { + SerializeContext ctx(data,0); + + uint32_t tlvsize = size_item(item) ; + + if(tlvsize > size) + throw std::runtime_error("Cannot serialise: not enough room.") ; + + if(!setRsItemHeader(data, tlvsize, const_cast(item)->PacketId(), tlvsize)) + { + std::cerr << "RsSerializer::serialise_item(): ERROR. Not enough size!" << std::endl; + return false ; + } + ctx.mOffset = 8; + ctx.mSize = tlvsize; + + const_cast(item)->serial_process(RsSerializable::SERIALIZE,ctx) ; + + if(ctx.mSize != ctx.mOffset) + { + std::cerr << "RsSerializer::serialise_item(): ERROR. offset does not match expected size!" << std::endl; + return false ; + } + return true ; + } + + uint32_t size_item(const RsSerializable *item) + { + SerializeContext ctx(NULL,0); + + ctx.mSize = 8 ; // header size + const_cast(item)->serial_process(RsSerializable::SIZE_ESTIMATE, ctx) ; + + return ctx.mSize ; + } +}; + + + diff --git a/libretroshare/src/serialization/rstypeserializer.h b/libretroshare/src/serialization/rstypeserializer.h new file mode 100644 index 000000000..a713832b3 --- /dev/null +++ b/libretroshare/src/serialization/rstypeserializer.h @@ -0,0 +1,195 @@ +#include "serialiser/rstlvbase.h" + +template T ntoh(T t) +{ + if(sizeof(T) == 8) return t; + if(sizeof(T) == 4) return ntohl(t) ; + if(sizeof(T) == 2) return ntohs(t) ; + + std::cerr << "(EE) unhandled type of size " << sizeof(T) << " in ntoh<>" << std::endl; + return t; +} +template T hton(T t) +{ + if(sizeof(T) == 8) return t; + if(sizeof(T) == 4) return htonl(t) ; + if(sizeof(T) == 2) return htons(t) ; + + std::cerr << "(EE) unhandled type of size " << sizeof(T) << " in hton<>" << std::endl; + return t; +} + +class RsTypeSerializer +{ + public: + template + static void serial_process(RsSerializable::SerializeJob j,SerializeContext& ctx,T& member) + { + switch(j) + { + case RsSerializable::SIZE_ESTIMATE: ctx.mSize += serial_size(member) ; + break ; + + case RsSerializable::DESERIALIZE: ctx.mOk = ctx.mOk && deserialize(ctx.mData,ctx.mSize,ctx.mOffset,member) ; + break ; + + case RsSerializable::SERIALIZE: ctx.mOk = ctx.mOk && serialize(ctx.mData,ctx.mSize,ctx.mOffset,member) ; + break ; + + default: + ctx.mOk = false ; + throw std::runtime_error("Unknown serial job") ; + } + } + + protected: + template static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, const T& member); + template static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, T& member); + template static uint32_t serial_size(const T& /* member */); +}; + +/// Templates to generate RsSerializer for standard integral types +// +template class t_SerializerNType +{ +public: + static bool serialize(uint8_t data[], uint32_t size, uint32_t &offset, const N& member) + { + if (size <= offset || size < SIZE + offset) + { + SERIALIZE_ERROR() << ": not enough room. SIZE+offset=" << SIZE+offset << " and size is only " << size << std::endl; + return false; + } + + N tmp = hton(member); + memcpy(data+offset, &tmp, SIZE); + offset += SIZE; + return true; + } + static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, N& member) + { + if (size <= offset || size < offset + SIZE) + { + SERIALIZE_ERROR() << ": not enough room. SIZE+offset=" << SIZE+offset << " and size is only " << size << std::endl; + return false; + } + + N tmp ; + memcpy(&tmp, data+offset, SIZE); + member = ntoh(tmp); + offset += SIZE; + return true; + } + + static uint32_t serial_size(const N& /* member */) + { + return SIZE; + } +}; + +template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint8_t& member) +{ + return t_SerializerNType::serialize(data,size,offset,member); +} +template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint32_t& member) +{ + return t_SerializerNType::serialize(data,size,offset,member); +} +template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint64_t& member) +{ + return t_SerializerNType::serialize(data,size,offset,member); +} +template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint8_t& member) +{ + return t_SerializerNType::deserialize(data,size,offset,member); +} +template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint32_t& member) +{ + return t_SerializerNType::deserialize(data,size,offset,member); +} +template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint64_t& member) +{ + return t_SerializerNType::deserialize(data,size,offset,member); +} +template<> uint32_t RsTypeSerializer::serial_size(const uint8_t& member) +{ + return t_SerializerNType::serial_size(member); +} +template<> uint32_t RsTypeSerializer::serial_size(const uint32_t& member) +{ + return t_SerializerNType::serial_size(member); +} +template<> uint32_t RsTypeSerializer::serial_size(const uint64_t& member) +{ + return t_SerializerNType::serial_size(member); +} +//// Float +// +template<> uint32_t RsTypeSerializer::serial_size(const float&){ return 4; } + +template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t& offset, const float& f) +{ + uint32_t sz = serial_size(f); + + if ( !data || size <= offset || size < sz + offset ) + { + SERIALIZE_ERROR() << ": not enough room. SIZE+offset=" << sz+offset << " and size is only " << size << std::endl; + return false; + } + + const float tmp = f; + if(tmp < 0.0f) + { + SERIALIZE_ERROR() << "Cannot serialise invalid negative float value " << tmp << std::endl; + return false; + } + + /* This serialisation is quite accurate. The max relative error is approx. + * 0.01% and most of the time less than 1e-05% The error is well distributed + * over numbers also. */ + + uint32_t n; + if(tmp < 1e-7) n = (~(uint32_t)0); + else n = ((uint32_t)( (1.0f/(1.0f+tmp) * (~(uint32_t)0)))); + n = hton(n); + memcpy(data+offset, &n, sz); + offset += sz; + return true; +} + + +template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, float& f) +{ + uint32_t sz = serial_size(f); + + if ( !data || size <= offset || size < offset + sz ) + { + SERIALIZE_ERROR() << "Cannot deserialise float value. Not enough room. size=" << size << ", offset=" << offset << std::endl; + return false; + } + + uint32_t n; + memcpy(&n, data+offset, sz); + n = ntoh(n); + f = 1.0f/ ( n/(float)(~(uint32_t)0)) - 1.0f; + return true; +} + +typedef std::pair TlvString; + +/// Serializer for std::string +template<> uint32_t RsTypeSerializer::serial_size(const TlvString& s) +{ + return GetTlvStringSize(s.first) ; +} + +template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,const TlvString& s) +{ + return SetTlvString(data,size,&offset,s.second,s.first) ; +} + +template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,TlvString& s) +{ + return GetTlvString((void*)data,size,&offset,s.second,s.first) ; +} + diff --git a/libretroshare/src/serialization/serial_test.cc b/libretroshare/src/serialization/serial_test.cc index 08c53b6db..9b5745b4b 100644 --- a/libretroshare/src/serialization/serial_test.cc +++ b/libretroshare/src/serialization/serial_test.cc @@ -4,16 +4,18 @@ #include -#include "serializer.h" #include "util/rsmemory.h" #include "util/rsprint.h" #include "serialiser/rsserial.h" +#include "serializer.h" +#include "rstypeserializer.h" + static const uint16_t RS_SERVICE_TYPE_TEST = 0xffff; static const uint8_t RS_ITEM_SUBTYPE_TEST1 = 0x01 ; // Template serialization of RsTypeSerialiser::serial_process() for unknown/new types -// +// Here we do it for std::set as an example. // template<> uint32_t RsTypeSerializer::serial_size(const std::set& s) { @@ -25,13 +27,16 @@ template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint3 bool ok = true ; uint32_t offset_save = offset ; - if(tlvsize + offset >= size) + if(tlvsize + offset > size) + { + std::cerr << "RsTypeSerializer::serialize: error. tlvsize+offset > size, where tlvsize=" << tlvsize << ", offset=" << offset << ", size=" << size << std::endl; return false ; + } - ok = ok && RsTypeSerializer::serialize(data,size,offset,member.size()) ; + ok = ok && RsTypeSerializer::serialize(data,size,offset,member.size()) ; for(std::set::const_iterator it(member.begin());it!=member.end();++it) - ok = ok && RsTypeSerializer::serialize(data,size,offset,*it) ; + ok = ok && RsTypeSerializer::serialize(data,size,offset,*it) ; if(!ok) { @@ -50,7 +55,7 @@ template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t siz ok = ok && RsTypeSerializer::deserialize(data,size,offset,n); - for(uint32_t i=0;i bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t siz class RsTestItem: public RsSerializable { public: - RsTestItem() : RsSerializable(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_TEST,RS_ITEM_SUBTYPE_TEST1) {} + RsTestItem() : RsSerializable(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_TEST,RS_ITEM_SUBTYPE_TEST1) + { + str = "test string"; + ts = time(NULL) ; + + int_set.insert(lrand48()) ; + int_set.insert(lrand48()) ; + int_set.insert(lrand48()) ; + } // Derived from RsSerializable // virtual void serial_process(RsSerializable::SerializeJob j, SerializeContext& ctx) { + TlvString tt(str,TLV_TYPE_STR_DESCR) ; + RsTypeSerializer::serial_process(j,ctx,ts ) ; - RsTypeSerializer::serial_process(j,ctx,str) ; + RsTypeSerializer::serial_process(j,ctx,tt ) ; RsTypeSerializer::serial_process(j,ctx,int_set ) ; } @@ -89,11 +104,12 @@ class RsTestItem: public RsSerializable virtual void clear() {} virtual std::ostream& print(std::ostream&,uint16_t indent) {} - private: std::string str ; uint64_t ts ; std::set int_set ; + + friend int main(int argc,char *argv[]); }; // New user-defined serializer class. @@ -116,6 +132,12 @@ class RsTestSerializer: public RsSerializer } }; +// Methods to check the equality of items. +// +void check(const std::string& s1,const std::string& s2) { assert(s1 == s2) ; } +void check(const uint64_t& s1,const uint64_t& s2) { assert(s1 == s2) ; } +void check(const std::set& s1,const std::set& s2) { assert(s1 == s2) ; } + int main(int argc,char *argv[]) { try @@ -126,13 +148,25 @@ int main(int argc,char *argv[]) std::cerr << "t1.serial_size() = " << size << std::endl; + // Allocate some memory to serialise to + // RsTemporaryMemory mem1(size); RsTestSerializer().serialize_item(&t1,mem1,mem1.size()) ; + std::cerr << "Serialized t1: " << RsUtil::BinToHex(mem1,mem1.size()) << std::endl; + + // Now deserialise into a new item + // RsSerializable *t2 = RsTestSerializer().deserialize_item(mem1,mem1.size()) ; - std::cerr << "Serialized t1: " << RsUtil::BinToHex(mem1,mem1.size()) << std::endl; + // make sure t1 is equal to t2 + // + check(t1.str,dynamic_cast(t2)->str) ; + check(t1.ts,dynamic_cast(t2)->ts) ; + check(t1.int_set,dynamic_cast(t2)->int_set) ; + + delete t2; return 0; } diff --git a/libretroshare/src/serialization/serializer.h b/libretroshare/src/serialization/serializer.h deleted file mode 100644 index 462206c42..000000000 --- a/libretroshare/src/serialization/serializer.h +++ /dev/null @@ -1,328 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include "arpa/inet.h" -#include "serialiser/rsserial.h" - -class RsItem ; - -class SerializeContext; - -class RsSerializable: public RsItem -{ -public: - typedef enum { SIZE_ESTIMATE = 0x01, SERIALIZE = 0x02, DESERIALIZE = 0x03} SerializeJob ; - - RsSerializable(uint8_t version,uint16_t service,uint8_t id) - : RsItem(version,service,id) - { - } - - /** - * @brief serialize this object to the given buffer - * @param Job to do: serialise or deserialize. - * @param data Chunk of memory were to dump the serialized data - * @param size Size of memory chunk - * @param offset Readed to determine at witch offset start writing data, - * written to inform caller were written data ends, the updated value - * is usually passed by the caller to serialize of another - * RsSerializable so it can write on the same chunk of memory just - * after where this RsSerializable has been serialized. - * @return true if serialization successed, false otherwise - */ - - virtual void serial_process(SerializeJob j,SerializeContext& ctx) = 0; -}; - -class SerializeContext -{ - public: - - SerializeContext(uint8_t *data,uint32_t size) - : mData(data),mSize(size),mOffset(0),mOk(true) {} - - unsigned char *mData ; - uint32_t mSize ; - uint32_t mOffset ; - bool mOk ; -}; -template T ntoh(T t) -{ - if(sizeof(T) == 8) return t; - if(sizeof(T) == 4) return ntohl(t) ; - if(sizeof(T) == 2) return ntohs(t) ; - - std::cerr << "(EE) unhandled type of size " << sizeof(T) << " in ntoh<>" << std::endl; - return t; -} -template T hton(T t) -{ - if(sizeof(T) == 8) return t; - if(sizeof(T) == 4) return htonl(t) ; - if(sizeof(T) == 2) return htons(t) ; - - std::cerr << "(EE) unhandled type of size " << sizeof(T) << " in hton<>" << std::endl; - return t; -} - -class RsTypeSerializer -{ - public: - template - static void serial_process(RsSerializable::SerializeJob j,SerializeContext& ctx,T& member) - { - switch(j) - { - case RsSerializable::SIZE_ESTIMATE: ctx.mSize += serial_size(member) ; - break ; - - case RsSerializable::DESERIALIZE: deserialize(ctx.mData,ctx.mSize,ctx.mOffset,member) ; - break ; - - case RsSerializable::SERIALIZE: serialize(ctx.mData,ctx.mSize,ctx.mOffset,member) ; - break ; - - default: - throw std::runtime_error("Unknown serial job") ; - } - } - - protected: - template - static bool serialize(uint8_t data[], uint32_t size, uint32_t &offset, const T& member); - - template - static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, T& member); - - template - static uint32_t serial_size(const T& /* member */); -}; - -/// Templates to generate RsSerializer for standard integral types -// -template class t_SerializerNType -{ -public: - static bool serialize(uint8_t data[], uint32_t size, uint32_t &offset, const N& member) - { - if (size <= offset || size - offset < SIZE) - return false; - - N tmp = hton(member); - memcpy(data+offset, &tmp, SIZE); - offset += SIZE; - return true; - } - static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, N& member) - { - if (size <= offset || size - offset < SIZE) - return false; - - N tmp ; - memcpy(&tmp, data+offset, SIZE); - member = ntoh(tmp); - offset += SIZE; - return true; - } - - static uint32_t serial_size(const N& /* member */) - { - return SIZE; - } -}; - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint8_t& member) -{ - return t_SerializerNType::serialize(data,size,offset,member); -} -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint32_t& member) -{ - return t_SerializerNType::serialize(data,size,offset,member); -} -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint64_t& member) -{ - return t_SerializerNType::serialize(data,size,offset,member); -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint8_t& member) -{ - return t_SerializerNType::deserialize(data,size,offset,member); -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint32_t& member) -{ - return t_SerializerNType::deserialize(data,size,offset,member); -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint64_t& member) -{ - return t_SerializerNType::deserialize(data,size,offset,member); -} -template<> uint32_t RsTypeSerializer::serial_size(const uint8_t& member) -{ - return t_SerializerNType::serial_size(member); -} -template<> uint32_t RsTypeSerializer::serial_size(const uint32_t& member) -{ - return t_SerializerNType::serial_size(member); -} -template<> uint32_t RsTypeSerializer::serial_size(const uint64_t& member) -{ - return t_SerializerNType::serial_size(member); -} -//// Float -// -template<> - uint32_t RsTypeSerializer::serial_size(const float&){ return 4; } - - -template<> -bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const float& f) - { - uint32_t sz = serial_size(f); - if ( !data || size <= offset || size - offset < sz ) - return false; - - const float tmp = f; - if(tmp < 0.0f) - { - std::cerr << "(EE) Cannot serialise invalid negative float value " - << tmp << " in " << __PRETTY_FUNCTION__ << std::endl; - return false; - } - - /* This serialisation is quite accurate. The max relative error is approx. - * 0.01% and most of the time less than 1e-05% The error is well distributed - * over numbers also. */ - uint32_t n; - if(tmp < 1e-7) n = (~(uint32_t)0); - else n = ((uint32_t)( (1.0f/(1.0f+tmp) * (~(uint32_t)0)))); - n = hton(n); - memcpy(data+offset, &n, sz); - offset += sz; - return true; - } - -template<> uint32_t RsTypeSerializer::serial_size(const std::string& s) -{ - return s.length() + 4; -} - - -template<> - bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, float& f) - { - uint32_t sz = serial_size(f); - if ( !data || size <= offset || - size - offset < sz ) - return false; - - uint32_t n; - memcpy(&n, data+offset, sz); - n = ntoh(n); - f = 1.0f/ ( n/(float)(~(uint32_t)0)) - 1.0f; - return true; - } - - -/// Serializer for std::string - template<> - bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,const std::string& s) - { - if ( !data || size <= offset || size - offset < serial_size(s)) - return false; - - uint32_t charsLen = s.length(); - uint32_t netLen = hton(charsLen); - memcpy(data+offset, &netLen, 4); offset += 4; - memcpy(data+offset, s.c_str(), charsLen); offset += charsLen; - return true; - } -template<> - bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,std::string& s) - { - if ( !data || size <= offset || size - offset < 4 ) return false; - uint32_t charsLen; - memcpy(&charsLen, data+offset, 4); offset += 4; - charsLen = ntoh(charsLen); - - if ( size <= offset || size - offset < charsLen ) return false; - s.clear(); - s.insert(0, (char*)data+offset, charsLen); - offset += charsLen; - return true; - } - -class RsSerializer -{ - public: - /*! create_item - * should be overloaded to create the correct type of item depending on the data - */ - virtual RsSerializable *create_item(uint16_t service, uint8_t item_sub_id) - { - return NULL ; - } - - RsSerializable *deserialize_item(const uint8_t *data,uint32_t size) - { - uint32_t rstype = getRsItemId(const_cast((const void*)data)) ; - - RsSerializable *item = create_item(getRsItemService(rstype),getRsItemSubType(rstype)) ; - - if(!item) - { - std::cerr << "(EE) cannot deserialise: unknown item type " << std::hex << rstype << std::dec << std::endl; - return NULL ; - } - - SerializeContext ctx(const_cast(data),size); - item->serial_process(RsSerializable::DESERIALIZE, ctx) ; - - if(ctx.mOk) - return item ; - - delete item ; - return NULL ; - } - - bool serialize_item(const RsSerializable *item,uint8_t *const data,uint32_t size) - { - SerializeContext ctx(data,0); - - uint32_t tlvsize = size_item(item) ; - - if(tlvsize > size) - throw std::runtime_error("Cannot serialise: not enough room.") ; - - if(!setRsItemHeader(data, tlvsize, const_cast(item)->PacketId(), tlvsize)) - { - std::cerr << "RsSerializer::serialise_item(): ERROR. Not enough size!" << std::endl; - return false ; - } - ctx.mOffset = 8; - ctx.mSize = tlvsize; - - const_cast(item)->serial_process(RsSerializable::SERIALIZE,ctx) ; - - if(ctx.mSize != ctx.mOffset) - { - std::cerr << "RsSerializer::serialise_item(): ERROR. offset does not match expected size!" << std::endl; - return false ; - } - return true ; - } - - uint32_t size_item(const RsSerializable *item) - { - SerializeContext ctx(NULL,0); - - ctx.mSize = 8 ; // header size - const_cast(item)->serial_process(RsSerializable::SIZE_ESTIMATE, ctx) ; - - return ctx.mSize ; - } -}; - - -