From ea8f800003330eaabb576092a1697b79eb96bfc8 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 8 May 2017 00:19:11 +0200 Subject: [PATCH] Port GxsTrans to new serialization system RsItem added some comment and more verbose error reporting RsTypeSerializer added support for RsItem derived classes as members added utility macros for better readability of the code and easier handling of RsItem derived members RS_REGISTER_SERIAL_MEMBER(I) RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) RS_REGISTER_ITEM_TYPE(T) RsNxsMsg::serial_process use new macros for better readability and to have an exemple of usage with RsTlvItem derived class Fix undefined reference to RsNxsMsg::print --- libretroshare/src/chat/p3chatservice.cc | 9 +- libretroshare/src/chat/rschatitems.cc | 7 + libretroshare/src/chat/rschatitems.h | 11 + libretroshare/src/gxstrans/p3gxstrans.cc | 20 +- libretroshare/src/gxstrans/p3gxstransitems.cc | 193 +--- libretroshare/src/gxstrans/p3gxstransitems.h | 167 +--- libretroshare/src/rsitems/rsitem.h | 25 +- libretroshare/src/rsitems/rsnxsitems.cc | 26 +- libretroshare/src/rsitems/rsnxsitems.h | 2 +- .../src/serialiser/rstypeserializer.cc | 56 ++ .../src/serialiser/rstypeserializer.h | 867 ++++++++++-------- 11 files changed, 655 insertions(+), 728 deletions(-) diff --git a/libretroshare/src/chat/p3chatservice.cc b/libretroshare/src/chat/p3chatservice.cc index 3798666e5..32dbe64a5 100644 --- a/libretroshare/src/chat/p3chatservice.cc +++ b/libretroshare/src/chat/p3chatservice.cc @@ -346,9 +346,9 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg) if(it != mDistantGxsMap.end()) { const DistantEndpoints& de(it->second); - uint32_t sz = ci->serial_size(); + uint32_t sz = _serializer->size(ci); std::vector data; data.resize(sz); - ci->serialise(&data[0], sz); + _serializer->serialise(ci, &data[0], &sz); mGxsTransport.sendMail(tId, GxsTransSubServices::P3_CHAT_SERVICE, de.from, de.to, &data[0], sz); } @@ -717,8 +717,9 @@ bool p3ChatService::receiveGxsTransMail( const RsGxsId& authorId, if(initiateDistantChatConnexion( authorId, recipientId, pid, error_code, false )) { - RsChatMsgItem* item = new RsChatMsgItem( const_cast(data), - dataSize ); + RsChatMsgItem* item = static_cast( + _serializer->deserialise( + const_cast(data), &dataSize )); RsPeerId rd(p3GxsTunnelService::makeGxsTunnelId(authorId, recipientId)); item->PeerId(rd); handleRecvChatMsgItem(item); diff --git a/libretroshare/src/chat/rschatitems.cc b/libretroshare/src/chat/rschatitems.cc index 2b7dd67d8..35ccaa905 100644 --- a/libretroshare/src/chat/rschatitems.cc +++ b/libretroshare/src/chat/rschatitems.cc @@ -195,4 +195,11 @@ void RsPrivateChatMsgConfigItem::get(RsChatMsgItem *ci) ci->recvTime = recvTime; } +/* Necessary to serialize `store` that is an STL container with RsChatMsgItem + * inside which is a subtype of RsItem */ +RS_REGISTER_ITEM_TYPE(RsChatMsgItem) +void PrivateOugoingMapItem::serial_process( + RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ) +{ RS_REGISTER_SERIAL_MEMBER(store); } diff --git a/libretroshare/src/chat/rschatitems.h b/libretroshare/src/chat/rschatitems.h index 617ca3276..253bb66f1 100644 --- a/libretroshare/src/chat/rschatitems.h +++ b/libretroshare/src/chat/rschatitems.h @@ -325,6 +325,17 @@ class RsChatAvatarItem: public RsChatItem unsigned char *image_data ; // image }; + +struct PrivateOugoingMapItem : RsChatItem +{ + PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {} + + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ); + + std::map store; +}; + struct RsChatSerialiser : RsServiceSerializer { RsChatSerialiser(SerializationFlags flags = SERIALIZATION_FLAG_NONE) : diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc index b36a6ade6..4454bf6e1 100644 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ b/libretroshare/src/gxstrans/p3gxstrans.cc @@ -478,14 +478,16 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId, } GxsTransSubServices rsrvc = static_cast(csri); - RsNxsTransPresignedReceipt* receipt = new RsNxsTransPresignedReceipt(); uint32_t rcptsize = decrypted_data_size; - if(!receipt->deserialize(decrypted_data, rcptsize, offset)) + RsNxsTransPresignedReceipt* receipt = + static_cast( + RsGxsTransSerializer().deserialise( + const_cast(decrypted_data), &rcptsize ) ); + if(!receipt) { std::cerr << "p3GxsTrans::dispatchDecryptedMail(...) (EE) fatal error " << "deserializing presigned return receipt , something really" << " wrong is happening!" << std::endl; - delete receipt; return false; } std::cout << "p3GxsTrans::dispatchDecryptedMail(...) dispatching receipt " @@ -541,10 +543,10 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr) grcpt.meta = pr.mailItem.meta; grcpt.meta.mPublishTs = time(NULL); grcpt.mailId = pr.mailItem.mailId; - uint32_t groff = 0, grsz = grcpt.serial_size(); + uint32_t grsz = RsGxsTransSerializer().size(&grcpt); std::vector grsrz; grsrz.resize(grsz); - grcpt.serialize(&grsrz[0], grsz, groff); + RsGxsTransSerializer().serialise(&grcpt, &grsrz[0], &grsz); pr.presignedReceipt.grpId = mPreferredGroupId; pr.presignedReceipt.metaData = new RsGxsMsgMetaData(); @@ -572,13 +574,14 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr) case GxsTransSendStatus::PENDING_PAYLOAD_CREATE: { uint16_t serv = static_cast(pr.clientService); - uint32_t rcptsize = pr.presignedReceipt.serial_size(); + uint32_t rcptsize = RsGxsTransSerializer().size(&pr.presignedReceipt); uint32_t datasize = pr.mailData.size(); pr.mailItem.payload.resize(2 + rcptsize + datasize); uint32_t offset = 0; setRawUInt16(&pr.mailItem.payload[0], 2, &offset, serv); - pr.presignedReceipt.serialise( &pr.mailItem.payload[offset], - rcptsize ); + RsGxsTransSerializer().serialise(&pr.presignedReceipt, + &pr.mailItem.payload[offset], + &rcptsize); offset += rcptsize; memcpy(&pr.mailItem.payload[offset], &pr.mailData[0], datasize); } @@ -781,4 +784,3 @@ bool p3GxsTrans::loadList(std::list&loadList) return true; } - diff --git a/libretroshare/src/gxstrans/p3gxstransitems.cc b/libretroshare/src/gxstrans/p3gxstransitems.cc index eb5736f8e..cab1e2dfb 100644 --- a/libretroshare/src/gxstrans/p3gxstransitems.cc +++ b/libretroshare/src/gxstrans/p3gxstransitems.cc @@ -17,88 +17,14 @@ */ #include "gxstrans/p3gxstransitems.h" +#include "serialiser/rstypeserializer.h" const RsGxsId RsGxsTransMailItem::allRecipientsHint("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - -bool RsGxsTransBaseItem::serialize(uint8_t* data, uint32_t size, - uint32_t& offset) const -{ - bool ok = setRsItemHeader(data+offset, size, PacketId(), size); - ok = ok && (offset += 8); // Take header in account - ok = ok && setRawUInt64(data, size, &offset, mailId); - return ok; -} - -bool RsGxsTransBaseItem::deserialize( const uint8_t* data, uint32_t& size, - uint32_t& offset) -{ - void* hdrPtr = const_cast(data+offset); - uint32_t rssize = getRsItemSize(hdrPtr); - uint32_t roffset = offset + 8; // Take header in account - - void* dataPtr = const_cast(data); - bool ok = rssize <= size; - ok = ok && getRawUInt64(dataPtr, rssize, &roffset, &mailId); - if(ok) { size = rssize; offset = roffset; } - else size = 0; - return ok; -} - -std::ostream& RsGxsTransBaseItem::print(std::ostream &out, uint16_t) -{ return out << __PRETTY_FUNCTION__ << " mailId: " << mailId; } - -bool RsGxsTransSerializer::serialise(RsItem* item, void* data, uint32_t* size) -{ - uint32_t itemSize = RsGxsTransSerializer::size(item); - if(*size < itemSize) - { - std::cout << __PRETTY_FUNCTION__ << " failed due to wrong size: " - << size << " < " << itemSize << std::endl; - return false; - } - - uint8_t* dataPtr = reinterpret_cast(data); - bool ok = false; - switch(static_cast(item->PacketSubType())) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: - { - uint32_t offset = 0; - RsGxsTransMailItem* i = dynamic_cast(item); - ok = i && i->serialize(dataPtr, itemSize, offset); - break; - } - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: - { - RsGxsTransPresignedReceipt* i = - dynamic_cast(item); - uint32_t offset = 0; - ok = i && i->serialize(dataPtr, itemSize, offset); - break; - } - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: - ok = setRsItemHeader(data, itemSize, item->PacketId(), itemSize); - break; - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: - { - uint32_t offset = 0; - OutgoingRecord* i = dynamic_cast(item); - ok = i && i->serialize(dataPtr, itemSize, offset); - break; - } - default: ok = false; break; - } - - if(ok) - { - *size = itemSize; - return true; - } - - std::cout << __PRETTY_FUNCTION__ << " failed!" << std::endl; - return false; -} +OutgoingRecord::OutgoingRecord() : + RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, + static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) ) +{ clear();} OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, const uint8_t* data, uint32_t size ) : @@ -111,102 +37,17 @@ OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, memcpy(&mailData[0], data, size); } -void OutgoingRecord::clear() + +RS_REGISTER_ITEM_TYPE(RsGxsTransMailItem) // for mailItem +RS_REGISTER_ITEM_TYPE(RsNxsTransPresignedReceipt) // for presignedReceipt + +void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) { - status = GxsTransSendStatus::UNKNOWN; - recipient.clear(); - mailItem.clear(); - mailData.clear(); - clientService = GxsTransSubServices::UNKNOWN; - presignedReceipt.clear(); + RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t); + RS_REGISTER_SERIAL_MEMBER(recipient); + RS_REGISTER_SERIAL_MEMBER(mailItem); + RS_REGISTER_SERIAL_MEMBER(mailData); + RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t); + RS_REGISTER_SERIAL_MEMBER(presignedReceipt); } - -std::ostream& OutgoingRecord::print(std::ostream& out, uint16_t) -{ return out << "TODO: OutgoingRecordItem::print(...)"; } - -OutgoingRecord::OutgoingRecord() : - RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, - static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) ) -{ clear();} - -uint32_t OutgoingRecord::serial_size() const -{ - return 8 + // Header - 1 + // status - recipient.serial_size() + - mailItem.serial_size() + - 4 + // sizeof(mailData.size()) - mailData.size() + - 2 + // clientService - presignedReceipt.serial_size(); -} - -bool OutgoingRecord::serialize( uint8_t* data, uint32_t size, - uint32_t& offset) const -{ - bool ok = true; - - ok = ok && setRsItemHeader(data+offset, size, PacketId(), size) - && (offset += 8); // Take header in account - - ok = ok && setRawUInt8(data, size, &offset, static_cast(status)); - - ok = ok && recipient.serialise(data, size, offset); - - uint32_t tmpOffset = 0; - uint32_t tmpSize = mailItem.serial_size(); - ok = ok && mailItem.serialize(data+offset, tmpSize, tmpOffset) - && (offset += tmpOffset); - - uint32_t dSize = mailData.size(); - ok = ok && setRawUInt32(data, size, &offset, dSize) - && memcpy(data+offset, &mailData[0], dSize) && (offset += dSize); - - ok = ok && setRawUInt16( data, size, &offset, - static_cast(clientService) ); - - dSize = presignedReceipt.serial_size(); - ok = ok && presignedReceipt.serialise(data+offset, dSize) - && (offset += dSize); - - return ok; -} - -bool OutgoingRecord::deserialize( - const uint8_t* data, uint32_t& size, uint32_t& offset) -{ - bool ok = true; - - void* dataPtr = const_cast(data); - offset += 8; // Header - - uint8_t tmpStatus = 0; - ok = ok && getRawUInt8(dataPtr, size, &offset, &tmpStatus); - status = static_cast(tmpStatus); - - uint32_t tmpSize = size; - ok = ok && recipient.deserialise(dataPtr, tmpSize, offset); - - void* hdrPtr = const_cast(data+offset); - tmpSize = getRsItemSize(hdrPtr); - - uint32_t tmpOffset = 0; - ok = ok && mailItem.deserialize(static_cast(hdrPtr), tmpSize, tmpOffset); - ok = ok && (offset += tmpOffset); - - tmpSize = size; - ok = getRawUInt32(dataPtr, tmpSize, &offset, &tmpSize); - ok = ok && (tmpSize+offset < size); - ok = ok && (mailData.resize(tmpSize), memcpy(&mailData[0], data, tmpSize)); - ok = ok && (offset += tmpSize); - - uint16_t cs = 0; - ok = ok && getRawUInt16(dataPtr, offset+2, &offset, &cs); - clientService = static_cast(cs); - - tmpSize = size; - ok = ok && presignedReceipt.deserialize(data, tmpSize, offset); - - return ok; -} - diff --git a/libretroshare/src/gxstrans/p3gxstransitems.h b/libretroshare/src/gxstrans/p3gxstransitems.h index fa6395f3b..276dd739e 100644 --- a/libretroshare/src/gxstrans/p3gxstransitems.h +++ b/libretroshare/src/gxstrans/p3gxstransitems.h @@ -19,12 +19,13 @@ #include -#include "serialiser/rsgxsitems.h" +#include "rsitems/rsgxsitems.h" #include "serialiser/rsbaseserial.h" #include "serialiser/rstlvidset.h" #include "retroshare/rsgxsflags.h" #include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC #include "services/p3idservice.h" +#include "serialiser/rstypeserializer.h" /// Subservices identifiers (like port for TCP) enum class GxsTransSubServices : uint16_t @@ -65,14 +66,9 @@ struct RsGxsTransBaseItem : RsGxsMsgItem meta = RsMsgMetaData(); } - static uint32_t inline serial_size() - { - return 8 + // Header - 8; // mailId - } - bool serialize(uint8_t* data, uint32_t size, uint32_t& offset) const; - bool deserialize(const uint8_t* data, uint32_t& size, uint32_t& offset); - std::ostream &print(std::ostream &out, uint16_t /*indent = 0*/); + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ) + { RS_REGISTER_SERIAL_MEMBER_TYPED(mailId, uint64_t); } }; struct RsGxsTransPresignedReceipt : RsGxsTransBaseItem @@ -149,46 +145,15 @@ struct RsGxsTransMailItem : RsGxsTransBaseItem * is specified */ std::vector payload; - uint32_t serial_size() const + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ) { - return RsGxsTransBaseItem::serial_size() + - 1 + // cryptoType - recipientHint.serial_size() + - payload.size(); + RsGxsTransBaseItem::serial_process(j, ctx); + RS_REGISTER_SERIAL_MEMBER_TYPED(cryptoType, uint8_t); + RS_REGISTER_SERIAL_MEMBER(recipientHint); + RS_REGISTER_SERIAL_MEMBER(payload); } - bool serialize(uint8_t* data, uint32_t size, uint32_t& offset) const - { - bool ok = size < MAX_SIZE; - ok = ok && RsGxsTransBaseItem::serialize(data, size, offset); - ok = ok && setRawUInt8( data, size, &offset, - static_cast(cryptoType) ); - ok = ok && recipientHint.serialise(data, size, offset); - uint32_t psz = payload.size(); - ok = ok && memcpy(data+offset, &payload[0], psz); - offset += psz; - return ok; - } - bool deserialize(const uint8_t* data, uint32_t& size, uint32_t& offset) - { - void* sizePtr = const_cast(data+offset); - uint32_t rssize = getRsItemSize(sizePtr); - uint32_t roffset = offset; - bool ok = rssize <= size && size < MAX_SIZE; - ok = ok && RsGxsTransBaseItem::deserialize(data, rssize, roffset); - - void* dataPtr = const_cast(data); - uint8_t crType; - ok = ok && getRawUInt8(dataPtr, rssize, &roffset, &crType); - cryptoType = static_cast(crType); - ok = ok && recipientHint.deserialise(dataPtr, rssize, roffset); - uint32_t psz = rssize - roffset; - ok = ok && (payload.resize(psz), memcpy(&payload[0], data+roffset, psz)); - ok = ok && (roffset += psz); - if(ok) { size = rssize; offset = roffset; } - else size = 0; - return ok; - } void clear() { RsGxsTransBaseItem::clear(); @@ -213,6 +178,11 @@ struct RsGxsTransGroupItem : RsGxsGrpItem meta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; } + // TODO: Talk with Cyril why there is no RsGxsGrpItem::serial_process + virtual void serial_process(RsGenericSerializer::SerializeJob /*j*/, + RsGenericSerializer::SerializeContext& /*ctx*/) + {} + void clear() {} std::ostream &print(std::ostream &out, uint16_t /*indent = 0*/) { return out; } @@ -253,12 +223,10 @@ struct OutgoingRecord : RsItem GxsTransSubServices clientService; RsNxsTransPresignedReceipt presignedReceipt; - uint32_t serial_size() const; - bool serialize(uint8_t* data, uint32_t size, uint32_t& offset) const; - bool deserialize(const uint8_t* data, uint32_t& size, uint32_t& offset); + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ); - virtual void clear(); - virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); + void clear() {} private: friend class RsGxsTransSerializer; @@ -266,100 +234,23 @@ private: }; -struct RsGxsTransSerializer : RsSerialType +struct RsGxsTransSerializer : public RsServiceSerializer { - RsGxsTransSerializer() : RsSerialType( RS_PKT_VERSION_SERVICE, - RS_SERVICE_TYPE_GXS_TRANS ) {} + RsGxsTransSerializer() : RsServiceSerializer(RS_SERVICE_TYPE_GXS_TRANS) {} ~RsGxsTransSerializer() {} - uint32_t size(RsItem* item) + RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const { - uint32_t sz = 0; - switch(static_cast(item->PacketSubType())) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: - { - RsGxsTransMailItem* i = dynamic_cast(item); - if(i) sz = i->serial_size(); - break; - } - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: - sz = RsGxsTransPresignedReceipt::serial_size(); break; - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: sz = 8; break; - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: - { - OutgoingRecord* ci = dynamic_cast(item); - if(ci) sz = ci->serial_size(); - break; - } - default: break; - } + if(service_id != RS_SERVICE_TYPE_GXS_TRANS) return NULL; - return sz; - } - - bool serialise(RsItem* item, void* data, uint32_t* size); - - RsItem* deserialise(void* data, uint32_t* size) - { - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - uint8_t pktv = getRsItemVersion(rstype); - uint16_t srvc = getRsItemService(rstype); - const uint8_t* dataPtr = reinterpret_cast(data); - - if ( (RS_PKT_VERSION_SERVICE != pktv) || // 0x02 - (RS_SERVICE_TYPE_GXS_TRANS != srvc) || // 0x0230 = 560 - (*size < rssize) ) + switch(static_cast(item_sub_id)) { - print_stacktrace(); - return NULL; + case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: return new RsGxsTransMailItem(); + case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: return new RsGxsTransPresignedReceipt(); + case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: return new RsGxsTransGroupItem(); + case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: return new OutgoingRecord(); + default: return NULL; } - - *size = rssize; - bool ok = true; - RsItem* ret = NULL; - - switch (static_cast(getRsItemSubType(rstype))) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: - { - RsGxsTransMailItem* i = new RsGxsTransMailItem(); - uint32_t offset = 0; - ok = ok && i->deserialize(dataPtr, *size, offset); - ret = i; - break; - } - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: - { - RsGxsTransPresignedReceipt* i = new RsGxsTransPresignedReceipt(); - uint32_t offset = 0; - ok &= i->deserialize(dataPtr, *size, offset); - ret = i; - break; - } - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: - { - ret = new RsGxsTransGroupItem(); - break; - } - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: - { - OutgoingRecord* i = new OutgoingRecord(); - uint32_t offset = 0; - ok = ok && i->deserialize(dataPtr, *size, offset); - ret = i; - break; - } - default: - ok = false; - break; - } - - if(ok) return ret; - - delete ret; - return NULL; } }; diff --git a/libretroshare/src/rsitems/rsitem.h b/libretroshare/src/rsitems/rsitem.h index 8dbda2fb3..5698728a0 100644 --- a/libretroshare/src/rsitems/rsitem.h +++ b/libretroshare/src/rsitems/rsitem.h @@ -3,6 +3,7 @@ #include "util/smallobject.h" #include "retroshare/rstypes.h" #include "serialiser/rsserializer.h" +#include "util/stacktrace.h" class RsItem: public RsMemoryManagement::SmallObject { @@ -15,6 +16,8 @@ class RsItem: public RsMemoryManagement::SmallObject #endif virtual ~RsItem(); + + /// TODO: Do this make sense with the new serialization system? virtual void clear() = 0; virtual std::ostream &print(std::ostream &out, uint16_t /* indent */ = 0) @@ -48,21 +51,16 @@ class RsItem: public RsMemoryManagement::SmallObject inline void setPriorityLevel(uint8_t l) { _priority_level = l ;} /** - * @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 + * TODO: This should be made pure virtual as soon as all the codebase + * is ported to the new serialization system */ - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) + virtual void serial_process(RsGenericSerializer::SerializeJob, + RsGenericSerializer::SerializeContext&)// = 0; { - std::cerr << "(EE) RsItem::serial_process() called by an item using new serialization classes, but not derived! Class is " << typeid(*this).name() << std::endl; + std::cerr << "(EE) RsItem::serial_process() called by an item using" + << "new serialization classes, but not derived! Class is " + << typeid(*this).name() << std::endl; + print_stacktrace(); } protected: @@ -71,6 +69,7 @@ class RsItem: public RsMemoryManagement::SmallObject uint8_t _priority_level ; }; +/// TODO: Do this make sense with the new serialization system? class RsRawItem: public RsItem { public: diff --git a/libretroshare/src/rsitems/rsnxsitems.cc b/libretroshare/src/rsitems/rsnxsitems.cc index 104935930..200d45391 100644 --- a/libretroshare/src/rsitems/rsnxsitems.cc +++ b/libretroshare/src/rsitems/rsnxsitems.cc @@ -69,15 +69,18 @@ void RsNxsSyncMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGene RsTypeSerializer::serial_process (j,ctx,msgId ,"msgId") ; RsTypeSerializer::serial_process (j,ctx,authorId ,"authorId") ; } -void RsNxsMsg::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) + +void RsNxsMsg::serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ) { - RsTypeSerializer::serial_process (j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,pos ,"pos") ; - RsTypeSerializer::serial_process (j,ctx,msgId ,"msgId") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,msg ,"msg") ; - RsTypeSerializer::serial_process(j,ctx,meta ,"meta") ; + RS_REGISTER_SERIAL_MEMBER_TYPED(transactionNumber, uint32_t); + RS_REGISTER_SERIAL_MEMBER_TYPED(pos, uint8_t); + RS_REGISTER_SERIAL_MEMBER(msgId); + RS_REGISTER_SERIAL_MEMBER(grpId); + RS_REGISTER_SERIAL_MEMBER_TYPED(msg, RsTlvItem); + RS_REGISTER_SERIAL_MEMBER_TYPED(meta, RsTlvItem); } + void RsNxsGrp::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { RsTypeSerializer::serial_process (j,ctx,transactionNumber,"transactionNumber") ; @@ -149,11 +152,14 @@ void RsNxsMsg::clear() meta.TlvClear(); } +std::ostream&RsNxsMsg::print(std::ostream& out, uint16_t /*indent*/) +{ return out; } + void RsNxsGrp::clear() { - grpId.clear(); - grp.TlvClear(); - meta.TlvClear(); + grpId.clear(); + grp.TlvClear(); + meta.TlvClear(); } void RsNxsSyncGrpReqItem::clear() diff --git a/libretroshare/src/rsitems/rsnxsitems.h b/libretroshare/src/rsitems/rsnxsitems.h index 127d876f6..6779989f4 100644 --- a/libretroshare/src/rsitems/rsnxsitems.h +++ b/libretroshare/src/rsitems/rsnxsitems.h @@ -376,7 +376,7 @@ struct RsNxsMsg : RsNxsItem RsGenericSerializer::SerializeContext& ctx ); virtual void clear(); - virtual std::ostream &print(std::ostream &out, uint16_t indent); + virtual std::ostream &print(std::ostream& out, uint16_t indent); uint8_t pos; /// used for splitting up msg uint8_t count; /// number of split up messages diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc index f4cfc0d62..c2b8bd1c4 100644 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ b/libretroshare/src/serialiser/rstypeserializer.cc @@ -27,6 +27,8 @@ #include "serialiser/rsbaseserial.h" #include "serialiser/rstlvkeys.h" +#include "rsitems/rsitem.h" + #include "util/rsprint.h" #include @@ -306,3 +308,57 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const RsTlvIt std::cerr << " [" << typeid(s).name() << "] " << n << std::endl; } + +//============================================================================// +// RsItem and derivated // +//============================================================================// + +template<> uint32_t RsTypeSerializer::serial_size(const RsItem& s) +{ + RsGenericSerializer::SerializeContext ctx( + NULL, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE ); + + ctx.mOffset = 8; // header size + const_cast(s).serial_process(RsGenericSerializer::SIZE_ESTIMATE, + ctx); + + return ctx.mOffset; +} + +template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size, + uint32_t &offset, const RsItem& s ) +{ + RsGenericSerializer::SerializeContext ctx( + data, size, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE ); + ctx.mOffset = offset; + const_cast(s).serial_process(RsGenericSerializer::SERIALIZE, + ctx); + return true; +} + +template<> bool RsTypeSerializer::deserialize( const uint8_t data[], + uint32_t size, uint32_t& offset, + RsItem& s ) +{ + RsGenericSerializer::SerializeContext ctx( + const_cast(data), size, + RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE ); + ctx.mOffset = offset; + const_cast(s).serial_process(RsGenericSerializer::DESERIALIZE, + ctx); + return true; +} + +template<> void RsTypeSerializer::print_data( const std::string& n, + const RsItem& s ) +{ + RsGenericSerializer::SerializeContext ctx( + NULL, 0, + RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE ); + const_cast(s).serial_process(RsGenericSerializer::PRINT, + ctx); +} diff --git a/libretroshare/src/serialiser/rstypeserializer.h b/libretroshare/src/serialiser/rstypeserializer.h index 333f1a364..ffc84e72b 100644 --- a/libretroshare/src/serialiser/rstypeserializer.h +++ b/libretroshare/src/serialiser/rstypeserializer.h @@ -33,409 +33,522 @@ #include "serialiser/rsserializer.h" +/** @def RS_REGISTER_SERIAL_MEMBER(I) + * Use this macro to register the members of `YourItem` for serial processing + * inside `YourItem::serial_process(j, ctx)` + * + * Inspired by http://stackoverflow.com/a/39345864 + */ +#define RS_REGISTER_SERIAL_MEMBER(I) \ + do { RsTypeSerializer::serial_process(j, ctx, I, #I); } while(0) -class RsTypeSerializer +/** @def RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) + * This macro usage is similar to @see RS_REGISTER_SERIAL_MEMBER(I) but it + * permit to force serialization/deserialization type, it is expecially useful + * with enum class members ot RsTlvItem derivative members, be very careful with + * the type you pass, as reinterpret_cast on a reference is used that is + * expecially permissive so you can shot your feet if not carefull enough. + * + * If you are using this with an RsItem derivative (so passing RsItem as T) + * consider to register your item type with @see RS_REGISTER_ITEM_TYPE(T) in + * association with @see RS_REGISTER_SERIAL_MEMBER(I) that rely on template + * function generation, as in this particular case + * RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) would cause the serial code rely on + * C++ dynamic dispatching that may have a noticeable impact on runtime + * performances. + */ +#define RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) do {\ + RsTypeSerializer::serial_process(j, ctx, reinterpret_cast(I), #I);\ + } while(0) + +/** @def RS_REGISTER_ITEM_TYPE(T) + * Use this macro into `youritem.cc` only if you need to process members of + * subtypes of RsItem. + * + * The usage of this macro is strictly needed only in some cases, for example if + * you are registering for serialization a member of a container that contains + * items of subclasses of RsItem like * `std::map` + * + * @code{.cpp} +struct PrivateOugoingMapItem : RsChatItem { - public: - // This type should be used to pass a parameter to drive the serialisation if needed. + PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {} - struct TlvMemBlock_proxy: public std::pair - { - TlvMemBlock_proxy(void *& p,uint32_t& s) : std::pair(p,s) {} - TlvMemBlock_proxy(uint8_t*& p,uint32_t& s) : std::pair(*(void**)&p,s) {} - }; + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ); - //=================================================================================================// - // Generic types // - //=================================================================================================// - - template - static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,T& member,const std::string& member_name) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: ctx.mOffset += serial_size(member) ; - break ; - - case RsGenericSerializer::DESERIALIZE: ctx.mOk = ctx.mOk && deserialize(ctx.mData,ctx.mSize,ctx.mOffset,member) ; - break ; - - case RsGenericSerializer::SERIALIZE: ctx.mOk = ctx.mOk && serialize(ctx.mData,ctx.mSize,ctx.mOffset,member) ; - break ; - - case RsGenericSerializer::PRINT: - print_data(member_name,member); - break; - default: - ctx.mOk = false ; - throw std::runtime_error("Unknown serial job") ; - } - } - - //=================================================================================================// - // Generic types + type_id // - //=================================================================================================// - - template - static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,uint16_t type_id,T& member,const std::string& member_name) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: ctx.mOffset += serial_size(type_id,member) ; - break ; - - case RsGenericSerializer::DESERIALIZE: ctx.mOk = ctx.mOk && deserialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member) ; - break ; - - case RsGenericSerializer::SERIALIZE: ctx.mOk = ctx.mOk && serialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member) ; - break ; - - case RsGenericSerializer::PRINT: - print_data(member_name,type_id,member); - break; - default: - ctx.mOk = false ; - throw std::runtime_error("Unknown serial job") ; - } - } - //=================================================================================================// - // std::map // - //=================================================================================================// - - template - static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::map& v,const std::string& member_name) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - { - ctx.mOffset += 4 ; - for(typename std::map::iterator it(v.begin());it!=v.end();++it) - { - serial_process(j,ctx,const_cast(it->first),"map::*it->first") ; - serial_process(j,ctx,const_cast(it->second),"map::*it->second") ; - } - } - break ; - - case RsGenericSerializer::DESERIALIZE: - { - uint32_t n=0 ; - serial_process(j,ctx,n,"temporary size"); - - for(uint32_t i=0;ifirst") ; - serial_process(j,ctx,u,"map::*it->second") ; - - v[t] = u ; - } - } - break ; - - case RsGenericSerializer::SERIALIZE: - { - uint32_t n=v.size(); - serial_process(j,ctx,n,"temporary size"); - - for(typename std::map::iterator it(v.begin());it!=v.end();++it) - { - serial_process(j,ctx,const_cast(it->first),"map::*it->first") ; - serial_process(j,ctx,const_cast(it->second),"map::*it->second") ; - } - } - break ; - - case RsGenericSerializer::PRINT: - { - if(v.empty()) - std::cerr << " Empty map \"" << member_name << "\"" << std::endl; - else - std::cerr << " std::map of " << v.size() << " elements: \"" << member_name << "\"" << std::endl; - - for(typename std::map::iterator it(v.begin());it!=v.end();++it) - { - std::cerr << " " ; - - serial_process(j,ctx,const_cast(it->first),"map::*it->first") ; - serial_process(j,ctx,const_cast(it->second),"map::*it->second") ; - } - } - break; - default: - break; - } - } - - //=================================================================================================// - // std::vector // - //=================================================================================================// - - template - static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::vector& v,const std::string& member_name) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - { - ctx.mOffset += 4 ; - for(uint32_t i=0;i // - //=================================================================================================// - - template - static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::set& v,const std::string& member_name) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - { - ctx.mOffset += 4 ; - for(typename std::set::iterator it(v.begin());it!=v.end();++it) - serial_process(j,ctx,const_cast(*it) ,member_name) ; // the const cast here is a hack to avoid serial_process to instantiate serialise(const T&) - } - break ; - - case RsGenericSerializer::DESERIALIZE: - { uint32_t n=0 ; - serial_process(j,ctx,n,"temporary size") ; - - for(uint32_t i=0;i(j,ctx,tmp,member_name) ; - v.insert(tmp); - } - } - break ; - - case RsGenericSerializer::SERIALIZE: - { - uint32_t n=v.size(); - serial_process(j,ctx,n,"temporary size") ; - for(typename std::set::iterator it(v.begin());it!=v.end();++it) - serial_process(j,ctx,const_cast(*it) ,member_name) ; // the const cast here is a hack to avoid serial_process to instantiate serialise(const T&) - } - break ; - - case RsGenericSerializer::PRINT: - { - if(v.empty()) - std::cerr << " Empty set"<< std::endl; - else - std::cerr << " Set of " << v.size() << " elements:" << std::endl; - } - break; - default: - break; - } - } - - - //=================================================================================================// - // std::list // - //=================================================================================================// - - template - static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::list& v,const std::string& member_name) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - { - ctx.mOffset += 4 ; - for(typename std::list::iterator it(v.begin());it!=v.end();++it) - serial_process(j,ctx,*it ,member_name) ; - } - break ; - - case RsGenericSerializer::DESERIALIZE: - { uint32_t n=0 ; - serial_process(j,ctx,n,"temporary size") ; - - for(uint32_t i=0;i(j,ctx,tmp,member_name) ; - v.push_back(tmp); - } - } - break ; - - case RsGenericSerializer::SERIALIZE: - { - uint32_t n=v.size(); - serial_process(j,ctx,n,"temporary size") ; - for(typename std::list::iterator it(v.begin());it!=v.end();++it) - serial_process(j,ctx,*it ,member_name) ; - } - break ; - - case RsGenericSerializer::PRINT: - { - if(v.empty()) - std::cerr << " Empty list"<< std::endl; - else - std::cerr << " List of " << v.size() << " elements:" << std::endl; - } - break; - default: - break; - } - } - - //=================================================================================================// - // t_RsFlags32<> types // - //=================================================================================================// - - template - static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,t_RsFlags32& v,const std::string& member_name) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: ctx.mOffset += 4 ; - break ; - - case RsGenericSerializer::DESERIALIZE: - { - uint32_t n=0 ; - deserialize(ctx.mData,ctx.mSize,ctx.mOffset,n) ; - v = t_RsFlags32(n) ; - } - break ; - - case RsGenericSerializer::SERIALIZE: - { - uint32_t n=v.toUInt32() ; - serialize(ctx.mData,ctx.mSize,ctx.mOffset,n) ; - } - break ; - - case RsGenericSerializer::PRINT: - std::cerr << " Flags of type " << std::hex << N << " : " << v.toUInt32() << std::endl; - break ; - } - - } - - 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 */); - template static void print_data(const std::string& name,const T& /* member */); - - template static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id,const T& member); - template static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset,uint16_t type_id, T& member); - template static uint32_t serial_size(uint16_t type_id,const T& /* member */); - template static void print_data(const std::string& name,uint16_t type_id,const T& /* member */); - - template static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsGenericIdType& member); - template static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsGenericIdType& member); - template static uint32_t serial_size(const t_RsGenericIdType& /* member */); - template static void print_data(const std::string& name,const t_RsGenericIdType& /* member */); - - template static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsTlvList& member); - template static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsTlvList& member); - template static uint32_t serial_size(const t_RsTlvList& /* member */); - template static void print_data(const std::string& name,const t_RsTlvList& /* member */); + std::map store; }; -//=================================================================================================// -// t_RsGenericId<> // -//=================================================================================================// +RS_REGISTER_ITEM_TYPE(RsChatMsgItem) + +void PrivateOugoingMapItem::serial_process( + RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ) +{ + // store is of type + RS_REGISTER_SERIAL_MEMBER(store); +} + * @endcode + * + * If you use this macro with a lot of different item types this can cause the + * generated binary grow in size, consider the usage of + * @see RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) passing RsItem as type in that + * case. + */ +#define RS_REGISTER_ITEM_TYPE(T) template<> \ + void RsTypeSerializer::serial_process( \ + RsGenericSerializer::SerializeJob j,\ + RsGenericSerializer::SerializeContext& ctx, T& item,\ + const std::string& /*name*/) { item.serial_process(j, ctx); } + +struct RsTypeSerializer +{ + /** This type should be used to pass a parameter to drive the serialisation + * if needed */ + struct TlvMemBlock_proxy: public std::pair + { + TlvMemBlock_proxy(void*& p, uint32_t& s) : + std::pair(p,s) {} + TlvMemBlock_proxy(uint8_t*& p,uint32_t& s) : + std::pair(*(void**)&p,s) {} + }; + + /// Generic types + template + static void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + T& member,const std::string& member_name) + { + switch(j) + { + case RsGenericSerializer::SIZE_ESTIMATE: + ctx.mOffset += serial_size(member); + break; + case RsGenericSerializer::DESERIALIZE: + ctx.mOk = ctx.mOk && + deserialize(ctx.mData,ctx.mSize,ctx.mOffset,member); + break; + case RsGenericSerializer::SERIALIZE: + ctx.mOk = ctx.mOk && + serialize(ctx.mData,ctx.mSize,ctx.mOffset,member); + break; + case RsGenericSerializer::PRINT: + print_data(member_name,member); + break; + default: + ctx.mOk = false; + throw std::runtime_error("Unknown serial job"); + } + } + + /// Generic types + type_id + template + static void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + uint16_t type_id, T& member, + const std::string& member_name ) + { + switch(j) + { + case RsGenericSerializer::SIZE_ESTIMATE: + ctx.mOffset += serial_size(type_id,member); + break; + case RsGenericSerializer::DESERIALIZE: + ctx.mOk = ctx.mOk && + deserialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member); + break; + case RsGenericSerializer::SERIALIZE: + ctx.mOk = ctx.mOk && + serialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member); + break; + case RsGenericSerializer::PRINT: + print_data(member_name,type_id,member); + break; + default: + ctx.mOk = false; + throw std::runtime_error("Unknown serial job"); + } + } + + /// std::map + template + static void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + std::map& v, + const std::string& member_name ) + { + switch(j) + { + case RsGenericSerializer::SIZE_ESTIMATE: + { + ctx.mOffset += 4; + for(typename std::map::iterator it(v.begin());it!=v.end();++it) + { + serial_process( j, ctx, const_cast(it->first), + "map::*it->first" ); + serial_process( j,ctx,const_cast(it->second), + "map::*it->second" ); + } + break; + } + case RsGenericSerializer::DESERIALIZE: + { + uint32_t n=0; + serial_process(j,ctx,n,"temporary size"); + + for(uint32_t i=0; ifirst"); + serial_process(j, ctx, u, "map::*it->second"); + v[t] = u; + } + break; + } + case RsGenericSerializer::SERIALIZE: + { + uint32_t n=v.size(); + serial_process(j,ctx,n,"temporary size"); + + for(typename std::map::iterator it(v.begin());it!=v.end();++it) + { + serial_process( j, ctx, const_cast(it->first), + "map::*it->first" ); + serial_process( j, ctx, const_cast(it->second), + "map::*it->second" ); + } + break; + } + case RsGenericSerializer::PRINT: + { + if(v.empty()) + std::cerr << " Empty map \"" << member_name << "\"" + << std::endl; + else + std::cerr << " std::map of " << v.size() << " elements: \"" + << member_name << "\"" << std::endl; + + for(typename std::map::iterator it(v.begin());it!=v.end();++it) + { + std::cerr << " "; + + serial_process( j, ctx,const_cast(it->first), + "map::*it->first" ); + serial_process( j, ctx, const_cast(it->second), + "map::*it->second" ); + } + break; + } + default: break; + } + } + + /// std::vector + template + static void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + std::vector& v, + const std::string& member_name ) + { + switch(j) + { + case RsGenericSerializer::SIZE_ESTIMATE: + { + ctx.mOffset += 4; + for(uint32_t i=0;i + template + static void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + std::set& v, const std::string& member_name ) + { + switch(j) + { + case RsGenericSerializer::SIZE_ESTIMATE: + { + ctx.mOffset += 4; + for(typename std::set::iterator it(v.begin());it!=v.end();++it) + // the const cast here is a hack to avoid serial_process to + // instantiate serialise(const T&) + serial_process(j,ctx,const_cast(*it) ,member_name); + break; + } + case RsGenericSerializer::DESERIALIZE: + { + uint32_t n=0; + serial_process(j,ctx,n,"temporary size"); + for(uint32_t i=0; i(j,ctx,tmp,member_name); + v.insert(tmp); + } + break; + } + case RsGenericSerializer::SERIALIZE: + { + uint32_t n=v.size(); + serial_process(j,ctx,n,"temporary size"); + for(typename std::set::iterator it(v.begin());it!=v.end();++it) + // the const cast here is a hack to avoid serial_process to + // instantiate serialise(const T&) + serial_process(j,ctx,const_cast(*it) ,member_name); + break; + } + case RsGenericSerializer::PRINT: + { + if(v.empty()) std::cerr << " Empty set"<< std::endl; + else std::cerr << " Set of " << v.size() << " elements:" + << std::endl; + break; + } + default: break; + } + } + + /// std::list + template + static void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + std::list& v, + const std::string& member_name ) + { + switch(j) + { + case RsGenericSerializer::SIZE_ESTIMATE: + { + ctx.mOffset += 4; + for(typename std::list::iterator it(v.begin());it!=v.end();++it) + serial_process(j,ctx,*it ,member_name); + break; + } + case RsGenericSerializer::DESERIALIZE: + { + uint32_t n=0; + serial_process(j,ctx,n,"temporary size"); + for(uint32_t i=0;i(j,ctx,tmp,member_name); + v.push_back(tmp); + } + break; + } + case RsGenericSerializer::SERIALIZE: + { + uint32_t n=v.size(); + serial_process(j,ctx,n,"temporary size"); + for(typename std::list::iterator it(v.begin());it!=v.end();++it) + serial_process(j,ctx,*it ,member_name); + break; + } + case RsGenericSerializer::PRINT: + { + if(v.empty()) std::cerr << " Empty list"<< std::endl; + else std::cerr << " List of " << v.size() << " elements:" + << std::endl; + break; + } + default: break; + } + } + + /// t_RsFlags32<> types + template + static void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + t_RsFlags32& v, + const std::string& /*member_name*/) + { + switch(j) + { + case RsGenericSerializer::SIZE_ESTIMATE: ctx.mOffset += 4; break; + case RsGenericSerializer::DESERIALIZE: + { + uint32_t n=0; + deserialize(ctx.mData,ctx.mSize,ctx.mOffset,n); + v = t_RsFlags32(n); + break; + } + case RsGenericSerializer::SERIALIZE: + { + uint32_t n=v.toUInt32(); + serialize(ctx.mData,ctx.mSize,ctx.mOffset,n); + break; + } + case RsGenericSerializer::PRINT: + std::cerr << " Flags of type " << std::hex << N << " : " + << v.toUInt32() << std::endl; + break; + } + } + +/** TODO + * Serialization format is inside context, but context is not passed to + * following functions, that need to know the format to do the job, actually + * RsGenericSerializer::FORMAT_BINARY is assumed in all of them!! + */ + +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); + + template static void print_data( + const std::string& name, const T& member); + + + template static bool serialize( + uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id, + const T& member ); + template static bool deserialize( + const uint8_t data[], uint32_t size, uint32_t &offset, + uint16_t type_id, T& member ); + template static uint32_t serial_size( + uint16_t type_id,const T& member ); + template static void print_data( + const std::string& name,uint16_t type_id,const T& member ); + + + template + static bool serialize( + uint8_t data[], uint32_t size, uint32_t &offset, + const t_RsGenericIdType& member ); + + template + static bool deserialize( + const uint8_t data[], uint32_t size, uint32_t &offset, + t_RsGenericIdType& member ); + + template + static uint32_t serial_size( + const t_RsGenericIdType& member ); + + template + static void print_data( + const std::string& name, + const t_RsGenericIdType& member ); + + + template + static bool serialize( + uint8_t data[], uint32_t size, uint32_t &offset, + const t_RsTlvList& member ); + + template + static bool deserialize( + const uint8_t data[], uint32_t size, uint32_t &offset, + t_RsTlvList& member ); + + template + static uint32_t serial_size(const t_RsTlvList& member); + + template + static void print_data( + const std::string& name, + const t_RsTlvList& member); +}; + + + +// t_RsGenericId<> +template +bool RsTypeSerializer::serialize ( + uint8_t data[], uint32_t size, uint32_t &offset, + const t_RsGenericIdType& member ) +{ return (*const_cast *>(&member)).serialise(data,size,offset); } template -bool RsTypeSerializer::serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsGenericIdType& member) -{ - return (*const_cast *>(&member)).serialise(data,size,offset) ; -} +bool RsTypeSerializer::deserialize( + const uint8_t data[], uint32_t size, uint32_t &offset, + t_RsGenericIdType& member ) +{ return member.deserialise(data,size,offset); } template -bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsGenericIdType& member) -{ - return member.deserialise(data,size,offset) ; -} +uint32_t RsTypeSerializer::serial_size( + const t_RsGenericIdType& member ) +{ return member.serial_size(); } template -uint32_t RsTypeSerializer::serial_size(const t_RsGenericIdType& member) +void RsTypeSerializer::print_data( + const std::string& /*name*/, + const t_RsGenericIdType& member ) { - return member.serial_size(); + std::cerr << " [RsGenericId<" << std::hex << UNIQUE_IDENTIFIER << ">] : " + << member << std::endl; } -template -void RsTypeSerializer::print_data(const std::string& /* name */,const t_RsGenericIdType& member) -{ - std::cerr << " [RsGenericId<" << std::hex << UNIQUE_IDENTIFIER << ">] : " << member << std::endl; -} - -//=================================================================================================// -// t_RsTlvList<> // -//=================================================================================================// +// t_RsTlvList<> template -bool RsTypeSerializer::serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsTlvList& member) +bool RsTypeSerializer::serialize( + uint8_t data[], uint32_t size, uint32_t &offset, + const t_RsTlvList& member ) { - return (*const_cast *>(&member)).SetTlv(data,size,&offset) ; + return (*const_cast *>(&member)).SetTlv(data,size,&offset); } template -bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsTlvList& member) +bool RsTypeSerializer::deserialize( + const uint8_t data[], uint32_t size, uint32_t &offset, + t_RsTlvList& member ) { - return member.GetTlv(const_cast(data),size,&offset) ; + return member.GetTlv(const_cast(data),size,&offset); } template -uint32_t RsTypeSerializer::serial_size(const t_RsTlvList& member) -{ - return member.TlvSize(); -} +uint32_t RsTypeSerializer::serial_size( + const t_RsTlvList& member) +{ return member.TlvSize(); } template -void RsTypeSerializer::print_data(const std::string& /* name */,const t_RsTlvList& member) +void RsTypeSerializer::print_data( + const std::string& /*name*/, + const t_RsTlvList& member) { - std::cerr << " [t_RsTlvString<" << std::hex << TLV_TYPE << ">] : size=" << member.mList.size() << std::endl; + std::cerr << " [t_RsTlvString<" << std::hex << TLV_TYPE << ">] : size=" + << member.mList.size() << std::endl; }