diff --git a/lib/filesystem/MinizipExtensions.cpp b/lib/filesystem/MinizipExtensions.cpp index f1283e6e1..aa3b77a2d 100644 --- a/lib/filesystem/MinizipExtensions.cpp +++ b/lib/filesystem/MinizipExtensions.cpp @@ -13,53 +13,31 @@ #include "CMemoryBuffer.h" #include "FileStream.h" -///CIOApi -voidpf ZCALLBACK CIOApi::openFileProxy(voidpf opaque, const void * filename, int mode) -{ - assert(opaque != nullptr); - - boost::filesystem::path path; - - if(filename != nullptr) - path = static_cast(filename); - - return ((CIOApi *)opaque)->openFile(path, mode); -} - -uLong ZCALLBACK CIOApi::readFileProxy(voidpf opaque, voidpf stream, void * buf, uLong size) +template inline uLong streamRead(voidpf opaque, voidpf stream, void * buf, uLong size) { assert(opaque != nullptr); assert(stream != nullptr); - CInputOutputStream * actualStream = static_cast(stream); + _Stream * actualStream = static_cast<_Stream *>(stream); return actualStream->read((ui8 *)buf, size); } -uLong ZCALLBACK CIOApi::writeFileProxy(voidpf opaque, voidpf stream, const void * buf, uLong size) +template inline ZPOS64_T streamTell(voidpf opaque, voidpf stream) { assert(opaque != nullptr); assert(stream != nullptr); - CInputOutputStream * actualStream = static_cast(stream); - return (uLong)actualStream->write((const ui8 *)buf, size); -} - -ZPOS64_T ZCALLBACK CIOApi::tellFileProxy(voidpf opaque, voidpf stream) -{ - assert(opaque != nullptr); - assert(stream != nullptr); - - CInputOutputStream * actualStream = static_cast(stream); + _Stream * actualStream = static_cast<_Stream *>(stream); return actualStream->tell(); } -long ZCALLBACK CIOApi::seekFileProxy(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +template inline long streamSeek(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { assert(opaque != nullptr); assert(stream != nullptr); - CInputOutputStream * actualStream = static_cast(stream); + _Stream * actualStream = static_cast<_Stream *>(stream); long ret = 0; switch (origin) @@ -82,47 +60,24 @@ long ZCALLBACK CIOApi::seekFileProxy(voidpf opaque, voidpf stream, ZPOS64_T off default: ret = -1; } if(ret == -1) - logGlobal->error("CIOApi::seekFileProxy: seek failed"); + logGlobal->error("Stream seek failed"); return ret; } -int ZCALLBACK CIOApi::closeFileProxy(voidpf opaque, voidpf stream) +template inline int streamProxyClose(voidpf opaque, voidpf stream) { assert(opaque != nullptr); assert(stream != nullptr); - CInputOutputStream * actualStream = static_cast(stream); + _Stream * actualStream = static_cast<_Stream *>(stream); - ((CIOApi *)opaque)->closeFile(actualStream); + logGlobal->traceStream() << "Proxy stream closed"; + + actualStream->seek(0); return 0; } -int ZCALLBACK CIOApi::errorFileProxy(voidpf opaque, voidpf stream) -{ - return 0; -} - -zlib_filefunc64_def CIOApi::getApiStructure() const -{ - zlib_filefunc64_def api; - api.opaque = (void *) this; - api.zopen64_file = &openFileProxy; - api.zread_file = &readFileProxy; - api.zwrite_file = &writeFileProxy; - api.ztell64_file = &tellFileProxy; - api.zseek64_file = &seekFileProxy; - api.zclose_file = &closeFileProxy; - api.zerror_file = &errorFileProxy; - - return api; -} - -void CIOApi::closeFile(CInputOutputStream * stream) const -{ - delete stream; -} - ///CDefaultIOApi CDefaultIOApi::CDefaultIOApi() { @@ -134,16 +89,11 @@ CDefaultIOApi::~CDefaultIOApi() } -zlib_filefunc64_def CDefaultIOApi::getApiStructure() const +zlib_filefunc64_def CDefaultIOApi::getApiStructure() { return * FileStream::GetMinizipFilefunc(); } -CInputOutputStream * CDefaultIOApi::openFile(const boost::filesystem::path & filename, int mode) const -{ - throw new std::runtime_error("CDefaultIOApi::openFile call not expected."); -} - ///CProxyIOApi CProxyIOApi::CProxyIOApi(CInputOutputStream * buffer): data(buffer) @@ -156,7 +106,68 @@ CProxyIOApi::~CProxyIOApi() } -CInputOutputStream * CProxyIOApi::openFile(const boost::filesystem::path & filename, int mode) const +zlib_filefunc64_def CProxyIOApi::getApiStructure() +{ + zlib_filefunc64_def api; + api.opaque = this; + api.zopen64_file = &openFileProxy; + api.zread_file = &readFileProxy; + api.zwrite_file = &writeFileProxy; + api.ztell64_file = &tellFileProxy; + api.zseek64_file = &seekFileProxy; + api.zclose_file = &closeFileProxy; + api.zerror_file = &errorFileProxy; + + return api; +} + +voidpf ZCALLBACK CProxyIOApi::openFileProxy(voidpf opaque, const void * filename, int mode) +{ + assert(opaque != nullptr); + + boost::filesystem::path path; + + if(filename != nullptr) + path = static_cast(filename); + + return ((CProxyIOApi *)opaque)->openFile(path, mode); +} + +uLong ZCALLBACK CProxyIOApi::readFileProxy(voidpf opaque, voidpf stream, void * buf, uLong size) +{ + return streamRead(opaque, stream, buf, size); +} + +uLong ZCALLBACK CProxyIOApi::writeFileProxy(voidpf opaque, voidpf stream, const void * buf, uLong size) +{ + assert(opaque != nullptr); + assert(stream != nullptr); + + CInputOutputStream * actualStream = static_cast(stream); + return (uLong)actualStream->write((const ui8 *)buf, size); +} + +ZPOS64_T ZCALLBACK CProxyIOApi::tellFileProxy(voidpf opaque, voidpf stream) +{ + return streamTell(opaque, stream); +} + +long ZCALLBACK CProxyIOApi::seekFileProxy(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +{ + return streamSeek(opaque, stream, offset, origin); +} + +int ZCALLBACK CProxyIOApi::closeFileProxy(voidpf opaque, voidpf stream) +{ + return streamProxyClose(opaque, stream); +} + +int ZCALLBACK CProxyIOApi::errorFileProxy(voidpf opaque, voidpf stream) +{ + return 0; +} + +CInputOutputStream * CProxyIOApi::openFile(const boost::filesystem::path & filename, int mode) { logGlobal->traceStream() << "CProxyIOApi: stream opened for " <traceStream() << "CProxyIOApi: stream closed"; - stream->seek(0);//stream is local singleton and even not owned, just seek + +} + +CProxyROIOApi::~CProxyROIOApi() +{ + +} + +zlib_filefunc64_def CProxyROIOApi::getApiStructure() +{ + zlib_filefunc64_def api; + api.opaque = this; + api.zopen64_file = &openFileProxy; + api.zread_file = &readFileProxy; + api.zwrite_file = &writeFileProxy; + api.ztell64_file = &tellFileProxy; + api.zseek64_file = &seekFileProxy; + api.zclose_file = &closeFileProxy; + api.zerror_file = &errorFileProxy; + + return api; +} + +CInputStream * CProxyROIOApi::openFile(const boost::filesystem::path& filename, int mode) +{ + logGlobal->traceStream() << "CProxyIOApi: stream opened for " <seek(0); + return data; +} + +voidpf ZCALLBACK CProxyROIOApi::openFileProxy(voidpf opaque, const void* filename, int mode) +{ + assert(opaque != nullptr); + + boost::filesystem::path path; + + if(filename != nullptr) + path = static_cast(filename); + + return ((CProxyROIOApi *)opaque)->openFile(path, mode); +} + +uLong ZCALLBACK CProxyROIOApi::readFileProxy(voidpf opaque, voidpf stream, void * buf, uLong size) +{ + return streamRead(opaque, stream, buf, size); +} + +uLong ZCALLBACK CProxyROIOApi::writeFileProxy(voidpf opaque, voidpf stream, const void* buf, uLong size) +{ + logGlobal->errorStream() << "Attempt to write to read-only stream"; + return 0; +} + +ZPOS64_T ZCALLBACK CProxyROIOApi::tellFileProxy(voidpf opaque, voidpf stream) +{ + return streamTell(opaque, stream); +} + +long ZCALLBACK CProxyROIOApi::seekFileProxy(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +{ + return streamSeek(opaque, stream, offset, origin); +} + +int ZCALLBACK CProxyROIOApi::closeFileProxy(voidpf opaque, voidpf stream) +{ + return streamProxyClose(opaque, stream); +} + +int ZCALLBACK CProxyROIOApi::errorFileProxy(voidpf opaque, voidpf stream) +{ + return 0; } diff --git a/lib/filesystem/MinizipExtensions.h b/lib/filesystem/MinizipExtensions.h index 7bea0ea9a..efd54a152 100644 --- a/lib/filesystem/MinizipExtensions.h +++ b/lib/filesystem/MinizipExtensions.h @@ -19,7 +19,7 @@ #include "../minizip/zip.h" #include "../minizip/ioapi.h" #endif - +class CInputStream; class CInputOutputStream; class CMemoryBuffer; @@ -28,22 +28,7 @@ class DLL_LINKAGE CIOApi public: virtual ~CIOApi(){}; - virtual zlib_filefunc64_def getApiStructure() const; - -protected: - virtual CInputOutputStream * openFile(const boost::filesystem::path & filename, int mode) const = 0; - - ///default implementation deletes stream object - virtual void closeFile(CInputOutputStream * stream) const; - -private: - static voidpf ZCALLBACK openFileProxy(voidpf opaque, const void * filename, int mode); - static uLong ZCALLBACK readFileProxy(voidpf opaque, voidpf stream, void * buf, uLong size); - static uLong ZCALLBACK writeFileProxy(voidpf opaque, voidpf stream, const void * buf, uLong size); - static ZPOS64_T ZCALLBACK tellFileProxy(voidpf opaque, voidpf stream); - static long ZCALLBACK seekFileProxy(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin); - static int ZCALLBACK closeFileProxy(voidpf opaque, voidpf stream); - static int ZCALLBACK errorFileProxy(voidpf opaque, voidpf stream); + virtual zlib_filefunc64_def getApiStructure() = 0; }; ///redirects back to minizip ioapi @@ -54,10 +39,7 @@ public: CDefaultIOApi(); ~CDefaultIOApi(); - zlib_filefunc64_def getApiStructure() const override; - -protected: - CInputOutputStream * openFile(const boost::filesystem::path & filename, int mode) const override; + zlib_filefunc64_def getApiStructure() override; }; ///redirects all file IO to single stream @@ -66,9 +48,41 @@ class DLL_LINKAGE CProxyIOApi: public CIOApi public: CProxyIOApi(CInputOutputStream * buffer); ~CProxyIOApi(); -protected: - CInputOutputStream * openFile(const boost::filesystem::path & filename, int mode) const override; - void closeFile(CInputOutputStream * stream) const override; + + zlib_filefunc64_def getApiStructure() override; private: + CInputOutputStream * openFile(const boost::filesystem::path & filename, int mode); + CInputOutputStream * data; + + static voidpf ZCALLBACK openFileProxy(voidpf opaque, const void * filename, int mode); + static uLong ZCALLBACK readFileProxy(voidpf opaque, voidpf stream, void * buf, uLong size); + static uLong ZCALLBACK writeFileProxy(voidpf opaque, voidpf stream, const void * buf, uLong size); + static ZPOS64_T ZCALLBACK tellFileProxy(voidpf opaque, voidpf stream); + static long ZCALLBACK seekFileProxy(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin); + static int ZCALLBACK closeFileProxy(voidpf opaque, voidpf stream); + static int ZCALLBACK errorFileProxy(voidpf opaque, voidpf stream); }; + +///redirects all file IO to single stream read-only +class DLL_LINKAGE CProxyROIOApi: public CIOApi +{ +public: + CProxyROIOApi(CInputStream * buffer); + ~CProxyROIOApi(); + + zlib_filefunc64_def getApiStructure() override; +private: + CInputStream * openFile(const boost::filesystem::path & filename, int mode); + + CInputStream * data; + + static voidpf ZCALLBACK openFileProxy(voidpf opaque, const void * filename, int mode); + static uLong ZCALLBACK readFileProxy(voidpf opaque, voidpf stream, void * buf, uLong size); + static uLong ZCALLBACK writeFileProxy(voidpf opaque, voidpf stream, const void * buf, uLong size); + static ZPOS64_T ZCALLBACK tellFileProxy(voidpf opaque, voidpf stream); + static long ZCALLBACK seekFileProxy(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin); + static int ZCALLBACK closeFileProxy(voidpf opaque, voidpf stream); + static int ZCALLBACK errorFileProxy(voidpf opaque, voidpf stream); +}; + diff --git a/lib/mapping/CMapService.cpp b/lib/mapping/CMapService.cpp index 80201429f..a71245d53 100644 --- a/lib/mapping/CMapService.cpp +++ b/lib/mapping/CMapService.cpp @@ -74,8 +74,7 @@ std::unique_ptr CMapService::getMapLoader(std::unique_ptr(new CMapLoaderJson(stream.get())); - throw std::runtime_error("Not implemented map format"); + return std::unique_ptr(new CMapLoaderJson(stream.get())); break; default: // Check which map format is used diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index 0f38abf34..4c8049944 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -221,18 +221,11 @@ void CMapPatcher::readPatchData() readTriggeredEvents(input); } -///CMapFormatZip -CMapFormatZip::CMapFormatZip(CInputOutputStream * stream): - buffer(stream), - ioApi(new CProxyIOApi(buffer)) -{ - -} - ///CMapLoaderJson -CMapLoaderJson::CMapLoaderJson(CInputOutputStream * stream): - CMapFormatZip(stream), +CMapLoaderJson::CMapLoaderJson(CInputStream * stream): + buffer(stream), + ioApi(new CProxyROIOApi(buffer)), loader("", "_", ioApi) { @@ -342,7 +335,7 @@ void CMapLoaderJson::readPlayerInfo(const JsonNode & input) for(int player = 0; player < PlayerColor::PLAYER_LIMIT_I; player++) { - PlayerInfo & info = map->players.at(player); + PlayerInfo & info = mapHeader->players.at(player); const JsonNode & playerSrc = src[GameConstants::PLAYER_COLOR_NAMES[player]]; @@ -412,15 +405,15 @@ void CMapLoaderJson::readTeams(const JsonNode& input) PlayerColor player = PlayerColor(vstd::find_pos(GameConstants::PLAYER_COLOR_NAMES, playerData.String())); if(player.isValidPlayer()) { - if(map->players[player.getNum()].canAnyonePlay()) + if(mapHeader->players[player.getNum()].canAnyonePlay()) { - map->players[player.getNum()].team = TeamID(team); + mapHeader->players[player.getNum()].team = TeamID(team); } } } } - for(PlayerInfo & player : map->players) + for(PlayerInfo & player : mapHeader->players) { if(player.canAnyonePlay() && player.team == TeamID::NO_TEAM) player.team = TeamID(mapHeader->howManyTeams++); @@ -654,7 +647,8 @@ void CMapLoaderJson::readObjects() ///CMapSaverJson CMapSaverJson::CMapSaverJson(CInputOutputStream * stream): - CMapFormatZip(stream), + buffer(stream), + ioApi(new CProxyIOApi(buffer)), saver(ioApi, "_") { diff --git a/lib/mapping/MapFormatJson.h b/lib/mapping/MapFormatJson.h index 7b92594fe..de3fabb45 100644 --- a/lib/mapping/MapFormatJson.h +++ b/lib/mapping/MapFormatJson.h @@ -90,16 +90,7 @@ private: const JsonNode input; }; -class DLL_LINKAGE CMapFormatZip : public CMapFormatJson -{ -public: - CMapFormatZip(CInputOutputStream * stream); -protected: - CInputOutputStream * buffer; - std::shared_ptr ioApi; -}; - -class DLL_LINKAGE CMapLoaderJson : public CMapFormatZip, public IMapLoader +class DLL_LINKAGE CMapLoaderJson : public CMapFormatJson, public IMapLoader { public: /** @@ -107,7 +98,7 @@ public: * * @param stream a stream containing the map data */ - CMapLoaderJson(CInputOutputStream * stream); + CMapLoaderJson(CInputStream * stream); /** * Loads the VCMI/Json map file. @@ -184,10 +175,13 @@ private: const JsonNode readJson(const std::string & archiveFilename); + CInputStream * buffer; + std::shared_ptr ioApi; + CZipLoader loader;///< object to handle zip archive operations }; -class DLL_LINKAGE CMapSaverJson : public CMapFormatZip, public IMapSaver +class DLL_LINKAGE CMapSaverJson : public CMapFormatJson, public IMapSaver { public: /** @@ -255,5 +249,7 @@ private: */ void writeObjects(); + CInputOutputStream * buffer; + std::shared_ptr ioApi; CZipSaver saver;///< object to handle zip archive operations };