constructors should be explicit
[chaz/yoink] / src / Moof / Packet.hh
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 /**
13 * \file Packet.hh
14 * Classes for building and interpreting datagram packets.
15 */
16
17 #ifndef _MOOF_PACKET_HH_
18 #define _MOOF_PACKET_HH_
19
20 #include <cstring>
21 #include <stdexcept>
22 #include <string>
23 #include <vector>
24
25
26 #ifndef PAGE_SIZE
27 #define PAGE_SIZE 4096
28 #endif
29
30
31 namespace Mf {
32
33
34 /**
35 * Represents a packet of serialized variables ready for transfer over the
36 * network. This method is most suitable for representing datagram
37 * packets, but it may also be useful for seralizing data for persistent
38 * state storage. The semantics are similar to that of a FIFO queue or
39 * stream where packets are written and read by inserting and extracting
40 * variables to and from the packet, although the actual order of the
41 * variables in the buffer may be different. At any time, a pointer to a
42 * buffer and the size of the buffer can be retrieved. This class also
43 * handles endian differences by serializing variables in network byte
44 * order (big endian).
45 */
46 class Packet
47 {
48 public:
49
50 /**
51 * Construct a packet with an initial capacity.
52 * \param capacity Initial capacity of the packet.
53 */
54 explicit Packet(size_t size = PAGE_SIZE);
55
56 /**
57 * Construct a packet with some bytes from a buffer. The bytes will be
58 * copied into the packet, so you don't need to keep the original
59 * buffer.
60 * \param data The bytes.
61 * \param size The number of bytes.
62 */
63 Packet(const char* data, size_t size);
64
65 /**
66 * Insert a variable into the packet, serializing it. This usually
67 * increases the size of the packet by the size of the data type.
68 * \param value The value to insert.
69 * \return This.
70 */
71 Packet& operator<<(bool value);
72 Packet& operator<<(int8_t value);
73 Packet& operator<<(int16_t value);
74 Packet& operator<<(int32_t value);
75 Packet& operator<<(int64_t value);
76 Packet& operator<<(uint8_t value);
77 Packet& operator<<(uint16_t value);
78 Packet& operator<<(uint32_t value);
79 Packet& operator<<(uint64_t value);
80 Packet& operator<<(float value);
81 Packet& operator<<(double value);
82
83 /**
84 * Write some bytes to the packet.
85 * \param bytes The bytes.
86 * \param size The number of bytes.
87 * return The number of bytes actually written.
88 */
89 size_t write(const void* bytes, size_t size);
90
91
92 /**
93 * Extract a variable from the packet. This usually decreases the size
94 * of the packet by the size of the data type.
95 * \param value Reference to the variable to extract.
96 * \return This.
97 */
98 Packet& operator>>(bool& value);
99 Packet& operator>>(int8_t& value);
100 Packet& operator>>(int16_t& value);
101 Packet& operator>>(int32_t& value);
102 Packet& operator>>(int64_t& value);
103 Packet& operator>>(uint8_t& value);
104 Packet& operator>>(uint16_t& value);
105 Packet& operator>>(uint32_t& value);
106 Packet& operator>>(uint64_t& value);
107 Packet& operator>>(float& value);
108 Packet& operator>>(double& value);
109
110 /**
111 * Read some bytes from the packet.
112 * \param bytes The buffer to hold the bytes read.
113 * \param size The size of the read buffer.
114 * \return The number of bytes actually read.
115 */
116 size_t read(void* bytes, size_t size);
117
118
119 /**
120 * Clear the contents of the packet, setting the size of the packet to
121 * zero.
122 */
123 void clear();
124
125
126 /**
127 * Reset the read/write markers to their initial positions, putting the
128 * packet in the state it was at right after construction.
129 */
130 void reset();
131
132
133 /**
134 * Get a pointer to an internal structure holding the serialized bytes
135 * of the packet.
136 * return The pointer.
137 */
138 const char* bytes() const
139 {
140 return mBuffer + mR;
141 }
142
143 /**
144 * Get the size of the buffer holding the serialized bytes of the
145 * packet.
146 * \return The number of bytes.
147 */
148 size_t size() const
149 {
150 return mW - mR;
151 }
152
153
154 // The rest of this stuff is just to implement correct copy semantics.
155
156 Packet(const Packet& copy);
157 Packet& operator=(const Packet& copy);
158 ~Packet();
159
160
161 private:
162
163 char* mBuffer;
164 size_t mSize;
165
166 size_t mR;
167 size_t mW;
168 size_t mOriginalW;
169
170 size_t mBoolR;
171 size_t mBoolW;
172 size_t mBoolNumR;
173 size_t mBoolNumW;
174 };
175
176
177 inline Packet& operator<<(Packet& packet, const char* value)
178 {
179 uint16_t length = strlen(value);
180 packet << length;
181 if (packet.write(value, length) != length)
182 {
183 throw std::length_error("out of memory");
184 }
185 return packet;
186 }
187
188 template <class T>
189 inline Packet& operator<<(Packet& packet, const std::basic_string<T>& value)
190 {
191 packet << static_cast<uint16_t>(value.length());
192 size_t numBytes = value.length() * sizeof(T);
193 if (packet.write(value.data(), numBytes) != numBytes)
194 {
195 throw std::length_error("out of memory");
196 }
197 return packet;
198 }
199
200 template <class T>
201 inline Packet& operator>>(Packet& packet, std::basic_string<T>& value)
202 {
203 uint16_t length = 0;
204 packet >> length;
205
206 T str[length];
207 size_t numBytes = length * sizeof(T);
208 if (packet.read(str, numBytes) != numBytes)
209 {
210 throw std::out_of_range("end of packet");
211 }
212 value.assign(str, length);
213 return packet;
214 }
215
216
217 template <class T>
218 inline Packet& operator<<(Packet& packet, const std::vector<T>& value)
219 {
220 packet << static_cast<uint16_t>(value.size());
221 typename std::vector<T>::const_iterator it;
222 for (it = value.begin(); it != value.end(); ++it)
223 {
224 packet << *it;
225 }
226 return packet;
227 }
228
229 template <class T>
230 inline Packet& operator>>(Packet& packet, std::vector<T>& value)
231 {
232 uint16_t size = 0;
233 packet >> size;
234
235 value.clear();
236 for (uint16_t i = 0; i < size; ++i)
237 {
238 T item;
239 packet >> item;
240 value.push_back(item);
241 }
242 return packet;
243 }
244
245
246 } // namespace Mf
247
248 #endif // _MOOF_PACKET_HH_
249
This page took 0.039923 seconds and 4 git commands to generate.