00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "datagramInputFile.h"
00016 #include "temporaryFile.h"
00017 #include "numeric_types.h"
00018 #include "datagramIterator.h"
00019 #include "profileTimer.h"
00020 #include "config_util.h"
00021 #include "config_express.h"
00022 #include "virtualFileSystem.h"
00023 #include "streamReader.h"
00024 #include "thread.h"
00025
00026
00027
00028
00029
00030
00031
00032 bool DatagramInputFile::
00033 open(const FileReference *file) {
00034 close();
00035
00036 _file = file;
00037 _filename = _file->get_filename();
00038
00039
00040 _filename.set_binary();
00041
00042 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00043 _vfile = vfs->get_file(_filename);
00044 if (_vfile == (VirtualFile *)NULL) {
00045
00046 return false;
00047 }
00048 _in = _vfile->open_read_file(true);
00049 _owns_in = (_in != (istream *)NULL);
00050 return _owns_in && !_in->fail();
00051 }
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 bool DatagramInputFile::
00063 open(istream &in, const Filename &filename) {
00064 close();
00065
00066 _in = ∈
00067 _owns_in = false;
00068 _filename = filename;
00069
00070 if (!filename.empty()) {
00071 _file = new FileReference(filename);
00072 }
00073
00074 return !_in->fail();
00075 }
00076
00077
00078
00079
00080
00081
00082
00083 void DatagramInputFile::
00084 close() {
00085 _vfile.clear();
00086 if (_owns_in) {
00087 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00088 vfs->close_read_file(_in);
00089 }
00090 _in = (istream *)NULL;
00091 _owns_in = false;
00092
00093 _file.clear();
00094 _filename = Filename();
00095
00096 _read_first_datagram = false;
00097 _error = false;
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 bool DatagramInputFile::
00110 read_header(string &header, size_t num_bytes) {
00111 nassertr(!_read_first_datagram, false);
00112 nassertr(_in != (istream *)NULL, false);
00113
00114 char *buffer = (char *)alloca(num_bytes);
00115 nassertr(buffer != (char *)NULL, false);
00116
00117 _in->read(buffer, num_bytes);
00118 if (_in->fail() || _in->eof()) {
00119 return false;
00120 }
00121
00122 header = string(buffer, num_bytes);
00123 Thread::consider_yield();
00124 return true;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134 bool DatagramInputFile::
00135 get_datagram(Datagram &data) {
00136 nassertr(_in != (istream *)NULL, false);
00137 _read_first_datagram = true;
00138
00139
00140 StreamReader reader(_in, false);
00141 size_t num_bytes = reader.get_uint32();
00142 if (_in->fail() || _in->eof()) {
00143 return false;
00144 }
00145
00146 if (num_bytes == 0) {
00147
00148
00149 data.clear();
00150 return true;
00151 }
00152
00153
00154
00155
00156
00157
00158 if (num_bytes > 65536) {
00159 char *buffer = (char *)PANDA_MALLOC_ARRAY(num_bytes);
00160 nassertr(buffer != (char *)NULL, false);
00161
00162 _in->read(buffer, num_bytes);
00163 if (_in->fail() || _in->eof()) {
00164 _error = true;
00165 PANDA_FREE_ARRAY(buffer);
00166 return false;
00167 }
00168
00169 data = Datagram(buffer, num_bytes);
00170 PANDA_FREE_ARRAY(buffer);
00171
00172 } else {
00173 char *buffer = (char *)alloca(num_bytes);
00174 nassertr(buffer != (char *)NULL, false);
00175
00176 _in->read(buffer, num_bytes);
00177 if (_in->fail() || _in->eof()) {
00178 _error = true;
00179 return false;
00180 }
00181
00182 data = Datagram(buffer, num_bytes);
00183 }
00184 Thread::consider_yield();
00185
00186 return true;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 bool DatagramInputFile::
00203 save_datagram(SubfileInfo &info) {
00204 nassertr(_in != (istream *)NULL, false);
00205 _read_first_datagram = true;
00206
00207
00208 StreamReader reader(_in, false);
00209 size_t num_bytes = reader.get_uint32();
00210 if (_in->fail() || _in->eof()) {
00211 return false;
00212 }
00213
00214
00215
00216 if (_file != (FileReference *)NULL) {
00217 info = SubfileInfo(_file, _in->tellg(), num_bytes);
00218 _in->seekg(num_bytes, ios::cur);
00219 return true;
00220 }
00221
00222
00223 PT(TemporaryFile) tfile = new TemporaryFile(Filename::temporary("", ""));
00224 pofstream out;
00225 Filename filename = tfile->get_filename();
00226 filename.set_binary();
00227 if (!filename.open_write(out)) {
00228 util_cat.error()
00229 << "Couldn't write to " << tfile->get_filename() << "\n";
00230 return false;
00231 }
00232
00233 if (util_cat.is_debug()) {
00234 util_cat.debug()
00235 << "Copying " << num_bytes << " bytes to " << tfile->get_filename() << "\n";
00236 }
00237
00238 size_t num_remaining = num_bytes;
00239 static const size_t buffer_size = 4096;
00240 char buffer[buffer_size];
00241
00242 _in->read(buffer, min(buffer_size, num_remaining));
00243 size_t count = _in->gcount();
00244 while (count != 0) {
00245 out.write(buffer, count);
00246 if (out.fail()) {
00247 util_cat.error()
00248 << "Couldn't write " << num_bytes << " bytes to "
00249 << tfile->get_filename() << "\n";
00250 return false;
00251 }
00252 num_remaining -= count;
00253 if (num_remaining == 0) {
00254 break;
00255 }
00256 _in->read(buffer, min(buffer_size, num_remaining));
00257 count = _in->gcount();
00258 }
00259
00260 if (num_remaining != 0) {
00261 util_cat.error()
00262 << "Truncated data stream.\n";
00263 return false;
00264 }
00265
00266 info = SubfileInfo(tfile, 0, num_bytes);
00267 return true;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 bool DatagramInputFile::
00278 is_eof() {
00279 return _in != (istream *)NULL ? _in->eof() : true;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288 bool DatagramInputFile::
00289 is_error() {
00290 if (_in == (istream *)NULL) {
00291 return true;
00292 }
00293
00294 if (_in->fail()) {
00295 _error = true;
00296 }
00297 return _error;
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307 const Filename &DatagramInputFile::
00308 get_filename() {
00309 return _filename;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319 const FileReference *DatagramInputFile::
00320 get_file() {
00321 return _file;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331 VirtualFile *DatagramInputFile::
00332 get_vfile() {
00333 return _vfile;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 streampos DatagramInputFile::
00349 get_file_pos() {
00350 if (_in == (istream *)NULL) {
00351 return 0;
00352 }
00353 return _in->tellg();
00354 }