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 cereal 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 RANDOLPH VOORHIES OR SHANE GRANT 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 7408 : BinaryOutputArchive(std::ostream & stream) :
58 : OutputArchive<BinaryOutputArchive, AllowEmptyClassElision>(this),
59 7408 : itsStream(stream)
60 7408 : { }
61 :
62 7408 : ~BinaryOutputArchive() CEREAL_NOEXCEPT = default;
63 :
64 : //! Writes size bytes of data to the output stream
65 5128914 : void saveBinary( const void * data, std::streamsize size )
66 : {
67 5128914 : auto const writtenSize = itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size );
68 :
69 5128914 : if(writtenSize != size)
70 0 : throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize));
71 5128914 : }
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 7408 : BinaryInputArchive(std::istream & stream) :
93 : InputArchive<BinaryInputArchive, AllowEmptyClassElision>(this),
94 7408 : itsStream(stream)
95 7408 : { }
96 :
97 7408 : ~BinaryInputArchive() CEREAL_NOEXCEPT = default;
98 :
99 : //! Reads size bytes of data from the input stream
100 5126914 : void loadBinary( void * const data, std::streamsize size )
101 : {
102 5126914 : auto const readSize = itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size );
103 :
104 5126914 : if(readSize != size)
105 0 : throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
106 5126914 : }
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 4985964 : CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, T const & t)
119 : {
120 4985964 : ar.saveBinary(std::addressof(t), sizeof(t));
121 4985964 : }
122 635713 :
123 : //! Loading for POD types from binary
124 635713 : template<class T> inline
125 635713 : typename std::enable_if<std::is_arithmetic<T>::value, void>::type
126 2305373 : CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, T & t)
127 : {
128 2305373 : ar.loadBinary(std::addressof(t), sizeof(t));
129 2305373 : }
130 612790 :
131 : //! Serializing NVP types to binary
132 612790 : template <class Archive, class T> inline
133 612790 : CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
134 3284728 : CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, NameValuePair<T> & t )
135 : {
136 3284728 : ar( t.value );
137 3284728 : }
138 952594 :
139 : //! Serializing SizeTags to binary
140 952594 : template <class Archive, class T> inline
141 952594 : CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
142 2758208 : CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, SizeTag<T> & t )
143 : {
144 2758208 : ar( t.size );
145 2758208 : }
146 1180938 :
147 : //! Saving binary data
148 1180938 : template <class T> inline
149 1181138 : void CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, BinaryData<T> const & bd)
150 690523 : {
151 200 : ar.saveBinary( bd.data, static_cast<std::streamsize>( bd.size ) );
152 690723 : }
153 690523 :
154 522765 : //! Loading binary data
155 : template <class T> inline
156 522965 : void CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, BinaryData<T> & bd)
157 523565 : {
158 198772 : ar.loadBinary(bd.data, static_cast<std::streamsize>( bd.size ) );
159 1000 : }
160 199372 : } // namespace cereal
161 198772 :
162 939328 : // register archives for polymorphic support
163 200 : CEREAL_REGISTER_ARCHIVE(cereal::BinaryOutputArchive)
164 939528 : CEREAL_REGISTER_ARCHIVE(cereal::BinaryInputArchive)
165 939528 :
166 123568 : // tie input and output archives together
167 200 : CEREAL_SETUP_ARCHIVE_TRAITS(cereal::BinaryInputArchive, cereal::BinaryOutputArchive)
168 123768 :
169 123768 : #endif // CEREAL_ARCHIVES_BINARY_HPP_
|