Panda3D

virtualFileMountRamdisk.cxx

00001 // Filename: virtualFileMountRamdisk.cxx
00002 // Created by:  drose (19Sep11)
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 "virtualFileMountRamdisk.h"
00016 #include "subStream.h"
00017 #include "dcast.h"
00018 
00019 TypeHandle VirtualFileMountRamdisk::_type_handle;
00020 TypeHandle VirtualFileMountRamdisk::FileBase::_type_handle;
00021 TypeHandle VirtualFileMountRamdisk::File::_type_handle;
00022 TypeHandle VirtualFileMountRamdisk::Directory::_type_handle;
00023 
00024 ////////////////////////////////////////////////////////////////////
00025 //     Function: VirtualFileMountRamdisk::Constructor
00026 //       Access: Public
00027 //  Description: 
00028 ////////////////////////////////////////////////////////////////////
00029 VirtualFileMountRamdisk::
00030 VirtualFileMountRamdisk() : _root("") {
00031 }
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: VirtualFileMountRamdisk::has_file
00035 //       Access: Public, Virtual
00036 //  Description: Returns true if the indicated file exists within the
00037 //               mount system.
00038 ////////////////////////////////////////////////////////////////////
00039 bool VirtualFileMountRamdisk::
00040 has_file(const Filename &file) const {
00041   ((VirtualFileMountRamdisk *)this)->_lock.acquire();
00042   PT(FileBase) f = _root.do_find_file(file);
00043   ((VirtualFileMountRamdisk *)this)->_lock.release();
00044   return (f != NULL);
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: VirtualFileMountRamdisk::create_file
00049 //       Access: Public, Virtual
00050 //  Description: Attempts to create the indicated file within the
00051 //               mount, if it does not already exist.  Returns true on
00052 //               success (or if the file already exists), or false if
00053 //               it cannot be created.
00054 ////////////////////////////////////////////////////////////////////
00055 bool VirtualFileMountRamdisk::
00056 create_file(const Filename &file) {
00057   _lock.acquire();
00058   PT(File) f = _root.do_create_file(file);
00059   _lock.release();
00060   return (f != NULL);
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: VirtualFileMountRamdisk::delete_file
00065 //       Access: Public, Virtual
00066 //  Description: Attempts to delete the indicated file or directory
00067 //               within the mount.  This can remove a single file or
00068 //               an empty directory.  It will not remove a nonempty
00069 //               directory.  Returns true on success, false on
00070 //               failure.
00071 ////////////////////////////////////////////////////////////////////
00072 bool VirtualFileMountRamdisk::
00073 delete_file(const Filename &file) {
00074   _lock.acquire();
00075   PT(FileBase) f = _root.do_delete_file(file);
00076   _lock.release();
00077   return (f != NULL);
00078 }
00079 
00080 ////////////////////////////////////////////////////////////////////
00081 //     Function: VirtualFileMountRamdisk::rename_file
00082 //       Access: Public
00083 //  Description: Attempts to rename the contents of the indicated file
00084 //               to the indicated file.  Both filenames will be within
00085 //               the mount.  Returns true on success, false on
00086 //               failure.  If this returns false, this will be
00087 //               attempted again with a copy-and-delete operation.
00088 ////////////////////////////////////////////////////////////////////
00089 bool VirtualFileMountRamdisk::
00090 rename_file(const Filename &orig_filename, const Filename &new_filename) {
00091   _lock.acquire();
00092   PT(FileBase) orig_fb = _root.do_find_file(orig_filename);
00093   if (orig_fb == NULL) {
00094     _lock.release();
00095     return false;
00096   }
00097 
00098   if (orig_fb->is_directory()) {
00099     // Rename the directory.
00100     Directory *orig_d = DCAST(Directory, orig_fb);
00101     PT(Directory) new_d = _root.do_make_directory(new_filename);
00102     if (new_d == NULL || !new_d->_files.empty()) {
00103       _lock.release();
00104       return false;
00105     }
00106 
00107     if (express_cat.is_debug()) {
00108       express_cat.debug()
00109         << "Renaming ramdisk directory " << orig_filename << " to " << new_filename << "\n";
00110     }
00111 
00112     new_d->_files.swap(orig_d->_files);
00113     _root.do_delete_file(orig_filename);
00114     _lock.release();
00115     return true;
00116   }
00117 
00118   // Rename the file.
00119   File *orig_f = DCAST(File, orig_fb);
00120   PT(File) new_f = _root.do_create_file(new_filename);
00121   if (new_f == NULL) {
00122     _lock.release();
00123     return false;
00124   }
00125 
00126   if (express_cat.is_debug()) {
00127     express_cat.debug()
00128       << "Renaming ramdisk file " << orig_filename << " to " << new_filename << "\n";
00129   }
00130 
00131   new_f->_data.str(orig_f->_data.str());
00132   _root.do_delete_file(orig_filename);
00133 
00134   _lock.release();
00135   return true;
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: VirtualFileMountRamdisk::copy_file
00140 //       Access: Public
00141 //  Description: Attempts to copy the contents of the indicated file
00142 //               to the indicated file.  Both filenames will be within
00143 //               the mount.  Returns true on success, false on
00144 //               failure.  If this returns false, the copy will be
00145 //               performed by explicit read-and-write operations.
00146 ////////////////////////////////////////////////////////////////////
00147 bool VirtualFileMountRamdisk::
00148 copy_file(const Filename &orig_filename, const Filename &new_filename) {
00149   _lock.acquire();
00150   PT(FileBase) orig_fb = _root.do_find_file(orig_filename);
00151   if (orig_fb == NULL || orig_fb->is_directory()) {
00152     _lock.release();
00153     return false;
00154   }
00155 
00156   // Copy the file.
00157   File *orig_f = DCAST(File, orig_fb);
00158   PT(File) new_f = _root.do_create_file(new_filename);
00159   if (new_f == NULL) {
00160     _lock.release();
00161     return false;
00162   }
00163 
00164   if (express_cat.is_debug()) {
00165     express_cat.debug()
00166       << "Copying ramdisk file " << orig_filename << " to " << new_filename << "\n";
00167   }
00168 
00169   new_f->_data.str(orig_f->_data.str());
00170 
00171   _lock.release();
00172   return true;
00173 }
00174 
00175 ////////////////////////////////////////////////////////////////////
00176 //     Function: VirtualFileMountRamdisk::make_directory
00177 //       Access: Public, Virtual
00178 //  Description: Attempts to create the indicated file within the
00179 //               mount, if it does not already exist.  Returns true on
00180 //               success, or false if it cannot be created.  If the
00181 //               directory already existed prior to this call, may
00182 //               return either true or false.
00183 ////////////////////////////////////////////////////////////////////
00184 bool VirtualFileMountRamdisk::
00185 make_directory(const Filename &file) {
00186   _lock.acquire();
00187   PT(Directory) f = _root.do_make_directory(file);
00188   _lock.release();
00189   return (f != NULL);
00190 }
00191 
00192 ////////////////////////////////////////////////////////////////////
00193 //     Function: VirtualFileMountRamdisk::is_directory
00194 //       Access: Public, Virtual
00195 //  Description: Returns true if the indicated file exists within the
00196 //               mount system and is a directory.
00197 ////////////////////////////////////////////////////////////////////
00198 bool VirtualFileMountRamdisk::
00199 is_directory(const Filename &file) const {
00200   ((VirtualFileMountRamdisk *)this)->_lock.acquire();
00201   PT(FileBase) f = _root.do_find_file(file);
00202   ((VirtualFileMountRamdisk *)this)->_lock.release();
00203   return (f != NULL && f->is_directory());
00204 }
00205 
00206 ////////////////////////////////////////////////////////////////////
00207 //     Function: VirtualFileMountRamdisk::is_regular_file
00208 //       Access: Public, Virtual
00209 //  Description: Returns true if the indicated file exists within the
00210 //               mount system and is a regular file.
00211 ////////////////////////////////////////////////////////////////////
00212 bool VirtualFileMountRamdisk::
00213 is_regular_file(const Filename &file) const {
00214   ((VirtualFileMountRamdisk *)this)->_lock.acquire();
00215   PT(FileBase) f = _root.do_find_file(file);
00216   ((VirtualFileMountRamdisk *)this)->_lock.release();
00217   return (f != NULL && !f->is_directory());
00218 }
00219 
00220 ////////////////////////////////////////////////////////////////////
00221 //     Function: VirtualFileMountRamdisk::is_writable
00222 //       Access: Public, Virtual
00223 //  Description: Returns true if the named file or directory may be
00224 //               written to, false otherwise.
00225 ////////////////////////////////////////////////////////////////////
00226 bool VirtualFileMountRamdisk::
00227 is_writable(const Filename &file) const {
00228   return has_file(file);
00229 }
00230 
00231 ////////////////////////////////////////////////////////////////////
00232 //     Function: VirtualFileMountRamdisk::open_read_file
00233 //       Access: Public, Virtual
00234 //  Description: Opens the file for reading, if it exists.  Returns a
00235 //               newly allocated istream on success (which you should
00236 //               eventually delete when you are done reading).
00237 //               Returns NULL on failure.
00238 ////////////////////////////////////////////////////////////////////
00239 istream *VirtualFileMountRamdisk::
00240 open_read_file(const Filename &file) const {
00241   ((VirtualFileMountRamdisk *)this)->_lock.acquire();
00242   PT(FileBase) f = _root.do_find_file(file);
00243   ((VirtualFileMountRamdisk *)this)->_lock.release();
00244   if (f == (FileBase *)NULL || f->is_directory()) {
00245     return false;
00246   }
00247 
00248   File *f2 = DCAST(File, f);
00249   return new ISubStream(&f2->_wrapper, 0, 0);
00250 }
00251 
00252 ////////////////////////////////////////////////////////////////////
00253 //     Function: VirtualFileMountRamdisk::open_write_file
00254 //       Access: Published, Virtual
00255 //  Description: Opens the file for writing.  Returns a newly
00256 //               allocated ostream on success (which you should
00257 //               eventually delete when you are done writing).
00258 //               Returns NULL on failure.
00259 ////////////////////////////////////////////////////////////////////
00260 ostream *VirtualFileMountRamdisk::
00261 open_write_file(const Filename &file, bool truncate) {
00262   _lock.acquire();
00263   PT(File) f = _root.do_create_file(file);
00264   _lock.release();
00265   if (f == (File *)NULL) {
00266     return false;
00267   }
00268 
00269   if (truncate) {
00270     // Reset to an empty string.
00271     f->_data.str(string());
00272   }
00273 
00274   return new OSubStream(&f->_wrapper, 0, 0);
00275 }
00276 
00277 ////////////////////////////////////////////////////////////////////
00278 //     Function: VirtualFileMountRamdisk::open_append_file
00279 //       Access: Published
00280 //  Description: Works like open_write_file(), but the file is opened
00281 //               in append mode.  Like open_write_file, the returned
00282 //               pointer should eventually be passed to
00283 //               close_write_file().
00284 ////////////////////////////////////////////////////////////////////
00285 ostream *VirtualFileMountRamdisk::
00286 open_append_file(const Filename &file) {
00287   _lock.acquire();
00288   PT(File) f = _root.do_create_file(file);
00289   _lock.release();
00290   if (f == (File *)NULL) {
00291     return false;
00292   }
00293 
00294   return new OSubStream(&f->_wrapper, 0, 0, true);
00295 }
00296 
00297 ////////////////////////////////////////////////////////////////////
00298 //     Function: VirtualFileMountRamdisk::open_read_write_file
00299 //       Access: Published, Virtual
00300 //  Description: Opens the file for writing.  Returns a newly
00301 //               allocated iostream on success (which you should
00302 //               eventually delete when you are done writing).
00303 //               Returns NULL on failure.
00304 ////////////////////////////////////////////////////////////////////
00305 iostream *VirtualFileMountRamdisk::
00306 open_read_write_file(const Filename &file, bool truncate) {
00307   _lock.acquire();
00308   PT(File) f = _root.do_create_file(file);
00309   _lock.release();
00310   if (f == (File *)NULL) {
00311     return false;
00312   }
00313 
00314   return new SubStream(&f->_wrapper, 0, 0);
00315 }
00316 
00317 ////////////////////////////////////////////////////////////////////
00318 //     Function: VirtualFileMountRamdisk::open_read_append_file
00319 //       Access: Published, Virtual
00320 //  Description: Works like open_read_write_file(), but the file is opened
00321 //               in append mode.  Like open_read_write_file, the returned
00322 //               pointer should eventually be passed to
00323 //               close_read_write_file().
00324 ////////////////////////////////////////////////////////////////////
00325 iostream *VirtualFileMountRamdisk::
00326 open_read_append_file(const Filename &file) {
00327   _lock.acquire();
00328   PT(FileBase) f = _root.do_find_file(file);
00329   _lock.release();
00330   if (f == (FileBase *)NULL || f->is_directory()) {
00331     return false;
00332   }
00333 
00334   File *f2 = DCAST(File, f);
00335   return new SubStream(&f2->_wrapper, 0, 0, true);
00336 }
00337 
00338 ////////////////////////////////////////////////////////////////////
00339 //     Function: VirtualFileMountRamdisk::get_file_size
00340 //       Access: Published, Virtual
00341 //  Description: Returns the current size on disk (or wherever it is)
00342 //               of the already-open file.  Pass in the stream that
00343 //               was returned by open_read_file(); some
00344 //               implementations may require this stream to determine
00345 //               the size.
00346 ////////////////////////////////////////////////////////////////////
00347 off_t VirtualFileMountRamdisk::
00348 get_file_size(const Filename &file, istream *stream) const {
00349   ((VirtualFileMountRamdisk *)this)->_lock.acquire();
00350   PT(FileBase) f = _root.do_find_file(file);
00351   ((VirtualFileMountRamdisk *)this)->_lock.release();
00352   if (f == (FileBase *)NULL || f->is_directory()) {
00353     return false;
00354   }
00355 
00356   File *f2 = DCAST(File, f);
00357   return f2->_data.str().length();
00358 }
00359 
00360 ////////////////////////////////////////////////////////////////////
00361 //     Function: VirtualFileMountRamdisk::get_file_size
00362 //       Access: Published, Virtual
00363 //  Description: Returns the current size on disk (or wherever it is)
00364 //               of the file before it has been opened.
00365 ////////////////////////////////////////////////////////////////////
00366 off_t VirtualFileMountRamdisk::
00367 get_file_size(const Filename &file) const {
00368   ((VirtualFileMountRamdisk *)this)->_lock.acquire();
00369   PT(FileBase) f = _root.do_find_file(file);
00370   ((VirtualFileMountRamdisk *)this)->_lock.release();
00371   if (f == (FileBase *)NULL || f->is_directory()) {
00372     return false;
00373   }
00374 
00375   File *f2 = DCAST(File, f);
00376   return f2->_data.str().length();
00377 }
00378 
00379 ////////////////////////////////////////////////////////////////////
00380 //     Function: VirtualFileMountRamdisk::get_timestamp
00381 //       Access: Published, Virtual
00382 //  Description: Returns a time_t value that represents the time the
00383 //               file was last modified, to within whatever precision
00384 //               the operating system records this information (on a
00385 //               Windows95 system, for instance, this may only be
00386 //               accurate to within 2 seconds).
00387 //
00388 //               If the timestamp cannot be determined, either because
00389 //               it is not supported by the operating system or
00390 //               because there is some error (such as file not found),
00391 //               returns 0.
00392 ////////////////////////////////////////////////////////////////////
00393 time_t VirtualFileMountRamdisk::
00394 get_timestamp(const Filename &file) const {
00395   return 0;
00396 }
00397 
00398 ////////////////////////////////////////////////////////////////////
00399 //     Function: VirtualFileMountRamdisk::scan_directory
00400 //       Access: Public, Virtual
00401 //  Description: Fills the given vector up with the list of filenames
00402 //               that are local to this directory, if the filename is
00403 //               a directory.  Returns true if successful, or false if
00404 //               the file is not a directory or cannot be read.
00405 ////////////////////////////////////////////////////////////////////
00406 bool VirtualFileMountRamdisk::
00407 scan_directory(vector_string &contents, const Filename &dir) const {
00408   ((VirtualFileMountRamdisk *)this)->_lock.acquire();
00409   PT(FileBase) f = _root.do_find_file(dir);
00410   if (f == (FileBase *)NULL || !f->is_directory()) {
00411     ((VirtualFileMountRamdisk *)this)->_lock.release();
00412     return false;
00413   }
00414 
00415   Directory *f2 = DCAST(Directory, f);
00416   bool result = f2->do_scan_directory(contents);
00417 
00418   ((VirtualFileMountRamdisk *)this)->_lock.release();
00419   return result;
00420 }
00421 
00422 ////////////////////////////////////////////////////////////////////
00423 //     Function: VirtualFileMountRamdisk::atomic_compare_and_exchange_contents
00424 //       Access: Public, Virtual
00425 //  Description: See Filename::atomic_compare_and_exchange_contents().
00426 ////////////////////////////////////////////////////////////////////
00427 bool VirtualFileMountRamdisk::
00428 atomic_compare_and_exchange_contents(const Filename &file, string &orig_contents,
00429                                      const string &old_contents, 
00430                                      const string &new_contents) {
00431   _lock.acquire();
00432   PT(FileBase) f = _root.do_find_file(file);
00433   if (f == (FileBase *)NULL || f->is_directory()) {
00434     _lock.release();
00435     return false;
00436   }
00437 
00438   bool retval = false;
00439   File *f2 = DCAST(File, f);
00440   orig_contents = f2->_data.str();
00441   if (orig_contents == old_contents) {
00442     f2->_data.str(new_contents);
00443     retval = true;
00444   }
00445 
00446   _lock.release();
00447   return retval;
00448 }
00449 
00450 ////////////////////////////////////////////////////////////////////
00451 //     Function: VirtualFileMountRamdisk::atomic_read_contents
00452 //       Access: Public, Virtual
00453 //  Description: See Filename::atomic_read_contents().
00454 ////////////////////////////////////////////////////////////////////
00455 bool VirtualFileMountRamdisk::
00456 atomic_read_contents(const Filename &file, string &contents) const {
00457   ((VirtualFileMountRamdisk *)this)->_lock.acquire();
00458   PT(FileBase) f = _root.do_find_file(file);
00459   if (f == (FileBase *)NULL || f->is_directory()) {
00460     ((VirtualFileMountRamdisk *)this)->_lock.release();
00461     return false;
00462   }
00463 
00464   File *f2 = DCAST(File, f);
00465   contents = f2->_data.str();
00466 
00467   ((VirtualFileMountRamdisk *)this)->_lock.release();
00468   return true;
00469 }
00470 
00471 
00472 ////////////////////////////////////////////////////////////////////
00473 //     Function: VirtualFileMountRamdisk::output
00474 //       Access: Public, Virtual
00475 //  Description: 
00476 ////////////////////////////////////////////////////////////////////
00477 void VirtualFileMountRamdisk::
00478 output(ostream &out) const {
00479   out << "VirtualFileMountRamdisk";
00480 }
00481 
00482 ////////////////////////////////////////////////////////////////////
00483 //     Function: VirtualFileMountRamdisk::FileBase::Destructor
00484 //       Access: Public, Virtual
00485 //  Description: 
00486 ////////////////////////////////////////////////////////////////////
00487 VirtualFileMountRamdisk::FileBase::
00488 ~FileBase() {
00489 }
00490 
00491 ////////////////////////////////////////////////////////////////////
00492 //     Function: VirtualFileMountRamdisk::FileBase::is_directory
00493 //       Access: Public, Virtual
00494 //  Description: 
00495 ////////////////////////////////////////////////////////////////////
00496 bool VirtualFileMountRamdisk::FileBase::
00497 is_directory() const {
00498   return false;
00499 }
00500 
00501 ////////////////////////////////////////////////////////////////////
00502 //     Function: VirtualFileMountRamdisk::Directory::is_directory
00503 //       Access: Public, Virtual
00504 //  Description: 
00505 ////////////////////////////////////////////////////////////////////
00506 bool VirtualFileMountRamdisk::Directory::
00507 is_directory() const {
00508   return true;
00509 }
00510 
00511 ////////////////////////////////////////////////////////////////////
00512 //     Function: VirtualFileMountRamdisk::Directory::do_find_file
00513 //       Access: Public
00514 //  Description: Recursively search for the file with the indicated
00515 //               name in this directory hierarchy.
00516 ////////////////////////////////////////////////////////////////////
00517 PT(VirtualFileMountRamdisk::FileBase) VirtualFileMountRamdisk::Directory::
00518 do_find_file(const string &filename) const {
00519   size_t slash = filename.find('/');
00520   if (slash == string::npos) {
00521     // Search for a file within the local directory.
00522     FileBase tfile(filename);
00523     tfile.local_object();
00524     Files::const_iterator fi = _files.find(&tfile);
00525     if (fi != _files.end()) {
00526       return (*fi);
00527     }
00528     return NULL;
00529   }
00530 
00531   // A nested directory.  Search for the directory name, then recurse.
00532   string dirname = filename.substr(0, slash);
00533   string remainder = filename.substr(slash + 1);
00534   FileBase tfile(dirname);
00535   tfile.local_object();
00536   Files::const_iterator fi = _files.find(&tfile);
00537   if (fi != _files.end()) {
00538     PT(FileBase) file = (*fi);
00539     if (file->is_directory()) {
00540       return DCAST(Directory, file.p())->do_find_file(remainder);
00541     }
00542   }
00543 
00544   return NULL;
00545 }
00546 
00547 ////////////////////////////////////////////////////////////////////
00548 //     Function: VirtualFileMountRamdisk::Directory::do_create_file
00549 //       Access: Public
00550 //  Description: Recursively search for the file with the indicated
00551 //               name in this directory hierarchy.  If not found,
00552 //               creates a new file.
00553 ////////////////////////////////////////////////////////////////////
00554 PT(VirtualFileMountRamdisk::File) VirtualFileMountRamdisk::Directory::
00555 do_create_file(const string &filename) {
00556   size_t slash = filename.find('/');
00557   if (slash == string::npos) {
00558     // Search for a file within the local directory.
00559     FileBase tfile(filename);
00560     tfile.local_object();
00561     Files::iterator fi = _files.find(&tfile);
00562     if (fi != _files.end()) {
00563       PT(FileBase) file = (*fi);
00564       if (!file->is_directory()) {
00565         return DCAST(File, file.p());
00566       }
00567       // Cannot create: a directory by the same name already exists.
00568       return NULL;
00569     }
00570 
00571     // Create a new file.
00572     if (express_cat.is_debug()) {
00573       express_cat.debug()
00574         << "Making ramdisk file " << filename << "\n";
00575     }
00576     PT(File) file = new File(filename);
00577     _files.insert(file.p());
00578     return file;
00579   }
00580 
00581   // A nested directory.  Search for the directory name, then recurse.
00582   string dirname = filename.substr(0, slash);
00583   string remainder = filename.substr(slash + 1);
00584   FileBase tfile(dirname);
00585   tfile.local_object();
00586   Files::iterator fi = _files.find(&tfile);
00587   if (fi != _files.end()) {
00588     PT(FileBase) file = (*fi);
00589     if (file->is_directory()) {
00590       return DCAST(Directory, file.p())->do_create_file(remainder);
00591     }
00592   }
00593 
00594   return NULL;
00595 }
00596 
00597 ////////////////////////////////////////////////////////////////////
00598 //     Function: VirtualFileMountRamdisk::Directory::do_make_directory
00599 //       Access: Public
00600 //  Description: Recursively search for the file with the indicated
00601 //               name in this directory hierarchy.  If not found,
00602 //               creates a new directory.
00603 ////////////////////////////////////////////////////////////////////
00604 PT(VirtualFileMountRamdisk::Directory) VirtualFileMountRamdisk::Directory::
00605 do_make_directory(const string &filename) {
00606   size_t slash = filename.find('/');
00607   if (slash == string::npos) {
00608     // Search for a file within the local directory.
00609     FileBase tfile(filename);
00610     tfile.local_object();
00611     Files::iterator fi = _files.find(&tfile);
00612     if (fi != _files.end()) {
00613       PT(FileBase) file = (*fi);
00614       if (file->is_directory()) {
00615         return DCAST(Directory, file.p());
00616       }
00617       // Cannot create: a file by the same name already exists.
00618       return NULL;
00619     }
00620 
00621     // Create a new directory.
00622     if (express_cat.is_debug()) {
00623       express_cat.debug()
00624         << "Making ramdisk directory " << filename << "\n";
00625     }
00626     PT(Directory) file = new Directory(filename);
00627     _files.insert(file.p());
00628     return file;
00629   }
00630 
00631   // A nested directory.  Search for the directory name, then recurse.
00632   string dirname = filename.substr(0, slash);
00633   string remainder = filename.substr(slash + 1);
00634   FileBase tfile(dirname);
00635   tfile.local_object();
00636   Files::iterator fi = _files.find(&tfile);
00637   if (fi != _files.end()) {
00638     PT(FileBase) file = (*fi);
00639     if (file->is_directory()) {
00640       return DCAST(Directory, file.p())->do_make_directory(remainder);
00641     }
00642   }
00643 
00644   return NULL;
00645 }
00646 
00647 ////////////////////////////////////////////////////////////////////
00648 //     Function: VirtualFileMountRamdisk::Directory::do_delete_file
00649 //       Access: Public
00650 //  Description: Recursively search for the file with the indicated
00651 //               name in this directory hierarchy, and removes it.
00652 //               Returns the removed FileBase object.
00653 ////////////////////////////////////////////////////////////////////
00654 PT(VirtualFileMountRamdisk::FileBase) VirtualFileMountRamdisk::Directory::
00655 do_delete_file(const string &filename) {
00656   size_t slash = filename.find('/');
00657   if (slash == string::npos) {
00658     // Search for a file within the local directory.
00659     FileBase tfile(filename);
00660     tfile.local_object();
00661     Files::iterator fi = _files.find(&tfile);
00662     if (fi != _files.end()) {
00663       PT(FileBase) file = (*fi);
00664       if (file->is_directory()) {
00665         Directory *dir = DCAST(Directory, file.p());
00666         if (!dir->_files.empty()) {
00667           // Can't delete a nonempty directory.
00668           return NULL;
00669         }
00670       }
00671       _files.erase(fi);
00672       return file;
00673     }
00674     return NULL;
00675   }
00676 
00677   // A nested directory.  Search for the directory name, then recurse.
00678   string dirname = filename.substr(0, slash);
00679   string remainder = filename.substr(slash + 1);
00680   FileBase tfile(dirname);
00681   tfile.local_object();
00682   Files::iterator fi = _files.find(&tfile);
00683   if (fi != _files.end()) {
00684     PT(FileBase) file = (*fi);
00685     if (file->is_directory()) {
00686       return DCAST(Directory, file.p())->do_delete_file(remainder);
00687     }
00688   }
00689 
00690   return NULL;
00691 }
00692 
00693 ////////////////////////////////////////////////////////////////////
00694 //     Function: VirtualFileMountRamdisk::Directory::do_scan_directory
00695 //       Access: Public
00696 //  Description: 
00697 ////////////////////////////////////////////////////////////////////
00698 bool VirtualFileMountRamdisk::Directory::
00699 do_scan_directory(vector_string &contents) const {
00700   Files::const_iterator fi;
00701   for (fi = _files.begin(); fi != _files.end(); ++fi) {
00702     FileBase *file = (*fi);
00703     contents.push_back(file->_basename);
00704   }
00705 
00706   return true;
00707 }
 All Classes Functions Variables Enumerations