mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
* std::unordered_map implementation in MSVC 10 has terribly slow destructor. Since bug is fixed only in VC11, I replaced it with boost::unordered_map.
* fixed crash with invalid .lod archive (some H3 installations have fake 1 byte .lod "archives" * fixed crash when parsing invalid map file * minor random optimizations (rv-refs, etc)
This commit is contained in:
parent
9cbc1f1058
commit
cd63c177e2
16
Global.h
16
Global.h
@ -29,15 +29,21 @@
|
||||
#include "tchar_amigaos4.h"
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
|
||||
|
@ -1049,17 +1049,20 @@ void SelectionTab::parseMaps(const std::vector<ResourceID> &files, int start, in
|
||||
|
||||
while(start < allItems.size())
|
||||
{
|
||||
CCompressedStream stream(std::move(CResourceHandler::get()->load(files[start])), true);
|
||||
int read = stream.read(mapBuffer, 1500);
|
||||
try
|
||||
{
|
||||
CCompressedStream stream(std::move(CResourceHandler::get()->load(files[start])), true);
|
||||
int read = stream.read(mapBuffer, 1500);
|
||||
|
||||
if(read < 50 || !mapBuffer[4])
|
||||
throw std::runtime_error("corrupted map file");
|
||||
|
||||
if(read < 50 || !mapBuffer[4])
|
||||
{
|
||||
tlog3 << "\t\tWarning: corrupted map file: " << files[start].getName() << std::endl;
|
||||
}
|
||||
else //valid map
|
||||
{
|
||||
allItems[start].mapInit(files[start].getName(), mapBuffer);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
tlog3 << "\t\tWarning: failed to load map " << files[start].getName() << ": " << e.what() << std::endl;
|
||||
}
|
||||
start += threads;
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ CFileInfo::CFileInfo() : name("")
|
||||
|
||||
}
|
||||
|
||||
CFileInfo::CFileInfo(const std::string & name)
|
||||
: name(name)
|
||||
CFileInfo::CFileInfo(std::string name)
|
||||
: name(std::move(name))
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
*
|
||||
* @param name The path and name of the file.
|
||||
*/
|
||||
explicit CFileInfo(const std::string & name);
|
||||
explicit CFileInfo(std::string name);
|
||||
|
||||
/**
|
||||
* Checks if the file exists.
|
||||
|
@ -29,7 +29,7 @@ bool CFilesystemLoader::existsEntry(const std::string & resourceName) const
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unordered_map<ResourceID, std::string> CFilesystemLoader::getEntries() const
|
||||
boost::unordered_map<ResourceID, std::string> CFilesystemLoader::getEntries() const
|
||||
{
|
||||
return fileList;
|
||||
}
|
||||
@ -54,11 +54,10 @@ bool CFilesystemLoader::createEntry(std::string filename)
|
||||
}
|
||||
|
||||
|
||||
std::unordered_map<ResourceID, std::string> CFilesystemLoader::listFiles(size_t depth, bool initial) const
|
||||
boost::unordered_map<ResourceID, std::string> CFilesystemLoader::listFiles(size_t depth, bool initial) const
|
||||
{
|
||||
|
||||
assert(boost::filesystem::is_directory(baseDirectory));
|
||||
std::unordered_map<ResourceID, std::string> fileList;
|
||||
boost::unordered_map<ResourceID, std::string> fileList;
|
||||
|
||||
std::vector<std::string> path;//vector holding relative path to our file
|
||||
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
*
|
||||
* @return a list of all entries in the filesystem.
|
||||
*/
|
||||
std::unordered_map<ResourceID, std::string> getEntries() const;
|
||||
boost::unordered_map<ResourceID, std::string> getEntries() const;
|
||||
|
||||
/**
|
||||
* Gets the origin of the archive loader.
|
||||
@ -72,7 +72,7 @@ private:
|
||||
* key = ResourceID for resource loader
|
||||
* value = name that can be used to access file
|
||||
*/
|
||||
std::unordered_map<ResourceID, std::string> fileList;
|
||||
boost::unordered_map<ResourceID, std::string> fileList;
|
||||
|
||||
/**
|
||||
* Returns a list of pathnames denoting the files in the directory denoted by this pathname.
|
||||
@ -83,5 +83,5 @@ private:
|
||||
* @return a list of pathnames denoting the files and directories in the directory denoted by this pathname
|
||||
* The array will be empty if the directory is empty. Ptr is null if the directory doesn't exist or if it isn't a directory.
|
||||
*/
|
||||
std::unordered_map<ResourceID, std::string> listFiles(size_t depth, bool initial) const;
|
||||
boost::unordered_map<ResourceID, std::string> listFiles(size_t depth, bool initial) const;
|
||||
};
|
||||
|
@ -19,6 +19,10 @@ CLodArchiveLoader::CLodArchiveLoader(const std::string & archive)
|
||||
this->archive = archive;
|
||||
CFileInputStream fileStream(archive);
|
||||
|
||||
// Fake .lod file with no data has to be silently ignored.
|
||||
if(fileStream.getSize() < 10)
|
||||
return;
|
||||
|
||||
// Retrieve file extension of archive in uppercase
|
||||
CFileInfo fileInfo(archive);
|
||||
std::string ext = fileInfo.getExtension();
|
||||
@ -57,6 +61,7 @@ void CLodArchiveLoader::initLODArchive(CFileInputStream & fileStream)
|
||||
|
||||
// Read count of total files
|
||||
CBinaryReader reader(fileStream);
|
||||
|
||||
fileStream.seek(8);
|
||||
ui32 totalFiles = reader.readUInt32();
|
||||
|
||||
@ -184,9 +189,9 @@ std::unique_ptr<CInputStream> CLodArchiveLoader::load(const std::string & resour
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<ResourceID, std::string> CLodArchiveLoader::getEntries() const
|
||||
boost::unordered_map<ResourceID, std::string> CLodArchiveLoader::getEntries() const
|
||||
{
|
||||
std::unordered_map<ResourceID, std::string> retList;
|
||||
boost::unordered_map<ResourceID, std::string> retList;
|
||||
|
||||
for(auto it = entries.begin(); it != entries.end(); ++it)
|
||||
{
|
||||
@ -194,7 +199,7 @@ std::unordered_map<ResourceID, std::string> CLodArchiveLoader::getEntries() cons
|
||||
retList[ResourceID(entry.name)] = entry.name;
|
||||
}
|
||||
|
||||
return std::move(retList);
|
||||
return retList;
|
||||
}
|
||||
|
||||
const ArchiveEntry * CLodArchiveLoader::getArchiveEntry(const std::string & resourceName) const
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
*
|
||||
* @return a list of all entries in the archive.
|
||||
*/
|
||||
std::unordered_map<ResourceID, std::string> getEntries() const;
|
||||
boost::unordered_map<ResourceID, std::string> getEntries() const;
|
||||
|
||||
/**
|
||||
* Gets the archive entry for the requested resource
|
||||
@ -122,5 +122,5 @@ private:
|
||||
std::string archive;
|
||||
|
||||
/** Holds all entries of the archive file. An entry can be accessed via the entry name. **/
|
||||
std::unordered_map<std::string, ArchiveEntry> entries;
|
||||
boost::unordered_map<std::string, ArchiveEntry> entries;
|
||||
};
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "../JsonNode.h"
|
||||
#include "../GameConstants.h"
|
||||
#include "../VCMIDirs.h"
|
||||
#include "../CStopWatch.h"
|
||||
|
||||
CResourceLoader * CResourceHandler::resourceLoader = nullptr;
|
||||
CResourceLoader * CResourceHandler::initialLoader = nullptr;
|
||||
@ -17,16 +18,16 @@ ResourceID::ResourceID()
|
||||
{
|
||||
}
|
||||
|
||||
ResourceID::ResourceID(const std::string & name)
|
||||
ResourceID::ResourceID(std::string name)
|
||||
{
|
||||
CFileInfo info(name);
|
||||
CFileInfo info(std::move(name));
|
||||
setName(info.getStem());
|
||||
setType(info.getType());
|
||||
}
|
||||
|
||||
ResourceID::ResourceID(const std::string & name, EResType::Type type)
|
||||
ResourceID::ResourceID(std::string name, EResType::Type type)
|
||||
{
|
||||
setName(name);
|
||||
setName(std::move(name));
|
||||
setType(type);
|
||||
}
|
||||
|
||||
@ -53,9 +54,9 @@ EResType::Type ResourceID::getType() const
|
||||
return type;
|
||||
}
|
||||
|
||||
void ResourceID::setName(const std::string & name)
|
||||
void ResourceID::setName(std::string name)
|
||||
{
|
||||
this->name = name;
|
||||
this->name = std::move(name);
|
||||
|
||||
size_t dotPos = this->name.find_last_of("/.");
|
||||
|
||||
@ -111,9 +112,9 @@ ResourceLocator CResourceLoader::getResource(const ResourceID & resourceIdent) c
|
||||
return resource->second.back();
|
||||
}
|
||||
|
||||
const std::list<ResourceLocator> & CResourceLoader::getResourcesWithName(const ResourceID & resourceIdent) const
|
||||
const std::vector<ResourceLocator> & CResourceLoader::getResourcesWithName(const ResourceID & resourceIdent) const
|
||||
{
|
||||
static const std::list<ResourceLocator> emptyList;
|
||||
static const std::vector<ResourceLocator> emptyList;
|
||||
auto resource = resources.find(resourceIdent);
|
||||
|
||||
if (resource == resources.end())
|
||||
@ -163,7 +164,7 @@ void CResourceLoader::addLoader(std::string mountPoint, shared_ptr<ISimpleResour
|
||||
loaders.push_back(loaderEntry);
|
||||
|
||||
// Get entries and add them to the resources list
|
||||
const std::unordered_map<ResourceID, std::string> & entries = loader->getEntries();
|
||||
const boost::unordered_map<ResourceID, std::string> & entries = loader->getEntries();
|
||||
|
||||
boost::to_upper(mountPoint);
|
||||
|
||||
@ -337,7 +338,8 @@ void CResourceHandler::loadFileSystem(const std::string fsConfigURI)
|
||||
{
|
||||
BOOST_FOREACH(auto & entry, mountPoint.second.Vector())
|
||||
{
|
||||
tlog5 << "loading resource at " << entry["path"].String() << "\n";
|
||||
CStopWatch timer;
|
||||
tlog5 << "\t\tLoading resource at " << entry["path"].String();
|
||||
|
||||
std::string URI = entry["path"].String();
|
||||
if (entry["type"].String() == "dir")
|
||||
@ -364,6 +366,8 @@ void CResourceHandler::loadFileSystem(const std::string fsConfigURI)
|
||||
resourceLoader->addLoader(mountPoint.first,
|
||||
shared_ptr<ISimpleResourceLoader>(new CLodArchiveLoader(filename)), false);
|
||||
}
|
||||
|
||||
tlog5 << " took " << timer.getDiff() << " ms.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,12 +71,21 @@ public:
|
||||
*/
|
||||
ResourceID();
|
||||
|
||||
/**
|
||||
* Move Ctor.
|
||||
*/
|
||||
ResourceID(ResourceID && other)
|
||||
: name(std::move(other.name)), type(other.getType())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Ctor. Can be used to create indentifier for resource loading using one parameter
|
||||
*
|
||||
* @param name The resource name including extension.
|
||||
*/
|
||||
explicit ResourceID(const std::string & fullName);
|
||||
explicit ResourceID(std::string fullName);
|
||||
|
||||
/**
|
||||
* Ctor.
|
||||
@ -84,7 +93,7 @@ public:
|
||||
* @param name The resource name.
|
||||
* @param type The resource type. A constant from the enumeration EResType.
|
||||
*/
|
||||
ResourceID(const std::string & name, EResType::Type type);
|
||||
ResourceID(std::string name, EResType::Type type);
|
||||
|
||||
/**
|
||||
* Compares this object with a another resource identifier.
|
||||
@ -97,6 +106,16 @@ public:
|
||||
return name == other.name && type == other.type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move-assignment operator.
|
||||
*/
|
||||
inline ResourceID& operator=(ResourceID && other)
|
||||
{
|
||||
name = std::move(other.name);
|
||||
type = other.getType();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the identifier.
|
||||
*
|
||||
@ -116,7 +135,7 @@ public:
|
||||
*
|
||||
* @param name the name of the identifier. No extension, will be converted to uppercase.
|
||||
*/
|
||||
void setName(const std::string & name);
|
||||
void setName(std::string name);
|
||||
|
||||
/**
|
||||
* Sets the type of the identifier.
|
||||
@ -147,27 +166,40 @@ private:
|
||||
EResType::Type type;
|
||||
};
|
||||
|
||||
namespace std
|
||||
/**
|
||||
* Generates a hash value for the resource identifier object.
|
||||
*
|
||||
* @param resourceIdent The object from which a hash value should be generated.
|
||||
* @return the generated hash value
|
||||
*/
|
||||
inline size_t hash_value(const ResourceID & resourceIdent)
|
||||
{
|
||||
/**
|
||||
* Template specialization for std::hash.
|
||||
*/
|
||||
template <>
|
||||
class hash<ResourceID>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Generates a hash value for the resource identifier object.
|
||||
*
|
||||
* @param resourceIdent The object from which a hash value should be generated.
|
||||
* @return the generated hash value
|
||||
*/
|
||||
size_t operator()(const ResourceID & resourceIdent) const
|
||||
{
|
||||
return hash<string>()(resourceIdent.getName()) ^ hash<int>()(static_cast<int>(resourceIdent.getType()));
|
||||
}
|
||||
};
|
||||
};
|
||||
boost::hash<int> intHasher;
|
||||
boost::hash<std::string> stringHasher;
|
||||
return stringHasher(resourceIdent.getName()) ^ intHasher(static_cast<int>(resourceIdent.getType()));
|
||||
}
|
||||
|
||||
// namespace std
|
||||
// {
|
||||
// /**
|
||||
// * Template specialization for std::hash.
|
||||
// */
|
||||
// template <>
|
||||
// class hash<ResourceID>
|
||||
// {
|
||||
// public:
|
||||
// /**
|
||||
// * Generates a hash value for the resource identifier object.
|
||||
// *
|
||||
// * @param resourceIdent The object from which a hash value should be generated.
|
||||
// * @return the generated hash value
|
||||
// */
|
||||
// size_t operator()(const ResourceID & resourceIdent) const
|
||||
// {
|
||||
// return hash<string>()(resourceIdent.getName()) ^ hash<int>()(static_cast<int>(resourceIdent.getType()));
|
||||
// }
|
||||
// };
|
||||
// };
|
||||
|
||||
/**
|
||||
* This class manages the loading of resources whether standard
|
||||
@ -175,7 +207,7 @@ public:
|
||||
*/
|
||||
class DLL_LINKAGE CResourceLoader
|
||||
{
|
||||
typedef std::unordered_map<ResourceID, std::list<ResourceLocator> > ResourcesMap;
|
||||
typedef boost::unordered_map<ResourceID, std::vector<ResourceLocator> > ResourcesMap;
|
||||
|
||||
public:
|
||||
/// class for iterating over all available files/Identifiers
|
||||
@ -259,7 +291,7 @@ public:
|
||||
ResourceLocator getResource(const ResourceID & resourceIdent) const;
|
||||
|
||||
/// returns ALL overriden resources with same name, including last one acessible via getResource
|
||||
const std::list<ResourceLocator> & getResourcesWithName(const ResourceID & resourceIdent) const;
|
||||
const std::vector<ResourceLocator> & getResourcesWithName(const ResourceID & resourceIdent) const;
|
||||
|
||||
/// returns real name of file in filesystem. Not usable for archives
|
||||
std::string getResourceName(const ResourceID & resourceIdent) const;
|
||||
@ -309,7 +341,7 @@ public:
|
||||
*/
|
||||
void addLoader(std::string mountPoint, shared_ptr<ISimpleResourceLoader> loader, bool writeable);
|
||||
|
||||
private:
|
||||
public:
|
||||
|
||||
/**
|
||||
* Contains lists of same resources which can be accessed uniquely by an
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
*
|
||||
* @return Returns a list of all entries in the archive or (file) system.
|
||||
*/
|
||||
virtual std::unordered_map<ResourceID, std::string> getEntries() const =0;
|
||||
virtual boost::unordered_map<ResourceID, std::string> getEntries() const =0;
|
||||
|
||||
/**
|
||||
* Gets the origin of the loader.
|
||||
|
Loading…
Reference in New Issue
Block a user