git repos / blockattack-game

blame: source/code/Libs/include/cereal/archives/portable_binary.hpp

normal view · raw

7a956470 sago007 2016-02-14 17:09 1
/*! \file binary.hpp
7a956470 sago007 2016-02-14 17:09 2
    \brief Binary input and output archives */
7a956470 sago007 2016-02-14 17:09 3
/*
7a956470 sago007 2016-02-14 17:09 4
  Copyright (c) 2014, Randolph Voorhies, Shane Grant
7a956470 sago007 2016-02-14 17:09 5
  All rights reserved.
7a956470 sago007 2016-02-14 17:09 6
7a956470 sago007 2016-02-14 17:09 7
  Redistribution and use in source and binary forms, with or without
7a956470 sago007 2016-02-14 17:09 8
  modification, are permitted provided that the following conditions are met:
7a956470 sago007 2016-02-14 17:09 9
      * Redistributions of source code must retain the above copyright
7a956470 sago007 2016-02-14 17:09 10
        notice, this list of conditions and the following disclaimer.
7a956470 sago007 2016-02-14 17:09 11
      * Redistributions in binary form must reproduce the above copyright
7a956470 sago007 2016-02-14 17:09 12
        notice, this list of conditions and the following disclaimer in the
7a956470 sago007 2016-02-14 17:09 13
        documentation and/or other materials provided with the distribution.
7a956470 sago007 2016-02-14 17:09 14
      * Neither the name of cereal nor the
7a956470 sago007 2016-02-14 17:09 15
        names of its contributors may be used to endorse or promote products
7a956470 sago007 2016-02-14 17:09 16
        derived from this software without specific prior written permission.
7a956470 sago007 2016-02-14 17:09 17
7a956470 sago007 2016-02-14 17:09 18
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
7a956470 sago007 2016-02-14 17:09 19
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
7a956470 sago007 2016-02-14 17:09 20
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
7a956470 sago007 2016-02-14 17:09 21
  DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
7a956470 sago007 2016-02-14 17:09 22
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
7a956470 sago007 2016-02-14 17:09 23
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
7a956470 sago007 2016-02-14 17:09 24
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7a956470 sago007 2016-02-14 17:09 25
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7a956470 sago007 2016-02-14 17:09 26
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7a956470 sago007 2016-02-14 17:09 27
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7a956470 sago007 2016-02-14 17:09 28
*/
7a956470 sago007 2016-02-14 17:09 29
#ifndef CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
7a956470 sago007 2016-02-14 17:09 30
#define CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
7a956470 sago007 2016-02-14 17:09 31
7a956470 sago007 2016-02-14 17:09 32
#include <cereal/cereal.hpp>
7a956470 sago007 2016-02-14 17:09 33
#include <sstream>
7a956470 sago007 2016-02-14 17:09 34
#include <limits>
7a956470 sago007 2016-02-14 17:09 35
7a956470 sago007 2016-02-14 17:09 36
namespace cereal
7a956470 sago007 2016-02-14 17:09 37
{
7a956470 sago007 2016-02-14 17:09 38
  namespace portable_binary_detail
7a956470 sago007 2016-02-14 17:09 39
  {
7a956470 sago007 2016-02-14 17:09 40
    //! Returns true if the current machine is little endian
7a956470 sago007 2016-02-14 17:09 41
    /*! @ingroup Internal */
7a956470 sago007 2016-02-14 17:09 42
    inline bool is_little_endian()
7a956470 sago007 2016-02-14 17:09 43
    {
7a956470 sago007 2016-02-14 17:09 44
      static std::int32_t test = 1;
7a956470 sago007 2016-02-14 17:09 45
      return *reinterpret_cast<std::int8_t*>( &test ) == 1;
7a956470 sago007 2016-02-14 17:09 46
    }
7a956470 sago007 2016-02-14 17:09 47
7a956470 sago007 2016-02-14 17:09 48
    //! Swaps the order of bytes for some chunk of memory
7a956470 sago007 2016-02-14 17:09 49
    /*! @param data The data as a uint8_t pointer
7a956470 sago007 2016-02-14 17:09 50
        @tparam DataSize The true size of the data
7a956470 sago007 2016-02-14 17:09 51
        @ingroup Internal */
7a956470 sago007 2016-02-14 17:09 52
    template <std::size_t DataSize>
7a956470 sago007 2016-02-14 17:09 53
    inline void swap_bytes( std::uint8_t * data )
7a956470 sago007 2016-02-14 17:09 54
    {
7a956470 sago007 2016-02-14 17:09 55
      for( std::size_t i = 0, end = DataSize / 2; i < end; ++i )
7a956470 sago007 2016-02-14 17:09 56
        std::swap( data[i], data[DataSize - i - 1] );
7a956470 sago007 2016-02-14 17:09 57
    }
7a956470 sago007 2016-02-14 17:09 58
  } // end namespace portable_binary_detail
7a956470 sago007 2016-02-14 17:09 59
7a956470 sago007 2016-02-14 17:09 60
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 61
  //! An output archive designed to save data in a compact binary representation portable over different architectures
7a956470 sago007 2016-02-14 17:09 62
  /*! This archive outputs data to a stream in an extremely compact binary
7a956470 sago007 2016-02-14 17:09 63
      representation with as little extra metadata as possible.
7a956470 sago007 2016-02-14 17:09 64
7a956470 sago007 2016-02-14 17:09 65
      This archive will record the endianness of the data and assuming that
7a956470 sago007 2016-02-14 17:09 66
      the user takes care of ensuring serialized types are the same size
7a956470 sago007 2016-02-14 17:09 67
      across machines, is portable over different architectures.
7a956470 sago007 2016-02-14 17:09 68
7a956470 sago007 2016-02-14 17:09 69
      When using a binary archive and a file stream, you must use the
7a956470 sago007 2016-02-14 17:09 70
      std::ios::binary format flag to avoid having your data altered
7a956470 sago007 2016-02-14 17:09 71
      inadvertently.
7a956470 sago007 2016-02-14 17:09 72
7a956470 sago007 2016-02-14 17:09 73
      \warning This archive has not been thoroughly tested across different architectures.
7a956470 sago007 2016-02-14 17:09 74
               Please report any issues, optimizations, or feature requests at
7a956470 sago007 2016-02-14 17:09 75
               <a href="www.github.com/USCiLab/cereal">the project github</a>.
7a956470 sago007 2016-02-14 17:09 76
7a956470 sago007 2016-02-14 17:09 77
    \ingroup Archives */
7a956470 sago007 2016-02-14 17:09 78
  class PortableBinaryOutputArchive : public OutputArchive<PortableBinaryOutputArchive, AllowEmptyClassElision>
7a956470 sago007 2016-02-14 17:09 79
  {
7a956470 sago007 2016-02-14 17:09 80
    public:
7a956470 sago007 2016-02-14 17:09 81
      //! Construct, outputting to the provided stream
7a956470 sago007 2016-02-14 17:09 82
      /*! @param stream The stream to output to.  Can be a stringstream, a file stream, or
7a956470 sago007 2016-02-14 17:09 83
        even cout! */
7a956470 sago007 2016-02-14 17:09 84
      PortableBinaryOutputArchive(std::ostream & stream) :
7a956470 sago007 2016-02-14 17:09 85
        OutputArchive<PortableBinaryOutputArchive, AllowEmptyClassElision>(this),
7a956470 sago007 2016-02-14 17:09 86
        itsStream(stream)
7a956470 sago007 2016-02-14 17:09 87
      {
7a956470 sago007 2016-02-14 17:09 88
        this->operator()( portable_binary_detail::is_little_endian() );
7a956470 sago007 2016-02-14 17:09 89
      }
7a956470 sago007 2016-02-14 17:09 90
7a956470 sago007 2016-02-14 17:09 91
      //! Writes size bytes of data to the output stream
7a956470 sago007 2016-02-14 17:09 92
      void saveBinary( const void * data, std::size_t size )
7a956470 sago007 2016-02-14 17:09 93
      {
7a956470 sago007 2016-02-14 17:09 94
        auto const writtenSize = static_cast<std::size_t>( itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size ) );
7a956470 sago007 2016-02-14 17:09 95
7a956470 sago007 2016-02-14 17:09 96
        if(writtenSize != size)
7a956470 sago007 2016-02-14 17:09 97
          throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize));
