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