Panda3D
|
00001 // Filename: virtualFile.cxx 00002 // Created by: drose (03Aug02) 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 "virtualFile.h" 00016 #include "virtualFileSystem.h" 00017 #include "virtualFileList.h" 00018 #include "config_express.h" 00019 #include "pvector.h" 00020 00021 TypeHandle VirtualFile::_type_handle; 00022 00023 //////////////////////////////////////////////////////////////////// 00024 // Function: VirtualFile::has_file 00025 // Access: Published, Virtual 00026 // Description: Returns true if this file exists, false otherwise. 00027 //////////////////////////////////////////////////////////////////// 00028 bool VirtualFile:: 00029 has_file() const { 00030 return false; 00031 } 00032 00033 //////////////////////////////////////////////////////////////////// 00034 // Function: VirtualFile::is_directory 00035 // Access: Published, Virtual 00036 // Description: Returns true if this file represents a directory (and 00037 // scan_directory() may be called), false otherwise. 00038 //////////////////////////////////////////////////////////////////// 00039 bool VirtualFile:: 00040 is_directory() const { 00041 return false; 00042 } 00043 00044 //////////////////////////////////////////////////////////////////// 00045 // Function: VirtualFile::is_regular_file 00046 // Access: Published, Virtual 00047 // Description: Returns true if this file represents a regular file 00048 // (and read_file() may be called), false otherwise. 00049 //////////////////////////////////////////////////////////////////// 00050 bool VirtualFile:: 00051 is_regular_file() const { 00052 return false; 00053 } 00054 00055 //////////////////////////////////////////////////////////////////// 00056 // Function: VirtualFile::scan_directory 00057 // Access: Published 00058 // Description: If the file represents a directory (that is, 00059 // is_directory() returns true), this returns the list 00060 // of files within the directory at the current time. 00061 // Returns NULL if the file is not a directory or if the 00062 // directory cannot be read. 00063 //////////////////////////////////////////////////////////////////// 00064 PT(VirtualFileList) VirtualFile:: 00065 scan_directory() const { 00066 // First, we have to make sure there aren't any mount points attached 00067 // under this directory. These will override any local filenames. 00068 VirtualFileSystem *file_system = get_file_system(); 00069 Filename this_filename = get_filename(); 00070 vector_string mount_points_flat; 00071 file_system->scan_mount_points(mount_points_flat, this_filename); 00072 00073 // Copy the set of nested mount points to a sorted list so we can 00074 // search it quickly. 00075 ov_set<string> mount_points; 00076 copy(mount_points_flat.begin(), mount_points_flat.end(), 00077 back_inserter(mount_points)); 00078 mount_points.sort(); 00079 00080 00081 PT(VirtualFileList) file_list = new VirtualFileList; 00082 00083 // Each of those mount points maps to a directory root or something 00084 // from the file system. 00085 ov_set<string>::const_iterator mi; 00086 for (mi = mount_points.begin(); mi != mount_points.end(); ++mi) { 00087 const string &basename = (*mi); 00088 Filename filename(this_filename, basename); 00089 PT(VirtualFile) file = file_system->get_file(filename); 00090 file_list->add_file(file); 00091 } 00092 00093 // Now, get the actual local files in this directory. 00094 vector_string names; 00095 if (!scan_local_directory(file_list, mount_points)) { 00096 // Not a directory, or unable to read directory. 00097 if (file_list->get_num_files() == 0) { 00098 return NULL; 00099 } 00100 00101 // We couldn't read the physical directory, but we do have some 00102 // mounted files to return. 00103 return file_list; 00104 } 00105 00106 return file_list; 00107 } 00108 00109 //////////////////////////////////////////////////////////////////// 00110 // Function: VirtualFile::output 00111 // Access: Published 00112 // Description: 00113 //////////////////////////////////////////////////////////////////// 00114 void VirtualFile:: 00115 output(ostream &out) const { 00116 out << get_filename(); 00117 } 00118 00119 //////////////////////////////////////////////////////////////////// 00120 // Function: VirtualFile::ls 00121 // Access: Published 00122 // Description: If the file represents a directory, lists its 00123 // contents. 00124 //////////////////////////////////////////////////////////////////// 00125 void VirtualFile:: 00126 ls(ostream &out) const { 00127 CPT(VirtualFileList) contents = scan_directory(); 00128 if (contents == (VirtualFileList *)NULL) { 00129 if (!is_directory()) { 00130 out << get_filename() << "\n"; 00131 } else { 00132 out << get_filename() << " cannot be read.\n"; 00133 } 00134 return; 00135 } 00136 00137 int num_files = contents->get_num_files(); 00138 for (int i = 0; i < num_files; i++) { 00139 VirtualFile *file = contents->get_file(i); 00140 out << file->get_filename().get_basename() << "\n"; 00141 } 00142 } 00143 00144 //////////////////////////////////////////////////////////////////// 00145 // Function: VirtualFile::ls_all 00146 // Access: Published 00147 // Description: If the file represents a directory, recursively lists 00148 // its contents and those of all subdirectories. 00149 //////////////////////////////////////////////////////////////////// 00150 void VirtualFile:: 00151 ls_all(ostream &out) const { 00152 if (!is_directory()) { 00153 out << get_filename() << " is not a directory.\n"; 00154 } else { 00155 r_ls_all(out, get_filename()); 00156 } 00157 } 00158 00159 //////////////////////////////////////////////////////////////////// 00160 // Function: VirtualFile::open_read_file 00161 // Access: Published, Virtual 00162 // Description: Opens the file for reading. Returns a newly 00163 // allocated istream on success (which you should 00164 // eventually delete when you are done reading). 00165 // Returns NULL on failure. 00166 //////////////////////////////////////////////////////////////////// 00167 istream *VirtualFile:: 00168 open_read_file(bool auto_unwrap) const { 00169 return NULL; 00170 } 00171 00172 //////////////////////////////////////////////////////////////////// 00173 // Function: VirtualFile::get_file_size 00174 // Access: Published, Virtual 00175 // Description: Returns the current size on disk (or wherever it is) 00176 // of the already-open file. Pass in the stream that 00177 // was returned by open_read_file(); some 00178 // implementations may require this stream to determine 00179 // the size. 00180 //////////////////////////////////////////////////////////////////// 00181 off_t VirtualFile:: 00182 get_file_size(istream *stream) const { 00183 return get_file_size(); 00184 } 00185 00186 //////////////////////////////////////////////////////////////////// 00187 // Function: VirtualFile::get_file_size 00188 // Access: Published, Virtual 00189 // Description: Returns the current size on disk (or wherever it is) 00190 // of the file before it has been opened. 00191 //////////////////////////////////////////////////////////////////// 00192 off_t VirtualFile:: 00193 get_file_size() const { 00194 return 0; 00195 } 00196 00197 //////////////////////////////////////////////////////////////////// 00198 // Function: VirtualFile::get_timestamp 00199 // Access: Published, Virtual 00200 // Description: Returns a time_t value that represents the time the 00201 // file was last modified, to within whatever precision 00202 // the operating system records this information (on a 00203 // Windows95 system, for instance, this may only be 00204 // accurate to within 2 seconds). 00205 // 00206 // If the timestamp cannot be determined, either because 00207 // it is not supported by the operating system or 00208 // because there is some error (such as file not found), 00209 // returns 0. 00210 //////////////////////////////////////////////////////////////////// 00211 time_t VirtualFile:: 00212 get_timestamp() const { 00213 return 0; 00214 } 00215 00216 //////////////////////////////////////////////////////////////////// 00217 // Function: VirtualFile::close_read_file 00218 // Access: Public 00219 // Description: Closes a file opened by a previous call to 00220 // open_read_file(). This really just deletes the 00221 // istream pointer, but it is recommended to use this 00222 // interface instead of deleting it explicitly, to help 00223 // work around compiler issues. 00224 //////////////////////////////////////////////////////////////////// 00225 void VirtualFile:: 00226 close_read_file(istream *stream) const { 00227 if (stream != (istream *)NULL) { 00228 // For some reason--compiler bug in gcc 3.2?--explicitly deleting 00229 // the stream pointer does not call the appropriate global delete 00230 // function; instead apparently calling the system delete 00231 // function. So we call the delete function by hand instead. 00232 #if !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) 00233 stream->~istream(); 00234 (*global_operator_delete)(stream); 00235 #else 00236 delete stream; 00237 #endif 00238 } 00239 } 00240 00241 //////////////////////////////////////////////////////////////////// 00242 // Function: VirtualFile::was_read_successful 00243 // Access: Public 00244 // Description: Call this method after a reading the istream returned 00245 // by open_read_file() to completion. If it returns 00246 // true, the file was read completely and without error; 00247 // if it returns false, there may have been some errors 00248 // or a truncated file read. This is particularly 00249 // likely if the stream is a VirtualFileHTTP. 00250 //////////////////////////////////////////////////////////////////// 00251 bool VirtualFile:: 00252 was_read_successful() const { 00253 return true; 00254 } 00255 00256 //////////////////////////////////////////////////////////////////// 00257 // Function: VirtualFile::read_file 00258 // Access: Public 00259 // Description: Fills up the indicated string with the contents of 00260 // the file, if it is a regular file. Returns true on 00261 // success, false otherwise. 00262 //////////////////////////////////////////////////////////////////// 00263 bool VirtualFile:: 00264 read_file(string &result, bool auto_unwrap) const { 00265 result = string(); 00266 00267 pvector<unsigned char> pv; 00268 if (!read_file(pv, auto_unwrap)) { 00269 return false; 00270 } 00271 00272 if (!pv.empty()) { 00273 result.append((const char *)&pv[0], pv.size()); 00274 } 00275 00276 return true; 00277 } 00278 00279 //////////////////////////////////////////////////////////////////// 00280 // Function: VirtualFile::read_file 00281 // Access: Public, Virtual 00282 // Description: Fills up the indicated pvector with the contents of 00283 // the file, if it is a regular file. Returns true on 00284 // success, false otherwise. 00285 //////////////////////////////////////////////////////////////////// 00286 bool VirtualFile:: 00287 read_file(pvector<unsigned char> &result, bool auto_unwrap) const { 00288 return false; 00289 } 00290 00291 //////////////////////////////////////////////////////////////////// 00292 // Function: VirtualFile::simple_read_file 00293 // Access: Public, Static 00294 // Description: Fills up the indicated pvector with the contents of 00295 // the just-opened file. Returns true on success, false 00296 // otherwise. If the pvector was not empty on entry, the 00297 // data read from the file will be appended onto it. 00298 //////////////////////////////////////////////////////////////////// 00299 bool VirtualFile:: 00300 simple_read_file(istream *in, pvector<unsigned char> &result) { 00301 static const size_t buffer_size = 4096; 00302 char buffer[buffer_size]; 00303 00304 in->read(buffer, buffer_size); 00305 size_t count = in->gcount(); 00306 while (count != 0) { 00307 thread_consider_yield(); 00308 result.insert(result.end(), buffer, buffer + count); 00309 in->read(buffer, buffer_size); 00310 count = in->gcount(); 00311 } 00312 00313 return (!in->fail() || in->eof()); 00314 } 00315 00316 //////////////////////////////////////////////////////////////////// 00317 // Function: VirtualFile::simple_read_file 00318 // Access: Public 00319 // Description: As in simple_read_file() with two parameters, above, 00320 // but only reads up to max_bytes bytes from the file. 00321 //////////////////////////////////////////////////////////////////// 00322 bool VirtualFile:: 00323 simple_read_file(istream *in, pvector<unsigned char> &result, size_t max_bytes) { 00324 static const size_t buffer_size = 4096; 00325 char buffer[buffer_size]; 00326 00327 in->read(buffer, min(buffer_size, max_bytes)); 00328 size_t count = in->gcount(); 00329 while (count != 0) { 00330 thread_consider_yield(); 00331 nassertr(count <= max_bytes, false); 00332 result.insert(result.end(), buffer, buffer + count); 00333 max_bytes -= count; 00334 in->read(buffer, min(buffer_size, max_bytes)); 00335 count = in->gcount(); 00336 } 00337 00338 return (!in->fail() || in->eof()); 00339 } 00340 00341 //////////////////////////////////////////////////////////////////// 00342 // Function: VirtualFile::scan_local_directory 00343 // Access: Protected, Virtual 00344 // Description: Fills file_list up with the list of files that are 00345 // within this directory, excluding those whose 00346 // basenames are listed in mount_points. Returns true 00347 // if successful, false if the file is not a directory 00348 // or the directory cannot be read. 00349 //////////////////////////////////////////////////////////////////// 00350 bool VirtualFile:: 00351 scan_local_directory(VirtualFileList *, const ov_set<string> &) const { 00352 return false; 00353 } 00354 00355 //////////////////////////////////////////////////////////////////// 00356 // Function: VirtualFile::r_ls_all 00357 // Access: Private 00358 // Description: The recursive implementation of ls_all(). 00359 //////////////////////////////////////////////////////////////////// 00360 void VirtualFile:: 00361 r_ls_all(ostream &out, const Filename &root) const { 00362 CPT(VirtualFileList) contents = scan_directory(); 00363 if (contents == (VirtualFileList *)NULL) { 00364 return; 00365 } 00366 00367 int num_files = contents->get_num_files(); 00368 for (int i = 0; i < num_files; i++) { 00369 VirtualFile *file = contents->get_file(i); 00370 Filename filename = file->get_filename(); 00371 filename.make_relative_to(root); 00372 out << filename << "\n"; 00373 if (file->is_directory()) { 00374 file->r_ls_all(out, root); 00375 } 00376 } 00377 }