7a956470 sago007 2016-02-14 17:09 98
      }
7a956470 sago007 2016-02-14 17:09 99
7a956470 sago007 2016-02-14 17:09 100
    private:
7a956470 sago007 2016-02-14 17:09 101
      std::ostream & itsStream;
7a956470 sago007 2016-02-14 17:09 102
  };
7a956470 sago007 2016-02-14 17:09 103
7a956470 sago007 2016-02-14 17:09 104
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 105
  //! An input archive designed to load data saved using PortableBinaryOutputArchive
7a956470 sago007 2016-02-14 17:09 106
  /*! This archive outputs data to a stream in an extremely compact binary
7a956470 sago007 2016-02-14 17:09 107
      representation with as little extra metadata as possible.
7a956470 sago007 2016-02-14 17:09 108
7a956470 sago007 2016-02-14 17:09 109
      This archive will load the endianness of the serialized data and
7a956470 sago007 2016-02-14 17:09 110
      if necessary transform it to match that of the local machine.  This comes
7a956470 sago007 2016-02-14 17:09 111
      at a significant performance cost compared to non portable archives if
7a956470 sago007 2016-02-14 17:09 112
      the transformation is necessary, and also causes a small performance hit
7a956470 sago007 2016-02-14 17:09 113
      even if it is not necessary.
7a956470 sago007 2016-02-14 17:09 114
7a956470 sago007 2016-02-14 17:09 115
      It is recommended to use portable archives only if you know that you will
7a956470 sago007 2016-02-14 17:09 116
      be sending binary data to machines with different endianness.
7a956470 sago007 2016-02-14 17:09 117
7a956470 sago007 2016-02-14 17:09 118
      The archive will do nothing to ensure types are the same size - that is
7a956470 sago007 2016-02-14 17:09 119
      the responsibility of the user.
7a956470 sago007 2016-02-14 17:09 120
7a956470 sago007 2016-02-14 17:09 121
      When using a binary archive and a file stream, you must use the
7a956470 sago007 2016-02-14 17:09 122
      std::ios::binary format flag to avoid having your data altered
7a956470 sago007 2016-02-14 17:09 123
      inadvertently.
7a956470 sago007 2016-02-14 17:09 124
7a956470 sago007 2016-02-14 17:09 125
      \warning This archive has not been thoroughly tested across different architectures.
7a956470 sago007 2016-02-14 17:09 126
               Please report any issues, optimizations, or feature requests at
7a956470 sago007 2016-02-14 17:09 127
               <a href="www.github.com/USCiLab/cereal">the project github</a>.
7a956470 sago007 2016-02-14 17:09 128
7a956470 sago007 2016-02-14 17:09 129
    \ingroup Archives */
