Improved the ana serializer implementation with helpers for containers.

This commit is contained in:
Guillermo Biset 2010-07-23 22:21:57 +00:00
parent 784cf12b97
commit 85a65de531

View file

@ -44,8 +44,38 @@ namespace ana
{
namespace serializer
{
template <class T>
struct template_is_container { enum { value = 0 }; };
// This could/should be done with Template Meta Programming
template <class T>
struct template_is_container< std::vector<T> > { enum { value = 1 }; };
template <class K, class D>
struct template_is_container< std::vector<K,D> > { enum { value = 1 }; };
template <class T>
struct template_is_container< std::list<T> > { enum { value = 1 }; };
template <class K, class D>
struct template_is_container< std::list<K,D> > { enum { value = 1 }; };
template <class K, class D, class C>
struct template_is_container< std::set<K,D,C> > { enum { value = 1 }; };
template <class K, class D>
struct template_is_container< std::map<K,D> > { enum { value = 1 }; };
template <class K, class D>
struct template_is_container< std::multimap<K,D> > { enum { value = 1 }; };
class bostream
{
private:
template<class T, bool IsContainer> struct _inserter_helper;
template<class T, bool IsContainer> friend struct _inserter_helper;
public:
bostream() :
_s()
@ -55,7 +85,7 @@ namespace ana
template <class T>
bostream& operator<< (T x)
{
_s.append(reinterpret_cast<char*>(&x), sizeof(T));
_inserter_helper<T, template_is_container<T>::value >::call(this, x);
return *this;
}
@ -100,6 +130,9 @@ namespace ana
class bistream
{
private:
template<class T> friend class container_reader;
public:
bistream(const std::string& str) :
_s(str),
@ -160,6 +193,112 @@ namespace ana
std::string _s;
std::size_t _pos;
};
template<class T>
class container_writer
{
public:
container_writer( size_t size, bostream& bos) :
_elements_left( size ),
_bos( bos )
{
_bos << uint32_t( size );
}
container_writer& operator<<(T element)
{
assert( _elements_left > 0 );
--_elements_left;
_bos << element;
return *this;
}
~container_writer()
{
if ( _elements_left != 0 )
throw/* std::runtime_error*/("More elements were expected to be written.");
}
private:
size_t _elements_left;
bostream& _bos;
};
template<class T>
class container_reader
{
public:
container_reader( bistream& bis) :
_elements_left( 0 ),
_bis( bis )
{
_bis >> _elements_left;
}
container_reader& operator>>(T& element)
{
assert( _elements_left > 0 );
--_elements_left;
_bis >> element;
return *this;
}
void skip(size_t elements = 1)
{
if ( elements > _elements_left )
throw("Trying to skip too much.");
_elements_left -= elements;
_bis._pos += sizeof(T) * elements;
if ( _bis._pos > _bis._s.size() )
throw("Too much mas skipped.");
}
void finished()
{
skip( _elements_left );
_elements_left = 0;
}
~container_reader()
{
if ( _elements_left != 0 )
finished();
}
private:
size_t _elements_left;
bistream& _bis;
};
template<class T>
struct bostream::_inserter_helper<T, false>
{
static void call(bostream* bos, const T& x)
{
bos->_s.append(reinterpret_cast<const char*>(&x), sizeof(T));
}
};
template<class T>
struct bostream::_inserter_helper<T, true>
{
static void call(bostream* bos, const T& cont)
{
const uint32_t size(cont.size());
(*bos) << size;
typename T::const_iterator it( cont.begin() );
for (; it != cont.end(); ++it)
(*bos) << *it;
}
};
} //serializer namespace
} //ana namespace