Port GxsTrans to new serialization system

RsItem added some comment and more verbose error reporting
RsTypeSerializer added support for RsItem derived classes as members
  added utility macros for better readability of the code and easier
  handling of RsItem derived members
  RS_REGISTER_SERIAL_MEMBER(I)
  RS_REGISTER_SERIAL_MEMBER_TYPED(I, T)
  RS_REGISTER_ITEM_TYPE(T)

RsNxsMsg::serial_process use new macros for better readability and to
 have an exemple of usage with RsTlvItem derived class
Fix undefined reference to RsNxsMsg::print
This commit is contained in:
Gioacchino Mazzurco 2017-05-08 00:19:11 +02:00
parent f7f36f697e
commit ea8f800003
11 changed files with 655 additions and 728 deletions

View file

@ -27,6 +27,8 @@
#include "serialiser/rsbaseserial.h"
#include "serialiser/rstlvkeys.h"
#include "rsitems/rsitem.h"
#include "util/rsprint.h"
#include <iomanip>
@ -306,3 +308,57 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const RsTlvIt
std::cerr << " [" << typeid(s).name() << "] " << n << std::endl;
}
//============================================================================//
// RsItem and derivated //
//============================================================================//
template<> uint32_t RsTypeSerializer::serial_size(const RsItem& s)
{
RsGenericSerializer::SerializeContext ctx(
NULL, 0, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
ctx.mOffset = 8; // header size
const_cast<RsItem&>(s).serial_process(RsGenericSerializer::SIZE_ESTIMATE,
ctx);
return ctx.mOffset;
}
template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size,
uint32_t &offset, const RsItem& s )
{
RsGenericSerializer::SerializeContext ctx(
data, size, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
ctx.mOffset = offset;
const_cast<RsItem&>(s).serial_process(RsGenericSerializer::SERIALIZE,
ctx);
return true;
}
template<> bool RsTypeSerializer::deserialize( const uint8_t data[],
uint32_t size, uint32_t& offset,
RsItem& s )
{
RsGenericSerializer::SerializeContext ctx(
const_cast<uint8_t*>(data), size,
RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
ctx.mOffset = offset;
const_cast<RsItem&>(s).serial_process(RsGenericSerializer::DESERIALIZE,
ctx);
return true;
}
template<> void RsTypeSerializer::print_data( const std::string& n,
const RsItem& s )
{
RsGenericSerializer::SerializeContext ctx(
NULL, 0,
RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
const_cast<RsItem&>(s).serial_process(RsGenericSerializer::PRINT,
ctx);
}

View file

@ -33,409 +33,522 @@
#include "serialiser/rsserializer.h"
/** @def RS_REGISTER_SERIAL_MEMBER(I)
* Use this macro to register the members of `YourItem` for serial processing
* inside `YourItem::serial_process(j, ctx)`
*
* Inspired by http://stackoverflow.com/a/39345864
*/
#define RS_REGISTER_SERIAL_MEMBER(I) \
do { RsTypeSerializer::serial_process(j, ctx, I, #I); } while(0)
class RsTypeSerializer
/** @def RS_REGISTER_SERIAL_MEMBER_TYPED(I, T)
* This macro usage is similar to @see RS_REGISTER_SERIAL_MEMBER(I) but it
* permit to force serialization/deserialization type, it is expecially useful
* with enum class members ot RsTlvItem derivative members, be very careful with
* the type you pass, as reinterpret_cast on a reference is used that is
* expecially permissive so you can shot your feet if not carefull enough.
*
* If you are using this with an RsItem derivative (so passing RsItem as T)
* consider to register your item type with @see RS_REGISTER_ITEM_TYPE(T) in
* association with @see RS_REGISTER_SERIAL_MEMBER(I) that rely on template
* function generation, as in this particular case
* RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) would cause the serial code rely on
* C++ dynamic dispatching that may have a noticeable impact on runtime
* performances.
*/
#define RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) do {\
RsTypeSerializer::serial_process<T>(j, ctx, reinterpret_cast<T&>(I), #I);\
} while(0)
/** @def RS_REGISTER_ITEM_TYPE(T)
* Use this macro into `youritem.cc` only if you need to process members of
* subtypes of RsItem.
*
* The usage of this macro is strictly needed only in some cases, for example if
* you are registering for serialization a member of a container that contains
* items of subclasses of RsItem like * `std::map<uint64_t, RsChatMsgItem>`
*
* @code{.cpp}
struct PrivateOugoingMapItem : RsChatItem
{
public:
// This type should be used to pass a parameter to drive the serialisation if needed.
PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {}
struct TlvMemBlock_proxy: public std::pair<void*& ,uint32_t&>
{
TlvMemBlock_proxy(void *& p,uint32_t& s) : std::pair<void*&,uint32_t&>(p,s) {}
TlvMemBlock_proxy(uint8_t*& p,uint32_t& s) : std::pair<void*&,uint32_t&>(*(void**)&p,s) {}
};
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx );
//=================================================================================================//
// Generic types //
//=================================================================================================//
template<typename T>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,T& member,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE: ctx.mOffset += serial_size(member) ;
break ;
case RsGenericSerializer::DESERIALIZE: ctx.mOk = ctx.mOk && deserialize(ctx.mData,ctx.mSize,ctx.mOffset,member) ;
break ;
case RsGenericSerializer::SERIALIZE: ctx.mOk = ctx.mOk && serialize(ctx.mData,ctx.mSize,ctx.mOffset,member) ;
break ;
case RsGenericSerializer::PRINT:
print_data(member_name,member);
break;
default:
ctx.mOk = false ;
throw std::runtime_error("Unknown serial job") ;
}
}
//=================================================================================================//
// Generic types + type_id //
//=================================================================================================//
template<typename T>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,uint16_t type_id,T& member,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE: ctx.mOffset += serial_size(type_id,member) ;
break ;
case RsGenericSerializer::DESERIALIZE: ctx.mOk = ctx.mOk && deserialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member) ;
break ;
case RsGenericSerializer::SERIALIZE: ctx.mOk = ctx.mOk && serialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member) ;
break ;
case RsGenericSerializer::PRINT:
print_data(member_name,type_id,member);
break;
default:
ctx.mOk = false ;
throw std::runtime_error("Unknown serial job") ;
}
}
//=================================================================================================//
// std::map<T,U> //
//=================================================================================================//
template<typename T,typename U>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::map<T,U>& v,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4 ;
for(typename std::map<T,U>::iterator it(v.begin());it!=v.end();++it)
{
serial_process(j,ctx,const_cast<T&>(it->first),"map::*it->first") ;
serial_process(j,ctx,const_cast<U&>(it->second),"map::*it->second") ;
}
}
break ;
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0 ;
serial_process(j,ctx,n,"temporary size");
for(uint32_t i=0;i<n;++i)
{
T t ;
U u ;
serial_process(j,ctx,t,"map::*it->first") ;
serial_process(j,ctx,u,"map::*it->second") ;
v[t] = u ;
}
}
break ;
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size");
for(typename std::map<T,U>::iterator it(v.begin());it!=v.end();++it)
{
serial_process(j,ctx,const_cast<T&>(it->first),"map::*it->first") ;
serial_process(j,ctx,const_cast<U&>(it->second),"map::*it->second") ;
}
}
break ;
case RsGenericSerializer::PRINT:
{
if(v.empty())
std::cerr << " Empty map \"" << member_name << "\"" << std::endl;
else
std::cerr << " std::map of " << v.size() << " elements: \"" << member_name << "\"" << std::endl;
for(typename std::map<T,U>::iterator it(v.begin());it!=v.end();++it)
{
std::cerr << " " ;
serial_process(j,ctx,const_cast<T&>(it->first),"map::*it->first") ;
serial_process(j,ctx,const_cast<U&>(it->second),"map::*it->second") ;
}
}
break;
default:
break;
}
}
//=================================================================================================//
// std::vector<T> //
//=================================================================================================//
template<typename T>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::vector<T>& v,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4 ;
for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name) ;
}
break ;
case RsGenericSerializer::DESERIALIZE:
{ uint32_t n=0 ;
serial_process(j,ctx,n,"temporary size") ;
v.resize(n) ;
for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name) ;
}
break ;
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size") ;
for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name) ;
}
break ;
case RsGenericSerializer::PRINT:
{
if(v.empty())
std::cerr << " Empty array"<< std::endl;
else
std::cerr << " Array of " << v.size() << " elements:" << std::endl;
for(uint32_t i=0;i<v.size();++i)
{
std::cerr << " " ;
serial_process(j,ctx,v[i],member_name) ;
}
}
break;
default:
break;
}
}
//=================================================================================================//
// std::set<T> //
//=================================================================================================//
template<typename T>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::set<T>& v,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4 ;
for(typename std::set<T>::iterator it(v.begin());it!=v.end();++it)
serial_process(j,ctx,const_cast<T&>(*it) ,member_name) ; // the const cast here is a hack to avoid serial_process to instantiate serialise(const T&)
}
break ;
case RsGenericSerializer::DESERIALIZE:
{ uint32_t n=0 ;
serial_process(j,ctx,n,"temporary size") ;
for(uint32_t i=0;i<n;++i)
{
T tmp;
serial_process<T>(j,ctx,tmp,member_name) ;
v.insert(tmp);
}
}
break ;
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size") ;
for(typename std::set<T>::iterator it(v.begin());it!=v.end();++it)
serial_process(j,ctx,const_cast<T&>(*it) ,member_name) ; // the const cast here is a hack to avoid serial_process to instantiate serialise(const T&)
}
break ;
case RsGenericSerializer::PRINT:
{
if(v.empty())
std::cerr << " Empty set"<< std::endl;
else
std::cerr << " Set of " << v.size() << " elements:" << std::endl;
}
break;
default:
break;
}
}
//=================================================================================================//
// std::list<T> //
//=================================================================================================//
template<typename T>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,std::list<T>& v,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4 ;
for(typename std::list<T>::iterator it(v.begin());it!=v.end();++it)
serial_process(j,ctx,*it ,member_name) ;
}
break ;
case RsGenericSerializer::DESERIALIZE:
{ uint32_t n=0 ;
serial_process(j,ctx,n,"temporary size") ;
for(uint32_t i=0;i<n;++i)
{
T tmp;
serial_process<T>(j,ctx,tmp,member_name) ;
v.push_back(tmp);
}
}
break ;
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size") ;
for(typename std::list<T>::iterator it(v.begin());it!=v.end();++it)
serial_process(j,ctx,*it ,member_name) ;
}
break ;
case RsGenericSerializer::PRINT:
{
if(v.empty())
std::cerr << " Empty list"<< std::endl;
else
std::cerr << " List of " << v.size() << " elements:" << std::endl;
}
break;
default:
break;
}
}
//=================================================================================================//
// t_RsFlags32<> types //
//=================================================================================================//
template<int N>
static void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,t_RsFlags32<N>& v,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE: ctx.mOffset += 4 ;
break ;
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0 ;
deserialize<uint32_t>(ctx.mData,ctx.mSize,ctx.mOffset,n) ;
v = t_RsFlags32<N>(n) ;
}
break ;
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.toUInt32() ;
serialize<uint32_t>(ctx.mData,ctx.mSize,ctx.mOffset,n) ;
}
break ;
case RsGenericSerializer::PRINT:
std::cerr << " Flags of type " << std::hex << N << " : " << v.toUInt32() << std::endl;
break ;
}
}
protected:
template<typename T> static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, const T& member);
template<typename T> static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, T& member);
template<typename T> static uint32_t serial_size(const T& /* member */);
template<typename T> static void print_data(const std::string& name,const T& /* member */);
template<typename T> static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id,const T& member);
template<typename T> static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset,uint16_t type_id, T& member);
template<typename T> static uint32_t serial_size(uint16_t type_id,const T& /* member */);
template<typename T> static void print_data(const std::string& name,uint16_t type_id,const T& /* member */);
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member);
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member);
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> static uint32_t serial_size(const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& /* member */);
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> static void print_data(const std::string& name,const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& /* member */);
template<class TLV_CLASS,uint32_t TLV_TYPE> static bool serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member);
template<class TLV_CLASS,uint32_t TLV_TYPE> static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsTlvList<TLV_CLASS,TLV_TYPE>& member);
template<class TLV_CLASS,uint32_t TLV_TYPE> static uint32_t serial_size(const t_RsTlvList<TLV_CLASS,TLV_TYPE>& /* member */);
template<class TLV_CLASS,uint32_t TLV_TYPE> static void print_data(const std::string& name,const t_RsTlvList<TLV_CLASS,TLV_TYPE>& /* member */);
std::map<uint64_t, RsChatMsgItem> store;
};
//=================================================================================================//
// t_RsGenericId<> //
//=================================================================================================//
RS_REGISTER_ITEM_TYPE(RsChatMsgItem)
void PrivateOugoingMapItem::serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
// store is of type
RS_REGISTER_SERIAL_MEMBER(store);
}
* @endcode
*
* If you use this macro with a lot of different item types this can cause the
* generated binary grow in size, consider the usage of
* @see RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) passing RsItem as type in that
* case.
*/
#define RS_REGISTER_ITEM_TYPE(T) template<> \
void RsTypeSerializer::serial_process<T>( \
RsGenericSerializer::SerializeJob j,\
RsGenericSerializer::SerializeContext& ctx, T& item,\
const std::string& /*name*/) { item.serial_process(j, ctx); }
struct RsTypeSerializer
{
/** This type should be used to pass a parameter to drive the serialisation
* if needed */
struct TlvMemBlock_proxy: public std::pair<void*&,uint32_t&>
{
TlvMemBlock_proxy(void*& p, uint32_t& s) :
std::pair<void*&,uint32_t&>(p,s) {}
TlvMemBlock_proxy(uint8_t*& p,uint32_t& s) :
std::pair<void*&,uint32_t&>(*(void**)&p,s) {}
};
/// Generic types
template<typename T>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
T& member,const std::string& member_name)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
ctx.mOffset += serial_size(member);
break;
case RsGenericSerializer::DESERIALIZE:
ctx.mOk = ctx.mOk &&
deserialize(ctx.mData,ctx.mSize,ctx.mOffset,member);
break;
case RsGenericSerializer::SERIALIZE:
ctx.mOk = ctx.mOk &&
serialize(ctx.mData,ctx.mSize,ctx.mOffset,member);
break;
case RsGenericSerializer::PRINT:
print_data(member_name,member);
break;
default:
ctx.mOk = false;
throw std::runtime_error("Unknown serial job");
}
}
/// Generic types + type_id
template<typename T>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
uint16_t type_id, T& member,
const std::string& member_name )
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
ctx.mOffset += serial_size(type_id,member);
break;
case RsGenericSerializer::DESERIALIZE:
ctx.mOk = ctx.mOk &&
deserialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member);
break;
case RsGenericSerializer::SERIALIZE:
ctx.mOk = ctx.mOk &&
serialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member);
break;
case RsGenericSerializer::PRINT:
print_data(member_name,type_id,member);
break;
default:
ctx.mOk = false;
throw std::runtime_error("Unknown serial job");
}
}
/// std::map<T,U>
template<typename T,typename U>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
std::map<T,U>& v,
const std::string& member_name )
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4;
for(typename std::map<T,U>::iterator it(v.begin());it!=v.end();++it)
{
serial_process( j, ctx, const_cast<T&>(it->first),
"map::*it->first" );
serial_process( j,ctx,const_cast<U&>(it->second),
"map::*it->second" );
}
break;
}
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0;
serial_process(j,ctx,n,"temporary size");
for(uint32_t i=0; i<n; ++i)
{
T t; U u;
serial_process(j, ctx, t, "map::*it->first");
serial_process(j, ctx, u, "map::*it->second");
v[t] = u;
}
break;
}
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size");
for(typename std::map<T,U>::iterator it(v.begin());it!=v.end();++it)
{
serial_process( j, ctx, const_cast<T&>(it->first),
"map::*it->first" );
serial_process( j, ctx, const_cast<U&>(it->second),
"map::*it->second" );
}
break;
}
case RsGenericSerializer::PRINT:
{
if(v.empty())
std::cerr << " Empty map \"" << member_name << "\""
<< std::endl;
else
std::cerr << " std::map of " << v.size() << " elements: \""
<< member_name << "\"" << std::endl;
for(typename std::map<T,U>::iterator it(v.begin());it!=v.end();++it)
{
std::cerr << " ";
serial_process( j, ctx,const_cast<T&>(it->first),
"map::*it->first" );
serial_process( j, ctx, const_cast<U&>(it->second),
"map::*it->second" );
}
break;
}
default: break;
}
}
/// std::vector<T>
template<typename T>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
std::vector<T>& v,
const std::string& member_name )
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4;
for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name);
break;
}
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0;
serial_process(j,ctx,n,"temporary size");
v.resize(n);
for(uint32_t i=0;i<v.size();++i)
serial_process(j,ctx,v[i],member_name);
break;
}
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size");
for(uint32_t i=0; i<v.size(); ++i)
serial_process(j,ctx,v[i],member_name);
break;
}
case RsGenericSerializer::PRINT:
{
if(v.empty())
std::cerr << " Empty array"<< std::endl;
else
std::cerr << " Array of " << v.size() << " elements:"
<< std::endl;
for(uint32_t i=0;i<v.size();++i)
{
std::cerr << " " ;
serial_process(j,ctx,v[i],member_name);
}
break;
}
default: break;
}
}
/// std::set<T>
template<typename T>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
std::set<T>& v, const std::string& member_name )
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4;
for(typename std::set<T>::iterator it(v.begin());it!=v.end();++it)
// the const cast here is a hack to avoid serial_process to
// instantiate serialise(const T&)
serial_process(j,ctx,const_cast<T&>(*it) ,member_name);
break;
}
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0;
serial_process(j,ctx,n,"temporary size");
for(uint32_t i=0; i<n; ++i)
{
T tmp;
serial_process<T>(j,ctx,tmp,member_name);
v.insert(tmp);
}
break;
}
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size");
for(typename std::set<T>::iterator it(v.begin());it!=v.end();++it)
// the const cast here is a hack to avoid serial_process to
// instantiate serialise(const T&)
serial_process(j,ctx,const_cast<T&>(*it) ,member_name);
break;
}
case RsGenericSerializer::PRINT:
{
if(v.empty()) std::cerr << " Empty set"<< std::endl;
else std::cerr << " Set of " << v.size() << " elements:"
<< std::endl;
break;
}
default: break;
}
}
/// std::list<T>
template<typename T>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
std::list<T>& v,
const std::string& member_name )
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE:
{
ctx.mOffset += 4;
for(typename std::list<T>::iterator it(v.begin());it!=v.end();++it)
serial_process(j,ctx,*it ,member_name);
break;
}
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0;
serial_process(j,ctx,n,"temporary size");
for(uint32_t i=0;i<n;++i)
{
T tmp;
serial_process<T>(j,ctx,tmp,member_name);
v.push_back(tmp);
}
break;
}
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.size();
serial_process(j,ctx,n,"temporary size");
for(typename std::list<T>::iterator it(v.begin());it!=v.end();++it)
serial_process(j,ctx,*it ,member_name);
break;
}
case RsGenericSerializer::PRINT:
{
if(v.empty()) std::cerr << " Empty list"<< std::endl;
else std::cerr << " List of " << v.size() << " elements:"
<< std::endl;
break;
}
default: break;
}
}
/// t_RsFlags32<> types
template<int N>
static void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx,
t_RsFlags32<N>& v,
const std::string& /*member_name*/)
{
switch(j)
{
case RsGenericSerializer::SIZE_ESTIMATE: ctx.mOffset += 4; break;
case RsGenericSerializer::DESERIALIZE:
{
uint32_t n=0;
deserialize<uint32_t>(ctx.mData,ctx.mSize,ctx.mOffset,n);
v = t_RsFlags32<N>(n);
break;
}
case RsGenericSerializer::SERIALIZE:
{
uint32_t n=v.toUInt32();
serialize<uint32_t>(ctx.mData,ctx.mSize,ctx.mOffset,n);
break;
}
case RsGenericSerializer::PRINT:
std::cerr << " Flags of type " << std::hex << N << " : "
<< v.toUInt32() << std::endl;
break;
}
}
/** TODO
* Serialization format is inside context, but context is not passed to
* following functions, that need to know the format to do the job, actually
* RsGenericSerializer::FORMAT_BINARY is assumed in all of them!!
*/
protected:
template<typename T> static bool serialize(
uint8_t data[], uint32_t size, uint32_t &offset, const T& member );
template<typename T> static bool deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset, T& member);
template<typename T> static uint32_t serial_size(const T& member);
template<typename T> static void print_data(
const std::string& name, const T& member);
template<typename T> static bool serialize(
uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id,
const T& member );
template<typename T> static bool deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset,
uint16_t type_id, T& member );
template<typename T> static uint32_t serial_size(
uint16_t type_id,const T& member );
template<typename T> static void print_data(
const std::string& name,uint16_t type_id,const T& member );
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
static bool serialize(
uint8_t data[], uint32_t size, uint32_t &offset,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member );
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
static bool deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset,
t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member );
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
static uint32_t serial_size(
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member );
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
static void print_data(
const std::string& name,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member );
template<class TLV_CLASS,uint32_t TLV_TYPE>
static bool serialize(
uint8_t data[], uint32_t size, uint32_t &offset,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member );
template<class TLV_CLASS,uint32_t TLV_TYPE>
static bool deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset,
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member );
template<class TLV_CLASS,uint32_t TLV_TYPE>
static uint32_t serial_size(const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member);
template<class TLV_CLASS,uint32_t TLV_TYPE>
static void print_data(
const std::string& name,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member);
};
// t_RsGenericId<>
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
bool RsTypeSerializer::serialize (
uint8_t data[], uint32_t size, uint32_t &offset,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member )
{ return (*const_cast<const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER> *>(&member)).serialise(data,size,offset); }
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
bool RsTypeSerializer::serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member)
{
return (*const_cast<const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER> *>(&member)).serialise(data,size,offset) ;
}
bool RsTypeSerializer::deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset,
t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member )
{ return member.deserialise(data,size,offset); }
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member)
{
return member.deserialise(data,size,offset) ;
}
uint32_t RsTypeSerializer::serial_size(
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member )
{ return member.serial_size(); }
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
uint32_t RsTypeSerializer::serial_size(const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member)
void RsTypeSerializer::print_data(
const std::string& /*name*/,
const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member )
{
return member.serial_size();
std::cerr << " [RsGenericId<" << std::hex << UNIQUE_IDENTIFIER << ">] : "
<< member << std::endl;
}
template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER>
void RsTypeSerializer::print_data(const std::string& /* name */,const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member)
{
std::cerr << " [RsGenericId<" << std::hex << UNIQUE_IDENTIFIER << ">] : " << member << std::endl;
}
//=================================================================================================//
// t_RsTlvList<> //
//=================================================================================================//
// t_RsTlvList<>
template<class TLV_CLASS,uint32_t TLV_TYPE>
bool RsTypeSerializer::serialize (uint8_t data[], uint32_t size, uint32_t &offset, const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member)
bool RsTypeSerializer::serialize(
uint8_t data[], uint32_t size, uint32_t &offset,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member )
{
return (*const_cast<const t_RsTlvList<TLV_CLASS,TLV_TYPE> *>(&member)).SetTlv(data,size,&offset) ;
return (*const_cast<const t_RsTlvList<TLV_CLASS,TLV_TYPE> *>(&member)).SetTlv(data,size,&offset);
}
template<class TLV_CLASS,uint32_t TLV_TYPE>
bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, t_RsTlvList<TLV_CLASS,TLV_TYPE>& member)
bool RsTypeSerializer::deserialize(
const uint8_t data[], uint32_t size, uint32_t &offset,
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member )
{
return member.GetTlv(const_cast<uint8_t*>(data),size,&offset) ;
return member.GetTlv(const_cast<uint8_t*>(data),size,&offset);
}
template<class TLV_CLASS,uint32_t TLV_TYPE>
uint32_t RsTypeSerializer::serial_size(const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member)
{
return member.TlvSize();
}
uint32_t RsTypeSerializer::serial_size(
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member)
{ return member.TlvSize(); }
template<class TLV_CLASS,uint32_t TLV_TYPE>
void RsTypeSerializer::print_data(const std::string& /* name */,const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member)
void RsTypeSerializer::print_data(
const std::string& /*name*/,
const t_RsTlvList<TLV_CLASS,TLV_TYPE>& member)
{
std::cerr << " [t_RsTlvString<" << std::hex << TLV_TYPE << ">] : size=" << member.mList.size() << std::endl;
std::cerr << " [t_RsTlvString<" << std::hex << TLV_TYPE << ">] : size="
<< member.mList.size() << std::endl;
}