7a956470 sago007 2016-02-14 17:09 130
  class PortableBinaryInputArchive : public InputArchive<PortableBinaryInputArchive, AllowEmptyClassElision>
7a956470 sago007 2016-02-14 17:09 131
  {
7a956470 sago007 2016-02-14 17:09 132
    public:
7a956470 sago007 2016-02-14 17:09 133
      //! Construct, loading from the provided stream
7a956470 sago007 2016-02-14 17:09 134
      /*! @param stream The stream to read from. */
7a956470 sago007 2016-02-14 17:09 135
      PortableBinaryInputArchive(std::istream & stream) :
7a956470 sago007 2016-02-14 17:09 136
        InputArchive<PortableBinaryInputArchive, AllowEmptyClassElision>(this),
7a956470 sago007 2016-02-14 17:09 137
        itsStream(stream),
7a956470 sago007 2016-02-14 17:09 138
        itsConvertEndianness( false )
7a956470 sago007 2016-02-14 17:09 139
      {
7a956470 sago007 2016-02-14 17:09 140
        bool streamLittleEndian;
7a956470 sago007 2016-02-14 17:09 141
        this->operator()( streamLittleEndian );
7a956470 sago007 2016-02-14 17:09 142
        itsConvertEndianness = portable_binary_detail::is_little_endian() ^ streamLittleEndian;
7a956470 sago007 2016-02-14 17:09 143
      }
7a956470 sago007 2016-02-14 17:09 144
7a956470 sago007 2016-02-14 17:09 145
      //! Reads size bytes of data from the input stream
7a956470 sago007 2016-02-14 17:09 146
      /*! @param data The data to save
7a956470 sago007 2016-02-14 17:09 147
          @param size The number of bytes in the data
7a956470 sago007 2016-02-14 17:09 148
          @tparam DataSize T The size of the actual type of the data elements being loaded */
7a956470 sago007 2016-02-14 17:09 149
      template <std::size_t DataSize>
7a956470 sago007 2016-02-14 17:09 150
      void loadBinary( void * const data, std::size_t size )
7a956470 sago007 2016-02-14 17:09 151
      {
7a956470 sago007 2016-02-14 17:09 152
        // load data
7a956470 sago007 2016-02-14 17:09 153
        auto const readSize = static_cast<std::size_t>( itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size ) );
7a956470 sago007 2016-02-14 17:09 154
7a956470 sago007 2016-02-14 17:09 155
        if(readSize != size)
7a956470 sago007 2016-02-14 17:09 156
          throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
7a956470 sago007 2016-02-14 17:09 157
7a956470 sago007 2016-02-14 17:09 158
        // flip bits if needed
7a956470 sago007 2016-02-14 17:09 159
        if( itsConvertEndianness )
7a956470 sago007 2016-02-14 17:09 160
        {
7a956470 sago007 2016-02-14 17:09 161
          std::uint8_t * ptr = reinterpret_cast<std::uint8_t*>( data );
7a956470 sago007 2016-02-14 17:09 162
          for( std::size_t i = 0; i < size; i += DataSize )
7a956470 sago007 2016-02-14 17:09 163
            portable_binary_detail::swap_bytes<DataSize>( ptr );
7a956470 sago007 2016-02-14 17:09 164
        }
7a956470 sago007 2016-02-14 17:09 165
      }
