Panda3D

virtualFile.cxx

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 }
 All Classes Functions Variables Enumerations