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
This commit is contained in:
Gioacchino Mazzurco 2017-05-08 00:19:11 +02:00
parent f7f36f697e
commit ea8f800003
11 changed files with 655 additions and 728 deletions

View File

@ -346,9 +346,9 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
if(it != mDistantGxsMap.end()) if(it != mDistantGxsMap.end())
{ {
const DistantEndpoints& de(it->second); const DistantEndpoints& de(it->second);
uint32_t sz = ci->serial_size(); uint32_t sz = _serializer->size(ci);
std::vector<uint8_t> data; data.resize(sz); std::vector<uint8_t> data; data.resize(sz);
ci->serialise(&data[0], sz); _serializer->serialise(ci, &data[0], &sz);
mGxsTransport.sendMail(tId, GxsTransSubServices::P3_CHAT_SERVICE, mGxsTransport.sendMail(tId, GxsTransSubServices::P3_CHAT_SERVICE,
de.from, de.to, &data[0], sz); de.from, de.to, &data[0], sz);
} }
@ -717,8 +717,9 @@ bool p3ChatService::receiveGxsTransMail( const RsGxsId& authorId,
if(initiateDistantChatConnexion( if(initiateDistantChatConnexion(
authorId, recipientId, pid, error_code, false )) authorId, recipientId, pid, error_code, false ))
{ {
RsChatMsgItem* item = new RsChatMsgItem( const_cast<uint8_t*>(data), RsChatMsgItem* item = static_cast<RsChatMsgItem*>(
dataSize ); _serializer->deserialise(
const_cast<uint8_t*>(data), &dataSize ));
RsPeerId rd(p3GxsTunnelService::makeGxsTunnelId(authorId, recipientId)); RsPeerId rd(p3GxsTunnelService::makeGxsTunnelId(authorId, recipientId));
item->PeerId(rd); item->PeerId(rd);
handleRecvChatMsgItem(item); handleRecvChatMsgItem(item);

View File

@ -195,4 +195,11 @@ void RsPrivateChatMsgConfigItem::get(RsChatMsgItem *ci)
ci->recvTime = recvTime; 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); }

View File

@ -325,6 +325,17 @@ class RsChatAvatarItem: public RsChatItem
unsigned char *image_data ; // image 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<uint64_t, RsChatMsgItem> store;
};
struct RsChatSerialiser : RsServiceSerializer struct RsChatSerialiser : RsServiceSerializer
{ {
RsChatSerialiser(SerializationFlags flags = SERIALIZATION_FLAG_NONE) : RsChatSerialiser(SerializationFlags flags = SERIALIZATION_FLAG_NONE) :

View File

@ -478,14 +478,16 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId,
} }
GxsTransSubServices rsrvc = static_cast<GxsTransSubServices>(csri); GxsTransSubServices rsrvc = static_cast<GxsTransSubServices>(csri);
RsNxsTransPresignedReceipt* receipt = new RsNxsTransPresignedReceipt();
uint32_t rcptsize = decrypted_data_size; uint32_t rcptsize = decrypted_data_size;
if(!receipt->deserialize(decrypted_data, rcptsize, offset)) RsNxsTransPresignedReceipt* receipt =
static_cast<RsNxsTransPresignedReceipt*>(
RsGxsTransSerializer().deserialise(
const_cast<uint8_t*>(decrypted_data), &rcptsize ) );
if(!receipt)
{ {
std::cerr << "p3GxsTrans::dispatchDecryptedMail(...) (EE) fatal error " std::cerr << "p3GxsTrans::dispatchDecryptedMail(...) (EE) fatal error "
<< "deserializing presigned return receipt , something really" << "deserializing presigned return receipt , something really"
<< " wrong is happening!" << std::endl; << " wrong is happening!" << std::endl;
delete receipt;
return false; return false;
} }
std::cout << "p3GxsTrans::dispatchDecryptedMail(...) dispatching receipt " std::cout << "p3GxsTrans::dispatchDecryptedMail(...) dispatching receipt "
@ -541,10 +543,10 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
grcpt.meta = pr.mailItem.meta; grcpt.meta = pr.mailItem.meta;
grcpt.meta.mPublishTs = time(NULL); grcpt.meta.mPublishTs = time(NULL);
grcpt.mailId = pr.mailItem.mailId; grcpt.mailId = pr.mailItem.mailId;
uint32_t groff = 0, grsz = grcpt.serial_size(); uint32_t grsz = RsGxsTransSerializer().size(&grcpt);
std::vector<uint8_t> grsrz; std::vector<uint8_t> grsrz;
grsrz.resize(grsz); grsrz.resize(grsz);
grcpt.serialize(&grsrz[0], grsz, groff); RsGxsTransSerializer().serialise(&grcpt, &grsrz[0], &grsz);
pr.presignedReceipt.grpId = mPreferredGroupId; pr.presignedReceipt.grpId = mPreferredGroupId;
pr.presignedReceipt.metaData = new RsGxsMsgMetaData(); pr.presignedReceipt.metaData = new RsGxsMsgMetaData();
@ -572,13 +574,14 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
case GxsTransSendStatus::PENDING_PAYLOAD_CREATE: case GxsTransSendStatus::PENDING_PAYLOAD_CREATE:
{ {
uint16_t serv = static_cast<uint16_t>(pr.clientService); uint16_t serv = static_cast<uint16_t>(pr.clientService);
uint32_t rcptsize = pr.presignedReceipt.serial_size(); uint32_t rcptsize = RsGxsTransSerializer().size(&pr.presignedReceipt);
uint32_t datasize = pr.mailData.size(); uint32_t datasize = pr.mailData.size();
pr.mailItem.payload.resize(2 + rcptsize + datasize); pr.mailItem.payload.resize(2 + rcptsize + datasize);
uint32_t offset = 0; uint32_t offset = 0;
setRawUInt16(&pr.mailItem.payload[0], 2, &offset, serv); setRawUInt16(&pr.mailItem.payload[0], 2, &offset, serv);
pr.presignedReceipt.serialise( &pr.mailItem.payload[offset], RsGxsTransSerializer().serialise(&pr.presignedReceipt,
rcptsize ); &pr.mailItem.payload[offset],
&rcptsize);
offset += rcptsize; offset += rcptsize;
memcpy(&pr.mailItem.payload[offset], &pr.mailData[0], datasize); memcpy(&pr.mailItem.payload[offset], &pr.mailData[0], datasize);
} }
@ -781,4 +784,3 @@ bool p3GxsTrans::loadList(std::list<RsItem *>&loadList)
return true; return true;
} }

