diff --git a/panda/src/express/multifile.cxx b/panda/src/express/multifile.cxx index 9022145b43..8d81c977f6 100644 --- a/panda/src/express/multifile.cxx +++ b/panda/src/express/multifile.cxx @@ -547,6 +547,82 @@ find_subfile(const string &subfile_name) const { return (fi - _subfiles.begin()); } +//////////////////////////////////////////////////////////////////// +// Function: Multifile::has_directory +// Access: Published +// Description: Returns true if the indicated subfile name is the +// directory prefix to one or more files within the +// Multifile. That is, the Multifile contains at least +// one file named "subfile_name/...". +//////////////////////////////////////////////////////////////////// +bool Multifile:: +has_directory(const string &subfile_name) const { + string prefix = subfile_name; + if (!prefix.empty()) { + prefix += '/'; + } + Subfile find_subfile(prefix); + Subfiles::const_iterator fi; + fi = _subfiles.upper_bound(&find_subfile); + if (fi == _subfiles.end()) { + // Not present. + return false; + } + + // At least one subfile exists whose name sorts after prefix. If it + // contains prefix as the initial substring, then we have a match. + Subfile *subfile = (*fi); + return (subfile->_name.length() > prefix.length() && + subfile->_name.substr(0, prefix.length()) == prefix); +} + +//////////////////////////////////////////////////////////////////// +// Function: Multifile::scan_directory +// Access: Published +// Description: Considers subfile_name to be the name of a +// subdirectory within the Multifile, but not a file +// itself; ills the given vector up with the sorted list +// of subdirectories or files within the named +// directory. +// +// Note that directories do not exist explicitly within +// a Multifile; this just checks for the existence of +// files with the given initial prefix. +// +// Returns true if successful, false otherwise. +//////////////////////////////////////////////////////////////////// +bool Multifile:: +scan_directory(vector_string &contents, const string &subfile_name) const { + string prefix = subfile_name; + if (!prefix.empty()) { + prefix += '/'; + } + Subfile find_subfile(prefix); + Subfiles::const_iterator fi; + fi = _subfiles.upper_bound(&find_subfile); + + string previous = ""; + while (fi != _subfiles.end()) { + Subfile *subfile = (*fi); + if (!(subfile->_name.length() > prefix.length() && + subfile->_name.substr(0, prefix.length()) == prefix)) { + // We've reached the end of the list of subfiles beneath the + // indicated direcotry prefix. + return true; + } + + size_t slash = subfile->_name.find('/', prefix.length()); + string basename = subfile->_name.substr(prefix.length(), slash); + if (basename != previous) { + contents.push_back(basename); + previous = basename; + } + ++fi; + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: Multifile::remove_subfile // Access: Published diff --git a/panda/src/express/multifile.h b/panda/src/express/multifile.h index d48f07a50e..32141f4a69 100644 --- a/panda/src/express/multifile.h +++ b/panda/src/express/multifile.h @@ -63,6 +63,9 @@ PUBLISHED: int get_num_subfiles() const; int find_subfile(const string &subfile_name) const; + bool has_directory(const string &subfile_name) const; + bool scan_directory(vector_string &contents, + const string &subfile_name) const; void remove_subfile(int index); const string &get_subfile_name(int index) const; size_t get_subfile_length(int index) const; diff --git a/panda/src/putil/virtualFile.cxx b/panda/src/putil/virtualFile.cxx index 1ca5b55230..c3c254c3a3 100644 --- a/panda/src/putil/virtualFile.cxx +++ b/panda/src/putil/virtualFile.cxx @@ -74,7 +74,7 @@ read_file(Datagram &data) const { util_cat.info() << "Error while reading " << get_filename() << "\n"; } - return failed; + return !failed; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/putil/virtualFileMountMultifile.cxx b/panda/src/putil/virtualFileMountMultifile.cxx index 514e20ecd7..fb0802a46c 100644 --- a/panda/src/putil/virtualFileMountMultifile.cxx +++ b/panda/src/putil/virtualFileMountMultifile.cxx @@ -45,7 +45,9 @@ VirtualFileMountMultifile:: //////////////////////////////////////////////////////////////////// bool VirtualFileMountMultifile:: has_file(const Filename &file) const { - return false; + return (file.empty() || + _multifile->find_subfile(file) >= 0 || + _multifile->has_directory(file)); } //////////////////////////////////////////////////////////////////// @@ -56,7 +58,7 @@ has_file(const Filename &file) const { //////////////////////////////////////////////////////////////////// bool VirtualFileMountMultifile:: is_directory(const Filename &file) const { - return false; + return (file.empty() || _multifile->has_directory(file)); } //////////////////////////////////////////////////////////////////// @@ -67,7 +69,7 @@ is_directory(const Filename &file) const { //////////////////////////////////////////////////////////////////// bool VirtualFileMountMultifile:: is_regular_file(const Filename &file) const { - return false; + return (_multifile->find_subfile(file) >= 0); } //////////////////////////////////////////////////////////////////// @@ -80,20 +82,23 @@ is_regular_file(const Filename &file) const { //////////////////////////////////////////////////////////////////// istream *VirtualFileMountMultifile:: open_read_file(const Filename &file) const { - return NULL; + int subfile_index = _multifile->find_subfile(file); + if (subfile_index < 0) { + return NULL; + } + return _multifile->open_read_subfile(subfile_index); } //////////////////////////////////////////////////////////////////// // 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. +// 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 VirtualFileMountMultifile:: scan_directory(vector_string &contents, const Filename &dir) const { - return false; + return _multifile->scan_directory(contents, dir); } diff --git a/panda/src/putil/virtualFileMountSystem.cxx b/panda/src/putil/virtualFileMountSystem.cxx index e1c3c40dcd..7713e41a68 100644 --- a/panda/src/putil/virtualFileMountSystem.cxx +++ b/panda/src/putil/virtualFileMountSystem.cxx @@ -81,11 +81,10 @@ open_read_file(const Filename &file) const { //////////////////////////////////////////////////////////////////// // 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. +// 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 VirtualFileMountSystem:: scan_directory(vector_string &contents, const Filename &dir) const {