initial virtual file system

This commit is contained in:
David Rose 2002-08-03 20:55:57 +00:00
parent 410a8f423a
commit 255bcd1299
32 changed files with 2409 additions and 117 deletions

View File

@ -123,13 +123,13 @@ run() {
_subfile_length = _multifile.get_subfile_length(_subfile_index);
_subfile_pos = 0;
_read = &_multifile.open_read_subfile(_subfile_index);
_read = _multifile.open_read_subfile(_subfile_index);
} else if (_subfile_pos >= _subfile_length) {
// Time to close this subfile.
_multifile.close_subfile();
_write.close();
delete _read;
_read = (istream *)NULL;
_write.close();
_subfile_index++;
} else {
@ -195,7 +195,10 @@ cleanup() {
return;
}
if (_read != (istream *)NULL) {
delete _read;
_read = (istream *)NULL;
}
_multifile.close();
_write.close();
_read = (istream *)NULL;
}

View File

@ -17,6 +17,17 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: Multifile::get_multifile_name
// Access: Published
// Description: Returns the filename of the Multifile, if it is
// available.
////////////////////////////////////////////////////////////////////
INLINE const Filename &Multifile::
get_multifile_name() const {
return _multifile_name;
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::is_read_valid
// Access: Published
@ -26,8 +37,7 @@
////////////////////////////////////////////////////////////////////
INLINE bool Multifile::
is_read_valid() const {
return (_read != (istream *)NULL && !_read->fail() &&
_open_subfile == (Subfile *)NULL);
return (_read != (istream *)NULL && !_read->fail());
}
////////////////////////////////////////////////////////////////////
@ -39,8 +49,7 @@ is_read_valid() const {
////////////////////////////////////////////////////////////////////
INLINE bool Multifile::
is_write_valid() const {
return (_write != (ostream *)NULL && !_write->fail() &&
_open_subfile == (Subfile *)NULL);
return (_write != (ostream *)NULL && !_write->fail());
}
////////////////////////////////////////////////////////////////////
@ -51,39 +60,7 @@ is_write_valid() const {
////////////////////////////////////////////////////////////////////
INLINE bool Multifile::
needs_repack() const {
return _needs_repack;
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::set_scale_factor
// Access: Published
// Description: Changes the internal scale factor for this Multifile.
//
// This is normally 1, but it may be set to any
// arbitrary value (greater than zero) to support
// Multifile archives that exceed 4GB, if necessary.
// (Individual subfiles may still not exceed 4GB.)
//
// All addresses within the file are rounded up to the
// next multiple of _scale_factor, and zeros are written
// to the file to fill the resulting gaps. Then the
// address is divided by _scale_factor and written out
// as a 32-bit integer. Thus, setting a scale factor of
// 2 supports up to 8GB files, 3 supports 12GB files,
// etc.
//
// Calling this function on an already-existing
// Multifile forces an immediate repack() operation.
////////////////////////////////////////////////////////////////////
INLINE void Multifile::
set_scale_factor(size_t scale_factor) {
nassertv(scale_factor != (size_t)0);
if (_scale_factor != scale_factor) {
_scale_factor = scale_factor;
if (_next_index != (streampos)0) {
repack();
}
}
return _needs_repack || (_scale_factor != _new_scale_factor);
}
////////////////////////////////////////////////////////////////////
@ -94,7 +71,7 @@ set_scale_factor(size_t scale_factor) {
////////////////////////////////////////////////////////////////////
INLINE size_t Multifile::
get_scale_factor() const {
return _scale_factor;
return _new_scale_factor;
}
////////////////////////////////////////////////////////////////////

View File

@ -84,9 +84,9 @@ Multifile() {
_last_index = 0;
_needs_repack = false;
_scale_factor = 1;
_new_scale_factor = 1;
_file_major_ver = 0;
_file_minor_ver = 0;
_open_subfile = (Subfile *)NULL;
}
////////////////////////////////////////////////////////////////////
@ -99,6 +99,26 @@ Multifile::
close();
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::Copy Constructor
// Access: Private
// Description: Don't try to copy Multifiles.
////////////////////////////////////////////////////////////////////
Multifile::
Multifile(const Multifile &copy) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::Copy Assignment Operator
// Access: Private
// Description: Don't try to copy Multifiles.
////////////////////////////////////////////////////////////////////
void Multifile::
operator = (const Multifile &copy) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::open_read
// Access: Published
@ -192,14 +212,21 @@ open_read_write(const Filename &multifile_name) {
////////////////////////////////////////////////////////////////////
void Multifile::
close() {
close_subfile();
flush();
if (_new_scale_factor != _scale_factor) {
// If we have changed the scale factor recently, we need to force
// a repack.
repack();
} else {
flush();
}
_read = (istream *)NULL;
_write = (ostream *)NULL;
_next_index = 0;
_last_index = 0;
_needs_repack = false;
_scale_factor = 1;
_new_scale_factor = 1;
_file_major_ver = 0;
_file_minor_ver = 0;
@ -211,6 +238,49 @@ close() {
clear_subfiles();
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::set_scale_factor
// Access: Published
// Description: Changes the internal scale factor for this Multifile.
//
// This is normally 1, but it may be set to any
// arbitrary value (greater than zero) to support
// Multifile archives that exceed 4GB, if necessary.
// (Individual subfiles may still not exceed 4GB.)
//
// All addresses within the file are rounded up to the
// next multiple of _scale_factor, and zeros are written
// to the file to fill the resulting gaps. Then the
// address is divided by _scale_factor and written out
// as a 32-bit integer. Thus, setting a scale factor of
// 2 supports up to 8GB files, 3 supports 12GB files,
// etc.
//
// Calling this function on an already-existing
// Multifile will have no immediate effect until a
// future call to repack() or close() (or until the
// Multifile is destructed).
////////////////////////////////////////////////////////////////////
void Multifile::
set_scale_factor(size_t scale_factor) {
nassertv(is_write_valid());
nassertv(scale_factor != (size_t)0);
if (_next_index == (streampos)0) {
// If it's a brand new Multifile, we can go ahead and set it
// immediately.
_scale_factor = scale_factor;
} else {
// Otherwise, we'd better have read access so we can repack it
// later.
nassertv(is_read_valid());
}
// Setting the _new_scale_factor different from the _scale_factor
// will force a repack operation on close.
_new_scale_factor = scale_factor;
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::add_subfile
// Access: Published
@ -378,6 +448,12 @@ flush() {
////////////////////////////////////////////////////////////////////
bool Multifile::
repack() {
if (_next_index == (streampos)0) {
// If the Multifile hasn't yet been written, this is really just a
// flush operation.
return flush();
}
nassertr(is_write_valid() && is_read_valid(), false);
nassertr(!_multifile_name.empty(), false);
@ -407,6 +483,7 @@ repack() {
copy(_subfiles.begin(), _subfiles.end(), back_inserter(_new_subfiles));
_next_index = 0;
_last_index = 0;
_scale_factor = _new_scale_factor;
// And we write our contents to our new temporary file.
_write = &temp;
@ -535,14 +612,14 @@ read_subfile(int index, Datagram &data) {
nassertv(index >= 0 && index < (int)_subfiles.size());
data.clear();
istream &in = open_read_subfile(index);
int byte = in.get();
while (!in.eof() && !in.fail()) {
istream *in = open_read_subfile(index);
int byte = in->get();
while (!in->eof() && !in->fail()) {
data.add_int8(byte);
byte = in.get();
byte = in->get();
}
bool failed = in.fail();
close_subfile();
bool failed = in->fail();
delete in;
nassertv(!failed);
}
@ -570,6 +647,31 @@ extract_subfile(int index, const Filename &filename) {
return extract_subfile_to(index, out);
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void Multifile::
output(ostream &out) const {
out << "Multifile " << _multifile_name << ", " << get_num_subfiles()
<< " subfiles.\n";
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::ls
// Access: Published
// Description: Shows a list of all subfiles within the Multifile.
////////////////////////////////////////////////////////////////////
void Multifile::
ls(ostream &out) const {
int num_subfiles = get_num_subfiles();
for (int i = 0; i < num_subfiles; i++) {
string subfile_name = get_subfile_name(i);
out << subfile_name << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::open_read
// Access: Public
@ -662,16 +764,16 @@ extract_subfile_to(int index, ostream &out) {
nassertr(is_read_valid(), false);
nassertr(index >= 0 && index < (int)_subfiles.size(), false);
istream &in = open_read_subfile(index);
istream *in = open_read_subfile(index);
int byte = in.get();
while (!in.fail() && !in.eof()) {
int byte = in->get();
while (!in->fail() && !in->eof()) {
out.put(byte);
byte = in.get();
byte = in->get();
}
bool failed = (in.fail() && !in.eof());
close_subfile();
bool failed = (in->fail() && !in->eof());
delete in;
nassertr(!failed, false);
return (!out.fail());
@ -682,64 +784,47 @@ extract_subfile_to(int index, ostream &out) {
// Access: Public
// Description: Returns an istream that may be used to read the
// indicated subfile. You may seek() within this
// istream to your heart's content; even though it is
// probably a reference to the already-opened fstream of
// the Multifile itself, byte 0 appears to be the
// beginning of the subfile and EOF appears to be the
// end of the subfile.
// istream to your heart's content; even though it will
// be a reference to the already-opened fstream of the
// Multifile itself, byte 0 appears to be the beginning
// of the subfile and EOF appears to be the end of the
// subfile.
//
// It is not valid to perform any additional operations
// on this Multifile until close_subfile() has
// subsequently been called.
// The returned istream will have been allocated via
// new; you should delete it when you are finished
// reading the subfile.
//
// Any future calls to repack() or close() (or the
// Multifile destructor) will invalidate all currently
// open subfile pointers.
//
// The return value will never be NULL. If there is a
// problem, an unopened fstream is returned.
////////////////////////////////////////////////////////////////////
istream &Multifile::
istream *Multifile::
open_read_subfile(int index) {
#ifndef NDEBUG
static ifstream empty_stream;
nassertr(_open_subfile == (Subfile *)NULL, empty_stream);
nassertr(is_read_valid(), empty_stream);
nassertr(index >= 0 && index < (int)_subfiles.size(), empty_stream);
#endif
_open_subfile = _subfiles[index];
nassertr(is_read_valid(), new fstream);
nassertr(index >= 0 && index < (int)_subfiles.size(), new fstream);
Subfile *subfile = _subfiles[index];
if (_open_subfile->_source != (istream *)NULL) {
// The subfile has not yet been incorporated, and it is defined
// with an istream; return the istream directly.
_open_subfile->_source->seekg(0);
return *_open_subfile->_source;
if (subfile->_source != (istream *)NULL ||
!subfile->_source_filename.empty()) {
// The subfile has not yet been copied into the physical
// Multifile. Force a flush operation to incorporate it.
flush();
// That shouldn't change the subfile index or delete the subfile
// pointer.
nassertr(subfile == _subfiles[index], new fstream);
}
if (!_open_subfile->_source_filename.empty()) {
// The subfile has not yet been incorporated, and it is defined
// with a filename; open the filename and return that.
_open_subfile->_source_filename.open_read(_subfile_fstream);
return _subfile_fstream;
}
// The subfile has been incorporated; return an ISubStream object
// that references into the open Multifile istream.
nassertr(_open_subfile->_data_start != (streampos)0, empty_stream);
_subfile_substream.open(_read, _open_subfile->_data_start,
_open_subfile->_data_start + (streampos)_open_subfile->_data_length);
return _subfile_substream;
}
////////////////////////////////////////////////////////////////////
// Function: Multifile::close_subfile
// Access: Public
// Description: "Closes" the istream that was returned via a previous
// call to open_read_subfile(), and makes other
// operations on the Multifile valid once more.
////////////////////////////////////////////////////////////////////
void Multifile::
close_subfile() {
if (_open_subfile != (Subfile *)NULL &&
_open_subfile->_source != (istream *)NULL) {
_open_subfile->_source->seekg(0);
}
_open_subfile = (Subfile *)NULL;
_subfile_fstream.close();
_subfile_substream.close();
// Return an ISubStream object that references into the open
// Multifile istream.
nassertr(subfile->_data_start != (streampos)0, new fstream);
ISubStream *stream = new ISubStream;
stream->open(_read, subfile->_data_start,
subfile->_data_start + (streampos)subfile->_data_length);
return stream;
}
////////////////////////////////////////////////////////////////////
@ -850,6 +935,7 @@ read_index() {
_file_major_ver = dgi.get_int16();
_file_minor_ver = dgi.get_int16();
_scale_factor = dgi.get_uint32();
_new_scale_factor = _scale_factor;
if (_file_major_ver != _current_major_ver ||
(_file_major_ver == _current_major_ver &&

View File

@ -38,16 +38,23 @@ PUBLISHED:
Multifile();
~Multifile();
private:
Multifile(const Multifile &copy);
void operator = (const Multifile &copy);
PUBLISHED:
bool open_read(const Filename &multifile_name);
bool open_write(const Filename &multifile_name);
bool open_read_write(const Filename &multifile_name);
void close();
INLINE const Filename &get_multifile_name() const;
INLINE bool is_read_valid() const;
INLINE bool is_write_valid() const;
INLINE bool needs_repack() const;
INLINE void set_scale_factor(size_t scale_factor);
void set_scale_factor(size_t scale_factor);
INLINE size_t get_scale_factor() const;
bool add_subfile(const string &subfile_name, const Filename &filename);
@ -63,6 +70,9 @@ PUBLISHED:
void read_subfile(int index, Datagram &datagram);
bool extract_subfile(int index, const Filename &filename);
void output(ostream &out) const;
void ls(ostream &out = cout) const;
public:
// Special interfaces to work with iostreams, not necessarily files.
bool open_read(istream *multifile_stream);
@ -71,8 +81,7 @@ public:
bool add_subfile(const string &subfile_name, istream *subfile_data);
bool extract_subfile_to(int index, ostream &out);
istream &open_read_subfile(int index);
void close_subfile();
istream *open_read_subfile(int index);
private:
enum SubfileFlags {
@ -129,6 +138,7 @@ private:
bool _needs_repack;
size_t _scale_factor;
size_t _new_scale_factor;
ifstream _read_file;
ofstream _write_file;
@ -138,11 +148,6 @@ private:
int _file_major_ver;
int _file_minor_ver;
// These are used to open a subfile for reading.
Subfile *_open_subfile;
ifstream _subfile_fstream;
ISubStream _subfile_substream;
static const char _header[];
static const size_t _header_size;
static const int _current_major_ver;

View File

@ -49,6 +49,7 @@ SubStreamBuf() {
////////////////////////////////////////////////////////////////////
SubStreamBuf::
~SubStreamBuf() {
close();
}
////////////////////////////////////////////////////////////////////

View File

@ -46,6 +46,12 @@
typedWritableReferenceCount.h updateSeq.I updateSeq.h \
vector_double.h vector_float.h vector_typedWritable.h \
vector_ushort.h vector_writable.h \
virtualFileComposite.h virtualFileComposite.I virtualFile.h \
virtualFile.I virtualFileList.I virtualFileList.h virtualFileMount.h \
virtualFileMount.I virtualFileMountMultifile.h \
virtualFileMountMultifile.I virtualFileMountSystem.h \
virtualFileMountSystem.I virtualFileSimple.h virtualFileSimple.I \
virtualFileSystem.h virtualFileSystem.I \
writableConfigurable.h \
writableParam.I writableParam.h
@ -75,6 +81,10 @@
vector_double.cxx vector_float.cxx \
vector_typedWritable.cxx \
vector_ushort.cxx vector_writable.cxx \
virtualFileComposite.cxx virtualFile.cxx virtualFileList.cxx \
virtualFileMount.cxx \
virtualFileMountMultifile.cxx virtualFileMountSystem.cxx \
virtualFileSimple.cxx virtualFileSystem.cxx \
writableConfigurable.cxx writableParam.cxx
#define INSTALL_HEADERS \
@ -113,6 +123,12 @@
typedWritableReferenceCount.h updateSeq.I updateSeq.h \
vector_double.h vector_float.h vector_typedWritable.h \
vector_ushort.h vector_writable.h \
virtualFileComposite.h virtualFileComposite.I virtualFile.h \
virtualFile.I virtualFileList.I virtualFileList.h virtualFileMount.h \
virtualFileMount.I virtualFileMountMultifile.h \
virtualFileMountMultifile.I virtualFileMountSystem.h \
virtualFileMountSystem.I virtualFileSimple.h virtualFileSimple.I \
virtualFileSystem.h virtualFileSystem.I \
writableConfigurable.h writableParam.I \
writableParam.h

View File

@ -30,6 +30,12 @@
#include "datagram.h"
#include "typedWritable.h"
#include "typedWritableReferenceCount.h"
#include "virtualFileComposite.h"
#include "virtualFile.h"
#include "virtualFileMount.h"
#include "virtualFileMountMultifile.h"
#include "virtualFileMountSystem.h"
#include "virtualFileSimple.h"
#include "writableParam.h"
#include "bamReaderParam.h"
#include "writableConfigurable.h"
@ -57,6 +63,12 @@ ConfigureFn(config_util) {
WritableParam::init_type();
BamReaderParam::init_type();
TypedWritableReferenceCount::init_type();
VirtualFileComposite::init_type();
VirtualFile::init_type();
VirtualFileMount::init_type();
VirtualFileMountMultifile::init_type();
VirtualFileMountSystem::init_type();
VirtualFileSimple::init_type();
WritableConfigurable::init_type();
}

View File

@ -16,6 +16,14 @@
#include "vector_typedWritable.cxx"
#include "vector_ushort.cxx"
#include "vector_writable.cxx"
#include "virtualFile.cxx"
#include "virtualFileComposite.cxx"
#include "virtualFileList.cxx"
#include "virtualFileMount.cxx"
#include "virtualFileMountMultifile.cxx"
#include "virtualFileMountSystem.cxx"
#include "virtualFileSimple.cxx"
#include "virtualFileSystem.cxx"
#include "writableConfigurable.cxx"
#include "writableParam.cxx"

View File

@ -0,0 +1,35 @@
// Filename: virtualFile.I
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VirtualFile::
VirtualFile() {
}
INLINE ostream &
operator << (ostream &out, const VirtualFile &file) {
file.output(out);
return out;
}

View File

@ -0,0 +1,233 @@
// Filename: virtualFile.cxx
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "virtualFile.h"
#include "virtualFileSystem.h"
#include "virtualFileList.h"
#include "config_util.h"
TypeHandle VirtualFile::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::is_directory
// Access: Published, Virtual
// Description: Returns true if this file represents a directory (and
// scan_directory() may be called), false otherwise.
////////////////////////////////////////////////////////////////////
bool VirtualFile::
is_directory() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::is_regular_file
// Access: Published, Virtual
// Description: Returns true if this file represents a regular file
// (and read_file() may be called), false otherwise.
////////////////////////////////////////////////////////////////////
bool VirtualFile::
is_regular_file() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::read_file
// Access: Published
// Description: Fills up the indicated Datagram with the contents of
// the file, if it is a regular file. Returns true on
// success, false otherwise.
////////////////////////////////////////////////////////////////////
bool VirtualFile::
read_file(Datagram &data) const {
data.clear();
istream *in = open_read_file();
if (in == (istream *)NULL) {
util_cat.info()
<< "Unable to read " << get_filename() << "\n";
return false;
}
int byte = in->get();
while (!in->eof() && !in->fail()) {
data.add_int8(byte);
byte = in->get();
}
bool failed = in->fail();
delete in;
if (failed) {
util_cat.info()
<< "Error while reading " << get_filename() << "\n";
}
return failed;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::open_read_file
// Access: Published, Virtual
// Description: Opens the file for reading. Returns a newly
// allocated istream on success (which you should
// eventually delete when you are done reading).
// Returns NULL on failure.
////////////////////////////////////////////////////////////////////
istream *VirtualFile::
open_read_file() const {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::scan_directory
// Access: Published
// Description: If the file represents a directory (that is,
// is_directory() returns true), this returns the list
// of files within the directory at the current time.
// Returns NULL if the file is not a directory or if the
// directory cannot be read.
////////////////////////////////////////////////////////////////////
PT(VirtualFileList) VirtualFile::
scan_directory() const {
// First, we have to make sure there aren't any mount points attached
// under this directory. These will override any local filenames.
VirtualFileSystem *file_system = get_file_system();
Filename this_filename = get_filename();
vector_string mount_points_flat;
file_system->scan_mount_points(mount_points_flat, this_filename);
// Copy the set of nested mount points to a sorted list so we can
// search it quickly.
ov_set<string> mount_points;
copy(mount_points_flat.begin(), mount_points_flat.end(),
back_inserter(mount_points));
mount_points.sort();
PT(VirtualFileList) file_list = new VirtualFileList;
// Each of those mount points maps to a directory root or something
// from the file system.
ov_set<string>::const_iterator mi;
for (mi = mount_points.begin(); mi != mount_points.end(); ++mi) {
const string &basename = (*mi);
Filename filename(this_filename, basename);
PT(VirtualFile) file = file_system->get_file(filename);
file_list->add_file(file);
}
// Now, get the actual local files in this directory.
vector_string names;
if (!scan_local_directory(file_list, mount_points)) {
// Not a directory, or unable to read directory.
if (file_list->get_num_files() == 0) {
return NULL;
}
// We couldn't read the physical directory, but we do have some
// mounted files to return.
return file_list;
}
return file_list;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void VirtualFile::
output(ostream &out) const {
out << get_filename();
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::ls
// Access: Published
// Description: If the file represents a directory, lists its
// contents.
////////////////////////////////////////////////////////////////////
void VirtualFile::
ls(ostream &out) const {
CPT(VirtualFileList) contents = scan_directory();
if (contents == NULL) {
if (!is_directory()) {
out << get_filename() << " is not a directory.\n";
} else {
out << get_filename() << " cannot be read.\n";
}
return;
}
int num_files = contents->get_num_files();
for (int i = 0; i < num_files; i++) {
VirtualFile *file = contents->get_file(i);
out << file->get_filename().get_basename() << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::ls_all
// Access: Published
// Description: If the file represents a directory, recursively lists
// its contents and those of all subdirectories.
////////////////////////////////////////////////////////////////////
void VirtualFile::
ls_all(ostream &out) const {
if (!is_directory()) {
out << get_filename() << " is not a directory.\n";
} else {
r_ls_all(out, get_filename());
}
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::scan_local_directory
// Access: Protected, Virtual
// Description: Fills file_list up with the list of files that are
// within this directory, excluding those whose
// basenames are listed in mount_points. Returns true
// if successful, false if the file is not a directory
// or the directory cannot be read.
////////////////////////////////////////////////////////////////////
bool VirtualFile::
scan_local_directory(VirtualFileList *, const ov_set<string> &) const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFile::r_ls_all
// Access: Private
// Description: The recursive implementation of ls_all().
////////////////////////////////////////////////////////////////////
void VirtualFile::
r_ls_all(ostream &out, const Filename &root) const {
CPT(VirtualFileList) contents = scan_directory();
if (contents == NULL) {
return;
}
int num_files = contents->get_num_files();
for (int i = 0; i < num_files; i++) {
VirtualFile *file = contents->get_file(i);
Filename filename = file->get_filename();
filename.make_relative_to(root);
out << filename << "\n";
if (file->is_directory()) {
file->r_ls_all(out, root);
}
}
}

View File

@ -0,0 +1,90 @@
// Filename: virtualFile.h
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef VIRTUALFILE_H
#define VIRTUALFILE_H
#include "pandabase.h"
#include "filename.h"
#include "pointerTo.h"
#include "typedReferenceCount.h"
#include "ordered_vector.h"
class VirtualFileMount;
class VirtualFileList;
class VirtualFileSystem;
////////////////////////////////////////////////////////////////////
// Class : VirtualFile
// Description : The abstract base class for a file or directory
// within the VirtualFileSystem.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VirtualFile : public TypedReferenceCount {
public:
INLINE VirtualFile();
PUBLISHED:
virtual VirtualFileSystem *get_file_system() const=0;
virtual Filename get_filename() const=0;
virtual bool is_directory() const;
virtual bool is_regular_file() const;
bool read_file(Datagram &data) const;
virtual istream *open_read_file() const;
PT(VirtualFileList) scan_directory() const;
void output(ostream &out) const;
void ls(ostream &out = cout) const;
void ls_all(ostream &out = cout) const;
protected:
virtual bool scan_local_directory(VirtualFileList *file_list,
const ov_set<string> &mount_points) const;
private:
void r_ls_all(ostream &out, const Filename &root) const;
public:
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedReferenceCount::init_type();
register_type(_type_handle, "VirtualFile",
TypedReferenceCount::get_class_type());
}
private:
static TypeHandle _type_handle;
friend class VirtualFileComposite;
};
INLINE ostream &operator << (ostream &out, const VirtualFile &file);
#include "virtualFile.I"
#endif

View File

@ -0,0 +1,46 @@
// Filename: virtualFileComposite.I
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VirtualFileComposite::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VirtualFileComposite::
VirtualFileComposite(VirtualFileSystem *file_system, const Filename &filename) :
_file_system(file_system),
_filename(filename)
{
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileComposite::add_component
// Access: Public
// Description: Adds one more component to the composite directory.
// The component should be a directory and the file
// system and filename should match the composite.
////////////////////////////////////////////////////////////////////
INLINE void VirtualFileComposite::
add_component(VirtualFile *file) {
nassertv(file->is_directory());
nassertv(file->get_file_system() == _file_system);
nassertv(file->get_filename() == _filename);
_components.push_back(file);
}

View File

@ -0,0 +1,78 @@
// Filename: virtualFileComposite.cxx
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "virtualFileComposite.h"
TypeHandle VirtualFileComposite::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: VirtualFileComposite::get_file_system
// Access: Published, Virtual
// Description: Returns the VirtualFileSystem this file is associated
// with.
////////////////////////////////////////////////////////////////////
VirtualFileSystem *VirtualFileComposite::
get_file_system() const {
return _file_system;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileComposite::get_filename
// Access: Published, Virtual
// Description: Returns the full pathname to this file within the
// virtual file system.
////////////////////////////////////////////////////////////////////
Filename VirtualFileComposite::
get_filename() const {
return _filename;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileComposite::is_directory
// Access: Published, Virtual
// Description: Returns true if this file represents a directory (and
// scan_directory() may be called), false otherwise.
////////////////////////////////////////////////////////////////////
bool VirtualFileComposite::
is_directory() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileComposite::scan_local_directory
// Access: Protected, Virtual
// Description: Fills file_list up with the list of files that are
// within this directory, excluding those whose
// basenames are listed in mount_points. Returns true
// if successful, false if the file is not a directory
// or the directory cannot be read.
////////////////////////////////////////////////////////////////////
bool VirtualFileComposite::
scan_local_directory(VirtualFileList *file_list,
const ov_set<string> &mount_points) const {
bool any_ok = false;
Components::const_iterator ci;
for (ci = _components.begin(); ci != _components.end(); ++ci) {
if ((*ci)->scan_local_directory(file_list, mount_points)) {
any_ok = true;
}
}
return any_ok;
}

View File

@ -0,0 +1,79 @@
// Filename: virtualFileComposite.h
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef VIRTUALFILECOMPOSITE_H
#define VIRTUALFILECOMPOSITE_H
#include "pandabase.h"
#include "virtualFile.h"
////////////////////////////////////////////////////////////////////
// Class : VirtualFileComposite
// Description : A composite directory within the VirtualFileSystem:
// this maps to more than one directory on different
// mount points. The resulting directory appears to be
// the union of all the individual simple directories.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VirtualFileComposite : public VirtualFile {
public:
INLINE VirtualFileComposite(VirtualFileSystem *file_system,
const Filename &filename);
INLINE void add_component(VirtualFile *file);
virtual VirtualFileSystem *get_file_system() const;
virtual Filename get_filename() const;
virtual bool is_directory() const;
protected:
virtual bool scan_local_directory(VirtualFileList *file_list,
const ov_set<string> &mount_points) const;
private:
VirtualFileSystem *_file_system;
Filename _filename;
typedef pvector< PT(VirtualFile) > Components;
Components _components;
public:
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
PUBLISHED:
static TypeHandle get_class_type() {
return _type_handle;
}
public:
static void init_type() {
VirtualFile::init_type();
register_type(_type_handle, "VirtualFileComposite",
VirtualFile::get_class_type());
}
private:
static TypeHandle _type_handle;
};
#include "virtualFileComposite.I"
#endif

View File

@ -0,0 +1,67 @@
// Filename: virtualFileList.I
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VirtualFileList::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VirtualFileList::
VirtualFileList() {
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileList::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE VirtualFileList::
~VirtualFileList() {
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileList::add_file
// Access: Public
// Description: Adds a new file to the list.
////////////////////////////////////////////////////////////////////
INLINE void VirtualFileList::
add_file(VirtualFile *file) {
_files.push_back(file);
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileList::get_num_files
// Access: Published
// Description: Returns the number of files in the list.
////////////////////////////////////////////////////////////////////
INLINE int VirtualFileList::
get_num_files() const {
return _files.size();
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileList::get_file
// Access: Published
// Description: Returns the nth file in the list.
////////////////////////////////////////////////////////////////////
INLINE VirtualFile *VirtualFileList::
get_file(int n) const {
nassertr(n >= 0 && n < (int)_files.size(), NULL);
return _files[n];
}

View File

@ -0,0 +1,19 @@
// Filename: virtualFileList.cxx
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "virtualFileList.h"

View File

@ -0,0 +1,53 @@
// Filename: virtualFileList.h
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef VIRTUALFILELIST_H
#define VIRTUALFILELIST_H
#include "pandabase.h"
#include "virtualFile.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : VirtualFileList
// Description : A list of VirtualFiles, as returned by
// VirtualDirectory::scan().
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VirtualFileList : public ReferenceCount {
public:
INLINE VirtualFileList();
PUBLISHED:
INLINE ~VirtualFileList();
public:
INLINE void add_file(VirtualFile *file);
PUBLISHED:
INLINE int get_num_files() const;
INLINE VirtualFile *get_file(int n) const;
private:
typedef pvector< PT(VirtualFile) > Files;
Files _files;
};
#include "virtualFileList.I"
#endif

View File

@ -0,0 +1,88 @@
// Filename: virtualFileMount.I
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMount::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VirtualFileMount::
VirtualFileMount(VirtualFileSystem *file_system,
const Filename &physical_filename,
const Filename &mount_point,
int mount_flags) :
_file_system(file_system),
_physical_filename(physical_filename),
_mount_point(mount_point),
_mount_flags(mount_flags)
{
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMount::get_file_system
// Access: Public
// Description: Returns the file system this mount object is attached
// to.
////////////////////////////////////////////////////////////////////
INLINE VirtualFileSystem *VirtualFileMount::
get_file_system() const {
return _file_system;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMount::get_physical_filename
// Access: Public
// Description: Returns the name of the source file on the OS
// filesystem of the directory or file that is mounted.
////////////////////////////////////////////////////////////////////
INLINE const Filename &VirtualFileMount::
get_physical_filename() const {
return _physical_filename;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMount::get_mount_point
// Access: Public
// Description: Returns the name of the directory within the virtual
// file system that this mount object is attached to.
// This directory name will end with a slash.
////////////////////////////////////////////////////////////////////
INLINE const Filename &VirtualFileMount::
get_mount_point() const {
return _mount_point;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMount::get_mount_flags
// Access: Public
// Description: Returns the set of flags passed by the user to the
// VirtualFileSystem::mount() command.
////////////////////////////////////////////////////////////////////
INLINE int VirtualFileMount::
get_mount_flags() const {
return _mount_flags;
}
INLINE ostream &
operator << (ostream &out, const VirtualFileMount &mount) {
mount.output(out);
return out;
}

View File

@ -0,0 +1,51 @@
// Filename: virtualFileMount.cxx
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "virtualFileMount.h"
TypeHandle VirtualFileMount::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMount::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
VirtualFileMount::
~VirtualFileMount() {
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMount::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void VirtualFileMount::
output(ostream &out) const {
out << get_physical_filename();
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMount::write
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void VirtualFileMount::
write(ostream &out) const {
out << get_physical_filename() << " on /" << get_mount_point() << "\n";
}

View File

@ -0,0 +1,90 @@
// Filename: virtualFileMount.h
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef VIRTUALFILEMOUNT_H
#define VIRTUALFILEMOUNT_H
#include "pandabase.h"
#include "filename.h"
#include "pointerTo.h"
#include "typedObject.h"
class VirtualFileSystem;
////////////////////////////////////////////////////////////////////
// Class : VirtualFileMount
// Description : The abstract base class for a mount definition used
// within a VirtualFileSystem. Normally users don't
// need to monkey with this class directly.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VirtualFileMount : public TypedObject {
public:
INLINE VirtualFileMount(VirtualFileSystem *file_system,
const Filename &physical_filename,
const Filename &mount_point,
int mount_flags);
virtual ~VirtualFileMount();
INLINE VirtualFileSystem *get_file_system() const;
INLINE const Filename &get_physical_filename() const;
INLINE const Filename &get_mount_point() const;
INLINE int get_mount_flags() const;
virtual bool has_file(const Filename &file) const=0;
virtual bool is_directory(const Filename &file) const=0;
virtual bool is_regular_file(const Filename &file) const=0;
virtual istream *open_read_file(const Filename &file) const=0;
virtual bool scan_directory(vector_string &contents,
const Filename &dir) const=0;
virtual void output(ostream &out) const;
virtual void write(ostream &out) const;
protected:
VirtualFileSystem *_file_system;
Filename _physical_filename;
Filename _mount_point;
int _mount_flags;
public:
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedObject::init_type();
register_type(_type_handle, "VirtualFileMount",
TypedObject::get_class_type());
}
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const VirtualFileMount &mount);
#include "virtualFileMount.I"
#endif

View File

@ -0,0 +1,45 @@
// Filename: virtualFileMountMultifile.I
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountMultifile::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VirtualFileMountMultifile::
VirtualFileMountMultifile(VirtualFileSystem *file_system,
Multifile *multifile,
const Filename &mount_point,
int mount_flags) :
VirtualFileMount(file_system, multifile->get_multifile_name(),
mount_point, mount_flags),
_multifile(multifile)
{
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountMultifile::get_multifile
// Access: Public
// Description: Returns the Multifile pointer that this mount object
// is based on.
////////////////////////////////////////////////////////////////////
INLINE Multifile *VirtualFileMountMultifile::
get_multifile() const {
return _multifile;
}

View File

@ -0,0 +1,99 @@
// Filename: virtualFileMountMultifile.cxx
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "virtualFileMountMultifile.h"
#include "virtualFileSystem.h"
TypeHandle VirtualFileMountMultifile::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountMultifile::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
VirtualFileMountMultifile::
~VirtualFileMountMultifile() {
if ((_mount_flags & VirtualFileSystem::MF_owns_pointer) != 0) {
// Delete the _multifile pointer if we own it.
nassertv(_multifile != (Multifile *)NULL);
delete _multifile;
}
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountMultifile::has_file
// Access: Public, Virtual
// Description: Returns true if the indicated file exists within the
// mount system.
////////////////////////////////////////////////////////////////////
bool VirtualFileMountMultifile::
has_file(const Filename &file) const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountMultifile::is_directory
// Access: Public, Virtual
// Description: Returns true if the indicated file exists within the
// mount system and is a directory.
////////////////////////////////////////////////////////////////////
bool VirtualFileMountMultifile::
is_directory(const Filename &file) const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountMultifile::is_regular_file
// Access: Public, Virtual
// Description: Returns true if the indicated file exists within the
// mount system and is a regular file.
////////////////////////////////////////////////////////////////////
bool VirtualFileMountMultifile::
is_regular_file(const Filename &file) const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountMultifile::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 or an invalid istream on failure.
////////////////////////////////////////////////////////////////////
istream *VirtualFileMountMultifile::
open_read_file(const Filename &file) const {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountMultifile::scan_directory
// Access: Public, Virtual
// Description: Fills the given vector up with the sorted 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 VirtualFileMountMultifile::
scan_directory(vector_string &contents, const Filename &dir) const {
return false;
}

View File

@ -0,0 +1,75 @@
// Filename: virtualFileMountMultifile.h
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef VIRTUALFILEMOUNTMULTIFILE_H
#define VIRTUALFILEMOUNTMULTIFILE_H
#include "pandabase.h"
#include "virtualFileMount.h"
#include "multifile.h"
////////////////////////////////////////////////////////////////////
// Class : VirtualFileMountMultifile
// Description : Maps a Multifile's contents into the
// VirtualFileSystem.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VirtualFileMountMultifile : public VirtualFileMount {
public:
INLINE VirtualFileMountMultifile(VirtualFileSystem *file_system,
Multifile *multifile,
const Filename &mount_point,
int mount_flags);
virtual ~VirtualFileMountMultifile();
INLINE Multifile *get_multifile() const;
virtual bool has_file(const Filename &file) const;
virtual bool is_directory(const Filename &file) const;
virtual bool is_regular_file(const Filename &file) const;
virtual istream *open_read_file(const Filename &file) const;
virtual bool scan_directory(vector_string &contents,
const Filename &dir) const;
private:
Multifile *_multifile;
public:
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
VirtualFileMount::init_type();
register_type(_type_handle, "VirtualFileMountMultifile",
VirtualFileMount::get_class_type());
}
private:
static TypeHandle _type_handle;
};
#include "virtualFileMountMultifile.I"
#endif

View File

@ -0,0 +1,32 @@
// Filename: virtualFileMountSystem.I
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountSystem::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VirtualFileMountSystem::
VirtualFileMountSystem(VirtualFileSystem *file_system,
const Filename &physical_filename,
const Filename &mount_point,
int mount_flags) :
VirtualFileMount(file_system, physical_filename, mount_point, mount_flags)
{
}

View File

@ -0,0 +1,95 @@
// Filename: virtualFileMountSystem.cxx
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "virtualFileMountSystem.h"
TypeHandle VirtualFileMountSystem::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountSystem::has_file
// Access: Public, Virtual
// Description: Returns true if the indicated file exists within the
// mount system.
////////////////////////////////////////////////////////////////////
bool VirtualFileMountSystem::
has_file(const Filename &file) const {
Filename pathname(_physical_filename, file);
return pathname.exists();
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountSystem::is_directory
// Access: Public, Virtual
// Description: Returns true if the indicated file exists within the
// mount system and is a directory.
////////////////////////////////////////////////////////////////////
bool VirtualFileMountSystem::
is_directory(const Filename &file) const {
Filename pathname(_physical_filename, file);
return pathname.is_directory();
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountSystem::is_regular_file
// Access: Public, Virtual
// Description: Returns true if the indicated file exists within the
// mount system and is a regular file.
////////////////////////////////////////////////////////////////////
bool VirtualFileMountSystem::
is_regular_file(const Filename &file) const {
Filename pathname(_physical_filename, file);
return pathname.is_regular_file();
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountSystem::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 or an invalid istream on failure.
////////////////////////////////////////////////////////////////////
istream *VirtualFileMountSystem::
open_read_file(const Filename &file) const {
Filename pathname(_physical_filename, file);
ifstream *stream = new ifstream;
if (!pathname.open_read(*stream)) {
// Couldn't open the file for some reason.
delete stream;
return NULL;
}
return stream;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileMountSystem::scan_directory
// Access: Public, Virtual
// Description: Fills the given vector up with the sorted 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 VirtualFileMountSystem::
scan_directory(vector_string &contents, const Filename &dir) const {
Filename pathname(_physical_filename, dir);
return pathname.scan_directory(contents);
}

View File

@ -0,0 +1,68 @@
// Filename: virtualFileMountSystem.h
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef VIRTUALFILEMOUNTSYSTEM_H
#define VIRTUALFILEMOUNTSYSTEM_H
#include "pandabase.h"
#include "virtualFileMount.h"
////////////////////////////////////////////////////////////////////
// Class : VirtualFileMountSystem
// Description : Maps an actual OS directory into the
// VirtualFileSystem.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VirtualFileMountSystem : public VirtualFileMount {
public:
INLINE VirtualFileMountSystem(VirtualFileSystem *file_system,
const Filename &physical_filename,
const Filename &mount_point,
int mount_flags);
virtual bool has_file(const Filename &file) const;
virtual bool is_directory(const Filename &file) const;
virtual bool is_regular_file(const Filename &file) const;
virtual istream *open_read_file(const Filename &file) const;
virtual bool scan_directory(vector_string &contents,
const Filename &dir) const;
public:
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
VirtualFileMount::init_type();
register_type(_type_handle, "VirtualFileMountSystem",
VirtualFileMount::get_class_type());
}
private:
static TypeHandle _type_handle;
};
#include "virtualFileMountSystem.I"
#endif

View File

@ -0,0 +1,30 @@
// Filename: virtualFileSimple.I
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSimple::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VirtualFileSimple::
VirtualFileSimple(VirtualFileMount *mount, const Filename &local_filename) :
_mount(mount),
_local_filename(local_filename)
{
}

View File

@ -0,0 +1,130 @@
// Filename: virtualFileSimple.cxx
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "virtualFileSimple.h"
TypeHandle VirtualFileSimple::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSimple::get_file_system
// Access: Published, Virtual
// Description: Returns the VirtualFileSystem this file is associated
// with.
////////////////////////////////////////////////////////////////////
VirtualFileSystem *VirtualFileSimple::
get_file_system() const {
return _mount->get_file_system();
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSimple::get_filename
// Access: Published, Virtual
// Description: Returns the full pathname to this file within the
// virtual file system.
////////////////////////////////////////////////////////////////////
Filename VirtualFileSimple::
get_filename() const {
string mount_point = _mount->get_mount_point();
if (_local_filename.empty()) {
if (mount_point.empty()) {
return "/";
} else {
return string("/") + mount_point;
}
} else {
if (mount_point.empty()) {
return string("/") + _local_filename.get_fullpath();
} else {
return string("/") + mount_point + string("/") + _local_filename.get_fullpath();
}
}
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSimple::is_directory
// Access: Published, Virtual
// Description: Returns true if this file represents a directory (and
// scan_directory() may be called), false otherwise.
////////////////////////////////////////////////////////////////////
bool VirtualFileSimple::
is_directory() const {
return _mount->is_directory(_local_filename);
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSimple::is_regular_file
// Access: Published, Virtual
// Description: Returns true if this file represents a regular file
// (and read_file() may be called), false otherwise.
////////////////////////////////////////////////////////////////////
bool VirtualFileSimple::
is_regular_file() const {
return _mount->is_regular_file(_local_filename);
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSimple::open_read_file
// Access: Published, Virtual
// Description: Opens the file for reading. Returns a newly
// allocated istream on success (which you should
// eventually delete when you are done reading).
// Returns NULL on failure.
////////////////////////////////////////////////////////////////////
istream *VirtualFileSimple::
open_read_file() const {
return _mount->open_read_file(_local_filename);
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSimple::scan_local_directory
// Access: Protected, Virtual
// Description: Fills file_list up with the list of files that are
// within this directory, excluding those whose
// basenames are listed in mount_points. Returns true
// if successful, false if the file is not a directory
// or the directory cannot be read.
////////////////////////////////////////////////////////////////////
bool VirtualFileSimple::
scan_local_directory(VirtualFileList *file_list,
const ov_set<string> &mount_points) const {
vector_string names;
if (!_mount->scan_directory(names, _local_filename)) {
return false;
}
// Now the scan above gave us a list of basenames. Turn these back
// into VirtualFile pointers.
// Each of the files returned by the mount will be just a simple
// file within the same mount tree, unless it is shadowed by a
// mount point listed in mount_points.
vector_string::const_iterator ni;
for (ni = names.begin(); ni != names.end(); ++ni) {
const string &basename = (*ni);
if (mount_points.find(basename) == mount_points.end()) {
Filename filename(_local_filename, basename);
VirtualFileSimple *file = new VirtualFileSimple(_mount, filename);
file_list->add_file(file);
}
}
return true;
}

View File

@ -0,0 +1,78 @@
// Filename: virtualFileSimple.h
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef VIRTUALFILESIMPLE_H
#define VIRTUALFILESIMPLE_H
#include "pandabase.h"
#include "virtualFile.h"
////////////////////////////////////////////////////////////////////
// Class : VirtualFileSimple
// Description : A simple file or directory within the
// VirtualFileSystem: this maps to exactly one file on
// one mount point. Most directories, and all regular
// files, are of this kind.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VirtualFileSimple : public VirtualFile {
public:
INLINE VirtualFileSimple(VirtualFileMount *mount,
const Filename &local_filename);
virtual VirtualFileSystem *get_file_system() const;
virtual Filename get_filename() const;
virtual bool is_directory() const;
virtual bool is_regular_file() const;
virtual istream *open_read_file() const;
protected:
virtual bool scan_local_directory(VirtualFileList *file_list,
const ov_set<string> &mount_points) const;
private:
VirtualFileMount *_mount;
Filename _local_filename;
public:
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
PUBLISHED:
static TypeHandle get_class_type() {
return _type_handle;
}
public:
static void init_type() {
VirtualFile::init_type();
register_type(_type_handle, "VirtualFileSimple",
VirtualFile::get_class_type());
}
private:
static TypeHandle _type_handle;
};
#include "virtualFileSimple.I"
#endif

View File

@ -0,0 +1,17 @@
// Filename: virtualFileSystem.I
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,500 @@
// Filename: virtualFileSystem.cxx
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "virtualFileSystem.h"
#include "virtualFileMount.h"
#include "virtualFileMountMultifile.h"
#include "virtualFileMountSystem.h"
#include "dSearchPath.h"
#include "dcast.h"
VirtualFileSystem *VirtualFileSystem::_global_ptr = NULL;
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
VirtualFileSystem::
VirtualFileSystem() {
_cwd = "/";
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
VirtualFileSystem::
~VirtualFileSystem() {
unmount_all();
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::mount
// Access: Published
// Description: Mounts the indicated Multifile at the given mount
// point. If flags contains MF_owns_pointer, the
// Multifile will be deleted when it is eventually
// unmounted.
////////////////////////////////////////////////////////////////////
bool VirtualFileSystem::
mount(Multifile *multifile, const string &mount_point, int flags) {
VirtualFileMountMultifile *mount =
new VirtualFileMountMultifile(this, multifile,
normalize_mount_point(mount_point),
flags);
_mounts.push_back(mount);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::mount
// Access: Published
// Description: Mounts the indicated system file or directory at the
// given mount point. If the named file is a directory,
// mounts the directory. If the named file is a
// Multifile, mounts it as a Multifile. Returns true on
// success, false on failure.
//
// A given system directory may be mounted to multiple
// different mount point, and the same mount point may
// share multiple system directories. In the case of
// ambiguities, the most-recently mounted system wins.
////////////////////////////////////////////////////////////////////
bool VirtualFileSystem::
mount(const Filename &physical_filename, const string &mount_point,
int flags) {
if (!physical_filename.exists()) {
util_cat.warning()
<< "Attempt to mount " << physical_filename << ", not found.\n";
return false;
}
if (physical_filename.is_directory()) {
flags &= ~MF_owns_pointer;
VirtualFileMountSystem *mount =
new VirtualFileMountSystem(this, physical_filename,
normalize_mount_point(mount_point),
flags);
_mounts.push_back(mount);
return true;
} else {
// It's not a directory; it must be a Multifile.
Multifile *multifile = new Multifile;
// For now these are always opened read only. Maybe later we'll
// support read-write on Multifiles.
flags |= MF_read_only;
if (!multifile->open_read(physical_filename)) {
delete multifile;
return false;
}
// We want to delete this pointer when we're done.
flags |= MF_owns_pointer;
return mount(multifile, mount_point, flags);
}
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::unmount
// Access: Published
// Description: Unmounts all appearances of the indicated Multifile
// from the file system. Returns the number of
// appearances unmounted.
////////////////////////////////////////////////////////////////////
int VirtualFileSystem::
unmount(Multifile *multifile) {
Mounts::iterator ri, wi;
wi = ri = _mounts.begin();
while (ri != _mounts.end()) {
VirtualFileMount *mount = (*ri);
(*wi) = mount;
if (mount->is_exact_type(VirtualFileMountMultifile::get_class_type())) {
VirtualFileMountMultifile *mmount =
DCAST(VirtualFileMountMultifile, mount);
if (mmount->get_multifile() == multifile) {
// Remove this one. Don't increment wi.
delete mount;
} else {
// Don't remove this one.
++wi;
}
} else {
// Don't remove this one.
++wi;
}
++ri;
}
int num_removed = _mounts.end() - wi;
_mounts.erase(wi, _mounts.end());
return num_removed;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::unmount
// Access: Published
// Description: Unmounts all appearances of the indicated physical
// filename (either a directory name or a Multifile
// name) from the file system. Returns the number of
// appearances unmounted.
////////////////////////////////////////////////////////////////////
int VirtualFileSystem::
unmount(const Filename &physical_filename) {
Mounts::iterator ri, wi;
wi = ri = _mounts.begin();
while (ri != _mounts.end()) {
VirtualFileMount *mount = (*ri);
(*wi) = mount;
if (mount->get_physical_filename() == physical_filename) {
// Remove this one. Don't increment wi.
delete mount;
} else {
// Don't remove this one.
++wi;
}
++ri;
}
int num_removed = _mounts.end() - wi;
_mounts.erase(wi, _mounts.end());
return num_removed;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::unmount_point
// Access: Published
// Description: Unmounts all systems attached to the given mount
// point from the file system. Returns the number of
// appearances unmounted.
////////////////////////////////////////////////////////////////////
int VirtualFileSystem::
unmount_point(const string &mount_point) {
Filename nmp = normalize_mount_point(mount_point);
Mounts::iterator ri, wi;
wi = ri = _mounts.begin();
while (ri != _mounts.end()) {
VirtualFileMount *mount = (*ri);
(*wi) = mount;
if (mount->get_mount_point() == nmp) {
// Remove this one. Don't increment wi.
delete mount;
} else {
// Don't remove this one.
++wi;
}
++ri;
}
int num_removed = _mounts.end() - wi;
_mounts.erase(wi, _mounts.end());
return num_removed;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::unmount_all
// Access: Published
// Description: Unmounts all files from the file system. Returns the
// number of systems unmounted.
////////////////////////////////////////////////////////////////////
int VirtualFileSystem::
unmount_all() {
Mounts::iterator mi;
for (mi = _mounts.begin(); mi != _mounts.end(); ++mi) {
VirtualFileMount *mount = (*mi);
delete mount;
}
int num_removed = _mounts.size();
_mounts.clear();
return num_removed;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::chdir
// Access: Published
// Description: Changes the current directory. This is used to
// resolve relative pathnames in get_file() and/or
// find_file(). Returns true if successful, false
// otherwise.
////////////////////////////////////////////////////////////////////
bool VirtualFileSystem::
chdir(const Filename &new_directory) {
if (new_directory == "/") {
// We can always return to the root.
_cwd = new_directory;
return true;
}
PT(VirtualFile) file = get_file(new_directory);
if (file != (VirtualFile *)NULL && file->is_directory()) {
_cwd = file->get_filename();
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::get_cwd
// Access: Published
// Description: Returns the current directory name. See chdir().
////////////////////////////////////////////////////////////////////
const Filename &VirtualFileSystem::
get_cwd() const {
return _cwd;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::get_file
// Access: Published
// Description: Looks up the file by the indicated name in the file
// system. Returns a VirtualFile pointer representing
// the file if it is found, or NULL if it is not.
////////////////////////////////////////////////////////////////////
PT(VirtualFile) VirtualFileSystem::
get_file(const Filename &file) const {
nassertr(!file.empty(), NULL);
Filename pathname(file);
if (pathname.is_local()) {
pathname = Filename(_cwd, file);
}
pathname.standardize();
string strpath = pathname.get_fullpath().substr(1);
// Now scan all the mount points, from the back (since later mounts
// override more recent ones), until a match is found.
PT(VirtualFile) found_file = NULL;
VirtualFileComposite *composite_file = NULL;
Mounts::const_reverse_iterator rmi;
for (rmi = _mounts.rbegin(); rmi != _mounts.rend(); ++rmi) {
VirtualFileMount *mount = (*rmi);
string mount_point = mount->get_mount_point();
if (strpath == mount_point) {
// Here's an exact match on the mount point. This filename is
// the root directory of this mount object.
if (found_match(found_file, composite_file, mount, "")) {
return found_file;
}
} else if (mount_point.empty()) {
// This is the root mount point; all files are in here.
if (mount->has_file(strpath)) {
// Bingo!
if (found_match(found_file, composite_file, mount, strpath)) {
return found_file;
}
}
} else if (strpath.length() > mount_point.length() &&
strpath.substr(0, mount_point.length()) == mount_point &&
strpath[mount_point.length()] == '/') {
// This pathname falls within this mount system.
Filename local_filename = strpath.substr(mount_point.length() + 1);
if (mount->has_file(local_filename)) {
// Bingo!
if (found_match(found_file, composite_file, mount, local_filename)) {
return found_file;
}
}
}
}
return found_file;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::find_file
// Access: Published
// Description: Uses the indicated search path to find the file
// within the file system. Returns the first occurrence
// of the file found, or NULL if the file cannot be
// found.
////////////////////////////////////////////////////////////////////
PT(VirtualFile) VirtualFileSystem::
find_file(const Filename &file, const DSearchPath &searchpath) const {
if (file.is_local()) {
return get_file(file);
}
int num_directories = searchpath.get_num_directories();
for (int i = 0; i < num_directories; i++) {
Filename match(searchpath.get_directory(i), file);
PT(VirtualFile) found_file = get_file(match);
if (found_file != (VirtualFile *)NULL) {
return found_file;
}
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::write
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void VirtualFileSystem::
write(ostream &out) const {
Mounts::const_iterator mi;
for (mi = _mounts.begin(); mi != _mounts.end(); ++mi) {
VirtualFileMount *mount = (*mi);
mount->write(out);
}
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::get_global_ptr
// Access: Published, Static
// Description: Returns the default global VirtualFileSystem. You
// may create your own personal VirtualFileSystem
// objects and use them for whatever you like, but Panda
// will attempt to load models and stuff from this
// default object.
//
// Initially, the global VirtualFileSystem is set up to
// mount the OS filesystem to root; i.e. it is
// equivalent to the OS filesystem. This may be
// subsequently adjusted by the user.
////////////////////////////////////////////////////////////////////
VirtualFileSystem *VirtualFileSystem::
get_global_ptr() {
if (_global_ptr == (VirtualFileSystem *)NULL) {
_global_ptr = new VirtualFileSystem;
_global_ptr->mount("/", "/", 0);
}
return _global_ptr;
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::scan_mount_points
// Access: Public
// Description: Adds to names a list of all the mount points in use
// that are one directory below path, if any. That is,
// these are the external files or directories mounted
// directly to the indicated path.
//
// The names vector is filled with a set of basenames,
// the basename part of the mount point.
////////////////////////////////////////////////////////////////////
void VirtualFileSystem::
scan_mount_points(vector_string &names, const Filename &path) const {
nassertv(!path.empty() && !path.is_local());
string prefix = path.get_fullpath().substr(1);
Mounts::const_iterator mi;
for (mi = _mounts.begin(); mi != _mounts.end(); ++mi) {
VirtualFileMount *mount = (*mi);
string mount_point = mount->get_mount_point();
if (prefix.empty()) {
// The indicated path is the root. Is the mount point on the
// root?
if (mount_point.find('/') == string::npos) {
// No embedded slashes, so the mount point is only one
// directory below the root.
names.push_back(mount_point);
}
} else {
if (mount_point.substr(0, prefix.length()) == prefix &&
mount_point.length() > prefix.length() &&
mount_point[prefix.length()] == '/') {
// This mount point is below the indicated path. Is it only one
// directory below?
string basename = mount_point.substr(prefix.length());
if (basename.find('/') == string::npos) {
// No embedded slashes, so it's only one directory below.
names.push_back(basename);
}
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::normalize_mount_point
// Access: Private
// Description: Converts the mount point string supplied by the user
// to standard form (relative to the current directory,
// with no double slashes, and not terminating with a
// slash). The initial slash is removed.
////////////////////////////////////////////////////////////////////
Filename VirtualFileSystem::
normalize_mount_point(const string &mount_point) const {
Filename nmp = mount_point;
if (nmp.is_local()) {
nmp = Filename(_cwd, mount_point);
}
nmp.standardize();
nassertr(!nmp.empty() && nmp[0] == '/', nmp);
return nmp.get_fullpath().substr(1);
}
////////////////////////////////////////////////////////////////////
// Function: VirtualFileSystem::found_match
// Access: Private
// Description: Evaluates one match found during a get_file()
// operation. There may be multiple matches for a
// particular filename due to the ambiguities introduced
// by allowing multiple mount points, so we may have to
// keep searching even after the first match is found.
//
// Returns true if the search should terminate now, or
// false if it should keep iterating.
////////////////////////////////////////////////////////////////////
bool VirtualFileSystem::
found_match(PT(VirtualFile) &found_file, VirtualFileComposite *&composite_file,
VirtualFileMount *mount, const string &local_filename) const {
if (found_file == (VirtualFile *)NULL) {
// This was our first match. Save it.
found_file = new VirtualFileSimple(mount, local_filename);
if (!mount->is_directory(local_filename)) {
// If it's not a directory, we're done.
return true;
}
} else {
// This was our second match. The previous match(es) must
// have been directories.
if (!mount->is_directory(local_filename)) {
// However, this one isn't a directory. We're done.
return true;
}
// At least two directories matched to the same path. We
// need a composite directory.
if (composite_file == (VirtualFileComposite *)NULL) {
composite_file =
new VirtualFileComposite((VirtualFileSystem *)this, found_file->get_filename());
composite_file->add_component(found_file);
found_file = composite_file;
}
composite_file->add_component(new VirtualFileSimple(mount, local_filename));
}
// Keep going, looking for more directories.
return false;
}

View File

@ -0,0 +1,86 @@
// Filename: virtualFileSystem.h
// Created by: drose (03Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef VIRTUALFILESYSTEM_H
#define VIRTUALFILESYSTEM_H
#include "pandabase.h"
#include "filename.h"
#include "pmap.h"
class Multifile;
class VirtualFileMount;
////////////////////////////////////////////////////////////////////
// Class : VirtualFileSystem
// Description : A hierarchy of directories and files that appears to
// be one continuous file system, even though the files
// may originate from several different sources that may
// not be related to the actual OS's file system.
//
// For instance, a VirtualFileSystem can transparently
// mount one or more Multifiles as their own
// subdirectory hierarchies.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VirtualFileSystem {
PUBLISHED:
VirtualFileSystem();
~VirtualFileSystem();
enum MountFlags {
MF_owns_pointer = 0x0001,
MF_read_only = 0x0002,
};
bool mount(Multifile *multifile, const string &mount_point, int flags);
bool mount(const Filename &physical_filename, const string &mount_point, int flags);
int unmount(Multifile *multifile);
int unmount(const Filename &physical_filename);
int unmount_point(const string &mount_point);
int unmount_all();
bool chdir(const Filename &new_directory);
const Filename &get_cwd() const;
PT(VirtualFile) get_file(const Filename &file) const;
PT(VirtualFile) find_file(const Filename &file,
const DSearchPath &searchpath) const;
void write(ostream &out) const;
static VirtualFileSystem *get_global_ptr();
public:
void scan_mount_points(vector_string &names, const Filename &path) const;
private:
Filename normalize_mount_point(const string &mount_point) const;
bool found_match(PT(VirtualFile) &found_file, VirtualFileComposite *&composite_file,
VirtualFileMount *mount, const string &local_filename) const;
typedef pvector<VirtualFileMount *> Mounts;
Mounts _mounts;
Filename _cwd;
static VirtualFileSystem *_global_ptr;
};
#include "virtualFileSystem.I"
#endif