Line data Source code
1 : /*! \file binary.hpp
2 : \brief Binary input and output archives */
3 : /*
4 : Copyright (c) 2014, Randolph Voorhies, Shane Grant
5 : All rights reserved.
6 :
7 : Redistribution and use in source and binary forms, with or without
8 : modification, are permitted provided that the following conditions are met:
9 : * Redistributions of source code must retain the above copyright
10 : notice, this list of conditions and the following disclaimer.
11 : * Redistributions in binary form must reproduce the above copyright
12 : notice, this list of conditions and the following disclaimer in the
13 : documentation and/or other materials provided with the distribution.
14 : * Neither the name of the copyright holder nor the
15 : names of its contributors may be used to endorse or promote products
16 : derived from this software without specific prior written permission.
17 :
18 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 : ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 : WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 : DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
22 : DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 : (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 : LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 : ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 : SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 : */
29 : #ifndef CEREAL_ARCHIVES_BINARY_HPP_
30 : #define CEREAL_ARCHIVES_BINARY_HPP_
31 :
32 : #include "cereal/cereal.hpp"
33 : #include <sstream>
34 :
35 : namespace cereal
36 : {
37 : // ######################################################################
38 : //! An output archive designed to save data in a compact binary representation
39 : /*! This archive outputs data to a stream in an extremely compact binary
40 : representation with as little extra metadata as possible.
41 :
42 : This archive does nothing to ensure that the endianness of the saved
43 : and loaded data is the same. If you need to have portability over
44 : architectures with different endianness, use PortableBinaryOutputArchive.
45 :
46 : When using a binary archive and a file stream, you must use the
47 : std::ios::binary format flag to avoid having your data altered
48 : inadvertently.
49 :
50 : \ingroup Archives */
51 : class BinaryOutputArchive : public OutputArchive<BinaryOutputArchive, AllowEmptyClassElision>
52 : {
53 : public:
54 : //! Construct, outputting to the provided stream
55 : /*! @param stream The stream to output to. Can be a stringstream, a file stream, or
56 : even cout! */
57 3704 : BinaryOutputArchive(std::ostream & stream) :
58 : OutputArchive<BinaryOutputArchive, AllowEmptyClassElision>(this),
59 3704 : itsStream(stream)
60 3704 : { }
61 :
62 3704 : ~BinaryOutputArchive() CEREAL_NOEXCEPT = default;
63 :
64 : //! Writes size bytes of data to the output stream
65 2564755 : void saveBinary( const void * data, std::streamsize size )
66 : {
67 2564755 : auto const writtenSize = itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size );
68 :
69 2564755 : if(writtenSize != size)
70 0 : throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize));
71 2564755 : }
72 :
73 : private:
74 : std::ostream & itsStream;
75 : };
76 :
77 : // ######################################################################
78 : //! An input archive designed to load data saved using BinaryOutputArchive
79 : /* This archive does nothing to ensure that the endianness of the saved
80 : and loaded data is the same. If you need to have portability over
81 : architectures with different endianness, use PortableBinaryOutputArchive.
82 :
83 : When using a binary archive and a file stream, you must use the
84 : std::ios::binary format flag to avoid having your data altered
85 : inadvertently.
86 :
87 : \ingroup Archives */
88 : class BinaryInputArchive : public InputArchive<BinaryInputArchive, AllowEmptyClassElision>
89 : {
90 : public:
91 : //! Construct, loading from the provided stream
92 3704 : BinaryInputArchive(std::istream & stream) :
93 : InputArchive<BinaryInputArchive, AllowEmptyClassElision>(this),
94 3704 : itsStream(stream)
95 3704 : { }
96 :
97 3704 : ~BinaryInputArchive() CEREAL_NOEXCEPT = default;
98 :
99 : //! Reads size bytes of data from the input stream
100 2563755 : void loadBinary( void * const data, std::streamsize size )
101 : {
102 2563755 : auto const readSize = itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size );
103 :
104 2563755 : if(readSize != size)
105 0 : throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
106 2563755 : }
107 :
108 : private:
109 : std::istream & itsStream;
110 : };
111 :
112 : // ######################################################################
113 : // Common BinaryArchive serialization functions
114 :
115 : //! Saving for POD types to binary
116 : template<class T> inline
117 : typename std::enable_if<std::is_arithmetic<T>::value, void>::type
118 2493206 : CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, T const & t)
119 : {
120 2493206 : ar.saveBinary(std::addressof(t), sizeof(t));
121 2493206 : }
122 :
123 : //! Loading for POD types from binary
124 : template<class T> inline
125 : typename std::enable_if<std::is_arithmetic<T>::value, void>::type
126 2492206 : CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, T & t)
127 : {
128 2492206 : ar.loadBinary(std::addressof(t), sizeof(t));
129 2492206 : }
130 :
131 : //! Serializing NVP types to binary
132 : template <class Archive, class T> inline
133 : CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
134 : CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, NameValuePair<T> & t )
135 : {
136 : ar( t.value );
137 : }
138 :
139 : //! Serializing SizeTags to binary
140 : template <class Archive, class T> inline
141 : CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
142 162698 : CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, SizeTag<T> & t )
143 : {
144 162698 : ar( t.size );
145 162698 : }
146 :
147 : //! Saving binary data
148 : template <class T> inline
149 71549 : void CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, BinaryData<T> const & bd)
150 : {
151 71549 : ar.saveBinary( bd.data, static_cast<std::streamsize>( bd.size ) );
152 71549 : }
153 :
154 : //! Loading binary data
155 : template <class T> inline
156 71549 : void CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, BinaryData<T> & bd)
157 : {
158 71549 : ar.loadBinary(bd.data, static_cast<std::streamsize>( bd.size ) );
159 71549 : }
160 : } // namespace cereal
161 :
162 : // register archives for polymorphic support
163 : CEREAL_REGISTER_ARCHIVE(cereal::BinaryOutputArchive)
164 : CEREAL_REGISTER_ARCHIVE(cereal::BinaryInputArchive)
165 :
166 : // tie input and output archives together
167 : CEREAL_SETUP_ARCHIVE_TRAITS(cereal::BinaryInputArchive, cereal::BinaryOutputArchive)
168 :
169 : #endif // CEREAL_ARCHIVES_BINARY_HPP_
|