Panda3D
|
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 }