Add automatic JSON serialization/deserialization

Abstract serialization concept to pure virtaul class RsSerializable
  from which every other serializable class must inherit from
Use RapidJSON for JSON manipulation
Add TO_JSON and FROM_JSON SerializeJob
Deprecate unused SerializationFormat
Remove some unused old piece of code
Adjust many lines to max 80 columns for better readability on little
  screens
Clean up documentation and code, remove old cruft
Add copyright notice on edited files that miss it
This commit is contained in:
Gioacchino Mazzurco 2018-01-16 03:31:03 +01:00
parent 49cacc41a1
commit 5cdc5aa58d
12 changed files with 1384 additions and 405 deletions

View File

@ -207,7 +207,7 @@ void RsPrivateChatMsgConfigItem::get(RsChatMsgItem *ci)
/* Necessary to serialize `store` that is an STL container with RsChatMsgItem /* Necessary to serialize `store` that is an STL container with RsChatMsgItem
* inside which is a subtype of RsItem */ * inside which is a subtype of RsItem */
RS_REGISTER_ITEM_TYPE(RsChatMsgItem) RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsChatMsgItem)
void PrivateOugoingMapItem::serial_process( void PrivateOugoingMapItem::serial_process(
RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeJob j,

View File

@ -1,6 +1,6 @@
/* /*
* GXS Mailing Service * GXS Mailing Service
* Copyright (C) 2016-2017 Gioacchino Mazzurco <gio@eigenlab.org> * Copyright (C) 2016-2018 Gioacchino Mazzurco <gio@eigenlab.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@ -38,11 +38,15 @@ OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs,
memcpy(&mailData[0], data, size); memcpy(&mailData[0], data, size);
} }
// for mailItem
RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsGxsTransMailItem)
RS_REGISTER_ITEM_TYPE(RsGxsTransMailItem) // for mailItem // for presignedReceipt
RS_REGISTER_ITEM_TYPE(RsNxsTransPresignedReceipt) // for presignedReceipt RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsNxsTransPresignedReceipt)
void OutgoingRecord_deprecated::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) void OutgoingRecord_deprecated::serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{ {
RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t); RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t);
RS_REGISTER_SERIAL_MEMBER(recipient); RS_REGISTER_SERIAL_MEMBER(recipient);

View File

@ -648,6 +648,7 @@ SOURCES += serialiser/rsbaseserial.cc \
rsitems/rsgxsupdateitems.cc \ rsitems/rsgxsupdateitems.cc \
rsitems/rsserviceinfoitems.cc \ rsitems/rsserviceinfoitems.cc \
SOURCES += services/autoproxy/rsautoproxymonitor.cc \ SOURCES += services/autoproxy/rsautoproxymonitor.cc \
services/autoproxy/p3i2pbob.cc \ services/autoproxy/p3i2pbob.cc \
services/p3msgservice.cc \ services/p3msgservice.cc \
@ -786,7 +787,8 @@ SOURCES += gxstunnel/p3gxstunnel.cc \
gxstunnel/rsgxstunnelitems.cc gxstunnel/rsgxstunnelitems.cc
# new serialization code # new serialization code
HEADERS += serialiser/rsserializer.h \ HEADERS += serialiser/rsserializable.h \
serialiser/rsserializer.h \
serialiser/rstypeserializer.h serialiser/rstypeserializer.h
SOURCES += serialiser/rsserializer.cc \ SOURCES += serialiser/rsserializer.cc \

View File

@ -1,3 +1,23 @@
/*
* rsgxsifacetypes.h
*
* Copyright (C) 2013 crispy
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* /*
* rsgxsifacetypes.h * rsgxsifacetypes.h
* *
@ -13,8 +33,10 @@
#include <string> #include <string>
#include <inttypes.h> #include <inttypes.h>
#include <retroshare/rstypes.h> #include "retroshare/rstypes.h"
#include <retroshare/rsids.h> #include "retroshare/rsids.h"
#include "serialiser/rsserializable.h"
#include "serialiser/rstypeserializer.h"
typedef GXSGroupId RsGxsGroupId; typedef GXSGroupId RsGxsGroupId;
typedef Sha1CheckSum RsGxsMessageId; typedef Sha1CheckSum RsGxsMessageId;
@ -34,7 +56,7 @@ typedef std::map<RsGxsGroupId, std::vector<RsMsgMetaData> > MsgMetaResult;
class RsGxsGrpMetaData; class RsGxsGrpMetaData;
class RsGxsMsgMetaData; class RsGxsMsgMetaData;
struct RsGroupMetaData struct RsGroupMetaData : RsSerializable
{ {
// (csoler) The correct default value to be used in mCircleType is GXS_CIRCLE_TYPE_PUBLIC, which is defined in rsgxscircles.h, // (csoler) The correct default value to be used in mCircleType is GXS_CIRCLE_TYPE_PUBLIC, which is defined in rsgxscircles.h,
// but because of a loop in the includes, I cannot include it here. So I replaced with its current value 0x0001. // but because of a loop in the includes, I cannot include it here. So I replaced with its current value 0x0001.
@ -73,6 +95,30 @@ struct RsGroupMetaData
std::string mServiceString; // Service Specific Free-Form extra storage. std::string mServiceString; // Service Specific Free-Form extra storage.
RsPeerId mOriginator; RsPeerId mOriginator;
RsGxsCircleId mInternalCircle; RsGxsCircleId mInternalCircle;
/// @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
RS_REGISTER_SERIAL_MEMBER(mGroupId);
RS_REGISTER_SERIAL_MEMBER(mGroupName);
RS_REGISTER_SERIAL_MEMBER(mGroupFlags);
RS_REGISTER_SERIAL_MEMBER(mSignFlags);
RS_REGISTER_SERIAL_MEMBER(mPublishTs);
RS_REGISTER_SERIAL_MEMBER(mAuthorId);
RS_REGISTER_SERIAL_MEMBER(mCircleId);
RS_REGISTER_SERIAL_MEMBER(mCircleType);
RS_REGISTER_SERIAL_MEMBER(mAuthenFlags);
RS_REGISTER_SERIAL_MEMBER(mParentGrpId);
RS_REGISTER_SERIAL_MEMBER(mSubscribeFlags);
RS_REGISTER_SERIAL_MEMBER(mPop);
RS_REGISTER_SERIAL_MEMBER(mVisibleMsgCount);
RS_REGISTER_SERIAL_MEMBER(mLastPost);
RS_REGISTER_SERIAL_MEMBER(mGroupStatus);
RS_REGISTER_SERIAL_MEMBER(mServiceString);
RS_REGISTER_SERIAL_MEMBER(mOriginator);
RS_REGISTER_SERIAL_MEMBER(mInternalCircle);
}
}; };

View File

@ -6,7 +6,8 @@
* *
* RetroShare C++ Interface. * RetroShare C++ Interface.
* *
* Copyright 2012-2012 by Robert Fernie. * Copyright (C) 2012 Robert Fernie.
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -36,6 +37,9 @@
#include "retroshare/rsids.h" #include "retroshare/rsids.h"
#include "serialiser/rstlvimage.h" #include "serialiser/rstlvimage.h"
#include "retroshare/rsgxscommon.h" #include "retroshare/rsgxscommon.h"
#include "serialiser/rsserializable.h"
#include "serialiser/rstypeserializer.h"
#include "util/rsdeprecate.h"
/* The Main Interface Class - for information about your Peers */ /* The Main Interface Class - for information about your Peers */
class RsIdentity; class RsIdentity;
@ -63,6 +67,7 @@ extern RsIdentity *rsIdentity;
#define RSID_RELATION_OTHER 0x0008 #define RSID_RELATION_OTHER 0x0008
#define RSID_RELATION_UNKNOWN 0x0010 #define RSID_RELATION_UNKNOWN 0x0010
/// @deprecated remove toghether with RsGxsIdGroup::mRecognTags
#define RSRECOGN_MAX_TAGINFO 5 #define RSRECOGN_MAX_TAGINFO 5
// Unicode symbols. NOT utf-8 bytes, because of multi byte characters // Unicode symbols. NOT utf-8 bytes, because of multi byte characters
@ -77,27 +82,36 @@ static const uint32_t RS_IDENTITY_FLAGS_PGP_KNOWN = 0x0004;
static const uint32_t RS_IDENTITY_FLAGS_IS_OWN_ID = 0x0008; static const uint32_t RS_IDENTITY_FLAGS_IS_OWN_ID = 0x0008;
static const uint32_t RS_IDENTITY_FLAGS_IS_DEPRECATED= 0x0010; // used to denote keys with deprecated fingerprint format. static const uint32_t RS_IDENTITY_FLAGS_IS_DEPRECATED= 0x0010; // used to denote keys with deprecated fingerprint format.
class GxsReputation struct GxsReputation : RsSerializable
{ {
public:
GxsReputation(); GxsReputation();
bool updateIdScore(bool pgpLinked, bool pgpKnown); bool updateIdScore(bool pgpLinked, bool pgpKnown);
bool update(); // checks ranges and calculates overall score. bool update(); /// checks ranges and calculates overall score.
int mOverallScore;
int mIdScore; // PGP, Known, etc. int32_t mOverallScore;
int mOwnOpinion; int32_t mIdScore; /// PGP, Known, etc.
int mPeerOpinion; int32_t mOwnOpinion;
int32_t mPeerOpinion;
/// @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
RS_REGISTER_SERIAL_MEMBER(mOverallScore);
RS_REGISTER_SERIAL_MEMBER(mIdScore);
RS_REGISTER_SERIAL_MEMBER(mOwnOpinion);
RS_REGISTER_SERIAL_MEMBER(mPeerOpinion);
}
}; };
struct RsGxsIdGroup struct RsGxsIdGroup : RsSerializable
{ {
RsGxsIdGroup() : RsGxsIdGroup() :
mLastUsageTS(0), mPgpKnown(false), mIsAContact(false) {} mLastUsageTS(0), mPgpKnown(false), mIsAContact(false) {}
~RsGxsIdGroup() {} ~RsGxsIdGroup() {}
RsGroupMetaData mMeta; RsGroupMetaData mMeta;
// In GroupMetaData. // In GroupMetaData.
@ -120,7 +134,7 @@ struct RsGxsIdGroup
std::string mPgpIdSign; std::string mPgpIdSign;
// Recognition Strings. MAX# defined above. // Recognition Strings. MAX# defined above.
std::list<std::string> mRecognTags; RS_DEPRECATED std::list<std::string> mRecognTags;
// Avatar // Avatar
RsGxsImage mImage ; RsGxsImage mImage ;
@ -131,8 +145,11 @@ struct RsGxsIdGroup
bool mIsAContact; // change that into flags one day bool mIsAContact; // change that into flags one day
RsPgpId mPgpId; RsPgpId mPgpId;
GxsReputation mReputation; GxsReputation mReputation;
};
/// @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx );
};
std::ostream &operator<<(std::ostream &out, const RsGxsIdGroup &group); std::ostream &operator<<(std::ostream &out, const RsGxsIdGroup &group);
@ -149,12 +166,11 @@ class RsRecognTag
}; };
class RsRecognTagDetails struct RsRecognTagDetails
{ {
public: RsRecognTagDetails() :
RsRecognTagDetails() valid_from(0), valid_to(0), tag_class(0), tag_type(0), is_valid(false),
:valid_from(0), valid_to(0), tag_class(0), tag_type(0), is_pending(false) {}
is_valid(false), is_pending(false) { return; }
time_t valid_from; time_t valid_from;
time_t valid_to; time_t valid_to;
@ -167,105 +183,168 @@ class RsRecognTagDetails
bool is_pending; bool is_pending;
}; };
class RsIdOpinion
{
public:
RsGxsId id;
int rating;
};
struct RsIdentityParameters
class RsIdentityParameters
{ {
public: RsIdentityParameters() :
RsIdentityParameters(): isPgpLinked(false) { return; } isPgpLinked(false) {}
bool isPgpLinked; bool isPgpLinked;
std::string nickname; std::string nickname;
RsGxsImage mImage; RsGxsImage mImage;
}; };
class RsIdentityUsage struct RsIdentityUsage : RsSerializable
{ {
public: enum UsageCode : uint8_t
enum UsageCode { UNKNOWN_USAGE = 0x00, {
GROUP_ADMIN_SIGNATURE_CREATION = 0x01, // These 2 are normally not normal GXS identities, but nothing prevents it to happen either. UNKNOWN_USAGE = 0x00,
/** These 2 are normally not normal GXS identities, but nothing prevents
* it to happen either. */
GROUP_ADMIN_SIGNATURE_CREATION = 0x01,
GROUP_ADMIN_SIGNATURE_VALIDATION = 0x02, GROUP_ADMIN_SIGNATURE_VALIDATION = 0x02,
GROUP_AUTHOR_SIGNATURE_CREATION = 0x03, // not typically used, since most services do not require group author signatures
/** Not typically used, since most services do not require group author
* signatures */
GROUP_AUTHOR_SIGNATURE_CREATION = 0x03,
GROUP_AUTHOR_SIGNATURE_VALIDATION = 0x04, GROUP_AUTHOR_SIGNATURE_VALIDATION = 0x04,
MESSAGE_AUTHOR_SIGNATURE_CREATION = 0x05, // most common use case. Messages are signed by authors in e.g. forums.
/// most common use case. Messages are signed by authors in e.g. forums.
MESSAGE_AUTHOR_SIGNATURE_CREATION = 0x05,
MESSAGE_AUTHOR_SIGNATURE_VALIDATION = 0x06, MESSAGE_AUTHOR_SIGNATURE_VALIDATION = 0x06,
GROUP_AUTHOR_KEEP_ALIVE = 0x07, // Identities are stamped regularly by crawlign the set of messages for all groups. That helps keepign the useful identities in hand.
MESSAGE_AUTHOR_KEEP_ALIVE = 0x08, // Identities are stamped regularly by crawlign the set of messages for all groups. That helps keepign the useful identities in hand. /** Identities are stamped regularly by crawlign the set of messages for
CHAT_LOBBY_MSG_VALIDATION = 0x09, // Chat lobby msgs are signed, so each time one comes, or a chat lobby event comes, a signature verificaiton happens. * all groups. That helps keepign the useful identities in hand. */
GLOBAL_ROUTER_SIGNATURE_CHECK = 0x0a, // Global router message validation GROUP_AUTHOR_KEEP_ALIVE = 0x07,
GLOBAL_ROUTER_SIGNATURE_CREATION = 0x0b, // Global router message signature MESSAGE_AUTHOR_KEEP_ALIVE = 0x08,
GXS_TUNNEL_DH_SIGNATURE_CHECK = 0x0c, //
GXS_TUNNEL_DH_SIGNATURE_CREATION = 0x0d, // /** Chat lobby msgs are signed, so each time one comes, or a chat lobby
IDENTITY_DATA_UPDATE = 0x0e, // Group update on that identity data. Can be avatar, name, etc. * event comes, a signature verificaiton happens. */
IDENTITY_GENERIC_SIGNATURE_CHECK = 0x0f, // Any signature verified for that identity CHAT_LOBBY_MSG_VALIDATION = 0x09,
IDENTITY_GENERIC_SIGNATURE_CREATION = 0x10, // Any signature made by that identity
/// Global router message validation
GLOBAL_ROUTER_SIGNATURE_CHECK = 0x0a,
/// Global router message signature
GLOBAL_ROUTER_SIGNATURE_CREATION = 0x0b,
GXS_TUNNEL_DH_SIGNATURE_CHECK = 0x0c,
GXS_TUNNEL_DH_SIGNATURE_CREATION = 0x0d,
/// Group update on that identity data. Can be avatar, name, etc.
IDENTITY_DATA_UPDATE = 0x0e,
/// Any signature verified for that identity
IDENTITY_GENERIC_SIGNATURE_CHECK = 0x0f,
/// Any signature made by that identity
IDENTITY_GENERIC_SIGNATURE_CREATION = 0x10,
IDENTITY_GENERIC_ENCRYPTION = 0x11, IDENTITY_GENERIC_ENCRYPTION = 0x11,
IDENTITY_GENERIC_DECRYPTION = 0x12, IDENTITY_GENERIC_DECRYPTION = 0x12,
CIRCLE_MEMBERSHIP_CHECK = 0x13 CIRCLE_MEMBERSHIP_CHECK = 0x13
} ; } ;
explicit RsIdentityUsage(uint16_t service,const RsIdentityUsage::UsageCode& code,const RsGxsGroupId& gid=RsGxsGroupId(),const RsGxsMessageId& mid=RsGxsMessageId(),uint64_t additional_id=0,const std::string& comment = std::string()); RsIdentityUsage( uint16_t service, const RsIdentityUsage::UsageCode& code,
const RsGxsGroupId& gid = RsGxsGroupId(),
const RsGxsMessageId& mid = RsGxsMessageId(),
uint64_t additional_id=0,
const std::string& comment = std::string() );
uint16_t mServiceId; // Id of the service using that identity, as understood by rsServiceControl /// Id of the service using that identity, as understood by rsServiceControl
UsageCode mUsageCode; // Specific code to use. Will allow forming the correct translated message in the GUI if necessary. uint16_t mServiceId;
RsGxsGroupId mGrpId; // Group ID using the identity
RsGxsMessageId mMsgId; // Message ID using the identity /** Specific code to use. Will allow forming the correct translated message
uint64_t mAdditionalId; // Some additional ID. Can be used for e.g. chat lobbies. * in the GUI if necessary. */
std::string mComment ; // additional comment to be used mainly for debugging, but not GUI display UsageCode mUsageCode;
bool operator<(const RsIdentityUsage& u) const /// Group ID using the identity
{ RsGxsGroupId mGrpId;
return mHash < u.mHash ;
} /// Message ID using the identity
RsGxsMessageId mMsgId;
/// Some additional ID. Can be used for e.g. chat lobbies.
uint64_t mAdditionalId;
/// additional comment to be used mainly for debugging, but not GUI display
std::string mComment;
bool operator<(const RsIdentityUsage& u) const { return mHash < u.mHash; }
RsFileHash mHash ; RsFileHash mHash ;
/// @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
RS_REGISTER_SERIAL_MEMBER(mServiceId);
RS_REGISTER_SERIAL_MEMBER_TYPED(mUsageCode, uint8_t);
RS_REGISTER_SERIAL_MEMBER(mGrpId);
RS_REGISTER_SERIAL_MEMBER(mMsgId);
RS_REGISTER_SERIAL_MEMBER(mAdditionalId);
RS_REGISTER_SERIAL_MEMBER(mComment);
RS_REGISTER_SERIAL_MEMBER(mHash);
}
friend class RsTypeSerializer;
private:
/** Accessible only to friend class RsTypeSerializer needed for
* deserialization */
RsIdentityUsage();
}; };
class RsIdentityDetails RS_REGISTER_SERIALIZABLE_TYPE_DECL(RsIdentityUsage)
struct RsIdentityDetails : RsSerializable
{ {
public: RsIdentityDetails() : mFlags(0), mLastUsageTS(0) {}
RsIdentityDetails()
: mFlags(0), mLastUsageTS(0) { return; }
RsGxsId mId; RsGxsId mId;
// identity details.
std::string mNickname; std::string mNickname;
uint32_t mFlags; uint32_t mFlags;
// PGP Stuff.
RsPgpId mPgpId; RsPgpId mPgpId;
// Recogn details. /// @deprecated Recogn details.
std::list<RsRecognTag> mRecognTags; RS_DEPRECATED std::list<RsRecognTag> mRecognTags;
// Cyril: Reputation details. At some point we might want to merge information /** Cyril: Reputation details. At some point we might want to merge
// between the two into a single global score. Since the old reputation system * information between the two into a single global score. Since the old
// is not finished yet, I leave this in place. We should decide what to do with it. * reputation system is not finished yet, I leave this in place. We should
* decide what to do with it.
*/
RsReputations::ReputationInfo mReputation; RsReputations::ReputationInfo mReputation;
// avatar
RsGxsImage mAvatar; RsGxsImage mAvatar;
// last usage
time_t mLastUsageTS; time_t mLastUsageTS;
std::map<RsIdentityUsage,time_t> mUseCases; std::map<RsIdentityUsage,time_t> mUseCases;
/// @see RsSerializable
virtual void serial_process(RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx)
{
RS_REGISTER_SERIAL_MEMBER(mId);
RS_REGISTER_SERIAL_MEMBER(mNickname);
RS_REGISTER_SERIAL_MEMBER(mFlags);
RS_REGISTER_SERIAL_MEMBER(mPgpId);
//RS_REGISTER_SERIAL_MEMBER_TYPED(mReputation, RsSerializable);
//RS_REGISTER_SERIAL_MEMBER_TYPED(mAvatar, RsSerializable);
RS_REGISTER_SERIAL_MEMBER(mLastUsageTS);
RS_REGISTER_SERIAL_MEMBER(mUseCases);
}
}; };
class RsIdentity: public RsGxsIfaceHelper struct RsIdentity : RsGxsIfaceHelper
{ {
public:
explicit RsIdentity(RsGxsIface *gxs): RsGxsIfaceHelper(gxs) {} explicit RsIdentity(RsGxsIface *gxs): RsGxsIfaceHelper(gxs) {}
virtual ~RsIdentity() {} virtual ~RsIdentity() {}

View File

@ -1,17 +1,34 @@
#pragma once #pragma once
/*
* RetroShare Serialiser.
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <typeinfo> // for typeid #include <typeinfo> // for typeid
#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 "serialiser/rsserializable.h"
#include "util/stacktrace.h" #include "util/stacktrace.h"
#include <typeinfo> #include <typeinfo>
class RsItem: public RsMemoryManagement::SmallObject struct RsItem : RsMemoryManagement::SmallObject, RsSerializable
{ {
public:
explicit RsItem(uint32_t t); explicit RsItem(uint32_t t);
RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype); RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype);
#ifdef DO_STATISTICS #ifdef DO_STATISTICS
@ -26,27 +43,29 @@ class RsItem: public RsMemoryManagement::SmallObject
virtual std::ostream &print(std::ostream &out, uint16_t /* indent */ = 0) virtual std::ostream &print(std::ostream &out, uint16_t /* indent */ = 0)
{ {
RsGenericSerializer::SerializeContext ctx(NULL,0,RsGenericSerializer::FORMAT_BINARY,RsGenericSerializer::SERIALIZATION_FLAG_NONE); RsGenericSerializer::SerializeContext ctx(
NULL, 0, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
serial_process(RsGenericSerializer::PRINT,ctx); serial_process(RsGenericSerializer::PRINT,ctx);
return out; return out;
} }
void print_string(std::string &out, uint16_t indent = 0); void print_string(std::string &out, uint16_t indent = 0);
/* source / destination id */ /// source / destination id
const RsPeerId& PeerId() const { return peerId; } const RsPeerId& PeerId() const { return peerId; }
void PeerId(const RsPeerId& id) { peerId = id; } void PeerId(const RsPeerId& id) { peerId = id; }
/* complete id */ /// complete id
uint32_t PacketId() const; uint32_t PacketId() const;
/* id parts */ /// id parts
uint8_t PacketVersion(); uint8_t PacketVersion();
uint8_t PacketClass(); uint8_t PacketClass();
uint8_t PacketType(); uint8_t PacketType();
uint8_t PacketSubType() const; uint8_t PacketSubType() const;
/* For Service Packets */ /// For Service Packets
RsItem(uint8_t ver, uint16_t service, uint8_t subtype); RsItem(uint8_t ver, uint16_t service, uint8_t subtype);
uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */ uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */
void setPacketService(uint16_t service); void setPacketService(uint16_t service);
@ -55,13 +74,14 @@ class RsItem: public RsMemoryManagement::SmallObject
inline void setPriorityLevel(uint8_t l) { _priority_level = l ;} inline void setPriorityLevel(uint8_t l) { _priority_level = l ;}
/** /**
* TODO: This should be made pure virtual as soon as all the codebase * TODO: This default implementation should be removed and childs structs
* is ported to the new serialization system * implement RsSerializable(...) as soon as all the codebase is ported to
* the new serialization system
*/ */
virtual void serial_process(RsGenericSerializer::SerializeJob, virtual void serial_process(RsGenericSerializer::SerializeJob,
RsGenericSerializer::SerializeContext&)// = 0; RsGenericSerializer::SerializeContext&)// = 0;
{ {
std::cerr << "(EE) RsItem::serial_process() called by an item using" std::cerr << "(EE) RsItem::serial_process(...) called by an item using"
<< "new serialization classes, but not derived! Class is " << "new serialization classes, but not derived! Class is "
<< typeid(*this).name() << std::endl; << typeid(*this).name() << std::endl;
print_stacktrace(); print_stacktrace();

View File

@ -238,7 +238,6 @@ uint32_t getRawStringSize(const std::string &outStr)
bool getRawString(const void *data, uint32_t size, uint32_t *offset, std::string &outStr) bool getRawString(const void *data, uint32_t size, uint32_t *offset, std::string &outStr)
{ {
#warning Gio: "I had to change this. It seems like a bug to not clear the string. Should make sure it's not introducing any side effect."
outStr.clear(); outStr.clear();
uint32_t len = 0; uint32_t len = 0;

View File

@ -0,0 +1,137 @@
#pragma once
/*
* RetroShare Serialiser.
* Copyright (C) 2016-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "serialiser/rsserializer.h"
/** @brief Minimal ancestor for all serializable structs in RetroShare
* If you want your struct to be easly serializable you should inherit from this
* struct.
*/
struct RsSerializable
{
/** Register struct members to serialize in this method taking advantage of
* the helper macros
* @see RS_REGISTER_SERIAL_MEMBER(I)
* @see RS_REGISTER_SERIAL_MEMBER_TYPED(I, T)
* @see RS_REGISTER_SERIALIZABLE_TYPE(T)
*/
virtual void serial_process(RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx) = 0;
};
/** @def RS_REGISTER_SERIAL_MEMBER(I)
* Use this macro to register the members of `YourSerializable` for serial
* processing inside `YourSerializable::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)
/** @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 or 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 RsSerializable derivative (so passing
* RsSerializable as T) consider to register your item type with
* @see RS_REGISTER_SERIALIZABLE_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.
*/
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#define RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) do {\
RsTypeSerializer::serial_process<T>(j, ctx, reinterpret_cast<T&>(I), #I);\
} while(0)
#pragma GCC diagnostic pop
/** @def RS_REGISTER_SERIALIZABLE_TYPE(T)
* Use this macro into `youritem.cc` only if you need to process members of
* subtypes of RsSerializable.
*
* 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 RsSerializable like
* `std::map<uint64_t, RsChatMsgItem>`
*
* @code{.cpp}
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;
};
RS_REGISTER_SERIALIZABLE_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 RsSerializable as type in
* that case.
*/
#define RS_REGISTER_SERIALIZABLE_TYPE_DEF(T) template<> /*static*/\
void RsTypeSerializer::serial_process<T>( \
RsGenericSerializer::SerializeJob j,\
RsGenericSerializer::SerializeContext& ctx, T& item,\
const std::string& objName ) \
{ \
RsTypeSerializer::serial_process<RsSerializable>( j, \
ctx, static_cast<RsSerializable&>(item), objName ); \
}
/** @def RS_REGISTER_SERIALIZABLE_TYPE_DECL(T)
* The usage of this macro into your header file is needed only in case you
* needed @see RS_REGISTER_SERIALIZABLE_TYPE_DEF(T) in your definitions file,
* but it was not enough and the compiler kept complanining about undefined
* references to serialize, deserialize, serial_size, print_data, to_JSON,
* from_JSON for your RsSerializable derrived type.
*
* One example of such case is RsIdentityUsage that is declared in
* retroshare/rsidentity.h but defined in services/p3idservice.cc, also if
* RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsIdentityUsage) was used in p3idservice.cc
* for some reason it was not enough for the compiler to see it so
* RS_REGISTER_SERIALIZABLE_TYPE_DECL(RsIdentityUsage) has been added in
* rsidentity.h too and now the compiler is happy.
*/
#define RS_REGISTER_SERIALIZABLE_TYPE_DECL(T) template<> /*static*/\
void RsTypeSerializer::serial_process<T>( \
RsGenericSerializer::SerializeJob j,\
RsGenericSerializer::SerializeContext& ctx, T& item,\
const std::string& /*objName*/ );

View File

@ -3,7 +3,8 @@
* *
* RetroShare Serialiser. * RetroShare Serialiser.
* *
* Copyright 2016 by Cyril Soler * Copyright (C) 2016 Cyril Soler
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -153,9 +154,11 @@
#include <string.h> #include <string.h>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <rapidjson/document.h>
#include "retroshare/rsflags.h" #include "retroshare/rsflags.h"
#include "serialiser/rsserial.h" #include "serialiser/rsserial.h"
#include "util/rsdeprecate.h"
class RsItem ; class RsItem ;
@ -194,106 +197,125 @@ class RsRawSerialiser: public RsSerialType
virtual RsItem * deserialise(void *data, uint32_t *size); virtual RsItem * deserialise(void *data, uint32_t *size);
}; };
// Top class for all services and config serializers. typedef rapidjson::Document RsJson;
class RsGenericSerializer: public RsSerialType /// Top class for all services and config serializers.
struct RsGenericSerializer : RsSerialType
{ {
public: typedef enum
typedef enum { SIZE_ESTIMATE = 0x01, SERIALIZE = 0x02, DESERIALIZE = 0x03, PRINT=0x04 } SerializeJob ;
typedef enum { FORMAT_BINARY = 0x01, FORMAT_JSON = 0x02 } SerializationFormat ;
class SerializeContext
{ {
public: SIZE_ESTIMATE = 0x01,
SERIALIZE = 0x02,
DESERIALIZE = 0x03,
PRINT = 0x04,
TO_JSON,
FROM_JSON
} SerializeJob;
SerializeContext(uint8_t *data,uint32_t size,SerializationFormat format,SerializationFlags flags) /** @deprecated use SerializeJob instead */
: mData(data),mSize(size),mOffset(0),mOk(true),mFormat(format),mFlags(flags) {} RS_DEPRECATED typedef enum
{
FORMAT_BINARY = 0x01,
FORMAT_JSON = 0x02
} SerializationFormat;
struct SerializeContext
{
/** Allow shared allocator usage to avoid costly JSON deepcopy for
* nested RsSerializable */
SerializeContext(
uint8_t *data, uint32_t size, SerializationFormat format,
SerializationFlags flags,
RsJson::AllocatorType* allocator = nullptr) :
mData(data), mSize(size), mOffset(0), mOk(true), mFormat(format),
mFlags(flags), mJson(rapidjson::kObjectType, allocator) {}
unsigned char *mData; unsigned char *mData;
uint32_t mSize; uint32_t mSize;
uint32_t mOffset; uint32_t mOffset;
bool mOk; bool mOk;
SerializationFormat mFormat ; RS_DEPRECATED SerializationFormat mFormat;
SerializationFlags mFlags; SerializationFlags mFlags;
RsJson mJson;
}; };
// These are convenience flags to be used by the items when processing the data. The names of the flags /** These are convenience flags to be used by the items when processing the
// are not very important. What matters is that the serial_process() method of each item correctly * data. The names of the flags are not very important. What matters is that
// deals with the data when it sees the flags, if the serialiser sets them. By default the flags are not * the serial_process() method of each item correctly deals with the data
// set and shouldn't be handled. * when it sees the flags, if the serialiser sets them.
// When deriving a new serializer, the user can set his own flags, using compatible values * By default the flags are not set and shouldn't be handled.
* When deriving a new serializer, the user can set his own flags, using
* compatible values
*/
static const SerializationFlags SERIALIZATION_FLAG_NONE; // 0x0000 static const SerializationFlags SERIALIZATION_FLAG_NONE; // 0x0000
static const SerializationFlags SERIALIZATION_FLAG_CONFIG; // 0x0001 static const SerializationFlags SERIALIZATION_FLAG_CONFIG; // 0x0001
static const SerializationFlags SERIALIZATION_FLAG_SIGNATURE; // 0x0002 static const SerializationFlags SERIALIZATION_FLAG_SIGNATURE; // 0x0002
static const SerializationFlags SERIALIZATION_FLAG_SKIP_HEADER; // 0x0004 static const SerializationFlags SERIALIZATION_FLAG_SKIP_HEADER; // 0x0004
// The following functions overload RsSerialType. They *should not* need to be further overloaded. /**
* The following functions overload RsSerialType.
* They *should not* need to be further overloaded.
*/
RsItem *deserialise(void *data,uint32_t *size) = 0; RsItem *deserialise(void *data,uint32_t *size) = 0;
bool serialise(RsItem *item,void *data,uint32_t *size); bool serialise(RsItem *item,void *data,uint32_t *size);
uint32_t size(RsItem *item); uint32_t size(RsItem *item);
void print(RsItem *item); void print(RsItem *item);
protected: protected:
RsGenericSerializer(uint8_t serial_class, RsGenericSerializer(
uint8_t serial_type, uint8_t serial_class, uint8_t serial_type,
SerializationFormat format, SerializationFormat format, SerializationFlags flags ) :
SerializationFlags flags ) RsSerialType( RS_PKT_VERSION1, serial_class, serial_type),
: RsSerialType(RS_PKT_VERSION1,serial_class,serial_type), mFormat(format),mFlags(flags) mFormat(format), mFlags(flags) {}
{}
RsGenericSerializer(uint16_t service, RsGenericSerializer(
SerializationFormat format, uint16_t service, SerializationFormat format,
SerializationFlags flags ) SerializationFlags flags ) :
: RsSerialType(RS_PKT_VERSION_SERVICE,service), mFormat(format),mFlags(flags) RsSerialType( RS_PKT_VERSION_SERVICE, service ), mFormat(format),
{} mFlags(flags) {}
SerializationFormat mFormat; SerializationFormat mFormat;
SerializationFlags mFlags; SerializationFlags mFlags;
}; };
// Top class for service serializers. Derive your on service serializer from this class and overload creat_item().
class RsServiceSerializer: public RsGenericSerializer /** Top class for service serializers.
{ * Derive your on service serializer from this class and overload creat_item().
public:
RsServiceSerializer(uint16_t service_id,
SerializationFormat format = FORMAT_BINARY,
SerializationFlags flags = SERIALIZATION_FLAG_NONE)
: RsGenericSerializer(service_id,format,flags) {}
/*! create_item
* should be overloaded to create the correct type of item depending on the data
*/ */
virtual RsItem *create_item(uint16_t /* service */, uint8_t /* item_sub_id */) const=0; struct RsServiceSerializer : RsGenericSerializer
{
RsServiceSerializer(
uint16_t service_id, SerializationFormat format = FORMAT_BINARY,
SerializationFlags flags = SERIALIZATION_FLAG_NONE ) :
RsGenericSerializer(service_id, format, flags) {}
/*! should be overloaded to create the correct type of item depending on the
* data */
virtual RsItem *create_item( uint16_t /* service */,
uint8_t /* item_sub_id */ ) const = 0;
RsItem *deserialise(void *data, uint32_t *size); RsItem *deserialise(void *data, uint32_t *size);
}; };
// Top class for config serializers. Config serializers are only used internally by RS core. The development of new services or plugins do not need this.
class RsConfigSerializer: public RsGenericSerializer /** Top class for config serializers.
* Config serializers are only used internally by RS core.
* The development of new services or plugins do not need this.
*/
struct RsConfigSerializer : RsGenericSerializer
{ {
public:
RsConfigSerializer(uint8_t config_class, RsConfigSerializer(uint8_t config_class,
uint8_t config_type, uint8_t config_type,
SerializationFormat format = FORMAT_BINARY, SerializationFormat format = FORMAT_BINARY,
SerializationFlags flags = SERIALIZATION_FLAG_NONE) SerializationFlags flags = SERIALIZATION_FLAG_NONE) :
RsGenericSerializer(config_class,config_type,format,flags) {}
: RsGenericSerializer(config_class,config_type,format,flags) {} /*! should be overloaded to create the correct type of item depending on the
* data */
/*! create_item virtual RsItem *create_item(uint8_t /* item_type */,
* should be overloaded to create the correct type of item depending on the data uint8_t /* item_sub_type */) const = 0;
*/
virtual RsItem *create_item(uint8_t /* item_type */, uint8_t /* item_sub_type */) const=0;
RsItem *deserialise(void *data,uint32_t *size); RsItem *deserialise(void *data,uint32_t *size);
}; };

View File

@ -3,7 +3,8 @@
* *
* RetroShare Serialiser. * RetroShare Serialiser.
* *
* Copyright 2017 by Cyril Soler * Copyright (C) 2017 Cyril Soler
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -26,27 +27,48 @@
#include "serialiser/rstypeserializer.h" #include "serialiser/rstypeserializer.h"
#include "serialiser/rsbaseserial.h" #include "serialiser/rsbaseserial.h"
#include "serialiser/rstlvkeys.h" #include "serialiser/rstlvkeys.h"
#include "serialiser/rsserializable.h"
#include "rsitems/rsitem.h"
#include "util/rsprint.h" #include "util/rsprint.h"
#include <iomanip> #include <iomanip>
#include <typeinfo> #include <typeinfo>
#include <time.h> #include <time.h>
#include <string>
#include <typeinfo> // for typeid
#include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>
//static const uint32_t MAX_SERIALIZED_ARRAY_SIZE = 500 ; //static const uint32_t MAX_SERIALIZED_ARRAY_SIZE = 500 ;
static const uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB. static const uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB.
//=================================================================================================// #define SAFE_GET_JSON_V() \
const char* mName = memberName.c_str(); \
bool ret = jVal.HasMember(mName); \
if(!ret) \
{ \
std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName \
<< "\" not found in JSON:" << std::endl \
<< jVal << std::endl << std::endl; \
print_stacktrace(); \
return false; \
} \
rapidjson::Value& v = jVal[mName]
//============================================================================//
// Integer types // // Integer types //
//=================================================================================================// //============================================================================//
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const bool& member) template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const bool& member)
{ {
return setRawUInt8(data,size,&offset,member); return setRawUInt8(data,size,&offset,member);
} }
template<> bool RsTypeSerializer::serialize(uint8_t /*data*/[], uint32_t /*size*/, uint32_t& /*offset*/, const int32_t& /*member*/)
{
// TODO: nice to have but not used ATM
return false;
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint8_t& member) template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint8_t& member)
{ {
return setRawUInt8(data,size,&offset,member); return setRawUInt8(data,size,&offset,member);
@ -75,6 +97,11 @@ template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t siz
member = m; member = m;
return ok; return ok;
} }
template<> bool RsTypeSerializer::deserialize(const uint8_t /*data*/[], uint32_t /*size*/, uint32_t& /*offset*/, int32_t& /*member*/)
{
// TODO: nice to have but not used ATM
return false;
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint8_t& member) template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint8_t& member)
{ {
return getRawUInt8(data,size,&offset,&member); return getRawUInt8(data,size,&offset,&member);
@ -100,6 +127,10 @@ template<> uint32_t RsTypeSerializer::serial_size(const bool& /* member*/)
{ {
return 1; return 1;
} }
template<> uint32_t RsTypeSerializer::serial_size(const int32_t& /* member*/)
{
return 4;
}
template<> uint32_t RsTypeSerializer::serial_size(const uint8_t& /* member*/) template<> uint32_t RsTypeSerializer::serial_size(const uint8_t& /* member*/)
{ {
return 1; return 1;
@ -125,6 +156,10 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const bool &
{ {
std::cerr << " [bool ] " << n << ": " << V << std::endl; std::cerr << " [bool ] " << n << ": " << V << std::endl;
} }
template<> void RsTypeSerializer::print_data(const std::string& n, const int32_t& V)
{
std::cerr << " [int32_t ] " << n << ": " << V << std::endl;
}
template<> void RsTypeSerializer::print_data(const std::string& n, const uint8_t & V) template<> void RsTypeSerializer::print_data(const std::string& n, const uint8_t & V)
{ {
std::cerr << " [uint8_t ] " << n << ": " << V << std::endl; std::cerr << " [uint8_t ] " << n << ": " << V << std::endl;
@ -146,10 +181,104 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const time_t&
std::cerr << " [time_t ] " << n << ": " << V << " (" << time(NULL)-V << " secs ago)" << std::endl; std::cerr << " [time_t ] " << n << ": " << V << " (" << time(NULL)-V << " secs ago)" << std::endl;
} }
#define SIMPLE_TO_JSON_DEF(T) \
template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, \
const T& member, RsJson& jDoc ) \
{ \
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); \
\
rapidjson::Value key; \
key.SetString(memberName.c_str(), memberName.length(), allocator); \
\
rapidjson::Value value(member); \
\
jDoc.AddMember(key, value, allocator); \
\
return true; \
}
//=================================================================================================// SIMPLE_TO_JSON_DEF(bool)
SIMPLE_TO_JSON_DEF(int32_t)
SIMPLE_TO_JSON_DEF(time_t)
SIMPLE_TO_JSON_DEF(uint8_t)
SIMPLE_TO_JSON_DEF(uint16_t)
SIMPLE_TO_JSON_DEF(uint32_t)
SIMPLE_TO_JSON_DEF(uint64_t)
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName, bool& member,
RsJson& jVal )
{
SAFE_GET_JSON_V();
ret = ret && v.IsBool();
if(ret) member = v.GetBool();
return ret;
}
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
int32_t& member, RsJson& jVal )
{
SAFE_GET_JSON_V();
ret = ret && v.IsInt();
if(ret) member = v.GetInt();
return ret;
}
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName, time_t& member,
RsJson& jVal )
{
SAFE_GET_JSON_V();
ret = ret && v.IsUint();
if(ret) member = v.GetUint();
return ret;
}
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
uint8_t& member, RsJson& jVal )
{
SAFE_GET_JSON_V();
ret = ret && v.IsUint();
if(ret) member = v.GetUint();
return ret;
}
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
uint16_t& member, RsJson& jVal )
{
SAFE_GET_JSON_V();
ret = ret && v.IsUint();
if(ret) member = v.GetUint();
return ret;
}
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
uint32_t& member, RsJson& jVal )
{
SAFE_GET_JSON_V();
ret = ret && v.IsUint();
if(ret) member = v.GetUint();
return ret;
}
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
uint64_t& member, RsJson& jVal )
{
SAFE_GET_JSON_V();
ret = ret && v.IsUint();
if(ret) member = v.GetUint();
return ret;
}
//============================================================================//
// FLoats // // FLoats //
//=================================================================================================// //============================================================================//
template<> uint32_t RsTypeSerializer::serial_size(const float&){ return 4; } template<> uint32_t RsTypeSerializer::serial_size(const float&){ return 4; }
@ -166,10 +295,75 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const float&
std::cerr << " [float ] " << n << ": " << V << std::endl; std::cerr << " [float ] " << n << ": " << V << std::endl;
} }
SIMPLE_TO_JSON_DEF(float)
//=================================================================================================// template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
float& member, RsJson& jVal )
{
SAFE_GET_JSON_V();
ret = ret && v.IsFloat();
if(ret) member = v.GetFloat();
return ret;
}
//============================================================================//
// std::string //
//============================================================================//
template<> uint32_t RsTypeSerializer::serial_size(const std::string& str)
{
return getRawStringSize(str);
}
template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size,
uint32_t& offset,
const std::string& str )
{
return setRawString(data, size, &offset, str);
}
template<> bool RsTypeSerializer::deserialize( const uint8_t data[],
uint32_t size, uint32_t &offset,
std::string& str )
{
return getRawString(data, size, &offset, str);
}
template<> void RsTypeSerializer::print_data( const std::string& n,
const std::string& str )
{
std::cerr << " [std::string] " << n << ": " << str << std::endl;
}
template<> /*static*/
bool RsTypeSerializer::to_JSON( const std::string& membername,
const std::string& member, RsJson& jDoc )
{
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator();
rapidjson::Value key;
key.SetString(membername.c_str(), membername.length(), allocator);
rapidjson::Value value;;
value.SetString(member.c_str(), member.length(), allocator);
jDoc.AddMember(key, value, allocator);
return true;
}
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
std::string& member, RsJson& jVal )
{
SAFE_GET_JSON_V();
ret = ret && v.IsString();
if(ret) member = v.GetString();
return ret;
}
//============================================================================//
// TlvString with subtype // // TlvString with subtype //
//=================================================================================================// //============================================================================//
template<> uint32_t RsTypeSerializer::serial_size(uint16_t /* type_subtype */,const std::string& s) template<> uint32_t RsTypeSerializer::serial_size(uint16_t /* type_subtype */,const std::string& s)
{ {
@ -191,43 +385,127 @@ template<> void RsTypeSerializer::print_data(const std::string& n, uint16_t type
std::cerr << " [TlvString ] " << n << ": type=" << std::hex <<std::setw(4)<<std::setfill('0') << type_substring << std::dec << " s=\"" << V<< "\"" << std::endl; std::cerr << " [TlvString ] " << n << ": type=" << std::hex <<std::setw(4)<<std::setfill('0') << type_substring << std::dec << " s=\"" << V<< "\"" << std::endl;
} }
//=================================================================================================// template<> /*static*/
// TlvInt with subtype // bool RsTypeSerializer::to_JSON( const std::string& memberName,
//=================================================================================================// uint16_t /*sub_type*/,
const std::string& member, RsJson& jDoc )
{
return to_JSON<std::string>(memberName, member, jDoc);
}
template<> uint32_t RsTypeSerializer::serial_size(uint16_t /* type_subtype */,const uint32_t& /*s*/) template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
uint16_t /*sub_type*/,
std::string& member, RsJson& jVal )
{
return from_JSON<std::string>(memberName, member, jVal);
}
//============================================================================//
// TlvInt with subtype //
//============================================================================//
template<> uint32_t RsTypeSerializer::serial_size( uint16_t /* type_subtype */,
const uint32_t& /*s*/ )
{ {
return GetTlvUInt32Size(); return GetTlvUInt32Size();
} }
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,uint16_t sub_type,const uint32_t& s) template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size,
uint32_t &offset,uint16_t sub_type,
const uint32_t& s)
{ {
return SetTlvUInt32(data,size,&offset,sub_type,s); return SetTlvUInt32(data,size,&offset,sub_type,s);
} }
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,uint16_t sub_type,uint32_t& s) template<> bool RsTypeSerializer::deserialize( const uint8_t data[],
uint32_t size, uint32_t& offset,
uint16_t sub_type, uint32_t& s)
{ {
return GetTlvUInt32((void*)data, size, &offset, sub_type, &s); return GetTlvUInt32((void*)data, size, &offset, sub_type, &s);
} }
template<> void RsTypeSerializer::print_data(const std::string& n, uint16_t sub_type,const uint32_t& V) template<> void RsTypeSerializer::print_data(const std::string& n, uint16_t sub_type,const uint32_t& V)
{ {
std::cerr << " [TlvUInt32 ] " << n << ": type=" << std::hex <<std::setw(4)<<std::setfill('0') << sub_type << std::dec << " s=\"" << V<< "\"" << std::endl; std::cerr << " [TlvUInt32 ] " << n << ": type=" << std::hex
<< std::setw(4) << std::setfill('0') << sub_type << std::dec
<< " s=\"" << V << "\"" << std::endl;
} }
template<> /*static*/
//=================================================================================================// bool RsTypeSerializer::to_JSON( const std::string& memberName,
// std::string // uint16_t /*sub_type*/,
//=================================================================================================// const uint32_t& member, RsJson& jDoc )
template<> void RsTypeSerializer::print_data(const std::string& n, const std::string& V)
{ {
std::cerr << " [std::string] " << n << ": " << V << std::endl; return to_JSON<uint32_t>(memberName, member, jDoc);
} }
//=================================================================================================// template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
uint16_t /*sub_type*/,
uint32_t& member, RsJson& jVal )
{
return from_JSON<uint32_t>(memberName, member, jVal);
}
//============================================================================//
// TlvItems //
//============================================================================//
template<> uint32_t RsTypeSerializer::serial_size(const RsTlvItem& s)
{
return s.TlvSize();
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size,
uint32_t &offset,const RsTlvItem& s)
{
return s.SetTlv(data,size,&offset);
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[],
uint32_t size,uint32_t& offset,
RsTlvItem& s)
{
return s.GetTlv((void*)data,size,&offset) ;
}
template<> void RsTypeSerializer::print_data( const std::string& n,
const RsTlvItem& s )
{
std::cerr << " [" << typeid(s).name() << "] " << n << std::endl;
}
template<> /*static*/
bool RsTypeSerializer::to_JSON( const std::string& memberName,
const RsTlvItem& member, RsJson& jDoc )
{
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator();
rapidjson::Value key;
key.SetString(memberName.c_str(), memberName.length(), allocator);
rapidjson::Value value;
const char* tName = typeid(member).name();
value.SetString(tName, allocator);
jDoc.AddMember(key, value, allocator);
return true;
}
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/,
RsTlvItem& /*member*/, RsJson& /*jVal*/)
{
return true;
}
//============================================================================//
// Binary blocks // // Binary blocks //
//=================================================================================================// //============================================================================//
template<> uint32_t RsTypeSerializer::serial_size(const RsTypeSerializer::TlvMemBlock_proxy& r) { return 4 + r.second ; } template<> uint32_t RsTypeSerializer::serial_size(const RsTypeSerializer::TlvMemBlock_proxy& r) { return 4 + r.second ; }
@ -286,82 +564,141 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const RsTypeS
std::cerr << " [Binary data] " << n << ", length=" << s.second << " data=" << RsUtil::BinToHex((uint8_t*)s.first,std::min(50u,s.second)) << ((s.second>50)?"...":"") << std::endl; std::cerr << " [Binary data] " << n << ", length=" << s.second << " data=" << RsUtil::BinToHex((uint8_t*)s.first,std::min(50u,s.second)) << ((s.second>50)?"...":"") << std::endl;
} }
//=================================================================================================//
// TlvItems //
//=================================================================================================//
template<> uint32_t RsTypeSerializer::serial_size(const RsTlvItem& s)
{
return s.TlvSize() ;
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,const RsTlvItem& s)
{
return s.SetTlv(data,size,&offset) ;
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,RsTlvItem& s)
{
return s.GetTlv((void*)data,size,&offset) ;
}
template<> void RsTypeSerializer::print_data(const std::string& n, const RsTlvItem& s)
{
// can we call TlvPrint inside this?
std::cerr << " [" << typeid(s).name() << "] " << n << std::endl;
}
//============================================================================// //============================================================================//
// RsItem and derivated // // RsSerializable and derivated //
//============================================================================// //============================================================================//
template<> uint32_t RsTypeSerializer::serial_size(const RsItem& s) template<> uint32_t RsTypeSerializer::serial_size(const RsSerializable& s)
{ {
RsGenericSerializer::SerializeContext ctx( RsGenericSerializer::SerializeContext ctx(
NULL, 0, RsGenericSerializer::FORMAT_BINARY, NULL, 0, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE ); RsGenericSerializer::SERIALIZATION_FLAG_NONE );
ctx.mOffset = 8; // header size ctx.mOffset = 8; // header size
const_cast<RsItem&>(s).serial_process(RsGenericSerializer::SIZE_ESTIMATE, const_cast<RsSerializable&>(s).serial_process(
ctx); RsGenericSerializer::SIZE_ESTIMATE, ctx );
return ctx.mOffset; return ctx.mOffset;
} }
template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size, template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size,
uint32_t &offset, const RsItem& s ) uint32_t &offset,
const RsSerializable& s )
{ {
RsGenericSerializer::SerializeContext ctx( RsGenericSerializer::SerializeContext ctx(
data, size, RsGenericSerializer::FORMAT_BINARY, data, size, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE ); RsGenericSerializer::SERIALIZATION_FLAG_NONE );
ctx.mOffset = offset; ctx.mOffset = offset;
const_cast<RsItem&>(s).serial_process(RsGenericSerializer::SERIALIZE, const_cast<RsSerializable&>(s).serial_process(
ctx); RsGenericSerializer::SERIALIZE, ctx );
return true; return true;
} }
template<> bool RsTypeSerializer::deserialize( const uint8_t data[], template<> bool RsTypeSerializer::deserialize( const uint8_t data[],
uint32_t size, uint32_t& offset, uint32_t size, uint32_t& offset,
RsItem& s ) RsSerializable& s )
{ {
RsGenericSerializer::SerializeContext ctx( RsGenericSerializer::SerializeContext ctx(
const_cast<uint8_t*>(data), size, const_cast<uint8_t*>(data), size,
RsGenericSerializer::FORMAT_BINARY, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE ); RsGenericSerializer::SERIALIZATION_FLAG_NONE );
ctx.mOffset = offset; ctx.mOffset = offset;
const_cast<RsItem&>(s).serial_process(RsGenericSerializer::DESERIALIZE, const_cast<RsSerializable&>(s).serial_process(
ctx); RsGenericSerializer::DESERIALIZE, ctx );
return true; return true;
} }
template<> void RsTypeSerializer::print_data( const std::string& /*n*/, template<> void RsTypeSerializer::print_data( const std::string& /*n*/,
const RsItem& s ) const RsSerializable& s )
{ {
RsGenericSerializer::SerializeContext ctx( RsGenericSerializer::SerializeContext ctx(
NULL, 0, NULL, 0,
RsGenericSerializer::FORMAT_BINARY, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE ); RsGenericSerializer::SERIALIZATION_FLAG_NONE );
const_cast<RsItem&>(s).serial_process(RsGenericSerializer::PRINT, const_cast<RsSerializable&>(s).serial_process( RsGenericSerializer::PRINT,
ctx ); ctx );
} }
template<> /*static*/
bool RsTypeSerializer::to_JSON( const std::string& memberName,
const RsSerializable& member, RsJson& jDoc )
{
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator();
// Reuse allocator to avoid deep copy later
RsGenericSerializer::SerializeContext ctx(
NULL, 0, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
&allocator );
const_cast<RsSerializable&>(member).serial_process(
RsGenericSerializer::TO_JSON, ctx );
rapidjson::Value key;
key.SetString(memberName.c_str(), memberName.length(), allocator);
/* Because the passed allocator is reused it doesn't go out of scope and
* there is no need of deep copy and we can take advantage of the much
* faster rapidjson move semantic */
jDoc.AddMember(key, ctx.mJson, allocator);
return ctx.mOk;
}
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
RsSerializable& member, RsJson& jVal )
{
SAFE_GET_JSON_V();
if(ret)
{
RsGenericSerializer::SerializeContext ctx(
NULL, 0, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
ctx.mJson.SetObject() = v; // Beware of move semantic!!
member.serial_process(RsGenericSerializer::FROM_JSON, ctx);
ret = ret && ctx.mOk;
}
return ret;
}
template<> /*static*/
void RsTypeSerializer::serial_process<RsSerializable>(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx, RsSerializable& object,
const std::string& objName )
{
switch (j)
{
case RsGenericSerializer::SIZE_ESTIMATE: // fall-through
case RsGenericSerializer::SERIALIZE: // fall-through
case RsGenericSerializer::DESERIALIZE: // fall-through
case RsGenericSerializer::PRINT: // fall-through
object.serial_process(j, ctx);
break;
case RsGenericSerializer::TO_JSON:
ctx.mOk = ctx.mOk && to_JSON(objName, object, ctx.mJson);
break;
case RsGenericSerializer::FROM_JSON:
ctx.mOk = ctx.mOk && from_JSON(objName, object, ctx.mJson);
break;
default: break;
}
}
//============================================================================//
// RsJson std:ostream support //
//============================================================================//
std::ostream &operator<<(std::ostream &out, const RsJson &jDoc)
{
rapidjson::StringBuffer buffer; buffer.Clear();
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
jDoc.Accept(writer);
return out << buffer.GetString();
}

View File

@ -3,7 +3,8 @@
* *
* RetroShare Serialiser. * RetroShare Serialiser.
* *
* Copyright 2017 by Cyril Soler * Copyright (C) 2017 Cyril Soler
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -32,83 +33,91 @@
#include "retroshare/rsids.h" #include "retroshare/rsids.h"
#include "serialiser/rsserializer.h" #include "serialiser/rsserializer.h"
#include "serialiser/rsserializable.h"
/** @def RS_REGISTER_SERIAL_MEMBER(I) #include <rapidjson/document.h>
* Use this macro to register the members of `YourItem` for serial processing
* inside `YourItem::serial_process(j, ctx)` /** INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set}<T>
* * Can't use a template function because T is needed for const_cast */
* Inspired by http://stackoverflow.com/a/39345864 #define RsTypeSerializer_PRIVATE_TO_JSON_ARRAY() do \
{ \
using namespace rapidjson; \
\
Document::AllocatorType& allocator = ctx.mJson.GetAllocator(); \
\
Value arrKey; arrKey.SetString(memberName.c_str(), allocator); \
\
Value arr(kArrayType); \
\
for (auto& el : v) \
{ \
/* Use same allocator to avoid deep copy */\
RsGenericSerializer::SerializeContext elCtx(\
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,\
RsGenericSerializer::SERIALIZATION_FLAG_NONE,\
&allocator );\
\
/* If el is const the default serial_process template is matched */ \
/* also when specialization is necessary so the compilation break */ \
serial_process(j, elCtx, const_cast<T&>(el), memberName); \
\
elCtx.mOk = elCtx.mOk && elCtx.mJson.HasMember(arrKey);\
if(elCtx.mOk) arr.PushBack(elCtx.mJson[arrKey], allocator);\
else\
{\
ctx.mOk = false;\
break;\
}\
}\
\
ctx.mJson.AddMember(arrKey, arr, allocator);\
} while (false)
/** INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set}<T>
* Can't use a template function because std::{vector,list,set}<T> has different
* name for insert/push_back function
*/ */
#define RS_REGISTER_SERIAL_MEMBER(I) \ #define RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(INSERT_FUN) do\
do { RsTypeSerializer::serial_process(j, ctx, I, #I); } while(0) {\
using namespace rapidjson;\
\
bool& ok(ctx.mOk);\
Document& jDoc(ctx.mJson);\
Document::AllocatorType& allocator = jDoc.GetAllocator();\
\
Value arrKey;\
arrKey.SetString(memberName.c_str(), memberName.length());\
\
ok = ok && jDoc.IsObject();\
ok = ok && jDoc.HasMember(arrKey);\
\
if(ok && jDoc[arrKey].IsArray())\
{\
for (auto&& arrEl : jDoc[arrKey].GetArray())\
{\
RsGenericSerializer::SerializeContext elCtx(\
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,\
RsGenericSerializer::SERIALIZATION_FLAG_NONE,\
&allocator );\
elCtx.mJson.AddMember(arrKey, arrEl, allocator);\
\
T el;\
serial_process(j, elCtx, el, memberName); \
ok = ok && elCtx.mOk;\
\
if(ok) v.INSERT_FUN(el);\
else break;\
}\
}\
} while(false)
/** @def RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) std::ostream &operator<<(std::ostream &out, const RsJson &jDoc);
* 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 or 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.
*/
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#define RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) do {\
RsTypeSerializer::serial_process<T>(j, ctx, reinterpret_cast<T&>(I), #I);\
} while(0)
#pragma GCC diagnostic pop
/** @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
{
PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {}
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx );
std::map<uint64_t, RsChatMsgItem> store;
};
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 struct RsTypeSerializer
{ {
/** This type should be used to pass a parameter to drive the serialisation /** This type should be used to pass a parameter to drive the serialisation
* if needed */ * if needed */
struct TlvMemBlock_proxy: public std::pair<void*&,uint32_t&> struct TlvMemBlock_proxy : std::pair<void*&,uint32_t&>
{ {
TlvMemBlock_proxy(void*& p, uint32_t& s) : TlvMemBlock_proxy(void*& p, uint32_t& s) :
std::pair<void*&,uint32_t&>(p,s) {} std::pair<void*&,uint32_t&>(p,s) {}
@ -138,6 +147,12 @@ struct RsTypeSerializer
case RsGenericSerializer::PRINT: case RsGenericSerializer::PRINT:
print_data(member_name,member); print_data(member_name,member);
break; break;
case RsGenericSerializer::TO_JSON:
ctx.mOk = ctx.mOk && to_JSON(member_name, member, ctx.mJson);
break;
case RsGenericSerializer::FROM_JSON:
ctx.mOk = ctx.mOk && from_JSON(member_name, member, ctx.mJson);
break;
default: default:
ctx.mOk = false; ctx.mOk = false;
throw std::runtime_error("Unknown serial job"); throw std::runtime_error("Unknown serial job");
@ -165,7 +180,15 @@ struct RsTypeSerializer
serialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member); serialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member);
break; break;
case RsGenericSerializer::PRINT: case RsGenericSerializer::PRINT:
print_data(member_name,type_id,member); print_data(member_name, member);
break;
case RsGenericSerializer::TO_JSON:
ctx.mOk = ctx.mOk &&
to_JSON(member_name, type_id, member, ctx.mJson);
break;
case RsGenericSerializer::FROM_JSON:
ctx.mOk = ctx.mOk &&
from_JSON(member_name, type_id, member, ctx.mJson);
break; break;
default: default:
ctx.mOk = false; ctx.mOk = false;
@ -178,7 +201,7 @@ struct RsTypeSerializer
static void serial_process( RsGenericSerializer::SerializeJob j, static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx, RsGenericSerializer::SerializeContext& ctx,
std::map<T,U>& v, std::map<T,U>& v,
const std::string& member_name ) const std::string& memberName )
{ {
switch(j) switch(j)
{ {
@ -225,11 +248,11 @@ struct RsTypeSerializer
case RsGenericSerializer::PRINT: case RsGenericSerializer::PRINT:
{ {
if(v.empty()) if(v.empty())
std::cerr << " Empty map \"" << member_name << "\"" std::cerr << " Empty map \"" << memberName << "\""
<< std::endl; << std::endl;
else else
std::cerr << " std::map of " << v.size() << " elements: \"" std::cerr << " std::map of " << v.size() << " elements: \""
<< member_name << "\"" << std::endl; << memberName << "\"" << std::endl;
for(typename std::map<T,U>::iterator it(v.begin());it!=v.end();++it) for(typename std::map<T,U>::iterator it(v.begin());it!=v.end();++it)
{ {
@ -242,6 +265,95 @@ struct RsTypeSerializer
} }
break; break;
} }
case RsGenericSerializer::TO_JSON:
{
using namespace rapidjson;
Document::AllocatorType& allocator = ctx.mJson.GetAllocator();
Value arrKey; arrKey.SetString(memberName.c_str(),
memberName.length(), allocator);
Value arr(kArrayType);
for (auto& kv : v)
{
// Use same allocator to avoid deep copy
RsGenericSerializer::SerializeContext kCtx(
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
&allocator );
serial_process<T>(j, kCtx, const_cast<T&>(kv.first), "key");
RsGenericSerializer::SerializeContext vCtx(
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
&allocator );
serial_process<U>(j, vCtx, const_cast<U&>(kv.second), "value");
if(kCtx.mOk && vCtx.mOk)
{
Value el(kObjectType);
el.AddMember("key", kCtx.mJson["key"], allocator);
el.AddMember("value", vCtx.mJson["value"], allocator);
arr.PushBack(el, allocator);
}
}
ctx.mJson.AddMember(arrKey, arr, allocator);
break;
}
case RsGenericSerializer::FROM_JSON:
{
using namespace rapidjson;
bool& ok(ctx.mOk);
Document& jDoc(ctx.mJson);
Document::AllocatorType& allocator = jDoc.GetAllocator();
Value arrKey;
arrKey.SetString(memberName.c_str(), memberName.length());
ok = ok && jDoc.IsObject();
ok = ok && jDoc.HasMember(arrKey);
if(ok && jDoc[arrKey].IsArray())
{
for (auto&& kvEl : jDoc[arrKey].GetArray())
{
ok = ok && kvEl.IsObject();
ok = ok && kvEl.HasMember("key");
ok = ok && kvEl.HasMember("value");
if (!ok) break;
RsGenericSerializer::SerializeContext kCtx(
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
&allocator );
ok && (kCtx.mJson.
AddMember("key", kvEl["key"], allocator), true);
T key;
ok = ok && (serial_process(j, kCtx, key, "key"), kCtx.mOk);
RsGenericSerializer::SerializeContext vCtx(
nullptr, 0, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
&allocator );
ok && (vCtx.mJson.
AddMember("value", kvEl["value"], allocator), true);
U value;
ok = ok && ( serial_process(j, vCtx, value, "value"),
vCtx.mOk );
if(ok) v.insert(std::pair<T,U>(key,value));
else break;
}
}
break;
}
default: break; default: break;
} }
} }
@ -251,7 +363,7 @@ struct RsTypeSerializer
static void serial_process( RsGenericSerializer::SerializeJob j, static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx, RsGenericSerializer::SerializeContext& ctx,
std::vector<T>& v, std::vector<T>& v,
const std::string& member_name ) const std::string& memberName )
{ {
switch(j) switch(j)
{ {
@ -259,7 +371,7 @@ struct RsTypeSerializer
{ {
ctx.mOffset += 4; ctx.mOffset += 4;
for(uint32_t i=0;i<v.size();++i) for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name); serial_process(j,ctx,v[i],memberName);
break; break;
} }
case RsGenericSerializer::DESERIALIZE: case RsGenericSerializer::DESERIALIZE:
@ -268,7 +380,7 @@ struct RsTypeSerializer
serial_process(j,ctx,n,"temporary size"); serial_process(j,ctx,n,"temporary size");
v.resize(n); v.resize(n);
for(uint32_t i=0;i<v.size();++i) for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name); serial_process(j,ctx,v[i],memberName);
break; break;
} }
case RsGenericSerializer::SERIALIZE: case RsGenericSerializer::SERIALIZE:
@ -276,7 +388,7 @@ struct RsTypeSerializer
uint32_t n=v.size(); uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size"); serial_process(j,ctx,n,"temporary size");
for(uint32_t i=0; i<v.size(); ++i) for(uint32_t i=0; i<v.size(); ++i)
serial_process(j,ctx,v[i],member_name); serial_process(j,ctx,v[i],memberName);
break; break;
} }
case RsGenericSerializer::PRINT: case RsGenericSerializer::PRINT:
@ -289,10 +401,16 @@ struct RsTypeSerializer
for(uint32_t i=0;i<v.size();++i) for(uint32_t i=0;i<v.size();++i)
{ {
std::cerr << " " ; std::cerr << " " ;
serial_process(j,ctx,v[i],member_name); serial_process(j,ctx,v[i],memberName);
} }
break; break;
} }
case RsGenericSerializer::TO_JSON:
RsTypeSerializer_PRIVATE_TO_JSON_ARRAY();
break;
case RsGenericSerializer::FROM_JSON:
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(push_back);
break;
default: break; default: break;
} }
} }
@ -301,7 +419,7 @@ struct RsTypeSerializer
template<typename T> template<typename T>
static void serial_process( RsGenericSerializer::SerializeJob j, static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx, RsGenericSerializer::SerializeContext& ctx,
std::set<T>& v, const std::string& member_name ) std::set<T>& v, const std::string& memberName )
{ {
switch(j) switch(j)
{ {
@ -311,7 +429,7 @@ struct RsTypeSerializer
for(typename std::set<T>::iterator it(v.begin());it!=v.end();++it) 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 // the const cast here is a hack to avoid serial_process to
// instantiate serialise(const T&) // instantiate serialise(const T&)
serial_process(j,ctx,const_cast<T&>(*it) ,member_name); serial_process(j,ctx,const_cast<T&>(*it) ,memberName);
break; break;
} }
case RsGenericSerializer::DESERIALIZE: case RsGenericSerializer::DESERIALIZE:
@ -321,7 +439,7 @@ struct RsTypeSerializer
for(uint32_t i=0; i<n; ++i) for(uint32_t i=0; i<n; ++i)
{ {
T tmp; T tmp;
serial_process<T>(j,ctx,tmp,member_name); serial_process<T>(j,ctx,tmp,memberName);
v.insert(tmp); v.insert(tmp);
} }
break; break;
@ -333,7 +451,7 @@ struct RsTypeSerializer
for(typename std::set<T>::iterator it(v.begin());it!=v.end();++it) 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 // the const cast here is a hack to avoid serial_process to
// instantiate serialise(const T&) // instantiate serialise(const T&)
serial_process(j,ctx,const_cast<T&>(*it) ,member_name); serial_process(j,ctx,const_cast<T&>(*it) ,memberName);
break; break;
} }
case RsGenericSerializer::PRINT: case RsGenericSerializer::PRINT:
@ -343,6 +461,12 @@ struct RsTypeSerializer
<< std::endl; << std::endl;
break; break;
} }
case RsGenericSerializer::TO_JSON:
RsTypeSerializer_PRIVATE_TO_JSON_ARRAY();
break;
case RsGenericSerializer::FROM_JSON:
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(insert);
break;
default: break; default: break;
} }
} }
@ -352,7 +476,7 @@ struct RsTypeSerializer
static void serial_process( RsGenericSerializer::SerializeJob j, static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx, RsGenericSerializer::SerializeContext& ctx,
std::list<T>& v, std::list<T>& v,
const std::string& member_name ) const std::string& memberName )
{ {
switch(j) switch(j)
{ {
@ -360,7 +484,7 @@ struct RsTypeSerializer
{ {
ctx.mOffset += 4; ctx.mOffset += 4;
for(typename std::list<T>::iterator it(v.begin());it!=v.end();++it) for(typename std::list<T>::iterator it(v.begin());it!=v.end();++it)
serial_process(j,ctx,*it ,member_name); serial_process(j,ctx,*it ,memberName);
break; break;
} }
case RsGenericSerializer::DESERIALIZE: case RsGenericSerializer::DESERIALIZE:
@ -370,7 +494,7 @@ struct RsTypeSerializer
for(uint32_t i=0;i<n;++i) for(uint32_t i=0;i<n;++i)
{ {
T tmp; T tmp;
serial_process<T>(j,ctx,tmp,member_name); serial_process<T>(j,ctx,tmp,memberName);
v.push_back(tmp); v.push_back(tmp);
} }
break; break;
@ -380,7 +504,7 @@ struct RsTypeSerializer
uint32_t n=v.size(); uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size"); serial_process(j,ctx,n,"temporary size");
for(typename std::list<T>::iterator it(v.begin());it!=v.end();++it) for(typename std::list<T>::iterator it(v.begin());it!=v.end();++it)
serial_process(j,ctx,*it ,member_name); serial_process(j,ctx,*it ,memberName);
break; break;
} }
case RsGenericSerializer::PRINT: case RsGenericSerializer::PRINT:
@ -390,6 +514,12 @@ struct RsTypeSerializer
<< std::endl; << std::endl;
break; break;
} }
case RsGenericSerializer::TO_JSON:
RsTypeSerializer_PRIVATE_TO_JSON_ARRAY();
break;
case RsGenericSerializer::FROM_JSON:
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(push_back);
break;
default: break; default: break;
} }
} }
@ -399,7 +529,7 @@ struct RsTypeSerializer
static void serial_process( RsGenericSerializer::SerializeJob j, static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx, RsGenericSerializer::SerializeContext& ctx,
t_RsFlags32<N>& v, t_RsFlags32<N>& v,
const std::string& /*member_name*/) const std::string& memberName )
{ {
switch(j) switch(j)
{ {
@ -421,16 +551,27 @@ struct RsTypeSerializer
std::cerr << " Flags of type " << std::hex << N << " : " std::cerr << " Flags of type " << std::hex << N << " : "
<< v.toUInt32() << std::endl; << v.toUInt32() << std::endl;
break; break;
case RsGenericSerializer::TO_JSON:
ctx.mOk = to_JSON(memberName, v.toUInt32(), ctx.mJson);
break;
case RsGenericSerializer::FROM_JSON:
{
uint32_t f;
ctx.mOk = from_JSON(memberName, f, ctx.mJson);
v = t_RsFlags32<N>(f);
break;
}
default: 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: protected:
//============================================================================//
// Generic types declarations //
//============================================================================//
template<typename T> static bool serialize( template<typename T> static bool serialize(
uint8_t data[], uint32_t size, uint32_t &offset, const T& member ); uint8_t data[], uint32_t size, uint32_t &offset, const T& member );
@ -442,17 +583,41 @@ protected:
template<typename T> static void print_data( template<typename T> static void print_data(
const std::string& name, const T& member); const std::string& name, const T& member);
template<typename T> static bool to_JSON( const std::string& membername,
const T& member, RsJson& jDoc );
template<typename T> static bool from_JSON( const std::string& memberName,
T& member, RsJson& jDoc );
//============================================================================//
// Generic types + type_id declarations //
//============================================================================//
template<typename T> static bool serialize( template<typename T> static bool serialize(
uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id, uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id,
const T& member ); const T& member );
template<typename T> static bool deserialize( template<typename T> static bool deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset, const uint8_t data[], uint32_t size, uint32_t &offset,
uint16_t type_id, T& member ); uint16_t type_id, T& member );
template<typename T> static uint32_t serial_size( template<typename T> static uint32_t serial_size(
uint16_t type_id,const T& member ); 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<typename T> static void print_data( const std::string& n,
uint16_t type_id,const T& member );
template<typename T> static bool to_JSON( const std::string& membername,
uint16_t type_id,
const T& member, RsJson& jVal );
template<typename T> static bool from_JSON( const std::string& memberName,
uint16_t type_id,
T& member, RsJson& jDoc );
//============================================================================//
// t_RsGenericId<...> declarations //
//============================================================================//
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>
static bool serialize( static bool serialize(
@ -466,13 +631,29 @@ protected:
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>
static uint32_t serial_size( static uint32_t serial_size(
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member ); 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> template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
static void print_data( static void print_data(
const std::string& name, const std::string& name,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member ); 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 to_JSON(
const std::string& membername,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member,
RsJson& jVal );
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
static bool from_JSON(
const std::string& memberName,
t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member,
RsJson& jDoc );
//============================================================================//
// t_RsTlvList<...> declarations //
//============================================================================//
template<class TLV_CLASS,uint32_t TLV_TYPE> template<class TLV_CLASS,uint32_t TLV_TYPE>
static bool serialize( static bool serialize(
@ -491,16 +672,33 @@ protected:
static void print_data( static void print_data(
const std::string& name, const std::string& name,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member); const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member);
template<class TLV_CLASS,uint32_t TLV_TYPE>
static bool to_JSON( const std::string& membername,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member,
RsJson& jVal );
template<class TLV_CLASS,uint32_t TLV_TYPE>
static bool from_JSON( const std::string& memberName,
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member,
RsJson& jDoc );
}; };
//============================================================================//
// t_RsGenericId<...> //
//============================================================================//
// t_RsGenericId<>
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 ( bool RsTypeSerializer::serialize (
uint8_t data[], uint32_t size, uint32_t &offset, uint8_t data[], uint32_t size, uint32_t &offset,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member ) const t_RsGenericIdType<
{ return (*const_cast<const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER> *>(&member)).serialise(data,size,offset); } 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::deserialize( bool RsTypeSerializer::deserialize(
@ -522,8 +720,45 @@ void RsTypeSerializer::print_data(
<< member << std::endl; << member << std::endl;
} }
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
bool RsTypeSerializer::to_JSON( const std::string& memberName,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member,
RsJson& jDoc )
{
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator();
rapidjson::Value key;
key.SetString(memberName.c_str(), memberName.length(), allocator);
const std::string vStr = member.toStdString();
rapidjson::Value value;
value.SetString(vStr.c_str(), vStr.length(), allocator);
jDoc.AddMember(key, value, allocator);
return true;
}
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
bool RsTypeSerializer::from_JSON( const std::string& membername,
t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member,
RsJson& jVal )
{
const char* mName = membername.c_str();
bool ret = jVal.HasMember(mName);
if(ret)
{
rapidjson::Value& v = jVal[mName];
ret = ret && v.IsString();
ret && (member = t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>(std::string(v.GetString())), false);
}
return ret;
}
//============================================================================//
// t_RsTlvList<...> //
//============================================================================//
// t_RsTlvList<>
template<class TLV_CLASS,uint32_t TLV_TYPE> template<class TLV_CLASS,uint32_t TLV_TYPE>
bool RsTypeSerializer::serialize( bool RsTypeSerializer::serialize(
uint8_t data[], uint32_t size, uint32_t &offset, uint8_t data[], uint32_t size, uint32_t &offset,
@ -553,3 +788,76 @@ void RsTypeSerializer::print_data(
std::cerr << " [t_RsTlvString<" << std::hex << TLV_TYPE << ">] : size=" std::cerr << " [t_RsTlvString<" << std::hex << TLV_TYPE << ">] : size="
<< member.mList.size() << std::endl; << member.mList.size() << std::endl;
} }
template<class TLV_CLASS,uint32_t TLV_TYPE> /* static */
bool RsTypeSerializer::to_JSON( const std::string& memberName,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member,
RsJson& jDoc )
{
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator();
rapidjson::Value key;
key.SetString(memberName.c_str(), memberName.length(), allocator);
rapidjson::Value value;
const char* tName = typeid(member).name();
value.SetString(tName, allocator);
jDoc.AddMember(key, value, allocator);
std::cerr << __PRETTY_FUNCTION__ << " JSON serialization for type "
<< typeid(member).name() << " " << memberName
<< " not available." << std::endl;
print_stacktrace();
return true;
}
template<class TLV_CLASS,uint32_t TLV_TYPE>
bool RsTypeSerializer::from_JSON( const std::string& memberName,
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member,
RsJson& /*jVal*/ )
{
std::cerr << __PRETTY_FUNCTION__ << " JSON deserialization for type "
<< typeid(member).name() << " " << memberName
<< " not available." << std::endl;
print_stacktrace();
return true;
}
//============================================================================//
// Generic types //
//============================================================================//
template<typename T> /*static*/
bool RsTypeSerializer::to_JSON(const std::string& memberName, const T& member,
RsJson& jDoc )
{
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator();
rapidjson::Value key;
key.SetString(memberName.c_str(), memberName.length(), allocator);
rapidjson::Value value;
const char* tName = typeid(member).name();
value.SetString(tName, allocator);
jDoc.AddMember(key, value, allocator);
std::cerr << __PRETTY_FUNCTION__ << " JSON serialization for type "
<< typeid(member).name() << " " << memberName
<< " not available." << std::endl;
print_stacktrace();
return true;
}
template<typename T> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
T& member, RsJson& /*jDoc*/ )
{
std::cerr << __PRETTY_FUNCTION__ << " JSON deserialization for type "
<< typeid(member).name() << " " << memberName
<< " not available." << std::endl;
print_stacktrace();
return true;
}

View File

@ -3,7 +3,8 @@
* *
* Id interface for RetroShare. * Id interface for RetroShare.
* *
* Copyright 2012-2012 by Robert Fernie. * Copyright (C) 2012 Robert Fernie
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -4505,11 +4506,30 @@ void p3IdService::handle_event(uint32_t event_type, const std::string &/*elabel*
} }
} }
RsIdentityUsage::RsIdentityUsage(uint16_t service,const RsIdentityUsage::UsageCode& code,const RsGxsGroupId& gid,const RsGxsMessageId& mid,uint64_t additional_id,const std::string& comment) void RsGxsIdGroup::serial_process(
: mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid),mAdditionalId(additional_id),mComment(comment) RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
RS_REGISTER_SERIAL_MEMBER_TYPED(mMeta, RsSerializable);
RS_REGISTER_SERIAL_MEMBER(mPgpIdHash);
//RS_REGISTER_SERIAL_MEMBER(mPgpIdSign);
RS_REGISTER_SERIAL_MEMBER(mRecognTags);
//RS_REGISTER_SERIAL_MEMBER(mImage);
RS_REGISTER_SERIAL_MEMBER(mLastUsageTS);
RS_REGISTER_SERIAL_MEMBER(mPgpKnown);
RS_REGISTER_SERIAL_MEMBER(mIsAContact);
RS_REGISTER_SERIAL_MEMBER(mPgpId);
RS_REGISTER_SERIAL_MEMBER_TYPED(mReputation, RsSerializable);
}
RsIdentityUsage::RsIdentityUsage(
uint16_t service, const RsIdentityUsage::UsageCode& code,
const RsGxsGroupId& gid, const RsGxsMessageId& mid,
uint64_t additional_id,const std::string& comment ) :
mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid),
mAdditionalId(additional_id), mComment(comment)
{ {
#ifdef DEBUG_IDS #ifdef DEBUG_IDS
// This is a hack, since it will hash also mHash, but because it is initialized to 0, and only computed in the constructor here, it should be ok.
std::cerr << "New identity usage: " << std::endl; std::cerr << "New identity usage: " << std::endl;
std::cerr << " service=" << std::hex << service << std::endl; std::cerr << " service=" << std::hex << service << std::endl;
std::cerr << " code =" << std::hex << code << std::endl; std::cerr << " code =" << std::hex << code << std::endl;
@ -4519,6 +4539,9 @@ RsIdentityUsage::RsIdentityUsage(uint16_t service,const RsIdentityUsage::UsageCo
std::cerr << " commnt =\"" << std::hex << comment << "\"" << std::endl; std::cerr << " commnt =\"" << std::hex << comment << "\"" << std::endl;
#endif #endif
/* This is a hack, since it will hash also mHash, but because it is
* initialized to 0, and only computed in the constructor here, it should
* be ok. */
librs::crypto::HashStream hs(librs::crypto::HashStream::SHA1) ; librs::crypto::HashStream hs(librs::crypto::HashStream::SHA1) ;
hs << (uint32_t)service ; hs << (uint32_t)service ;
@ -4535,5 +4558,7 @@ RsIdentityUsage::RsIdentityUsage(uint16_t service,const RsIdentityUsage::UsageCo
#endif #endif
} }
RsIdentityUsage::RsIdentityUsage() :
mServiceId(0), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0) {}
RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsIdentityUsage)