Merge remote branch 'ace/fs-fix'

pull/21/head
Marc Zinnschlag 13 years ago
commit 509650d5f3

@ -204,13 +204,18 @@ OMW::Engine::~Engine()
void OMW::Engine::loadBSA() void OMW::Engine::loadBSA()
{ {
const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa"); const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa");
std::string dataDirectory;
for (Files::MultiDirCollection::TIter iter(bsa.begin()); iter!=bsa.end(); ++iter) for (Files::MultiDirCollection::TIter iter(bsa.begin()); iter!=bsa.end(); ++iter)
{ {
std::cout << "Adding " << iter->second.string() << std::endl; std::cout << "Adding " << iter->second.string() << std::endl;
Bsa::addBSA(iter->second.string()); Bsa::addBSA(iter->second.string());
}
dataDirectory = iter->second.parent_path().string(); const Files::PathContainer& dataDirs = mFileCollections.getPaths();
std::string dataDirectory;
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
{
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);
} }

@ -45,6 +45,20 @@ struct ciLessBoost : std::binary_function<std::string, std::string, bool>
} }
}; };
struct pathComparer
{
private:
int m_start, m_size;
public:
pathComparer(int start, int size) : m_start(start), m_size(size) { }
bool operator() (const std::string& first, const std::string& other)
{
return lexicographical_compare(first.substr(m_start,m_size), other.substr(m_start,m_size), boost::algorithm::is_iless());
}
};
static bool fsstrict = false; static bool fsstrict = false;
/// An OGRE Archive wrapping a BSAFile archive /// An OGRE Archive wrapping a BSAFile archive
@ -55,16 +69,59 @@ class DirArchive: public Ogre::FileSystemArchive
std::map<std::string, std::vector<std::string>, ciLessBoost> m; std::map<std::string, std::vector<std::string>, ciLessBoost> m;
unsigned int cutoff; unsigned int cutoff;
bool comparePortion(std::string file1, std::string file2, int start, int size) const bool findFile(const String& filename, std::string& copy) const
{ {
for(int i = start; i < start+size; i++)
{ {
char one = file1.at(i); String passed = filename;
char two = file2.at(i); if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
if(tolower(one) != tolower(two) ) || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|| filename.at(filename.length() - 1) == '|')
{
passed = filename.substr(0, filename.length() - 2);
}
if(filename.at(filename.length() - 2) == '>')
passed = filename.substr(0, filename.length() - 6);
copy = passed;
}
std::replace(copy.begin(), copy.end(), '\\', '/');
if(copy.at(0) == '/')
copy.erase(0, 1);
if(fsstrict == true)
return true;
std::string folder;
int delimiter = 0;
size_t lastSlash = copy.rfind('/');
if (lastSlash != std::string::npos)
{
folder = copy.substr(0, lastSlash);
delimiter = lastSlash+1;
}
std::vector<std::string> current;
{
std::map<std::string,std::vector<std::string>,ciLessBoost>::const_iterator found = m.find(folder);
if (found == m.end())
{
return false; return false;
}
else
current = found->second;
} }
return true;
pathComparer comp(delimiter, copy.size() - delimiter-1);
std::vector<std::string>::iterator find = std::lower_bound(current.begin(), current.end(), copy, comp);
if (find != current.end() && !comp(copy, current.front()))
{
copy = *find;
return true;
}
return false;
} }
public: public:
@ -83,16 +140,14 @@ class DirArchive: public Ogre::FileSystemArchive
//need to cut off first //need to cut off first
boost::filesystem::directory_iterator dir_iter(d), dir_end; boost::filesystem::directory_iterator dir_iter(d), dir_end;
std::vector<std::string> filesind; std::vector<std::string> filesind;
boost::filesystem::path f;
for(;dir_iter != dir_end; dir_iter++) for(;dir_iter != dir_end; dir_iter++)
{ {
if(boost::filesystem::is_directory(*dir_iter)) if(boost::filesystem::is_directory(*dir_iter))
populateMap(*dir_iter); populateMap(*dir_iter);
else else
{ {
std::string s = dir_iter->path().string();
f = *dir_iter; std::replace(s.begin(), s.end(), '\\', '/');
std::string s = f.string();
std::string small; std::string small;
if(cutoff < s.size()) if(cutoff < s.size())
@ -103,14 +158,17 @@ class DirArchive: public Ogre::FileSystemArchive
filesind.push_back(small); filesind.push_back(small);
} }
} }
std::sort(filesind.begin(), filesind.end(), ciLessBoost());
std::string small; std::string small;
std::string original = d.string(); std::string original = d.string();
std::replace(original.begin(), original.end(), '\\', '/');
if(cutoff < original.size()) if(cutoff < original.size())
small = original.substr(cutoff, original.size() - cutoff); small = original.substr(cutoff, original.size() - cutoff);
else else
small = original.substr(cutoff - 1, original.size() - cutoff); small = original.substr(cutoff - 1, original.size() - cutoff);
m[small] = filesind;
m[small] = filesind;
} }
bool isCaseSensitive() const { return fsstrict; } bool isCaseSensitive() const { return fsstrict; }
@ -120,97 +178,21 @@ class DirArchive: public Ogre::FileSystemArchive
void unload() {} void unload() {}
bool exists(const String& filename) { bool exists(const String& filename) {
std::string copy = filename; std::string copy;
if (findFile(filename, copy))
for (unsigned int i = 0; i < filename.size(); i++)
{
if(copy.at(i) == '\\' ){
copy.replace(i, 1, "/");
}
}
if(copy.at(0) == '\\' || copy.at(0) == '/')
{
copy.erase(0, 1);
}
if(fsstrict == true)
{
//std::cout << "fsstrict " << copy << "\n";
return FileSystemArchive::exists(copy); return FileSystemArchive::exists(copy);
}
int last = copy.size() - 1;
int i = last;
for (;last >= 0; i--)
{
if(copy.at(i) == '/' || copy.at(i) == '\\')
break;
}
std::string folder = copy.substr(0, i); //folder with no slash
std::vector<std::string>& current = m[folder];
for(std::vector<std::string>::iterator iter = current.begin(); iter != current.end(); iter++)
{
if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){
return FileSystemArchive::exists(*iter);
}
}
return false; return false;
} }
DataStreamPtr open(const String& filename, bool readonly = true) const DataStreamPtr open(const String& filename, bool readonly = true) const
{ {
std::map<std::string, std::vector<std::string>, ciLessBoost> mlocal = m; std::string copy;
std::string copy = filename;
if (findFile(filename, copy))
for (unsigned int i = 0; i < filename.size(); i++)
{
if(copy.at(i) == '\\' ){
copy.replace(i, 1, "/");
}
}
if(copy.at(0) == '\\' || copy.at(0) == '/')
{
copy.erase(0, 1);
}
if(fsstrict == true)
{
return FileSystemArchive::open(copy, readonly); return FileSystemArchive::open(copy, readonly);
}
int last = copy.size() - 1;
int i = last;
for (;last >= 0; i--)
{
if(copy.at(i) == '/' || copy.at(i) == '\\')
break;
}
std::string folder = copy.substr(0, i); //folder with no slash
std::vector<std::string> current = mlocal[folder];
for(std::vector<std::string>::iterator iter = current.begin(); iter != current.end(); iter++)
{
if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){
return FileSystemArchive::open(*iter, readonly);
}
}
DataStreamPtr p; DataStreamPtr p;
return p; return p;
} }

@ -30,4 +30,9 @@ namespace Files
return iter->second; return iter->second;
} }
const Files::PathContainer& Collections::getPaths() const
{
return mDirectories;
}
} }

@ -21,6 +21,8 @@ namespace Files
/// leading dot and must be all lower-case. /// leading dot and must be all lower-case.
const MultiDirCollection& getCollection(const std::string& extension) const; const MultiDirCollection& getCollection(const std::string& extension) const;
const Files::PathContainer& getPaths() const;
private: private:
typedef std::map<std::string, MultiDirCollection> MultiDirCollectionContainer; typedef std::map<std::string, MultiDirCollection> MultiDirCollectionContainer;
Files::PathContainer mDirectories; Files::PathContainer mDirectories;

@ -1368,7 +1368,7 @@ void NIFLoader::loadResource(Resource *resource)
if (!vfs->isFile(resourceName)) if (!vfs->isFile(resourceName))
{ {
warn("File not found."); warn("File "+resourceName+" not found.");
return; return;
} }

Loading…
Cancel
Save