----------------------------------------------------------------
| 249 | |
| 250 | // ---------------------------------------------------------------- |
| 251 | ZipFile *ZipFileInfo::Extract(std::string &filename, unzFile zip_handle) const { |
| 252 | // Find in the ZIP. This cannot fail |
| 253 | unz_file_pos_s *filepos = const_cast<unz_file_pos_s *>(&(m_ZipFilePos)); |
| 254 | if (unzGoToFilePos(zip_handle, filepos) != UNZ_OK) |
| 255 | return nullptr; |
| 256 | |
| 257 | if (unzOpenCurrentFile(zip_handle) != UNZ_OK) |
| 258 | return nullptr; |
| 259 | |
| 260 | ZipFile *zip_file = new ZipFile(filename, m_Size); |
| 261 | |
| 262 | // Unzip has a limit of UINT16_MAX bytes buffer |
| 263 | uint16_t unzipBufferSize = zip_file->m_Size <= UINT16_MAX ? static_cast<uint16_t>(zip_file->m_Size) : UINT16_MAX; |
| 264 | std::unique_ptr<uint8_t[]> unzipBuffer = std::unique_ptr<uint8_t[]>(new uint8_t[unzipBufferSize]); |
| 265 | size_t readCount = 0; |
| 266 | while (readCount < zip_file->m_Size) |
| 267 | { |
| 268 | size_t bufferSize = zip_file->m_Size - readCount; |
| 269 | if (bufferSize > UINT16_MAX) { |
| 270 | bufferSize = UINT16_MAX; |
| 271 | } |
| 272 | |
| 273 | int ret = unzReadCurrentFile(zip_handle, unzipBuffer.get(), static_cast<unsigned int>(bufferSize)); |
| 274 | if (ret != static_cast<int>(bufferSize)) |
| 275 | { |
| 276 | // Failed, release the memory |
| 277 | delete zip_file; |
| 278 | zip_file = nullptr; |
| 279 | break; |
| 280 | } |
| 281 | |
| 282 | std::memcpy(zip_file->m_Buffer.get() + readCount, unzipBuffer.get(), ret); |
| 283 | readCount += ret; |
| 284 | } |
| 285 | |
| 286 | ai_assert(unzCloseCurrentFile(zip_handle) == UNZ_OK); |
| 287 | return zip_file; |
| 288 | } |
| 289 | |
| 290 | // ---------------------------------------------------------------- |
| 291 | ZipFile::ZipFile(std::string &filename, size_t size) : |
no test coverage detected