diff --git a/code/Common/ZipArchiveIOSystem.cpp b/code/Common/ZipArchiveIOSystem.cpp index 8d00da912..6ad10e54a 100644 --- a/code/Common/ZipArchiveIOSystem.cpp +++ b/code/Common/ZipArchiveIOSystem.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,8 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Zip File I/O implementation for #Importer */ -#include #include +#include #include @@ -53,70 +52,69 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #ifdef ASSIMP_USE_HUNTER -# include +# include #else -# include +# include #endif namespace Assimp { - // ---------------------------------------------------------------- - // Wraps an existing Assimp::IOSystem for unzip - class IOSystem2Unzip { - public: - static voidpf open(voidpf opaque, const char* filename, int mode); - static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size); - static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size); - static long tell(voidpf opaque, voidpf stream); - static long seek(voidpf opaque, voidpf stream, uLong offset, int origin); - static int close(voidpf opaque, voidpf stream); - static int testerror(voidpf opaque, voidpf stream); - static zlib_filefunc_def get(IOSystem* pIOHandler); - }; - voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) { - IOSystem* io_system = reinterpret_cast(opaque); +// ---------------------------------------------------------------- +// Wraps an existing Assimp::IOSystem for unzip +class IOSystem2Unzip { +public: + static voidpf open(voidpf opaque, const char *filename, int mode); + static uLong read(voidpf opaque, voidpf stream, void *buf, uLong size); + static uLong write(voidpf opaque, voidpf stream, const void *buf, uLong size); + static long tell(voidpf opaque, voidpf stream); + static long seek(voidpf opaque, voidpf stream, uLong offset, int origin); + static int close(voidpf opaque, voidpf stream); + static int testerror(voidpf opaque, voidpf stream); + static zlib_filefunc_def get(IOSystem *pIOHandler); +}; - const char* mode_fopen = nullptr; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) { - mode_fopen = "rb"; - } - else { - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) { - mode_fopen = "r+b"; - } - else { - if (mode & ZLIB_FILEFUNC_MODE_CREATE) { - mode_fopen = "wb"; - } +voidpf IOSystem2Unzip::open(voidpf opaque, const char *filename, int mode) { + IOSystem *io_system = reinterpret_cast(opaque); + + const char *mode_fopen = nullptr; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) { + mode_fopen = "rb"; + } else { + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) { + mode_fopen = "r+b"; + } else { + if (mode & ZLIB_FILEFUNC_MODE_CREATE) { + mode_fopen = "wb"; } } - - return (voidpf)io_system->Open(filename, mode_fopen); } - uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) { - IOStream* io_stream = (IOStream*)stream; + return (voidpf)io_system->Open(filename, mode_fopen); +} - return static_cast(io_stream->Read(buf, 1, size)); - } +uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void *buf, uLong size) { + IOStream *io_stream = (IOStream *)stream; - uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) { - IOStream* io_stream = (IOStream*)stream; + return static_cast(io_stream->Read(buf, 1, size)); +} - return static_cast(io_stream->Write(buf, 1, size)); - } +uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void *buf, uLong size) { + IOStream *io_stream = (IOStream *)stream; - long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) { - IOStream* io_stream = (IOStream*)stream; + return static_cast(io_stream->Write(buf, 1, size)); +} - return static_cast(io_stream->Tell()); - } +long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) { + IOStream *io_stream = (IOStream *)stream; - long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) { - IOStream* io_stream = (IOStream*)stream; + return static_cast(io_stream->Tell()); +} - aiOrigin assimp_origin; - switch (origin) { +long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) { + IOStream *io_stream = (IOStream *)stream; + + aiOrigin assimp_origin; + switch (origin) { default: case ZLIB_FILEFUNC_SEEK_CUR: assimp_origin = aiOrigin_CUR; @@ -127,157 +125,153 @@ namespace Assimp { case ZLIB_FILEFUNC_SEEK_SET: assimp_origin = aiOrigin_SET; break; - } - - return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1); } - int IOSystem2Unzip::close(voidpf opaque, voidpf stream) { - IOSystem* io_system = (IOSystem*)opaque; - IOStream* io_stream = (IOStream*)stream; + return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1); +} - io_system->Close(io_stream); +int IOSystem2Unzip::close(voidpf opaque, voidpf stream) { + IOSystem *io_system = (IOSystem *)opaque; + IOStream *io_stream = (IOStream *)stream; - return 0; - } + io_system->Close(io_stream); - int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) { - return 0; - } + return 0; +} - zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) { - zlib_filefunc_def mapping; +int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) { + return 0; +} + +zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) { + zlib_filefunc_def mapping; #ifdef ASSIMP_USE_HUNTER - mapping.zopen_file = (open_file_func)open; - mapping.zread_file = (read_file_func)read; - mapping.zwrite_file = (write_file_func)write; - mapping.ztell_file = (tell_file_func)tell; - mapping.zseek_file = (seek_file_func)seek; - mapping.zclose_file = (close_file_func)close; - mapping.zerror_file = (error_file_func)testerror; + mapping.zopen_file = (open_file_func)open; + mapping.zread_file = (read_file_func)read; + mapping.zwrite_file = (write_file_func)write; + mapping.ztell_file = (tell_file_func)tell; + mapping.zseek_file = (seek_file_func)seek; + mapping.zclose_file = (close_file_func)close; + mapping.zerror_file = (error_file_func)testerror; #else - mapping.zopen_file = open; - mapping.zread_file = read; - mapping.zwrite_file = write; - mapping.ztell_file = tell; - mapping.zseek_file = seek; - mapping.zclose_file = close; - mapping.zerror_file = testerror; + mapping.zopen_file = open; + mapping.zread_file = read; + mapping.zwrite_file = write; + mapping.ztell_file = tell; + mapping.zseek_file = seek; + mapping.zclose_file = close; + mapping.zerror_file = testerror; #endif - mapping.opaque = reinterpret_cast(pIOHandler); + mapping.opaque = reinterpret_cast(pIOHandler); - return mapping; + return mapping; +} + +// ---------------------------------------------------------------- +// A read-only file inside a ZIP + +class ZipFile : public IOStream { + friend class ZipFileInfo; + explicit ZipFile(size_t size); + +public: + virtual ~ZipFile(); + + // IOStream interface + size_t Read(void *pvBuffer, size_t pSize, size_t pCount) override; + size_t Write(const void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override { return 0; } + size_t FileSize() const override; + aiReturn Seek(size_t pOffset, aiOrigin pOrigin) override; + size_t Tell() const override; + void Flush() override {} + +private: + size_t m_Size = 0; + size_t m_SeekPtr = 0; + std::unique_ptr m_Buffer; +}; + +// ---------------------------------------------------------------- +// Info about a read-only file inside a ZIP +class ZipFileInfo { +public: + explicit ZipFileInfo(unzFile zip_handle, size_t size); + + // Allocate and Extract data from the ZIP + ZipFile *Extract(unzFile zip_handle) const; + +private: + size_t m_Size = 0; + unz_file_pos_s m_ZipFilePos; +}; + +ZipFileInfo::ZipFileInfo(unzFile zip_handle, size_t size) : + m_Size(size) { + ai_assert(m_Size != 0); + // Workaround for MSVC 2013 - C2797 + m_ZipFilePos.num_of_file = 0; + m_ZipFilePos.pos_in_zip_directory = 0; + unzGetFilePos(zip_handle, &(m_ZipFilePos)); +} + +ZipFile *ZipFileInfo::Extract(unzFile zip_handle) const { + // Find in the ZIP. This cannot fail + unz_file_pos_s *filepos = const_cast(&(m_ZipFilePos)); + if (unzGoToFilePos(zip_handle, filepos) != UNZ_OK) + return nullptr; + + if (unzOpenCurrentFile(zip_handle) != UNZ_OK) + return nullptr; + + ZipFile *zip_file = new ZipFile(m_Size); + + if (unzReadCurrentFile(zip_handle, zip_file->m_Buffer.get(), static_cast(m_Size)) != static_cast(m_Size)) { + // Failed, release the memory + delete zip_file; + zip_file = nullptr; } - // ---------------------------------------------------------------- - // A read-only file inside a ZIP + ai_assert(unzCloseCurrentFile(zip_handle) == UNZ_OK); + return zip_file; +} - class ZipFile : public IOStream { - friend class ZipFileInfo; - explicit ZipFile(size_t size); - public: - virtual ~ZipFile(); +ZipFile::ZipFile(size_t size) : + m_Size(size) { + ai_assert(m_Size != 0); + m_Buffer = std::unique_ptr(new uint8_t[m_Size]); +} - // IOStream interface - size_t Read(void* pvBuffer, size_t pSize, size_t pCount) override; - size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override { return 0; } - size_t FileSize() const override; - aiReturn Seek(size_t pOffset, aiOrigin pOrigin) override; - size_t Tell() const override; - void Flush() override {} +ZipFile::~ZipFile() { +} - private: - size_t m_Size = 0; - size_t m_SeekPtr = 0; - std::unique_ptr m_Buffer; - }; +size_t ZipFile::Read(void *pvBuffer, size_t pSize, size_t pCount) { + // Should be impossible + ai_assert(m_Buffer != nullptr); + ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); - - // ---------------------------------------------------------------- - // Info about a read-only file inside a ZIP - class ZipFileInfo - { - public: - explicit ZipFileInfo(unzFile zip_handle, size_t size); - - // Allocate and Extract data from the ZIP - ZipFile * Extract(unzFile zip_handle) const; - - private: - size_t m_Size = 0; - unz_file_pos_s m_ZipFilePos; - }; - - ZipFileInfo::ZipFileInfo(unzFile zip_handle, size_t size) - : m_Size(size) { - ai_assert(m_Size != 0); - // Workaround for MSVC 2013 - C2797 - m_ZipFilePos.num_of_file = 0; - m_ZipFilePos.pos_in_zip_directory = 0; - unzGetFilePos(zip_handle, &(m_ZipFilePos)); + // Clip down to file size + size_t byteSize = pSize * pCount; + if ((byteSize + m_SeekPtr) > m_Size) { + pCount = (m_Size - m_SeekPtr) / pSize; + byteSize = pSize * pCount; + if (byteSize == 0) + return 0; } - ZipFile * ZipFileInfo::Extract(unzFile zip_handle) const { - // Find in the ZIP. This cannot fail - unz_file_pos_s *filepos = const_cast(&(m_ZipFilePos)); - if (unzGoToFilePos(zip_handle, filepos) != UNZ_OK) - return nullptr; + std::memcpy(pvBuffer, m_Buffer.get() + m_SeekPtr, byteSize); - if (unzOpenCurrentFile(zip_handle) != UNZ_OK) - return nullptr; + m_SeekPtr += byteSize; - ZipFile *zip_file = new ZipFile(m_Size); + return pCount; +} - if (unzReadCurrentFile(zip_handle, zip_file->m_Buffer.get(), static_cast(m_Size)) != static_cast(m_Size)) - { - // Failed, release the memory - delete zip_file; - zip_file = nullptr; - } +size_t ZipFile::FileSize() const { + return m_Size; +} - ai_assert(unzCloseCurrentFile(zip_handle) == UNZ_OK); - return zip_file; - } - - ZipFile::ZipFile(size_t size) - : m_Size(size) { - ai_assert(m_Size != 0); - m_Buffer = std::unique_ptr(new uint8_t[m_Size]); - } - - ZipFile::~ZipFile() { - } - - size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) { - // Should be impossible - ai_assert(m_Buffer != nullptr); - ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); - - // Clip down to file size - size_t byteSize = pSize * pCount; - if ((byteSize + m_SeekPtr) > m_Size) - { - pCount = (m_Size - m_SeekPtr) / pSize; - byteSize = pSize * pCount; - if (byteSize == 0) - return 0; - } - - std::memcpy(pvBuffer, m_Buffer.get() + m_SeekPtr, byteSize); - - m_SeekPtr += byteSize; - - return pCount; - } - - size_t ZipFile::FileSize() const { - return m_Size; - } - - aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) { - switch (pOrigin) - { +aiReturn ZipFile::Seek(size_t pOffset, aiOrigin pOrigin) { + switch (pOrigin) { case aiOrigin_SET: { if (pOffset > m_Size) return aiReturn_FAILURE; m_SeekPtr = pOffset; @@ -296,242 +290,237 @@ namespace Assimp { return aiReturn_SUCCESS; } default:; - } - - return aiReturn_FAILURE; - } - - size_t ZipFile::Tell() const { - return m_SeekPtr; - } - - // ---------------------------------------------------------------- - // pImpl of the Zip Archive IO - class ZipArchiveIOSystem::Implement { - public: - static const unsigned int FileNameSize = 256; - - Implement(IOSystem* pIOHandler, const char* pFilename, const char* pMode); - ~Implement(); - - bool isOpen() const; - void getFileList(std::vector& rFileList); - void getFileListExtension(std::vector& rFileList, const std::string& extension); - bool Exists(std::string& filename); - IOStream* OpenFile(std::string& filename); - - static void SimplifyFilename(std::string& filename); - - private: - void MapArchive(); - - private: - typedef std::map ZipFileInfoMap; - - unzFile m_ZipFileHandle = nullptr; - ZipFileInfoMap m_ArchiveMap; - }; - - ZipArchiveIOSystem::Implement::Implement(IOSystem* pIOHandler, const char* pFilename, const char* pMode) { - ai_assert(strcmp(pMode, "r") == 0); - ai_assert(pFilename != nullptr); - if (pFilename[0] == 0) - return; - - zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler); - m_ZipFileHandle = unzOpen2(pFilename, &mapping); - } - - ZipArchiveIOSystem::Implement::~Implement() { - if (m_ZipFileHandle != nullptr) { - unzClose(m_ZipFileHandle); - m_ZipFileHandle = nullptr; - } - } - - void ZipArchiveIOSystem::Implement::MapArchive() { - if (m_ZipFileHandle == nullptr) - return; - - if (!m_ArchiveMap.empty()) - return; - - // At first ensure file is already open - if (unzGoToFirstFile(m_ZipFileHandle) != UNZ_OK) - return; - - // Loop over all files - do { - char filename[FileNameSize]; - unz_file_info fileInfo; - - if (unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, nullptr, 0, nullptr, 0) == UNZ_OK) { - if (fileInfo.uncompressed_size != 0) { - std::string filename_string(filename, fileInfo.size_filename); - SimplifyFilename(filename_string); - m_ArchiveMap.emplace(filename_string, ZipFileInfo(m_ZipFileHandle, fileInfo.uncompressed_size)); - } - } - } while (unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE); - } - - bool ZipArchiveIOSystem::Implement::isOpen() const { - return (m_ZipFileHandle != nullptr); - } - - void ZipArchiveIOSystem::Implement::getFileList(std::vector& rFileList) { - MapArchive(); - rFileList.clear(); - - for (const auto &file : m_ArchiveMap) { - rFileList.push_back(file.first); - } - } - - void ZipArchiveIOSystem::Implement::getFileListExtension(std::vector& rFileList, const std::string& extension) { - MapArchive(); - rFileList.clear(); - - for (const auto &file : m_ArchiveMap) { - if (extension == BaseImporter::GetExtension(file.first)) - rFileList.push_back(file.first); - } - } - - bool ZipArchiveIOSystem::Implement::Exists(std::string& filename) { - MapArchive(); - - ZipFileInfoMap::const_iterator it = m_ArchiveMap.find(filename); - return (it != m_ArchiveMap.end()); - } - - IOStream * ZipArchiveIOSystem::Implement::OpenFile(std::string& filename) { - MapArchive(); - - SimplifyFilename(filename); - - // Find in the map - ZipFileInfoMap::const_iterator zip_it = m_ArchiveMap.find(filename); - if (zip_it == m_ArchiveMap.cend()) - return nullptr; - - const ZipFileInfo &zip_file = (*zip_it).second; - return zip_file.Extract(m_ZipFileHandle); - } - - inline void ReplaceAll(std::string& data, const std::string& before, const std::string& after) { - size_t pos = data.find(before); - while (pos != std::string::npos) - { - data.replace(pos, before.size(), after); - pos = data.find(before, pos + after.size()); - } - } - - inline void ReplaceAllChar(std::string& data, const char before, const char after) { - size_t pos = data.find(before); - while (pos != std::string::npos) - { - data[pos] = after; - pos = data.find(before, pos + 1); - } - } - - void ZipArchiveIOSystem::Implement::SimplifyFilename(std::string& filename) - { - ReplaceAllChar(filename, '\\', '/'); - - // Remove all . and / from the beginning of the path - size_t pos = filename.find_first_not_of("./"); - if (pos != 0) - filename.erase(0, pos); - - // Simplify "my/folder/../file.png" constructions, if any - static const std::string relative("/../"); - const size_t relsize = relative.size() - 1; - pos = filename.find(relative); - while (pos != std::string::npos) - { - // Previous slash - size_t prevpos = filename.rfind('/', pos - 1); - if (prevpos == pos) - filename.erase(0, pos + relative.size()); - else - filename.erase(prevpos, pos + relsize - prevpos); - - pos = filename.find(relative); - } - } - - ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem* pIOHandler, const char* pFilename, const char* pMode) - : pImpl(new Implement(pIOHandler, pFilename, pMode)) { - } - - // ---------------------------------------------------------------- - // The ZipArchiveIO - ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem* pIOHandler, const std::string& rFilename, const char* pMode) - : pImpl(new Implement(pIOHandler, rFilename.c_str(), pMode)) - { - } - - ZipArchiveIOSystem::~ZipArchiveIOSystem() { - delete pImpl; - } - - bool ZipArchiveIOSystem::Exists(const char* pFilename) const { - ai_assert(pFilename != nullptr); - - if (pFilename == nullptr) { - return false; - } - - std::string filename(pFilename); - return pImpl->Exists(filename); - } - - // This is always '/' in a ZIP - char ZipArchiveIOSystem::getOsSeparator() const { - return '/'; - } - - // Only supports Reading - IOStream * ZipArchiveIOSystem::Open(const char* pFilename, const char* pMode) { - ai_assert(pFilename != nullptr); - - for (size_t i = 0; pMode[i] != 0; ++i) - { - ai_assert(pMode[i] != 'w'); - if (pMode[i] == 'w') - return nullptr; - } - - std::string filename(pFilename); - return pImpl->OpenFile(filename); - } - - void ZipArchiveIOSystem::Close(IOStream* pFile) { - delete pFile; - } - - bool ZipArchiveIOSystem::isOpen() const { - return (pImpl->isOpen()); - } - - void ZipArchiveIOSystem::getFileList(std::vector& rFileList) const { - return pImpl->getFileList(rFileList); - } - - void ZipArchiveIOSystem::getFileListExtension(std::vector& rFileList, const std::string& extension) const { - return pImpl->getFileListExtension(rFileList, extension); - } - - bool ZipArchiveIOSystem::isZipArchive(IOSystem* pIOHandler, const char* pFilename) { - Implement tmp(pIOHandler, pFilename, "r"); - return tmp.isOpen(); - } - - bool ZipArchiveIOSystem::isZipArchive(IOSystem* pIOHandler, const std::string& rFilename) { - return isZipArchive(pIOHandler, rFilename.c_str()); } + return aiReturn_FAILURE; } + +size_t ZipFile::Tell() const { + return m_SeekPtr; +} + +// ---------------------------------------------------------------- +// pImpl of the Zip Archive IO +class ZipArchiveIOSystem::Implement { +public: + static const unsigned int FileNameSize = 256; + + Implement(IOSystem *pIOHandler, const char *pFilename, const char *pMode); + ~Implement(); + + bool isOpen() const; + void getFileList(std::vector &rFileList); + void getFileListExtension(std::vector &rFileList, const std::string &extension); + bool Exists(std::string &filename); + IOStream *OpenFile(std::string &filename); + + static void SimplifyFilename(std::string &filename); + +private: + void MapArchive(); + +private: + typedef std::map ZipFileInfoMap; + + unzFile m_ZipFileHandle = nullptr; + ZipFileInfoMap m_ArchiveMap; +}; + +ZipArchiveIOSystem::Implement::Implement(IOSystem *pIOHandler, const char *pFilename, const char *pMode) { + ai_assert(strcmp(pMode, "r") == 0); + ai_assert(pFilename != nullptr); + if (pFilename[0] == 0 || nullptr == pMode) { + return; + } + + zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler); + m_ZipFileHandle = unzOpen2(pFilename, &mapping); +} + +ZipArchiveIOSystem::Implement::~Implement() { + if (m_ZipFileHandle != nullptr) { + unzClose(m_ZipFileHandle); + m_ZipFileHandle = nullptr; + } +} + +void ZipArchiveIOSystem::Implement::MapArchive() { + if (m_ZipFileHandle == nullptr) + return; + + if (!m_ArchiveMap.empty()) + return; + + // At first ensure file is already open + if (unzGoToFirstFile(m_ZipFileHandle) != UNZ_OK) + return; + + // Loop over all files + do { + char filename[FileNameSize]; + unz_file_info fileInfo; + + if (unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, nullptr, 0, nullptr, 0) == UNZ_OK) { + if (fileInfo.uncompressed_size != 0) { + std::string filename_string(filename, fileInfo.size_filename); + SimplifyFilename(filename_string); + m_ArchiveMap.emplace(filename_string, ZipFileInfo(m_ZipFileHandle, fileInfo.uncompressed_size)); + } + } + } while (unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE); +} + +bool ZipArchiveIOSystem::Implement::isOpen() const { + return (m_ZipFileHandle != nullptr); +} + +void ZipArchiveIOSystem::Implement::getFileList(std::vector &rFileList) { + MapArchive(); + rFileList.clear(); + + for (const auto &file : m_ArchiveMap) { + rFileList.push_back(file.first); + } +} + +void ZipArchiveIOSystem::Implement::getFileListExtension(std::vector &rFileList, const std::string &extension) { + MapArchive(); + rFileList.clear(); + + for (const auto &file : m_ArchiveMap) { + if (extension == BaseImporter::GetExtension(file.first)) + rFileList.push_back(file.first); + } +} + +bool ZipArchiveIOSystem::Implement::Exists(std::string &filename) { + MapArchive(); + + ZipFileInfoMap::const_iterator it = m_ArchiveMap.find(filename); + return (it != m_ArchiveMap.end()); +} + +IOStream *ZipArchiveIOSystem::Implement::OpenFile(std::string &filename) { + MapArchive(); + + SimplifyFilename(filename); + + // Find in the map + ZipFileInfoMap::const_iterator zip_it = m_ArchiveMap.find(filename); + if (zip_it == m_ArchiveMap.cend()) + return nullptr; + + const ZipFileInfo &zip_file = (*zip_it).second; + return zip_file.Extract(m_ZipFileHandle); +} + +inline void ReplaceAll(std::string &data, const std::string &before, const std::string &after) { + size_t pos = data.find(before); + while (pos != std::string::npos) { + data.replace(pos, before.size(), after); + pos = data.find(before, pos + after.size()); + } +} + +inline void ReplaceAllChar(std::string &data, const char before, const char after) { + size_t pos = data.find(before); + while (pos != std::string::npos) { + data[pos] = after; + pos = data.find(before, pos + 1); + } +} + +void ZipArchiveIOSystem::Implement::SimplifyFilename(std::string &filename) { + ReplaceAllChar(filename, '\\', '/'); + + // Remove all . and / from the beginning of the path + size_t pos = filename.find_first_not_of("./"); + if (pos != 0) + filename.erase(0, pos); + + // Simplify "my/folder/../file.png" constructions, if any + static const std::string relative("/../"); + const size_t relsize = relative.size() - 1; + pos = filename.find(relative); + while (pos != std::string::npos) { + // Previous slash + size_t prevpos = filename.rfind('/', pos - 1); + if (prevpos == pos) + filename.erase(0, pos + relative.size()); + else + filename.erase(prevpos, pos + relsize - prevpos); + + pos = filename.find(relative); + } +} + +ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem *pIOHandler, const char *pFilename, const char *pMode) : + pImpl(new Implement(pIOHandler, pFilename, pMode)) { +} + +// ---------------------------------------------------------------- +// The ZipArchiveIO +ZipArchiveIOSystem::ZipArchiveIOSystem(IOSystem *pIOHandler, const std::string &rFilename, const char *pMode) : + pImpl(new Implement(pIOHandler, rFilename.c_str(), pMode)) { +} + +ZipArchiveIOSystem::~ZipArchiveIOSystem() { + delete pImpl; +} + +bool ZipArchiveIOSystem::Exists(const char *pFilename) const { + ai_assert(pFilename != nullptr); + + if (pFilename == nullptr) { + return false; + } + + std::string filename(pFilename); + return pImpl->Exists(filename); +} + +// This is always '/' in a ZIP +char ZipArchiveIOSystem::getOsSeparator() const { + return '/'; +} + +// Only supports Reading +IOStream *ZipArchiveIOSystem::Open(const char *pFilename, const char *pMode) { + ai_assert(pFilename != nullptr); + + for (size_t i = 0; pMode[i] != 0; ++i) { + ai_assert(pMode[i] != 'w'); + if (pMode[i] == 'w') + return nullptr; + } + + std::string filename(pFilename); + return pImpl->OpenFile(filename); +} + +void ZipArchiveIOSystem::Close(IOStream *pFile) { + delete pFile; +} + +bool ZipArchiveIOSystem::isOpen() const { + return (pImpl->isOpen()); +} + +void ZipArchiveIOSystem::getFileList(std::vector &rFileList) const { + return pImpl->getFileList(rFileList); +} + +void ZipArchiveIOSystem::getFileListExtension(std::vector &rFileList, const std::string &extension) const { + return pImpl->getFileListExtension(rFileList, extension); +} + +bool ZipArchiveIOSystem::isZipArchive(IOSystem *pIOHandler, const char *pFilename) { + Implement tmp(pIOHandler, pFilename, "r"); + return tmp.isOpen(); +} + +bool ZipArchiveIOSystem::isZipArchive(IOSystem *pIOHandler, const std::string &rFilename) { + return isZipArchive(pIOHandler, rFilename.c_str()); +} + +} // namespace Assimp diff --git a/include/assimp/defs.h b/include/assimp/defs.h index 46ecef280..06ea78950 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -158,7 +158,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #ifdef _MSC_VER -# pragma warning(disable : 4521 4714 4127) +# pragma warning(disable : 4521 4512 4714 4127) # ifdef ASSIMP_BUILD_DLL_EXPORT # pragma warning (disable : 4251) # endif