fleshed out BSAArchive and DirArchive.

Implemented both lists & finds, with pattern matching.

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

@ -164,9 +164,6 @@ void OMW::Engine::loadBSA()
dataDirectory = iter->string();
std::cout << "Data dir " << dataDirectory << std::endl;
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 Bsa;
struct ciLessBoost : std::binary_function<std::string, std::string, bool>
struct PathPatternMatcher
{
bool operator() (const std::string & s1, const std::string & s2) const {
//case insensitive version of is_less
return boost::ilexicographical_compare(s1, s2);
PathPatternMatcher (char const * pattern) : pattern (pattern)
{
}
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:
std::string find;
StringVectorPtr ptr;
public:
pathComparer(const std::string& toFind) : find(toFind) { }
FileNameGatherer (StringVectorPtr ptr) : ptr (ptr)
{
}
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;
/// An OGRE Archive wrapping a BSAFile archive
@ -94,6 +208,11 @@ class DirArchive: public Ogre::Archive
return mIndex.find (normalized);
}
static char const * extractFilename (index::value_type const & entry)
{
return entry.first.c_str ();
}
public:
DirArchive(const String& name)
@ -143,27 +262,20 @@ public:
StringVectorPtr list(bool recursive = true, bool dirs = false)
{
StringVectorPtr ptr = StringVectorPtr(new StringVector());
std::cout << "DirArchive<" << getName () << ">::list" << std::endl;
return ptr;
return find ("*", recursive, dirs);
}
FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false)
{
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
std::cout << "DirArchive<" << getName () << ">::listFileInfo" << std::endl;
return ptr;
return findFileInfo ("*", recursive, dirs);
}
StringVectorPtr find(const String& pattern, bool recursive = true,
bool dirs = false)
{
std::string normalizedPattern = normalize_path (pattern.begin (), pattern.end ());
StringVectorPtr ptr = StringVectorPtr(new StringVector());
if (pattern == "*")
for (index::const_iterator i = mIndex.begin (); i != mIndex.end (); ++i)
ptr->push_back (i->first);
matchFiles (recursive, normalizedPattern, mIndex.begin (), mIndex.end (), extractFilename, FileNameGatherer (ptr));
return ptr;
}
@ -178,21 +290,20 @@ public:
bool dirs = false) const
{
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 ())
{
FileInfo fi;
std::size_t npos = i->first.rfind ('/');
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;
gatherer (i->first);
}
else
{
ptr->push_back(fi);
matchFiles (recursive, normalizedPattern, mIndex.begin (), mIndex.end (), extractFilename, gatherer);
}
return ptr;
@ -203,6 +314,11 @@ class BSAArchive : public Archive
{
BSAFile arc;
static char const * extractFilename (BSAFile::FileStruct const & entry)
{
return entry.name;
}
public:
BSAArchive(const String& name)
: Archive(name, "BSA")
@ -230,26 +346,18 @@ public:
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; }
// This is never called as far as I can see.
StringVectorPtr list(bool recursive = true, bool dirs = false)
{
//std::cout << "list(" << recursive << ", " << dirs << ")\n";
StringVectorPtr ptr = StringVectorPtr(new StringVector());
return ptr;
return find ("*", recursive, dirs);
}
// Also never called.
FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false)
{
//std::cout << "listFileInfo(" << recursive << ", " << dirs << ")\n";
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
return ptr;
return findFileInfo ("*", recursive, dirs);
}
// 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,
bool dirs = false)
{
//std::cout << "find(" << pattern << ", " << recursive
// << ", " << dirs << ")\n";
StringVectorPtr ptr = StringVectorPtr(new StringVector());
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;
StringVectorPtr ptr = StringVectorPtr(new StringVector());
matchFiles (recursive, pattern, arc.getList ().begin (), arc.getList ().end (), extractFilename, FileNameGatherer (ptr));
return ptr;
}
/* Gets called once for each of the ogre formats, *.program,
@ -281,47 +381,9 @@ public:
*/
FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,
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());
// 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);
}
matchFiles (recursive, pattern, arc.getList ().begin (), arc.getList ().end (), extractFilename, FileInfoGatherer (this, ptr));
return ptr;
}
};

Loading…
Cancel
Save