7a956470 sago007 2016-02-14 17:09 166
7a956470 sago007 2016-02-14 17:09 167
    private:
7a956470 sago007 2016-02-14 17:09 168
      std::istream & itsStream;
7a956470 sago007 2016-02-14 17:09 169
      bool itsConvertEndianness; //!< If set to true, we will need to swap bytes upon loading
7a956470 sago007 2016-02-14 17:09 170
  };
7a956470 sago007 2016-02-14 17:09 171
7a956470 sago007 2016-02-14 17:09 172
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 173
  // Common BinaryArchive serialization functions
7a956470 sago007 2016-02-14 17:09 174
7a956470 sago007 2016-02-14 17:09 175
  //! Saving for POD types to portable binary
7a956470 sago007 2016-02-14 17:09 176
  template<class T> inline
7a956470 sago007 2016-02-14 17:09 177
  typename std::enable_if<std::is_arithmetic<T>::value, void>::type
7a956470 sago007 2016-02-14 17:09 178
  CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive & ar, T const & t)
7a956470 sago007 2016-02-14 17:09 179
  {
7a956470 sago007 2016-02-14 17:09 180
    static_assert( !std::is_floating_point<T>::value ||
7a956470 sago007 2016-02-14 17:09 181
                   (std::is_floating_point<T>::value && std::numeric_limits<T>::is_iec559),
7a956470 sago007 2016-02-14 17:09 182
                   "Portable binary only supports IEEE 754 standardized floating point" );
7a956470 sago007 2016-02-14 17:09 183
    ar.saveBinary(std::addressof(t), sizeof(t));
7a956470 sago007 2016-02-14 17:09 184
  }
7a956470 sago007 2016-02-14 17:09 185
7a956470 sago007 2016-02-14 17:09 186
  //! Loading for POD types from portable binary
7a956470 sago007 2016-02-14 17:09 187
  template<class T> inline
7a956470 sago007 2016-02-14 17:09 188
  typename std::enable_if<std::is_arithmetic<T>::value, void>::type
7a956470 sago007 2016-02-14 17:09 189
  CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive & ar, T & t)
7a956470 sago007 2016-02-14 17:09 190
  {
7a956470 sago007 2016-02-14 17:09 191
    static_assert( !std::is_floating_point<T>::value ||
7a956470 sago007 2016-02-14 17:09 192
                   (std::is_floating_point<T>::value && std::numeric_limits<T>::is_iec559),
7a956470 sago007 2016-02-14 17:09 193
                   "Portable binary only supports IEEE 754 standardized floating point" );
7a956470 sago007 2016-02-14 17:09 194
    ar.template loadBinary<sizeof(T)>(std::addressof(t), sizeof(t));
7a956470 sago007 2016-02-14 17:09 195
  }
