created .cc files for serialization

This commit is contained in:
csoler 2017-04-02 14:48:17 +02:00
parent b52071d0c9
commit ddbe2ef9a1
6 changed files with 82 additions and 259 deletions

View File

@ -771,6 +771,13 @@ HEADERS += gxstunnel/p3gxstunnel.h \
SOURCES += gxstunnel/p3gxstunnel.cc \
gxstunnel/rsgxstunnelitems.cc
# new serialization code
HEADERS += serialization/rsserializer.h \
serialization/rstypeserializer.h
SOURCES += serialization/rsserializer.cc \
serialization/rstypeserializer.cc
# Identity Service
HEADERS += retroshare/rsidentity.h \
gxs/rsgixs.h \

View File

@ -122,7 +122,10 @@ class RsItem: public RsMemoryManagement::SmallObject
*/
typedef enum { SIZE_ESTIMATE = 0x01, SERIALIZE = 0x02, DESERIALIZE = 0x03} SerializeJob ;
virtual void serial_process(SerializeJob j,SerializeContext& ctx) = 0;
virtual void serial_process(SerializeJob j,SerializeContext& ctx)
{
std::cerr << "(EE) RsItem::serial_process() called by an item using new serialization classes, but not derived! " << std::endl;
}
private:
uint32_t type;

View File

@ -1,35 +0,0 @@
#pragma once
#include "serialiser/rsserial.h"
class RsItem ;
class SerializeContext;
#define SERIALIZE_ERROR() std::cerr << __PRETTY_FUNCTION__ << " : "
class RsSerializable: public RsItem
{
public:
typedef enum { SIZE_ESTIMATE = 0x01, SERIALIZE = 0x02, DESERIALIZE = 0x03} SerializeJob ;
RsSerializable(uint8_t version,uint16_t service,uint8_t id)
: RsItem(version,service,id)
{
}
/**
* @brief serialize this object to the given buffer
* @param Job to do: serialise or deserialize.
* @param data Chunk of memory were to dump the serialized data
* @param size Size of memory chunk
* @param offset Readed to determine at witch offset start writing data,
* written to inform caller were written data ends, the updated value
* is usually passed by the caller to serialize of another
* RsSerializable so it can write on the same chunk of memory just
* after where this RsSerializable has been serialized.
* @return true if serialization successed, false otherwise
*/
virtual void serial_process(SerializeJob j,SerializeContext& ctx) = 0;
};

View File

@ -0,0 +1,67 @@
#pragma once
#include "serialization/rsserializer.h"
RsItem *RsSerializer::deserialise(const uint8_t *data,uint32_t size)
{
uint32_t rstype = getRsItemId(const_cast<void*>((const void*)data)) ;
RsItem *item = create_item(getRsItemService(rstype),getRsItemSubType(rstype)) ;
if(!item)
{
std::cerr << "(EE) cannot deserialise: unknown item type " << std::hex << rstype << std::dec << std::endl;
return NULL ;
}
SerializeContext ctx(const_cast<uint8_t*>(data),size);
ctx.mOffset = 8 ;
item->serial_process(RsItem::DESERIALIZE, ctx) ;
if(ctx.mOk)
return item ;
delete item ;
return NULL ;
}
bool RsSerializer::serialise(RsItem *item,uint8_t *const data,uint32_t size)
{
SerializeContext ctx(data,0);
uint32_t tlvsize = this->size(item) ;
if(tlvsize > size)
throw std::runtime_error("Cannot serialise: not enough room.") ;
if(!setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize))
{
std::cerr << "RsSerializer::serialise_item(): ERROR. Not enough size!" << std::endl;
return false ;
}
ctx.mOffset = 8;
ctx.mSize = tlvsize;
item->serial_process(RsItem::SERIALIZE,ctx) ;
if(ctx.mSize != ctx.mOffset)
{
std::cerr << "RsSerializer::serialise_item(): ERROR. offset does not match expected size!" << std::endl;
return false ;
}
return true ;
}
uint32_t RsSerializer::size(RsItem *item)
{
SerializeContext ctx(NULL,0);
ctx.mSize = 8 ; // header size
item->serial_process(RsItem::SIZE_ESTIMATE, ctx) ;
return ctx.mSize ;
}

View File

@ -35,66 +35,9 @@ class RsSerializer: public RsSerialType
return NULL ;
}
RsItem *deserialise(const uint8_t *data,uint32_t size)
{
uint32_t rstype = getRsItemId(const_cast<void*>((const void*)data)) ;
RsItem *item = create_item(getRsItemService(rstype),getRsItemSubType(rstype)) ;
if(!item)
{
std::cerr << "(EE) cannot deserialise: unknown item type " << std::hex << rstype << std::dec << std::endl;
return NULL ;
}
SerializeContext ctx(const_cast<uint8_t*>(data),size);
ctx.mOffset = 8 ;
item->serial_process(RsItem::DESERIALIZE, ctx) ;
if(ctx.mOk)
return item ;
delete item ;
return NULL ;
}
bool serialise(RsItem *item,uint8_t *const data,uint32_t size)
{
SerializeContext ctx(data,0);
uint32_t tlvsize = this->size(item) ;
if(tlvsize > size)
throw std::runtime_error("Cannot serialise: not enough room.") ;
if(!setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize))
{
std::cerr << "RsSerializer::serialise_item(): ERROR. Not enough size!" << std::endl;
return false ;
}
ctx.mOffset = 8;
ctx.mSize = tlvsize;
item->serial_process(RsItem::SERIALIZE,ctx) ;
if(ctx.mSize != ctx.mOffset)
{
std::cerr << "RsSerializer::serialise_item(): ERROR. offset does not match expected size!" << std::endl;
return false ;
}
return true ;
}
uint32_t size(RsItem *item)
{
SerializeContext ctx(NULL,0);
ctx.mSize = 8 ; // header size
item->serial_process(RsItem::SIZE_ESTIMATE, ctx) ;
return ctx.mSize ;
}
RsItem *deserialise(const uint8_t *data,uint32_t size) ;
bool serialise(RsItem *item,uint8_t *const data,uint32_t size) ;
uint32_t size(RsItem *item) ;
};

