Panda3D
 All Classes Functions Variables Enumerations
datagram.cxx
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 }
 All Classes Functions Variables Enumerations