7a956470 sago007 2016-02-14 17:09 196
7a956470 sago007 2016-02-14 17:09 197
  //! Serializing NVP types to portable binary
7a956470 sago007 2016-02-14 17:09 198
  template <class Archive, class T> inline
7a956470 sago007 2016-02-14 17:09 199
  CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive)
7a956470 sago007 2016-02-14 17:09 200
  CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, NameValuePair<T> & t )
7a956470 sago007 2016-02-14 17:09 201
  {
7a956470 sago007 2016-02-14 17:09 202
    ar( t.value );
7a956470 sago007 2016-02-14 17:09 203
  }
7a956470 sago007 2016-02-14 17:09 204
7a956470 sago007 2016-02-14 17:09 205
  //! Serializing SizeTags to portable binary
7a956470 sago007 2016-02-14 17:09 206
  template <class Archive, class T> inline
7a956470 sago007 2016-02-14 17:09 207
  CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive)
7a956470 sago007 2016-02-14 17:09 208
  CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, SizeTag<T> & t )
7a956470 sago007 2016-02-14 17:09 209
  {
7a956470 sago007 2016-02-14 17:09 210
    ar( t.size );
7a956470 sago007 2016-02-14 17:09 211
  }
7a956470 sago007 2016-02-14 17:09 212
7a956470 sago007 2016-02-14 17:09 213
  //! Saving binary data to portable binary
7a956470 sago007 2016-02-14 17:09 214
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 215
  void CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive & ar, BinaryData<T> const & bd)
7a956470 sago007 2016-02-14 17:09 216
  {
7a956470 sago007 2016-02-14 17:09 217
    typedef typename std::remove_pointer<T>::type TT;
7a956470 sago007 2016-02-14 17:09 218
    static_assert( !std::is_floating_point<TT>::value ||
7a956470 sago007 2016-02-14 17:09 219
                   (std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559),
7a956470 sago007 2016-02-14 17:09 220
                   "Portable binary only supports IEEE 754 standardized floating point" );
7a956470 sago007 2016-02-14 17:09 221
7a956470 sago007 2016-02-14 17:09 222
    ar.saveBinary( bd.data, static_cast<std::size_t>( bd.size ) );
7a956470 sago007 2016-02-14 17:09 223
  }
7a956470 sago007 2016-02-14 17:09 224
7a956470 sago007 2016-02-14 17:09 225
  //! Loading binary data from portable binary
7a956470 sago007 2016-02-14 17:09 226
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 227
  void CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive & ar, BinaryData<T> & bd)
7a956470 sago007 2016-02-14 17:09 228
  {
7a956470 sago007 2016-02-14 17:09 229
    typedef typename std::remove_pointer<T>::type TT;
7a956470 sago007 2016-02-14 17:09 230
    static_assert( !std::is_floating_point<TT>::value ||
7a956470 sago007 2016-02-14 17:09 231
                   (std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559),
7a956470 sago007 2016-02-14 17:09 232
                   "Portable binary only supports IEEE 754 standardized floating point" );
7a956470 sago007 2016-02-14 17:09 233
7a956470 sago007 2016-02-14 17:09 234
    ar.template loadBinary<sizeof(TT)>( bd.data, static_cast<std::size_t>( bd.size ) );
7a956470 sago007 2016-02-14 17:09 235
  }
7a956470 sago007 2016-02-14 17:09 236
} // namespace cereal
7a956470 sago007 2016-02-14 17:09 237
7a956470 sago007 2016-02-14 17:09 238
// register archives for polymorphic support
7a956470 sago007 2016-02-14 17:09 239
CEREAL_REGISTER_ARCHIVE(cereal::PortableBinaryOutputArchive)
7a956470 sago007 2016-02-14 17:09 240
CEREAL_REGISTER_ARCHIVE(cereal::PortableBinaryInputArchive)
7a956470 sago007 2016-02-14 17:09 241
7a956470 sago007 2016-02-14 17:09 242
// tie input and output archives together
7a956470 sago007 2016-02-14 17:09 243
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive)
7a956470 sago007 2016-02-14 17:09 244
7a956470 sago007 2016-02-14 17:09 245
#endif // CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
1970-01-01 00:00 246