Explorar o código

vfs multifile support

David Rose %!s(int64=23) %!d(string=hai) anos
pai
achega
89528a5fc9

+ 76 - 0
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

+ 3 - 0
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;

+ 1 - 1
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;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 15 - 10
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);
 }
 

+ 4 - 5
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 {