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; }