Panda3D
datagram.cxx
1 // Filename: datagram.cxx
2 // Created by: drose (06Jun00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 
16 #include "datagram.h"
17 
18 #include "pnotify.h"
19 
20 // for sprintf().
21 #include <stdio.h>
22 
23 TypeHandle Datagram::_type_handle;
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: Datagram::Destructor
27 // Access: Public, Virtual
28 // Description:
29 ////////////////////////////////////////////////////////////////////
30 Datagram::
31 ~Datagram() {
32 }
33 
34 ////////////////////////////////////////////////////////////////////
35 // Function: Datagram::clear
36 // Access: Public, Virtual
37 // Description: Resets the datagram to empty, in preparation for
38 // building up a new datagram.
39 ////////////////////////////////////////////////////////////////////
40 void Datagram::
41 clear() {
42  _data.clear();
43 }
44 
45 ////////////////////////////////////////////////////////////////////
46 // Function: Datagram::dump_hex
47 // Access: Public
48 // Description: Writes a representation of the entire datagram
49 // contents, as a sequence of hex (and ASCII) values.
50 ////////////////////////////////////////////////////////////////////
51 void Datagram::
52 dump_hex(ostream &out, unsigned int indent) const {
53  const char *message = (const char *)get_data();
54  size_t num_bytes = get_length();
55  for (size_t line = 0; line < num_bytes; line += 16) {
56  char hex[12];
57  sprintf(hex, "%04x ", ((unsigned int )line));
58  for (unsigned int ind = 0; ind < indent; ind++) {
59  out << " ";
60  }
61  out << hex;
62 
63  size_t p;
64  for (p = line; p < line + 16; p++) {
65  if (p < num_bytes) {
66  char hex[12];
67  sprintf(hex, " %02x", ((unsigned int)message[p]) & 0xff);
68  out << hex;
69  } else {
70  out << " ";
71  }
72  }
73  out << " ";
74  for (p = line; p < line + 16 && p < num_bytes; p++) {
75  // must cast to (unsigned char) to avoid conversion to large negative integers outside of 0xFF range
76  if (isgraph((unsigned char)message[p]) || message[p] == ' ') {
77  out << (char)message[p];
78  } else {
79  out << ".";
80  }
81  }
82  out << "\n";
83  }
84 }
85 
86 ////////////////////////////////////////////////////////////////////
87 // Function: Datagram::add_wstring
88 // Access: Public
89 // Description: Adds a variable-length wstring to the datagram.
90 ////////////////////////////////////////////////////////////////////
91 void Datagram::
92 add_wstring(const wstring &str) {
93  // By convention, wstrings are marked with 32-bit lengths.
94  add_uint32(str.length());
95 
96  // Now append each character in the string. We store each code
97  // little-endian, for no real good reason.
98  wstring::const_iterator ci;
99  for (ci = str.begin(); ci != str.end(); ++ci) {
100  add_uint16(*ci);
101  }
102 }
103 
104 ////////////////////////////////////////////////////////////////////
105 // Function: Datagram::pad_bytes
106 // Access: Public
107 // Description: Adds the indicated number of zero bytes to the
108 // datagram.
109 ////////////////////////////////////////////////////////////////////
110 void Datagram::
111 pad_bytes(size_t size) {
112  nassertv((int)size >= 0);
113 
114  if (_data == (uchar *)NULL) {
115  // Create a new array.
116  _data = PTA_uchar::empty_array(0);
117 
118  } else if (_data.get_ref_count() != 1) {
119  // Copy on write.
120  PTA_uchar new_data = PTA_uchar::empty_array(0);
121  new_data.v() = _data.v();
122  _data = new_data;
123  }
124 
125  // Now append the data.
126 
127  // It is very important that we *don't* do this reserve() operation.
128  // See the further comments in append_data(), below.
129  // _data.reserve(_data.size() + size);
130 
131  while (size > 0) {
132  _data.push_back('\0');
133  --size;
134  }
135 }
136 
137 ////////////////////////////////////////////////////////////////////
138 // Function: Datagram::append_data
139 // Access: Public
140 // Description: Appends some more raw data to the end of the
141 // datagram.
142 ////////////////////////////////////////////////////////////////////
143 void Datagram::
144 append_data(const void *data, size_t size) {
145  nassertv((int)size >= 0);
146 
147  if (_data == (uchar *)NULL) {
148  // Create a new array.
149  _data = PTA_uchar::empty_array(0);
150 
151  } else if (_data.get_ref_count() != 1) {
152  // Copy on write.
153  PTA_uchar new_data = PTA_uchar::empty_array(0);
154  new_data.v() = _data.v();
155  _data = new_data;
156  }
157 
158  // Now append the data.
159 
160  // It is very important that we *don't* do this reserve() operation.
161  // This actually slows it down on Windows, which takes the reserve()
162  // request as a fixed size the array should be set to (!) instead of
163  // as a minimum size to guarantee. This forces the array to
164  // reallocate itself with *every* call to append_data!
165  // _data.reserve(_data.size() + size);
166 
167  _data.v().insert(_data.v().end(), (const unsigned char *)data,
168  (const unsigned char *)data + size);
169 }
170 
171 ////////////////////////////////////////////////////////////////////
172 // Function: Datagram::assign
173 // Access: Public
174 // Description: Replaces the datagram's data with the indicated
175 // block.
176 ////////////////////////////////////////////////////////////////////
177 void Datagram::
178 assign(const void *data, size_t size) {
179  nassertv((int)size >= 0);
180 
181  _data = PTA_uchar::empty_array(0);
182  _data.v().insert(_data.v().end(), (const unsigned char *)data,
183  (const unsigned char *)data + size);
184 }
185 
186 ////////////////////////////////////////////////////////////////////
187 // Function : Datagram::output
188 // Access : Public
189 // Description : Write a string representation of this instance to
190 // <out>.
191 ////////////////////////////////////////////////////////////////////
192 void Datagram::
193 output(ostream &out) const {
194  #ifndef NDEBUG //[
195  out<<""<<"Datagram";
196  #endif //] NDEBUG
197 }
198 
199 ////////////////////////////////////////////////////////////////////
200 // Function : Datagram::write
201 // Access : Public
202 // Description : Write a string representation of this instance to
203 // <out>.
204 ////////////////////////////////////////////////////////////////////
205 void Datagram::
206 write(ostream &out, unsigned int indent) const {
207  #ifndef NDEBUG //[
208  out.width(indent);
209  out<<""<<"Datagram:\n";
210  dump_hex(out, indent);
211  #endif //] NDEBUG
212 }
void append_data(const void *data, size_t size)
Appends some more raw data to the end of the datagram.
Definition: datagram.cxx:144
void add_wstring(const wstring &str)
Adds a variable-length wstring to the datagram.
Definition: datagram.cxx:92
void dump_hex(ostream &out, unsigned int indent=0) const
Writes a representation of the entire datagram contents, as a sequence of hex (and ASCII) values...
Definition: datagram.cxx:52
virtual void clear()
Resets the datagram to empty, in preparation for building up a new datagram.
Definition: datagram.cxx:41
void assign(const void *data, size_t size)
Replaces the datagram&#39;s data with the indicated block.
Definition: datagram.cxx:178
void output(ostream &out) const
Write a string representation of this instance to <out>.
Definition: datagram.cxx:193
void pad_bytes(size_t size)
Adds the indicated number of zero bytes to the datagram.
Definition: datagram.cxx:111
void write(ostream &out, unsigned int indent=0) const
Write a string representation of this instance to <out>.
Definition: datagram.cxx:206
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:181
void add_uint32(PN_uint32 value)
Adds an unsigned 32-bit integer to the datagram.
Definition: datagram.I:192
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:457
const void * get_data() const
Returns a pointer to the beginning of the datagram&#39;s data.
Definition: datagram.I:447