Panda3D
datagram.I
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file datagram.I
10  * @author drose
11  * @date 2000-06-06
12  */
13 
14 /**
15  * Constructs a datagram from an existing block of data.
16  */
17 INLINE Datagram::
18 Datagram(const void *data, size_t size) {
19  append_data(data, size);
20 }
21 
22 /**
23  * Constructs a datagram from an existing block of data.
24  */
25 INLINE Datagram::
26 Datagram(vector_uchar data) :
27  _data(std::move(data)) {
28 }
29 
30 /**
31  * Adds a boolean value to the datagram.
32  */
33 INLINE void Datagram::
34 add_bool(bool b) {
35  add_uint8(b);
36 }
37 
38 /**
39  * Adds a signed 8-bit integer to the datagram.
40  */
41 INLINE void Datagram::
42 add_int8(int8_t value) {
43  append_data(&value, 1);
44 }
45 
46 /**
47  * Adds an unsigned 8-bit integer to the datagram.
48  */
49 INLINE void Datagram::
50 add_uint8(uint8_t value) {
51  append_data(&value, 1);
52 }
53 
54 /**
55  * Adds a signed 16-bit integer to the datagram.
56  */
57 INLINE void Datagram::
58 add_int16(int16_t value) {
59  LittleEndian s(&value, sizeof(value));
60  append_data(s.get_data(), sizeof(value));
61 }
62 
63 /**
64  * Adds a signed 32-bit integer to the datagram.
65  */
66 INLINE void Datagram::
67 add_int32(int32_t value) {
68  LittleEndian s(&value, sizeof(value));
69  append_data(s.get_data(), sizeof(value));
70 }
71 
72 /**
73  * Adds a signed 64-bit integer to the datagram.
74  */
75 INLINE void Datagram::
76 add_int64(int64_t value) {
77  LittleEndian s(&value, sizeof(value));
78  append_data(s.get_data(), sizeof(value));
79 }
80 
81 /**
82  * Adds an unsigned 16-bit integer to the datagram.
83  */
84 INLINE void Datagram::
85 add_uint16(uint16_t value) {
86  LittleEndian s(&value, sizeof(value));
87  append_data(s.get_data(), sizeof(value));
88 }
89 
90 /**
91  * Adds an unsigned 32-bit integer to the datagram.
92  */
93 INLINE void Datagram::
94 add_uint32(uint32_t value) {
95  LittleEndian s(&value, sizeof(value));
96  append_data(s.get_data(), sizeof(value));
97 }
98 
99 /**
100  * Adds an unsigned 64-bit integer to the datagram.
101  */
102 INLINE void Datagram::
103 add_uint64(uint64_t value) {
104  LittleEndian s(&value, sizeof(value));
105  append_data(s.get_data(), sizeof(value));
106 }
107 
108 /**
109  * Adds a 32-bit single-precision floating-point number to the datagram.
110  * Since this kind of float is not necessarily portable across different
111  * architectures, special care is required.
112  */
113 INLINE void Datagram::
114 add_float32(PN_float32 value) {
115  LittleEndian s(&value, sizeof(value));
116  append_data(s.get_data(), sizeof(value));
117 }
118 
119 /**
120  * Adds a 64-bit floating-point number to the datagram.
121  */
122 INLINE void Datagram::
123 add_float64(PN_float64 value) {
124  LittleEndian s(&value, sizeof(value));
125  append_data(s.get_data(), sizeof(value));
126 }
127 
128 /**
129  * Adds either a 32-bit or a 64-bit floating-point number, according to
130  * set_stdfloat_double().
131  */
132 INLINE void Datagram::
133 add_stdfloat(PN_stdfloat value) {
134  if (_stdfloat_double) {
135  add_float64((double)value);
136  } else {
137  add_float32((float)value);
138  }
139 }
140 
141 /**
142  * Adds a signed 16-bit big-endian integer to the datagram.
143  */
144 INLINE void Datagram::
145 add_be_int16(int16_t value) {
146  BigEndian s(&value, sizeof(value));
147  append_data(s.get_data(), sizeof(value));
148 }
149 
150 /**
151  * Adds a signed 32-bit big-endian integer to the datagram.
152  */
153 INLINE void Datagram::
154 add_be_int32(int32_t value) {
155  BigEndian s(&value, sizeof(value));
156  append_data(s.get_data(), sizeof(value));
157 }
158 
159 /**
160  * Adds a signed 64-bit big-endian integer to the datagram.
161  */
162 INLINE void Datagram::
163 add_be_int64(int64_t value) {
164  BigEndian s(&value, sizeof(value));
165  append_data(s.get_data(), sizeof(value));
166 }
167 
168 /**
169  * Adds an unsigned 16-bit big-endian integer to the datagram.
170  */
171 INLINE void Datagram::
172 add_be_uint16(uint16_t value) {
173  BigEndian s(&value, sizeof(value));
174  append_data(s.get_data(), sizeof(value));
175 }
176 
177 /**
178  * Adds an unsigned 32-bit big-endian integer to the datagram.
179  */
180 INLINE void Datagram::
181 add_be_uint32(uint32_t value) {
182  BigEndian s(&value, sizeof(value));
183  append_data(s.get_data(), sizeof(value));
184 }
185 
186 /**
187  * Adds an unsigned 64-bit big-endian integer to the datagram.
188  */
189 INLINE void Datagram::
190 add_be_uint64(uint64_t value) {
191  BigEndian s(&value, sizeof(value));
192  append_data(s.get_data(), sizeof(value));
193 }
194 
195 /**
196  * Adds a 32-bit single-precision big-endian floating-point number to the
197  * datagram.
198  */
199 INLINE void Datagram::
200 add_be_float32(PN_float32 value) {
201  BigEndian s(&value, sizeof(value));
202  append_data(s.get_data(), sizeof(value));
203 }
204 
205 /**
206  * Adds a 64-bit big-endian floating-point number to the datagram.
207  */
208 INLINE void Datagram::
209 add_be_float64(PN_float64 value) {
210  BigEndian s(&value, sizeof(value));
211  append_data(s.get_data(), sizeof(value));
212 }
213 
214 /**
215  * Adds a variable-length string to the datagram. This actually adds a count
216  * followed by n bytes.
217  */
218 INLINE void Datagram::
219 add_string(const std::string &str) {
220  // The max sendable length for a string is 2^16.
221  nassertv(str.length() <= (uint16_t)0xffff);
222 
223  // Strings always are preceded by their length
224  add_uint16((uint16_t)str.length());
225 
226  // Add the string
227  append_data(str.data(), str.length());
228 }
229 
230 /**
231  * Adds a variable-length string to the datagram, using a 32-bit length field
232  * to allow very long strings.
233  */
234 INLINE void Datagram::
235 add_string32(const std::string &str) {
236  // Strings always are preceded by their length
237  add_uint32((uint32_t)str.length());
238 
239  // Add the string
240  append_data(str.data(), str.length());
241 }
242 
243 /**
244  * Adds a variable-length string to the datagram, as a NULL-terminated string.
245  */
246 INLINE void Datagram::
247 add_z_string(const std::string &str) {
248  // We must not have any nested null characters in the string.
249  size_t null_pos = str.find('\0');
250  // Add the string (sans the null character).
251  append_data(str.data(), std::min<size_t>(null_pos, str.length()));
252 
253  // And the null character.
254  add_uint8('\0');
255 }
256 
257 /**
258  * Adds a fixed-length string to the datagram. If the string given is less
259  * than the requested size, this will pad the string out with zeroes; if it is
260  * greater than the requested size, this will silently truncate the string.
261  */
262 INLINE void Datagram::
263 add_fixed_string(const std::string &str, size_t size) {
264  if (str.length() < size) {
265  append_data(str.data(), str.length());
266  pad_bytes(size - str.length());
267 
268  } else { // str.length() >= size
269  append_data(str.data(), size);
270  }
271 }
272 
273 /**
274  * Adds a variable-length binary blob to the datagram. This actually adds a
275  * count followed by n bytes.
276  */
277 INLINE void Datagram::
278 add_blob(const vector_uchar &data) {
279  // The max sendable size for a blob is 2^16.
280  nassertv(data.size() <= (uint16_t)0xffff);
281 
282  // Blobs always are preceded by their size
283  add_uint16((uint16_t)data.size());
284 
285  // Add the blob
286  append_data(data.data(), data.size());
287 }
288 
289 /**
290  * Adds a variable-length binary blob to the datagram, using a 32-bit length
291  * field to allow very long blobs.
292  */
293 INLINE void Datagram::
294 add_blob32(const vector_uchar &data) {
295  // Blobs always are preceded by their size
296  add_uint32((uint32_t)data.size());
297 
298  // Add the blob
299  append_data(data.data(), data.size());
300 }
301 
302 /**
303  * Appends some more raw data to the end of the datagram.
304  */
305 INLINE void Datagram::
306 append_data(const vector_uchar &data) {
307  append_data(data.data(), data.size());
308 }
309 
310 /**
311  * Returns the datagram's data as a string.
312  */
313 INLINE std::string Datagram::
314 get_message() const {
315  // Silly special case for gcc 3.2, which can't tolerate string(NULL, 0).
316  if (_data.size() == 0) {
317  return std::string();
318  } else {
319  return std::string((const char *)_data.p(), _data.size());
320  }
321 }
322 
323 /**
324  * Returns a pointer to the beginning of the datagram's data.
325  */
326 INLINE const void *Datagram::
327 get_data() const {
328  return _data.p();
329 }
330 
331 /**
332  * Returns the number of bytes in the datagram.
333  */
334 INLINE size_t Datagram::
335 get_length() const {
336  return _data.size();
337 }
338 
339 /**
340  * Replaces the data in the Datagram with the data in the indicated PTA_uchar.
341  * This is assignment by reference: subsequent changes to the Datagram will
342  * also change the source PTA_uchar.
343  */
344 INLINE void Datagram::
345 set_array(PTA_uchar data) {
346  _data = data;
347 }
348 
349 /**
350  * Replaces the data in the Datagram with a copy of the data in the indicated
351  * CPTA_uchar. Unlike set_array(), a complete copy is made of the data;
352  * subsequent changes to the Datagram will *not* change the source CPTA_uchar.
353  */
354 INLINE void Datagram::
356  _data.clear();
357  _data.v() = data.v();
358 }
359 
360 /**
361  * Returns a const pointer to the actual data in the Datagram.
362  */
363 INLINE CPTA_uchar Datagram::
364 get_array() const {
365  return _data;
366 }
367 
368 /**
369  * Returns a modifiable pointer to the actual data in the Datagram.
370  */
371 INLINE PTA_uchar Datagram::
373  if (_data == nullptr) {
374  // Create a new array.
375  _data = PTA_uchar::empty_array(0);
376 
377  } else if (_data.get_ref_count() != 1) {
378  // Copy on write.
379  PTA_uchar new_data = PTA_uchar::empty_array(0);
380  new_data.v() = _data.v();
381  _data = new_data;
382  }
383 
384  return _data;
385 }
386 
387 /**
388  * Changes the stdfloat_double flag, which defines the operation performed by
389  * add_stdfloat() and DatagramIterator::get_stdfloat(). When this is true,
390  * add_stdfloat() adds a 64-bit floating-point number; when it is false, it
391  * adds a 32-bit floating-point number. The default is based on the
392  * STDFLOAT_DOUBLE compilation flag.
393  */
394 INLINE void Datagram::
395 set_stdfloat_double(bool stdfloat_double) {
396  _stdfloat_double = stdfloat_double;
397 }
398 
399 /**
400  * Returns the stdfloat_double flag. See set_stdfloat_double().
401  */
402 INLINE bool Datagram::
404  return _stdfloat_double;
405 }
406 
407 /**
408  *
409  */
410 INLINE bool Datagram::
411 operator == (const Datagram &other) const {
412  if (_data == other._data) {
413  return true;
414  }
415  if (_data != nullptr && other._data != nullptr) {
416  return _data.v() == other._data.v();
417  }
418  return false;
419 }
420 
421 /**
422  *
423  */
424 INLINE bool Datagram::
425 operator != (const Datagram &other) const {
426  return !operator == (other);
427 }
428 
429 /**
430  *
431  */
432 INLINE bool Datagram::
433 operator < (const Datagram &other) const {
434  if (_data == other._data) {
435  // Same pointers.
436  return false;
437  }
438 
439  if (_data != nullptr && other._data != nullptr) {
440  // Different pointers, neither NULL.
441  return _data.v() < other._data.v();
442  }
443 
444  // One of the pointers is NULL, but not the other one.
445  return _data.size() < other._data.size();
446 }
447 
448 INLINE void
449 generic_write_datagram(Datagram &dest, bool value) {
450  dest.add_bool(value);
451 }
452 
453 INLINE void
454 generic_write_datagram(Datagram &dest, int value) {
455  dest.add_int32(value);
456 }
457 
458 INLINE void
459 generic_write_datagram(Datagram &dest, float value) {
460  dest.add_float32(value);
461 }
462 
463 INLINE void
464 generic_write_datagram(Datagram &dest, double value) {
465  dest.add_float64(value);
466 }
467 
468 INLINE void
469 generic_write_datagram(Datagram &dest, const std::string &value) {
470  dest.add_string(value);
471 }
472 
473 INLINE void
474 generic_write_datagram(Datagram &dest, const std::wstring &value) {
475  dest.add_wstring(value);
476 }
477 
478 INLINE void
479 generic_write_datagram(Datagram &dest, const vector_uchar &value) {
480  dest.add_blob(value);
481 }
void add_int16(int16_t value)
Adds a signed 16-bit integer to the datagram.
Definition: datagram.I:58
CPTA_uchar get_array() const
Returns a const pointer to the actual data in the Datagram.
Definition: datagram.I:364
void add_float64(PN_float64 value)
Adds a 64-bit floating-point number to the datagram.
Definition: datagram.I:123
void append_data(const void *data, size_t size)
Appends some more raw data to the end of the datagram.
Definition: datagram.cxx:129
void add_z_string(const std::string &str)
Adds a variable-length string to the datagram, as a NULL-terminated string.
Definition: datagram.I:247
void add_float32(PN_float32 value)
Adds a 32-bit single-precision floating-point number to the datagram.
Definition: datagram.I:114
bool get_stdfloat_double() const
Returns the stdfloat_double flag.
Definition: datagram.I:403
void add_wstring(const std::wstring &str)
Adds a variable-length wstring to the datagram.
Definition: datagram.cxx:83
PTA_uchar modify_array()
Returns a modifiable pointer to the actual data in the Datagram.
Definition: datagram.I:372
void set_array(PTA_uchar data)
Replaces the data in the Datagram with the data in the indicated PTA_uchar.
Definition: datagram.I:345
void add_int64(int64_t value)
Adds a signed 64-bit integer to the datagram.
Definition: datagram.I:76
void add_be_int64(int64_t value)
Adds a signed 64-bit big-endian integer to the datagram.
Definition: datagram.I:163
void add_string32(const std::string &str)
Adds a variable-length string to the datagram, using a 32-bit length field to allow very long strings...
Definition: datagram.I:235
void pad_bytes(size_t size)
Adds the indicated number of zero bytes to the datagram.
Definition: datagram.cxx:99
void add_uint32(uint32_t value)
Adds an unsigned 32-bit integer to the datagram.
Definition: datagram.I:94
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
Definition: datagram.I:133
void set_stdfloat_double(bool stdfloat_double)
Changes the stdfloat_double flag, which defines the operation performed by add_stdfloat() and Datagra...
Definition: datagram.I:395
void add_be_float64(PN_float64 value)
Adds a 64-bit big-endian floating-point number to the datagram.
Definition: datagram.I:209
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
void add_int8(int8_t value)
Adds a signed 8-bit integer to the datagram.
Definition: datagram.I:42
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:34
void add_be_float32(PN_float32 value)
Adds a 32-bit single-precision big-endian floating-point number to the datagram.
Definition: datagram.I:200
void add_be_uint16(uint16_t value)
Adds an unsigned 16-bit big-endian integer to the datagram.
Definition: datagram.I:172
const void * get_data() const
Returns the pointer to the first byte of the data, either reversed or nonreversed,...
void add_blob(const vector_uchar &)
Adds a variable-length binary blob to the datagram.
Definition: datagram.I:278
NativeNumericData and ReversedNumericData work together to provide a sneaky interface for automatical...
void add_be_int16(int16_t value)
Adds a signed 16-bit big-endian integer to the datagram.
Definition: datagram.I:145
void add_string(const std::string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:219
void add_be_uint32(uint32_t value)
Adds an unsigned 32-bit big-endian integer to the datagram.
Definition: datagram.I:181
NativeNumericData and ReversedNumericData work together to provide a sneaky interface for automatical...
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
Definition: datagram.I:67
void add_be_uint64(uint64_t value)
Adds an unsigned 64-bit big-endian integer to the datagram.
Definition: datagram.I:190
void copy_array(CPTA_uchar data)
Replaces the data in the Datagram with a copy of the data in the indicated CPTA_uchar.
Definition: datagram.I:355
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
Definition: datagram.I:50
std::string get_message() const
Returns the datagram's data as a string.
Definition: datagram.I:314
void add_fixed_string(const std::string &str, size_t size)
Adds a fixed-length string to the datagram.
Definition: datagram.I:263
void add_be_int32(int32_t value)
Adds a signed 32-bit big-endian integer to the datagram.
Definition: datagram.I:154
void add_uint64(uint64_t value)
Adds an unsigned 64-bit integer to the datagram.
Definition: datagram.I:103
const void * get_data() const
Returns the pointer to the first byte of the data, either reversed or nonreversed,...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:335
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.
Definition: datagram.I:327
void add_blob32(const vector_uchar &)
Adds a variable-length binary blob to the datagram, using a 32-bit length field to allow very long bl...
Definition: datagram.I:294