mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-28 00:49:28 -05:00
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:
parent
49cacc41a1
commit
5cdc5aa58d
@ -207,7 +207,7 @@ void RsPrivateChatMsgConfigItem::get(RsChatMsgItem *ci)
|
||||
|
||||
/* Necessary to serialize `store` that is an STL container with RsChatMsgItem
|
||||
* inside which is a subtype of RsItem */
|
||||
RS_REGISTER_ITEM_TYPE(RsChatMsgItem)
|
||||
RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsChatMsgItem)
|
||||
|
||||
void PrivateOugoingMapItem::serial_process(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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);
|
||||
}
|
||||
|
||||
// for mailItem
|
||||
RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsGxsTransMailItem)
|
||||
|
||||
RS_REGISTER_ITEM_TYPE(RsGxsTransMailItem) // for mailItem
|
||||
RS_REGISTER_ITEM_TYPE(RsNxsTransPresignedReceipt) // for presignedReceipt
|
||||
// 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(recipient);
|
||||
|
@ -553,7 +553,7 @@ SOURCES += ft/ftchunkmap.cc \
|
||||
ft/ftfilesearch.cc \
|
||||
ft/ftserver.cc \
|
||||
ft/fttransfermodule.cc \
|
||||
ft/ftturtlefiletransferitem.cc
|
||||
ft/ftturtlefiletransferitem.cc
|
||||
|
||||
SOURCES += crypto/chacha20.cpp \
|
||||
crypto/hashstream.cc
|
||||
@ -648,6 +648,7 @@ SOURCES += serialiser/rsbaseserial.cc \
|
||||
rsitems/rsgxsupdateitems.cc \
|
||||
rsitems/rsserviceinfoitems.cc \
|
||||
|
||||
|
||||
SOURCES += services/autoproxy/rsautoproxymonitor.cc \
|
||||
services/autoproxy/p3i2pbob.cc \
|
||||
services/p3msgservice.cc \
|
||||
@ -786,7 +787,8 @@ SOURCES += gxstunnel/p3gxstunnel.cc \
|
||||
gxstunnel/rsgxstunnelitems.cc
|
||||
|
||||
# new serialization code
|
||||
HEADERS += serialiser/rsserializer.h \
|
||||
HEADERS += serialiser/rsserializable.h \
|
||||
serialiser/rsserializer.h \
|
||||
serialiser/rstypeserializer.h
|
||||
|
||||
SOURCES += serialiser/rsserializer.cc \
|
||||
|
@ -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
|
||||
*
|
||||
@ -13,8 +33,10 @@
|
||||
#include <string>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <retroshare/rstypes.h>
|
||||
#include <retroshare/rsids.h>
|
||||
#include "retroshare/rstypes.h"
|
||||
#include "retroshare/rsids.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
#include "serialiser/rstypeserializer.h"
|
||||
|
||||
typedef GXSGroupId RsGxsGroupId;
|
||||
typedef Sha1CheckSum RsGxsMessageId;
|
||||
@ -34,7 +56,7 @@ typedef std::map<RsGxsGroupId, std::vector<RsMsgMetaData> > MsgMetaResult;
|
||||
class RsGxsGrpMetaData;
|
||||
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,
|
||||
// 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.
|
||||
RsPeerId mOriginator;
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -6,7 +6,8 @@
|
||||
*
|
||||
* 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
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@ -36,6 +37,9 @@
|
||||
#include "retroshare/rsids.h"
|
||||
#include "serialiser/rstlvimage.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 */
|
||||
class RsIdentity;
|
||||
@ -63,6 +67,7 @@ extern RsIdentity *rsIdentity;
|
||||
#define RSID_RELATION_OTHER 0x0008
|
||||
#define RSID_RELATION_UNKNOWN 0x0010
|
||||
|
||||
/// @deprecated remove toghether with RsGxsIdGroup::mRecognTags
|
||||
#define RSRECOGN_MAX_TAGINFO 5
|
||||
|
||||
// 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_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 update(); // checks ranges and calculates overall score.
|
||||
int mOverallScore;
|
||||
int mIdScore; // PGP, Known, etc.
|
||||
int mOwnOpinion;
|
||||
int mPeerOpinion;
|
||||
bool updateIdScore(bool pgpLinked, bool pgpKnown);
|
||||
bool update(); /// checks ranges and calculates overall score.
|
||||
|
||||
int32_t mOverallScore;
|
||||
int32_t mIdScore; /// PGP, Known, etc.
|
||||
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() :
|
||||
mLastUsageTS(0), mPgpKnown(false), mIsAContact(false) {}
|
||||
~RsGxsIdGroup() {}
|
||||
|
||||
|
||||
RsGroupMetaData mMeta;
|
||||
|
||||
// In GroupMetaData.
|
||||
@ -120,7 +134,7 @@ struct RsGxsIdGroup
|
||||
std::string mPgpIdSign;
|
||||
|
||||
// Recognition Strings. MAX# defined above.
|
||||
std::list<std::string> mRecognTags;
|
||||
RS_DEPRECATED std::list<std::string> mRecognTags;
|
||||
|
||||
// Avatar
|
||||
RsGxsImage mImage ;
|
||||
@ -131,8 +145,11 @@ struct RsGxsIdGroup
|
||||
bool mIsAContact; // change that into flags one day
|
||||
RsPgpId mPgpId;
|
||||
GxsReputation mReputation;
|
||||
};
|
||||
|
||||
/// @see RsSerializable
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx );
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const RsGxsIdGroup &group);
|
||||
|
||||
@ -149,12 +166,11 @@ class RsRecognTag
|
||||
};
|
||||
|
||||
|
||||
class RsRecognTagDetails
|
||||
struct RsRecognTagDetails
|
||||
{
|
||||
public:
|
||||
RsRecognTagDetails()
|
||||
:valid_from(0), valid_to(0), tag_class(0), tag_type(0),
|
||||
is_valid(false), is_pending(false) { return; }
|
||||
RsRecognTagDetails() :
|
||||
valid_from(0), valid_to(0), tag_class(0), tag_type(0), is_valid(false),
|
||||
is_pending(false) {}
|
||||
|
||||
time_t valid_from;
|
||||
time_t valid_to;
|
||||
@ -167,105 +183,168 @@ class RsRecognTagDetails
|
||||
bool is_pending;
|
||||
};
|
||||
|
||||
class RsIdOpinion
|
||||
{
|
||||
public:
|
||||
RsGxsId id;
|
||||
int rating;
|
||||
};
|
||||
|
||||
|
||||
class RsIdentityParameters
|
||||
struct RsIdentityParameters
|
||||
{
|
||||
public:
|
||||
RsIdentityParameters(): isPgpLinked(false) { return; }
|
||||
RsIdentityParameters() :
|
||||
isPgpLinked(false) {}
|
||||
|
||||
bool isPgpLinked;
|
||||
std::string nickname;
|
||||
RsGxsImage mImage ;
|
||||
std::string nickname;
|
||||
RsGxsImage mImage;
|
||||
};
|
||||
|
||||
class RsIdentityUsage
|
||||
struct RsIdentityUsage : RsSerializable
|
||||
{
|
||||
public:
|
||||
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.
|
||||
GROUP_ADMIN_SIGNATURE_VALIDATION = 0x02,
|
||||
GROUP_AUTHOR_SIGNATURE_CREATION = 0x03, // not typically used, since most services do not require group author signatures
|
||||
GROUP_AUTHOR_SIGNATURE_VALIDATION = 0x04,
|
||||
MESSAGE_AUTHOR_SIGNATURE_CREATION = 0x05, // most common use case. Messages are signed by authors in e.g. forums.
|
||||
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.
|
||||
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.
|
||||
GLOBAL_ROUTER_SIGNATURE_CHECK = 0x0a, // Global router message validation
|
||||
GLOBAL_ROUTER_SIGNATURE_CREATION = 0x0b, // Global router message signature
|
||||
GXS_TUNNEL_DH_SIGNATURE_CHECK = 0x0c, //
|
||||
GXS_TUNNEL_DH_SIGNATURE_CREATION = 0x0d, //
|
||||
IDENTITY_DATA_UPDATE = 0x0e, // Group update on that identity data. Can be avatar, name, etc.
|
||||
IDENTITY_GENERIC_SIGNATURE_CHECK = 0x0f, // Any signature verified for that identity
|
||||
IDENTITY_GENERIC_SIGNATURE_CREATION = 0x10, // Any signature made by that identity
|
||||
IDENTITY_GENERIC_ENCRYPTION = 0x11,
|
||||
IDENTITY_GENERIC_DECRYPTION = 0x12,
|
||||
CIRCLE_MEMBERSHIP_CHECK = 0x13
|
||||
} ;
|
||||
enum UsageCode : uint8_t
|
||||
{
|
||||
UNKNOWN_USAGE = 0x00,
|
||||
|
||||
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());
|
||||
/** 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,
|
||||
|
||||
uint16_t mServiceId; // 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.
|
||||
RsGxsGroupId mGrpId; // Group ID using the identity
|
||||
/** Not typically used, since most services do not require group author
|
||||
* signatures */
|
||||
GROUP_AUTHOR_SIGNATURE_CREATION = 0x03,
|
||||
GROUP_AUTHOR_SIGNATURE_VALIDATION = 0x04,
|
||||
|
||||
RsGxsMessageId mMsgId; // Message ID using the identity
|
||||
uint64_t mAdditionalId; // Some additional ID. Can be used for e.g. chat lobbies.
|
||||
std::string mComment ; // additional comment to be used mainly for debugging, but not GUI display
|
||||
/// most common use case. Messages are signed by authors in e.g. forums.
|
||||
MESSAGE_AUTHOR_SIGNATURE_CREATION = 0x05,
|
||||
MESSAGE_AUTHOR_SIGNATURE_VALIDATION = 0x06,
|
||||
|
||||
bool operator<(const RsIdentityUsage& u) const
|
||||
{
|
||||
return mHash < u.mHash ;
|
||||
}
|
||||
RsFileHash mHash ;
|
||||
/** Identities are stamped regularly by crawlign the set of messages for
|
||||
* all groups. That helps keepign the useful identities in hand. */
|
||||
GROUP_AUTHOR_KEEP_ALIVE = 0x07,
|
||||
MESSAGE_AUTHOR_KEEP_ALIVE = 0x08,
|
||||
|
||||
/** Chat lobby msgs are signed, so each time one comes, or a chat lobby
|
||||
* event comes, a signature verificaiton happens. */
|
||||
CHAT_LOBBY_MSG_VALIDATION = 0x09,
|
||||
|
||||
/// 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_DECRYPTION = 0x12,
|
||||
CIRCLE_MEMBERSHIP_CHECK = 0x13
|
||||
} ;
|
||||
|
||||
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() );
|
||||
|
||||
/// Id of the service using that identity, as understood by rsServiceControl
|
||||
uint16_t mServiceId;
|
||||
|
||||
/** Specific code to use. Will allow forming the correct translated message
|
||||
* in the GUI if necessary. */
|
||||
UsageCode mUsageCode;
|
||||
|
||||
/// Group ID using the identity
|
||||
RsGxsGroupId mGrpId;
|
||||
|
||||
/// 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 ;
|
||||
|
||||
/// @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) { return; }
|
||||
RsIdentityDetails() : mFlags(0), mLastUsageTS(0) {}
|
||||
|
||||
RsGxsId mId;
|
||||
|
||||
// identity details.
|
||||
std::string mNickname;
|
||||
|
||||
uint32_t mFlags ;
|
||||
uint32_t mFlags;
|
||||
|
||||
// PGP Stuff.
|
||||
RsPgpId mPgpId;
|
||||
RsPgpId mPgpId;
|
||||
|
||||
// Recogn details.
|
||||
std::list<RsRecognTag> mRecognTags;
|
||||
/// @deprecated Recogn details.
|
||||
RS_DEPRECATED std::list<RsRecognTag> mRecognTags;
|
||||
|
||||
// Cyril: Reputation details. At some point we might want to merge information
|
||||
// between the two into a single global score. Since the old reputation system
|
||||
// is not finished yet, I leave this in place. We should decide what to do with it.
|
||||
RsReputations::ReputationInfo mReputation;
|
||||
/** Cyril: Reputation details. At some point we might want to merge
|
||||
* information between the two into a single global score. Since the old
|
||||
* reputation system is not finished yet, I leave this in place. We should
|
||||
* decide what to do with it.
|
||||
*/
|
||||
RsReputations::ReputationInfo mReputation;
|
||||
|
||||
// avatar
|
||||
RsGxsImage mAvatar ;
|
||||
RsGxsImage mAvatar;
|
||||
|
||||
// last usage
|
||||
time_t mLastUsageTS ;
|
||||
std::map<RsIdentityUsage,time_t> mUseCases ;
|
||||
time_t mLastUsageTS;
|
||||
|
||||
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) {}
|
||||
virtual ~RsIdentity() {}
|
||||
|
||||
|
@ -1,76 +1,96 @@
|
||||
#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 "util/smallobject.h"
|
||||
#include "retroshare/rstypes.h"
|
||||
#include "serialiser/rsserializer.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
#include "util/stacktrace.h"
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
class RsItem: public RsMemoryManagement::SmallObject
|
||||
struct RsItem : RsMemoryManagement::SmallObject, RsSerializable
|
||||
{
|
||||
public:
|
||||
explicit RsItem(uint32_t t);
|
||||
RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype);
|
||||
explicit RsItem(uint32_t t);
|
||||
RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype);
|
||||
#ifdef DO_STATISTICS
|
||||
void *operator new(size_t s) ;
|
||||
void operator delete(void *,size_t s) ;
|
||||
void *operator new(size_t s) ;
|
||||
void operator delete(void *,size_t s) ;
|
||||
#endif
|
||||
|
||||
virtual ~RsItem();
|
||||
virtual ~RsItem();
|
||||
|
||||
/// TODO: Do this make sense with the new serialization system?
|
||||
virtual void clear() = 0;
|
||||
/// 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)
|
||||
{
|
||||
RsGenericSerializer::SerializeContext ctx(NULL,0,RsGenericSerializer::FORMAT_BINARY,RsGenericSerializer::SERIALIZATION_FLAG_NONE);
|
||||
serial_process(RsGenericSerializer::PRINT,ctx) ;
|
||||
return out;
|
||||
}
|
||||
virtual std::ostream &print(std::ostream &out, uint16_t /* indent */ = 0)
|
||||
{
|
||||
RsGenericSerializer::SerializeContext ctx(
|
||||
NULL, 0, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
|
||||
serial_process(RsGenericSerializer::PRINT,ctx);
|
||||
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 */
|
||||
const RsPeerId& PeerId() const { return peerId; }
|
||||
void PeerId(const RsPeerId& id) { peerId = id; }
|
||||
/// source / destination id
|
||||
const RsPeerId& PeerId() const { return peerId; }
|
||||
void PeerId(const RsPeerId& id) { peerId = id; }
|
||||
|
||||
/* complete id */
|
||||
uint32_t PacketId() const;
|
||||
/// complete id
|
||||
uint32_t PacketId() const;
|
||||
|
||||
/* id parts */
|
||||
uint8_t PacketVersion();
|
||||
uint8_t PacketClass();
|
||||
uint8_t PacketType();
|
||||
uint8_t PacketSubType() const;
|
||||
/// id parts
|
||||
uint8_t PacketVersion();
|
||||
uint8_t PacketClass();
|
||||
uint8_t PacketType();
|
||||
uint8_t PacketSubType() const;
|
||||
|
||||
/* For Service Packets */
|
||||
RsItem(uint8_t ver, uint16_t service, uint8_t subtype);
|
||||
uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */
|
||||
void setPacketService(uint16_t service);
|
||||
/// For Service Packets
|
||||
RsItem(uint8_t ver, uint16_t service, uint8_t subtype);
|
||||
uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */
|
||||
void setPacketService(uint16_t service);
|
||||
|
||||
inline uint8_t priority_level() const { return _priority_level ;}
|
||||
inline void setPriorityLevel(uint8_t l) { _priority_level = l ;}
|
||||
inline uint8_t priority_level() const { return _priority_level ;}
|
||||
inline void setPriorityLevel(uint8_t l) { _priority_level = l ;}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
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;
|
||||
print_stacktrace();
|
||||
}
|
||||
/**
|
||||
* TODO: This default implementation should be removed and childs structs
|
||||
* implement RsSerializable(...) as soon as all the codebase is ported to
|
||||
* the new serialization system
|
||||
*/
|
||||
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;
|
||||
print_stacktrace();
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t type;
|
||||
RsPeerId peerId;
|
||||
uint8_t _priority_level ;
|
||||
protected:
|
||||
uint32_t type;
|
||||
RsPeerId peerId;
|
||||
uint8_t _priority_level;
|
||||
};
|
||||
|
||||
/// TODO: Do this make sense with the new serialization system?
|
||||
|
@ -238,8 +238,7 @@ uint32_t getRawStringSize(const 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;
|
||||
if (!getRawUInt32(data, size, offset, &len))
|
||||
|
137
libretroshare/src/serialiser/rsserializable.h
Normal file
137
libretroshare/src/serialiser/rsserializable.h
Normal 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*/ );
|
@ -3,7 +3,8 @@
|
||||
*
|
||||
* 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
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@ -153,9 +154,11 @@
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
#include "retroshare/rsflags.h"
|
||||
#include "serialiser/rsserial.h"
|
||||
#include "util/rsdeprecate.h"
|
||||
|
||||
class RsItem ;
|
||||
|
||||
@ -194,106 +197,125 @@ class RsRawSerialiser: public RsSerialType
|
||||
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 { SIZE_ESTIMATE = 0x01, SERIALIZE = 0x02, DESERIALIZE = 0x03, PRINT=0x04 } SerializeJob ;
|
||||
typedef enum { FORMAT_BINARY = 0x01, FORMAT_JSON = 0x02 } SerializationFormat ;
|
||||
|
||||
class SerializeContext
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
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)
|
||||
: mData(data),mSize(size),mOffset(0),mOk(true),mFormat(format),mFlags(flags) {}
|
||||
/** @deprecated use SerializeJob instead */
|
||||
RS_DEPRECATED typedef enum
|
||||
{
|
||||
FORMAT_BINARY = 0x01,
|
||||
FORMAT_JSON = 0x02
|
||||
} SerializationFormat;
|
||||
|
||||
unsigned char *mData ;
|
||||
uint32_t mSize ;
|
||||
uint32_t mOffset ;
|
||||
bool mOk ;
|
||||
SerializationFormat mFormat ;
|
||||
SerializationFlags mFlags ;
|
||||
};
|
||||
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) {}
|
||||
|
||||
// These are convenience flags to be used by the items when processing the data. The names of the flags
|
||||
// are not very important. What matters is that the serial_process() method of each item correctly
|
||||
// deals with the data when it sees the flags, if the serialiser sets them. 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
|
||||
unsigned char *mData;
|
||||
uint32_t mSize;
|
||||
uint32_t mOffset;
|
||||
bool mOk;
|
||||
RS_DEPRECATED SerializationFormat mFormat;
|
||||
SerializationFlags mFlags;
|
||||
RsJson mJson;
|
||||
};
|
||||
|
||||
static const SerializationFlags SERIALIZATION_FLAG_NONE ; // 0x0000
|
||||
static const SerializationFlags SERIALIZATION_FLAG_CONFIG ; // 0x0001
|
||||
static const SerializationFlags SERIALIZATION_FLAG_SIGNATURE ; // 0x0002
|
||||
static const SerializationFlags SERIALIZATION_FLAG_SKIP_HEADER ; // 0x0004
|
||||
/** These are convenience flags to be used by the items when processing the
|
||||
* data. The names of the flags are not very important. What matters is that
|
||||
* the serial_process() method of each item correctly deals with the data
|
||||
* when it sees the flags, if the serialiser sets them.
|
||||
* 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_CONFIG; // 0x0001
|
||||
static const SerializationFlags SERIALIZATION_FLAG_SIGNATURE; // 0x0002
|
||||
static const SerializationFlags SERIALIZATION_FLAG_SKIP_HEADER; // 0x0004
|
||||
|
||||
// The following functions overload RsSerialType. They *should not* need to be further overloaded.
|
||||
|
||||
RsItem *deserialise(void *data,uint32_t *size) =0;
|
||||
bool serialise(RsItem *item,void *data,uint32_t *size) ;
|
||||
uint32_t size(RsItem *item) ;
|
||||
void print(RsItem *item) ;
|
||||
/**
|
||||
* The following functions overload RsSerialType.
|
||||
* They *should not* need to be further overloaded.
|
||||
*/
|
||||
RsItem *deserialise(void *data,uint32_t *size) = 0;
|
||||
bool serialise(RsItem *item,void *data,uint32_t *size);
|
||||
uint32_t size(RsItem *item);
|
||||
void print(RsItem *item);
|
||||
|
||||
protected:
|
||||
RsGenericSerializer(uint8_t serial_class,
|
||||
uint8_t serial_type,
|
||||
SerializationFormat format,
|
||||
SerializationFlags flags )
|
||||
: RsSerialType(RS_PKT_VERSION1,serial_class,serial_type), mFormat(format),mFlags(flags)
|
||||
{}
|
||||
RsGenericSerializer(
|
||||
uint8_t serial_class, uint8_t serial_type,
|
||||
SerializationFormat format, SerializationFlags flags ) :
|
||||
RsSerialType( RS_PKT_VERSION1, serial_class, serial_type),
|
||||
mFormat(format), mFlags(flags) {}
|
||||
|
||||
RsGenericSerializer(uint16_t service,
|
||||
SerializationFormat format,
|
||||
SerializationFlags flags )
|
||||
: RsSerialType(RS_PKT_VERSION_SERVICE,service), mFormat(format),mFlags(flags)
|
||||
{}
|
||||
|
||||
SerializationFormat mFormat ;
|
||||
SerializationFlags mFlags ;
|
||||
RsGenericSerializer(
|
||||
uint16_t service, SerializationFormat format,
|
||||
SerializationFlags flags ) :
|
||||
RsSerialType( RS_PKT_VERSION_SERVICE, service ), mFormat(format),
|
||||
mFlags(flags) {}
|
||||
|
||||
SerializationFormat mFormat;
|
||||
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().
|
||||
*/
|
||||
struct RsServiceSerializer : RsGenericSerializer
|
||||
{
|
||||
public:
|
||||
RsServiceSerializer(uint16_t service_id,
|
||||
SerializationFormat format = FORMAT_BINARY,
|
||||
SerializationFlags flags = SERIALIZATION_FLAG_NONE)
|
||||
RsServiceSerializer(
|
||||
uint16_t service_id, SerializationFormat format = FORMAT_BINARY,
|
||||
SerializationFlags flags = SERIALIZATION_FLAG_NONE ) :
|
||||
RsGenericSerializer(service_id, format, flags) {}
|
||||
|
||||
: 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;
|
||||
|
||||
/*! 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;
|
||||
|
||||
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,
|
||||
uint8_t config_type,
|
||||
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 */
|
||||
virtual RsItem *create_item(uint8_t /* item_type */,
|
||||
uint8_t /* item_sub_type */) const = 0;
|
||||
|
||||
/*! create_item
|
||||
* should be overloaded to create the correct type of item depending on the data
|
||||
*/
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -3,7 +3,8 @@
|
||||
*
|
||||
* 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
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@ -26,27 +27,48 @@
|
||||
#include "serialiser/rstypeserializer.h"
|
||||
#include "serialiser/rsbaseserial.h"
|
||||
#include "serialiser/rstlvkeys.h"
|
||||
|
||||
#include "rsitems/rsitem.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
|
||||
#include "util/rsprint.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <typeinfo>
|
||||
#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_CHUNK_SIZE = 10*1024*1024 ; // 10 MB.
|
||||
|
||||
//=================================================================================================//
|
||||
// Integer types //
|
||||
//=================================================================================================//
|
||||
#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 //
|
||||
//============================================================================//
|
||||
|
||||
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const bool& 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)
|
||||
{
|
||||
return setRawUInt8(data,size,&offset,member);
|
||||
@ -70,10 +92,15 @@ template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint3
|
||||
|
||||
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, bool& member)
|
||||
{
|
||||
uint8_t m ;
|
||||
uint8_t m;
|
||||
bool ok = getRawUInt8(data,size,&offset,&m);
|
||||
member = m ;
|
||||
return ok;
|
||||
member = m;
|
||||
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)
|
||||
{
|
||||
@ -100,6 +127,10 @@ template<> uint32_t RsTypeSerializer::serial_size(const bool& /* member*/)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
template<> uint32_t RsTypeSerializer::serial_size(const int32_t& /* member*/)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
template<> uint32_t RsTypeSerializer::serial_size(const uint8_t& /* member*/)
|
||||
{
|
||||
return 1;
|
||||
@ -125,6 +156,10 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const bool &
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#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; \
|
||||
}
|
||||
|
||||
//=================================================================================================//
|
||||
// FLoats //
|
||||
//=================================================================================================//
|
||||
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 //
|
||||
//============================================================================//
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
SIMPLE_TO_JSON_DEF(float)
|
||||
|
||||
//=================================================================================================//
|
||||
// TlvString with subtype //
|
||||
//=================================================================================================//
|
||||
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 //
|
||||
//============================================================================//
|
||||
|
||||
template<> uint32_t RsTypeSerializer::serial_size(uint16_t /* type_subtype */,const std::string& s)
|
||||
{
|
||||
@ -188,46 +382,130 @@ template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t siz
|
||||
|
||||
template<> void RsTypeSerializer::print_data(const std::string& n, uint16_t type_substring,const std::string& V)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
//=================================================================================================//
|
||||
// TlvInt with subtype //
|
||||
//=================================================================================================//
|
||||
|
||||
template<> uint32_t RsTypeSerializer::serial_size(uint16_t /* type_subtype */,const uint32_t& /*s*/)
|
||||
template<> /*static*/
|
||||
bool RsTypeSerializer::to_JSON( const std::string& memberName,
|
||||
uint16_t /*sub_type*/,
|
||||
const std::string& member, RsJson& jDoc )
|
||||
{
|
||||
return GetTlvUInt32Size() ;
|
||||
return to_JSON<std::string>(memberName, member, jDoc);
|
||||
}
|
||||
|
||||
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,uint16_t sub_type,const uint32_t& s)
|
||||
template<> /*static*/
|
||||
bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||
uint16_t /*sub_type*/,
|
||||
std::string& member, RsJson& jVal )
|
||||
{
|
||||
return SetTlvUInt32(data,size,&offset,sub_type,s) ;
|
||||
return from_JSON<std::string>(memberName, member, jVal);
|
||||
}
|
||||
|
||||
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,uint16_t sub_type,uint32_t& s)
|
||||
//============================================================================//
|
||||
// TlvInt with subtype //
|
||||
//============================================================================//
|
||||
|
||||
template<> uint32_t RsTypeSerializer::serial_size( uint16_t /* type_subtype */,
|
||||
const uint32_t& /*s*/ )
|
||||
{
|
||||
return GetTlvUInt32((void*)data,size,&offset,sub_type,&s) ;
|
||||
return GetTlvUInt32Size();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//=================================================================================================//
|
||||
// std::string //
|
||||
//=================================================================================================//
|
||||
|
||||
template<> void RsTypeSerializer::print_data(const std::string& n, const std::string& V)
|
||||
template<> /*static*/
|
||||
bool RsTypeSerializer::to_JSON( const std::string& memberName,
|
||||
uint16_t /*sub_type*/,
|
||||
const uint32_t& member, RsJson& jDoc )
|
||||
{
|
||||
std::cerr << " [std::string] " << n << ": " << V << std::endl;
|
||||
return to_JSON<uint32_t>(memberName, member, jDoc);
|
||||
}
|
||||
|
||||
//=================================================================================================//
|
||||
// Binary blocks //
|
||||
//=================================================================================================//
|
||||
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 //
|
||||
//============================================================================//
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//=================================================================================================//
|
||||
// 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(
|
||||
NULL, 0, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
|
||||
|
||||
ctx.mOffset = 8; // header size
|
||||
const_cast<RsItem&>(s).serial_process(RsGenericSerializer::SIZE_ESTIMATE,
|
||||
ctx);
|
||||
const_cast<RsSerializable&>(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 )
|
||||
uint32_t &offset,
|
||||
const RsSerializable& 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);
|
||||
const_cast<RsSerializable&>(s).serial_process(
|
||||
RsGenericSerializer::SERIALIZE, ctx );
|
||||
return true;
|
||||
}
|
||||
|
||||
template<> bool RsTypeSerializer::deserialize( const uint8_t data[],
|
||||
uint32_t size, uint32_t& offset,
|
||||
RsItem& s )
|
||||
RsSerializable& 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);
|
||||
const_cast<RsSerializable&>(s).serial_process(
|
||||
RsGenericSerializer::DESERIALIZE, ctx );
|
||||
return true;
|
||||
}
|
||||
|
||||
template<> void RsTypeSerializer::print_data( const std::string& /*n*/,
|
||||
const RsItem& s )
|
||||
const RsSerializable& s )
|
||||
{
|
||||
RsGenericSerializer::SerializeContext ctx(
|
||||
NULL, 0,
|
||||
RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
|
||||
const_cast<RsItem&>(s).serial_process(RsGenericSerializer::PRINT,
|
||||
ctx);
|
||||
const_cast<RsSerializable&>(s).serial_process( RsGenericSerializer::PRINT,
|
||||
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();
|
||||
}
|
||||
|
@ -3,7 +3,8 @@
|
||||
*
|
||||
* 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
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@ -32,83 +33,91 @@
|
||||
#include "retroshare/rsids.h"
|
||||
|
||||
#include "serialiser/rsserializer.h"
|
||||
#include "serialiser/rsserializable.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
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
/** 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 */
|
||||
#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) \
|
||||
do { RsTypeSerializer::serial_process(j, ctx, I, #I); } while(0)
|
||||
#define RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(INSERT_FUN) do\
|
||||
{\
|
||||
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)
|
||||
* 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); }
|
||||
std::ostream &operator<<(std::ostream &out, const RsJson &jDoc);
|
||||
|
||||
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&>
|
||||
struct TlvMemBlock_proxy : std::pair<void*&,uint32_t&>
|
||||
{
|
||||
TlvMemBlock_proxy(void*& p, uint32_t& s) :
|
||||
std::pair<void*&,uint32_t&>(p,s) {}
|
||||
@ -120,7 +129,7 @@ struct RsTypeSerializer
|
||||
template<typename T>
|
||||
static void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
T& member,const std::string& member_name)
|
||||
T& member, const std::string& member_name )
|
||||
{
|
||||
switch(j)
|
||||
{
|
||||
@ -138,6 +147,12 @@ struct RsTypeSerializer
|
||||
case RsGenericSerializer::PRINT:
|
||||
print_data(member_name,member);
|
||||
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:
|
||||
ctx.mOk = false;
|
||||
throw std::runtime_error("Unknown serial job");
|
||||
@ -165,7 +180,15 @@ struct RsTypeSerializer
|
||||
serialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member);
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
ctx.mOk = false;
|
||||
@ -178,7 +201,7 @@ struct RsTypeSerializer
|
||||
static void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
std::map<T,U>& v,
|
||||
const std::string& member_name )
|
||||
const std::string& memberName )
|
||||
{
|
||||
switch(j)
|
||||
{
|
||||
@ -225,11 +248,11 @@ struct RsTypeSerializer
|
||||
case RsGenericSerializer::PRINT:
|
||||
{
|
||||
if(v.empty())
|
||||
std::cerr << " Empty map \"" << member_name << "\""
|
||||
std::cerr << " Empty map \"" << memberName << "\""
|
||||
<< std::endl;
|
||||
else
|
||||
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)
|
||||
{
|
||||
@ -242,6 +265,95 @@ struct RsTypeSerializer
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -251,7 +363,7 @@ struct RsTypeSerializer
|
||||
static void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
std::vector<T>& v,
|
||||
const std::string& member_name )
|
||||
const std::string& memberName )
|
||||
{
|
||||
switch(j)
|
||||
{
|
||||
@ -259,7 +371,7 @@ struct RsTypeSerializer
|
||||
{
|
||||
ctx.mOffset += 4;
|
||||
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;
|
||||
}
|
||||
case RsGenericSerializer::DESERIALIZE:
|
||||
@ -268,7 +380,7 @@ struct RsTypeSerializer
|
||||
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);
|
||||
serial_process(j,ctx,v[i],memberName);
|
||||
break;
|
||||
}
|
||||
case RsGenericSerializer::SERIALIZE:
|
||||
@ -276,7 +388,7 @@ struct RsTypeSerializer
|
||||
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);
|
||||
serial_process(j,ctx,v[i],memberName);
|
||||
break;
|
||||
}
|
||||
case RsGenericSerializer::PRINT:
|
||||
@ -289,10 +401,16 @@ struct RsTypeSerializer
|
||||
for(uint32_t i=0;i<v.size();++i)
|
||||
{
|
||||
std::cerr << " " ;
|
||||
serial_process(j,ctx,v[i],member_name);
|
||||
serial_process(j,ctx,v[i],memberName);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -301,7 +419,7 @@ struct RsTypeSerializer
|
||||
template<typename T>
|
||||
static void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
std::set<T>& v, const std::string& member_name )
|
||||
std::set<T>& v, const std::string& memberName )
|
||||
{
|
||||
switch(j)
|
||||
{
|
||||
@ -311,7 +429,7 @@ struct RsTypeSerializer
|
||||
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);
|
||||
serial_process(j,ctx,const_cast<T&>(*it) ,memberName);
|
||||
break;
|
||||
}
|
||||
case RsGenericSerializer::DESERIALIZE:
|
||||
@ -321,7 +439,7 @@ struct RsTypeSerializer
|
||||
for(uint32_t i=0; i<n; ++i)
|
||||
{
|
||||
T tmp;
|
||||
serial_process<T>(j,ctx,tmp,member_name);
|
||||
serial_process<T>(j,ctx,tmp,memberName);
|
||||
v.insert(tmp);
|
||||
}
|
||||
break;
|
||||
@ -333,7 +451,7 @@ struct RsTypeSerializer
|
||||
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);
|
||||
serial_process(j,ctx,const_cast<T&>(*it) ,memberName);
|
||||
break;
|
||||
}
|
||||
case RsGenericSerializer::PRINT:
|
||||
@ -343,6 +461,12 @@ struct RsTypeSerializer
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
case RsGenericSerializer::TO_JSON:
|
||||
RsTypeSerializer_PRIVATE_TO_JSON_ARRAY();
|
||||
break;
|
||||
case RsGenericSerializer::FROM_JSON:
|
||||
RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(insert);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -352,7 +476,7 @@ struct RsTypeSerializer
|
||||
static void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
std::list<T>& v,
|
||||
const std::string& member_name )
|
||||
const std::string& memberName )
|
||||
{
|
||||
switch(j)
|
||||
{
|
||||
@ -360,7 +484,7 @@ struct RsTypeSerializer
|
||||
{
|
||||
ctx.mOffset += 4;
|
||||
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;
|
||||
}
|
||||
case RsGenericSerializer::DESERIALIZE:
|
||||
@ -370,7 +494,7 @@ struct RsTypeSerializer
|
||||
for(uint32_t i=0;i<n;++i)
|
||||
{
|
||||
T tmp;
|
||||
serial_process<T>(j,ctx,tmp,member_name);
|
||||
serial_process<T>(j,ctx,tmp,memberName);
|
||||
v.push_back(tmp);
|
||||
}
|
||||
break;
|
||||
@ -380,7 +504,7 @@ struct RsTypeSerializer
|
||||
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);
|
||||
serial_process(j,ctx,*it ,memberName);
|
||||
break;
|
||||
}
|
||||
case RsGenericSerializer::PRINT:
|
||||
@ -390,6 +514,12 @@ struct RsTypeSerializer
|
||||
<< std::endl;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -399,7 +529,7 @@ struct RsTypeSerializer
|
||||
static void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
t_RsFlags32<N>& v,
|
||||
const std::string& /*member_name*/)
|
||||
const std::string& memberName )
|
||||
{
|
||||
switch(j)
|
||||
{
|
||||
@ -421,16 +551,27 @@ struct RsTypeSerializer
|
||||
std::cerr << " Flags of type " << std::hex << N << " : "
|
||||
<< v.toUInt32() << std::endl;
|
||||
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:
|
||||
|
||||
//============================================================================//
|
||||
// Generic types declarations //
|
||||
//============================================================================//
|
||||
|
||||
template<typename T> static bool serialize(
|
||||
uint8_t data[], uint32_t size, uint32_t &offset, const T& member );
|
||||
|
||||
@ -442,17 +583,41 @@ protected:
|
||||
template<typename T> static void print_data(
|
||||
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(
|
||||
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<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>
|
||||
static bool serialize(
|
||||
@ -466,13 +631,29 @@ protected:
|
||||
|
||||
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 );
|
||||
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<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>
|
||||
static bool serialize(
|
||||
@ -491,16 +672,33 @@ protected:
|
||||
static void print_data(
|
||||
const std::string& name,
|
||||
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>
|
||||
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); }
|
||||
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::deserialize(
|
||||
@ -522,8 +720,45 @@ void RsTypeSerializer::print_data(
|
||||
<< 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>
|
||||
bool RsTypeSerializer::serialize(
|
||||
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="
|
||||
<< 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;
|
||||
}
|
||||
|
@ -3,7 +3,8 @@
|
||||
*
|
||||
* 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
|
||||
* 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)
|
||||
: mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid),mAdditionalId(additional_id),mComment(comment)
|
||||
void RsGxsIdGroup::serial_process(
|
||||
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
|
||||
// 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 << " service=" << std::hex << service << 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;
|
||||
#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) ;
|
||||
|
||||
hs << (uint32_t)service ;
|
||||
@ -4535,5 +4558,7 @@ RsIdentityUsage::RsIdentityUsage(uint16_t service,const RsIdentityUsage::UsageCo
|
||||
#endif
|
||||
}
|
||||
|
||||
RsIdentityUsage::RsIdentityUsage() :
|
||||
mServiceId(0), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0) {}
|
||||
|
||||
|
||||
RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsIdentityUsage)
|
||||
|
Loading…
Reference in New Issue
Block a user