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())
{
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);
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<uint8_t*>(data),
dataSize );
RsChatMsgItem* item = static_cast<RsChatMsgItem*>(
_serializer->deserialise(
const_cast<uint8_t*>(data), &dataSize ));
RsPeerId rd(p3GxsTunnelService::makeGxsTunnelId(authorId, recipientId));
item->PeerId(rd);
handleRecvChatMsgItem(item);

View File

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

View File

@ -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<uint64_t, RsChatMsgItem> store;
};
struct RsChatSerialiser : RsServiceSerializer
{
RsChatSerialiser(SerializationFlags flags = SERIALIZATION_FLAG_NONE) :

View File

@ -478,14 +478,16 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId,
}
GxsTransSubServices rsrvc = static_cast<GxsTransSubServices>(csri);
RsNxsTransPresignedReceipt* receipt = new RsNxsTransPresignedReceipt();
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 "
<< "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<uint8_t> 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<uint16_t>(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<RsItem *>&loadList)
return true;
}

View File

@ -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<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() :
RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS,
static_cast<uint8_t>(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<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 "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<uint8_t> 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<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()
{
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<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;
}
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<uint8_t*>(data);
if ( (RS_PKT_VERSION_SERVICE != pktv) || // 0x02
(RS_SERVICE_TYPE_GXS_TRANS != srvc) || // 0x0230 = 560
(*size < rssize) )
switch(static_cast<GxsTransItemsSubtypes>(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<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 "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:

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,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") ;
RsTypeSerializer::serial_process<uint8_t> (j,ctx,pos ,"pos") ;
RsTypeSerializer::serial_process (j,ctx,msgId ,"msgId") ;
RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ;
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,msg ,"msg") ;
RsTypeSerializer::serial_process<RsTlvItem>(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<uint32_t> (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()

View File

@ -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

View File

@ -27,6 +27,8 @@
#include "serialiser/rsbaseserial.h"
#include "serialiser/rstlvkeys.h"
#include "rsitems/rsitem.h"
#include "util/rsprint.h"
#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;
}
//============================================================================//
// 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"
/** @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:
// 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<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) {}
};
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx );
//=================================================================================================//
// 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 */);
std::map<uint64_t, RsChatMsgItem> 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<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>
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) ;
}
bool RsTypeSerializer::deserialize(
const uint8_t data[], uint32_t size, uint32_t &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>
bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member)
{
return member.deserialise(data,size,offset) ;
}
uint32_t RsTypeSerializer::serial_size(
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member )
{ return member.serial_size(); }
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>
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>
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>
uint32_t RsTypeSerializer::serial_size(const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member)
{
return member.TlvSize();
}
uint32_t RsTypeSerializer::serial_size(
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member)
{ return member.TlvSize(); }
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;
}