#ifndef CEREAL_BINARY_ARCHIVE_BINARY_ARCHIVE_HPP_ #define CEREAL_BINARY_ARCHIVE_BINARY_ARCHIVE_HPP_ #include #include namespace cereal { // ###################################################################### class BinaryOutputArchive : public OutputArchive { public: BinaryOutputArchive(std::ostream & stream) : OutputArchive(this), itsStream(stream) { } //! Writes size bytes of data to the output stream void save_binary( const void * data, size_t size ) { auto const writtenSize = itsStream.rdbuf()->sputn( reinterpret_cast( data ), size ); if(writtenSize != size) throw 1; // TODO: something terrible } //! Pushes a placeholder for data onto the archive and saves its position void pushPosition( size_t size ) { itsPositionStack.push( itsStream.tellp() ); for(size_t i = 0; i < size; ++i) itsStream.rdbuf()->sputc('\0'); // char doesn't matter, but null-term is zero } //! Pops the most recently pushed position onto the archive, going to the end //! of the archive if the stack is empty /*! @return true if the stack is empty and we are at the end of the archive */ bool popPosition() { if( itsPositionStack.empty() ) // seek to end of stream { itsStream.seekp( 0, std::ios_base::end ); return true; } else { itsStream.seekp( itsPositionStack.top() ); itsPositionStack.pop(); return false; } } //! Resets the position stack and seeks to the end of the archive void resetPosition() { while( !popPosition() ); } private: std::ostream & itsStream; std::stack itsPositionStack; }; // ###################################################################### class BinaryInputArchive : public InputArchive { public: BinaryInputArchive(std::istream & stream) : InputArchive(this), itsStream(stream) { } //! Reads size bytes of data from the input stream void load_binary( void * const data, size_t size ) { auto const readSize = itsStream.rdbuf()->sgetn( reinterpret_cast( data ), size ); if(readSize != size) throw 1; // TODO: something terrible } private: std::istream & itsStream; }; //! Saving for POD types to binary template typename std::enable_if::value, void>::type save(BinaryOutputArchive & ar, T const & t) { ar.save_binary(std::addressof(t), sizeof(t)); //std::cout << "Saving POD size: " << sizeof(T) << " [" << t << "]" << std::endl; } //! Loading for POD types from binary template typename std::enable_if::value, void>::type load(BinaryInputArchive & ar, T & t) { ar.load_binary(std::addressof(t), sizeof(t)); //std::cout << "Loading POD size: " << sizeof(T) << " [" << t << "]" << std::endl; } //! Saving for NVP types to binary template void save(BinaryOutputArchive & ar, NameValuePair const & t) { //std::cout << "Saving NVP: " << t.name << std::endl; ar & t.value; } //! Loading for NVP types from binary template void load(BinaryInputArchive & ar, NameValuePair t) { //std::cout << "Loading NVP... " << std::endl; ar & t.value; } template typename std::enable_if::value, void>::type save(BinaryOutputArchive & ar, T const & array) { ar.save_binary(array, traits::sizeofArray() * sizeof(typename std::remove_all_extents::type)); } template typename std::enable_if::value, void>::type load(BinaryInputArchive & ar, T & array) { ar.load_binary(array, traits::sizeofArray() * sizeof(typename std::remove_all_extents::type)); } template void serialize( Archive & ar, T * & t ) { static_assert(!sizeof(T), "Cereal does not support serializing raw pointers - please use a smart pointer"); } } #endif // CEREAL_BINARY_ARCHIVE_BINARY_ARCHIVE_HPP_