From 5cdc5aa58d7daf1097fd11af59c18dff7bfa7cb1 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Tue, 16 Jan 2018 03:31:03 +0100 Subject: [PATCH 01/17] 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 --- libretroshare/src/chat/rschatitems.cc | 2 +- libretroshare/src/gxstrans/p3gxstransitems.cc | 12 +- libretroshare/src/libretroshare.pro | 6 +- .../src/retroshare/rsgxsifacetypes.h | 52 +- libretroshare/src/retroshare/rsidentity.h | 257 ++++++--- libretroshare/src/rsitems/rsitem.h | 116 ++-- libretroshare/src/serialiser/rsbaseserial.cc | 3 +- libretroshare/src/serialiser/rsserializable.h | 137 +++++ libretroshare/src/serialiser/rsserializer.h | 172 +++--- .../src/serialiser/rstypeserializer.cc | 487 ++++++++++++++--- .../src/serialiser/rstypeserializer.h | 510 ++++++++++++++---- libretroshare/src/services/p3idservice.cc | 35 +- 12 files changed, 1384 insertions(+), 405 deletions(-) create mode 100644 libretroshare/src/serialiser/rsserializable.h diff --git a/libretroshare/src/chat/rschatitems.cc b/libretroshare/src/chat/rschatitems.cc index 24aef56f9..370cef5d3 100644 --- a/libretroshare/src/chat/rschatitems.cc +++ b/libretroshare/src/chat/rschatitems.cc @@ -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, diff --git a/libretroshare/src/gxstrans/p3gxstransitems.cc b/libretroshare/src/gxstrans/p3gxstransitems.cc index cebbd9e69..8ea0f4557 100644 --- a/libretroshare/src/gxstrans/p3gxstransitems.cc +++ b/libretroshare/src/gxstrans/p3gxstransitems.cc @@ -1,6 +1,6 @@ /* * GXS Mailing Service - * Copyright (C) 2016-2017 Gioacchino Mazzurco + * Copyright (C) 2016-2018 Gioacchino Mazzurco * * 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); diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index 1521f5574..99499c686 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -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 \ diff --git a/libretroshare/src/retroshare/rsgxsifacetypes.h b/libretroshare/src/retroshare/rsgxsifacetypes.h index fd477fc9f..659a87e2f 100644 --- a/libretroshare/src/retroshare/rsgxsifacetypes.h +++ b/libretroshare/src/retroshare/rsgxsifacetypes.h @@ -1,3 +1,23 @@ +/* + * rsgxsifacetypes.h + * + * Copyright (C) 2013 crispy + * Copyright (C) 2018 Gioacchino Mazzurco + * + * 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 . + */ + /* * rsgxsifacetypes.h * @@ -13,8 +33,10 @@ #include #include -#include -#include +#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 > 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); + } }; diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index bf650d462..b79cbe8fd 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -6,7 +6,8 @@ * * RetroShare C++ Interface. * - * Copyright 2012-2012 by Robert Fernie. + * Copyright (C) 2012 Robert Fernie. + * Copyright (C) 2018 Gioacchino Mazzurco * * 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 mRecognTags; + RS_DEPRECATED std::list 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 mRecognTags; + /// @deprecated Recogn details. + RS_DEPRECATED std::list 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 mUseCases ; + time_t mLastUsageTS; + + std::map 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() {} diff --git a/libretroshare/src/rsitems/rsitem.h b/libretroshare/src/rsitems/rsitem.h index 056bbe084..fb76d1562 100644 --- a/libretroshare/src/rsitems/rsitem.h +++ b/libretroshare/src/rsitems/rsitem.h @@ -1,76 +1,96 @@ #pragma once +/* + * RetroShare Serialiser. + * Copyright (C) 2018 Gioacchino Mazzurco + * + * 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 . + */ #include // for typeid #include "util/smallobject.h" #include "retroshare/rstypes.h" #include "serialiser/rsserializer.h" +#include "serialiser/rsserializable.h" #include "util/stacktrace.h" #include -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? diff --git a/libretroshare/src/serialiser/rsbaseserial.cc b/libretroshare/src/serialiser/rsbaseserial.cc index 44bd249d1..ef862db5c 100644 --- a/libretroshare/src/serialiser/rsbaseserial.cc +++ b/libretroshare/src/serialiser/rsbaseserial.cc @@ -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)) diff --git a/libretroshare/src/serialiser/rsserializable.h b/libretroshare/src/serialiser/rsserializable.h new file mode 100644 index 000000000..b90e6c666 --- /dev/null +++ b/libretroshare/src/serialiser/rsserializable.h @@ -0,0 +1,137 @@ +#pragma once +/* + * RetroShare Serialiser. + * Copyright (C) 2016-2018 Gioacchino Mazzurco + * + * 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 . + */ + +#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(j, ctx, reinterpret_cast(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` + * + * @code{.cpp} +struct PrivateOugoingMapItem : RsChatItem +{ + PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {} + + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ); + + std::map 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( \ + RsGenericSerializer::SerializeJob j,\ + RsGenericSerializer::SerializeContext& ctx, T& item,\ + const std::string& objName ) \ +{ \ + RsTypeSerializer::serial_process( j, \ + ctx, static_cast(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( \ + RsGenericSerializer::SerializeJob j,\ + RsGenericSerializer::SerializeContext& ctx, T& item,\ + const std::string& /*objName*/ ); diff --git a/libretroshare/src/serialiser/rsserializer.h b/libretroshare/src/serialiser/rsserializer.h index 2cae93ab7..63b565a9b 100644 --- a/libretroshare/src/serialiser/rsserializer.h +++ b/libretroshare/src/serialiser/rsserializer.h @@ -3,7 +3,8 @@ * * RetroShare Serialiser. * - * Copyright 2016 by Cyril Soler + * Copyright (C) 2016 Cyril Soler + * Copyright (C) 2018 Gioacchino Mazzurco * * 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 #include #include +#include #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); }; - - - diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc index 8be8660ae..c2b0ba905 100644 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ b/libretroshare/src/serialiser/rstypeserializer.cc @@ -3,7 +3,8 @@ * * RetroShare Serialiser. * - * Copyright 2017 by Cyril Soler + * Copyright (C) 2017 Cyril Soler + * Copyright (C) 2018 Gioacchino Mazzurco * * 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 #include #include +#include +#include // for typeid +#include +#include //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 < 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(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(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 < 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(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(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(s).serial_process(RsGenericSerializer::SIZE_ESTIMATE, - ctx); + const_cast(s).serial_process( + RsGenericSerializer::SIZE_ESTIMATE, ctx ); return ctx.mOffset; } template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size, - uint32_t &offset, const RsItem& s ) + uint32_t &offset, + const RsSerializable& s ) { RsGenericSerializer::SerializeContext ctx( data, size, RsGenericSerializer::FORMAT_BINARY, RsGenericSerializer::SERIALIZATION_FLAG_NONE ); ctx.mOffset = offset; - const_cast(s).serial_process(RsGenericSerializer::SERIALIZE, - ctx); + const_cast(s).serial_process( + RsGenericSerializer::SERIALIZE, ctx ); return true; } template<> bool RsTypeSerializer::deserialize( const uint8_t data[], uint32_t size, uint32_t& offset, - RsItem& s ) + RsSerializable& s ) { RsGenericSerializer::SerializeContext ctx( const_cast(data), size, RsGenericSerializer::FORMAT_BINARY, RsGenericSerializer::SERIALIZATION_FLAG_NONE ); ctx.mOffset = offset; - const_cast(s).serial_process(RsGenericSerializer::DESERIALIZE, - ctx); + const_cast(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(s).serial_process(RsGenericSerializer::PRINT, - ctx); + const_cast(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(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( + 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 writer(buffer); + jDoc.Accept(writer); + return out << buffer.GetString(); } diff --git a/libretroshare/src/serialiser/rstypeserializer.h b/libretroshare/src/serialiser/rstypeserializer.h index f4867f10f..1de678d50 100644 --- a/libretroshare/src/serialiser/rstypeserializer.h +++ b/libretroshare/src/serialiser/rstypeserializer.h @@ -3,7 +3,8 @@ * * RetroShare Serialiser. * - * Copyright 2017 by Cyril Soler + * Copyright (C) 2017 Cyril Soler + * Copyright (C) 2018 Gioacchino Mazzurco * * 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 + +/** INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set} + * 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(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} + * Can't use a template function because std::{vector,list,set} 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(j, ctx, reinterpret_cast(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` - * - * @code{.cpp} -struct PrivateOugoingMapItem : RsChatItem -{ - PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - std::map 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( \ - 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 + struct TlvMemBlock_proxy : std::pair { TlvMemBlock_proxy(void*& p, uint32_t& s) : std::pair(p,s) {} @@ -120,7 +129,7 @@ struct RsTypeSerializer template 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& 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::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(j, kCtx, const_cast(kv.first), "key"); + + RsGenericSerializer::SerializeContext vCtx( + nullptr, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE, + &allocator ); + serial_process(j, vCtx, const_cast(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(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& 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 static void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx, - std::set& v, const std::string& member_name ) + std::set& v, const std::string& memberName ) { switch(j) { @@ -311,7 +429,7 @@ struct RsTypeSerializer for(typename std::set::iterator it(v.begin());it!=v.end();++it) // the const cast here is a hack to avoid serial_process to // instantiate serialise(const T&) - serial_process(j,ctx,const_cast(*it) ,member_name); + serial_process(j,ctx,const_cast(*it) ,memberName); break; } case RsGenericSerializer::DESERIALIZE: @@ -321,7 +439,7 @@ struct RsTypeSerializer for(uint32_t i=0; i(j,ctx,tmp,member_name); + serial_process(j,ctx,tmp,memberName); v.insert(tmp); } break; @@ -333,7 +451,7 @@ struct RsTypeSerializer for(typename std::set::iterator it(v.begin());it!=v.end();++it) // the const cast here is a hack to avoid serial_process to // instantiate serialise(const T&) - serial_process(j,ctx,const_cast(*it) ,member_name); + serial_process(j,ctx,const_cast(*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& 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::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(j,ctx,tmp,member_name); + serial_process(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::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& 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(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 static bool serialize( uint8_t data[], uint32_t size, uint32_t &offset, const T& member ); @@ -442,17 +583,41 @@ protected: template static void print_data( const std::string& name, const T& member); + template static bool to_JSON( const std::string& membername, + const T& member, RsJson& jDoc ); + + template static bool from_JSON( const std::string& memberName, + T& member, RsJson& jDoc ); + +//============================================================================// +// Generic types + type_id declarations // +//============================================================================// template static bool serialize( uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id, const T& member ); + template static bool deserialize( const uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id, T& member ); + template static uint32_t serial_size( uint16_t type_id,const T& member ); - template static void print_data( - const std::string& name,uint16_t type_id,const T& member ); + + template static void print_data( const std::string& n, + uint16_t type_id,const T& member ); + + template static bool to_JSON( const std::string& membername, + uint16_t type_id, + const T& member, RsJson& jVal ); + + template static bool from_JSON( const std::string& memberName, + uint16_t type_id, + T& member, RsJson& jDoc ); + +//============================================================================// +// t_RsGenericId<...> declarations // +//============================================================================// template static bool serialize( @@ -466,13 +631,29 @@ protected: template static uint32_t serial_size( - const t_RsGenericIdType& member ); + const t_RsGenericIdType< + ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member ); template static void print_data( const std::string& name, const t_RsGenericIdType& member ); + template + static bool to_JSON( + const std::string& membername, + const t_RsGenericIdType& member, + RsJson& jVal ); + + template + static bool from_JSON( + const std::string& memberName, + t_RsGenericIdType& member, + RsJson& jDoc ); + +//============================================================================// +// t_RsTlvList<...> declarations // +//============================================================================// template static bool serialize( @@ -491,16 +672,33 @@ protected: static void print_data( const std::string& name, const t_RsTlvList& member); + + template + static bool to_JSON( const std::string& membername, + const t_RsTlvList& member, + RsJson& jVal ); + + template + static bool from_JSON( const std::string& memberName, + t_RsTlvList& member, + RsJson& jDoc ); }; +//============================================================================// +// t_RsGenericId<...> // +//============================================================================// -// t_RsGenericId<> template bool RsTypeSerializer::serialize ( uint8_t data[], uint32_t size, uint32_t &offset, - const t_RsGenericIdType& member ) -{ return (*const_cast *>(&member)).serialise(data,size,offset); } + const t_RsGenericIdType< + ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member ) +{ + return (*const_cast *>(&member) + ).serialise(data,size,offset); +} template bool RsTypeSerializer::deserialize( @@ -522,8 +720,45 @@ void RsTypeSerializer::print_data( << member << std::endl; } +template +bool RsTypeSerializer::to_JSON( const std::string& memberName, + const t_RsGenericIdType& 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 +bool RsTypeSerializer::from_JSON( const std::string& membername, + t_RsGenericIdType& 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(std::string(v.GetString())), false); + } + return ret; +} + +//============================================================================// +// t_RsTlvList<...> // +//============================================================================// -// t_RsTlvList<> template 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 /* static */ +bool RsTypeSerializer::to_JSON( const std::string& memberName, + const t_RsTlvList& 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 +bool RsTypeSerializer::from_JSON( const std::string& memberName, + t_RsTlvList& 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 /*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 /*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; +} diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 8695280a7..6dfb43ce8 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -3,7 +3,8 @@ * * Id interface for RetroShare. * - * Copyright 2012-2012 by Robert Fernie. + * Copyright (C) 2012 Robert Fernie + * Copyright (C) 2018 Gioacchino Mazzurco * * 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) From 18891645e0a5549308bc2fd03744f2f8be79ef6c Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Tue, 16 Jan 2018 11:42:20 +0100 Subject: [PATCH 02/17] Add rapidjson installation in appveyor.yml --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index cc1cbef95..4878efe71 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,7 +12,7 @@ #---------------------------------# # version format -version: RetroShare 0.6.0.{build}-{branch} +version: RetroShare-git-{branch}-{build} # you can use {branch} name in version format too # version: 1.0.{build}-{branch} @@ -106,6 +106,7 @@ install: - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-ffmpeg mingw-w64-x86_64-ffmpeg" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-libmicrohttpd mingw-w64-x86_64-libmicrohttpd" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-libxslt mingw-w64-x86_64-libxslt" + - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-rapidjson mingw-w64-x86_64-rapidjson" # Hack for new MSys2 - copy C:\msys64\mingw32\i686-w64-mingw32\bin\ar.exe C:\msys64\mingw32\bin\i686-w64-mingw32-ar.exe From 9d40d416f6cf5d478386284835260764823dcb86 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Sun, 21 Jan 2018 20:27:49 +0100 Subject: [PATCH 03/17] Better naming for serialization helper macro --- libretroshare/src/chat/rschatitems.cc | 2 +- libretroshare/src/gxstrans/p3gxstransitems.cc | 30 +++++++-------- libretroshare/src/gxstrans/p3gxstransitems.h | 8 ++-- .../src/retroshare/rsgxsifacetypes.h | 36 +++++++++--------- libretroshare/src/retroshare/rsidentity.h | 38 +++++++++---------- libretroshare/src/rsitems/rsnxsitems.cc | 12 +++--- libretroshare/src/serialiser/rsserializable.h | 25 ++++++------ libretroshare/src/services/p3idservice.cc | 20 +++++----- 8 files changed, 86 insertions(+), 85 deletions(-) diff --git a/libretroshare/src/chat/rschatitems.cc b/libretroshare/src/chat/rschatitems.cc index 370cef5d3..00511c1f8 100644 --- a/libretroshare/src/chat/rschatitems.cc +++ b/libretroshare/src/chat/rschatitems.cc @@ -212,4 +212,4 @@ RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsChatMsgItem) void PrivateOugoingMapItem::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) -{ RS_REGISTER_SERIAL_MEMBER(store); } +{ RS_PROCESS_SERIAL_MEMBER(store); } diff --git a/libretroshare/src/gxstrans/p3gxstransitems.cc b/libretroshare/src/gxstrans/p3gxstransitems.cc index 8ea0f4557..43745aa4d 100644 --- a/libretroshare/src/gxstrans/p3gxstransitems.cc +++ b/libretroshare/src/gxstrans/p3gxstransitems.cc @@ -48,24 +48,24 @@ void OutgoingRecord_deprecated::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t); - RS_REGISTER_SERIAL_MEMBER(recipient); - RS_REGISTER_SERIAL_MEMBER(mailItem); - RS_REGISTER_SERIAL_MEMBER(mailData); - RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t); - RS_REGISTER_SERIAL_MEMBER(presignedReceipt); + RS_PROCESS_SERIAL_MEMBER_TYPED(status, uint8_t); + RS_PROCESS_SERIAL_MEMBER(recipient); + RS_PROCESS_SERIAL_MEMBER(mailItem); + RS_PROCESS_SERIAL_MEMBER(mailData); + RS_PROCESS_SERIAL_MEMBER_TYPED(clientService, uint16_t); + RS_PROCESS_SERIAL_MEMBER(presignedReceipt); } void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) { - RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t); - RS_REGISTER_SERIAL_MEMBER(recipient); - RS_REGISTER_SERIAL_MEMBER(author); - RS_REGISTER_SERIAL_MEMBER(group_id); - RS_REGISTER_SERIAL_MEMBER(sent_ts); - RS_REGISTER_SERIAL_MEMBER(mailItem); - RS_REGISTER_SERIAL_MEMBER(mailData); - RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t); - RS_REGISTER_SERIAL_MEMBER(presignedReceipt); + RS_PROCESS_SERIAL_MEMBER_TYPED(status, uint8_t); + RS_PROCESS_SERIAL_MEMBER(recipient); + RS_PROCESS_SERIAL_MEMBER(author); + RS_PROCESS_SERIAL_MEMBER(group_id); + RS_PROCESS_SERIAL_MEMBER(sent_ts); + RS_PROCESS_SERIAL_MEMBER(mailItem); + RS_PROCESS_SERIAL_MEMBER(mailData); + RS_PROCESS_SERIAL_MEMBER_TYPED(clientService, uint16_t); + RS_PROCESS_SERIAL_MEMBER(presignedReceipt); } diff --git a/libretroshare/src/gxstrans/p3gxstransitems.h b/libretroshare/src/gxstrans/p3gxstransitems.h index f158d0bdd..41b1b2d1b 100644 --- a/libretroshare/src/gxstrans/p3gxstransitems.h +++ b/libretroshare/src/gxstrans/p3gxstransitems.h @@ -55,7 +55,7 @@ public: void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) - { RS_REGISTER_SERIAL_MEMBER_TYPED(mailId, uint64_t); } + { RS_PROCESS_SERIAL_MEMBER_TYPED(mailId, uint64_t); } }; class RsGxsTransPresignedReceipt : public RsGxsTransBaseMsgItem @@ -140,9 +140,9 @@ public: RsGenericSerializer::SerializeContext& ctx ) { RsGxsTransBaseMsgItem::serial_process(j, ctx); - RS_REGISTER_SERIAL_MEMBER_TYPED(cryptoType, uint8_t); - RS_REGISTER_SERIAL_MEMBER(recipientHint); - RS_REGISTER_SERIAL_MEMBER(payload); + RS_PROCESS_SERIAL_MEMBER_TYPED(cryptoType, uint8_t); + RS_PROCESS_SERIAL_MEMBER(recipientHint); + RS_PROCESS_SERIAL_MEMBER(payload); } void clear() diff --git a/libretroshare/src/retroshare/rsgxsifacetypes.h b/libretroshare/src/retroshare/rsgxsifacetypes.h index 659a87e2f..52daf1023 100644 --- a/libretroshare/src/retroshare/rsgxsifacetypes.h +++ b/libretroshare/src/retroshare/rsgxsifacetypes.h @@ -100,24 +100,24 @@ struct RsGroupMetaData : 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); + RS_PROCESS_SERIAL_MEMBER(mGroupId); + RS_PROCESS_SERIAL_MEMBER(mGroupName); + RS_PROCESS_SERIAL_MEMBER(mGroupFlags); + RS_PROCESS_SERIAL_MEMBER(mSignFlags); + RS_PROCESS_SERIAL_MEMBER(mPublishTs); + RS_PROCESS_SERIAL_MEMBER(mAuthorId); + RS_PROCESS_SERIAL_MEMBER(mCircleId); + RS_PROCESS_SERIAL_MEMBER(mCircleType); + RS_PROCESS_SERIAL_MEMBER(mAuthenFlags); + RS_PROCESS_SERIAL_MEMBER(mParentGrpId); + RS_PROCESS_SERIAL_MEMBER(mSubscribeFlags); + RS_PROCESS_SERIAL_MEMBER(mPop); + RS_PROCESS_SERIAL_MEMBER(mVisibleMsgCount); + RS_PROCESS_SERIAL_MEMBER(mLastPost); + RS_PROCESS_SERIAL_MEMBER(mGroupStatus); + RS_PROCESS_SERIAL_MEMBER(mServiceString); + RS_PROCESS_SERIAL_MEMBER(mOriginator); + RS_PROCESS_SERIAL_MEMBER(mInternalCircle); } }; diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index b79cbe8fd..b53c929fc 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -98,10 +98,10 @@ struct GxsReputation : 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); + RS_PROCESS_SERIAL_MEMBER(mOverallScore); + RS_PROCESS_SERIAL_MEMBER(mIdScore); + RS_PROCESS_SERIAL_MEMBER(mOwnOpinion); + RS_PROCESS_SERIAL_MEMBER(mPeerOpinion); } }; @@ -278,13 +278,13 @@ struct RsIdentityUsage : 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); + RS_PROCESS_SERIAL_MEMBER(mServiceId); + RS_PROCESS_SERIAL_MEMBER_TYPED(mUsageCode, uint8_t); + RS_PROCESS_SERIAL_MEMBER(mGrpId); + RS_PROCESS_SERIAL_MEMBER(mMsgId); + RS_PROCESS_SERIAL_MEMBER(mAdditionalId); + RS_PROCESS_SERIAL_MEMBER(mComment); + RS_PROCESS_SERIAL_MEMBER(mHash); } friend class RsTypeSerializer; @@ -329,14 +329,14 @@ struct RsIdentityDetails : 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); + RS_PROCESS_SERIAL_MEMBER(mId); + RS_PROCESS_SERIAL_MEMBER(mNickname); + RS_PROCESS_SERIAL_MEMBER(mFlags); + RS_PROCESS_SERIAL_MEMBER(mPgpId); + //RS_PROCESS_SERIAL_MEMBER_TYPED(mReputation, RsSerializable); + //RS_PROCESS_SERIAL_MEMBER_TYPED(mAvatar, RsSerializable); + RS_PROCESS_SERIAL_MEMBER(mLastUsageTS); + RS_PROCESS_SERIAL_MEMBER(mUseCases); } }; diff --git a/libretroshare/src/rsitems/rsnxsitems.cc b/libretroshare/src/rsitems/rsnxsitems.cc index 91c35ce72..383d36614 100644 --- a/libretroshare/src/rsitems/rsnxsitems.cc +++ b/libretroshare/src/rsitems/rsnxsitems.cc @@ -73,12 +73,12 @@ void RsNxsSyncMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGene void RsNxsMsg::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - RS_REGISTER_SERIAL_MEMBER_TYPED(transactionNumber, uint32_t); - RS_REGISTER_SERIAL_MEMBER_TYPED(pos, uint8_t); - RS_REGISTER_SERIAL_MEMBER(msgId); - RS_REGISTER_SERIAL_MEMBER(grpId); - RS_REGISTER_SERIAL_MEMBER_TYPED(msg, RsTlvItem); - RS_REGISTER_SERIAL_MEMBER_TYPED(meta, RsTlvItem); + RS_PROCESS_SERIAL_MEMBER_TYPED(transactionNumber, uint32_t); + RS_PROCESS_SERIAL_MEMBER_TYPED(pos, uint8_t); + RS_PROCESS_SERIAL_MEMBER(msgId); + RS_PROCESS_SERIAL_MEMBER(grpId); + RS_PROCESS_SERIAL_MEMBER_TYPED(msg, RsTlvItem); + RS_PROCESS_SERIAL_MEMBER_TYPED(meta, RsTlvItem); } void RsNxsGrp::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) diff --git a/libretroshare/src/serialiser/rsserializable.h b/libretroshare/src/serialiser/rsserializable.h index b90e6c666..2c520de4c 100644 --- a/libretroshare/src/serialiser/rsserializable.h +++ b/libretroshare/src/serialiser/rsserializable.h @@ -22,32 +22,33 @@ /** @brief Minimal ancestor for all serializable structs in RetroShare * If you want your struct to be easly serializable you should inherit from this * struct. + * If you want your struct to be serializable as part of a container like an + * `std::vector` @see RS_REGISTER_SERIALIZABLE_TYPE(T) */ 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) + * @see RS_PROCESS_SERIAL_MEMBER(I) + * @see RS_PROCESS_SERIAL_MEMBER_TYPED(I, T) */ virtual void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) = 0; }; -/** @def RS_REGISTER_SERIAL_MEMBER(I) +/** @def RS_PROCESS_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) \ +#define RS_PROCESS_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 +/** @def RS_PROCESS_SERIAL_MEMBER_TYPED(I, T) + * This macro usage is similar to @see RS_PROCESS_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 @@ -56,14 +57,14 @@ struct RsSerializable * 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 + * association with @see RS_PROCESS_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 + * RS_PROCESS_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 {\ +#define RS_PROCESS_SERIAL_MEMBER_TYPED(I, T) do {\ RsTypeSerializer::serial_process(j, ctx, reinterpret_cast(I), #I);\ } while(0) #pragma GCC diagnostic pop @@ -96,13 +97,13 @@ void PrivateOugoingMapItem::serial_process( RsGenericSerializer::SerializeContext& ctx ) { // store is of type - RS_REGISTER_SERIAL_MEMBER(store); + RS_PROCESS_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 + * @see RS_PROCESS_SERIAL_MEMBER_TYPED(I, T) passing RsSerializable as type in * that case. */ #define RS_REGISTER_SERIALIZABLE_TYPE_DEF(T) template<> /*static*/\ diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 6dfb43ce8..d29c80906 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -4510,16 +4510,16 @@ 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); + RS_PROCESS_SERIAL_MEMBER_TYPED(mMeta, RsSerializable); + RS_PROCESS_SERIAL_MEMBER(mPgpIdHash); + //RS_PROCESS_SERIAL_MEMBER(mPgpIdSign); + RS_PROCESS_SERIAL_MEMBER(mRecognTags); + //RS_PROCESS_SERIAL_MEMBER(mImage); + RS_PROCESS_SERIAL_MEMBER(mLastUsageTS); + RS_PROCESS_SERIAL_MEMBER(mPgpKnown); + RS_PROCESS_SERIAL_MEMBER(mIsAContact); + RS_PROCESS_SERIAL_MEMBER(mPgpId); + RS_PROCESS_SERIAL_MEMBER_TYPED(mReputation, RsSerializable); } RsIdentityUsage::RsIdentityUsage( From bc0990e3c8e772e3b0dfe176662f1c5a97bee983 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Sun, 21 Jan 2018 20:52:59 +0100 Subject: [PATCH 04/17] Install rapidJSON in travis CI --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index 90a8f8514..92828940b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,13 @@ matrix: sudo: false before_install: + - wget https://github.com/Tencent/rapidjson/archive/v1.1.0.tar.gz + - tar -xf v1.1.0.tar.gz + - if [ $TRAVIS_OS_NAME == osx ]; then ln -s rapidjson-1.1.0/include/rapidjson/ /usr/local/include/rapidjson ; fi + - if [ $TRAVIS_OS_NAME == linux ]; then sudo cp -r rapidjson-1.1.0/include/rapidjson/ /usr/include/rapidjson ; fi + - find /usr/local/include/ + - find /usr/include/ + - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get update; fi - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get install -y build-essential checkinstall cmake libavutil-dev libavcodec-dev libavformat-dev libbz2-dev libcurl4-openssl-dev libcv-dev libopencv-highgui-dev libhighgui-dev libgnome-keyring-dev libgstreamer-plugins-base0.10-dev libgstreamer0.10-dev libjasper-dev libjpeg-dev libmicrohttpd-dev libopencv-dev libprotobuf-dev libqt4-dev libspeex-dev libspeexdsp-dev libsqlite3-dev libssl-dev libswscale-dev libtbb-dev libtiff4-dev libupnp-dev libv4l-dev libxine-dev libxslt1-dev libxss-dev pkg-config protobuf-compiler python-dev qtmobility-dev gdb ; fi From b95e3380c0501fcaec9e488b08624c4081d43b16 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 22 Jan 2018 11:09:00 +0100 Subject: [PATCH 05/17] Fix Android compilation --- android-prepare-toolchain.sh | 9 +++++++++ .../src/serialiser/rstypeserializer.cc | 20 +++++++++++++++++++ .../src/serialiser/rstypeserializer.h | 2 ++ 3 files changed, 31 insertions(+) diff --git a/android-prepare-toolchain.sh b/android-prepare-toolchain.sh index d89e071e2..13c130c31 100755 --- a/android-prepare-toolchain.sh +++ b/android-prepare-toolchain.sh @@ -145,8 +145,17 @@ build_libmicrohttpd() cd .. } +build_rapidjson() +{ + B_dir="rapidjson-1.1.0" + [ -f $B_dir.tar.gz ] || wget -O $B_dir.tar.gz https://github.com/Tencent/rapidjson/archive/v1.1.0.tar.gz + tar -xf $B_dir.tar.gz + cp -r rapidjson-1.1.0/include/rapidjson/ "${SYSROOT}/usr/include/rapidjson" +} + build_toolchain build_bzlib build_openssl build_sqlite build_libupnp +build_rapidjson diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc index c2b0ba905..68c1cde37 100644 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ b/libretroshare/src/serialiser/rstypeserializer.cc @@ -199,7 +199,27 @@ template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, \ SIMPLE_TO_JSON_DEF(bool) SIMPLE_TO_JSON_DEF(int32_t) + +#ifdef __ANDROID__ +template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, + const time_t& member, RsJson& jDoc ) +{ + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); + + rapidjson::Value key; + key.SetString(memberName.c_str(), memberName.length(), allocator); + + int64_t tValue = member; + rapidjson::Value value(tValue); + + jDoc.AddMember(key, value, allocator); + + return true; +} +#else SIMPLE_TO_JSON_DEF(time_t) +#endif + SIMPLE_TO_JSON_DEF(uint8_t) SIMPLE_TO_JSON_DEF(uint16_t) SIMPLE_TO_JSON_DEF(uint32_t) diff --git a/libretroshare/src/serialiser/rstypeserializer.h b/libretroshare/src/serialiser/rstypeserializer.h index 1de678d50..68adacaf7 100644 --- a/libretroshare/src/serialiser/rstypeserializer.h +++ b/libretroshare/src/serialiser/rstypeserializer.h @@ -36,6 +36,8 @@ #include "serialiser/rsserializable.h" #include +#include // for typeid + /** INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set} * Can't use a template function because T is needed for const_cast */ From 6c40bd4212ad2a9389936d7acbbf11bef6c46ee0 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 22 Jan 2018 12:11:13 +0100 Subject: [PATCH 06/17] Fix Travix CI on mac osx --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 92828940b..864e86a74 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ matrix: before_install: - wget https://github.com/Tencent/rapidjson/archive/v1.1.0.tar.gz - tar -xf v1.1.0.tar.gz - - if [ $TRAVIS_OS_NAME == osx ]; then ln -s rapidjson-1.1.0/include/rapidjson/ /usr/local/include/rapidjson ; fi + - if [ $TRAVIS_OS_NAME == osx ]; then cp -r rapidjson-1.1.0/include/rapidjson/ /usr/local/include/rapidjson ; fi - if [ $TRAVIS_OS_NAME == linux ]; then sudo cp -r rapidjson-1.1.0/include/rapidjson/ /usr/include/rapidjson ; fi - find /usr/local/include/ - find /usr/include/ From 04d32d2f4428d8cafce7afee590ac17f35c4564c Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 22 Jan 2018 12:55:22 +0100 Subject: [PATCH 07/17] Remove duplicated include --- libretroshare/src/serialiser/rstypeserializer.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc index 68c1cde37..9b59d8ade 100644 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ b/libretroshare/src/serialiser/rstypeserializer.cc @@ -32,7 +32,6 @@ #include "util/rsprint.h" #include -#include #include #include #include // for typeid From 9c68bcbca4e2cb25fc028c6f673b142b2209d334 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 22 Jan 2018 14:50:07 +0100 Subject: [PATCH 08/17] Fix some warnings --- libretroshare/src/retroshare/rsidentity.h | 4 ++-- libretroshare/src/serialiser/rstypeserializer.h | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index b53c929fc..d9ec9c5a7 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -42,7 +42,7 @@ #include "util/rsdeprecate.h" /* The Main Interface Class - for information about your Peers */ -class RsIdentity; +struct RsIdentity; extern RsIdentity *rsIdentity; @@ -287,7 +287,7 @@ struct RsIdentityUsage : RsSerializable RS_PROCESS_SERIAL_MEMBER(mHash); } - friend class RsTypeSerializer; + friend struct RsTypeSerializer; private: /** Accessible only to friend class RsTypeSerializer needed for * deserialization */ diff --git a/libretroshare/src/serialiser/rstypeserializer.h b/libretroshare/src/serialiser/rstypeserializer.h index 68adacaf7..452700cf2 100644 --- a/libretroshare/src/serialiser/rstypeserializer.h +++ b/libretroshare/src/serialiser/rstypeserializer.h @@ -332,8 +332,8 @@ struct RsTypeSerializer nullptr, 0, RsGenericSerializer::FORMAT_BINARY, RsGenericSerializer::SERIALIZATION_FLAG_NONE, &allocator ); - ok && (kCtx.mJson. - AddMember("key", kvEl["key"], allocator), true); + if(ok) + kCtx.mJson.AddMember("key", kvEl["key"], allocator); T key; ok = ok && (serial_process(j, kCtx, key, "key"), kCtx.mOk); @@ -342,8 +342,8 @@ struct RsTypeSerializer nullptr, 0, RsGenericSerializer::FORMAT_BINARY, RsGenericSerializer::SERIALIZATION_FLAG_NONE, &allocator ); - ok && (vCtx.mJson. - AddMember("value", kvEl["value"], allocator), true); + if(ok) + vCtx.mJson.AddMember("value", kvEl["value"], allocator); U value; ok = ok && ( serial_process(j, vCtx, value, "value"), @@ -752,7 +752,7 @@ bool RsTypeSerializer::from_JSON( const std::string& membername, { rapidjson::Value& v = jVal[mName]; ret = ret && v.IsString(); - ret && (member = t_RsGenericIdType(std::string(v.GetString())), false); + if(ret) member = t_RsGenericIdType(std::string(v.GetString())); } return ret; } From 443ffb9f85d553da7e06028e88cf2d2ea53f1b15 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 22 Jan 2018 15:02:33 +0100 Subject: [PATCH 09/17] Fix some warnings --- libretroshare/src/chat/distributedchat.h | 2 +- libretroshare/src/grouter/grouterclientservice.h | 2 +- libretroshare/src/grouter/groutermatrix.h | 2 +- libretroshare/src/pqi/pqihandler.h | 2 +- libretroshare/src/pqi/pqiloopback.cc | 2 +- libretroshare/src/pqi/pqiloopback.h | 2 +- libretroshare/src/pqi/pqistreamer.h | 2 +- libretroshare/src/serialiser/rsserial.h | 2 +- libretroshare/src/serialiser/rsserializer.h | 2 +- libretroshare/src/turtle/turtleclientservice.h | 2 +- tests/librssimulator/testing/IsolatedServiceTester.h | 2 +- tests/librssimulator/testing/SetFilter.h | 2 +- tests/librssimulator/testing/SetPacket.h | 2 +- tests/librssimulator/testing/SetServiceTester.h | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libretroshare/src/chat/distributedchat.h b/libretroshare/src/chat/distributedchat.h index ed5a438f9..ca7155dd2 100644 --- a/libretroshare/src/chat/distributedchat.h +++ b/libretroshare/src/chat/distributedchat.h @@ -30,7 +30,7 @@ typedef RsPeerId ChatLobbyVirtualPeerId ; -class RsItem ; +struct RsItem; class p3HistoryMgr ; class p3IdService ; class p3ServiceControl; diff --git a/libretroshare/src/grouter/grouterclientservice.h b/libretroshare/src/grouter/grouterclientservice.h index a6bef29e1..35c22614a 100644 --- a/libretroshare/src/grouter/grouterclientservice.h +++ b/libretroshare/src/grouter/grouterclientservice.h @@ -34,7 +34,7 @@ #include #include -class RsItem ; +struct RsItem; static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_UNKNOWN = 0x0000 ; // unused. static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_RECEIVED = 0x0001 ; // sent when data has been received and a receipt is available. diff --git a/libretroshare/src/grouter/groutermatrix.h b/libretroshare/src/grouter/groutermatrix.h index 99c9ae1bd..cb567b9bc 100644 --- a/libretroshare/src/grouter/groutermatrix.h +++ b/libretroshare/src/grouter/groutermatrix.h @@ -31,7 +31,7 @@ #include "retroshare/rsgrouter.h" #include "groutertypes.h" -class RsItem ; +struct RsItem; // The routing matrix records the event clues received from each friend // diff --git a/libretroshare/src/pqi/pqihandler.h b/libretroshare/src/pqi/pqihandler.h index cf1f19429..c285c4ef7 100644 --- a/libretroshare/src/pqi/pqihandler.h +++ b/libretroshare/src/pqi/pqihandler.h @@ -38,7 +38,7 @@ class PQInterface; class RSTrafficClue; class RsBwRates; -class RsItem; +struct RsItem; class RsRawItem; class SearchModule diff --git a/libretroshare/src/pqi/pqiloopback.cc b/libretroshare/src/pqi/pqiloopback.cc index ba4078ce2..8a8ba342b 100644 --- a/libretroshare/src/pqi/pqiloopback.cc +++ b/libretroshare/src/pqi/pqiloopback.cc @@ -27,7 +27,7 @@ #include // for NULL -class RsItem; +struct RsItem; /*** #define LOOPBACK_DEBUG 1 diff --git a/libretroshare/src/pqi/pqiloopback.h b/libretroshare/src/pqi/pqiloopback.h index 7186dd440..82c3923d8 100644 --- a/libretroshare/src/pqi/pqiloopback.h +++ b/libretroshare/src/pqi/pqiloopback.h @@ -31,7 +31,7 @@ #include "pqi/pqi_base.h" // for NetInterface (ptr only), PQInterface #include "retroshare/rstypes.h" // for RsPeerId -class RsItem; +struct RsItem; class pqiloopback: public PQInterface { diff --git a/libretroshare/src/pqi/pqistreamer.h b/libretroshare/src/pqi/pqistreamer.h index fe2754854..9908651b2 100644 --- a/libretroshare/src/pqi/pqistreamer.h +++ b/libretroshare/src/pqi/pqistreamer.h @@ -38,7 +38,7 @@ #include "retroshare/rstypes.h" // for RsPeerId #include "util/rsthreads.h" // for RsMutex -class RsItem; +struct RsItem; class RsSerialiser; struct PartialPacketRecord diff --git a/libretroshare/src/serialiser/rsserial.h b/libretroshare/src/serialiser/rsserial.h index 206f69608..ee3a79537 100644 --- a/libretroshare/src/serialiser/rsserial.h +++ b/libretroshare/src/serialiser/rsserial.h @@ -64,7 +64,7 @@ const uint8_t RS_PKT_CLASS_CONFIG = 0x02; const uint8_t RS_PKT_SUBTYPE_DEFAULT = 0x01; /* if only one subtype */ -class RsItem ; +struct RsItem; class RsSerialType ; diff --git a/libretroshare/src/serialiser/rsserializer.h b/libretroshare/src/serialiser/rsserializer.h index 63b565a9b..dcc4d089f 100644 --- a/libretroshare/src/serialiser/rsserializer.h +++ b/libretroshare/src/serialiser/rsserializer.h @@ -160,7 +160,7 @@ #include "serialiser/rsserial.h" #include "util/rsdeprecate.h" -class RsItem ; +struct RsItem; #define SERIALIZE_ERROR() std::cerr << __PRETTY_FUNCTION__ << " : " diff --git a/libretroshare/src/turtle/turtleclientservice.h b/libretroshare/src/turtle/turtleclientservice.h index d9552c662..51a9dbdc3 100644 --- a/libretroshare/src/turtle/turtleclientservice.h +++ b/libretroshare/src/turtle/turtleclientservice.h @@ -36,7 +36,7 @@ #include #include -class RsItem ; +struct RsItem; class p3turtle ; class RsTurtleClientService diff --git a/tests/librssimulator/testing/IsolatedServiceTester.h b/tests/librssimulator/testing/IsolatedServiceTester.h index aca9695ed..3fa5e2afc 100644 --- a/tests/librssimulator/testing/IsolatedServiceTester.h +++ b/tests/librssimulator/testing/IsolatedServiceTester.h @@ -4,7 +4,7 @@ #include "retroshare/rsids.h" #include "pqi/p3linkmgr.h" -class RsItem; +struct RsItem; class PeerNode; class RsSerialType; class RsSerialiser; diff --git a/tests/librssimulator/testing/SetFilter.h b/tests/librssimulator/testing/SetFilter.h index 9b9a8b15d..50df26955 100644 --- a/tests/librssimulator/testing/SetFilter.h +++ b/tests/librssimulator/testing/SetFilter.h @@ -4,7 +4,7 @@ #include "retroshare/rsids.h" #include "SetPacket.h" -class RsItem; +struct RsItem; class SetFilter { diff --git a/tests/librssimulator/testing/SetPacket.h b/tests/librssimulator/testing/SetPacket.h index ae529f37b..1e377191e 100644 --- a/tests/librssimulator/testing/SetPacket.h +++ b/tests/librssimulator/testing/SetPacket.h @@ -5,7 +5,7 @@ #include #include "retroshare/rsids.h" -class RsItem; +struct RsItem; class SetPacket { diff --git a/tests/librssimulator/testing/SetServiceTester.h b/tests/librssimulator/testing/SetServiceTester.h index ad03aed4e..862fc43e0 100644 --- a/tests/librssimulator/testing/SetServiceTester.h +++ b/tests/librssimulator/testing/SetServiceTester.h @@ -8,7 +8,7 @@ #include "SetPacket.h" #include "SetFilter.h" -class RsItem; +struct RsItem; class PeerNode; class RsSerialType; class RsSerialiser; From 76b607c210589006ebd8de7e1ad6d90b3b34ed87 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 22 Jan 2018 15:26:18 +0100 Subject: [PATCH 10/17] Fix warning in libresapi --- libresapi/src/api/FileSharingHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libresapi/src/api/FileSharingHandler.cpp b/libresapi/src/api/FileSharingHandler.cpp index d948a9511..dff941c1b 100644 --- a/libresapi/src/api/FileSharingHandler.cpp +++ b/libresapi/src/api/FileSharingHandler.cpp @@ -54,7 +54,7 @@ void FileSharingHandler::handleForceCheck(Request&, Response& resp) resp.setOk(); } -void FileSharingHandler::handleGetSharedDir(Request& req, Response& resp) +void FileSharingHandler::handleGetSharedDir(Request& /*req*/, Response& resp) { DirDetails dirDetails; mRsFiles->RequestDirDetails(NULL, dirDetails, RS_FILE_HINTS_LOCAL); From 234625ad28e9189cd96a90d42a37e942845b2efb Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 22 Jan 2018 21:50:51 +0100 Subject: [PATCH 11/17] Remove extra debugging in Travis CI --- .travis.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 864e86a74..2a173b915 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,13 +12,6 @@ matrix: sudo: false before_install: - - wget https://github.com/Tencent/rapidjson/archive/v1.1.0.tar.gz - - tar -xf v1.1.0.tar.gz - - if [ $TRAVIS_OS_NAME == osx ]; then cp -r rapidjson-1.1.0/include/rapidjson/ /usr/local/include/rapidjson ; fi - - if [ $TRAVIS_OS_NAME == linux ]; then sudo cp -r rapidjson-1.1.0/include/rapidjson/ /usr/include/rapidjson ; fi - - find /usr/local/include/ - - find /usr/include/ - - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get update; fi - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get install -y build-essential checkinstall cmake libavutil-dev libavcodec-dev libavformat-dev libbz2-dev libcurl4-openssl-dev libcv-dev libopencv-highgui-dev libhighgui-dev libgnome-keyring-dev libgstreamer-plugins-base0.10-dev libgstreamer0.10-dev libjasper-dev libjpeg-dev libmicrohttpd-dev libopencv-dev libprotobuf-dev libqt4-dev libspeex-dev libspeexdsp-dev libsqlite3-dev libssl-dev libswscale-dev libtbb-dev libtiff4-dev libupnp-dev libv4l-dev libxine-dev libxslt1-dev libxss-dev pkg-config protobuf-compiler python-dev qtmobility-dev gdb ; fi @@ -38,6 +31,11 @@ before_install: - if [ $TRAVIS_OS_NAME == osx ]; then ln -s /usr/local/opt/openssl/lib/*.a /usr/local/lib/; fi - if [ $TRAVIS_OS_NAME == osx ]; then ln -s /usr/local/opt/openssl/lib/*.dylib /usr/local/lib/; fi + - wget https://github.com/Tencent/rapidjson/archive/v1.1.0.tar.gz + - tar -xf v1.1.0.tar.gz + - if [ $TRAVIS_OS_NAME == osx ]; then cp -r rapidjson-1.1.0/include/rapidjson/ /usr/local/include/rapidjson ; fi + - if [ $TRAVIS_OS_NAME == linux ]; then sudo cp -r rapidjson-1.1.0/include/rapidjson/ /usr/include/rapidjson ; fi + # - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get update && sudo apt-get install -y llvm-3.4 llvm-3.4-dev; fi # - rvm use $RVM --install --binary --fuzzy # - gem update --system From 7409de5170b4bb9f3b62c33c98d69fe5265a37a5 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 22 Jan 2018 21:53:12 +0100 Subject: [PATCH 12/17] Fix compilation on systems with atipic time_t --- libretroshare/src/serialiser/rstypeserializer.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc index 9b59d8ade..88585e45a 100644 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ b/libretroshare/src/serialiser/rstypeserializer.cc @@ -199,7 +199,6 @@ template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, \ SIMPLE_TO_JSON_DEF(bool) SIMPLE_TO_JSON_DEF(int32_t) -#ifdef __ANDROID__ template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, const time_t& member, RsJson& jDoc ) { @@ -208,6 +207,7 @@ template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, rapidjson::Value key; key.SetString(memberName.c_str(), memberName.length(), allocator); + // without this compilation may break depending on how time_t is defined int64_t tValue = member; rapidjson::Value value(tValue); @@ -215,9 +215,6 @@ template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, return true; } -#else -SIMPLE_TO_JSON_DEF(time_t) -#endif SIMPLE_TO_JSON_DEF(uint8_t) SIMPLE_TO_JSON_DEF(uint16_t) From 13d4a2c9162ab2ba74249c0fe4ed6bdb1a817e01 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Thu, 25 Jan 2018 11:37:16 +0100 Subject: [PATCH 13/17] Safer and elgant serial helper macros --- libretroshare/src/chat/rschatitems.cc | 2 +- libretroshare/src/gxstrans/p3gxstransitems.cc | 30 +++--- libretroshare/src/gxstrans/p3gxstransitems.h | 8 +- .../src/retroshare/rsgxsifacetypes.h | 36 +++---- libretroshare/src/retroshare/rsidentity.h | 38 +++---- libretroshare/src/rsitems/rsnxsitems.cc | 12 +-- libretroshare/src/serialiser/rsserializable.h | 102 ++++++++++-------- libretroshare/src/services/p3idservice.cc | 20 ++-- 8 files changed, 133 insertions(+), 115 deletions(-) diff --git a/libretroshare/src/chat/rschatitems.cc b/libretroshare/src/chat/rschatitems.cc index 00511c1f8..1eee404b6 100644 --- a/libretroshare/src/chat/rschatitems.cc +++ b/libretroshare/src/chat/rschatitems.cc @@ -212,4 +212,4 @@ RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsChatMsgItem) void PrivateOugoingMapItem::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) -{ RS_PROCESS_SERIAL_MEMBER(store); } +{ RS_SERIAL_PROCESS(store); } diff --git a/libretroshare/src/gxstrans/p3gxstransitems.cc b/libretroshare/src/gxstrans/p3gxstransitems.cc index 43745aa4d..1db07c70a 100644 --- a/libretroshare/src/gxstrans/p3gxstransitems.cc +++ b/libretroshare/src/gxstrans/p3gxstransitems.cc @@ -48,24 +48,24 @@ void OutgoingRecord_deprecated::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - RS_PROCESS_SERIAL_MEMBER_TYPED(status, uint8_t); - RS_PROCESS_SERIAL_MEMBER(recipient); - RS_PROCESS_SERIAL_MEMBER(mailItem); - RS_PROCESS_SERIAL_MEMBER(mailData); - RS_PROCESS_SERIAL_MEMBER_TYPED(clientService, uint16_t); - RS_PROCESS_SERIAL_MEMBER(presignedReceipt); + RS_SERIAL_PROCESS(status); + RS_SERIAL_PROCESS(recipient); + RS_SERIAL_PROCESS(mailItem); + RS_SERIAL_PROCESS(mailData); + RS_SERIAL_PROCESS(clientService); + RS_SERIAL_PROCESS(presignedReceipt); } void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) { - RS_PROCESS_SERIAL_MEMBER_TYPED(status, uint8_t); - RS_PROCESS_SERIAL_MEMBER(recipient); - RS_PROCESS_SERIAL_MEMBER(author); - RS_PROCESS_SERIAL_MEMBER(group_id); - RS_PROCESS_SERIAL_MEMBER(sent_ts); - RS_PROCESS_SERIAL_MEMBER(mailItem); - RS_PROCESS_SERIAL_MEMBER(mailData); - RS_PROCESS_SERIAL_MEMBER_TYPED(clientService, uint16_t); - RS_PROCESS_SERIAL_MEMBER(presignedReceipt); + RS_SERIAL_PROCESS(status); + RS_SERIAL_PROCESS(recipient); + RS_SERIAL_PROCESS(author); + RS_SERIAL_PROCESS(group_id); + RS_SERIAL_PROCESS(sent_ts); + RS_SERIAL_PROCESS(mailItem); + RS_SERIAL_PROCESS(mailData); + RS_SERIAL_PROCESS(clientService); + RS_SERIAL_PROCESS(presignedReceipt); } diff --git a/libretroshare/src/gxstrans/p3gxstransitems.h b/libretroshare/src/gxstrans/p3gxstransitems.h index 41b1b2d1b..bd13c9e71 100644 --- a/libretroshare/src/gxstrans/p3gxstransitems.h +++ b/libretroshare/src/gxstrans/p3gxstransitems.h @@ -55,7 +55,7 @@ public: void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) - { RS_PROCESS_SERIAL_MEMBER_TYPED(mailId, uint64_t); } + { RS_SERIAL_PROCESS(mailId); } }; class RsGxsTransPresignedReceipt : public RsGxsTransBaseMsgItem @@ -140,9 +140,9 @@ public: RsGenericSerializer::SerializeContext& ctx ) { RsGxsTransBaseMsgItem::serial_process(j, ctx); - RS_PROCESS_SERIAL_MEMBER_TYPED(cryptoType, uint8_t); - RS_PROCESS_SERIAL_MEMBER(recipientHint); - RS_PROCESS_SERIAL_MEMBER(payload); + RS_SERIAL_PROCESS(cryptoType); + RS_SERIAL_PROCESS(recipientHint); + RS_SERIAL_PROCESS(payload); } void clear() diff --git a/libretroshare/src/retroshare/rsgxsifacetypes.h b/libretroshare/src/retroshare/rsgxsifacetypes.h index 52daf1023..18637f1b1 100644 --- a/libretroshare/src/retroshare/rsgxsifacetypes.h +++ b/libretroshare/src/retroshare/rsgxsifacetypes.h @@ -100,24 +100,24 @@ struct RsGroupMetaData : RsSerializable void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - RS_PROCESS_SERIAL_MEMBER(mGroupId); - RS_PROCESS_SERIAL_MEMBER(mGroupName); - RS_PROCESS_SERIAL_MEMBER(mGroupFlags); - RS_PROCESS_SERIAL_MEMBER(mSignFlags); - RS_PROCESS_SERIAL_MEMBER(mPublishTs); - RS_PROCESS_SERIAL_MEMBER(mAuthorId); - RS_PROCESS_SERIAL_MEMBER(mCircleId); - RS_PROCESS_SERIAL_MEMBER(mCircleType); - RS_PROCESS_SERIAL_MEMBER(mAuthenFlags); - RS_PROCESS_SERIAL_MEMBER(mParentGrpId); - RS_PROCESS_SERIAL_MEMBER(mSubscribeFlags); - RS_PROCESS_SERIAL_MEMBER(mPop); - RS_PROCESS_SERIAL_MEMBER(mVisibleMsgCount); - RS_PROCESS_SERIAL_MEMBER(mLastPost); - RS_PROCESS_SERIAL_MEMBER(mGroupStatus); - RS_PROCESS_SERIAL_MEMBER(mServiceString); - RS_PROCESS_SERIAL_MEMBER(mOriginator); - RS_PROCESS_SERIAL_MEMBER(mInternalCircle); + RS_SERIAL_PROCESS(mGroupId); + RS_SERIAL_PROCESS(mGroupName); + RS_SERIAL_PROCESS(mGroupFlags); + RS_SERIAL_PROCESS(mSignFlags); + RS_SERIAL_PROCESS(mPublishTs); + RS_SERIAL_PROCESS(mAuthorId); + RS_SERIAL_PROCESS(mCircleId); + RS_SERIAL_PROCESS(mCircleType); + RS_SERIAL_PROCESS(mAuthenFlags); + RS_SERIAL_PROCESS(mParentGrpId); + RS_SERIAL_PROCESS(mSubscribeFlags); + RS_SERIAL_PROCESS(mPop); + RS_SERIAL_PROCESS(mVisibleMsgCount); + RS_SERIAL_PROCESS(mLastPost); + RS_SERIAL_PROCESS(mGroupStatus); + RS_SERIAL_PROCESS(mServiceString); + RS_SERIAL_PROCESS(mOriginator); + RS_SERIAL_PROCESS(mInternalCircle); } }; diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index d9ec9c5a7..f021252b3 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -98,10 +98,10 @@ struct GxsReputation : RsSerializable void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - RS_PROCESS_SERIAL_MEMBER(mOverallScore); - RS_PROCESS_SERIAL_MEMBER(mIdScore); - RS_PROCESS_SERIAL_MEMBER(mOwnOpinion); - RS_PROCESS_SERIAL_MEMBER(mPeerOpinion); + RS_SERIAL_PROCESS(mOverallScore); + RS_SERIAL_PROCESS(mIdScore); + RS_SERIAL_PROCESS(mOwnOpinion); + RS_SERIAL_PROCESS(mPeerOpinion); } }; @@ -278,13 +278,13 @@ struct RsIdentityUsage : RsSerializable void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - RS_PROCESS_SERIAL_MEMBER(mServiceId); - RS_PROCESS_SERIAL_MEMBER_TYPED(mUsageCode, uint8_t); - RS_PROCESS_SERIAL_MEMBER(mGrpId); - RS_PROCESS_SERIAL_MEMBER(mMsgId); - RS_PROCESS_SERIAL_MEMBER(mAdditionalId); - RS_PROCESS_SERIAL_MEMBER(mComment); - RS_PROCESS_SERIAL_MEMBER(mHash); + RS_SERIAL_PROCESS(mServiceId); + RS_SERIAL_PROCESS(mUsageCode); + RS_SERIAL_PROCESS(mGrpId); + RS_SERIAL_PROCESS(mMsgId); + RS_SERIAL_PROCESS(mAdditionalId); + RS_SERIAL_PROCESS(mComment); + RS_SERIAL_PROCESS(mHash); } friend struct RsTypeSerializer; @@ -329,14 +329,14 @@ struct RsIdentityDetails : RsSerializable virtual void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) { - RS_PROCESS_SERIAL_MEMBER(mId); - RS_PROCESS_SERIAL_MEMBER(mNickname); - RS_PROCESS_SERIAL_MEMBER(mFlags); - RS_PROCESS_SERIAL_MEMBER(mPgpId); - //RS_PROCESS_SERIAL_MEMBER_TYPED(mReputation, RsSerializable); - //RS_PROCESS_SERIAL_MEMBER_TYPED(mAvatar, RsSerializable); - RS_PROCESS_SERIAL_MEMBER(mLastUsageTS); - RS_PROCESS_SERIAL_MEMBER(mUseCases); + RS_SERIAL_PROCESS(mId); + RS_SERIAL_PROCESS(mNickname); + RS_SERIAL_PROCESS(mFlags); + RS_SERIAL_PROCESS(mPgpId); + //RS_SERIAL_PROCESS(mReputation); + //RS_SERIAL_PROCESS(mAvatar); + RS_SERIAL_PROCESS(mLastUsageTS); + RS_SERIAL_PROCESS(mUseCases); } }; diff --git a/libretroshare/src/rsitems/rsnxsitems.cc b/libretroshare/src/rsitems/rsnxsitems.cc index 383d36614..8c6775275 100644 --- a/libretroshare/src/rsitems/rsnxsitems.cc +++ b/libretroshare/src/rsitems/rsnxsitems.cc @@ -73,12 +73,12 @@ void RsNxsSyncMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGene void RsNxsMsg::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - RS_PROCESS_SERIAL_MEMBER_TYPED(transactionNumber, uint32_t); - RS_PROCESS_SERIAL_MEMBER_TYPED(pos, uint8_t); - RS_PROCESS_SERIAL_MEMBER(msgId); - RS_PROCESS_SERIAL_MEMBER(grpId); - RS_PROCESS_SERIAL_MEMBER_TYPED(msg, RsTlvItem); - RS_PROCESS_SERIAL_MEMBER_TYPED(meta, RsTlvItem); + RS_SERIAL_PROCESS(transactionNumber); + RS_SERIAL_PROCESS(pos); + RS_SERIAL_PROCESS(msgId); + RS_SERIAL_PROCESS(grpId); + RS_SERIAL_PROCESS(msg); + RS_SERIAL_PROCESS(meta); } void RsNxsGrp::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) diff --git a/libretroshare/src/serialiser/rsserializable.h b/libretroshare/src/serialiser/rsserializable.h index 2c520de4c..acfe995af 100644 --- a/libretroshare/src/serialiser/rsserializable.h +++ b/libretroshare/src/serialiser/rsserializable.h @@ -17,60 +17,48 @@ * along with this program. If not, see . */ +#include + #include "serialiser/rsserializer.h" -/** @brief Minimal ancestor for all serializable structs in RetroShare + +/** @brief Minimal ancestor for all serializable structs in RetroShare. * If you want your struct to be easly serializable you should inherit from this * struct. * If you want your struct to be serializable as part of a container like an - * `std::vector` @see RS_REGISTER_SERIALIZABLE_TYPE(T) + * `std::vector` @see RS_REGISTER_SERIALIZABLE_TYPE_DEF(T) and + * @see RS_REGISTER_SERIALIZABLE_TYPE_DECL(T) */ struct RsSerializable { /** Register struct members to serialize in this method taking advantage of - * the helper macros - * @see RS_PROCESS_SERIAL_MEMBER(I) - * @see RS_PROCESS_SERIAL_MEMBER_TYPED(I, T) + * the helper macro @see RS_SERIAL_PROCESS(I) */ virtual void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) = 0; }; -/** @def RS_PROCESS_SERIAL_MEMBER(I) +/** @def RS_SERIAL_PROCESS(I) * Use this macro to register the members of `YourSerializable` for serial * processing inside `YourSerializable::serial_process(j, ctx)` * + * Pay special attention for member of enum type which must be declared + * specifying the underlying type otherwise the serialization format may differ + * in an uncompatible way depending on the compiler/platform. + * + * If your member is a derivative of RsSerializable in some cases it may be + * convenient also to register your item type with + * @see RS_REGISTER_SERIALIZABLE_TYPE_DEF(T). + * * Inspired by http://stackoverflow.com/a/39345864 */ -#define RS_PROCESS_SERIAL_MEMBER(I) \ - do { RsTypeSerializer::serial_process(j, ctx, I, #I); } while(0) - - -/** @def RS_PROCESS_SERIAL_MEMBER_TYPED(I, T) - * This macro usage is similar to @see RS_PROCESS_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_PROCESS_SERIAL_MEMBER(I) that rely on template - * function generation, as in this particular case - * RS_PROCESS_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_PROCESS_SERIAL_MEMBER_TYPED(I, T) do {\ - RsTypeSerializer::serial_process(j, ctx, reinterpret_cast(I), #I);\ +#define RS_SERIAL_PROCESS(I) do { \ + RsTypeSerializer::serial_process(j, ctx, __priv_to_RS_S_TYPE(I), #I ); \ } while(0) -#pragma GCC diagnostic pop -/** @def RS_REGISTER_SERIALIZABLE_TYPE(T) +/** @def RS_REGISTER_SERIALIZABLE_TYPE_DEF(T) * Use this macro into `youritem.cc` only if you need to process members of * subtypes of RsSerializable. * @@ -90,21 +78,15 @@ struct PrivateOugoingMapItem : RsChatItem std::map store; }; -RS_REGISTER_SERIALIZABLE_TYPE(RsChatMsgItem) +RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsChatMsgItem) void PrivateOugoingMapItem::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - // store is of type - RS_PROCESS_SERIAL_MEMBER(store); + RS_SERIAL_PROCESS(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_PROCESS_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( \ @@ -118,11 +100,11 @@ void PrivateOugoingMapItem::serial_process( /** @def RS_REGISTER_SERIALIZABLE_TYPE_DECL(T) - * The usage of this macro into your header file is needed only in case you + * The usage of this macro into your header file may be 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. + * from_JSON for your RsSerializable derived type. * * One example of such case is RsIdentityUsage that is declared in * retroshare/rsidentity.h but defined in services/p3idservice.cc, also if @@ -135,4 +117,40 @@ void PrivateOugoingMapItem::serial_process( void RsTypeSerializer::serial_process( \ RsGenericSerializer::SerializeJob j,\ RsGenericSerializer::SerializeContext& ctx, T& item,\ - const std::string& /*objName*/ ); + const std::string& objName ); + + +//============================================================================// +// Private type conversion helpers // +//============================================================================// + +/** + * @brief Privates type conversion helpers for RS_SERIAL_PROCESS. + * @private DO NOT use explicitely outside this file. + * Used to cast enums and derived type to matching types supported by + * RsTypeSerializer::serial_process(...) templated methods. + */ +template::value>::type> +inline typename std::underlying_type::type& __priv_to_RS_S_TYPE(T& i) +{ + return reinterpret_cast::type&>(i); +} + +template::value>::type> +inline RsSerializable& __priv_to_RS_S_TYPE(T& i) +{ + return static_cast(i); +} + +struct RsTlvItem; +template::value>::type> +inline RsTlvItem& __priv_to_RS_S_TYPE(T& i) +{ + return static_cast(i); +} + +template::value||std::is_base_of::value||std::is_base_of::value)>::type> +inline T& __priv_to_RS_S_TYPE(T& i) +{ + return i; +} diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index d29c80906..4796b3005 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -4510,16 +4510,16 @@ void RsGxsIdGroup::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - RS_PROCESS_SERIAL_MEMBER_TYPED(mMeta, RsSerializable); - RS_PROCESS_SERIAL_MEMBER(mPgpIdHash); - //RS_PROCESS_SERIAL_MEMBER(mPgpIdSign); - RS_PROCESS_SERIAL_MEMBER(mRecognTags); - //RS_PROCESS_SERIAL_MEMBER(mImage); - RS_PROCESS_SERIAL_MEMBER(mLastUsageTS); - RS_PROCESS_SERIAL_MEMBER(mPgpKnown); - RS_PROCESS_SERIAL_MEMBER(mIsAContact); - RS_PROCESS_SERIAL_MEMBER(mPgpId); - RS_PROCESS_SERIAL_MEMBER_TYPED(mReputation, RsSerializable); + RS_SERIAL_PROCESS(mMeta); + RS_SERIAL_PROCESS(mPgpIdHash); + //RS_SERIAL_PROCESS(mPgpIdSign); + RS_SERIAL_PROCESS(mRecognTags); + //RS_SERIAL_PROCESS(mImage); + RS_SERIAL_PROCESS(mLastUsageTS); + RS_SERIAL_PROCESS(mPgpKnown); + RS_SERIAL_PROCESS(mIsAContact); + RS_SERIAL_PROCESS(mPgpId); + RS_SERIAL_PROCESS(mReputation); } RsIdentityUsage::RsIdentityUsage( From ba6f2d7e816208db4a98feff6c44521cfc00128c Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Fri, 26 Jan 2018 17:18:05 +0100 Subject: [PATCH 14/17] Remove default template for to/from_JSON This way the compiler will complain if a type is added directly to RsTypeSerializer without specify all needed serial operations --- .../src/gxstunnel/rsgxstunnelitems.cc | 3 + libretroshare/src/retroshare/rstypes.h | 35 +++++++--- libretroshare/src/rsitems/rsconfigitems.cc | 29 +------- .../src/rsitems/rsfiletransferitems.cc | 42 ----------- libretroshare/src/rsitems/rsgxsupdateitems.cc | 23 +----- libretroshare/src/rsitems/rsgxsupdateitems.h | 23 +++--- libretroshare/src/rsserver/rstypes.cc | 2 +- .../src/serialiser/rstypeserializer.cc | 37 ++++++++-- .../src/serialiser/rstypeserializer.h | 70 +++++++++++-------- libretroshare/src/turtle/rsturtleitem.cc | 6 ++ 10 files changed, 126 insertions(+), 144 deletions(-) diff --git a/libretroshare/src/gxstunnel/rsgxstunnelitems.cc b/libretroshare/src/gxstunnel/rsgxstunnelitems.cc index 8e488c190..d653b03ea 100644 --- a/libretroshare/src/gxstunnel/rsgxstunnelitems.cc +++ b/libretroshare/src/gxstunnel/rsgxstunnelitems.cc @@ -102,6 +102,9 @@ template<> void RsTypeSerializer::print_data(const std::string& name,BIGNUM std::cerr << "[BIGNUM] : " << name << std::endl; } +RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(BIGNUM*) +RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(BIGNUM*) + void RsGxsTunnelStatusItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { RsTypeSerializer::serial_process(j,ctx,status,"status") ; diff --git a/libretroshare/src/retroshare/rstypes.h b/libretroshare/src/retroshare/rstypes.h index 9c098db59..84c3fc45d 100644 --- a/libretroshare/src/retroshare/rstypes.h +++ b/libretroshare/src/retroshare/rstypes.h @@ -36,6 +36,8 @@ #include #include +#include +#include #define USE_NEW_CHUNK_CHECKING_CODE @@ -118,13 +120,21 @@ class Condition std::string name; }; -class PeerBandwidthLimits +struct PeerBandwidthLimits : RsSerializable { -public: - PeerBandwidthLimits() : max_up_rate_kbs(0), max_dl_rate_kbs(0) {} - - uint32_t max_up_rate_kbs ; - uint32_t max_dl_rate_kbs ; + PeerBandwidthLimits() : max_up_rate_kbs(0), max_dl_rate_kbs(0) {} + + uint32_t max_up_rate_kbs; + uint32_t max_dl_rate_kbs; + + + /// @see RsSerializable + void serial_process(RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) + { + RS_SERIAL_PROCESS(max_up_rate_kbs); + RS_SERIAL_PROCESS(max_dl_rate_kbs); + } }; //class SearchRequest // unused stuff. @@ -295,7 +305,7 @@ class FileChunksInfo std::map > pending_slices ; }; -class CompressedChunkMap +class CompressedChunkMap : public RsSerializable { public: CompressedChunkMap() {} @@ -345,10 +355,17 @@ class CompressedChunkMap inline void set(uint32_t j) { _map[j >> 5] |= (1 << (j & 31)) ; } inline void reset(uint32_t j) { _map[j >> 5] &= ~(1 << (j & 31)) ; } - /// compressed map, one bit per chunk - std::vector _map ; + /// compressed map, one bit per chunk + std::vector _map; + + /// @see RsSerializable + void serial_process(RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) + { RS_SERIAL_PROCESS(_map); } }; +RS_REGISTER_SERIALIZABLE_TYPE_DECL(CompressedChunkMap) + template class t_CRCMap { public: diff --git a/libretroshare/src/rsitems/rsconfigitems.cc b/libretroshare/src/rsitems/rsconfigitems.cc index f6296bd04..b673b354a 100644 --- a/libretroshare/src/rsitems/rsconfigitems.cc +++ b/libretroshare/src/rsitems/rsconfigitems.cc @@ -28,6 +28,7 @@ #include "rsitems/rsconfigitems.h" #include "retroshare/rspeers.h" // Needed for RsGroupInfo. +#include "serialiser/rsserializable.h" #include "serialiser/rstypeserializer.h" /*** * #define RSSERIAL_DEBUG 1 @@ -89,7 +90,7 @@ void RsFileTransfer::serial_process(RsGenericSerializer::SerializeJob j,RsGeneri RsTypeSerializer::serial_process (j,ctx,flags,"flags") ; RsTypeSerializer::serial_process (j,ctx,chunk_strategy,"chunk_strategy") ; - RsTypeSerializer::serial_process (j,ctx,compressed_chunk_map,"compressed_chunk_map") ; + RS_SERIAL_PROCESS(compressed_chunk_map); } void RsFileConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) @@ -192,31 +193,7 @@ void RsPeerStunItem::serial_process(RsGenericSerializer::SerializeJob j,RsGeneri RsTypeSerializer::serial_process(j,ctx,stunList,"stunList") ; } -template<> uint32_t RsTypeSerializer::serial_size(const PeerBandwidthLimits& /*s*/) -{ - return 4+4 ; -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,const PeerBandwidthLimits& s) -{ - bool ok = true ; - ok = ok && setRawUInt32(data,size,&offset,s.max_up_rate_kbs); - ok = ok && setRawUInt32(data,size,&offset,s.max_dl_rate_kbs); - return ok; -} - -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,PeerBandwidthLimits& s) -{ - bool ok = true ; - ok = ok && getRawUInt32(data,size,&offset,&s.max_up_rate_kbs); - ok = ok && getRawUInt32(data,size,&offset,&s.max_dl_rate_kbs); - return ok; -} - -template<> void RsTypeSerializer::print_data(const std::string& /*n*/, const PeerBandwidthLimits& s) -{ - std::cerr << " [Peer BW limit] " << s.max_up_rate_kbs << " / " << s.max_dl_rate_kbs << std::endl; -} +RS_REGISTER_SERIALIZABLE_TYPE_DEF(PeerBandwidthLimits) RsNodeGroupItem::RsNodeGroupItem(const RsGroupInfo& g) :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_NODE_GROUP) diff --git a/libretroshare/src/rsitems/rsfiletransferitems.cc b/libretroshare/src/rsitems/rsfiletransferitems.cc index 7579c9560..4241081a7 100644 --- a/libretroshare/src/rsitems/rsfiletransferitems.cc +++ b/libretroshare/src/rsitems/rsfiletransferitems.cc @@ -91,48 +91,6 @@ void RsFileTransferSingleChunkCrcItem::serial_process(RsGenericSerializer::Seria RsTypeSerializer::serial_process (j,ctx,check_sum, "check_sum") ; } -//===================================================================================================// -// CompressedChunkMap // -//===================================================================================================// - -template<> uint32_t RsTypeSerializer::serial_size(const CompressedChunkMap& s) -{ - return 4 + 4*s._map.size() ; -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,const CompressedChunkMap& s) -{ - bool ok = true ; - - ok &= setRawUInt32(data, size, &offset, s._map.size()); - - for(uint32_t i=0;i bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,CompressedChunkMap& s) -{ - uint32_t S =0; - bool ok = getRawUInt32(data, size, &offset, &S); - - if(ok) - { - s._map.resize(S) ; - - for(uint32_t i=0;i void RsTypeSerializer::print_data(const std::string& n, const CompressedChunkMap& s) -{ - std::cerr << " [Compressed chunk map] " << n << " : length=" << s._map.size() << std::endl; -} - //===================================================================================================// // Serializer // //===================================================================================================// diff --git a/libretroshare/src/rsitems/rsgxsupdateitems.cc b/libretroshare/src/rsitems/rsgxsupdateitems.cc index 50f154cb2..6e18ed774 100644 --- a/libretroshare/src/rsitems/rsgxsupdateitems.cc +++ b/libretroshare/src/rsitems/rsgxsupdateitems.cc @@ -97,30 +97,9 @@ void RsGxsMsgUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGe RsTypeSerializer::serial_process(j,ctx,msgUpdateInfos,"msgUpdateInfos"); } -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - bool ok = true ; +RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsGxsMsgUpdate::MsgUpdateInfo) - ok = ok && setRawUInt32(data,size,&offset,info.time_stamp); - ok = ok && setRawUInt32(data,size,&offset,info.message_count); - return ok; -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - bool ok = true ; - - ok = ok && getRawUInt32(data,size,&offset,&info.time_stamp); - ok = ok && getRawUInt32(data,size,&offset,&info.message_count); - - return ok; -} -template<> uint32_t RsTypeSerializer::serial_size(const RsGxsMsgUpdateItem::MsgUpdateInfo& /* info */) { return 8; } - -template<> void RsTypeSerializer::print_data(const std::string& name,const RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - std::cerr << "[MsgUpdateInfo]: " << name << ": " << info.time_stamp << ", " << info.message_count << std::endl; -} void RsGxsServerMsgUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { diff --git a/libretroshare/src/rsitems/rsgxsupdateitems.h b/libretroshare/src/rsitems/rsgxsupdateitems.h index c9725426c..e0549b2b3 100644 --- a/libretroshare/src/rsitems/rsgxsupdateitems.h +++ b/libretroshare/src/rsitems/rsgxsupdateitems.h @@ -28,18 +28,11 @@ -#if 0 -#include -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvtypes.h" -#include "serialiser/rstlvkeys.h" -#endif - #include "gxs/rsgxs.h" #include "gxs/rsgxsdata.h" #include "serialiser/rstlvidset.h" +#include "serialiser/rstypeserializer.h" +#include "serialiser/rsserializable.h" const uint8_t RS_PKT_SUBTYPE_GXS_GRP_UPDATE = 0x01; @@ -140,17 +133,27 @@ public: class RsGxsMsgUpdate { public: - struct MsgUpdateInfo + struct MsgUpdateInfo : RsSerializable { MsgUpdateInfo(): time_stamp(0), message_count(0) {} uint32_t time_stamp ; uint32_t message_count ; + + /// @see RsSerializable + void serial_process(RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) + { + RS_SERIAL_PROCESS(time_stamp); + RS_SERIAL_PROCESS(message_count); + } }; std::map msgUpdateInfos; }; +RS_REGISTER_SERIALIZABLE_TYPE_DECL(RsGxsMsgUpdate::MsgUpdateInfo) + class RsGxsMsgUpdateItem : public RsGxsNetServiceItem, public RsGxsMsgUpdate { public: diff --git a/libretroshare/src/rsserver/rstypes.cc b/libretroshare/src/rsserver/rstypes.cc index 209a7da88..c13adef7a 100644 --- a/libretroshare/src/rsserver/rstypes.cc +++ b/libretroshare/src/rsserver/rstypes.cc @@ -76,4 +76,4 @@ std::ostream &operator<<(std::ostream &out, const FileInfo &info) return out; } - +RS_REGISTER_SERIALIZABLE_TYPE_DEF(CompressedChunkMap) diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc index 88585e45a..c03c64684 100644 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ b/libretroshare/src/serialiser/rstypeserializer.cc @@ -65,7 +65,8 @@ template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint3 } 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 + std::cerr << __PRETTY_FUNCTION__ << " Not implemented!" << std::endl; + print_stacktrace(); return false; } template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint8_t& member) @@ -98,7 +99,8 @@ template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t siz } 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 + std::cerr << __PRETTY_FUNCTION__ << " Not implemented!" << std::endl; + print_stacktrace(); return false; } template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint8_t& member) @@ -128,7 +130,9 @@ template<> uint32_t RsTypeSerializer::serial_size(const bool& /* member*/) } template<> uint32_t RsTypeSerializer::serial_size(const int32_t& /* member*/) { - return 4; + std::cerr << __PRETTY_FUNCTION__ << " Not implemented!" << std::endl; + print_stacktrace(); + return 0; } template<> uint32_t RsTypeSerializer::serial_size(const uint8_t& /* member*/) { @@ -513,8 +517,9 @@ bool RsTypeSerializer::to_JSON( const std::string& memberName, template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/, - RsTlvItem& /*member*/, RsJson& /*jVal*/) + RsTlvItem& member, RsJson& /*jVal*/) { + member.TlvClear(); return true; } @@ -580,6 +585,30 @@ 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; } +template<> /*static*/ +bool RsTypeSerializer::to_JSON( + const std::string& memberName, + const RsTypeSerializer::TlvMemBlock_proxy& 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*/, + RsTypeSerializer::TlvMemBlock_proxy&, + RsJson& /*jVal*/) +{ return true; } //============================================================================// // RsSerializable and derivated // diff --git a/libretroshare/src/serialiser/rstypeserializer.h b/libretroshare/src/serialiser/rstypeserializer.h index 452700cf2..4b5486b88 100644 --- a/libretroshare/src/serialiser/rstypeserializer.h +++ b/libretroshare/src/serialiser/rstypeserializer.h @@ -828,38 +828,48 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName, //============================================================================// -// Generic types // +// Not implemented types macros // //============================================================================// -template /*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; +/** + * @def RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(T) + * @def RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(T) + * Helper macros for types that has not yet implemented to/from JSON + * should be deleted from the code as soon as they are not needed anymore + */ +#define RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(T) \ +template<> /*static*/ \ +bool RsTypeSerializer::to_JSON(const std::string& memberName, T const& 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 << __FILE__ << __LINE__ << __PRETTY_FUNCTION__ \ + << " JSON serialization for type " \ + << typeid(member).name() << " " << memberName \ + << " not available." << std::endl; \ + print_stacktrace(); \ + return true; \ } -template /*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; +#define RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(T) \ +template<> /*static*/ \ +bool RsTypeSerializer::from_JSON( const std::string& memberName, \ + T& member, RsJson& /*jDoc*/ ) \ +{ \ + std::cerr << __FILE__ << __LINE__ << __PRETTY_FUNCTION__ \ + << " JSON deserialization for type " \ + << typeid(member).name() << " " << memberName \ + << " not available." << std::endl; \ + print_stacktrace(); \ + return true; \ } diff --git a/libretroshare/src/turtle/rsturtleitem.cc b/libretroshare/src/turtle/rsturtleitem.cc index 35b250117..cf206a153 100644 --- a/libretroshare/src/turtle/rsturtleitem.cc +++ b/libretroshare/src/turtle/rsturtleitem.cc @@ -140,6 +140,9 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const RsRegul std::cerr << " [RegExpr ] " << n << ", tokens=" << expr._tokens.size() << " ints=" << expr._ints.size() << " strings=" << expr._strings.size() << std::endl; } +RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(RsRegularExpression::LinearizedExpression) +RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(RsRegularExpression::LinearizedExpression) + void RsTurtleSearchResultItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; @@ -193,6 +196,9 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const TurtleF std::cerr << " [FileInfo ] " << n << " size=" << i.size << " hash=" << i.hash << ", name=" << i.name << std::endl; } +RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(TurtleFileInfo) +RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(TurtleFileInfo) + void RsTurtleOpenTunnelItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { RsTypeSerializer::serial_process (j,ctx,file_hash ,"file_hash") ; From 8b774595d78e13623af7bb34730a0456f2b1b0b8 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Sat, 27 Jan 2018 17:57:33 +0100 Subject: [PATCH 15/17] Better usage of type traits Don't need register types for serializationanymore Don't need casting helpers for serialization --- libretroshare/src/chat/rschatitems.cc | 3 - libretroshare/src/gxstrans/p3gxstransitems.cc | 6 - libretroshare/src/retroshare/rsidentity.h | 2 - libretroshare/src/retroshare/rstypes.h | 1 - libretroshare/src/rsitems/rsconfigitems.cc | 1 - libretroshare/src/rsitems/rsgxsupdateitems.cc | 6 - libretroshare/src/rsitems/rsgxsupdateitems.h | 1 - libretroshare/src/rsserver/rstypes.cc | 2 - libretroshare/src/serialiser/rsserializable.h | 107 +----------- .../src/serialiser/rstypeserializer.cc | 162 ++---------------- .../src/serialiser/rstypeserializer.h | 131 +++++++++++++- libretroshare/src/services/p3idservice.cc | 2 - 12 files changed, 145 insertions(+), 279 deletions(-) diff --git a/libretroshare/src/chat/rschatitems.cc b/libretroshare/src/chat/rschatitems.cc index 1eee404b6..7ae680105 100644 --- a/libretroshare/src/chat/rschatitems.cc +++ b/libretroshare/src/chat/rschatitems.cc @@ -205,9 +205,6 @@ void RsPrivateChatMsgConfigItem::get(RsChatMsgItem *ci) ci->recvTime = recvTime; } -/* Necessary to serialize `store` that is an STL container with RsChatMsgItem - * inside which is a subtype of RsItem */ -RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsChatMsgItem) void PrivateOugoingMapItem::serial_process( RsGenericSerializer::SerializeJob j, diff --git a/libretroshare/src/gxstrans/p3gxstransitems.cc b/libretroshare/src/gxstrans/p3gxstransitems.cc index 1db07c70a..5d28ec582 100644 --- a/libretroshare/src/gxstrans/p3gxstransitems.cc +++ b/libretroshare/src/gxstrans/p3gxstransitems.cc @@ -38,12 +38,6 @@ OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, memcpy(&mailData[0], data, size); } -// for mailItem -RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsGxsTransMailItem) - -// for presignedReceipt -RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsNxsTransPresignedReceipt) - void OutgoingRecord_deprecated::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index f021252b3..47da42de4 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -294,8 +294,6 @@ private: RsIdentityUsage(); }; -RS_REGISTER_SERIALIZABLE_TYPE_DECL(RsIdentityUsage) - struct RsIdentityDetails : RsSerializable { diff --git a/libretroshare/src/retroshare/rstypes.h b/libretroshare/src/retroshare/rstypes.h index 84c3fc45d..1e36d3832 100644 --- a/libretroshare/src/retroshare/rstypes.h +++ b/libretroshare/src/retroshare/rstypes.h @@ -364,7 +364,6 @@ class CompressedChunkMap : public RsSerializable { RS_SERIAL_PROCESS(_map); } }; -RS_REGISTER_SERIALIZABLE_TYPE_DECL(CompressedChunkMap) template class t_CRCMap { diff --git a/libretroshare/src/rsitems/rsconfigitems.cc b/libretroshare/src/rsitems/rsconfigitems.cc index b673b354a..83f508794 100644 --- a/libretroshare/src/rsitems/rsconfigitems.cc +++ b/libretroshare/src/rsitems/rsconfigitems.cc @@ -193,7 +193,6 @@ void RsPeerStunItem::serial_process(RsGenericSerializer::SerializeJob j,RsGeneri RsTypeSerializer::serial_process(j,ctx,stunList,"stunList") ; } -RS_REGISTER_SERIALIZABLE_TYPE_DEF(PeerBandwidthLimits) RsNodeGroupItem::RsNodeGroupItem(const RsGroupInfo& g) :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_NODE_GROUP) diff --git a/libretroshare/src/rsitems/rsgxsupdateitems.cc b/libretroshare/src/rsitems/rsgxsupdateitems.cc index 6e18ed774..a5f3ecf02 100644 --- a/libretroshare/src/rsitems/rsgxsupdateitems.cc +++ b/libretroshare/src/rsitems/rsgxsupdateitems.cc @@ -97,10 +97,6 @@ void RsGxsMsgUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGe RsTypeSerializer::serial_process(j,ctx,msgUpdateInfos,"msgUpdateInfos"); } -RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsGxsMsgUpdate::MsgUpdateInfo) - - - void RsGxsServerMsgUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { RsTypeSerializer::serial_process (j,ctx,grpId,"grpId"); @@ -113,5 +109,3 @@ void RsGxsGrpConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGe RsTypeSerializer::serial_process(j,ctx,msg_send_delay,"msg_send_delay") ; RsTypeSerializer::serial_process(j,ctx,msg_req_delay,"msg_req_delay") ; } - - diff --git a/libretroshare/src/rsitems/rsgxsupdateitems.h b/libretroshare/src/rsitems/rsgxsupdateitems.h index e0549b2b3..5d13028ff 100644 --- a/libretroshare/src/rsitems/rsgxsupdateitems.h +++ b/libretroshare/src/rsitems/rsgxsupdateitems.h @@ -152,7 +152,6 @@ public: std::map msgUpdateInfos; }; -RS_REGISTER_SERIALIZABLE_TYPE_DECL(RsGxsMsgUpdate::MsgUpdateInfo) class RsGxsMsgUpdateItem : public RsGxsNetServiceItem, public RsGxsMsgUpdate { diff --git a/libretroshare/src/rsserver/rstypes.cc b/libretroshare/src/rsserver/rstypes.cc index c13adef7a..4574c48e8 100644 --- a/libretroshare/src/rsserver/rstypes.cc +++ b/libretroshare/src/rsserver/rstypes.cc @@ -75,5 +75,3 @@ std::ostream &operator<<(std::ostream &out, const FileInfo &info) out << "Hash: " << info.hash; return out; } - -RS_REGISTER_SERIALIZABLE_TYPE_DEF(CompressedChunkMap) diff --git a/libretroshare/src/serialiser/rsserializable.h b/libretroshare/src/serialiser/rsserializable.h index acfe995af..f55378cf1 100644 --- a/libretroshare/src/serialiser/rsserializable.h +++ b/libretroshare/src/serialiser/rsserializable.h @@ -17,8 +17,6 @@ * along with this program. If not, see . */ -#include - #include "serialiser/rsserializer.h" @@ -38,7 +36,6 @@ struct RsSerializable RsGenericSerializer::SerializeContext& ctx) = 0; }; - /** @def RS_SERIAL_PROCESS(I) * Use this macro to register the members of `YourSerializable` for serial * processing inside `YourSerializable::serial_process(j, ctx)` @@ -47,110 +44,8 @@ struct RsSerializable * specifying the underlying type otherwise the serialization format may differ * in an uncompatible way depending on the compiler/platform. * - * If your member is a derivative of RsSerializable in some cases it may be - * convenient also to register your item type with - * @see RS_REGISTER_SERIALIZABLE_TYPE_DEF(T). - * * Inspired by http://stackoverflow.com/a/39345864 */ #define RS_SERIAL_PROCESS(I) do { \ - RsTypeSerializer::serial_process(j, ctx, __priv_to_RS_S_TYPE(I), #I ); \ + RsTypeSerializer::serial_process(j, ctx, I, #I ); \ } while(0) - - -/** @def RS_REGISTER_SERIALIZABLE_TYPE_DEF(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` - * - * @code{.cpp} -struct PrivateOugoingMapItem : RsChatItem -{ - PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - std::map store; -}; - -RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsChatMsgItem) - -void PrivateOugoingMapItem::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(store); -} - * @endcode - */ -#define RS_REGISTER_SERIALIZABLE_TYPE_DEF(T) template<> /*static*/\ - void RsTypeSerializer::serial_process( \ - RsGenericSerializer::SerializeJob j,\ - RsGenericSerializer::SerializeContext& ctx, T& item,\ - const std::string& objName ) \ -{ \ - RsTypeSerializer::serial_process( j, \ - ctx, static_cast(item), objName ); \ -} - - -/** @def RS_REGISTER_SERIALIZABLE_TYPE_DECL(T) - * The usage of this macro into your header file may be 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 derived 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( \ - RsGenericSerializer::SerializeJob j,\ - RsGenericSerializer::SerializeContext& ctx, T& item,\ - const std::string& objName ); - - -//============================================================================// -// Private type conversion helpers // -//============================================================================// - -/** - * @brief Privates type conversion helpers for RS_SERIAL_PROCESS. - * @private DO NOT use explicitely outside this file. - * Used to cast enums and derived type to matching types supported by - * RsTypeSerializer::serial_process(...) templated methods. - */ -template::value>::type> -inline typename std::underlying_type::type& __priv_to_RS_S_TYPE(T& i) -{ - return reinterpret_cast::type&>(i); -} - -template::value>::type> -inline RsSerializable& __priv_to_RS_S_TYPE(T& i) -{ - return static_cast(i); -} - -struct RsTlvItem; -template::value>::type> -inline RsTlvItem& __priv_to_RS_S_TYPE(T& i) -{ - return static_cast(i); -} - -template::value||std::is_base_of::value||std::is_base_of::value)>::type> -inline T& __priv_to_RS_S_TYPE(T& i) -{ - return i; -} diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc index c03c64684..f4dc2d3c1 100644 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ b/libretroshare/src/serialiser/rstypeserializer.cc @@ -44,16 +44,17 @@ static const uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB. #define SAFE_GET_JSON_V() \ const char* mName = memberName.c_str(); \ - bool ret = jVal.HasMember(mName); \ + bool ret = jDoc.HasMember(mName); \ if(!ret) \ { \ std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName \ << "\" not found in JSON:" << std::endl \ - << jVal << std::endl << std::endl; \ + << jDoc << std::endl << std::endl; \ print_stacktrace(); \ return false; \ } \ - rapidjson::Value& v = jVal[mName] + rapidjson::Value& v = jDoc[mName] + //============================================================================// // Integer types // @@ -227,7 +228,7 @@ SIMPLE_TO_JSON_DEF(uint64_t) template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, bool& member, - RsJson& jVal ) + RsJson& jDoc ) { SAFE_GET_JSON_V(); ret = ret && v.IsBool(); @@ -237,7 +238,7 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName, bool& member, template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, - int32_t& member, RsJson& jVal ) + int32_t& member, RsJson& jDoc ) { SAFE_GET_JSON_V(); ret = ret && v.IsInt(); @@ -247,7 +248,7 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName, template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, time_t& member, - RsJson& jVal ) + RsJson& jDoc ) { SAFE_GET_JSON_V(); ret = ret && v.IsUint(); @@ -257,7 +258,7 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName, time_t& member, template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint8_t& member, RsJson& jVal ) + uint8_t& member, RsJson& jDoc ) { SAFE_GET_JSON_V(); ret = ret && v.IsUint(); @@ -267,7 +268,7 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName, template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint16_t& member, RsJson& jVal ) + uint16_t& member, RsJson& jDoc ) { SAFE_GET_JSON_V(); ret = ret && v.IsUint(); @@ -277,7 +278,7 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName, template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint32_t& member, RsJson& jVal ) + uint32_t& member, RsJson& jDoc ) { SAFE_GET_JSON_V(); ret = ret && v.IsUint(); @@ -287,7 +288,7 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName, template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint64_t& member, RsJson& jVal ) + uint64_t& member, RsJson& jDoc ) { SAFE_GET_JSON_V(); ret = ret && v.IsUint(); @@ -319,7 +320,7 @@ SIMPLE_TO_JSON_DEF(float) template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, - float& member, RsJson& jVal ) + float& member, RsJson& jDoc ) { SAFE_GET_JSON_V(); ret = ret && v.IsFloat(); @@ -371,7 +372,7 @@ bool RsTypeSerializer::to_JSON( const std::string& membername, } template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, - std::string& member, RsJson& jVal ) + std::string& member, RsJson& jDoc ) { SAFE_GET_JSON_V(); ret = ret && v.IsString(); @@ -416,9 +417,9 @@ bool RsTypeSerializer::to_JSON( const std::string& memberName, template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, uint16_t /*sub_type*/, - std::string& member, RsJson& jVal ) + std::string& member, RsJson& jDoc ) { - return from_JSON(memberName, member, jVal); + return from_JSON(memberName, member, jDoc); } //============================================================================// @@ -463,9 +464,9 @@ bool RsTypeSerializer::to_JSON( const std::string& memberName, template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& memberName, uint16_t /*sub_type*/, - uint32_t& member, RsJson& jVal ) + uint32_t& member, RsJson& jDoc ) { - return from_JSON(memberName, member, jVal); + return from_JSON(memberName, member, jDoc); } @@ -517,7 +518,7 @@ bool RsTypeSerializer::to_JSON( const std::string& memberName, template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/, - RsTlvItem& member, RsJson& /*jVal*/) + RsTlvItem& member, RsJson& /*jDoc*/) { member.TlvClear(); return true; @@ -607,134 +608,9 @@ bool RsTypeSerializer::to_JSON( template<> /*static*/ bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/, RsTypeSerializer::TlvMemBlock_proxy&, - RsJson& /*jVal*/) + RsJson& /*jDoc*/) { return true; } -//============================================================================// -// RsSerializable and derivated // -//============================================================================// - -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(s).serial_process( - RsGenericSerializer::SIZE_ESTIMATE, ctx ); - - return ctx.mOffset; -} - -template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size, - uint32_t &offset, - const RsSerializable& s ) -{ - RsGenericSerializer::SerializeContext ctx( - data, size, RsGenericSerializer::FORMAT_BINARY, - RsGenericSerializer::SERIALIZATION_FLAG_NONE ); - ctx.mOffset = offset; - const_cast(s).serial_process( - RsGenericSerializer::SERIALIZE, ctx ); - return true; -} - -template<> bool RsTypeSerializer::deserialize( const uint8_t data[], - uint32_t size, uint32_t& offset, - RsSerializable& s ) -{ - RsGenericSerializer::SerializeContext ctx( - const_cast(data), size, - RsGenericSerializer::FORMAT_BINARY, - RsGenericSerializer::SERIALIZATION_FLAG_NONE ); - ctx.mOffset = offset; - const_cast(s).serial_process( - RsGenericSerializer::DESERIALIZE, ctx ); - return true; -} - -template<> void RsTypeSerializer::print_data( const std::string& /*n*/, - const RsSerializable& s ) -{ - RsGenericSerializer::SerializeContext ctx( - NULL, 0, - RsGenericSerializer::FORMAT_BINARY, - RsGenericSerializer::SERIALIZATION_FLAG_NONE ); - const_cast(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(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( - 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 // diff --git a/libretroshare/src/serialiser/rstypeserializer.h b/libretroshare/src/serialiser/rstypeserializer.h index 4b5486b88..f08a43239 100644 --- a/libretroshare/src/serialiser/rstypeserializer.h +++ b/libretroshare/src/serialiser/rstypeserializer.h @@ -37,6 +37,8 @@ #include #include // for typeid +#include +#include /** INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set} @@ -129,9 +131,10 @@ struct RsTypeSerializer /// Generic types template - static void serial_process( RsGenericSerializer::SerializeJob j, + typename std::enable_if::value || !(std::is_base_of::value || std::is_enum::value || std::is_base_of::value)>::type + 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) { @@ -156,8 +159,10 @@ struct RsTypeSerializer ctx.mOk = ctx.mOk && from_JSON(member_name, member, ctx.mJson); break; default: - ctx.mOk = false; - throw std::runtime_error("Unknown serial job"); + std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: " + << static_cast::type>(j) + << std::endl; + exit(EINVAL); } } @@ -193,8 +198,10 @@ struct RsTypeSerializer from_JSON(member_name, type_id, member, ctx.mJson); break; default: - ctx.mOk = false; - throw std::runtime_error("Unknown serial job"); + std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: " + << static_cast::type>(j) + << std::endl; + exit(EINVAL); } } @@ -567,6 +574,118 @@ struct RsTypeSerializer } } + /** + * @brief serial process enum types + * + * On declaration of your member of enum type you must specify the + * underlying type otherwise the serialization format may differ in an + * uncompatible way depending on the compiler/platform. + */ + template + typename std::enable_if::value>::type + static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + E& member, + const std::string& memberName ) + { +#ifdef RSSERIAL_DEBUG + std::cerr << __PRETTY_FUNCTION__ << " processing enum: " + << typeid(E).name() << " as " + << typeid(typename std::underlying_type::type).name() + << std::endl; +#endif + serial_process( + j, ctx, + reinterpret_cast::type&>(member), + memberName ); + } + + /// RsSerializable and derivatives + template + typename std::enable_if::value>::type + static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + T& member, + const std::string& memberName ) + { + switch(j) + { + case RsGenericSerializer::SIZE_ESTIMATE: // fallthrough + case RsGenericSerializer::DESERIALIZE: // fallthrough + case RsGenericSerializer::SERIALIZE: // fallthrough + case RsGenericSerializer::PRINT: + member.serial_process(j, ctx); + break; + case RsGenericSerializer::TO_JSON: + { + rapidjson::Document& jDoc(ctx.mJson); + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); + + // Reuse allocator to avoid deep copy later + RsGenericSerializer::SerializeContext lCtx( + nullptr, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE, + &allocator ); + + member.serial_process(j, lCtx); + + 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, lCtx.mJson, allocator); + + ctx.mOk = ctx.mOk && lCtx.mOk; + break; + } + case RsGenericSerializer::FROM_JSON: + { + rapidjson::Document& jDoc(ctx.mJson); + const char* mName = memberName.c_str(); + ctx.mOk = ctx.mOk && jDoc.HasMember(mName); + + if(!ctx.mOk) + { + std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName + << "\" not found in JSON:" << std::endl + << jDoc << std::endl << std::endl; + print_stacktrace(); + break; + } + + rapidjson::Value& v = jDoc[mName]; + + RsGenericSerializer::SerializeContext lCtx( + nullptr, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE ); + lCtx.mJson.SetObject() = v; // Beware of move semantic!! + + member.serial_process(j, lCtx); + ctx.mOk = ctx.mOk && lCtx.mOk; + + break; + } + default: + std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: " + << static_cast::type>(j) + << std::endl; + exit(EINVAL); + break; + } + } + + /// RsTlvItem derivatives only + template + typename std::enable_if::value && !std::is_same::value>::type + static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + T& member, + const std::string& memberName ) + { + serial_process(j, ctx, static_cast(member), memberName); + } protected: diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 4796b3005..5a3878a7d 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -4560,5 +4560,3 @@ RsIdentityUsage::RsIdentityUsage( RsIdentityUsage::RsIdentityUsage() : mServiceId(0), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0) {} - -RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsIdentityUsage) From ef6681b6f9c4b8bc506a59f9de0c3e92e6ceef9f Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Sat, 27 Jan 2018 18:39:17 +0100 Subject: [PATCH 16/17] Remove outdated documentation --- libretroshare/src/rsitems/rsitem.h | 2 +- libretroshare/src/serialiser/rsserializable.h | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/libretroshare/src/rsitems/rsitem.h b/libretroshare/src/rsitems/rsitem.h index fb76d1562..545870631 100644 --- a/libretroshare/src/rsitems/rsitem.h +++ b/libretroshare/src/rsitems/rsitem.h @@ -75,7 +75,7 @@ struct RsItem : RsMemoryManagement::SmallObject, RsSerializable /** * TODO: This default implementation should be removed and childs structs - * implement RsSerializable(...) as soon as all the codebase is ported to + * implement ::serial_process(...) as soon as all the codebase is ported to * the new serialization system */ virtual void serial_process(RsGenericSerializer::SerializeJob, diff --git a/libretroshare/src/serialiser/rsserializable.h b/libretroshare/src/serialiser/rsserializable.h index f55378cf1..c717afc4b 100644 --- a/libretroshare/src/serialiser/rsserializable.h +++ b/libretroshare/src/serialiser/rsserializable.h @@ -23,13 +23,10 @@ /** @brief Minimal ancestor for all serializable structs in RetroShare. * If you want your struct to be easly serializable you should inherit from this * struct. - * If you want your struct to be serializable as part of a container like an - * `std::vector` @see RS_REGISTER_SERIALIZABLE_TYPE_DEF(T) and - * @see RS_REGISTER_SERIALIZABLE_TYPE_DECL(T) */ struct RsSerializable { - /** Register struct members to serialize in this method taking advantage of + /** Process struct members to serialize in this method taking advantage of * the helper macro @see RS_SERIAL_PROCESS(I) */ virtual void serial_process(RsGenericSerializer::SerializeJob j, @@ -37,7 +34,7 @@ struct RsSerializable }; /** @def RS_SERIAL_PROCESS(I) - * Use this macro to register the members of `YourSerializable` for serial + * Use this macro to process the members of `YourSerializable` for serial * processing inside `YourSerializable::serial_process(j, ctx)` * * Pay special attention for member of enum type which must be declared From 86ce17722885fb53215f5ca0a748b9ba6f2f7d46 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Sat, 27 Jan 2018 19:57:15 +0100 Subject: [PATCH 17/17] time_t may be signed in JSON --- libretroshare/src/serialiser/rstypeserializer.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc index f4dc2d3c1..8d7ba5daf 100644 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ b/libretroshare/src/serialiser/rstypeserializer.cc @@ -251,8 +251,8 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName, time_t& member, RsJson& jDoc ) { SAFE_GET_JSON_V(); - ret = ret && v.IsUint(); - if(ret) member = v.GetUint(); + ret = ret && v.IsInt(); + if(ret) member = v.GetInt(); return ret; } @@ -298,7 +298,7 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName, //============================================================================// -// FLoats // +// Floats // //============================================================================// template<> uint32_t RsTypeSerializer::serial_size(const float&){ return 4; }