Imported Upstream version 0.26.0

This commit is contained in:
Bret Curtis 2013-10-17 16:37:22 +02:00
commit 9a2b6c69b6
1398 changed files with 212217 additions and 0 deletions

View 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;
}
}

View 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

View 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 */

View 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 */

View 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));
}

View 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

View 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;
}
}
}

View 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

View 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();
}
}

View 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 */

View 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 */

View 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__) */

View 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 */

View 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

View 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

View 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__) */

View 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 */

View 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();
}
}

View 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

View 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;
}
}
}

View 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 */

View 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__) */

View 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 */