View File

@ -1,24 +1,6 @@
#include "serialiser/rsserial.h"
#include "serialiser/rstlvbase.h"
template<typename T> T ntoh(T t)
{
if(sizeof(T) == 8) return t;
if(sizeof(T) == 4) return ntohl(t) ;
if(sizeof(T) == 2) return ntohs(t) ;
std::cerr << "(EE) unhandled type of size " << sizeof(T) << " in ntoh<>" << std::endl;
return t;
}
template<typename T> T hton(T t)
{
if(sizeof(T) == 8) return t;
if(sizeof(T) == 4) return htonl(t) ;
if(sizeof(T) == 2) return htons(t) ;
std::cerr << "(EE) unhandled type of size " << sizeof(T) << " in hton<>" << std::endl;
return t;
}
class RsTypeSerializer
{
public:
@ -48,148 +30,4 @@ class RsTypeSerializer
template<typename T> static uint32_t serial_size(const T& /* member */);
};
/// Templates to generate RsSerializer for standard integral types
//
template<typename N,uint32_t SIZE> class t_SerializerNType
{
public:
static bool serialize(uint8_t data[], uint32_t size, uint32_t &offset, const N& member)
{
if (size <= offset || size < SIZE + offset)
{
SERIALIZE_ERROR() << ": not enough room. SIZE+offset=" << SIZE+offset << " and size is only " << size << std::endl;
return false;
}
N tmp = hton<N>(member);
memcpy(data+offset, &tmp, SIZE);
offset += SIZE;
return true;
}
static bool deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, N& member)
{
if (size <= offset || size < offset + SIZE)
{
SERIALIZE_ERROR() << ": not enough room. SIZE+offset=" << SIZE+offset << " and size is only " << size << std::endl;
return false;
}
N tmp ;
memcpy(&tmp, data+offset, SIZE);
member = ntoh<N>(tmp);
offset += SIZE;
return true;
}
static uint32_t serial_size(const N& /* member */)
{
return SIZE;
}
};
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint8_t& member)
{
return t_SerializerNType<uint8_t,1>::serialize(data,size,offset,member);
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint32_t& member)
{
return t_SerializerNType<uint32_t,4>::serialize(data,size,offset,member);
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint64_t& member)
{
return t_SerializerNType<uint64_t,8>::serialize(data,size,offset,member);
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint8_t& member)
{
return t_SerializerNType<uint8_t,1>::deserialize(data,size,offset,member);
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint32_t& member)
{
return t_SerializerNType<uint32_t,4>::deserialize(data,size,offset,member);
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint64_t& member)
{
return t_SerializerNType<uint64_t,8>::deserialize(data,size,offset,member);
}
template<> uint32_t RsTypeSerializer::serial_size(const uint8_t& member)
{
return t_SerializerNType<uint8_t,1>::serial_size(member);
}
template<> uint32_t RsTypeSerializer::serial_size(const uint32_t& member)
{
return t_SerializerNType<uint32_t,4>::serial_size(member);
}
template<> uint32_t RsTypeSerializer::serial_size(const uint64_t& member)
{
return t_SerializerNType<uint64_t,8>::serial_size(member);
}
//// Float
//
template<> uint32_t RsTypeSerializer::serial_size(const float&){ return 4; }
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t& offset, const float& f)
{
uint32_t sz = serial_size(f);
if ( !data || size <= offset || size < sz + offset )
{
SERIALIZE_ERROR() << ": not enough room. SIZE+offset=" << sz+offset << " and size is only " << size << std::endl;
return false;
}
const float tmp = f;
if(tmp < 0.0f)
{
SERIALIZE_ERROR() << "Cannot serialise invalid negative float value " << tmp << std::endl;
return false;
}
/* This serialisation is quite accurate. The max relative error is approx.
* 0.01% and most of the time less than 1e-05% The error is well distributed
* over numbers also. */
uint32_t n;
if(tmp < 1e-7) n = (~(uint32_t)0);
else n = ((uint32_t)( (1.0f/(1.0f+tmp) * (~(uint32_t)0))));
n = hton<uint32_t>(n);
memcpy(data+offset, &n, sz);
offset += sz;
return true;
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, float& f)
{
uint32_t sz = serial_size(f);
if ( !data || size <= offset || size < offset + sz )
{
SERIALIZE_ERROR() << "Cannot deserialise float value. Not enough room. size=" << size << ", offset=" << offset << std::endl;
return false;
}
uint32_t n;
memcpy(&n, data+offset, sz);
n = ntoh<uint32_t>(n);
f = 1.0f/ ( n/(float)(~(uint32_t)0)) - 1.0f;
return true;
}
typedef std::pair<std::string&,uint16_t> TlvString;
/// Serializer for std::string
template<> uint32_t RsTypeSerializer::serial_size<TlvString>(const TlvString& s)
{
return GetTlvStringSize(s.first) ;
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,const TlvString& s)
{
return SetTlvString(data,size,&offset,s.second,s.first) ;
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,TlvString& s)
{
return GetTlvString((void*)data,size,&offset,s.second,s.first) ;
}