View File

@ -17,88 +17,14 @@
*/ */
#include "gxstrans/p3gxstransitems.h" #include "gxstrans/p3gxstransitems.h"
#include "serialiser/rstypeserializer.h"
const RsGxsId RsGxsTransMailItem::allRecipientsHint("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); const RsGxsId RsGxsTransMailItem::allRecipientsHint("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
OutgoingRecord::OutgoingRecord() :
bool RsGxsTransBaseItem::serialize(uint8_t* data, uint32_t size, RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS,
uint32_t& offset) const static_cast<uint8_t>(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) )
{ { clear();}
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<uint8_t*>(data+offset);
uint32_t rssize = getRsItemSize(hdrPtr);
uint32_t roffset = offset + 8; // Take header in account
void* dataPtr = const_cast<uint8_t*>(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<uint8_t*>(data);
bool ok = false;
switch(static_cast<GxsTransItemsSubtypes>(item->PacketSubType()))
{
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL:
{
uint32_t offset = 0;
RsGxsTransMailItem* i = dynamic_cast<RsGxsTransMailItem*>(item);
ok = i && i->serialize(dataPtr, itemSize, offset);
break;
}
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT:
{
RsGxsTransPresignedReceipt* i =
dynamic_cast<RsGxsTransPresignedReceipt*>(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<OutgoingRecord*>(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( RsGxsId rec, GxsTransSubServices cs, OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs,
const uint8_t* data, uint32_t size ) : const uint8_t* data, uint32_t size ) :
@ -111,102 +37,17 @@ OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs,
memcpy(&mailData[0], data, size); 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; RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t);
recipient.clear(); RS_REGISTER_SERIAL_MEMBER(recipient);
mailItem.clear(); RS_REGISTER_SERIAL_MEMBER(mailItem);
mailData.clear(); RS_REGISTER_SERIAL_MEMBER(mailData);
clientService = GxsTransSubServices::UNKNOWN; RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t);
presignedReceipt.clear(); 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<uint8_t>(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<uint8_t>(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<uint16_t>(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<uint8_t*>(data);
offset += 8; // Header
uint8_t tmpStatus = 0;
ok = ok && getRawUInt8(dataPtr, size, &offset, &tmpStatus);
status = static_cast<GxsTransSendStatus>(tmpStatus);
uint32_t tmpSize = size;
ok = ok && recipient.deserialise(dataPtr, tmpSize, offset);
void* hdrPtr = const_cast<uint8_t*>(data+offset);
tmpSize = getRsItemSize(hdrPtr);
uint32_t tmpOffset = 0;
ok = ok && mailItem.deserialize(static_cast<uint8_t*>(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<GxsTransSubServices>(cs);
tmpSize = size;
ok = ok && presignedReceipt.deserialize(data, tmpSize, offset);
return ok;
}

View File

@ -19,12 +19,13 @@
#include <string> #include <string>
#include "serialiser/rsgxsitems.h" #include "rsitems/rsgxsitems.h"
#include "serialiser/rsbaseserial.h" #include "serialiser/rsbaseserial.h"
#include "serialiser/rstlvidset.h" #include "serialiser/rstlvidset.h"
#include "retroshare/rsgxsflags.h" #include "retroshare/rsgxsflags.h"
#include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC #include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC
#include "services/p3idservice.h" #include "services/p3idservice.h"
#include "serialiser/rstypeserializer.h"
/// Subservices identifiers (like port for TCP) /// Subservices identifiers (like port for TCP)
enum class GxsTransSubServices : uint16_t enum class GxsTransSubServices : uint16_t
@ -65,14 +66,9 @@ struct RsGxsTransBaseItem : RsGxsMsgItem
meta = RsMsgMetaData(); meta = RsMsgMetaData();
} }
static uint32_t inline serial_size() void serial_process( RsGenericSerializer::SerializeJob j,
{ RsGenericSerializer::SerializeContext& ctx )
return 8 + // Header { RS_REGISTER_SERIAL_MEMBER_TYPED(mailId, uint64_t); }
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*/);
}; };
struct RsGxsTransPresignedReceipt : RsGxsTransBaseItem struct RsGxsTransPresignedReceipt : RsGxsTransBaseItem
@ -149,46 +145,15 @@ struct RsGxsTransMailItem : RsGxsTransBaseItem
* is specified */ * is specified */
std::vector<uint8_t> payload; std::vector<uint8_t> payload;
uint32_t serial_size() const void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{ {
return RsGxsTransBaseItem::serial_size() + RsGxsTransBaseItem::serial_process(j, ctx);
1 + // cryptoType RS_REGISTER_SERIAL_MEMBER_TYPED(cryptoType, uint8_t);
recipientHint.serial_size() + RS_REGISTER_SERIAL_MEMBER(recipientHint);
payload.size(); 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<uint8_t>(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<uint8_t*>(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<uint8_t*>(data);
uint8_t crType;
ok = ok && getRawUInt8(dataPtr, rssize, &roffset, &crType);
cryptoType = static_cast<RsGxsTransEncryptionMode>(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() void clear()
{ {
RsGxsTransBaseItem::clear(); RsGxsTransBaseItem::clear();
@ -213,6 +178,11 @@ struct RsGxsTransGroupItem : RsGxsGrpItem
meta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; 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() {} void clear() {}
std::ostream &print(std::ostream &out, uint16_t /*indent = 0*/) std::ostream &print(std::ostream &out, uint16_t /*indent = 0*/)
{ return out; } { return out; }
@ -253,12 +223,10 @@ struct OutgoingRecord : RsItem
GxsTransSubServices clientService; GxsTransSubServices clientService;
RsNxsTransPresignedReceipt presignedReceipt; RsNxsTransPresignedReceipt presignedReceipt;
uint32_t serial_size() const; void serial_process( RsGenericSerializer::SerializeJob j,
bool serialize(uint8_t* data, uint32_t size, uint32_t& offset) const; RsGenericSerializer::SerializeContext& ctx );
bool deserialize(const uint8_t* data, uint32_t& size, uint32_t& offset);
virtual void clear(); void clear() {}
virtual std::ostream &print(std::ostream &out, uint16_t indent = 0);
private: private:
friend class RsGxsTransSerializer; friend class RsGxsTransSerializer;
@ -266,100 +234,23 @@ private:
}; };
struct RsGxsTransSerializer : RsSerialType struct RsGxsTransSerializer : public RsServiceSerializer
{ {
RsGxsTransSerializer() : RsSerialType( RS_PKT_VERSION_SERVICE, RsGxsTransSerializer() : RsServiceSerializer(RS_SERVICE_TYPE_GXS_TRANS) {}
RS_SERVICE_TYPE_GXS_TRANS ) {}
~RsGxsTransSerializer() {} ~RsGxsTransSerializer() {}
uint32_t size(RsItem* item) RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const
{ {
uint32_t sz = 0; if(service_id != RS_SERVICE_TYPE_GXS_TRANS) return NULL;
switch(static_cast<GxsTransItemsSubtypes>(item->PacketSubType()))
{
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL:
{
RsGxsTransMailItem* i = dynamic_cast<RsGxsTransMailItem*>(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<OutgoingRecord*>(item);
if(ci) sz = ci->serial_size();
break;
}
default: break;
}
return sz; switch(static_cast<GxsTransItemsSubtypes>(item_sub_id))
}
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<uint8_t*>(data);
if ( (RS_PKT_VERSION_SERVICE != pktv) || // 0x02
(RS_SERVICE_TYPE_GXS_TRANS != srvc) || // 0x0230 = 560
(*size < rssize) )
{ {
print_stacktrace(); case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: return new RsGxsTransMailItem();
return NULL; 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<GxsTransItemsSubtypes>(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;
} }
}; };

View File

@ -3,6 +3,7 @@
#include "util/smallobject.h" #include "util/smallobject.h"
#include "retroshare/rstypes.h" #include "retroshare/rstypes.h"
#include "serialiser/rsserializer.h" #include "serialiser/rsserializer.h"
#include "util/stacktrace.h"
class RsItem: public RsMemoryManagement::SmallObject class RsItem: public RsMemoryManagement::SmallObject
{ {
@ -15,6 +16,8 @@ class RsItem: public RsMemoryManagement::SmallObject
#endif #endif
virtual ~RsItem(); virtual ~RsItem();
/// TODO: Do this make sense with the new serialization system?
virtual void clear() = 0; virtual void clear() = 0;
virtual std::ostream &print(std::ostream &out, uint16_t /* indent */ = 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 ;} inline void setPriorityLevel(uint8_t l) { _priority_level = l ;}
/** /**
* @brief serialize this object to the given buffer * TODO: This should be made pure virtual as soon as all the codebase
* @param Job to do: serialise or deserialize. * is ported to the new serialization system
* @param data Chunk of memory were to dump the serialized data
* @param size Size of memory chunk
* @param offset Readed to determine at witch offset start writing data,
* written to inform caller were written data ends, the updated value
* is usually passed by the caller to serialize of another
* RsSerializable so it can write on the same chunk of memory just
* after where this RsSerializable has been serialized.
* @return true if serialization successed, false otherwise
*/ */
virtual void serial_process(RsGenericSerializer::SerializeJob,
virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) 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: protected:
@ -71,6 +69,7 @@ class RsItem: public RsMemoryManagement::SmallObject
uint8_t _priority_level ; uint8_t _priority_level ;
}; };
/// TODO: Do this make sense with the new serialization system?
class RsRawItem: public RsItem class RsRawItem: public RsItem
{ {
public: public:

View File

@ -69,15 +69,18 @@ void RsNxsSyncMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGene
RsTypeSerializer::serial_process (j,ctx,msgId ,"msgId") ; RsTypeSerializer::serial_process (j,ctx,msgId ,"msgId") ;
RsTypeSerializer::serial_process (j,ctx,authorId ,"authorId") ; 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<uint32_t> (j,ctx,transactionNumber,"transactionNumber") ; RS_REGISTER_SERIAL_MEMBER_TYPED(transactionNumber, uint32_t);
RsTypeSerializer::serial_process<uint8_t> (j,ctx,pos ,"pos") ; RS_REGISTER_SERIAL_MEMBER_TYPED(pos, uint8_t);
RsTypeSerializer::serial_process (j,ctx,msgId ,"msgId") ; RS_REGISTER_SERIAL_MEMBER(msgId);
RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; RS_REGISTER_SERIAL_MEMBER(grpId);
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,msg ,"msg") ; RS_REGISTER_SERIAL_MEMBER_TYPED(msg, RsTlvItem);
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,meta ,"meta") ; RS_REGISTER_SERIAL_MEMBER_TYPED(meta, RsTlvItem);
} }
void RsNxsGrp::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) void RsNxsGrp::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
{ {
RsTypeSerializer::serial_process<uint32_t> (j,ctx,transactionNumber,"transactionNumber") ; RsTypeSerializer::serial_process<uint32_t> (j,ctx,transactionNumber,"transactionNumber") ;
@ -149,11 +152,14 @@ void RsNxsMsg::clear()
meta.TlvClear(); meta.TlvClear();
} }
std::ostream&RsNxsMsg::print(std::ostream& out, uint16_t /*indent*/)
{ return out; }
void RsNxsGrp::clear() void RsNxsGrp::clear()
{ {
grpId.clear(); grpId.clear();
grp.TlvClear(); grp.TlvClear();
meta.TlvClear(); meta.TlvClear();
} }
void RsNxsSyncGrpReqItem::clear() void RsNxsSyncGrpReqItem::clear()

View File

@ -376,7 +376,7 @@ struct RsNxsMsg : RsNxsItem
RsGenericSerializer::SerializeContext& ctx ); RsGenericSerializer::SerializeContext& ctx );
virtual void clear(); 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 pos; /// used for splitting up msg
uint8_t count; /// number of split up messages uint8_t count; /// number of split up messages

View File

@ -27,6 +27,8 @@
#include "serialiser/rsbaseserial.h" #include "serialiser/rsbaseserial.h"
#include "serialiser/rstlvkeys.h" #include "serialiser/rstlvkeys.h"
#include "rsitems/rsitem.h"
#include "util/rsprint.h" #include "util/rsprint.h"
#include <iomanip> #include <iomanip>
@ -306,3 +308,57 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const RsTlvIt
std::cerr << " [" << typeid(s).name() << "] " << n << std::endl; 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<RsItem&>(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<RsItem&>(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<uint8_t*>(data), size,
RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
ctx.mOffset = offset;
const_cast<RsItem&>(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<RsItem&>(s).serial_process(RsGenericSerializer::PRINT,
ctx);
}

View File

@ -33,409 +33,522 @@
#include "serialiser/rsserializer.h" #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<T>(j, ctx, reinterpret_cast<T&>(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<uint64_t, RsChatMsgItem>`
*
* @code{.cpp}
struct PrivateOugoingMapItem : RsChatItem
{ {
public: PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {}
// This type should be used to pass a parameter to drive the serialisation if needed.
struct TlvMemBlock_proxy: public std::pair<void*& ,uint32_t&> void serial_process( RsGenericSerializer::SerializeJob j,
{ RsGenericSerializer::SerializeContext& ctx );
TlvMemBlock_proxy(void *& p,uint32_t& s) : std::pair<void*&,uint32_t&>(p,s) {}
TlvMemBlock_proxy(uint8_t*& p,uint32_t& s) : std::pair<void*&,uint32_t&>(*(void**)&p,s) {}
};
//=================================================================================================// std::map<uint64_t, RsChatMsgItem> store;
// Generic types //
//=================================================================================================//
template<typename T>
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<typename T>
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<T,U> //
//=================================================================================================//
template<typename T,typename U>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::map<T,U>& v,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4 ;
for(typename std::map<T,U>::iterator it(v.begin());it!=v.end();++it)
{
serial_process(j,ctx,const_cast<T&>(it->first),"map::*it->first") ;
serial_process(j,ctx,const_cast<U&>(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;i<n;++i)
{
T t ;
U u ;
serial_process(j,ctx,t,"map::*it->first") ;
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<T,U>::iterator it(v.begin());it!=v.end();++it)
{
serial_process(j,ctx,const_cast<T&>(it->first),"map::*it->first") ;
serial_process(j,ctx,const_cast<U&>(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<T,U>::iterator it(v.begin());it!=v.end();++it)
{
std::cerr << " " ;
serial_process(j,ctx,const_cast<T&>(it->first),"map::*it->first") ;
serial_process(j,ctx,const_cast<U&>(it->second),"map::*it->second") ;
}
}
break;
default:
break;
}
}
//=================================================================================================//
// std::vector<T> //
//=================================================================================================//
template<typename T>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::vector<T>& v,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4 ;
for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name) ;
}
break ;
case RsGenericSerializer::DESERIALIZE:
{ uint32_t n=0 ;
serial_process(j,ctx,n,"temporary size") ;
v.resize(n) ;
for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name) ;
}
break ;
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size") ;
for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name) ;
}
break ;
case RsGenericSerializer::PRINT:
{
if(v.empty())
std::cerr << " Empty array"<< std::endl;
else
std::cerr << " Array of " << v.size() << " elements:" << std::endl;
for(uint32_t i=0;i<v.size();++i)
{
std::cerr << " " ;
serial_process(j,ctx,v[i],member_name) ;
}
}
break;
default:
break;
}
}
//=================================================================================================//
// std::set<T> //
//=================================================================================================//
template<typename T>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::set<T>& v,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4 ;
for(typename std::set<T>::iterator it(v.begin());it!=v.end();++it)
serial_process(j,ctx,const_cast<T&>(*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<n;++i)
{
T tmp;
serial_process<T>(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<T>::iterator it(v.begin());it!=v.end();++it)
serial_process(j,ctx,const_cast<T&>(*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<T> //
//=================================================================================================//
template<typename T>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::list<T>& v,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4 ;
for(typename std::list<T>::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<n;++i)
{
T tmp;
serial_process<T>(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<T>::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<int N>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,t_RsFlags32<N>& v,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE: ctx.mOffset += 4 ;
break ;
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0 ;
deserialize<uint32_t>(ctx.mData,ctx.mSize,ctx.mOffset,n) ;
v = t_RsFlags32<N>(n) ;
}
break ;
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.toUInt32() ;
serialize<uint32_t>(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<typename T> static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, const T& member);
template<typename T> static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, T& member);
template<typename T> static uint32_t serial_size(const T& /* member */);
template<typename T> static void print_data(const std::string& name,const T& /* member */);
template<typename T> static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id,const T& member);
template<typename T> static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset,uint16_t type_id, T& member);
template<typename T> static uint32_t serial_size(uint16_t type_id,const T& /* member */);
template<typename T> static void print_data(const std::string& name,uint16_t type_id,const T& /* member */);
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member);
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member);
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> static uint32_t serial_size(const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& /* member */);
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> static void print_data(const std::string& name,const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& /* member */);
template<class TLV_CLASS,uint32_t TLV_TYPE> static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member);
template<class TLV_CLASS,uint32_t TLV_TYPE> static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsTlvList<TLV_CLASS,TLV_TYPE>& member);
template<class TLV_CLASS,uint32_t TLV_TYPE> static uint32_t serial_size(const t_RsTlvList<TLV_CLASS,TLV_TYPE>& /* member */);
template<class TLV_CLASS,uint32_t TLV_TYPE> static void print_data(const std::string& name,const t_RsTlvList<TLV_CLASS,TLV_TYPE>& /* member */);
}; };
//=================================================================================================// RS_REGISTER_ITEM_TYPE(RsChatMsgItem)
// t_RsGenericId<> //
//=================================================================================================// 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<T>( \
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<void*&,uint32_t&>
{
TlvMemBlock_proxy(void*& p, uint32_t& s) :
std::pair<void*&,uint32_t&>(p,s) {}
TlvMemBlock_proxy(uint8_t*& p,uint32_t& s) :
std::pair<void*&,uint32_t&>(*(void**)&p,s) {}
};
/// Generic types
template<typename T>
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<typename T>
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<T,U>
template<typename T,typename U>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
std::map<T,U>& v,
const std::string& member_name )
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4;
for(typename std::map<T,U>::iterator it(v.begin());it!=v.end();++it)
{
serial_process( j, ctx, const_cast<T&>(it->first),
"map::*it->first" );
serial_process( j,ctx,const_cast<U&>(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; i<n; ++i)
{
T t; U u;
serial_process(j, ctx, t, "map::*it->first");
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<T,U>::iterator it(v.begin());it!=v.end();++it)
{
serial_process( j, ctx, const_cast<T&>(it->first),
"map::*it->first" );
serial_process( j, ctx, const_cast<U&>(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<T,U>::iterator it(v.begin());it!=v.end();++it)
{
std::cerr << " ";
serial_process( j, ctx,const_cast<T&>(it->first),
"map::*it->first" );
serial_process( j, ctx, const_cast<U&>(it->second),
"map::*it->second" );
}
break;
}
default: break;
}
}
/// std::vector<T>
template<typename T>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
std::vector<T>& v,
const std::string& member_name )
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4;
for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name);
break;
}
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0;
serial_process(j,ctx,n,"temporary size");
v.resize(n);
for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name);
break;
}
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size");
for(uint32_t i=0; i<v.size(); ++i)
serial_process(j,ctx,v[i],member_name);
break;
}
case RsGenericSerializer::PRINT:
{
if(v.empty())
std::cerr << " Empty array"<< std::endl;
else
std::cerr << " Array of " << v.size() << " elements:"
<< std::endl;
for(uint32_t i=0;i<v.size();++i)
{
std::cerr << " " ;
serial_process(j,ctx,v[i],member_name);
}
break;
}
default: break;
}
}
/// std::set<T>
template<typename T>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
std::set<T>& v, const std::string& member_name )
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4;
for(typename std::set<T>::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<T&>(*it) ,member_name);
break;
}
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0;
serial_process(j,ctx,n,"temporary size");
for(uint32_t i=0; i<n; ++i)
{
T tmp;
serial_process<T>(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<T>::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<T&>(*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<T>
template<typename T>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
std::list<T>& v,
const std::string& member_name )
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4;
for(typename std::list<T>::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<n;++i)
{
T tmp;
serial_process<T>(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<T>::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<int N>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
t_RsFlags32<N>& v,
const std::string& /*member_name*/)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE: ctx.mOffset += 4; break;
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0;
deserialize<uint32_t>(ctx.mData,ctx.mSize,ctx.mOffset,n);
v = t_RsFlags32<N>(n);
break;
}
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.toUInt32();
serialize<uint32_t>(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<typename T> static bool serialize(
uint8_t data[], uint32_t size, uint32_t &offset, const T& member );
template<typename T> static bool deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset, T& member);
template<typename T> static uint32_t serial_size(const T& member);
template<typename T> static void print_data(
const std::string& name, const T& member);
template<typename T> static bool serialize(
uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id,
const T& member );
template<typename T> static bool deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset,
uint16_t type_id, T& member );
template<typename T> static uint32_t serial_size(
uint16_t type_id,const T& member );
template<typename T> static void print_data(
const std::string& name,uint16_t type_id,const T& member );
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
static bool serialize(
uint8_t data[], uint32_t size, uint32_t &offset,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member );
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
static bool deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset,
t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member );
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
static uint32_t serial_size(
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member );
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
static void print_data(
const std::string& name,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member );
template<class TLV_CLASS,uint32_t TLV_TYPE>
static bool serialize(
uint8_t data[], uint32_t size, uint32_t &offset,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member );
template<class TLV_CLASS,uint32_t TLV_TYPE>
static bool deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset,
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member );
template<class TLV_CLASS,uint32_t TLV_TYPE>
static uint32_t serial_size(const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member);
template<class TLV_CLASS,uint32_t TLV_TYPE>
static void print_data(
const std::string& name,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member);
};
// t_RsGenericId<>
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
bool RsTypeSerializer::serialize (
uint8_t data[], uint32_t size, uint32_t &offset,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member )
{ return (*const_cast<const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER> *>(&member)).serialise(data,size,offset); }
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
bool RsTypeSerializer::serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member) bool RsTypeSerializer::deserialize(
{ const uint8_t data[], uint32_t size, uint32_t &offset,
return (*const_cast<const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER> *>(&member)).serialise(data,size,offset) ; t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member )
} { return member.deserialise(data,size,offset); }
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member) uint32_t RsTypeSerializer::serial_size(
{ const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member )
return member.deserialise(data,size,offset) ; { return member.serial_size(); }
}
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
uint32_t RsTypeSerializer::serial_size(const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member) void RsTypeSerializer::print_data(
const std::string& /*name*/,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member )
{ {
return member.serial_size(); std::cerr << " [RsGenericId<" << std::hex << UNIQUE_IDENTIFIER << ">] : "
<< member << std::endl;
} }
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
void RsTypeSerializer::print_data(const std::string& /* name */,const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member)
{
std::cerr << " [RsGenericId<" << std::hex << UNIQUE_IDENTIFIER << ">] : " << member << std::endl;
}
//=================================================================================================//
// t_RsTlvList<> //
//=================================================================================================//
// t_RsTlvList<>
template<class TLV_CLASS,uint32_t TLV_TYPE> template<class TLV_CLASS,uint32_t TLV_TYPE>
bool RsTypeSerializer::serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member) bool RsTypeSerializer::serialize(
uint8_t data[], uint32_t size, uint32_t &offset,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member )
{ {
return (*const_cast<const t_RsTlvList<TLV_CLASS,TLV_TYPE> *>(&member)).SetTlv(data,size,&offset) ; return (*const_cast<const t_RsTlvList<TLV_CLASS,TLV_TYPE> *>(&member)).SetTlv(data,size,&offset);
} }
template<class TLV_CLASS,uint32_t TLV_TYPE> template<class TLV_CLASS,uint32_t TLV_TYPE>
bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsTlvList<TLV_CLASS,TLV_TYPE>& member) bool RsTypeSerializer::deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset,
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member )
{ {
return member.GetTlv(const_cast<uint8_t*>(data),size,&offset) ; return member.GetTlv(const_cast<uint8_t*>(data),size,&offset);
} }
template<class TLV_CLASS,uint32_t TLV_TYPE> template<class TLV_CLASS,uint32_t TLV_TYPE>
uint32_t RsTypeSerializer::serial_size(const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member) uint32_t RsTypeSerializer::serial_size(
{ const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member)
return member.TlvSize(); { return member.TlvSize(); }
}
template<class TLV_CLASS,uint32_t TLV_TYPE> template<class TLV_CLASS,uint32_t TLV_TYPE>
void RsTypeSerializer::print_data(const std::string& /* name */,const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member) void RsTypeSerializer::print_data(
const std::string& /*name*/,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& 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;
} }