1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-15 11:46:56 +02:00

some work on new filesystem, not tested

- one more new file
- removed duplicating code
- filesystem parser is now recursive
- decompression should be possible if decompressed size is unknown
- autotools and cmake update
This commit is contained in:
Ivan Savenko 2012-07-23 10:23:43 +00:00
parent 4bd8a5a15b
commit a72a294a46
17 changed files with 434 additions and 460 deletions

View File

@ -2,7 +2,6 @@ project(vcmiclient)
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib) include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/BattleInterface ${CMAKE_CURRENT_SOURCE_DIR}/UIFramework)
include_directories(${SDL_INCLUDE_DIR} ${SDLIMAGE_INCLUDE_DIR} ${SDLMIXER_INCLUDE_DIR} ${SDLTTF_INCLUDE_DIR}) include_directories(${SDL_INCLUDE_DIR} ${SDLIMAGE_INCLUDE_DIR} ${SDLMIXER_INCLUDE_DIR} ${SDLTTF_INCLUDE_DIR})
include_directories(${Boost_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR} ${FFMPEG_INCLUDE_DIR}) include_directories(${Boost_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR} ${FFMPEG_INCLUDE_DIR})

View File

@ -1,10 +1,19 @@
project(libvcmi) project(libvcmi)
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIRECTORY}) include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIRECTORY} ${CMAKE_HOME_DIRECTORY}/lib)
include_directories(${SDL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) include_directories(${SDL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
set(lib_SRCS set(lib_SRCS
Filesystem/CBinaryReader.cpp
Filesystem/CFilesystemLoader.cpp
Filesystem/CMemoryStream.cpp
Filesystem/CFileInfo.cpp
Filesystem/CLodArchiveLoader.cpp
Filesystem/CResourceLoader.cpp
Filesystem/CFileInputStream.cpp
Filesystem/CLodStream.cpp
Filesystem/ISimpleResourceLoader.cpp
BattleAction.cpp BattleAction.cpp
BattleHex.cpp BattleHex.cpp
BattleState.cpp BattleState.cpp

View File

@ -3,6 +3,25 @@
#include <SDL_endian.h> #include <SDL_endian.h>
#include "CInputStream.h" #include "CInputStream.h"
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
template <typename CData>
CData readLE(CData data)
{
auto dataPtr = (char*)&data;
std::reverse(dataPtr, dataPtr + sizeof(data));
return data;
}
#else
template <typename CData>
CData readLE(CData data)
{
return data;
}
#endif
CBinaryReader::CBinaryReader() : stream(nullptr) CBinaryReader::CBinaryReader() : stream(nullptr)
{ {
@ -28,101 +47,37 @@ si64 CBinaryReader::read(ui8 * data, si64 size)
return stream->read(data, size); return stream->read(data, size);
} }
ui8 CBinaryReader::readUInt8() template <typename CData>
CData CBinaryReader::readInteger()
{ {
ui8 val; CData val;
si64 b = stream->read(&val, 1); si64 b = stream->read(reinterpret_cast<unsigned char *>(&val), sizeof(val));
if(b < 1) if(b < sizeof(val))
{ {
throw std::runtime_error(getEndOfStreamExceptionMsg(1)); throw std::runtime_error(getEndOfStreamExceptionMsg(sizeof(val)));
} }
return val; return readLE(val);
} }
si8 CBinaryReader::readInt8() //FIXME: any way to do this without macro?
{ #define INSTANTIATE(datatype, methodname) \
si8 val; datatype CBinaryReader::methodname() \
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 1); { return readInteger<datatype>(); }
if(b < 1)
{
throw std::runtime_error(getEndOfStreamExceptionMsg(1));
}
return val; // While it is certanly possible to leave only template method
} // but typing template parameter every time can be annoying
// and templates parameters can't be resolved by return type
INSTANTIATE(ui8, readUInt8)
INSTANTIATE(si8, readInt8)
INSTANTIATE(ui16, readUInt16)
INSTANTIATE(si16, readInt16)
INSTANTIATE(ui32, readUInt32)
INSTANTIATE(si32, readInt32)
INSTANTIATE(ui64, readUInt64)
INSTANTIATE(si64, readInt64)
ui16 CBinaryReader::readUInt16() #undef INSTANTIATE
{
ui16 val;
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 2);
if(b < 2)
{
throw std::runtime_error(getEndOfStreamExceptionMsg(2));
}
return SDL_SwapLE16(val);
}
si16 CBinaryReader::readInt16()
{
si16 val;
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 2);
if(b < 2)
{
throw std::runtime_error(getEndOfStreamExceptionMsg(2));
}
return SDL_SwapLE16(val);
}
ui32 CBinaryReader::readUInt32()
{
ui32 val;
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 4);
if(b < 4)
{
throw std::runtime_error(getEndOfStreamExceptionMsg(4));
}
return SDL_SwapLE32(val);
}
si32 CBinaryReader::readInt32()
{
si32 val;
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 4);
if(b < 4)
{
throw std::runtime_error(getEndOfStreamExceptionMsg(4));
}
return SDL_SwapLE32(val);
}
ui64 CBinaryReader::readUInt64()
{
ui64 val;
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 8);
if(b < 8)
{
throw std::runtime_error(getEndOfStreamExceptionMsg(8));
}
return SDL_SwapLE64(val);
}
si64 CBinaryReader::readInt64()
{
si64 val;
si64 b = stream->read(reinterpret_cast<ui8 *>(&val), 8);
if(b < 8)
{
throw std::runtime_error(getEndOfStreamExceptionMsg(8));
}
return SDL_SwapLE64(val);
}
std::string CBinaryReader::getEndOfStreamExceptionMsg(long bytesToRead) const std::string CBinaryReader::getEndOfStreamExceptionMsg(long bytesToRead) const
{ {

View File

@ -21,6 +21,16 @@ class CInputStream;
*/ */
class DLL_LINKAGE CBinaryReader : public boost::noncopyable class DLL_LINKAGE CBinaryReader : public boost::noncopyable
{ {
/**
* Reads any integer. Advances the read pointer by its size.
*
* @return read integer.
*
* @throws std::runtime_error if the end of the stream was reached unexpectedly
*/
template <typename CData>
CData readInteger();
public: public:
/** /**
* Default c-tor. * Default c-tor.

View File

@ -80,7 +80,7 @@ std::time_t CFileInfo::getDate() const
return boost::filesystem::last_write_time(name); return boost::filesystem::last_write_time(name);
} }
std::unique_ptr<std::list<CFileInfo> > CFileInfo::listFiles(const std::string & extensionFilter /*= ""*/) const std::unique_ptr<std::list<CFileInfo> > CFileInfo::listFiles(size_t depth, const std::string & extensionFilter /*= ""*/) const
{ {
std::unique_ptr<std::list<CFileInfo> > fileListPtr; std::unique_ptr<std::list<CFileInfo> > fileListPtr;
@ -88,8 +88,14 @@ std::unique_ptr<std::list<CFileInfo> > CFileInfo::listFiles(const std::string &
{ {
std::list<CFileInfo> * fileList = new std::list<CFileInfo>; std::list<CFileInfo> * fileList = new std::list<CFileInfo>;
boost::filesystem::directory_iterator enddir; boost::filesystem::recursive_directory_iterator enddir;
for(boost::filesystem::directory_iterator it(name); it != enddir; ++it) for(boost::filesystem::recursive_directory_iterator it(name); it != enddir; ++it)
{
if (boost::filesystem::is_directory(it->status()))
{
it.no_push(depth >= it.level());
}
if(boost::filesystem::is_regular(it->status()))
{ {
if(extensionFilter == "" || it->path().extension() == extensionFilter) if(extensionFilter == "" || it->path().extension() == extensionFilter)
{ {
@ -97,6 +103,7 @@ std::unique_ptr<std::list<CFileInfo> > CFileInfo::listFiles(const std::string &
fileList->push_back(file); fileList->push_back(file);
} }
} }
}
fileListPtr.reset(fileList); fileListPtr.reset(fileList);
} }

View File

@ -111,7 +111,7 @@ public:
* @return a list of pathnames denoting the files and directories in the directory denoted by this pathname as a unique ptr. * @return a list of pathnames denoting the files and directories in the directory denoted by this pathname as a unique ptr.
* 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. * 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::unique_ptr<std::list<CFileInfo> > listFiles(const std::string & extensionFilter = "") const; std::unique_ptr<std::list<CFileInfo> > listFiles(size_t depth, const std::string & extensionFilter = "") const;
private: private:
/** Contains the original URI(not modified) e.g. ./dir/foo.txt */ /** Contains the original URI(not modified) e.g. ./dir/foo.txt */

View File

@ -9,23 +9,23 @@ CFilesystemLoader::CFilesystemLoader()
} }
CFilesystemLoader::CFilesystemLoader(const std::string & baseDirectory) CFilesystemLoader::CFilesystemLoader(const std::string & baseDirectory, size_t depth)
{ {
open(baseDirectory); open(baseDirectory, depth);
} }
CFilesystemLoader::CFilesystemLoader(const CFileInfo & baseDirectory) CFilesystemLoader::CFilesystemLoader(const CFileInfo & baseDirectory, size_t depth)
{ {
open(baseDirectory); open(baseDirectory, depth);
} }
void CFilesystemLoader::open(const std::string & baseDirectory) void CFilesystemLoader::open(const std::string & baseDirectory, size_t depth)
{ {
// Indexes all files in the directory and store them // Indexes all files in the directory and store them
this->baseDirectory = baseDirectory; this->baseDirectory = baseDirectory;
CFileInfo directory(baseDirectory); CFileInfo directory(baseDirectory);
std::unique_ptr<std::list<CFileInfo> > fileList = directory.listFiles(); std::unique_ptr<std::list<CFileInfo> > fileList = directory.listFiles(depth);
if(fileList == nullptr) if(fileList)
{ {
throw std::runtime_error("Directory " + baseDirectory + " not available."); throw std::runtime_error("Directory " + baseDirectory + " not available.");
} }
@ -33,9 +33,9 @@ void CFilesystemLoader::open(const std::string & baseDirectory)
this->fileList = std::move(*fileList); this->fileList = std::move(*fileList);
} }
void CFilesystemLoader::open(const CFileInfo & baseDirectory) void CFilesystemLoader::open(const CFileInfo & baseDirectory, size_t depth)
{ {
open(baseDirectory.getName()); open(baseDirectory.getName(), depth);
} }
std::unique_ptr<CInputStream> CFilesystemLoader::load(const std::string & resourceName) const std::unique_ptr<CInputStream> CFilesystemLoader::load(const std::string & resourceName) const

View File

@ -31,10 +31,11 @@ public:
* Ctor. * Ctor.
* *
* @param baseDirectory Specifies the base directory and their sub-directories which should be indexed. * @param baseDirectory Specifies the base directory and their sub-directories which should be indexed.
* @param depth - recursion depth of subdirectories search. 0 = no recursion
* *
* @throws std::runtime_error if the base directory is not a directory or if it is not available * @throws std::runtime_error if the base directory is not a directory or if it is not available
*/ */
explicit CFilesystemLoader(const std::string & baseDirectory); explicit CFilesystemLoader(const std::string & baseDirectory, size_t depth = 16);
/** /**
* Ctor. * Ctor.
@ -43,7 +44,7 @@ public:
* *
* @throws std::runtime_error if the base directory is not a directory or if it is not available * @throws std::runtime_error if the base directory is not a directory or if it is not available
*/ */
explicit CFilesystemLoader(const CFileInfo & baseDirectory); explicit CFilesystemLoader(const CFileInfo & baseDirectory, size_t depth = 16);
/** /**
* Opens a base directory to be read and indexed. * Opens a base directory to be read and indexed.
@ -52,7 +53,7 @@ public:
* *
* @throws std::runtime_error if the base directory is not a directory or if it is not available * @throws std::runtime_error if the base directory is not a directory or if it is not available
*/ */
void open(const std::string & baseDirectory); void open(const std::string & baseDirectory, size_t depth);
/** /**
* Opens a base directory to be read and indexed. * Opens a base directory to be read and indexed.
@ -61,7 +62,7 @@ public:
* *
* @throws std::runtime_error if the base directory is not a directory or if it is not available * @throws std::runtime_error if the base directory is not a directory or if it is not available
*/ */
void open(const CFileInfo & baseDirectory); void open(const CFileInfo & baseDirectory, size_t depth);
/** /**
* Loads a resource with the given resource name. * Loads a resource with the given resource name.

View File

@ -3,7 +3,6 @@
#include "CLodArchiveLoader.h" #include "CLodArchiveLoader.h"
#include "CFileInputStream.h" #include "CFileInputStream.h"
#include <zlib.h>
CLodStream::CLodStream() CLodStream::CLodStream()
{ {
@ -48,87 +47,22 @@ si64 CLodStream::read(ui8 * data, si64 size)
assert(size >= archiveEntry->realSize); assert(size >= archiveEntry->realSize);
// Read the compressed data into a buffer // Read the compressed data into a buffer
ui8 * comp = new ui8[archiveEntry->size]; auto comp = std::unique_ptr<ui8[]>(new ui8[archiveEntry->size]);
fileStream.read(comp, archiveEntry->size); fileStream.read(comp.get(), archiveEntry->size);
// Decompress the file // Decompress the file
if(!decompressFile(comp, archiveEntry->size, archiveEntry->realSize, data)) data = CLodArchiveLoader::decompressFile(comp.get(), archiveEntry->size, archiveEntry->realSize).first;
if (!data)
{ {
throw std::runtime_error("File decompression wasn't successful. Resource name: " + archiveEntry->name); throw std::runtime_error("File decompression wasn't successful. Resource name: " + archiveEntry->name);
} }
delete[] comp;
// We're reading the total size always // We're reading the total size always
return archiveEntry->realSize; return archiveEntry->realSize;
} }
} }
bool CLodStream::decompressFile(ui8 * in, int size, int realSize, ui8 * out)
{
const int WBITS = 15;
const int FCHUNK = 50000;
int ret;
unsigned have;
z_stream strm;
int latPosOut = 0;
// Allocate inflate state
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, WBITS);
if (ret != Z_OK)
return false;
int chunkNumber = 0;
do
{
if(size < chunkNumber * FCHUNK)
break;
strm.avail_in = std::min(FCHUNK, size - chunkNumber * FCHUNK);
if (strm.avail_in == 0)
break;
strm.next_in = in + chunkNumber * FCHUNK;
// Run inflate() on input until output buffer not full
do
{
strm.avail_out = realSize - latPosOut;
strm.next_out = out + latPosOut;
ret = inflate(&strm, Z_NO_FLUSH);
bool breakLoop = false;
switch (ret)
{
case Z_STREAM_END:
breakLoop = true;
break;
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return false;
}
if(breakLoop)
break;
have = realSize - latPosOut - strm.avail_out;
latPosOut += have;
} while (strm.avail_out == 0);
++chunkNumber;
} while (ret != Z_STREAM_END);
// Clean up and return
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? true : false;
}
si64 CLodStream::seek(si64 position) si64 CLodStream::seek(si64 position)
{ {
return fileStream.seek(archiveEntry->offset + position); return fileStream.seek(archiveEntry->offset + position);

View File

@ -96,15 +96,6 @@ public:
void close(); void close();
private: private:
/**
* Decompresses an archive entry.
*
* @param in A pointer to the compressed data array
* @param size The size of the compressed data array
* @param realSize The size of the decompressed real size of the entry
* @param out
*/
bool decompressFile(ui8 * in, int size, int realSize, ui8 * out);
/** The file stream for reading from the LOD archive. */ /** The file stream for reading from the LOD archive. */
CFileInputStream fileStream; CFileInputStream fileStream;

View File

@ -5,9 +5,9 @@
CResourceLoader * CResourceLoaderFactory::resourceLoader = nullptr; CResourceLoader * CResourceLoaderFactory::resourceLoader = nullptr;
ResourceIdentifier::ResourceIdentifier() : type(EResType::OTHER) ResourceIdentifier::ResourceIdentifier()
:type(EResType::OTHER)
{ {
} }
ResourceIdentifier::ResourceIdentifier(const std::string & name, EResType type) : name(name), type(type) ResourceIdentifier::ResourceIdentifier(const std::string & name, EResType type) : name(name), type(type)
@ -38,28 +38,29 @@ void ResourceIdentifier::setType(EResType type)
CResourceLoader::CResourceLoader() CResourceLoader::CResourceLoader()
{ {
} }
CResourceLoader::~CResourceLoader() CResourceLoader::~CResourceLoader()
{ {
// Delete all loader objects // Delete all loader objects
for(auto it = loaders.begin(); it != loaders.end(); ++it) BOOST_FOREACH ( ISimpleResourceLoader* it, loaders)
{ {
delete *it; delete it;
} }
} }
std::unique_ptr<CInputStream> CResourceLoader::load(const ResourceIdentifier & resourceIdent) const std::unique_ptr<CInputStream> CResourceLoader::load(const ResourceIdentifier & resourceIdent) const
{ {
if(!existsResource(resourceIdent)) auto resource = resources.find(resourceIdent);
if(resource == resources.end())
{ {
throw std::runtime_error("Resource with name " + resourceIdent.getName() + " and type " throw std::runtime_error("Resource with name " + resourceIdent.getName() + " and type "
+ EResTypeHelper::getEResTypeAsString(resourceIdent.getType()) + " wasn't found."); + EResTypeHelper::getEResTypeAsString(resourceIdent.getType()) + " wasn't found.");
} }
// get the last added resource(most overriden) // get the last added resource(most overriden)
const ResourceLocator & locator = resources.at(resourceIdent).back(); const ResourceLocator & locator = resource->second.back();
// load the resource and return it // load the resource and return it
return locator.getLoader()->load(locator.getResourceName()); return locator.getLoader()->load(locator.getResourceName());
@ -68,14 +69,7 @@ std::unique_ptr<CInputStream> CResourceLoader::load(const ResourceIdentifier & r
bool CResourceLoader::existsResource(const ResourceIdentifier & resourceIdent) const bool CResourceLoader::existsResource(const ResourceIdentifier & resourceIdent) const
{ {
// Check if resource is registered // Check if resource is registered
if(resources.find(resourceIdent) != resources.end()) return resources.find(resourceIdent) != resources.end();
{
return true;
}
else
{
return false;
}
} }
void CResourceLoader::addLoader(ISimpleResourceLoader * loader) void CResourceLoader::addLoader(ISimpleResourceLoader * loader)
@ -85,9 +79,8 @@ void CResourceLoader::addLoader(ISimpleResourceLoader * loader)
// Get entries and add them to the resources list // Get entries and add them to the resources list
const std::list<std::string> & entries = loader->getEntries(); const std::list<std::string> & entries = loader->getEntries();
for(auto it = entries.begin(); it != entries.end(); ++it) BOOST_FOREACH (const std::string & entry, entries)
{ {
std::string entry = *it;
CFileInfo file(entry); CFileInfo file(entry);
// Create identifier and locator and add them to the resources list // Create identifier and locator and add them to the resources list
@ -137,118 +130,68 @@ EResType EResTypeHelper::getTypeFromExtension(std::string extension)
{ {
boost::to_upper(extension); boost::to_upper(extension);
if(extension == ".TXT" || extension == ".JSON") static const std::map<std::string, EResType> stringToRes =
{ boost::assign::map_list_of
return EResType::TEXT; (".TXT", EResType::TEXT)
} (".JSON", EResType::TEXT)
else if(extension == ".DEF" || extension == ".JSON") (".DEF", EResType::ANIMATION)
{ (".MSK", EResType::MASK)
return EResType::ANIMATION; (".MSG", EResType::MASK)
} (".H3C", EResType::CAMPAIGN)
else if(extension == ".MSK" || extension == ".MSG") (".H3M", EResType::MAP)
{ (".FNT", EResType::FONT)
return EResType::MASK; (".BMP", EResType::IMAGE)
} (".JPG", EResType::IMAGE)
else if(extension == ".H3C") (".PCX", EResType::IMAGE)
{ (".PNG", EResType::IMAGE)
return EResType::CAMPAIGN; (".TGA", EResType::IMAGE)
} (".WAV", EResType::SOUND)
else if(extension == ".H3M") (".SMK", EResType::VIDEO)
{ (".BIK", EResType::VIDEO)
return EResType::MAP; (".MJPG", EResType::VIDEO)
} (".MP3", EResType::MUSIC)
else if(extension == ".FNT") (".OGG", EResType::MUSIC)
{ (".LOD", EResType::ARCHIVE)
return EResType::FONT; (".VID", EResType::ARCHIVE)
} (".SND", EResType::ARCHIVE)
else if(extension == ".BMP" || extension == ".JPG" || extension == ".PCX" || extension == ".PNG" || extension == ".TGA") (".VCGM1", EResType::CLIENT_SAVEGAME)
{ (".VLGM1", EResType::LIB_SAVEGAME)
return EResType::IMAGE; (".VSGM1", EResType::SERVER_SAVEGAME);
}
else if(extension == ".WAV") auto iter = stringToRes.find(extension);
{ if (iter == stringToRes.end())
return EResType::SOUND;
}
else if(extension == ".SMK" || extension == ".BIK")
{
return EResType::VIDEO;
}
else if(extension == ".MP3" || extension == ".OGG")
{
return EResType::MUSIC;
}
else if(extension == ".ZIP" || extension == ".TAR.GZ" || extension == ".LOD" || extension == ".VID" || extension == ".SND")
{
return EResType::ARCHIVE;
}
else if(extension == ".VLGM1")
{
return EResType::SAVEGAME;
}
else
{
return EResType::OTHER; return EResType::OTHER;
} return iter->second;
} }
std::string EResTypeHelper::getEResTypeAsString(EResType type) std::string EResTypeHelper::getEResTypeAsString(EResType type)
{ {
if(type == EResType::ANIMATION)
{
return "ANIMATION";
}
else if(type == EResType::ANY)
{
return "ANY";
}
else if(type == EResType::ARCHIVE)
{
return "ARCHIVE";
}
else if(type == EResType::CAMPAIGN)
{
return "CAMPAIGN";
}
else if(type == EResType::FONT)
{
return "FONT";
}
else if(type == EResType::IMAGE)
{
return "IMAGE";
}
else if(type == EResType::MAP)
{
return "MAP";
}
else if(type == EResType::MASK)
{
return "MASK";
}
else if(type == EResType::MUSIC)
{
return "MUSIC";
}
else if(type == EResType::OTHER)
{
return "OTHER";
}
else if(type == EResType::SAVEGAME)
{
return "SAVEGAME";
}
else if(type == EResType::SOUND)
{
return "SOUND";
}
else if(type == EResType::TEXT)
{
return "TEXT";
}
else if(type == EResType::VIDEO)
{
return "VIDEO";
}
return ""; #define MAP_ENUM(value) (EResType::value, "value")
static const std::map<EResType, std::string> stringToRes = boost::assign::map_list_of
MAP_ENUM(ANY)
MAP_ENUM(TEXT)
MAP_ENUM(ANIMATION)
MAP_ENUM(MASK)
MAP_ENUM(CAMPAIGN)
MAP_ENUM(MAP)
MAP_ENUM(FONT)
MAP_ENUM(IMAGE)
MAP_ENUM(VIDEO)
MAP_ENUM(SOUND)
MAP_ENUM(MUSIC)
MAP_ENUM(ARCHIVE)
MAP_ENUM(CLIENT_SAVEGAME)
MAP_ENUM(LIB_SAVEGAME)
MAP_ENUM(SERVER_SAVEGAME)
MAP_ENUM(OTHER);
#undef MAP_ENUM
auto iter = stringToRes.find(type);
assert(iter != stringToRes.end());
return iter->second;
} }

View File

@ -21,7 +21,7 @@ class ISimpleResourceLoader;
* *
* Supported file extensions: * Supported file extensions:
* *
* Text: .json * Text: .txt .json
* Animation: .def * Animation: .def
* Mask: .msk * Mask: .msk
* Campaign: .h3c * Campaign: .h3c
@ -29,10 +29,10 @@ class ISimpleResourceLoader;
* Font: .fnt * Font: .fnt
* Image: .bmp, .jpg, .pcx, .png, .tga * Image: .bmp, .jpg, .pcx, .png, .tga
* Sound: .wav * Sound: .wav
* Video: .smk, .bik * Video: .smk, .bik .mjpg
* Music: .mp3, .ogg * Music: .mp3, .ogg
* Archive: .lod, .snd, .vid, .zip, .tar.gz * Archive: .lod, .snd, .vid
* Savegame: .vlgm1 * Savegame: .v*gm1
*/ */
enum EResType enum EResType
{ {
@ -48,7 +48,9 @@ enum EResType
SOUND, SOUND,
MUSIC, MUSIC,
ARCHIVE, ARCHIVE,
SAVEGAME, CLIENT_SAVEGAME,
LIB_SAVEGAME,
SERVER_SAVEGAME,
OTHER OTHER
}; };

View File

@ -0,0 +1,103 @@
#include "StdInc.h"
#include "ISimpleResourceLoader.h"
#include <zlib.h>
std::pair<ui8*, size_t> ISimpleResourceLoader::decompressFile(ui8 * in, size_t size, size_t realSize)
{
std::pair<ui8*, size_t> retError(nullptr, 0);
if (realSize == 0)
realSize = 16 * 1024;
std::unique_ptr<ui8[]> out(new ui8[realSize]);
const int WBITS = 15;
const int FCHUNK = 50000;
int ret;
z_stream strm;
int lastPosOut = 0;
// Allocate inflate state
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, WBITS);
if (ret != Z_OK)
return retError;
int chunkNumber = 0;
do
{
if(size < chunkNumber * FCHUNK)
break;
strm.avail_in = std::min<size_t>(FCHUNK, size - chunkNumber * FCHUNK);
if (strm.avail_in == 0)
break;
strm.next_in = in + chunkNumber * FCHUNK;
// Run inflate() on input until output buffer not full
do
{
strm.avail_out = realSize - lastPosOut;
strm.next_out = out.get() + lastPosOut;
ret = inflate(&strm, Z_NO_FLUSH);
bool breakLoop = false;
switch (ret)
{
case Z_STREAM_END:
breakLoop = true;
break;
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
case Z_DATA_ERROR:
inflateEnd(&strm);
return retError;
case Z_MEM_ERROR:
{
//not enough memory. Allocate bigger buffer and try again
realSize *= 2;
std::unique_ptr<ui8[]> newOut(new ui8[realSize]);
std::copy(out.get(), out.get() + strm.total_out, newOut.get());
out.reset(newOut.release());
}
}
if(breakLoop)
break;
lastPosOut = realSize - strm.avail_out;
}
while (strm.avail_out == 0);
++chunkNumber;
}
while (ret != Z_STREAM_END);
// Clean up and return
while (1)
{
ret = inflateEnd(&strm);
switch (ret)
{
case Z_STREAM_END:
//TODO: trim buffer? may be too time consuming
return std::make_pair(out.release(), realSize - strm.avail_out);
case Z_BUF_ERROR:
{
//not enough memory. Allocate bigger buffer and try again
realSize *= 2;
std::unique_ptr<ui8[]> newOut(new ui8[realSize]);
std::copy(out.get(), out.get() + strm.total_out, newOut.get());
out.reset(newOut.release());
}
default:
return retError;
}
}
}

View File

@ -19,6 +19,16 @@
class DLL_LINKAGE ISimpleResourceLoader class DLL_LINKAGE ISimpleResourceLoader
{ {
public: public:
/**
* Decompresses an archive entry.
*
* @param in A pointer to the compressed data array
* @param size The size of the compressed data array
* @param realSize The size of the decompressed real size of the entry or 0 if not known (slower)
* @returns pair(decompressed data, size)
*/
static std::pair<ui8*, size_t> decompressFile(ui8 * in, size_t size, size_t realSize);
/** /**
* Dtor. * Dtor.
*/ */

View File

@ -15,6 +15,7 @@ libvcmi_la_SOURCES = \
Filesystem/CLodStream.cpp \ Filesystem/CLodStream.cpp \
Filesystem/CMemoryStream.cpp \ Filesystem/CMemoryStream.cpp \
Filesystem/CResourceLoader.cpp \ Filesystem/CResourceLoader.cpp \
Filesystem/ISimpleResourceLoader.cpp \
BattleAction.cpp \ BattleAction.cpp \
BattleAction.h \ BattleAction.h \
BattleState.cpp \ BattleState.cpp \

View File

@ -90,22 +90,22 @@ am_libvcmi_la_OBJECTS = libvcmi_la-CBinaryReader.lo \
libvcmi_la-CFilesystemLoader.lo \ libvcmi_la-CFilesystemLoader.lo \
libvcmi_la-CLodArchiveLoader.lo libvcmi_la-CLodStream.lo \ libvcmi_la-CLodArchiveLoader.lo libvcmi_la-CLodStream.lo \
libvcmi_la-CMemoryStream.lo libvcmi_la-CResourceLoader.lo \ libvcmi_la-CMemoryStream.lo libvcmi_la-CResourceLoader.lo \
libvcmi_la-BattleAction.lo libvcmi_la-BattleState.lo \ libvcmi_la-ISimpleResourceLoader.lo libvcmi_la-BattleAction.lo \
libvcmi_la-CArtHandler.lo libvcmi_la-CBuildingHandler.lo \ libvcmi_la-BattleState.lo libvcmi_la-CArtHandler.lo \
libvcmi_la-CCampaignHandler.lo libvcmi_la-CConsoleHandler.lo \ libvcmi_la-CBuildingHandler.lo libvcmi_la-CCampaignHandler.lo \
libvcmi_la-CCreatureHandler.lo libvcmi_la-CCreatureSet.lo \ libvcmi_la-CConsoleHandler.lo libvcmi_la-CCreatureHandler.lo \
libvcmi_la-CDefObjInfoHandler.lo libvcmi_la-CFileUtility.lo \ libvcmi_la-CCreatureSet.lo libvcmi_la-CDefObjInfoHandler.lo \
libvcmi_la-CGameInterface.lo libvcmi_la-CGameState.lo \ libvcmi_la-CFileUtility.lo libvcmi_la-CGameInterface.lo \
libvcmi_la-CGeneralTextHandler.lo libvcmi_la-CHeroHandler.lo \ libvcmi_la-CGameState.lo libvcmi_la-CGeneralTextHandler.lo \
libvcmi_la-CLodHandler.lo libvcmi_la-CLogger.lo \ libvcmi_la-CHeroHandler.lo libvcmi_la-CLodHandler.lo \
libvcmi_la-CMapInfo.lo libvcmi_la-CObjectHandler.lo \ libvcmi_la-CLogger.lo libvcmi_la-CMapInfo.lo \
libvcmi_la-CObstacleInstance.lo libvcmi_la-CSpellHandler.lo \ libvcmi_la-CObjectHandler.lo libvcmi_la-CObstacleInstance.lo \
libvcmi_la-CTownHandler.lo libvcmi_la-CThreadHelper.lo \ libvcmi_la-CSpellHandler.lo libvcmi_la-CTownHandler.lo \
libvcmi_la-Connection.lo libvcmi_la-HeroBonus.lo \ libvcmi_la-CThreadHelper.lo libvcmi_la-Connection.lo \
libvcmi_la-IGameCallback.lo libvcmi_la-JsonNode.lo \ libvcmi_la-HeroBonus.lo libvcmi_la-IGameCallback.lo \
libvcmi_la-NetPacksLib.lo libvcmi_la-ResourceSet.lo \ libvcmi_la-JsonNode.lo libvcmi_la-NetPacksLib.lo \
libvcmi_la-BattleHex.lo libvcmi_la-VCMI_Lib.lo \ libvcmi_la-ResourceSet.lo libvcmi_la-BattleHex.lo \
libvcmi_la-map.lo libvcmi_la-VCMI_Lib.lo libvcmi_la-map.lo
libvcmi_la_OBJECTS = $(am_libvcmi_la_OBJECTS) libvcmi_la_OBJECTS = $(am_libvcmi_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@) AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -308,6 +308,7 @@ libvcmi_la_SOURCES = \
Filesystem/CLodStream.cpp \ Filesystem/CLodStream.cpp \
Filesystem/CMemoryStream.cpp \ Filesystem/CMemoryStream.cpp \
Filesystem/CResourceLoader.cpp \ Filesystem/CResourceLoader.cpp \
Filesystem/ISimpleResourceLoader.cpp \
BattleAction.cpp \ BattleAction.cpp \
BattleAction.h \ BattleAction.h \
BattleState.cpp \ BattleState.cpp \
@ -487,6 +488,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-Connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-Connection.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-HeroBonus.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-HeroBonus.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-IGameCallback.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-IGameCallback.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-ISimpleResourceLoader.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-JsonNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-JsonNode.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-NetPacksLib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-NetPacksLib.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-ResourceSet.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-ResourceSet.Plo@am__quote@
@ -570,6 +572,13 @@ libvcmi_la-CResourceLoader.lo: Filesystem/CResourceLoader.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CResourceLoader.lo `test -f 'Filesystem/CResourceLoader.cpp' || echo '$(srcdir)/'`Filesystem/CResourceLoader.cpp @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CResourceLoader.lo `test -f 'Filesystem/CResourceLoader.cpp' || echo '$(srcdir)/'`Filesystem/CResourceLoader.cpp
libvcmi_la-ISimpleResourceLoader.lo: Filesystem/ISimpleResourceLoader.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-ISimpleResourceLoader.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-ISimpleResourceLoader.Tpo -c -o libvcmi_la-ISimpleResourceLoader.lo `test -f 'Filesystem/ISimpleResourceLoader.cpp' || echo '$(srcdir)/'`Filesystem/ISimpleResourceLoader.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-ISimpleResourceLoader.Tpo $(DEPDIR)/libvcmi_la-ISimpleResourceLoader.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Filesystem/ISimpleResourceLoader.cpp' object='libvcmi_la-ISimpleResourceLoader.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-ISimpleResourceLoader.lo `test -f 'Filesystem/ISimpleResourceLoader.cpp' || echo '$(srcdir)/'`Filesystem/ISimpleResourceLoader.cpp
libvcmi_la-BattleAction.lo: BattleAction.cpp libvcmi_la-BattleAction.lo: BattleAction.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-BattleAction.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-BattleAction.Tpo -c -o libvcmi_la-BattleAction.lo `test -f 'BattleAction.cpp' || echo '$(srcdir)/'`BattleAction.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-BattleAction.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-BattleAction.Tpo -c -o libvcmi_la-BattleAction.lo `test -f 'BattleAction.cpp' || echo '$(srcdir)/'`BattleAction.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-BattleAction.Tpo $(DEPDIR)/libvcmi_la-BattleAction.Plo @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-BattleAction.Tpo $(DEPDIR)/libvcmi_la-BattleAction.Plo

View File

@ -912,7 +912,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
tlog1 << e.what() << std::endl; tlog1 << e.what() << std::endl;
end2 = true; end2 = true;
} }
//HANDLE_EXCEPTION(end2 = true); HANDLE_EXCEPTION(end2 = true);
tlog1 << "Ended handling connection\n"; tlog1 << "Ended handling connection\n";
} }