Преглед изворни кода

use 32-bit minizip file funcs on old Android

Andrey Filipenkov пре 1 година
родитељ
комит
5a58edde22

+ 7 - 2
lib/filesystem/CZipLoader.cpp

@@ -181,12 +181,17 @@ std::vector<std::string> ZipArchive::listFiles()
 ZipArchive::ZipArchive(const boost::filesystem::path & from)
 {
 	CDefaultIOApi zipAPI;
-	auto zipStructure = zipAPI.getApiStructure();
 
+#if MINIZIP_NEEDS_32BIT_FUNCS
+	auto zipStructure = zipAPI.getApiStructure32();
+	archive = unzOpen2(from.c_str(), &zipStructure);
+#else
+	auto zipStructure = zipAPI.getApiStructure();
 	archive = unzOpen2_64(from.c_str(), &zipStructure);
+#endif
 
 	if (archive == nullptr)
-		throw std::runtime_error("Failed to open file" + from.string() + "'%s'! Unable to list files!");
+		throw std::runtime_error("Failed to open file '" + from.string() + "' - unable to list files!");
 }
 
 ZipArchive::~ZipArchive()

+ 1 - 1
lib/filesystem/CZipLoader.h

@@ -50,7 +50,7 @@ class DLL_LINKAGE CZipLoader : public ISimpleResourceLoader
 
 	std::unordered_map<ResourcePath, unz64_file_pos> listFiles(const std::string & mountPoint, const boost::filesystem::path &archive);
 public:
-	CZipLoader(const std::string & mountPoint, const boost::filesystem::path & archive, std::shared_ptr<CIOApi> api = std::shared_ptr<CIOApi>(new CDefaultIOApi()));
+	CZipLoader(const std::string & mountPoint, const boost::filesystem::path & archive, std::shared_ptr<CIOApi> api = std::make_shared<CDefaultIOApi>());
 
 	/// Interface implementation
 	/// @see ISimpleResourceLoader

+ 19 - 4
lib/filesystem/MinizipExtensions.cpp

@@ -12,6 +12,8 @@
 
 #include "CMemoryBuffer.h"
 
+#include <mutex>
+
 VCMI_LIB_NAMESPACE_BEGIN
 
 template<class Stream>
@@ -130,15 +132,28 @@ static voidpf ZCALLBACK MinizipOpenFunc(voidpf opaque, const void* filename, int
 zlib_filefunc64_def CDefaultIOApi::getApiStructure()
 {
 	static zlib_filefunc64_def MinizipFilefunc;
-	static bool initialized = false;
-	if (!initialized)
+	static std::once_flag flag;
+	std::call_once(flag, []
 	{
 		fill_fopen64_filefunc(&MinizipFilefunc);
 		MinizipFilefunc.zopen64_file = &MinizipOpenFunc;
-		initialized = true;
-	}
+	});
+	return MinizipFilefunc;
+}
+
+#if MINIZIP_NEEDS_32BIT_FUNCS
+zlib_filefunc_def CDefaultIOApi::getApiStructure32()
+{
+	static zlib_filefunc_def MinizipFilefunc;
+	static std::once_flag flag;
+	std::call_once(flag, []
+	{
+		fill_fopen_filefunc(&MinizipFilefunc);
+		MinizipFilefunc.zopen_file = reinterpret_cast<void*(*)(void*, const char*, int)>(&MinizipOpenFunc);
+	});
 	return MinizipFilefunc;
 }
+#endif
 
 ///CProxyIOApi
 CProxyIOApi::CProxyIOApi(CInputOutputStream * buffer):

+ 8 - 0
lib/filesystem/MinizipExtensions.h

@@ -19,6 +19,11 @@
 #include "../minizip/ioapi.h"
 #endif
 
+// system zlib on old Androids isn't capable of using _64 functions: https://github.com/madler/zlib/pull/436
+#if defined(__ANDROID_API__) && (__ANDROID_API__ < 24)
+#define MINIZIP_NEEDS_32BIT_FUNCS 1
+#endif
+
 VCMI_LIB_NAMESPACE_BEGIN
 
 class CInputStream;
@@ -39,6 +44,9 @@ class DLL_LINKAGE CDefaultIOApi: public CIOApi
 {
 public:
 	zlib_filefunc64_def getApiStructure() override;
+#if MINIZIP_NEEDS_32BIT_FUNCS
+	zlib_filefunc_def getApiStructure32();
+#endif
 };
 
 ///redirects all file IO to single stream