708 lines
25 KiB
C++
708 lines
25 KiB
C++
// Filename: virtualFileMountRamdisk.cxx
|
|
// Created by: drose (19Sep11)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
//
|
|
// All use of this software is subject to the terms of the revised BSD
|
|
// license. You should have received a copy of this license along
|
|
// with this source code in a file named "LICENSE."
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "virtualFileMountRamdisk.h"
|
|
#include "subStream.h"
|
|
#include "dcast.h"
|
|
|
|
TypeHandle VirtualFileMountRamdisk::_type_handle;
|
|
TypeHandle VirtualFileMountRamdisk::FileBase::_type_handle;
|
|
TypeHandle VirtualFileMountRamdisk::File::_type_handle;
|
|
TypeHandle VirtualFileMountRamdisk::Directory::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
VirtualFileMountRamdisk::
|
|
VirtualFileMountRamdisk() : _root("") {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::has_file
|
|
// Access: Public, Virtual
|
|
// Description: Returns true if the indicated file exists within the
|
|
// mount system.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
has_file(const Filename &file) const {
|
|
((VirtualFileMountRamdisk *)this)->_lock.acquire();
|
|
PT(FileBase) f = _root.do_find_file(file);
|
|
((VirtualFileMountRamdisk *)this)->_lock.release();
|
|
return (f != NULL);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::create_file
|
|
// Access: Public, Virtual
|
|
// Description: Attempts to create the indicated file within the
|
|
// mount, if it does not already exist. Returns true on
|
|
// success (or if the file already exists), or false if
|
|
// it cannot be created.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
create_file(const Filename &file) {
|
|
_lock.acquire();
|
|
PT(File) f = _root.do_create_file(file);
|
|
_lock.release();
|
|
return (f != NULL);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::delete_file
|
|
// Access: Public, Virtual
|
|
// Description: Attempts to delete the indicated file or directory
|
|
// within the mount. This can remove a single file or
|
|
// an empty directory. It will not remove a nonempty
|
|
// directory. Returns true on success, false on
|
|
// failure.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
delete_file(const Filename &file) {
|
|
_lock.acquire();
|
|
PT(FileBase) f = _root.do_delete_file(file);
|
|
_lock.release();
|
|
return (f != NULL);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::rename_file
|
|
// Access: Public
|
|
// Description: Attempts to rename the contents of the indicated file
|
|
// to the indicated file. Both filenames will be within
|
|
// the mount. Returns true on success, false on
|
|
// failure. If this returns false, this will be
|
|
// attempted again with a copy-and-delete operation.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
rename_file(const Filename &orig_filename, const Filename &new_filename) {
|
|
_lock.acquire();
|
|
PT(FileBase) orig_fb = _root.do_find_file(orig_filename);
|
|
if (orig_fb == NULL) {
|
|
_lock.release();
|
|
return false;
|
|
}
|
|
|
|
if (orig_fb->is_directory()) {
|
|
// Rename the directory.
|
|
Directory *orig_d = DCAST(Directory, orig_fb);
|
|
PT(Directory) new_d = _root.do_make_directory(new_filename);
|
|
if (new_d == NULL || !new_d->_files.empty()) {
|
|
_lock.release();
|
|
return false;
|
|
}
|
|
|
|
if (express_cat.is_debug()) {
|
|
express_cat.debug()
|
|
<< "Renaming ramdisk directory " << orig_filename << " to " << new_filename << "\n";
|
|
}
|
|
|
|
new_d->_files.swap(orig_d->_files);
|
|
_root.do_delete_file(orig_filename);
|
|
_lock.release();
|
|
return true;
|
|
}
|
|
|
|
// Rename the file.
|
|
File *orig_f = DCAST(File, orig_fb);
|
|
PT(File) new_f = _root.do_create_file(new_filename);
|
|
if (new_f == NULL) {
|
|
_lock.release();
|
|
return false;
|
|
}
|
|
|
|
if (express_cat.is_debug()) {
|
|
express_cat.debug()
|
|
<< "Renaming ramdisk file " << orig_filename << " to " << new_filename << "\n";
|
|
}
|
|
|
|
new_f->_data.str(orig_f->_data.str());
|
|
_root.do_delete_file(orig_filename);
|
|
|
|
_lock.release();
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::copy_file
|
|
// Access: Public
|
|
// Description: Attempts to copy the contents of the indicated file
|
|
// to the indicated file. Both filenames will be within
|
|
// the mount. Returns true on success, false on
|
|
// failure. If this returns false, the copy will be
|
|
// performed by explicit read-and-write operations.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
copy_file(const Filename &orig_filename, const Filename &new_filename) {
|
|
_lock.acquire();
|
|
PT(FileBase) orig_fb = _root.do_find_file(orig_filename);
|
|
if (orig_fb == NULL || orig_fb->is_directory()) {
|
|
_lock.release();
|
|
return false;
|
|
}
|
|
|
|
// Copy the file.
|
|
File *orig_f = DCAST(File, orig_fb);
|
|
PT(File) new_f = _root.do_create_file(new_filename);
|
|
if (new_f == NULL) {
|
|
_lock.release();
|
|
return false;
|
|
}
|
|
|
|
if (express_cat.is_debug()) {
|
|
express_cat.debug()
|
|
<< "Copying ramdisk file " << orig_filename << " to " << new_filename << "\n";
|
|
}
|
|
|
|
new_f->_data.str(orig_f->_data.str());
|
|
|
|
_lock.release();
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::make_directory
|
|
// Access: Public, Virtual
|
|
// Description: Attempts to create the indicated file within the
|
|
// mount, if it does not already exist. Returns true on
|
|
// success, or false if it cannot be created. If the
|
|
// directory already existed prior to this call, may
|
|
// return either true or false.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
make_directory(const Filename &file) {
|
|
_lock.acquire();
|
|
PT(Directory) f = _root.do_make_directory(file);
|
|
_lock.release();
|
|
return (f != NULL);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::is_directory
|
|
// Access: Public, Virtual
|
|
// Description: Returns true if the indicated file exists within the
|
|
// mount system and is a directory.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
is_directory(const Filename &file) const {
|
|
((VirtualFileMountRamdisk *)this)->_lock.acquire();
|
|
PT(FileBase) f = _root.do_find_file(file);
|
|
((VirtualFileMountRamdisk *)this)->_lock.release();
|
|
return (f != NULL && f->is_directory());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::is_regular_file
|
|
// Access: Public, Virtual
|
|
// Description: Returns true if the indicated file exists within the
|
|
// mount system and is a regular file.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
is_regular_file(const Filename &file) const {
|
|
((VirtualFileMountRamdisk *)this)->_lock.acquire();
|
|
PT(FileBase) f = _root.do_find_file(file);
|
|
((VirtualFileMountRamdisk *)this)->_lock.release();
|
|
return (f != NULL && !f->is_directory());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::is_writable
|
|
// Access: Public, Virtual
|
|
// Description: Returns true if the named file or directory may be
|
|
// written to, false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
is_writable(const Filename &file) const {
|
|
return has_file(file);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::open_read_file
|
|
// Access: Public, Virtual
|
|
// Description: Opens the file for reading, if it exists. Returns a
|
|
// newly allocated istream on success (which you should
|
|
// eventually delete when you are done reading).
|
|
// Returns NULL on failure.
|
|
////////////////////////////////////////////////////////////////////
|
|
istream *VirtualFileMountRamdisk::
|
|
open_read_file(const Filename &file) const {
|
|
((VirtualFileMountRamdisk *)this)->_lock.acquire();
|
|
PT(FileBase) f = _root.do_find_file(file);
|
|
((VirtualFileMountRamdisk *)this)->_lock.release();
|
|
if (f == (FileBase *)NULL || f->is_directory()) {
|
|
return false;
|
|
}
|
|
|
|
File *f2 = DCAST(File, f);
|
|
return new ISubStream(&f2->_wrapper, 0, 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::open_write_file
|
|
// Access: Published, Virtual
|
|
// Description: Opens the file for writing. Returns a newly
|
|
// allocated ostream on success (which you should
|
|
// eventually delete when you are done writing).
|
|
// Returns NULL on failure.
|
|
////////////////////////////////////////////////////////////////////
|
|
ostream *VirtualFileMountRamdisk::
|
|
open_write_file(const Filename &file, bool truncate) {
|
|
_lock.acquire();
|
|
PT(File) f = _root.do_create_file(file);
|
|
_lock.release();
|
|
if (f == (File *)NULL) {
|
|
return false;
|
|
}
|
|
|
|
if (truncate) {
|
|
// Reset to an empty string.
|
|
f->_data.str(string());
|
|
}
|
|
|
|
return new OSubStream(&f->_wrapper, 0, 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::open_append_file
|
|
// Access: Published
|
|
// Description: Works like open_write_file(), but the file is opened
|
|
// in append mode. Like open_write_file, the returned
|
|
// pointer should eventually be passed to
|
|
// close_write_file().
|
|
////////////////////////////////////////////////////////////////////
|
|
ostream *VirtualFileMountRamdisk::
|
|
open_append_file(const Filename &file) {
|
|
_lock.acquire();
|
|
PT(File) f = _root.do_create_file(file);
|
|
_lock.release();
|
|
if (f == (File *)NULL) {
|
|
return false;
|
|
}
|
|
|
|
return new OSubStream(&f->_wrapper, 0, 0, true);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::open_read_write_file
|
|
// Access: Published, Virtual
|
|
// Description: Opens the file for writing. Returns a newly
|
|
// allocated iostream on success (which you should
|
|
// eventually delete when you are done writing).
|
|
// Returns NULL on failure.
|
|
////////////////////////////////////////////////////////////////////
|
|
iostream *VirtualFileMountRamdisk::
|
|
open_read_write_file(const Filename &file, bool truncate) {
|
|
_lock.acquire();
|
|
PT(File) f = _root.do_create_file(file);
|
|
_lock.release();
|
|
if (f == (File *)NULL) {
|
|
return false;
|
|
}
|
|
|
|
return new SubStream(&f->_wrapper, 0, 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::open_read_append_file
|
|
// Access: Published, Virtual
|
|
// Description: Works like open_read_write_file(), but the file is opened
|
|
// in append mode. Like open_read_write_file, the returned
|
|
// pointer should eventually be passed to
|
|
// close_read_write_file().
|
|
////////////////////////////////////////////////////////////////////
|
|
iostream *VirtualFileMountRamdisk::
|
|
open_read_append_file(const Filename &file) {
|
|
_lock.acquire();
|
|
PT(FileBase) f = _root.do_find_file(file);
|
|
_lock.release();
|
|
if (f == (FileBase *)NULL || f->is_directory()) {
|
|
return false;
|
|
}
|
|
|
|
File *f2 = DCAST(File, f);
|
|
return new SubStream(&f2->_wrapper, 0, 0, true);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::get_file_size
|
|
// Access: Published, Virtual
|
|
// Description: Returns the current size on disk (or wherever it is)
|
|
// of the already-open file. Pass in the stream that
|
|
// was returned by open_read_file(); some
|
|
// implementations may require this stream to determine
|
|
// the size.
|
|
////////////////////////////////////////////////////////////////////
|
|
off_t VirtualFileMountRamdisk::
|
|
get_file_size(const Filename &file, istream *stream) const {
|
|
((VirtualFileMountRamdisk *)this)->_lock.acquire();
|
|
PT(FileBase) f = _root.do_find_file(file);
|
|
((VirtualFileMountRamdisk *)this)->_lock.release();
|
|
if (f == (FileBase *)NULL || f->is_directory()) {
|
|
return false;
|
|
}
|
|
|
|
File *f2 = DCAST(File, f);
|
|
return f2->_data.str().length();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::get_file_size
|
|
// Access: Published, Virtual
|
|
// Description: Returns the current size on disk (or wherever it is)
|
|
// of the file before it has been opened.
|
|
////////////////////////////////////////////////////////////////////
|
|
off_t VirtualFileMountRamdisk::
|
|
get_file_size(const Filename &file) const {
|
|
((VirtualFileMountRamdisk *)this)->_lock.acquire();
|
|
PT(FileBase) f = _root.do_find_file(file);
|
|
((VirtualFileMountRamdisk *)this)->_lock.release();
|
|
if (f == (FileBase *)NULL || f->is_directory()) {
|
|
return false;
|
|
}
|
|
|
|
File *f2 = DCAST(File, f);
|
|
return f2->_data.str().length();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::get_timestamp
|
|
// Access: Published, Virtual
|
|
// Description: Returns a time_t value that represents the time the
|
|
// file was last modified, to within whatever precision
|
|
// the operating system records this information (on a
|
|
// Windows95 system, for instance, this may only be
|
|
// accurate to within 2 seconds).
|
|
//
|
|
// If the timestamp cannot be determined, either because
|
|
// it is not supported by the operating system or
|
|
// because there is some error (such as file not found),
|
|
// returns 0.
|
|
////////////////////////////////////////////////////////////////////
|
|
time_t VirtualFileMountRamdisk::
|
|
get_timestamp(const Filename &file) const {
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::scan_directory
|
|
// Access: Public, Virtual
|
|
// Description: Fills the given vector up with the list of filenames
|
|
// that are local to this directory, if the filename is
|
|
// a directory. Returns true if successful, or false if
|
|
// the file is not a directory or cannot be read.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
scan_directory(vector_string &contents, const Filename &dir) const {
|
|
((VirtualFileMountRamdisk *)this)->_lock.acquire();
|
|
PT(FileBase) f = _root.do_find_file(dir);
|
|
if (f == (FileBase *)NULL || !f->is_directory()) {
|
|
((VirtualFileMountRamdisk *)this)->_lock.release();
|
|
return false;
|
|
}
|
|
|
|
Directory *f2 = DCAST(Directory, f);
|
|
bool result = f2->do_scan_directory(contents);
|
|
|
|
((VirtualFileMountRamdisk *)this)->_lock.release();
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::atomic_compare_and_exchange_contents
|
|
// Access: Public, Virtual
|
|
// Description: See Filename::atomic_compare_and_exchange_contents().
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
atomic_compare_and_exchange_contents(const Filename &file, string &orig_contents,
|
|
const string &old_contents,
|
|
const string &new_contents) {
|
|
_lock.acquire();
|
|
PT(FileBase) f = _root.do_find_file(file);
|
|
if (f == (FileBase *)NULL || f->is_directory()) {
|
|
_lock.release();
|
|
return false;
|
|
}
|
|
|
|
bool retval = false;
|
|
File *f2 = DCAST(File, f);
|
|
orig_contents = f2->_data.str();
|
|
if (orig_contents == old_contents) {
|
|
f2->_data.str(new_contents);
|
|
retval = true;
|
|
}
|
|
|
|
_lock.release();
|
|
return retval;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::atomic_read_contents
|
|
// Access: Public, Virtual
|
|
// Description: See Filename::atomic_read_contents().
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::
|
|
atomic_read_contents(const Filename &file, string &contents) const {
|
|
((VirtualFileMountRamdisk *)this)->_lock.acquire();
|
|
PT(FileBase) f = _root.do_find_file(file);
|
|
if (f == (FileBase *)NULL || f->is_directory()) {
|
|
((VirtualFileMountRamdisk *)this)->_lock.release();
|
|
return false;
|
|
}
|
|
|
|
File *f2 = DCAST(File, f);
|
|
contents = f2->_data.str();
|
|
|
|
((VirtualFileMountRamdisk *)this)->_lock.release();
|
|
return true;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::output
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void VirtualFileMountRamdisk::
|
|
output(ostream &out) const {
|
|
out << "VirtualFileMountRamdisk";
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::FileBase::Destructor
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
VirtualFileMountRamdisk::FileBase::
|
|
~FileBase() {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::FileBase::is_directory
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::FileBase::
|
|
is_directory() const {
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::Directory::is_directory
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::Directory::
|
|
is_directory() const {
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::Directory::do_find_file
|
|
// Access: Public
|
|
// Description: Recursively search for the file with the indicated
|
|
// name in this directory hierarchy.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(VirtualFileMountRamdisk::FileBase) VirtualFileMountRamdisk::Directory::
|
|
do_find_file(const string &filename) const {
|
|
size_t slash = filename.find('/');
|
|
if (slash == string::npos) {
|
|
// Search for a file within the local directory.
|
|
FileBase tfile(filename);
|
|
tfile.local_object();
|
|
Files::const_iterator fi = _files.find(&tfile);
|
|
if (fi != _files.end()) {
|
|
return (*fi);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// A nested directory. Search for the directory name, then recurse.
|
|
string dirname = filename.substr(0, slash);
|
|
string remainder = filename.substr(slash + 1);
|
|
FileBase tfile(dirname);
|
|
tfile.local_object();
|
|
Files::const_iterator fi = _files.find(&tfile);
|
|
if (fi != _files.end()) {
|
|
PT(FileBase) file = (*fi);
|
|
if (file->is_directory()) {
|
|
return DCAST(Directory, file.p())->do_find_file(remainder);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::Directory::do_create_file
|
|
// Access: Public
|
|
// Description: Recursively search for the file with the indicated
|
|
// name in this directory hierarchy. If not found,
|
|
// creates a new file.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(VirtualFileMountRamdisk::File) VirtualFileMountRamdisk::Directory::
|
|
do_create_file(const string &filename) {
|
|
size_t slash = filename.find('/');
|
|
if (slash == string::npos) {
|
|
// Search for a file within the local directory.
|
|
FileBase tfile(filename);
|
|
tfile.local_object();
|
|
Files::iterator fi = _files.find(&tfile);
|
|
if (fi != _files.end()) {
|
|
PT(FileBase) file = (*fi);
|
|
if (!file->is_directory()) {
|
|
return DCAST(File, file.p());
|
|
}
|
|
// Cannot create: a directory by the same name already exists.
|
|
return NULL;
|
|
}
|
|
|
|
// Create a new file.
|
|
if (express_cat.is_debug()) {
|
|
express_cat.debug()
|
|
<< "Making ramdisk file " << filename << "\n";
|
|
}
|
|
PT(File) file = new File(filename);
|
|
_files.insert(file.p());
|
|
return file;
|
|
}
|
|
|
|
// A nested directory. Search for the directory name, then recurse.
|
|
string dirname = filename.substr(0, slash);
|
|
string remainder = filename.substr(slash + 1);
|
|
FileBase tfile(dirname);
|
|
tfile.local_object();
|
|
Files::iterator fi = _files.find(&tfile);
|
|
if (fi != _files.end()) {
|
|
PT(FileBase) file = (*fi);
|
|
if (file->is_directory()) {
|
|
return DCAST(Directory, file.p())->do_create_file(remainder);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::Directory::do_make_directory
|
|
// Access: Public
|
|
// Description: Recursively search for the file with the indicated
|
|
// name in this directory hierarchy. If not found,
|
|
// creates a new directory.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(VirtualFileMountRamdisk::Directory) VirtualFileMountRamdisk::Directory::
|
|
do_make_directory(const string &filename) {
|
|
size_t slash = filename.find('/');
|
|
if (slash == string::npos) {
|
|
// Search for a file within the local directory.
|
|
FileBase tfile(filename);
|
|
tfile.local_object();
|
|
Files::iterator fi = _files.find(&tfile);
|
|
if (fi != _files.end()) {
|
|
PT(FileBase) file = (*fi);
|
|
if (file->is_directory()) {
|
|
return DCAST(Directory, file.p());
|
|
}
|
|
// Cannot create: a file by the same name already exists.
|
|
return NULL;
|
|
}
|
|
|
|
// Create a new directory.
|
|
if (express_cat.is_debug()) {
|
|
express_cat.debug()
|
|
<< "Making ramdisk directory " << filename << "\n";
|
|
}
|
|
PT(Directory) file = new Directory(filename);
|
|
_files.insert(file.p());
|
|
return file;
|
|
}
|
|
|
|
// A nested directory. Search for the directory name, then recurse.
|
|
string dirname = filename.substr(0, slash);
|
|
string remainder = filename.substr(slash + 1);
|
|
FileBase tfile(dirname);
|
|
tfile.local_object();
|
|
Files::iterator fi = _files.find(&tfile);
|
|
if (fi != _files.end()) {
|
|
PT(FileBase) file = (*fi);
|
|
if (file->is_directory()) {
|
|
return DCAST(Directory, file.p())->do_make_directory(remainder);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::Directory::do_delete_file
|
|
// Access: Public
|
|
// Description: Recursively search for the file with the indicated
|
|
// name in this directory hierarchy, and removes it.
|
|
// Returns the removed FileBase object.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(VirtualFileMountRamdisk::FileBase) VirtualFileMountRamdisk::Directory::
|
|
do_delete_file(const string &filename) {
|
|
size_t slash = filename.find('/');
|
|
if (slash == string::npos) {
|
|
// Search for a file within the local directory.
|
|
FileBase tfile(filename);
|
|
tfile.local_object();
|
|
Files::iterator fi = _files.find(&tfile);
|
|
if (fi != _files.end()) {
|
|
PT(FileBase) file = (*fi);
|
|
if (file->is_directory()) {
|
|
Directory *dir = DCAST(Directory, file.p());
|
|
if (!dir->_files.empty()) {
|
|
// Can't delete a nonempty directory.
|
|
return NULL;
|
|
}
|
|
}
|
|
_files.erase(fi);
|
|
return file;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// A nested directory. Search for the directory name, then recurse.
|
|
string dirname = filename.substr(0, slash);
|
|
string remainder = filename.substr(slash + 1);
|
|
FileBase tfile(dirname);
|
|
tfile.local_object();
|
|
Files::iterator fi = _files.find(&tfile);
|
|
if (fi != _files.end()) {
|
|
PT(FileBase) file = (*fi);
|
|
if (file->is_directory()) {
|
|
return DCAST(Directory, file.p())->do_delete_file(remainder);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: VirtualFileMountRamdisk::Directory::do_scan_directory
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool VirtualFileMountRamdisk::Directory::
|
|
do_scan_directory(vector_string &contents) const {
|
|
Files::const_iterator fi;
|
|
for (fi = _files.begin(); fi != _files.end(); ++fi) {
|
|
FileBase *file = (*fi);
|
|
contents.push_back(file->_basename);
|
|
}
|
|
|
|
return true;
|
|
}
|