mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Better usage of type traits
Don't need register types for serializationanymore Don't need casting helpers for serialization
This commit is contained in:
parent
ba6f2d7e81
commit
8b774595d7
@ -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,
|
||||
|
@ -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 )
|
||||
|
@ -294,8 +294,6 @@ private:
|
||||
RsIdentityUsage();
|
||||
};
|
||||
|
||||
RS_REGISTER_SERIALIZABLE_TYPE_DECL(RsIdentityUsage)
|
||||
|
||||
|
||||
struct RsIdentityDetails : RsSerializable
|
||||
{
|
||||
|
@ -364,7 +364,6 @@ class CompressedChunkMap : public RsSerializable
|
||||
{ RS_SERIAL_PROCESS(_map); }
|
||||
};
|
||||
|
||||
RS_REGISTER_SERIALIZABLE_TYPE_DECL(CompressedChunkMap)
|
||||
|
||||
template<class CRCTYPE> class t_CRCMap
|
||||
{
|
||||
|
@ -193,7 +193,6 @@ void RsPeerStunItem::serial_process(RsGenericSerializer::SerializeJob j,RsGeneri
|
||||
RsTypeSerializer::serial_process<RsTlvItem>(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)
|
||||
|
@ -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<uint32_t>(j,ctx,msg_send_delay,"msg_send_delay") ;
|
||||
RsTypeSerializer::serial_process<uint32_t>(j,ctx,msg_req_delay,"msg_req_delay") ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -152,7 +152,6 @@ public:
|
||||
std::map<RsGxsGroupId, MsgUpdateInfo> msgUpdateInfos;
|
||||
};
|
||||
|
||||
RS_REGISTER_SERIALIZABLE_TYPE_DECL(RsGxsMsgUpdate::MsgUpdateInfo)
|
||||
|
||||
class RsGxsMsgUpdateItem : public RsGxsNetServiceItem, public RsGxsMsgUpdate
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#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<uint64_t, RsChatMsgItem>`
|
||||
*
|
||||
* @code{.cpp}
|
||||
struct PrivateOugoingMapItem : RsChatItem
|
||||
{
|
||||
PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {}
|
||||
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx );
|
||||
|
||||
std::map<uint64_t, RsChatMsgItem> store;
|
||||
};
|
||||
|
||||
RS_REGISTER_SERIALIZABLE_TYPE_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<T>( \
|
||||
RsGenericSerializer::SerializeJob j,\
|
||||
RsGenericSerializer::SerializeContext& ctx, T& item,\
|
||||
const std::string& objName ) \
|
||||
{ \
|
||||
RsTypeSerializer::serial_process<RsSerializable>( j, \
|
||||
ctx, static_cast<RsSerializable&>(item), objName ); \
|
||||
}
|
||||
|
||||
|
||||
/** @def RS_REGISTER_SERIALIZABLE_TYPE_DECL(T)
|
||||
* The usage of this macro into your header file 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<T>( \
|
||||
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<typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
|
||||
inline typename std::underlying_type<T>::type& __priv_to_RS_S_TYPE(T& i)
|
||||
{
|
||||
return reinterpret_cast<typename std::underlying_type<T>::type&>(i);
|
||||
}
|
||||
|
||||
template<typename T, typename = typename std::enable_if<std::is_base_of<RsSerializable, T>::value>::type>
|
||||
inline RsSerializable& __priv_to_RS_S_TYPE(T& i)
|
||||
{
|
||||
return static_cast<RsSerializable&>(i);
|
||||
}
|
||||
|
||||
struct RsTlvItem;
|
||||
template<typename T, typename = typename std::enable_if<std::is_base_of<RsTlvItem, T>::value>::type>
|
||||
inline RsTlvItem& __priv_to_RS_S_TYPE(T& i)
|
||||
{
|
||||
return static_cast<RsTlvItem&>(i);
|
||||
}
|
||||
|
||||
template<typename T, typename = typename std::enable_if<!(std::is_enum<T>::value||std::is_base_of<RsTlvItem, T>::value||std::is_base_of<RsSerializable, T>::value)>::type>
|
||||
inline T& __priv_to_RS_S_TYPE(T& i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
@ -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<std::string>(memberName, member, jVal);
|
||||
return from_JSON<std::string>(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<uint32_t>(memberName, member, jVal);
|
||||
return from_JSON<uint32_t>(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<RsSerializable&>(s).serial_process(
|
||||
RsGenericSerializer::SIZE_ESTIMATE, ctx );
|
||||
|
||||
return ctx.mOffset;
|
||||
}
|
||||
|
||||
template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size,
|
||||
uint32_t &offset,
|
||||
const RsSerializable& s )
|
||||
{
|
||||
RsGenericSerializer::SerializeContext ctx(
|
||||
data, size, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
|
||||
ctx.mOffset = offset;
|
||||
const_cast<RsSerializable&>(s).serial_process(
|
||||
RsGenericSerializer::SERIALIZE, ctx );
|
||||
return true;
|
||||
}
|
||||
|
||||
template<> bool RsTypeSerializer::deserialize( const uint8_t data[],
|
||||
uint32_t size, uint32_t& offset,
|
||||
RsSerializable& s )
|
||||
{
|
||||
RsGenericSerializer::SerializeContext ctx(
|
||||
const_cast<uint8_t*>(data), size,
|
||||
RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
|
||||
ctx.mOffset = offset;
|
||||
const_cast<RsSerializable&>(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<RsSerializable&>(s).serial_process( RsGenericSerializer::PRINT,
|
||||
ctx );
|
||||
}
|
||||
|
||||
template<> /*static*/
|
||||
bool RsTypeSerializer::to_JSON( const std::string& memberName,
|
||||
const RsSerializable& member, RsJson& jDoc )
|
||||
{
|
||||
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator();
|
||||
|
||||
// Reuse allocator to avoid deep copy later
|
||||
RsGenericSerializer::SerializeContext ctx(
|
||||
NULL, 0, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE,
|
||||
&allocator );
|
||||
|
||||
const_cast<RsSerializable&>(member).serial_process(
|
||||
RsGenericSerializer::TO_JSON, ctx );
|
||||
|
||||
rapidjson::Value key;
|
||||
key.SetString(memberName.c_str(), memberName.length(), allocator);
|
||||
|
||||
/* Because the passed allocator is reused it doesn't go out of scope and
|
||||
* there is no need of deep copy and we can take advantage of the much
|
||||
* faster rapidjson move semantic */
|
||||
jDoc.AddMember(key, ctx.mJson, allocator);
|
||||
|
||||
return ctx.mOk;
|
||||
}
|
||||
|
||||
template<> /*static*/
|
||||
bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||
RsSerializable& member, RsJson& jVal )
|
||||
{
|
||||
SAFE_GET_JSON_V();
|
||||
|
||||
if(ret)
|
||||
{
|
||||
RsGenericSerializer::SerializeContext ctx(
|
||||
NULL, 0, RsGenericSerializer::FORMAT_BINARY,
|
||||
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
|
||||
|
||||
ctx.mJson.SetObject() = v; // Beware of move semantic!!
|
||||
member.serial_process(RsGenericSerializer::FROM_JSON, ctx);
|
||||
ret = ret && ctx.mOk;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<> /*static*/
|
||||
void RsTypeSerializer::serial_process<RsSerializable>(
|
||||
RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx, RsSerializable& object,
|
||||
const std::string& objName )
|
||||
{
|
||||
switch (j)
|
||||
{
|
||||
case RsGenericSerializer::SIZE_ESTIMATE: // fall-through
|
||||
case RsGenericSerializer::SERIALIZE: // fall-through
|
||||
case RsGenericSerializer::DESERIALIZE: // fall-through
|
||||
case RsGenericSerializer::PRINT: // fall-through
|
||||
object.serial_process(j, ctx);
|
||||
break;
|
||||
case RsGenericSerializer::TO_JSON:
|
||||
ctx.mOk = ctx.mOk && to_JSON(objName, object, ctx.mJson);
|
||||
break;
|
||||
case RsGenericSerializer::FROM_JSON:
|
||||
ctx.mOk = ctx.mOk && from_JSON(objName, object, ctx.mJson);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================//
|
||||
// RsJson std:ostream support //
|
||||
|
@ -37,6 +37,8 @@
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <typeinfo> // for typeid
|
||||
#include <type_traits>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/** INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set}<T>
|
||||
@ -129,7 +131,8 @@ struct RsTypeSerializer
|
||||
|
||||
/// Generic types
|
||||
template<typename T>
|
||||
static void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
typename std::enable_if<std::is_same<RsTlvItem,T>::value || !(std::is_base_of<RsSerializable,T>::value || std::is_enum<T>::value || std::is_base_of<RsTlvItem,T>::value)>::type
|
||||
static /*void*/ serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
T& member, const std::string& member_name)
|
||||
{
|
||||
@ -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<std::underlying_type<decltype(j)>::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<std::underlying_type<decltype(j)>::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 E>
|
||||
typename std::enable_if<std::is_enum<E>::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<E>::type).name()
|
||||
<< std::endl;
|
||||
#endif
|
||||
serial_process(
|
||||
j, ctx,
|
||||
reinterpret_cast<typename std::underlying_type<E>::type&>(member),
|
||||
memberName );
|
||||
}
|
||||
|
||||
/// RsSerializable and derivatives
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_base_of<RsSerializable,T>::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<std::underlying_type<decltype(j)>::type>(j)
|
||||
<< std::endl;
|
||||
exit(EINVAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// RsTlvItem derivatives only
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_base_of<RsTlvItem,T>::value && !std::is_same<RsTlvItem,T>::value>::type
|
||||
static /*void*/ serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx,
|
||||
T& member,
|
||||
const std::string& memberName )
|
||||
{
|
||||
serial_process(j, ctx, static_cast<RsTlvItem&>(member), memberName);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -4560,5 +4560,3 @@ RsIdentityUsage::RsIdentityUsage(
|
||||
|
||||
RsIdentityUsage::RsIdentityUsage() :
|
||||
mServiceId(0), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0) {}
|
||||
|
||||
RS_REGISTER_SERIALIZABLE_TYPE_DEF(RsIdentityUsage)
|
||||
|
Loading…
Reference in New Issue
Block a user