2017-07-13 10:26:03 +02:00
|
|
|
/*
|
|
|
|
* AdapterLoaders.cpp, part of VCMI engine
|
|
|
|
*
|
|
|
|
* Authors: listed in file AUTHORS in main folder
|
|
|
|
*
|
|
|
|
* License: GNU General Public License v2.0 or later
|
|
|
|
* Full text of license available in license.txt file, in main folder
|
|
|
|
*
|
|
|
|
*/
|
2013-07-28 17:49:50 +03:00
|
|
|
#include "StdInc.h"
|
|
|
|
#include "AdapterLoaders.h"
|
|
|
|
|
|
|
|
#include "../JsonNode.h"
|
2013-11-08 23:36:26 +03:00
|
|
|
#include "Filesystem.h"
|
2013-07-28 17:49:50 +03:00
|
|
|
|
|
|
|
CMappedFileLoader::CMappedFileLoader(const std::string & mountPoint, const JsonNode &config)
|
|
|
|
{
|
|
|
|
for(auto entry : config.Struct())
|
|
|
|
{
|
2016-01-29 16:16:14 +02:00
|
|
|
//fileList[ResourceID(mountPoint + entry.first)] = ResourceID(mountPoint + entry.second.String());
|
|
|
|
fileList.emplace(ResourceID(mountPoint + entry.first), ResourceID(mountPoint + entry.second.String()));
|
2013-07-28 17:49:50 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<CInputStream> CMappedFileLoader::load(const ResourceID & resourceName) const
|
|
|
|
{
|
|
|
|
return CResourceHandler::get()->load(fileList.at(resourceName));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CMappedFileLoader::existsResource(const ResourceID & resourceName) const
|
|
|
|
{
|
|
|
|
return fileList.count(resourceName) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string CMappedFileLoader::getMountPoint() const
|
|
|
|
{
|
|
|
|
return ""; // does not have any meaning with this type of data source
|
|
|
|
}
|
|
|
|
|
2016-01-16 17:36:16 +02:00
|
|
|
boost::optional<boost::filesystem::path> CMappedFileLoader::getResourceName(const ResourceID & resourceName) const
|
2013-07-28 17:49:50 +03:00
|
|
|
{
|
|
|
|
return CResourceHandler::get()->getResourceName(fileList.at(resourceName));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unordered_set<ResourceID> CMappedFileLoader::getFilteredFiles(std::function<bool(const ResourceID &)> filter) const
|
|
|
|
{
|
|
|
|
std::unordered_set<ResourceID> foundID;
|
|
|
|
|
|
|
|
for (auto & file : fileList)
|
|
|
|
{
|
|
|
|
if (filter(file.first))
|
|
|
|
foundID.insert(file.first);
|
|
|
|
}
|
|
|
|
return foundID;
|
|
|
|
}
|
|
|
|
|
2013-07-28 21:57:07 +03:00
|
|
|
CFilesystemList::CFilesystemList()
|
|
|
|
{
|
2013-12-29 14:27:38 +03:00
|
|
|
//loaders = new std::vector<std::unique_ptr<ISimpleResourceLoader> >;
|
2013-07-28 21:57:07 +03:00
|
|
|
}
|
|
|
|
|
2013-07-29 13:08:02 +03:00
|
|
|
CFilesystemList::~CFilesystemList()
|
|
|
|
{
|
2013-12-29 14:27:38 +03:00
|
|
|
//delete loaders;
|
2013-07-29 13:08:02 +03:00
|
|
|
}
|
|
|
|
|
2013-07-28 17:49:50 +03:00
|
|
|
std::unique_ptr<CInputStream> CFilesystemList::load(const ResourceID & resourceName) const
|
|
|
|
{
|
2014-05-21 12:02:20 +03:00
|
|
|
// load resource from last loader that have it (last overridden version)
|
2013-12-29 14:27:38 +03:00
|
|
|
for (auto & loader : boost::adaptors::reverse(loaders))
|
2013-07-28 17:49:50 +03:00
|
|
|
{
|
|
|
|
if (loader->existsResource(resourceName))
|
|
|
|
return loader->load(resourceName);
|
|
|
|
}
|
|
|
|
|
|
|
|
throw std::runtime_error("Resource with name " + resourceName.getName() + " and type "
|
|
|
|
+ EResTypeHelper::getEResTypeAsString(resourceName.getType()) + " wasn't found.");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CFilesystemList::existsResource(const ResourceID & resourceName) const
|
|
|
|
{
|
2013-12-29 14:27:38 +03:00
|
|
|
for (auto & loader : loaders)
|
2013-11-14 16:21:09 +03:00
|
|
|
if (loader->existsResource(resourceName))
|
|
|
|
return true;
|
|
|
|
return false;
|
2013-07-28 17:49:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string CFilesystemList::getMountPoint() const
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2016-01-16 17:36:16 +02:00
|
|
|
boost::optional<boost::filesystem::path> CFilesystemList::getResourceName(const ResourceID & resourceName) const
|
2013-07-28 17:49:50 +03:00
|
|
|
{
|
|
|
|
if (existsResource(resourceName))
|
|
|
|
return getResourcesWithName(resourceName).back()->getResourceName(resourceName);
|
2016-01-16 17:36:16 +02:00
|
|
|
return boost::optional<boost::filesystem::path>();
|
2013-07-28 17:49:50 +03:00
|
|
|
}
|
|
|
|
|
2016-01-27 18:32:59 +02:00
|
|
|
std::set<boost::filesystem::path> CFilesystemList::getResourceNames(const ResourceID & resourceName) const
|
2016-01-27 10:38:35 +02:00
|
|
|
{
|
2016-01-27 18:32:59 +02:00
|
|
|
std::set<boost::filesystem::path> paths;
|
2016-01-27 10:38:35 +02:00
|
|
|
for(auto& loader : getResourcesWithName(resourceName))
|
|
|
|
{
|
|
|
|
auto rn = loader->getResourceName(resourceName);
|
|
|
|
if(rn)
|
|
|
|
{
|
2016-01-27 22:08:08 +02:00
|
|
|
paths.insert(rn->string());
|
2016-01-27 10:38:35 +02:00
|
|
|
}
|
|
|
|
}
|
2019-01-19 12:52:02 +02:00
|
|
|
return paths;
|
2016-01-27 10:38:35 +02:00
|
|
|
}
|
|
|
|
|
2016-10-16 22:09:57 +02:00
|
|
|
void CFilesystemList::updateFilteredFiles(std::function<bool(const std::string &)> filter) const
|
|
|
|
{
|
|
|
|
for (auto & loader : loaders)
|
|
|
|
loader->updateFilteredFiles(filter);
|
|
|
|
}
|
|
|
|
|
2013-07-28 17:49:50 +03:00
|
|
|
std::unordered_set<ResourceID> CFilesystemList::getFilteredFiles(std::function<bool(const ResourceID &)> filter) const
|
|
|
|
{
|
|
|
|
std::unordered_set<ResourceID> ret;
|
|
|
|
|
2013-12-29 14:27:38 +03:00
|
|
|
for (auto & loader : loaders)
|
2013-07-28 17:49:50 +03:00
|
|
|
for (auto & entry : loader->getFilteredFiles(filter))
|
|
|
|
ret.insert(entry);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CFilesystemList::createResource(std::string filename, bool update)
|
|
|
|
{
|
2017-08-11 19:03:05 +02:00
|
|
|
logGlobal->trace("Creating %s", filename);
|
2013-12-29 14:27:38 +03:00
|
|
|
for (auto & loader : boost::adaptors::reverse(loaders))
|
2013-07-28 17:49:50 +03:00
|
|
|
{
|
|
|
|
if (writeableLoaders.count(loader.get()) != 0 // writeable,
|
|
|
|
&& loader->createResource(filename, update)) // successfully created
|
|
|
|
{
|
|
|
|
// Check if resource was created successfully. Possible reasons for this to fail
|
|
|
|
// a) loader failed to create resource (e.g. read-only FS)
|
|
|
|
// b) in update mode, call with filename that does not exists
|
|
|
|
assert(load(ResourceID(filename)));
|
|
|
|
|
2017-08-10 18:39:27 +02:00
|
|
|
logGlobal->trace("Resource created successfully");
|
2013-07-28 17:49:50 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2017-08-10 18:39:27 +02:00
|
|
|
logGlobal->trace("Failed to create resource");
|
2013-07-28 17:49:50 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<const ISimpleResourceLoader *> CFilesystemList::getResourcesWithName(const ResourceID & resourceName) const
|
|
|
|
{
|
|
|
|
std::vector<const ISimpleResourceLoader *> ret;
|
|
|
|
|
2013-12-29 14:27:38 +03:00
|
|
|
for (auto & loader : loaders)
|
2013-07-28 17:49:50 +03:00
|
|
|
boost::range::copy(loader->getResourcesWithName(resourceName), std::back_inserter(ret));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CFilesystemList::addLoader(ISimpleResourceLoader * loader, bool writeable)
|
|
|
|
{
|
2013-12-29 14:27:38 +03:00
|
|
|
loaders.push_back(std::unique_ptr<ISimpleResourceLoader>(loader));
|
2013-07-28 17:49:50 +03:00
|
|
|
if (writeable)
|
|
|
|
writeableLoaders.insert(loader);
|
|
|
|
}
|
2022-09-17 13:04:01 +02:00
|
|
|
|
|
|
|
bool CFilesystemList::removeLoader(ISimpleResourceLoader * loader)
|
|
|
|
{
|
|
|
|
for(auto loaderIterator = loaders.begin(); loaderIterator != loaders.end(); ++loaderIterator)
|
|
|
|
{
|
|
|
|
if(loaderIterator->get() == loader)
|
|
|
|
{
|
|
|
|
loaders.erase(loaderIterator);
|
|
|
|
writeableLoaders.erase(loader);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|