mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-30 05:47:57 +03:00
Imported Upstream version 0.26.0
This commit is contained in:
commit
9a2b6c69b6
1398 changed files with 212217 additions and 0 deletions
64
components/files/collections.cpp
Normal file
64
components/files/collections.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
|
||||
#include "collections.hpp"
|
||||
|
||||
namespace Files
|
||||
{
|
||||
Collections::Collections()
|
||||
: mDirectories()
|
||||
, mFoldCase(false)
|
||||
, mCollections()
|
||||
{
|
||||
}
|
||||
|
||||
Collections::Collections(const Files::PathContainer& directories, bool foldCase)
|
||||
: mDirectories(directories)
|
||||
, mFoldCase(foldCase)
|
||||
, mCollections()
|
||||
{
|
||||
}
|
||||
|
||||
const MultiDirCollection& Collections::getCollection(const std::string& extension) const
|
||||
{
|
||||
MultiDirCollectionContainer::iterator iter = mCollections.find(extension);
|
||||
if (iter==mCollections.end())
|
||||
{
|
||||
std::pair<MultiDirCollectionContainer::iterator, bool> result =
|
||||
mCollections.insert(std::make_pair(extension, MultiDirCollection(mDirectories, extension, mFoldCase)));
|
||||
|
||||
iter = result.first;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
boost::filesystem::path Collections::getPath(const std::string& file) const
|
||||
{
|
||||
for (Files::PathContainer::const_iterator iter = mDirectories.begin();
|
||||
iter != mDirectories.end(); ++iter)
|
||||
{
|
||||
const boost::filesystem::path path = *iter / file;
|
||||
if (boost::filesystem::exists(path))
|
||||
return path.string();
|
||||
}
|
||||
|
||||
throw std::runtime_error ("file " + file + " not found");
|
||||
}
|
||||
|
||||
bool Collections::doesExist(const std::string& file) const
|
||||
{
|
||||
for (Files::PathContainer::const_iterator iter = mDirectories.begin();
|
||||
iter != mDirectories.end(); ++iter)
|
||||
{
|
||||
const boost::filesystem::path path = *iter / file;
|
||||
if (boost::filesystem::exists(path))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const Files::PathContainer& Collections::getPaths() const
|
||||
{
|
||||
return mDirectories;
|
||||
}
|
||||
}
|
43
components/files/collections.hpp
Normal file
43
components/files/collections.hpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef COMPONENTS_FILES_COLLECTION_HPP
|
||||
#define COMPONENTS_FILES_COLLECTION_HPP
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "multidircollection.hpp"
|
||||
|
||||
namespace Files
|
||||
{
|
||||
class Collections
|
||||
{
|
||||
public:
|
||||
Collections();
|
||||
|
||||
///< Directories are listed with increasing priority.
|
||||
Collections(const Files::PathContainer& directories, bool foldCase);
|
||||
|
||||
///< Return a file collection for the given extension. Extension must contain the
|
||||
/// leading dot and must be all lower-case.
|
||||
const MultiDirCollection& getCollection(const std::string& extension) const;
|
||||
|
||||
boost::filesystem::path getPath(const std::string& file) const;
|
||||
///< Return full path (including filename) of \a file.
|
||||
///
|
||||
/// If the file does not exist in any of the collection's
|
||||
/// directories, an exception is thrown. \a file must include the
|
||||
/// extension.
|
||||
|
||||
bool doesExist(const std::string& file) const;
|
||||
///< \return Does a file with the given name exist?
|
||||
|
||||
const Files::PathContainer& getPaths() const;
|
||||
|
||||
private:
|
||||
typedef std::map<std::string, MultiDirCollection> MultiDirCollectionContainer;
|
||||
Files::PathContainer mDirectories;
|
||||
|
||||
bool mFoldCase;
|
||||
mutable MultiDirCollectionContainer mCollections;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
165
components/files/configurationmanager.cpp
Normal file
165
components/files/configurationmanager.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
#include "configurationmanager.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/algorithm/string/erase.hpp>
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files
|
||||
{
|
||||
|
||||
static const char* const openmwCfgFile = "openmw.cfg";
|
||||
|
||||
const char* const mwToken = "?mw?";
|
||||
const char* const localToken = "?local?";
|
||||
const char* const userToken = "?user?";
|
||||
const char* const globalToken = "?global?";
|
||||
|
||||
ConfigurationManager::ConfigurationManager()
|
||||
: mFixedPath("openmw")
|
||||
{
|
||||
setupTokensMapping();
|
||||
|
||||
boost::filesystem::create_directories(mFixedPath.getUserPath());
|
||||
|
||||
mLogPath = mFixedPath.getUserPath();
|
||||
}
|
||||
|
||||
ConfigurationManager::~ConfigurationManager()
|
||||
{
|
||||
}
|
||||
|
||||
void ConfigurationManager::setupTokensMapping()
|
||||
{
|
||||
mTokensMapping.insert(std::make_pair(mwToken, &FixedPath<>::getInstallPath));
|
||||
mTokensMapping.insert(std::make_pair(localToken, &FixedPath<>::getLocalPath));
|
||||
mTokensMapping.insert(std::make_pair(userToken, &FixedPath<>::getUserPath));
|
||||
mTokensMapping.insert(std::make_pair(globalToken, &FixedPath<>::getGlobalDataPath));
|
||||
}
|
||||
|
||||
void ConfigurationManager::readConfiguration(boost::program_options::variables_map& variables,
|
||||
boost::program_options::options_description& description)
|
||||
{
|
||||
loadConfig(mFixedPath.getUserPath(), variables, description);
|
||||
boost::program_options::notify(variables);
|
||||
|
||||
loadConfig(mFixedPath.getLocalPath(), variables, description);
|
||||
boost::program_options::notify(variables);
|
||||
loadConfig(mFixedPath.getGlobalPath(), variables, description);
|
||||
boost::program_options::notify(variables);
|
||||
|
||||
}
|
||||
|
||||
void ConfigurationManager::processPaths(Files::PathContainer& dataDirs)
|
||||
{
|
||||
std::string path;
|
||||
for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
|
||||
{
|
||||
path = it->string();
|
||||
boost::erase_all(path, "\"");
|
||||
*it = boost::filesystem::path(path);
|
||||
|
||||
// Check if path contains a token
|
||||
if (!path.empty() && *path.begin() == '?')
|
||||
{
|
||||
std::string::size_type pos = path.find('?', 1);
|
||||
if (pos != std::string::npos && pos != 0)
|
||||
{
|
||||
TokensMappingContainer::iterator tokenIt = mTokensMapping.find(path.substr(0, pos + 1));
|
||||
if (tokenIt != mTokensMapping.end())
|
||||
{
|
||||
boost::filesystem::path tempPath(((mFixedPath).*(tokenIt->second))());
|
||||
if (pos < path.length() - 1)
|
||||
{
|
||||
// There is something after the token, so we should
|
||||
// append it to the path
|
||||
tempPath /= path.substr(pos + 1, path.length() - pos);
|
||||
}
|
||||
|
||||
*it = tempPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clean invalid / unknown token, it will be removed outside the loop
|
||||
(*it).clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_directory(*it))
|
||||
{
|
||||
(*it).clear();
|
||||
}
|
||||
}
|
||||
|
||||
dataDirs.erase(std::remove_if(dataDirs.begin(), dataDirs.end(),
|
||||
boost::bind(&boost::filesystem::path::empty, _1)), dataDirs.end());
|
||||
}
|
||||
|
||||
void ConfigurationManager::loadConfig(const boost::filesystem::path& path,
|
||||
boost::program_options::variables_map& variables,
|
||||
boost::program_options::options_description& description)
|
||||
{
|
||||
boost::filesystem::path cfgFile(path);
|
||||
cfgFile /= std::string(openmwCfgFile);
|
||||
if (boost::filesystem::is_regular_file(cfgFile))
|
||||
{
|
||||
std::cout << "Loading config file: " << cfgFile.string() << "... ";
|
||||
|
||||
std::ifstream configFileStream(cfgFile.string().c_str());
|
||||
if (configFileStream.is_open())
|
||||
{
|
||||
boost::program_options::store(boost::program_options::parse_config_file(
|
||||
configFileStream, description, true), variables);
|
||||
|
||||
std::cout << "done." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "failed." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const boost::filesystem::path& ConfigurationManager::getGlobalPath() const
|
||||
{
|
||||
return mFixedPath.getGlobalPath();
|
||||
}
|
||||
|
||||
const boost::filesystem::path& ConfigurationManager::getUserPath() const
|
||||
{
|
||||
return mFixedPath.getUserPath();
|
||||
}
|
||||
|
||||
const boost::filesystem::path& ConfigurationManager::getLocalPath() const
|
||||
{
|
||||
return mFixedPath.getLocalPath();
|
||||
}
|
||||
|
||||
const boost::filesystem::path& ConfigurationManager::getGlobalDataPath() const
|
||||
{
|
||||
return mFixedPath.getGlobalDataPath();
|
||||
}
|
||||
|
||||
const boost::filesystem::path& ConfigurationManager::getCachePath() const
|
||||
{
|
||||
return mFixedPath.getCachePath();
|
||||
}
|
||||
|
||||
const boost::filesystem::path& ConfigurationManager::getInstallPath() const
|
||||
{
|
||||
return mFixedPath.getInstallPath();
|
||||
}
|
||||
|
||||
const boost::filesystem::path& ConfigurationManager::getLogPath() const
|
||||
{
|
||||
return mLogPath;
|
||||
}
|
||||
|
||||
} /* namespace Cfg */
|
74
components/files/configurationmanager.hpp
Normal file
74
components/files/configurationmanager.hpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#ifndef COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP
|
||||
#define COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <boost/tr1/tr1/unordered_map>
|
||||
#elif defined HAVE_UNORDERED_MAP
|
||||
#include <unordered_map>
|
||||
#else
|
||||
#include <tr1/unordered_map>
|
||||
#endif
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <components/files/fixedpath.hpp>
|
||||
#include <components/files/collections.hpp>
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files
|
||||
{
|
||||
|
||||
/**
|
||||
* \struct ConfigurationManager
|
||||
*/
|
||||
struct ConfigurationManager
|
||||
{
|
||||
ConfigurationManager();
|
||||
virtual ~ConfigurationManager();
|
||||
|
||||
void readConfiguration(boost::program_options::variables_map& variables,
|
||||
boost::program_options::options_description& description);
|
||||
void processPaths(Files::PathContainer& dataDirs);
|
||||
|
||||
/**< Fixed paths */
|
||||
const boost::filesystem::path& getGlobalPath() const;
|
||||
const boost::filesystem::path& getUserPath() const;
|
||||
const boost::filesystem::path& getLocalPath() const;
|
||||
|
||||
const boost::filesystem::path& getGlobalDataPath() const;
|
||||
const boost::filesystem::path& getUserDataPath() const;
|
||||
const boost::filesystem::path& getLocalDataPath() const;
|
||||
const boost::filesystem::path& getInstallPath() const;
|
||||
|
||||
const boost::filesystem::path& getCachePath() const;
|
||||
|
||||
const boost::filesystem::path& getLogPath() const;
|
||||
|
||||
private:
|
||||
typedef Files::FixedPath<> FixedPathType;
|
||||
|
||||
typedef const boost::filesystem::path& (FixedPathType::*path_type_f)() const;
|
||||
#if defined HAVE_UNORDERED_MAP
|
||||
typedef std::unordered_map<std::string, path_type_f> TokensMappingContainer;
|
||||
#else
|
||||
typedef std::tr1::unordered_map<std::string, path_type_f> TokensMappingContainer;
|
||||
#endif
|
||||
|
||||
void loadConfig(const boost::filesystem::path& path,
|
||||
boost::program_options::variables_map& variables,
|
||||
boost::program_options::options_description& description);
|
||||
|
||||
void setupTokensMapping();
|
||||
|
||||
FixedPathType mFixedPath;
|
||||
|
||||
boost::filesystem::path mLogPath;
|
||||
|
||||
TokensMappingContainer mTokensMapping;
|
||||
};
|
||||
|
||||
} /* namespace Cfg */
|
||||
|
||||
#endif /* COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP */
|
172
components/files/constrainedfiledatastream.cpp
Normal file
172
components/files/constrainedfiledatastream.cpp
Normal file
|
@ -0,0 +1,172 @@
|
|||
#include "constrainedfiledatastream.hpp"
|
||||
#include "lowlevelfile.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
#include <libs/platform/stdint.h>
|
||||
|
||||
namespace {
|
||||
|
||||
class ConstrainedDataStream : public Ogre::DataStream {
|
||||
public:
|
||||
|
||||
static const size_t sBufferSize = 4096; // somewhat arbitrary though 64KB buffers didn't seem to improve performance any
|
||||
static const size_t sBufferThreshold = 1024; // reads larger than this bypass buffering as cost of memcpy outweighs cost of system call
|
||||
|
||||
ConstrainedDataStream(const Ogre::String &fname, size_t start, size_t length)
|
||||
{
|
||||
mFile.open (fname.c_str ());
|
||||
mSize = length != 0xFFFFFFFF ? length : mFile.size () - start;
|
||||
|
||||
mPos = 0;
|
||||
mOrigin = start;
|
||||
mExtent = start + mSize;
|
||||
|
||||
mBufferOrigin = 0;
|
||||
mBufferExtent = 0;
|
||||
}
|
||||
|
||||
|
||||
size_t read(void* buf, size_t count)
|
||||
{
|
||||
assert (mPos <= mSize);
|
||||
|
||||
uint8_t * out = reinterpret_cast <uint8_t *> (buf);
|
||||
|
||||
size_t posBeg = mOrigin + mPos;
|
||||
size_t posEnd = posBeg + count;
|
||||
|
||||
if (posEnd > mExtent)
|
||||
posEnd = mExtent;
|
||||
|
||||
size_t posCur = posBeg;
|
||||
|
||||
while (posCur != posEnd)
|
||||
{
|
||||
size_t readLeft = posEnd - posCur;
|
||||
|
||||
if (posCur < mBufferOrigin || posCur >= mBufferExtent)
|
||||
{
|
||||
if (readLeft >= sBufferThreshold || (posCur == mOrigin && posEnd == mExtent))
|
||||
{
|
||||
assert (mFile.tell () == mBufferExtent);
|
||||
|
||||
if (posCur != mBufferExtent)
|
||||
mFile.seek (posCur);
|
||||
|
||||
posCur += mFile.read (out, readLeft);
|
||||
|
||||
mBufferOrigin = mBufferExtent = posCur;
|
||||
|
||||
mPos = posCur - mOrigin;
|
||||
|
||||
return posCur - posBeg;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t newBufferOrigin;
|
||||
|
||||
if ((posCur < mBufferOrigin) && (mBufferOrigin - posCur < sBufferSize))
|
||||
newBufferOrigin = std::max (mOrigin, mBufferOrigin > sBufferSize ? mBufferOrigin - sBufferSize : 0);
|
||||
else
|
||||
newBufferOrigin = posCur;
|
||||
|
||||
fill (newBufferOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
size_t xfer = std::min (readLeft, mBufferExtent - posCur);
|
||||
|
||||
memcpy (out, mBuffer + (posCur - mBufferOrigin), xfer);
|
||||
|
||||
posCur += xfer;
|
||||
out += xfer;
|
||||
}
|
||||
|
||||
count = posEnd - posBeg;
|
||||
mPos += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
void skip(long count)
|
||||
{
|
||||
assert (mPos <= mSize);
|
||||
|
||||
if((count >= 0 && (size_t)count <= mSize-mPos) ||
|
||||
(count < 0 && (size_t)-count <= mPos))
|
||||
mPos += count;
|
||||
}
|
||||
|
||||
void seek(size_t pos)
|
||||
{
|
||||
assert (mPos <= mSize);
|
||||
|
||||
if (pos < mSize)
|
||||
mPos = pos;
|
||||
}
|
||||
|
||||
virtual size_t tell() const
|
||||
{
|
||||
assert (mPos <= mSize);
|
||||
|
||||
return mPos;
|
||||
}
|
||||
|
||||
virtual bool eof() const
|
||||
{
|
||||
assert (mPos <= mSize);
|
||||
|
||||
return mPos == mSize;
|
||||
}
|
||||
|
||||
virtual void close()
|
||||
{
|
||||
mFile.close();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void fill (size_t newOrigin)
|
||||
{
|
||||
assert (mFile.tell () == mBufferExtent);
|
||||
|
||||
size_t newExtent = newOrigin + sBufferSize;
|
||||
|
||||
if (newExtent > mExtent)
|
||||
newExtent = mExtent;
|
||||
|
||||
size_t oldExtent = mBufferExtent;
|
||||
|
||||
if (newOrigin != oldExtent)
|
||||
mFile.seek (newOrigin);
|
||||
|
||||
mBufferOrigin = mBufferExtent = newOrigin;
|
||||
|
||||
size_t amountRequested = newExtent - newOrigin;
|
||||
|
||||
size_t amountRead = mFile.read (mBuffer, amountRequested);
|
||||
|
||||
if (amountRead != amountRequested)
|
||||
throw std::runtime_error ("An unexpected condition occurred while reading from a file.");
|
||||
|
||||
mBufferExtent = newExtent;
|
||||
}
|
||||
|
||||
LowLevelFile mFile;
|
||||
|
||||
size_t mOrigin;
|
||||
size_t mExtent;
|
||||
size_t mPos;
|
||||
|
||||
uint8_t mBuffer [sBufferSize];
|
||||
size_t mBufferOrigin;
|
||||
size_t mBufferExtent;
|
||||
};
|
||||
|
||||
} // end of unnamed namespace
|
||||
|
||||
Ogre::DataStreamPtr openConstrainedFileDataStream (char const * filename, size_t offset, size_t length)
|
||||
{
|
||||
return Ogre::DataStreamPtr(new ConstrainedDataStream(filename, offset, length));
|
||||
}
|
8
components/files/constrainedfiledatastream.hpp
Normal file
8
components/files/constrainedfiledatastream.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef COMPONENTS_FILES_CONSTRAINEDFILEDATASTREAM_HPP
|
||||
#define COMPONENTS_FILES_CONSTRAINEDFILEDATASTREAM_HPP
|
||||
|
||||
#include <OgreDataStream.h>
|
||||
|
||||
Ogre::DataStreamPtr openConstrainedFileDataStream (char const * filename, size_t offset = 0, size_t length = 0xFFFFFFFF);
|
||||
|
||||
#endif // COMPONENTS_FILES_CONSTRAINEDFILEDATASTREAM_HPP
|
120
components/files/filelibrary.cpp
Normal file
120
components/files/filelibrary.cpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
#include "filelibrary.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <../components/misc/stringops.hpp>
|
||||
|
||||
namespace Files
|
||||
{
|
||||
// Looks for a string in a vector of strings
|
||||
bool containsVectorString(const StringVector& list, const std::string& str)
|
||||
{
|
||||
for (StringVector::const_iterator iter = list.begin();
|
||||
iter != list.end(); ++iter)
|
||||
{
|
||||
if (*iter == str)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Searches a path and adds the results to the library
|
||||
void FileLibrary::add(const boost::filesystem::path &root, bool recursive, bool strict,
|
||||
const StringVector &acceptableExtensions)
|
||||
{
|
||||
if (!boost::filesystem::exists(root))
|
||||
{
|
||||
std::cout << "Warning " << root.string() << " does not exist.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string fileExtension;
|
||||
std::string type;
|
||||
|
||||
// remember the last location of the priority list when listing new items
|
||||
int length = mPriorityList.size();
|
||||
|
||||
// First makes a list of all candidate files
|
||||
FileLister(root, mPriorityList, recursive);
|
||||
|
||||
// Then sort these files into sections according to the folder they belong to
|
||||
for (PathContainer::iterator listIter = mPriorityList.begin() + length;
|
||||
listIter != mPriorityList.end(); ++listIter)
|
||||
{
|
||||
if( !acceptableExtensions.empty() )
|
||||
{
|
||||
fileExtension = boost::filesystem::path (listIter->extension()).string();
|
||||
Misc::StringUtils::toLower(fileExtension);
|
||||
if(!containsVectorString(acceptableExtensions, fileExtension))
|
||||
continue;
|
||||
}
|
||||
|
||||
type = boost::filesystem::path (listIter->parent_path().leaf()).string();
|
||||
if (!strict)
|
||||
Misc::StringUtils::toLower(type);
|
||||
|
||||
mMap[type].push_back(*listIter);
|
||||
// std::cout << "Added path: " << listIter->string() << " in section "<< type <<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the named section exists
|
||||
bool FileLibrary::containsSection(std::string sectionName, bool strict)
|
||||
{
|
||||
if (!strict)
|
||||
Misc::StringUtils::toLower(sectionName);
|
||||
StringPathContMap::const_iterator mapIter = mMap.find(sectionName);
|
||||
if (mapIter == mMap.end())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns a pointer to const for a section of the library
|
||||
const PathContainer* FileLibrary::section(std::string sectionName, bool strict)
|
||||
{
|
||||
if (!strict)
|
||||
Misc::StringUtils::toLower(sectionName);
|
||||
StringPathContMap::const_iterator mapIter = mMap.find(sectionName);
|
||||
if (mapIter == mMap.end())
|
||||
{
|
||||
//std::cout << "Empty\n";
|
||||
return &mEmptyPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &(mapIter->second);
|
||||
}
|
||||
}
|
||||
|
||||
// Searches the library for an item and returns a boost path to it
|
||||
boost::filesystem::path FileLibrary::locate(std::string item, bool strict, bool ignoreExtensions, std::string sectionName)
|
||||
{
|
||||
boost::filesystem::path result("");
|
||||
if (sectionName == "")
|
||||
{
|
||||
return FileListLocator(mPriorityList, boost::filesystem::path(item), strict, ignoreExtensions);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!containsSection(sectionName, strict))
|
||||
{
|
||||
std::cout << "Warning: There is no section named " << sectionName << "\n";
|
||||
return result;
|
||||
}
|
||||
result = FileListLocator(mMap[sectionName], boost::filesystem::path(item), strict, ignoreExtensions);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Prints all the available sections, used for debugging
|
||||
void FileLibrary::printSections()
|
||||
{
|
||||
for(StringPathContMap::const_iterator mapIter = mMap.begin();
|
||||
mapIter != mMap.end(); ++mapIter)
|
||||
{
|
||||
std::cout << mapIter->first <<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
49
components/files/filelibrary.hpp
Normal file
49
components/files/filelibrary.hpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef COMPONENTS_FILES_FILELIBRARY_HPP
|
||||
#define COMPONENTS_FILES_FILELIBRARY_HPP
|
||||
|
||||
#include <components/files/fileops.hpp>
|
||||
|
||||
namespace Files
|
||||
{
|
||||
typedef std::map<std::string, PathContainer> StringPathContMap;
|
||||
typedef std::vector<std::string> StringVector;
|
||||
|
||||
/// Looks for a string in a vector of strings
|
||||
bool containsVectorString(const StringVector& list, const std::string& str);
|
||||
|
||||
/// \brief Searches directories and makes lists of files according to folder name
|
||||
class FileLibrary
|
||||
{
|
||||
private:
|
||||
StringPathContMap mMap;
|
||||
PathContainer mEmptyPath;
|
||||
PathContainer mPriorityList;
|
||||
|
||||
public:
|
||||
/// Searches a path and adds the results to the library
|
||||
/// Recursive search and fs strict options are available
|
||||
/// Takes a vector of acceptable files extensions, if none is given it lists everything.
|
||||
void add(const boost::filesystem::path &root, bool recursive, bool strict,
|
||||
const StringVector &acceptableExtensions);
|
||||
|
||||
/// Returns true if the named section exists
|
||||
/// You can run this check before running section()
|
||||
bool containsSection(std::string sectionName, bool strict);
|
||||
|
||||
/// Returns a pointer to const for a section of the library
|
||||
/// which is essentially a PathContainer.
|
||||
/// If the section does not exists it returns a pointer to an empty path.
|
||||
const PathContainer* section(std::string sectionName, bool strict);
|
||||
|
||||
/// Searches the library for an item and returns a boost path to it
|
||||
/// Optionally you can provide a specific section
|
||||
/// The result is the first that comes up according to alphabetical
|
||||
/// section naming
|
||||
boost::filesystem::path locate(std::string item, bool strict, bool ignoreExtensions, std::string sectionName="");
|
||||
|
||||
/// Prints all the available sections, used for debugging
|
||||
void printSections();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
120
components/files/fileops.cpp
Normal file
120
components/files/fileops.cpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
#include "fileops.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <../components/misc/stringops.hpp>
|
||||
|
||||
namespace Files
|
||||
{
|
||||
|
||||
bool isFile(const char *name)
|
||||
{
|
||||
return boost::filesystem::exists(boost::filesystem::path(name));
|
||||
}
|
||||
|
||||
// Returns true if the last part of the superset matches the subset
|
||||
bool endingMatches(const std::string& superset, const std::string& subset)
|
||||
{
|
||||
if (subset.length() > superset.length())
|
||||
return false;
|
||||
return superset.substr(superset.length() - subset.length()) == subset;
|
||||
}
|
||||
|
||||
// Makes a list of files from a directory
|
||||
void FileLister( boost::filesystem::path currentPath, Files::PathContainer& list, bool recursive)
|
||||
{
|
||||
if (!boost::filesystem::exists(currentPath))
|
||||
{
|
||||
std::cout << "WARNING: " << currentPath.string() << " does not exist.\n";
|
||||
return ;
|
||||
}
|
||||
if (recursive)
|
||||
{
|
||||
for ( boost::filesystem::recursive_directory_iterator end, itr(currentPath.string());
|
||||
itr != end; ++itr )
|
||||
{
|
||||
if ( boost::filesystem::is_regular_file(*itr))
|
||||
list.push_back(itr->path());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( boost::filesystem::directory_iterator end, itr(currentPath.string());
|
||||
itr != end; ++itr )
|
||||
{
|
||||
if ( boost::filesystem::is_regular_file(*itr))
|
||||
list.push_back(itr->path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Locates path in path container
|
||||
boost::filesystem::path FileListLocator (const Files::PathContainer& list, const boost::filesystem::path& toFind,
|
||||
bool strict, bool ignoreExtensions)
|
||||
{
|
||||
boost::filesystem::path result("");
|
||||
if (list.empty())
|
||||
return result;
|
||||
|
||||
std::string toFindStr;
|
||||
if (ignoreExtensions)
|
||||
toFindStr = boost::filesystem::basename(toFind);
|
||||
else
|
||||
toFindStr = toFind.string();
|
||||
|
||||
std::string fullPath;
|
||||
|
||||
// The filesystems slash sets the default slash
|
||||
std::string slash;
|
||||
std::string wrongslash;
|
||||
if(list[0].string().find("\\") != std::string::npos)
|
||||
{
|
||||
slash = "\\";
|
||||
wrongslash = "/";
|
||||
}
|
||||
else
|
||||
{
|
||||
slash = "/";
|
||||
wrongslash = "\\";
|
||||
}
|
||||
|
||||
// The file being looked for is converted to the new slash
|
||||
if(toFindStr.find(wrongslash) != std::string::npos )
|
||||
{
|
||||
boost::replace_all(toFindStr, wrongslash, slash);
|
||||
}
|
||||
|
||||
if (!strict)
|
||||
{
|
||||
Misc::StringUtils::toLower(toFindStr);
|
||||
}
|
||||
|
||||
for (Files::PathContainer::const_iterator it = list.begin(); it != list.end(); ++it)
|
||||
{
|
||||
fullPath = it->string();
|
||||
if (ignoreExtensions)
|
||||
fullPath.erase(fullPath.length() -
|
||||
boost::filesystem::path (it->extension()).string().length());
|
||||
|
||||
if (!strict)
|
||||
{
|
||||
Misc::StringUtils::toLower(fullPath);
|
||||
}
|
||||
if(endingMatches(fullPath, toFindStr))
|
||||
{
|
||||
result = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Overloaded form of the locator that takes a string and returns a string
|
||||
std::string FileListLocator (const Files::PathContainer& list,const std::string& toFind, bool strict, bool ignoreExtensions)
|
||||
{
|
||||
return FileListLocator(list, boost::filesystem::path(toFind), strict, ignoreExtensions).string();
|
||||
}
|
||||
|
||||
}
|
38
components/files/fileops.hpp
Normal file
38
components/files/fileops.hpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef COMPONENTS_FILES_FILEOPS_HPP
|
||||
#define COMPONENTS_FILES_FILEOPS_HPP
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
namespace Files
|
||||
{
|
||||
|
||||
///\brief Check if a given path is an existing file (not a directory)
|
||||
///\param [in] name - filename
|
||||
bool isFile(const char *name);
|
||||
|
||||
/// A vector of Boost Paths, very handy
|
||||
typedef std::vector<boost::filesystem::path> PathContainer;
|
||||
|
||||
/// Makes a list of files from a directory by taking a boost
|
||||
/// path and a Path Container and adds to the Path container
|
||||
/// all files in the path. It has a recursive option.
|
||||
void FileLister( boost::filesystem::path currentPath, Files::PathContainer& list, bool recursive);
|
||||
|
||||
/// Locates boost path in path container
|
||||
/// returns the path from the container
|
||||
/// that contains the searched path.
|
||||
/// If it's not found it returns and empty path
|
||||
/// Takes care of slashes, backslashes and it has a strict option.
|
||||
boost::filesystem::path FileListLocator (const Files::PathContainer& list, const boost::filesystem::path& toFind,
|
||||
bool strict, bool ignoreExtensions);
|
||||
|
||||
/// Overloaded form of the locator that takes a string and returns a string
|
||||
std::string FileListLocator (const Files::PathContainer& list,const std::string& toFind, bool strict, bool ignoreExtensions);
|
||||
|
||||
}
|
||||
|
||||
#endif /* COMPONENTS_FILES_FILEOPS_HPP */
|
123
components/files/fixedpath.hpp
Normal file
123
components/files/fixedpath.hpp
Normal file
|
@ -0,0 +1,123 @@
|
|||
#ifndef COMPONENTS_FILES_FIXEDPATH_HPP
|
||||
#define COMPONENTS_FILES_FIXEDPATH_HPP
|
||||
|
||||
#include <string>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
#include <components/files/linuxpath.hpp>
|
||||
namespace Files { typedef LinuxPath TargetPathType; }
|
||||
|
||||
#elif defined(__WIN32) || defined(__WINDOWS__) || defined(_WIN32)
|
||||
#include <components/files/windowspath.hpp>
|
||||
namespace Files { typedef WindowsPath TargetPathType; }
|
||||
|
||||
#elif defined(macintosh) || defined(Macintosh) || defined(__APPLE__) || defined(__MACH__)
|
||||
#include <components/files/macospath.hpp>
|
||||
namespace Files { typedef MacOsPath TargetPathType; }
|
||||
|
||||
#else
|
||||
#error "Unknown platform!"
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files
|
||||
{
|
||||
|
||||
/**
|
||||
* \struct Path
|
||||
*
|
||||
* \tparam P - Path strategy class type (depends on target system)
|
||||
*
|
||||
*/
|
||||
template
|
||||
<
|
||||
class P = TargetPathType
|
||||
>
|
||||
struct FixedPath
|
||||
{
|
||||
typedef P PathType;
|
||||
|
||||
/**
|
||||
* \brief Path constructor.
|
||||
*
|
||||
* \param [in] application_name - Name of the application
|
||||
*/
|
||||
FixedPath(const std::string& application_name)
|
||||
: mPath(application_name + "/")
|
||||
, mUserPath(mPath.getUserPath())
|
||||
, mGlobalPath(mPath.getGlobalPath())
|
||||
, mLocalPath(mPath.getLocalPath())
|
||||
, mGlobalDataPath(mPath.getGlobalDataPath())
|
||||
, mInstallPath(mPath.getInstallPath())
|
||||
, mCachePath(mPath.getCachePath())
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return path pointing to the user local configuration directory.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
const boost::filesystem::path& getUserPath() const
|
||||
{
|
||||
return mUserPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return path pointing to the global (system) configuration directory.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
const boost::filesystem::path& getGlobalPath() const
|
||||
{
|
||||
return mGlobalPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return path pointing to the directory where application was started.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
const boost::filesystem::path& getLocalPath() const
|
||||
{
|
||||
return mLocalPath;
|
||||
}
|
||||
|
||||
const boost::filesystem::path& getInstallPath() const
|
||||
{
|
||||
return mInstallPath;
|
||||
}
|
||||
|
||||
const boost::filesystem::path& getGlobalDataPath() const
|
||||
{
|
||||
return mGlobalDataPath;
|
||||
}
|
||||
|
||||
const boost::filesystem::path& getCachePath() const
|
||||
{
|
||||
return mCachePath;
|
||||
}
|
||||
|
||||
private:
|
||||
PathType mPath;
|
||||
|
||||
boost::filesystem::path mUserPath; /**< User path */
|
||||
boost::filesystem::path mGlobalPath; /**< Global path */
|
||||
boost::filesystem::path mLocalPath; /**< It is the same directory where application was run */
|
||||
|
||||
boost::filesystem::path mGlobalDataPath; /**< Global application data path */
|
||||
|
||||
boost::filesystem::path mCachePath;
|
||||
|
||||
boost::filesystem::path mInstallPath;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} /* namespace Files */
|
||||
|
||||
#endif /* COMPONENTS_FILES_FIXEDPATH_HPP */
|
164
components/files/linuxpath.cpp
Normal file
164
components/files/linuxpath.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
#include "linuxpath.hpp"
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files
|
||||
{
|
||||
|
||||
LinuxPath::LinuxPath(const std::string& application_name)
|
||||
: mName(application_name)
|
||||
{
|
||||
}
|
||||
|
||||
boost::filesystem::path LinuxPath::getUserPath() const
|
||||
{
|
||||
boost::filesystem::path userPath(".");
|
||||
|
||||
const char* theDir = getenv("HOME");
|
||||
if (theDir == NULL)
|
||||
{
|
||||
struct passwd* pwd = getpwuid(getuid());
|
||||
if (pwd != NULL)
|
||||
{
|
||||
theDir = pwd->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (theDir != NULL)
|
||||
{
|
||||
userPath = boost::filesystem::path(theDir);
|
||||
}
|
||||
|
||||
return userPath / ".config" / mName;
|
||||
}
|
||||
|
||||
boost::filesystem::path LinuxPath::getCachePath() const
|
||||
{
|
||||
boost::filesystem::path userPath(".");
|
||||
|
||||
const char* theDir = getenv("HOME");
|
||||
if (theDir == NULL)
|
||||
{
|
||||
struct passwd* pwd = getpwuid(getuid());
|
||||
if (pwd != NULL)
|
||||
{
|
||||
theDir = pwd->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (theDir != NULL)
|
||||
{
|
||||
userPath = boost::filesystem::path(theDir);
|
||||
}
|
||||
|
||||
return userPath / ".cache" / mName;
|
||||
}
|
||||
|
||||
boost::filesystem::path LinuxPath::getGlobalPath() const
|
||||
{
|
||||
boost::filesystem::path globalPath("/etc/");
|
||||
return globalPath / mName;
|
||||
}
|
||||
|
||||
boost::filesystem::path LinuxPath::getLocalPath() const
|
||||
{
|
||||
return boost::filesystem::path("./");
|
||||
}
|
||||
|
||||
boost::filesystem::path LinuxPath::getGlobalDataPath() const
|
||||
{
|
||||
boost::filesystem::path globalDataPath("/usr/share/games/");
|
||||
return globalDataPath / mName;
|
||||
}
|
||||
|
||||
boost::filesystem::path LinuxPath::getInstallPath() const
|
||||
{
|
||||
boost::filesystem::path installPath;
|
||||
|
||||
char *homePath = getenv("HOME");
|
||||
if (homePath == NULL)
|
||||
{
|
||||
struct passwd* pwd = getpwuid(getuid());
|
||||
if (pwd != NULL)
|
||||
{
|
||||
homePath = pwd->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (homePath != NULL)
|
||||
{
|
||||
boost::filesystem::path wineDefaultRegistry(homePath);
|
||||
wineDefaultRegistry /= ".wine/system.reg";
|
||||
|
||||
if (boost::filesystem::is_regular_file(wineDefaultRegistry))
|
||||
{
|
||||
boost::filesystem::ifstream file(wineDefaultRegistry);
|
||||
bool isRegEntry = false;
|
||||
std::string line;
|
||||
std::string mwpath;
|
||||
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
if (line[0] == '[') // we found an entry
|
||||
{
|
||||
if (isRegEntry)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
isRegEntry = (line.find("Softworks\\\\Morrowind]") != std::string::npos);
|
||||
}
|
||||
else if (isRegEntry)
|
||||
{
|
||||
if (line[0] == '"') // empty line means new registry key
|
||||
{
|
||||
std::string key = line.substr(1, line.find('"', 1) - 1);
|
||||
if (strcasecmp(key.c_str(), "Installed Path") == 0)
|
||||
{
|
||||
std::string::size_type valuePos = line.find('=') + 2;
|
||||
mwpath = line.substr(valuePos, line.rfind('"') - valuePos);
|
||||
|
||||
std::string::size_type pos = mwpath.find("\\");
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
mwpath.replace(pos, 2, "/");
|
||||
pos = mwpath.find("\\", pos + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mwpath.empty())
|
||||
{
|
||||
// Change drive letter to lowercase, so we could use
|
||||
// ~/.wine/dosdevices symlinks
|
||||
mwpath[0] = tolower(mwpath[0]);
|
||||
installPath /= homePath;
|
||||
installPath /= ".wine/dosdevices/";
|
||||
installPath /= mwpath;
|
||||
|
||||
if (!boost::filesystem::is_directory(installPath))
|
||||
{
|
||||
installPath.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return installPath;
|
||||
}
|
||||
|
||||
} /* namespace Files */
|
||||
|
||||
#endif /* defined(__linux__) || defined(__FreeBSD__) */
|
71
components/files/linuxpath.hpp
Normal file
71
components/files/linuxpath.hpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#ifndef COMPONENTS_FILES_LINUXPATH_H
|
||||
#define COMPONENTS_FILES_LINUXPATH_H
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files
|
||||
{
|
||||
|
||||
/**
|
||||
* \struct LinuxPath
|
||||
*/
|
||||
struct LinuxPath
|
||||
{
|
||||
LinuxPath(const std::string& application_name);
|
||||
|
||||
/**
|
||||
* \brief Return path to the user directory.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getUserPath() const;
|
||||
|
||||
/**
|
||||
* \brief Return path to the global (system) directory where game files could be placed.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getGlobalPath() const;
|
||||
|
||||
/**
|
||||
* \brief Return path to the runtime configuration directory which is the
|
||||
* place where an application was started.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getLocalPath() const;
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getGlobalDataPath() const;
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getCachePath() const;
|
||||
|
||||
/**
|
||||
* \brief Gets the path of the installed Morrowind version if there is one.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getInstallPath() const;
|
||||
|
||||
std::string mName;
|
||||
};
|
||||
|
||||
} /* namespace Files */
|
||||
|
||||
#endif /* defined(__linux__) || defined(__FreeBSD__) */
|
||||
|
||||
#endif /* COMPONENTS_FILES_LINUXPATH_H */
|
299
components/files/lowlevelfile.cpp
Normal file
299
components/files/lowlevelfile.cpp
Normal file
|
@ -0,0 +1,299 @@
|
|||
#include "lowlevelfile.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
|
||||
#if FILE_API == FILE_API_POSIX
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#if FILE_API == FILE_API_STDIO
|
||||
/*
|
||||
*
|
||||
* Implementation of LowLevelFile methods using c stdio
|
||||
*
|
||||
*/
|
||||
|
||||
LowLevelFile::LowLevelFile ()
|
||||
{
|
||||
mHandle = NULL;
|
||||
}
|
||||
|
||||
LowLevelFile::~LowLevelFile ()
|
||||
{
|
||||
if (mHandle != NULL)
|
||||
fclose (mHandle);
|
||||
}
|
||||
|
||||
void LowLevelFile::open (char const * filename)
|
||||
{
|
||||
assert (mHandle == NULL);
|
||||
|
||||
mHandle = fopen (filename, "rb");
|
||||
|
||||
if (mHandle == NULL)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "Failed to open '" << filename << "' for reading.";
|
||||
throw std::runtime_error (os.str ());
|
||||
}
|
||||
}
|
||||
|
||||
void LowLevelFile::close ()
|
||||
{
|
||||
assert (mHandle != NULL);
|
||||
|
||||
fclose (mHandle);
|
||||
|
||||
mHandle = NULL;
|
||||
}
|
||||
|
||||
size_t LowLevelFile::size ()
|
||||
{
|
||||
assert (mHandle != NULL);
|
||||
|
||||
long oldPosition = ftell (mHandle);
|
||||
|
||||
if (oldPosition == -1)
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
if (fseek (mHandle, 0, SEEK_END) != 0)
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
long Size = ftell (mHandle);
|
||||
|
||||
if (Size == -1)
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
if (fseek (mHandle, oldPosition, SEEK_SET) != 0)
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
return size_t (Size);
|
||||
}
|
||||
|
||||
void LowLevelFile::seek (size_t Position)
|
||||
{
|
||||
assert (mHandle != NULL);
|
||||
|
||||
if (fseek (mHandle, Position, SEEK_SET) != 0)
|
||||
throw std::runtime_error ("A seek operation on a file failed.");
|
||||
}
|
||||
|
||||
size_t LowLevelFile::tell ()
|
||||
{
|
||||
assert (mHandle != NULL);
|
||||
|
||||
long Position = ftell (mHandle);
|
||||
|
||||
if (Position == -1)
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
return size_t (Position);
|
||||
}
|
||||
|
||||
size_t LowLevelFile::read (void * data, size_t size)
|
||||
{
|
||||
assert (mHandle != NULL);
|
||||
|
||||
int amount = fread (data, 1, size, mHandle);
|
||||
|
||||
if (amount == 0 && ferror (mHandle))
|
||||
throw std::runtime_error ("A read operation on a file failed.");
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
#elif FILE_API == FILE_API_POSIX
|
||||
/*
|
||||
*
|
||||
* Implementation of LowLevelFile methods using posix IO calls
|
||||
*
|
||||
*/
|
||||
|
||||
LowLevelFile::LowLevelFile ()
|
||||
{
|
||||
mHandle = -1;
|
||||
}
|
||||
|
||||
LowLevelFile::~LowLevelFile ()
|
||||
{
|
||||
if (mHandle != -1)
|
||||
::close (mHandle);
|
||||
}
|
||||
|
||||
void LowLevelFile::open (char const * filename)
|
||||
{
|
||||
assert (mHandle == -1);
|
||||
|
||||
#ifdef O_BINARY
|
||||
static const int openFlags = O_RDONLY | O_BINARY;
|
||||
#else
|
||||
static const int openFlags = O_RDONLY;
|
||||
#endif
|
||||
|
||||
mHandle = ::open (filename, openFlags, 0);
|
||||
|
||||
if (mHandle == -1)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "Failed to open '" << filename << "' for reading.";
|
||||
throw std::runtime_error (os.str ());
|
||||
}
|
||||
}
|
||||
|
||||
void LowLevelFile::close ()
|
||||
{
|
||||
assert (mHandle != -1);
|
||||
|
||||
::close (mHandle);
|
||||
|
||||
mHandle = -1;
|
||||
}
|
||||
|
||||
size_t LowLevelFile::size ()
|
||||
{
|
||||
assert (mHandle != -1);
|
||||
|
||||
size_t oldPosition = ::lseek (mHandle, 0, SEEK_CUR);
|
||||
|
||||
if (oldPosition == size_t (-1))
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
size_t Size = ::lseek (mHandle, 0, SEEK_END);
|
||||
|
||||
if (Size == size_t (-1))
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
if (lseek (mHandle, oldPosition, SEEK_SET) == -1)
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
return Size;
|
||||
}
|
||||
|
||||
void LowLevelFile::seek (size_t Position)
|
||||
{
|
||||
assert (mHandle != -1);
|
||||
|
||||
if (::lseek (mHandle, Position, SEEK_SET) == -1)
|
||||
throw std::runtime_error ("A seek operation on a file failed.");
|
||||
}
|
||||
|
||||
size_t LowLevelFile::tell ()
|
||||
{
|
||||
assert (mHandle != -1);
|
||||
|
||||
size_t Position = ::lseek (mHandle, 0, SEEK_CUR);
|
||||
|
||||
if (Position == size_t (-1))
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
return Position;
|
||||
}
|
||||
|
||||
size_t LowLevelFile::read (void * data, size_t size)
|
||||
{
|
||||
assert (mHandle != -1);
|
||||
|
||||
int amount = ::read (mHandle, data, size);
|
||||
|
||||
if (amount == -1)
|
||||
throw std::runtime_error ("A read operation on a file failed.");
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
#elif FILE_API == FILE_API_WIN32
|
||||
/*
|
||||
*
|
||||
* Implementation of LowLevelFile methods using Win32 API calls
|
||||
*
|
||||
*/
|
||||
|
||||
LowLevelFile::LowLevelFile ()
|
||||
{
|
||||
mHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
LowLevelFile::~LowLevelFile ()
|
||||
{
|
||||
if (mHandle == INVALID_HANDLE_VALUE)
|
||||
CloseHandle (mHandle);
|
||||
}
|
||||
|
||||
void LowLevelFile::open (char const * filename)
|
||||
{
|
||||
assert (mHandle == INVALID_HANDLE_VALUE);
|
||||
|
||||
HANDLE handle = CreateFileA (filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
|
||||
if (handle == NULL)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "Failed to open '" << filename << "' for reading.";
|
||||
throw std::runtime_error (os.str ());
|
||||
}
|
||||
|
||||
mHandle = handle;
|
||||
}
|
||||
|
||||
void LowLevelFile::close ()
|
||||
{
|
||||
assert (mHandle != INVALID_HANDLE_VALUE);
|
||||
|
||||
CloseHandle (mHandle);
|
||||
|
||||
mHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
size_t LowLevelFile::size ()
|
||||
{
|
||||
assert (mHandle != INVALID_HANDLE_VALUE);
|
||||
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
|
||||
if (!GetFileInformationByHandle (mHandle, &info))
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
if (info.nFileSizeHigh != 0)
|
||||
throw std::runtime_error ("Files greater that 4GB are not supported.");
|
||||
|
||||
return info.nFileSizeLow;
|
||||
}
|
||||
|
||||
void LowLevelFile::seek (size_t Position)
|
||||
{
|
||||
assert (mHandle != INVALID_HANDLE_VALUE);
|
||||
|
||||
if (SetFilePointer (mHandle, Position, NULL, SEEK_SET) == INVALID_SET_FILE_POINTER)
|
||||
if (GetLastError () != NO_ERROR)
|
||||
throw std::runtime_error ("A seek operation on a file failed.");
|
||||
}
|
||||
|
||||
size_t LowLevelFile::tell ()
|
||||
{
|
||||
assert (mHandle != INVALID_HANDLE_VALUE);
|
||||
|
||||
DWORD value = SetFilePointer (mHandle, 0, NULL, SEEK_CUR);
|
||||
|
||||
if (value == INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
|
||||
throw std::runtime_error ("A query operation on a file failed.");
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
size_t LowLevelFile::read (void * data, size_t size)
|
||||
{
|
||||
assert (mHandle != INVALID_HANDLE_VALUE);
|
||||
|
||||
DWORD read;
|
||||
|
||||
if (!ReadFile (mHandle, data, size, &read, NULL))
|
||||
throw std::runtime_error ("A read operation on a file failed.");
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
#endif
|
56
components/files/lowlevelfile.hpp
Normal file
56
components/files/lowlevelfile.hpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef COMPONENTS_FILES_LOWLEVELFILE_HPP
|
||||
#define COMPONENTS_FILES_LOWLEVELFILE_HPP
|
||||
|
||||
#include <OgrePlatform.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#define FILE_API_STDIO 0
|
||||
#define FILE_API_POSIX 1
|
||||
#define FILE_API_WIN32 2
|
||||
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
|
||||
#define FILE_API FILE_API_POSIX
|
||||
#elif OGRE_PLATFORM == OGRE_PLATFORM_WIN32
|
||||
#define FILE_API FILE_API_WIN32
|
||||
#else
|
||||
#define FILE_API FILE_API_STDIO
|
||||
#endif
|
||||
|
||||
#if FILE_API == FILE_API_STDIO
|
||||
#include <cstdio>
|
||||
#elif FILE_API == FILE_API_POSIX
|
||||
#elif FILE_API == FILE_API_WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#error Unsupported File API
|
||||
#endif
|
||||
|
||||
class LowLevelFile
|
||||
{
|
||||
public:
|
||||
|
||||
LowLevelFile ();
|
||||
~LowLevelFile ();
|
||||
|
||||
void open (char const * filename);
|
||||
void close ();
|
||||
|
||||
size_t size ();
|
||||
|
||||
void seek (size_t Position);
|
||||
size_t tell ();
|
||||
|
||||
size_t read (void * data, size_t size);
|
||||
|
||||
private:
|
||||
#if FILE_API == FILE_API_STDIO
|
||||
FILE* mHandle;
|
||||
#elif FILE_API == FILE_API_POSIX
|
||||
int mHandle;
|
||||
#elif FILE_API == FILE_API_WIN32
|
||||
HANDLE mHandle;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
165
components/files/macospath.cpp
Normal file
165
components/files/macospath.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
#include "macospath.hpp"
|
||||
|
||||
#if defined(macintosh) || defined(Macintosh) || defined(__APPLE__) || defined(__MACH__)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
/**
|
||||
* FIXME: Someone with MacOS system should check this and correct if necessary
|
||||
*/
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files
|
||||
{
|
||||
|
||||
MacOsPath::MacOsPath(const std::string& application_name)
|
||||
: mName(application_name)
|
||||
{
|
||||
}
|
||||
|
||||
boost::filesystem::path MacOsPath::getUserPath() const
|
||||
{
|
||||
boost::filesystem::path userPath(".");
|
||||
|
||||
const char* theDir = getenv("HOME");
|
||||
if (theDir == NULL)
|
||||
{
|
||||
struct passwd* pwd = getpwuid(getuid());
|
||||
if (pwd != NULL)
|
||||
{
|
||||
theDir = pwd->pw_dir;
|
||||
}
|
||||
}
|
||||
if (theDir != NULL)
|
||||
{
|
||||
userPath = boost::filesystem::path(theDir) / "Library/Preferences/";
|
||||
}
|
||||
|
||||
return userPath / mName;
|
||||
}
|
||||
|
||||
boost::filesystem::path MacOsPath::getGlobalPath() const
|
||||
{
|
||||
boost::filesystem::path globalPath("/Library/Preferences/");
|
||||
return globalPath / mName;
|
||||
}
|
||||
|
||||
boost::filesystem::path MacOsPath::getCachePath() const
|
||||
{
|
||||
boost::filesystem::path userPath(".");
|
||||
|
||||
const char* theDir = getenv("HOME");
|
||||
if (theDir == NULL)
|
||||
{
|
||||
struct passwd* pwd = getpwuid(getuid());
|
||||
if (pwd != NULL)
|
||||
{
|
||||
theDir = pwd->pw_dir;
|
||||
}
|
||||
}
|
||||
if (theDir != NULL)
|
||||
{
|
||||
userPath = boost::filesystem::path(theDir) / "Library/Caches" / mName;
|
||||
}
|
||||
|
||||
return userPath;
|
||||
}
|
||||
|
||||
boost::filesystem::path MacOsPath::getLocalPath() const
|
||||
{
|
||||
return boost::filesystem::path("./");
|
||||
}
|
||||
|
||||
boost::filesystem::path MacOsPath::getGlobalDataPath() const
|
||||
{
|
||||
boost::filesystem::path globalDataPath("/Library/Application Support/");
|
||||
return globalDataPath / mName;
|
||||
}
|
||||
|
||||
boost::filesystem::path MacOsPath::getInstallPath() const
|
||||
{
|
||||
boost::filesystem::path installPath;
|
||||
|
||||
char *homePath = getenv("HOME");
|
||||
if (homePath == NULL)
|
||||
{
|
||||
struct passwd* pwd = getpwuid(getuid());
|
||||
if (pwd != NULL)
|
||||
{
|
||||
homePath = pwd->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (homePath != NULL)
|
||||
{
|
||||
boost::filesystem::path wineDefaultRegistry(homePath);
|
||||
wineDefaultRegistry /= ".wine/system.reg";
|
||||
|
||||
if (boost::filesystem::is_regular_file(wineDefaultRegistry))
|
||||
{
|
||||
boost::filesystem::ifstream file(wineDefaultRegistry);
|
||||
bool isRegEntry = false;
|
||||
std::string line;
|
||||
std::string mwpath;
|
||||
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
if (line[0] == '[') // we found an entry
|
||||
{
|
||||
if (isRegEntry)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
isRegEntry = (line.find("Softworks\\\\Morrowind]") != std::string::npos);
|
||||
}
|
||||
else if (isRegEntry)
|
||||
{
|
||||
if (line[0] == '"') // empty line means new registry key
|
||||
{
|
||||
std::string key = line.substr(1, line.find('"', 1) - 1);
|
||||
if (strcasecmp(key.c_str(), "Installed Path") == 0)
|
||||
{
|
||||
std::string::size_type valuePos = line.find('=') + 2;
|
||||
mwpath = line.substr(valuePos, line.rfind('"') - valuePos);
|
||||
|
||||
std::string::size_type pos = mwpath.find("\\");
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
mwpath.replace(pos, 2, "/");
|
||||
pos = mwpath.find("\\", pos + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mwpath.empty())
|
||||
{
|
||||
// Change drive letter to lowercase, so we could use ~/.wine/dosdevice symlinks
|
||||
mwpath[0] = tolower(mwpath[0]);
|
||||
installPath /= homePath;
|
||||
installPath /= ".wine/dosdevices/";
|
||||
installPath /= mwpath;
|
||||
|
||||
if (!boost::filesystem::is_directory(installPath))
|
||||
{
|
||||
installPath.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return installPath;
|
||||
}
|
||||
|
||||
|
||||
} /* namespace Files */
|
||||
|
||||
#endif /* defined(macintosh) || defined(Macintosh) || defined(__APPLE__) || defined(__MACH__) */
|
66
components/files/macospath.hpp
Normal file
66
components/files/macospath.hpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#ifndef COMPONENTS_FILES_MACOSPATH_H
|
||||
#define COMPONENTS_FILES_MACOSPATH_H
|
||||
|
||||
#if defined(macintosh) || defined(Macintosh) || defined(__APPLE__) || defined(__MACH__)
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files
|
||||
{
|
||||
|
||||
/**
|
||||
* \struct MacOsPath
|
||||
*/
|
||||
struct MacOsPath
|
||||
{
|
||||
MacOsPath(const std::string& application_name);
|
||||
|
||||
/**
|
||||
* \brief Return path to the local directory.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getUserPath() const;
|
||||
|
||||
/**
|
||||
* \brief Return path to the global (system) directory.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getGlobalPath() const;
|
||||
|
||||
/**
|
||||
* \brief Return path to the runtime directory which is the
|
||||
* place where an application was started.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getLocalPath() const;
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getCachePath() const;
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getGlobalDataPath() const;
|
||||
|
||||
boost::filesystem::path getInstallPath() const;
|
||||
|
||||
std::string mName;
|
||||
};
|
||||
|
||||
} /* namespace Files */
|
||||
|
||||
#endif /* defined(macintosh) || defined(Macintosh) || defined(__APPLE__) || defined(__MACH__) */
|
||||
|
||||
#endif /* COMPONENTS_FILES_MACOSPATH_H */
|
112
components/files/multidircollection.cpp
Normal file
112
components/files/multidircollection.cpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
|
||||
#include "multidircollection.hpp"
|
||||
|
||||
#include <cctype>
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
#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 Files::PathContainer& directories,
|
||||
const std::string& extension, bool foldCase)
|
||||
: mFiles (NameLess (!foldCase))
|
||||
{
|
||||
NameEqual equal (!foldCase);
|
||||
|
||||
for (PathContainer::const_iterator iter = directories.begin();
|
||||
iter!=directories.end(); ++iter)
|
||||
{
|
||||
if (!boost::filesystem::is_directory(*iter))
|
||||
{
|
||||
std::cout << "Skipping invalid directory: " << (*iter).string() << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (boost::filesystem::directory_iterator dirIter(*iter);
|
||||
dirIter != boost::filesystem::directory_iterator(); ++dirIter)
|
||||
{
|
||||
boost::filesystem::path path = *dirIter;
|
||||
|
||||
if (!equal (extension, boost::filesystem::path (path.extension()).string()))
|
||||
continue;
|
||||
|
||||
std::string filename = boost::filesystem::path (path.filename()).string();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool MultiDirCollection::doesExist (const std::string& file) const
|
||||
{
|
||||
return mFiles.find (file)!=mFiles.end();
|
||||
}
|
||||
|
||||
MultiDirCollection::TIter MultiDirCollection::begin() const
|
||||
{
|
||||
return mFiles.begin();
|
||||
}
|
||||
|
||||
MultiDirCollection::TIter MultiDirCollection::end() const
|
||||
{
|
||||
return mFiles.end();
|
||||
}
|
||||
}
|
88
components/files/multidircollection.hpp
Normal file
88
components/files/multidircollection.hpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
#ifndef COMPONENTS_FILES_MULTIDIRSOLLECTION_HPP
|
||||
#define COMPONENTS_FILES_MULTIDIRSOLLECTION_HPP
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <locale>
|
||||
#include <cctype>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
namespace Files
|
||||
{
|
||||
typedef std::vector<boost::filesystem::path> PathContainer;
|
||||
|
||||
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());
|
||||
std::locale loc;
|
||||
|
||||
for (std::size_t i=0; i<min; ++i)
|
||||
{
|
||||
char l = std::tolower (left[i], loc);
|
||||
char r = std::tolower (right[i], loc);
|
||||
|
||||
if (l<r)
|
||||
return true;
|
||||
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 Files::PathContainer& 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 \a file.
|
||||
///
|
||||
/// If the file does not exist, an exception is thrown. \a file must include
|
||||
/// the extension.
|
||||
|
||||
bool doesExist (const std::string& file) const;
|
||||
///< \return Does a file with the given name exist?
|
||||
|
||||
TIter begin() const;
|
||||
///< Return iterator pointing to the first file.
|
||||
|
||||
TIter end() const;
|
||||
///< Return iterator pointing past the last file.
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
51
components/files/ogreplugin.cpp
Normal file
51
components/files/ogreplugin.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include "ogreplugin.hpp"
|
||||
|
||||
#include <OgrePrerequisites.h>
|
||||
#include <OgreRoot.h>
|
||||
|
||||
namespace Files {
|
||||
|
||||
bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre::Root &ogreRoot) {
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||
std::ostringstream verStream;
|
||||
verStream << "." << OGRE_VERSION_MAJOR << "." << OGRE_VERSION_MINOR << "." << OGRE_VERSION_PATCH;
|
||||
pluginName = pluginName + verStream.str();
|
||||
#endif
|
||||
|
||||
std::string pluginExt;
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
|
||||
pluginExt = ".dll";
|
||||
#endif
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||
pluginExt = ".dylib";
|
||||
#endif
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
|
||||
pluginExt = ".so";
|
||||
#endif
|
||||
|
||||
// Append plugin suffix if debugging.
|
||||
std::string pluginPath;
|
||||
#if defined(DEBUG)
|
||||
pluginPath = pluginDir + "/" + pluginName + OGRE_PLUGIN_DEBUG_SUFFIX + pluginExt;
|
||||
if (boost::filesystem::exists(pluginPath)) {
|
||||
ogreRoot.loadPlugin(pluginPath);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
|
||||
return false;
|
||||
#endif //OGRE_PLATFORM == OGRE_PLATFORM_WIN32
|
||||
}
|
||||
#endif //defined(DEBUG)
|
||||
|
||||
pluginPath = pluginDir + "/" + pluginName + pluginExt;
|
||||
if (boost::filesystem::exists(pluginPath)) {
|
||||
ogreRoot.loadPlugin(pluginPath);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
42
components/files/ogreplugin.hpp
Normal file
42
components/files/ogreplugin.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef COMPONENTS_FILES_OGREPLUGIN_H
|
||||
#define COMPONENTS_FILES_OGREPLUGIN_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
namespace Ogre {
|
||||
class Root;
|
||||
}
|
||||
|
||||
#if (BOOST_VERSION <= 104500)
|
||||
namespace boost {
|
||||
namespace filesystem {
|
||||
inline path absolute(const path& p, const path& base=current_path()) {
|
||||
// call obsolete version of this function on older boost
|
||||
return complete(p, base);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* (BOOST_VERSION <= 104300) */
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files {
|
||||
|
||||
/**
|
||||
* \brief Loads Ogre plugin with given name.
|
||||
*
|
||||
* \param pluginDir absolute path to plugins
|
||||
* \param pluginName plugin name, for example "RenderSystem_GL"
|
||||
* \param ogreRoot Ogre::Root instance
|
||||
*
|
||||
* \return whether plugin was located or not
|
||||
*/
|
||||
bool loadOgrePlugin(const std::string &pluginDir, std::string pluginName, Ogre::Root &ogreRoot);
|
||||
|
||||
}
|
||||
|
||||
#endif /* COMPONENTS_FILES_OGREPLUGIN_H */
|
108
components/files/windowspath.cpp
Normal file
108
components/files/windowspath.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
#include "windowspath.hpp"
|
||||
|
||||
#if defined(_WIN32) || defined(__WINDOWS__)
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
/**
|
||||
* FIXME: Someone with Windows system should check this and correct if necessary
|
||||
*/
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files
|
||||
{
|
||||
|
||||
WindowsPath::WindowsPath(const std::string& application_name)
|
||||
: mName(application_name)
|
||||
{
|
||||
}
|
||||
|
||||
boost::filesystem::path WindowsPath::getUserPath() const
|
||||
{
|
||||
boost::filesystem::path userPath(".");
|
||||
|
||||
TCHAR path[MAX_PATH];
|
||||
memset(path, 0, sizeof(path));
|
||||
|
||||
if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, path)))
|
||||
{
|
||||
PathAppend(path, TEXT("My Games"));
|
||||
userPath = boost::filesystem::path(path);
|
||||
}
|
||||
|
||||
return userPath / mName;
|
||||
}
|
||||
|
||||
boost::filesystem::path WindowsPath::getGlobalPath() const
|
||||
{
|
||||
boost::filesystem::path globalPath(".");
|
||||
|
||||
TCHAR path[MAX_PATH];
|
||||
memset(path, 0, sizeof(path));
|
||||
|
||||
if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES | CSIDL_FLAG_CREATE, NULL, 0, path)))
|
||||
{
|
||||
globalPath = boost::filesystem::path(path);
|
||||
}
|
||||
|
||||
return globalPath / mName;
|
||||
}
|
||||
|
||||
boost::filesystem::path WindowsPath::getLocalPath() const
|
||||
{
|
||||
return boost::filesystem::path("./");
|
||||
}
|
||||
|
||||
boost::filesystem::path WindowsPath::getGlobalDataPath() const
|
||||
{
|
||||
return getGlobalPath();
|
||||
}
|
||||
|
||||
boost::filesystem::path WindowsPath::getCachePath() const
|
||||
{
|
||||
return getUserPath() / "cache";
|
||||
}
|
||||
|
||||
boost::filesystem::path WindowsPath::getInstallPath() const
|
||||
{
|
||||
boost::filesystem::path installPath("");
|
||||
|
||||
HKEY hKey;
|
||||
|
||||
BOOL f64 = FALSE;
|
||||
LPCTSTR regkey;
|
||||
if ((IsWow64Process(GetCurrentProcess(), &f64) && f64) || sizeof(void*) == 8)
|
||||
{
|
||||
regkey = "SOFTWARE\\Wow6432Node\\Bethesda Softworks\\Morrowind";
|
||||
}
|
||||
else
|
||||
{
|
||||
regkey = "SOFTWARE\\Bethesda Softworks\\Morrowind";
|
||||
}
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(regkey), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
||||
{
|
||||
//Key existed, let's try to read the install dir
|
||||
std::vector<char> buf(512);
|
||||
int len = 512;
|
||||
|
||||
if (RegQueryValueEx(hKey, TEXT("Installed Path"), NULL, NULL, (LPBYTE)&buf[0], (LPDWORD)&len) == ERROR_SUCCESS)
|
||||
{
|
||||
installPath = &buf[0];
|
||||
}
|
||||
}
|
||||
|
||||
return installPath;
|
||||
}
|
||||
|
||||
} /* namespace Files */
|
||||
|
||||
#endif /* defined(_WIN32) || defined(__WINDOWS__) */
|
77
components/files/windowspath.hpp
Normal file
77
components/files/windowspath.hpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
#ifndef COMPONENTS_FILES_WINDOWSPATH_HPP
|
||||
#define COMPONENTS_FILES_WINDOWSPATH_HPP
|
||||
|
||||
#if defined(_WIN32) || defined(__WINDOWS__)
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files
|
||||
{
|
||||
|
||||
/**
|
||||
* \struct WindowsPath
|
||||
*/
|
||||
struct WindowsPath
|
||||
{
|
||||
/**
|
||||
* \brief WindowsPath constructor.
|
||||
*
|
||||
* \param [in] application_name - The name of the application.
|
||||
*/
|
||||
WindowsPath(const std::string& application_name);
|
||||
|
||||
/**
|
||||
* \brief Returns user path i.e.:
|
||||
* "X:\Documents And Settings\<User name>\My Documents\My Games\"
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getUserPath() const;
|
||||
|
||||
/**
|
||||
* \brief Returns "X:\Program Files\"
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getGlobalPath() const;
|
||||
|
||||
/**
|
||||
* \brief Return local path which is a location where
|
||||
* an application was started
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getLocalPath() const;
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getCachePath() const;
|
||||
|
||||
/**
|
||||
* \brief Return same path like getGlobalPath
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getGlobalDataPath() const;
|
||||
|
||||
/**
|
||||
* \brief Gets the path of the installed Morrowind version if there is one.
|
||||
*
|
||||
* \return boost::filesystem::path
|
||||
*/
|
||||
boost::filesystem::path getInstallPath() const;
|
||||
|
||||
std::string mName;
|
||||
};
|
||||
|
||||
} /* namespace Files */
|
||||
|
||||
#endif /* defined(_WIN32) || defined(__WINDOWS__) */
|
||||
|
||||
#endif /* COMPONENTS_FILES_WINDOWSPATH_HPP */
|
Loading…
Add table
Add a link
Reference in a new issue