bool ZipFile::unpack() { close(); // delete the buffer const vfspos sz = size(); // will reopen the file if(sz < 0) return false; _buf = new char[size_t(sz) + 1]; if(!_buf) return false; if(!mz_zip_reader_extract_to_mem(MZ, _fileIdx, _buf, (size_t)sz, 0)) { delete [] _buf; _buf = NULL; return false; // this should not happen } _bufSize = sz; // In case of text data, make sure the buffer is always terminated with '\0'. // Won't hurt for binary data, so just do it in all cases. _buf[sz] = 0; if(_mode.find("b") == std::string::npos) // text mode? { _bufSize = (vfspos)strnNLcpy(_buf, _buf); } return true; }
unsigned int VFSFileZip::read(void *dst, unsigned int bytes) { VFS_GUARD_OPT(this); char *mem = (char*)getBuf(); char *startptr = mem + _pos; char *endptr = mem + size(); bytes = std::min((unsigned int)(endptr - startptr), bytes); // limit in case reading over buffer size if(_mode.find('b') == std::string::npos) strnNLcpy((char*)dst, (const char*)startptr, bytes); // non-binary == text mode else memcpy(dst, startptr, bytes); // binary copy _pos += bytes; return bytes; }
const void *VFSFileZip::getBuf(allocator_func alloc /* = NULL */, delete_func del /* = NULL */) { assert(!alloc == !del); // either both or none may be defined. Checked extra early to prevent possible errors later. VFS_GUARD_OPT(this); // _fixedStr gets deleted on mode change, so doing this check here is fine if(_fixedStr) return _fixedStr; if(!_buf) { size_t sz = (size_t)size(); _buf = allocHelperExtra(alloc, sz, 4); if(!_buf) return NULL; _delfunc = del; if(!zip_reader_reopen_vfsfile(_zip, 0)) return false; // can happen if the underlying zip file was deleted if(!mz_zip_reader_extract_to_mem(_zip, _zipstat.m_file_index, _buf, sz, 0)) return false; // this should not happen if(_mode.find("b") == std::string::npos) // text mode? { _fixedStr = allocHelperExtra(alloc, sz, 4); strnNLcpy(_fixedStr, (const char*)_buf); // FIXME: is this really correct? VFSFile::dropBuf(true); return _fixedStr; } } return _buf; }