Panda3D

datagramInputFile.cxx

00001 // Filename: datagramInputFile.cxx
00002 // Created by:  drose (30Oct00)
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 #include "datagramInputFile.h"
00016 #include "numeric_types.h"
00017 #include "datagramIterator.h"
00018 #include "profileTimer.h"
00019 #include "config_util.h"
00020 #include "config_express.h"
00021 #include "virtualFileSystem.h"
00022 #include "streamReader.h"
00023 #include "thread.h"
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: DatagramInputFile::open
00027 //       Access: Public
00028 //  Description: Opens the indicated filename for reading.  Returns
00029 //               true on success, false on failure.
00030 ////////////////////////////////////////////////////////////////////
00031 bool DatagramInputFile::
00032 open(Filename filename) {
00033   close();
00034 
00035   // DatagramInputFiles are always binary.
00036   filename.set_binary();
00037 
00038   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00039   _vfile = vfs->get_file(filename);
00040   if (_vfile == (VirtualFile *)NULL) {
00041     // No such file.
00042     return false;
00043   }
00044   _in = _vfile->open_read_file(true);
00045   _owns_in = (_in != (istream *)NULL);
00046   return _owns_in && !_in->fail();
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: DatagramInputFile::open
00051 //       Access: Public
00052 //  Description: Starts reading from the indicated stream.  Returns
00053 //               true on success, false on failure.  The
00054 //               DatagramInputFile does not take ownership of the
00055 //               stream; you are responsible for closing or deleting
00056 //               it when you are done.
00057 ////////////////////////////////////////////////////////////////////
00058 bool DatagramInputFile::
00059 open(istream &in) {
00060   close();
00061 
00062   _in = ∈
00063   _owns_in = false;
00064 
00065   return !_in->fail();
00066 }
00067 
00068 ////////////////////////////////////////////////////////////////////
00069 //     Function: DatagramInputFile::close
00070 //       Access: Public
00071 //  Description: Closes the file.  This is also implicitly done when
00072 //               the DatagramInputFile destructs.
00073 ////////////////////////////////////////////////////////////////////
00074 void DatagramInputFile::
00075 close() {
00076   _vfile.clear();
00077   _in_file.close();
00078   if (_owns_in) {
00079     VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00080     vfs->close_read_file(_in);
00081   }
00082   _in = (istream *)NULL;
00083   _owns_in = false;
00084 
00085   _read_first_datagram = false;
00086   _error = false;
00087 }
00088 
00089 ////////////////////////////////////////////////////////////////////
00090 //     Function: DatagramInputFile::read_header
00091 //       Access: Public
00092 //  Description: Reads a sequence of bytes from the beginning of the
00093 //               datagram file.  This may be called any number of
00094 //               times after the file has been opened and before the
00095 //               first datagram is read.  It may not be called once
00096 //               the first datagram has been read.
00097 ////////////////////////////////////////////////////////////////////
00098 bool DatagramInputFile::
00099 read_header(string &header, size_t num_bytes) {
00100   nassertr(!_read_first_datagram, false);
00101   nassertr(_in != (istream *)NULL, false);
00102 
00103   char *buffer = (char *)alloca(num_bytes);
00104   nassertr(buffer != (char *)NULL, false);
00105 
00106   _in->read(buffer, num_bytes);
00107   if (_in->fail() || _in->eof()) {
00108     return false;
00109   }
00110 
00111   header = string(buffer, num_bytes);
00112   Thread::consider_yield();
00113   return true;
00114 }
00115 
00116 ////////////////////////////////////////////////////////////////////
00117 //     Function: DatagramInputFile::get_datagram
00118 //       Access: Public, Virtual
00119 //  Description: Reads the next datagram from the file.  Returns true
00120 //               on success, false if there is an error or end of
00121 //               file.
00122 ////////////////////////////////////////////////////////////////////
00123 bool DatagramInputFile::
00124 get_datagram(Datagram &data) {
00125   nassertr(_in != (istream *)NULL, false);
00126   _read_first_datagram = true;
00127 
00128   // First, get the size of the upcoming datagram.
00129   StreamReader reader(_in, false);
00130   PN_uint32 num_bytes = reader.get_uint32();
00131   if (_in->fail() || _in->eof()) {
00132     return false;
00133   }
00134 
00135   if (num_bytes == 0) {
00136     // A special case for a zero-length datagram: no need to try to
00137     // read any data.
00138     data.clear();
00139     return true;
00140   }
00141 
00142   // Now, read the datagram itself.
00143 
00144   // If the number of bytes is large, we will need to allocate a
00145   // temporary buffer from the heap.  Otherwise, we can get away with
00146   // allocating it on the stack, via alloca().
00147   if (num_bytes > 65536) {
00148     char *buffer = (char *)PANDA_MALLOC_ARRAY(num_bytes);
00149     nassertr(buffer != (char *)NULL, false);
00150 
00151     _in->read(buffer, num_bytes);
00152     if (_in->fail() || _in->eof()) {
00153       _error = true;
00154       PANDA_FREE_ARRAY(buffer);
00155       return false;
00156     }
00157 
00158     data = Datagram(buffer, num_bytes);
00159     PANDA_FREE_ARRAY(buffer);
00160 
00161   } else {
00162     char *buffer = (char *)alloca(num_bytes);
00163     nassertr(buffer != (char *)NULL, false);
00164 
00165     _in->read(buffer, num_bytes);
00166     if (_in->fail() || _in->eof()) {
00167       _error = true;
00168       return false;
00169     }
00170 
00171     data = Datagram(buffer, num_bytes);
00172   }
00173   Thread::consider_yield();
00174 
00175   return true;
00176 }
00177 
00178 ////////////////////////////////////////////////////////////////////
00179 //     Function: DatagramInputFile::is_eof
00180 //       Access: Public, Virtual
00181 //  Description: Returns true if the file has reached the end-of-file.
00182 //               This test may only be made after a call to
00183 //               read_header() or get_datagram() has failed.
00184 ////////////////////////////////////////////////////////////////////
00185 bool DatagramInputFile::
00186 is_eof() {
00187   return _in != (istream *)NULL ? _in->eof() : true;
00188 }
00189 
00190 ////////////////////////////////////////////////////////////////////
00191 //     Function: DatagramInputFile::is_error
00192 //       Access: Public, Virtual
00193 //  Description: Returns true if the file has reached an error
00194 //               condition.
00195 ////////////////////////////////////////////////////////////////////
00196 bool DatagramInputFile::
00197 is_error() {
00198   if (_in == (istream *)NULL) {
00199     return true;
00200   }
00201 
00202   if (_in->fail()) {
00203     _error = true;
00204   }
00205   return _error;
00206 }
00207 
00208 ////////////////////////////////////////////////////////////////////
00209 //     Function: DatagramInputFile::get_file
00210 //       Access: Public, Virtual
00211 //  Description: Returns the VirtualFile that provides the source for
00212 //               these datagrams, if any, or NULL if the datagrams do
00213 //               not originate from a VirtualFile.
00214 ////////////////////////////////////////////////////////////////////
00215 VirtualFile *DatagramInputFile::
00216 get_file() {
00217   return _vfile;
00218 }
00219 
00220 ////////////////////////////////////////////////////////////////////
00221 //     Function: DatagramInputFile::get_file_pos
00222 //       Access: Public, Virtual
00223 //  Description: Returns the current file position within the data
00224 //               stream, if any, or 0 if the file position is not
00225 //               meaningful or cannot be determined.
00226 //
00227 //               For DatagramInputFiles that return a meaningful file
00228 //               position, this will be pointing to the first byte
00229 //               following the datagram returned after a call to
00230 //               get_datagram().
00231 ////////////////////////////////////////////////////////////////////
00232 streampos DatagramInputFile::
00233 get_file_pos() {
00234   if (_in == (istream *)NULL) {
00235     return 0;
00236   }
00237   return _in->tellg();
00238 }
 All Classes Functions Variables Enumerations