forked from mirror/openmw-tes3mp
added file collection class
This commit is contained in:
parent
5b6ec405e3
commit
d260e5c1bd
5 changed files with 235 additions and 0 deletions
|
@ -183,9 +183,13 @@ source_group(components\\misc FILES ${MISC} ${MISC_HEADER})
|
||||||
|
|
||||||
set(FILES
|
set(FILES
|
||||||
${COMP_DIR}/files/path.cpp
|
${COMP_DIR}/files/path.cpp
|
||||||
|
${COMP_DIR}/files/multidircollection.cpp
|
||||||
|
${COMP_DIR}/files/collections.cpp
|
||||||
)
|
)
|
||||||
set(FILES_HEADER
|
set(FILES_HEADER
|
||||||
${COMP_DIR}/files/path.hpp
|
${COMP_DIR}/files/path.hpp
|
||||||
|
${COMP_DIR}/files/multidircollection.hpp
|
||||||
|
${COMP_DIR}/files/collections.hpp
|
||||||
)
|
)
|
||||||
source_group(components\\files FILES ${FILES} ${FILES_HEADER})
|
source_group(components\\files FILES ${FILES} ${FILES_HEADER})
|
||||||
|
|
||||||
|
|
25
components/files/collections.cpp
Normal file
25
components/files/collections.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
#include "collections.hpp"
|
||||||
|
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
Collections::Collections (const std::vector<boost::filesystem::path>& directories, bool foldCase)
|
||||||
|
: mDirectories (directories), mFoldCase (foldCase)
|
||||||
|
{}
|
||||||
|
|
||||||
|
const MultiDirCollection& Collections::getCollection (const std::string& extension) const
|
||||||
|
{
|
||||||
|
std::map<std::string, MultiDirCollection>::iterator iter = mCollections.find (extension);
|
||||||
|
|
||||||
|
if (iter==mCollections.end())
|
||||||
|
{
|
||||||
|
std::pair<std::map<std::string, MultiDirCollection>::iterator, bool> result =
|
||||||
|
mCollections.insert (std::make_pair (extension,
|
||||||
|
MultiDirCollection (mDirectories, extension, mFoldCase)));
|
||||||
|
|
||||||
|
iter = result.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
}
|
26
components/files/collections.hpp
Normal file
26
components/files/collections.hpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef COMPONENTS_FILES_COLLECTION_HPP
|
||||||
|
#define COMPONENTS_FILES_COLLECTION_HPP
|
||||||
|
|
||||||
|
#include "multidircollection.hpp"
|
||||||
|
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
class Collections
|
||||||
|
{
|
||||||
|
std::vector<boost::filesystem::path> mDirectories;
|
||||||
|
bool mFoldCase;
|
||||||
|
mutable std::map<std::string, MultiDirCollection> mCollections;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Collections (const std::vector<boost::filesystem::path>& directories, bool foldCase);
|
||||||
|
///< Directories are listed with increasing priority.
|
||||||
|
|
||||||
|
const MultiDirCollection& getCollection (const std::string& extension) const;
|
||||||
|
///< Return a file collection for the given extension. Extension must contain the
|
||||||
|
/// leading dot and must be all lower-case.
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
102
components/files/multidircollection.cpp
Normal file
102
components/files/multidircollection.cpp
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
|
||||||
|
#include "multidircollection.hpp"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
struct NameEqual
|
||||||
|
{
|
||||||
|
bool mStrict;
|
||||||
|
|
||||||
|
NameEqual (bool strict) : mStrict (strict) {}
|
||||||
|
|
||||||
|
bool operator() (const std::string& left, const std::string& right) const
|
||||||
|
{
|
||||||
|
if (mStrict)
|
||||||
|
return left==right;
|
||||||
|
|
||||||
|
std::size_t len = left.length();
|
||||||
|
|
||||||
|
if (len!=right.length())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (std::size_t i=0; i<len; ++i)
|
||||||
|
{
|
||||||
|
char l = std::tolower (left[i]);
|
||||||
|
char r = std::tolower (right[i]);
|
||||||
|
|
||||||
|
if (l!=r)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiDirCollection::MultiDirCollection (const std::vector<boost::filesystem::path>& directories,
|
||||||
|
const std::string& extension, bool foldCase)
|
||||||
|
: mFiles (NameLess (foldCase))
|
||||||
|
{
|
||||||
|
NameEqual equal (foldCase);
|
||||||
|
|
||||||
|
for (std::vector<boost::filesystem::path>::const_iterator iter = directories.begin();
|
||||||
|
iter!=directories.end(); ++iter)
|
||||||
|
{
|
||||||
|
boost::filesystem::path dataDirectory = *iter;
|
||||||
|
|
||||||
|
for (boost::filesystem::directory_iterator iter (dataDirectory);
|
||||||
|
iter!=boost::filesystem::directory_iterator(); ++iter)
|
||||||
|
{
|
||||||
|
boost::filesystem::path path = *iter;
|
||||||
|
|
||||||
|
if (!equal (extension, path.extension()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string filename = path.filename();
|
||||||
|
|
||||||
|
TIter result = mFiles.find (filename);
|
||||||
|
|
||||||
|
if (result==mFiles.end())
|
||||||
|
{
|
||||||
|
mFiles.insert (std::make_pair (filename, path));
|
||||||
|
}
|
||||||
|
else if (result->first==filename)
|
||||||
|
{
|
||||||
|
mFiles[filename] = path;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// handle case folding
|
||||||
|
mFiles.erase (result->first);
|
||||||
|
mFiles.insert (std::make_pair (filename, path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::filesystem::path MultiDirCollection::getPath (const std::string& file) const
|
||||||
|
{
|
||||||
|
TIter iter = mFiles.find (file);
|
||||||
|
|
||||||
|
if (iter==mFiles.end())
|
||||||
|
throw std::runtime_error ("file " + file + " not found");
|
||||||
|
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiDirCollection::TIter MultiDirCollection::begin() const
|
||||||
|
{
|
||||||
|
return mFiles.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiDirCollection::TIter MultiDirCollection::end() const
|
||||||
|
{
|
||||||
|
return mFiles.end();
|
||||||
|
}
|
||||||
|
}
|
78
components/files/multidircollection.hpp
Normal file
78
components/files/multidircollection.hpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#ifndef COMPONENTS_FILES_MULTIDIRSOLLECTION_HPP
|
||||||
|
#define COMPONENTS_FILES_MULTIDIRSOLLECTION_HPP
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
struct NameLess
|
||||||
|
{
|
||||||
|
bool mStrict;
|
||||||
|
|
||||||
|
NameLess (bool strict) : mStrict (strict) {}
|
||||||
|
|
||||||
|
bool operator() (const std::string& left, const std::string& right) const
|
||||||
|
{
|
||||||
|
if (mStrict)
|
||||||
|
return left<right;
|
||||||
|
|
||||||
|
std::size_t min = std::min (left.length(), right.length());
|
||||||
|
|
||||||
|
for (std::size_t i=0; i<min; ++i)
|
||||||
|
{
|
||||||
|
char l = std::tolower (left[i]);
|
||||||
|
char r = std::tolower (right[i]);
|
||||||
|
|
||||||
|
if (l>=r)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left.length()<right.length();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief File collection across several directories
|
||||||
|
///
|
||||||
|
/// This class lists all files with one specific extensions within one or more
|
||||||
|
/// directories. If the same file appears more than once, the file in the directory
|
||||||
|
/// with the higher priority is used.
|
||||||
|
class MultiDirCollection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::map<std::string, boost::filesystem::path, NameLess> TContainer;
|
||||||
|
typedef TContainer::const_iterator TIter;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
TContainer mFiles;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MultiDirCollection (const std::vector<boost::filesystem::path>& directories,
|
||||||
|
const std::string& extension, bool foldCase);
|
||||||
|
///< Directories are listed with increasing priority.
|
||||||
|
/// \param extension The extension that should be listed in this collection. Must
|
||||||
|
/// contain the leading dot.
|
||||||
|
/// \param foldCase Ignore filename case
|
||||||
|
|
||||||
|
boost::filesystem::path getPath (const std::string& file) const;
|
||||||
|
///< Return full path (including filename) of \æ file.
|
||||||
|
///
|
||||||
|
/// If the file does not exist, an exception is thrown. \a file must include
|
||||||
|
/// the extension.
|
||||||
|
|
||||||
|
TIter begin() const;
|
||||||
|
///< Return iterator pointing to the first file.
|
||||||
|
|
||||||
|
TIter end() const;
|
||||||
|
///< Return iterator pointing past the last file.
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue