annotate C++/Pack.h @ 304:bae4af872cde

MFS
author David Demelier <markand@malikania.fr>
date Sat, 15 Nov 2014 13:19:30 +0100
parents 2935e07ddb88
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /*
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 * Pack.h -- binary data serialization
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 *
299
24085fae3162 Update licenses
David Demelier <markand@malikania.fr>
parents: 295
diff changeset
4 * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 *
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 * Permission to use, copy, modify, and/or distribute this software for any
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
7 * purpose with or without fee is hereby granted, provided that the above
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
8 * copyright notice and this permission notice appear in all copies.
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 *
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
17 */
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
18
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
19 #ifndef _PACK_H_
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
20 #define _PACK_H_
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
21
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
22 #include <cstdint>
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
23 #include <fstream>
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
24 #include <memory>
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
25 #include <sstream>
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
26 #include <string>
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
27
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
28 /**
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
29 * @class Pack
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
30 * @brief Serialize binary data to files
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
31 *
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
32 * This class write and read binary data from files. It currently
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
33 * support:
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
34 * uint8_t,
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
35 * uint16_t,
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
36 * uint32_t,
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
37 * uint64_t
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
38 */
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
39 class Pack {
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
40 private:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
41 template <typename T>
300
2935e07ddb88 Pack: little cosmetic changes
David Demelier <markand@malikania.fr>
parents: 299
diff changeset
42 struct IsContainer {
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
43 using Yes = char [1];
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
44 using No = char [2];
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
45
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
46 template <typename U>
300
2935e07ddb88 Pack: little cosmetic changes
David Demelier <markand@malikania.fr>
parents: 299
diff changeset
47 static constexpr Yes &test(typename U::value_type *);
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
48
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
49 template <typename U>
300
2935e07ddb88 Pack: little cosmetic changes
David Demelier <markand@malikania.fr>
parents: 299
diff changeset
50 static constexpr No &test(...);
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
51
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
52 static constexpr const bool value = sizeof (test<T>(0)) == sizeof (Yes);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
53 };
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
54
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
55 friend class PackWriter;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
56 friend class PackReader;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
57
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
58 public:
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
59 /**
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
60 * @enum Endian
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
61 * @brief Endian mode
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
62 */
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
63 enum Endian {
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 Little, //! Little endian
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
65 Big //! Big endian
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
66 };
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
67
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
68 public:
219
8fc177bbc4a6 Update some code
David Demelier <markand@malikania.fr>
parents: 185
diff changeset
69 /**
8fc177bbc4a6 Update some code
David Demelier <markand@malikania.fr>
parents: 185
diff changeset
70 * Host system endian mode.
8fc177bbc4a6 Update some code
David Demelier <markand@malikania.fr>
parents: 185
diff changeset
71 */
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
72 static const Endian mode;
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
73
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
74 /**
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
75 * @struct TypeInfo
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
76 * @brief Type information
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 *
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
78 * Used for conversions.
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
79 */
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
80 template <typename T>
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
81 struct TypeInfo {
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
82 static constexpr const bool convertible{false};
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
83 static constexpr const bool serializable{false};
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
84 };
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
85
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
86 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
87 * Helper to mark a specialization convertible.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
88 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
89 * Already done for:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
90 * uint8_t
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
91 * uint16_t
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
92 * uint32_t
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
93 * uint64_t
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
94 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
95 * The specialization must have the following function:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
96 *
300
2935e07ddb88 Pack: little cosmetic changes
David Demelier <markand@malikania.fr>
parents: 299
diff changeset
97 * static void convert(T &value) noexcept
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
98 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
99 struct Convertible {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
100 static constexpr const bool convertible{true};
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
101 };
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
102
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
103 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
104 * Helper to mark a specialization serializable.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
105 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
106 * The specialisation must have the following functions:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
107 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
108 * static void serialize(PackWriter &writer, const T &)
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
109 * static void unserialize(PackReader &reader, T &)
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
110 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
111 struct Serializable {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
112 static constexpr const bool serializable{true};
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
113 };
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
114
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
115 /**
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
116 * Convert data inplace.
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
117 *
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
118 * @param value the value
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
119 */
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
120 template <typename T>
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
121 static inline void convert(T &value) noexcept
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
122 {
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
123 static_assert(TypeInfo<T>::convertible, "unsupported type");
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
124
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
125 TypeInfo<T>::convert(value);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
126 }
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
127 };
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
128
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
129 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
130 * @class PackReader
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
131 * @brief Base abstract reader class
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
132 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
133 class PackReader {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
134 protected:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
135 Pack::Endian m_endian;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
136
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
137 PackReader(Pack::Endian endian);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
138
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
139 virtual std::istream &stream() = 0;
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
140
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
141 public:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
142 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
143 * Default destructor.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
144 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
145 virtual ~PackReader() = default;
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
146
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
147 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
148 * Read a primitive convertible type.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
149 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
150 * @param value the value destination
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
151 * @return *this
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
152 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
153 template <typename T, typename std::enable_if<Pack::TypeInfo<T>::convertible>::type * = nullptr>
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
154 PackReader &operator>>(T &value)
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
155 {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
156 stream().read(reinterpret_cast<char *>(&value), sizeof (T));
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
157
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
158 if (m_endian != Pack::mode)
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
159 Pack::convert(value);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
160
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
161 return *this;
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
162 }
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
163
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
164 /**
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
165 * Read a serializable type.
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
166 *
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
167 * @param value the value destination
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
168 * @return *this
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
169 */
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
170 template <typename T, typename std::enable_if<Pack::TypeInfo<T>::serializable>::type * = nullptr>
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
171 PackReader &operator>>(T &value)
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
172 {
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
173 Pack::TypeInfo<T>::unserialize(*this, value);
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
174
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
175 return *this;
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
176 }
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
177
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
178 /**
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
179 * Read an array.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
180 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
181 * This operator is a little bit tricky because you don't know in
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
182 * advance how much data you want to read. Because of that, this
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
183 * function looks the capacity of the container and reads that number
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
184 * of data.
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
185 *
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
186 * Because it looks for capacity, you can't use a container which
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
187 * already have some data, they will be overriden.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
188 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
189 * If this is a concern, you should roll your own loop to fill up
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
190 * your container.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
191 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
192 * @param container the container (all previous data will be lost)
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
193 * @return *this
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
194 */
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
195 template <typename T, typename std::enable_if<Pack::IsContainer<T>::value>::type * = nullptr>
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
196 PackReader &operator>>(T &container)
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
197 {
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
198 typename T::value_type v;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
199
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
200 T copy;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
201
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
202 for (size_t i = 0; i < container.capacity(); ++i) {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
203 (*this) >> v;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
204 copy.push_back(v);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
205 }
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
206
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
207 container = std::move(copy);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
208
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
209 return *this;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
210 }
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
211 };
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
212
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
213 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
214 * @class PackWriter
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
215 * @brief Base abstract writer class
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
216 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
217 class PackWriter {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
218 protected:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
219 Pack::Endian m_endian;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
220
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
221 PackWriter(Pack::Endian endian);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
222
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
223 virtual std::ostream &stream() = 0;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
224
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
225 public:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
226 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
227 * Default destructor.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
228 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
229 virtual ~PackWriter() = default;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
230
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
231 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
232 * Write a convertible type to the stream.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
233 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
234 * @param value the value
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
235 * @return *this
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
236 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
237 template <typename T, typename std::enable_if<Pack::TypeInfo<T>::convertible>::type * = nullptr>
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
238 PackWriter &operator<<(T value)
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
239 {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
240 if (m_endian != Pack::mode)
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
241 Pack::convert(value);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
242
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
243 stream().write(reinterpret_cast<const char *>(&value), sizeof (T));
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
244
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
245 return *this;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
246 }
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
247
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
248 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
249 * Write a serializable type to the stream.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
250 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
251 * @param value the value
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
252 * @return *this
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
253 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
254 template <typename T, typename std::enable_if<Pack::TypeInfo<T>::serializable>::type * = nullptr>
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
255 PackWriter &operator<<(const T &value)
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
256 {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
257 Pack::TypeInfo<T>::serialize(*this, value);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
258
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
259 return *this;
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
260 }
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
261
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
262 /**
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
263 * Write a container to the stream.
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
264 *
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
265 * @param container the container
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
266 * @return *this
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
267 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
268 template <typename T, typename std::enable_if<Pack::IsContainer<T>::value>::type * = nullptr>
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
269 PackWriter &operator<<(const T &container)
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
270 {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
271 for (const auto &v : container)
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
272 (*this) << v;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
273
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
274 return *this;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
275 }
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
276 };
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
277
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
278 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
279 * @class PackFileReader
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
280 * @brief Extract binary data from a file
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
281 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
282 class PackFileReader : public PackReader {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
283 private:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
284 std::ifstream m_in;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
285
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
286 protected:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
287 std::istream &stream() override;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
288
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
289 public:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
290 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
291 * Read a file.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
292 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
293 * @param path the path
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
294 * @param endian the endian requested
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
295 */
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
296 PackFileReader(const std::string &path, Pack::Endian endian);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
297 };
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
298
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
299 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
300 * @class PackStringReader
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
301 * @brief Extract binary data from a string
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
302 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
303 class PackStringReader : public PackReader {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
304 private:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
305 std::istringstream m_in;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
306
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
307 std::istream &stream() override;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
308
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
309 public:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
310 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
311 * Read a string.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
312 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
313 * @param input the input string
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
314 * @param endian the endian requested
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
315 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
316 PackStringReader(std::string input, Pack::Endian endian);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
317 };
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
318
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
319 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
320 * @class PackFileWriter
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
321 * @brief Write binary data to a string
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
322 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
323 class PackFileWriter : public PackWriter {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
324 private:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
325 std::ofstream m_out;
268
David Demelier <markand@malikania.fr>
parents: 267
diff changeset
326
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
327 protected:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
328 std::ostream &stream() override;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
329
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
330 public:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
331 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
332 * Write to a file.
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
333 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
334 * @param path the path
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
335 * @param endian the endian requested
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
336 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
337 PackFileWriter(const std::string &path, Pack::Endian endian);
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
338 };
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
339
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
340 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
341 * @class PackStringWriter
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
342 * @brief Write binary data to a string
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
343 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
344 class PackStringWriter : public PackWriter {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
345 private:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
346 std::ostringstream m_out;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
347
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
348 std::ostream &stream() override;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
349
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
350 public:
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
351 /**
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
352 * Write to a string
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
353 *
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
354 * @param endian the endian requested
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
355 */
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
356 PackStringWriter(Pack::Endian endian);
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
357
268
David Demelier <markand@malikania.fr>
parents: 267
diff changeset
358 /**
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
359 * The current buffer. Returns a copy of the string.
268
David Demelier <markand@malikania.fr>
parents: 267
diff changeset
360 *
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
361 * @return the string
268
David Demelier <markand@malikania.fr>
parents: 267
diff changeset
362 */
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
363 std::string buffer() const;
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
364 };
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
365
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
366 template <>
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
367 struct Pack::TypeInfo<uint8_t> : public Pack::Convertible {
295
345aaeb5e0ba Pack: fix constexpr can't be used on void return types
David Demelier <markand@malikania.fr>
parents: 290
diff changeset
368 static inline void convert(uint8_t &) noexcept
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
369 {
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
370 // uint8_t are endian independent
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
371 }
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
372 };
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
373
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
374 template <>
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
375 struct Pack::TypeInfo<uint16_t> : public Pack::Convertible {
295
345aaeb5e0ba Pack: fix constexpr can't be used on void return types
David Demelier <markand@malikania.fr>
parents: 290
diff changeset
376 static inline void convert(uint16_t &v)
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
377 {
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
378 v = (((v >> 8) & 0x00FFL) | ((v << 8) & 0xFF00L));
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
379 }
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
380 };
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
381
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
382 template <>
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
383 struct Pack::TypeInfo<uint32_t> : public Pack::Convertible {
295
345aaeb5e0ba Pack: fix constexpr can't be used on void return types
David Demelier <markand@malikania.fr>
parents: 290
diff changeset
384 static inline void convert(uint32_t &v)
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
385 {
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
386 v = ((((v) >> 24) & 0x000000FFL)
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
387 | (((v) >> 8) & 0x0000FF00L)
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
388 | (((v) << 8) & 0x00FF0000L)
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
389 | (((v) << 24) & 0xFF000000L));
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
390 }
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
391 };
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
392
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
393 template <>
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
394 struct Pack::TypeInfo<uint64_t> : public Pack::Convertible {
295
345aaeb5e0ba Pack: fix constexpr can't be used on void return types
David Demelier <markand@malikania.fr>
parents: 290
diff changeset
395 static inline void convert(uint64_t &v)
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
396 {
290
David Demelier <markand@malikania.fr>
parents: 268
diff changeset
397 v = ((((v) & 0xff00000000000000ull) >> 56)
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
398 | (((v) & 0x00ff000000000000ull) >> 40)
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
399 | (((v) & 0x0000ff0000000000ull) >> 24)
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
400 | (((v) & 0x000000ff00000000ull) >> 8 )
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
401 | (((v) & 0x00000000ff000000ull) << 8 )
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
402 | (((v) & 0x0000000000ff0000ull) << 24)
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
403 | (((v) & 0x000000000000ff00ull) << 40)
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
404 | (((v) & 0x00000000000000ffull) << 56));
266
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
405 }
David Demelier <markand@malikania.fr>
parents: 223
diff changeset
406 };
185
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
407
523156bb3af5 Add Pack class
David Demelier <markand@malikania.fr>
parents:
diff changeset
408 #endif // !_PACK_H_