00001 // Filename: datagram.cxx 00002 // Created by: drose (06Jun00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 00016 #include "datagram.h" 00017 00018 #include "pnotify.h" 00019 00020 // for sprintf(). 00021 #include <stdio.h> 00022 00023 TypeHandle Datagram::_type_handle; 00024 00025 //////////////////////////////////////////////////////////////////// 00026 // Function: Datagram::Destructor 00027 // Access: Public, Virtual 00028 // Description: 00029 //////////////////////////////////////////////////////////////////// 00030 Datagram:: 00031 ~Datagram() { 00032 } 00033 00034 //////////////////////////////////////////////////////////////////// 00035 // Function: Datagram::clear 00036 // Access: Public, Virtual 00037 // Description: Resets the datagram to empty, in preparation for 00038 // building up a new datagram. 00039 //////////////////////////////////////////////////////////////////// 00040 void Datagram:: 00041 clear() { 00042 _data.clear(); 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: Datagram::dump_hex 00047 // Access: Public 00048 // Description: Writes a representation of the entire datagram 00049 // contents, as a sequence of hex (and ASCII) values. 00050 //////////////////////////////////////////////////////////////////// 00051 void Datagram:: 00052 dump_hex(ostream &out, unsigned int indent) const { 00053 const char *message = (const char *)get_data(); 00054 size_t num_bytes = get_length(); 00055 for (size_t line = 0; line < num_bytes; line += 16) { 00056 char hex[12]; 00057 sprintf(hex, "%04x ", ((unsigned int )line)); 00058 for (unsigned int ind = 0; ind < indent; ind++) { 00059 out << " "; 00060 } 00061 out << hex; 00062 00063 size_t p; 00064 for (p = line; p < line + 16; p++) { 00065 if (p < num_bytes) { 00066 char hex[12]; 00067 sprintf(hex, " %02x", ((unsigned int)message[p]) & 0xff); 00068 out << hex; 00069 } else { 00070 out << " "; 00071 } 00072 } 00073 out << " "; 00074 for (p = line; p < line + 16 && p < num_bytes; p++) { 00075 // must cast to (unsigned char) to avoid conversion to large negative integers outside of 0xFF range 00076 if (isgraph((unsigned char)message[p]) || message[p] == ' ') { 00077 out << (char)message[p]; 00078 } else { 00079 out << "."; 00080 } 00081 } 00082 out << "\n"; 00083 } 00084 } 00085 00086 //////////////////////////////////////////////////////////////////// 00087 // Function: Datagram::add_wstring 00088 // Access: Public 00089 // Description: Adds a variable-length wstring to the datagram. 00090 //////////////////////////////////////////////////////////////////// 00091 void Datagram:: 00092 add_wstring(const wstring &str) { 00093 // By convention, wstrings are marked with 32-bit lengths. 00094 add_uint32(str.length()); 00095 00096 // Now append each character in the string. We store each code 00097 // little-endian, for no real good reason. 00098 wstring::const_iterator ci; 00099 for (ci = str.begin(); ci != str.end(); ++ci) { 00100 add_uint16(*ci); 00101 } 00102 } 00103 00104 //////////////////////////////////////////////////////////////////// 00105 // Function: Datagram::pad_bytes 00106 // Access: Public 00107 // Description: Adds the indicated number of zero bytes to the 00108 // datagram. 00109 //////////////////////////////////////////////////////////////////// 00110 void Datagram:: 00111 pad_bytes(size_t size) { 00112 nassertv((int)size >= 0); 00113 00114 if (_data == (uchar *)NULL) { 00115 // Create a new array. 00116 _data = PTA_uchar::empty_array(0); 00117 00118 } else if (_data.get_ref_count() != 1) { 00119 // Copy on write. 00120 PTA_uchar new_data = PTA_uchar::empty_array(0); 00121 new_data.v() = _data.v(); 00122 _data = new_data; 00123 } 00124 00125 // Now append the data. 00126 00127 // It is very important that we *don't* do this reserve() operation. 00128 // See the further comments in append_data(), below. 00129 // _data.reserve(_data.size() + size); 00130 00131 while (size > 0) { 00132 _data.push_back('\0'); 00133 --size; 00134 } 00135 } 00136 00137 //////////////////////////////////////////////////////////////////// 00138 // Function: Datagram::append_data 00139 // Access: Public 00140 // Description: Appends some more raw data to the end of the 00141 // datagram. 00142 //////////////////////////////////////////////////////////////////// 00143 void Datagram:: 00144 append_data(const void *data, size_t size) { 00145 nassertv((int)size >= 0); 00146 00147 if (_data == (uchar *)NULL) { 00148 // Create a new array. 00149 _data = PTA_uchar::empty_array(0); 00150 00151 } else if (_data.get_ref_count() != 1) { 00152 // Copy on write. 00153 PTA_uchar new_data = PTA_uchar::empty_array(0); 00154 new_data.v() = _data.v(); 00155 _data = new_data; 00156 } 00157 00158 // Now append the data. 00159 00160 // It is very important that we *don't* do this reserve() operation. 00161 // This actually slows it down on Windows, which takes the reserve() 00162 // request as a fixed size the array should be set to (!) instead of 00163 // as a minimum size to guarantee. This forces the array to 00164 // reallocate itself with *every* call to append_data! 00165 // _data.reserve(_data.size() + size); 00166 00167 _data.v().insert(_data.v().end(), (const unsigned char *)data, 00168 (const unsigned char *)data + size); 00169 } 00170 00171 //////////////////////////////////////////////////////////////////// 00172 // Function: Datagram::assign 00173 // Access: Public 00174 // Description: Replaces the datagram's data with the indicated 00175 // block. 00176 //////////////////////////////////////////////////////////////////// 00177 void Datagram:: 00178 assign(const void *data, size_t size) { 00179 nassertv((int)size >= 0); 00180 00181 _data = PTA_uchar::empty_array(0); 00182 _data.v().insert(_data.v().end(), (const unsigned char *)data, 00183 (const unsigned char *)data + size); 00184 } 00185 00186 //////////////////////////////////////////////////////////////////// 00187 // Function : Datagram::output 00188 // Access : Public 00189 // Description : Write a string representation of this instance to 00190 // <out>. 00191 //////////////////////////////////////////////////////////////////// 00192 void Datagram:: 00193 output(ostream &out) const { 00194 #ifndef NDEBUG //[ 00195 out<<""<<"Datagram"; 00196 #endif //] NDEBUG 00197 } 00198 00199 //////////////////////////////////////////////////////////////////// 00200 // Function : Datagram::write 00201 // Access : Public 00202 // Description : Write a string representation of this instance to 00203 // <out>. 00204 //////////////////////////////////////////////////////////////////// 00205 void Datagram:: 00206 write(ostream &out, unsigned int indent) const { 00207 #ifndef NDEBUG //[ 00208 out.width(indent); 00209 out<<""<<"Datagram:\n"; 00210 dump_hex(out, indent); 00211 #endif //] NDEBUG 00212 }