fleshed out BSAArchive and DirArchive.

Implemented both lists & finds, with pattern matching.

Conflicts:
	components/bsa/bsa_archive.cpp
actorid
Nathan Jeffords 12 years ago
parent 6567bf38f8
commit 44031ec3d7

@ -164,9 +164,6 @@ void OMW::Engine::loadBSA()
dataDirectory = iter->string(); dataDirectory = iter->string();
std::cout << "Data dir " << dataDirectory << std::endl; std::cout << "Data dir " << dataDirectory << std::endl;
Bsa::addDir(dataDirectory, mFSStrict); Bsa::addDir(dataDirectory, mFSStrict);
// Workaround until resource listing capabilities are added to DirArchive, we need those to list available splash screens
addResourcesDirectory (dataDirectory);
} }
} }

@ -37,28 +37,142 @@ namespace
using namespace Ogre; using namespace Ogre;
using namespace Bsa; using namespace Bsa;
struct ciLessBoost : std::binary_function<std::string, std::string, bool> struct PathPatternMatcher
{ {
bool operator() (const std::string & s1, const std::string & s2) const { PathPatternMatcher (char const * pattern) : pattern (pattern)
//case insensitive version of is_less {
return boost::ilexicographical_compare(s1, s2); }
bool operator () (char const * input)
{
char const * p = pattern;
char const * i = input;
while (*p && *i)
{
if (*p == '*')
{
++p;
while (*i && *i != *p && *i != '/' && *i != '\\')
++i;
}
else
if (*p == '?')
{
if (*i == '/' || *i == '\\')
break;
++i, ++p;
}
if (*p == '/' || *p == '\\')
{
if (*i != '/' && *i != '\\')
break;
++i, ++p;
}
else
{
if (*i != *p)
break;
++i, ++p;
}
}
return *p == 0 && *i == 0;
} }
private:
char const * pattern;
}; };
struct pathComparer struct FileNameGatherer
{ {
private: StringVectorPtr ptr;
std::string find;
public: FileNameGatherer (StringVectorPtr ptr) : ptr (ptr)
pathComparer(const std::string& toFind) : find(toFind) { } {
}
bool operator() (const std::string& other) void operator () (std::string const & filename) const
{ {
return boost::iequals(find, other); ptr->push_back (filename);
} }
}; };
struct FileInfoGatherer
{
Archive const * archive;
FileInfoListPtr ptr;
FileInfoGatherer (Archive const * archive, FileInfoListPtr ptr) :
archive (archive), ptr (ptr)
{
}
void operator () (std::string filename) const
{
FileInfo fi;
std::size_t pt = filename.rfind ('/');
if (pt == std::string::npos)
pt = 0;
fi.archive = const_cast <Archive *> (archive);
fi.path = filename.substr (0, pt);
fi.filename = filename.substr (pt);
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi);
}
};
template <typename file_iterator, typename filename_extractor, typename match_handler>
void matchFiles (bool recursive, std::string const & pattern, file_iterator begin, file_iterator end, filename_extractor filenameExtractor, match_handler matchHandler)
{
if (recursive && pattern == "*")
{
for (file_iterator i = begin; i != end; ++i)
matchHandler (filenameExtractor (*i));
}
else
{
PathPatternMatcher matcher (pattern.c_str ());
if (recursive)
{
for (file_iterator i = begin; i != end; ++i)
{
char const * filename = filenameExtractor (*i);
char const * matchable_part = filename;
for (char const * j = matchable_part; *j; ++j)
{
if (*j == '/' || *j == '\\')
matchable_part = j + 1;
}
if (matcher (matchable_part))
matchHandler (filename);
}
}
else
{
for (file_iterator i = begin; i != end; ++i)
{
char const * filename = filenameExtractor (*i);
if (matcher (filename))
matchHandler (filename);
}
}
}
}
static bool fsstrict = false; static bool fsstrict = false;
/// An OGRE Archive wrapping a BSAFile archive /// An OGRE Archive wrapping a BSAFile archive
@ -94,6 +208,11 @@ class DirArchive: public Ogre::Archive
return mIndex.find (normalized); return mIndex.find (normalized);
} }
static char const * extractFilename (index::value_type const & entry)
{
return entry.first.c_str ();
}
public: public:
DirArchive(const String& name) DirArchive(const String& name)
@ -143,27 +262,20 @@ public:
StringVectorPtr list(bool recursive = true, bool dirs = false) StringVectorPtr list(bool recursive = true, bool dirs = false)
{ {
StringVectorPtr ptr = StringVectorPtr(new StringVector()); return find ("*", recursive, dirs);
std::cout << "DirArchive<" << getName () << ">::list" << std::endl;
return ptr;
} }
FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false) FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false)
{ {
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList()); return findFileInfo ("*", recursive, dirs);
std::cout << "DirArchive<" << getName () << ">::listFileInfo" << std::endl;
return ptr;
} }
StringVectorPtr find(const String& pattern, bool recursive = true, StringVectorPtr find(const String& pattern, bool recursive = true,
bool dirs = false) bool dirs = false)
{ {
std::string normalizedPattern = normalize_path (pattern.begin (), pattern.end ());
StringVectorPtr ptr = StringVectorPtr(new StringVector()); StringVectorPtr ptr = StringVectorPtr(new StringVector());
matchFiles (recursive, normalizedPattern, mIndex.begin (), mIndex.end (), extractFilename, FileNameGatherer (ptr));
if (pattern == "*")
for (index::const_iterator i = mIndex.begin (); i != mIndex.end (); ++i)
ptr->push_back (i->first);
return ptr; return ptr;
} }
@ -178,21 +290,20 @@ public:
bool dirs = false) const bool dirs = false) const
{ {
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList()); FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
FileInfoGatherer gatherer (this, ptr);
std::string normalizedPattern = normalize_path (pattern.begin (), pattern.end ());
index::const_iterator i = lookup_filename (pattern); index::const_iterator i = mIndex.find (normalizedPattern);
if (i != mIndex.end ()) if (i != mIndex.end ())
{ {
FileInfo fi; gatherer (i->first);
}
std::size_t npos = i->first.rfind ('/'); else
{
fi.archive = this;
fi.filename = npos != std::string::npos ? i->first.substr (npos) : i->first;
fi.path = npos != std::string::npos ? i->first.substr (0, npos) : "";
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi); matchFiles (recursive, normalizedPattern, mIndex.begin (), mIndex.end (), extractFilename, gatherer);
} }
return ptr; return ptr;
@ -203,6 +314,11 @@ class BSAArchive : public Archive
{ {
BSAFile arc; BSAFile arc;
static char const * extractFilename (BSAFile::FileStruct const & entry)
{
return entry.name;
}
public: public:
BSAArchive(const String& name) BSAArchive(const String& name)
: Archive(name, "BSA") : Archive(name, "BSA")
@ -230,26 +346,18 @@ public:
return arc.exists(filename.c_str()); return arc.exists(filename.c_str());
} }
bool cexists(const String& filename) const {
return arc.exists(filename.c_str());
}
time_t getModifiedTime(const String&) { return 0; } time_t getModifiedTime(const String&) { return 0; }
// This is never called as far as I can see. // This is never called as far as I can see.
StringVectorPtr list(bool recursive = true, bool dirs = false) StringVectorPtr list(bool recursive = true, bool dirs = false)
{ {
//std::cout << "list(" << recursive << ", " << dirs << ")\n"; return find ("*", recursive, dirs);
StringVectorPtr ptr = StringVectorPtr(new StringVector());
return ptr;
} }
// Also never called. // Also never called.
FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false) FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false)
{ {
//std::cout << "listFileInfo(" << recursive << ", " << dirs << ")\n"; return findFileInfo ("*", recursive, dirs);
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
return ptr;
} }
// After load() is called, find("*") is called once. It doesn't seem // After load() is called, find("*") is called once. It doesn't seem
@ -258,17 +366,9 @@ public:
StringVectorPtr find(const String& pattern, bool recursive = true, StringVectorPtr find(const String& pattern, bool recursive = true,
bool dirs = false) bool dirs = false)
{ {
//std::cout << "find(" << pattern << ", " << recursive StringVectorPtr ptr = StringVectorPtr(new StringVector());
// << ", " << dirs << ")\n"; matchFiles (recursive, pattern, arc.getList ().begin (), arc.getList ().end (), extractFilename, FileNameGatherer (ptr));
StringVectorPtr ptr = StringVectorPtr(new StringVector()); return ptr;
BSAFile::FileList const & files = arc.getList ();
if (pattern == "*")
for (BSAFile::FileList::const_iterator i = files.begin (); i != files.end (); ++i)
ptr->push_back (i->name);
return ptr;
} }
/* Gets called once for each of the ogre formats, *.program, /* Gets called once for each of the ogre formats, *.program,
@ -281,47 +381,9 @@ public:
*/ */
FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true, FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,
bool dirs = false) const bool dirs = false) const
{
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
// Check if the file exists (only works for single files - wild
// cards and recursive search isn't implemented.)
if(cexists(pattern))
{
FileInfo fi;
fi.archive = this;
fi.filename = pattern;
// It apparently doesn't matter that we return bogus
// information
fi.path = "";
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi);
}
return ptr;
}
FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,
bool dirs = false)
{ {
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList()); FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
matchFiles (recursive, pattern, arc.getList ().begin (), arc.getList ().end (), extractFilename, FileInfoGatherer (this, ptr));
// Check if the file exists (only works for single files - wild
// cards and recursive search isn't implemented.)
if(cexists(pattern))
{
FileInfo fi;
fi.archive = this;
fi.filename = pattern;
// It apparently doesn't matter that we return bogus
// information
fi.path = "";
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi);
}
return ptr; return ptr;
} }
}; };

Loading…
Cancel
Save