24 #include "third_party/unzip/unzip.h"
25 #include "third_party/zlib/src/contrib/minizip/zip.h"
32 struct MemoryZipStream::ZipStreamInfo :
public Allocatable {
34 zlib_filefunc_def def;
46 static voidpf ZCALLBACK
47 OpenZipStream(voidpf opaque,
const char* filename,
int mode) {
48 if (MemoryZipStream::ZipStreamInfo* info =
49 reinterpret_cast<MemoryZipStream::ZipStreamInfo*>(opaque))
55 static uLong ZCALLBACK
56 ReadFromZipStream(voidpf opaque, voidpf stream,
void* buf, uLong size) {
58 if (MemoryZipStream::ZipStreamInfo* info =
59 reinterpret_cast<MemoryZipStream::ZipStreamInfo*>(opaque)) {
60 if (info->position + size > info->buffer.size()) {
61 const int64 available = info->buffer.size() - info->position;
62 size = available < 0 ? 0 : static_cast<uLong>(available);
65 memcpy(buf, &info->buffer[info->position], size);
66 info->position += size;
75 static uLong ZCALLBACK WriteToZipStream(
76 voidpf opaque, voidpf stream,
const void* buf, uLong size) {
77 uLong bytes_written = 0;
78 if (MemoryZipStream::ZipStreamInfo* info =
79 reinterpret_cast<MemoryZipStream::ZipStreamInfo*>(opaque)) {
80 if (info->position + size > info->buffer.size())
81 info->buffer.resize(info->position + size);
83 memcpy(&info->buffer[info->position], buf, size);
84 info->position += size;
92 static ZipLong ZCALLBACK TellZipStream(voidpf opaque, voidpf stream) {
94 if (MemoryZipStream::ZipStreamInfo* info =
95 reinterpret_cast<MemoryZipStream::ZipStreamInfo*>(opaque))
96 position =
static_cast<ZipLong
>(info->position);
101 static ZipLong ZCALLBACK
102 SeekZipStream(voidpf opaque, voidpf stream, uLong
offset,
int origin) {
104 if (MemoryZipStream::ZipStreamInfo* info =
105 reinterpret_cast<MemoryZipStream::ZipStreamInfo*>(opaque)) {
107 const int64 size = info->buffer.size();
108 if (origin == SEEK_SET) {
111 }
else if (origin == SEEK_CUR) {
112 ok = (
static_cast<size_t>(
offset) + info->position) <=
113 static_cast<size_t>(size);
116 }
else if (origin == SEEK_END) {
117 const int64 new_pos = size -
static_cast<int64
>(
offset);
118 ok = new_pos >= 0 && new_pos <= size;
120 info->position = offset +
static_cast<size_t>(size);
127 static int ZCALLBACK CloseZipStream(voidpf opaque, voidpf stream) {
132 static int ZCALLBACK ErrorZipStream(voidpf opaque, voidpf stream) {
134 LOG(
ERROR) <<
"An error occurred in a MemoryZipStream";
139 explicit ScopedUnzip(MemoryZipStream::ZipStreamInfo* info)
140 :
handle(info->
buffer.size() ? unzAttach(&info->def, &info->def) : NULL) {
152 explicit ScopedZip(MemoryZipStream::ZipStreamInfo* info)
153 :
handle(info->buffer.size()
154 ? zipOpen2(
"", APPEND_STATUS_ADDINZIP, NULL, &info->def)
155 : zipOpen2(
"", APPEND_STATUS_CREATE, NULL, &info->def)) {}
168 : info_(new(GetAllocator()) ZipStreamInfo()) {
173 : info_(new(GetAllocator()) ZipStreamInfo()) {
174 info_->buffer = data;
179 : info_(new(GetAllocator()) ZipStreamInfo()) {
180 info_->buffer.swap(*data);
188 if (ScopedZip zip = ScopedZip(info_.get())) {
190 zip.handle, filename.c_str(), NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED,
192 zipWriteInFileInZip(zip.handle, data.data(),
193 static_cast<unsigned int>(data.size()));
194 zipCloseFileInZip(zip.handle);
199 const std::string& data) {
200 DataVector vec(*
this, data.begin(), data.end());
205 bool contains =
false;
206 if (ScopedUnzip unz = ScopedUnzip(info_.get()))
207 contains = unzLocateFile(unz.handle, filename.c_str(), 0) == UNZ_OK;
212 const std::string& filename) {
214 if (ScopedUnzip unz = ScopedUnzip(info_.get())) {
218 static const int kStringLength = 256;
219 char extra_field[kStringLength + 1];
220 char comment[kStringLength + 1];
221 if (unzLocateFile(unz.handle, filename.c_str(), 0) == UNZ_OK &&
222 unzOpenCurrentFile(unz.handle) == UNZ_OK &&
223 unzGetCurrentFileInfo(unz.handle, &info, NULL, 0, extra_field,
224 kStringLength, comment, kStringLength) ==
227 data.resize(info.uncompressed_size);
229 unzReadCurrentFile(unz.handle, &data[0],
230 static_cast<unsigned int>(info.uncompressed_size));
237 return info_->buffer;
240 void MemoryZipStream::InitCallbacks() {
242 info_->def.zopen_file = OpenZipStream;
243 info_->def.zread_file = ReadFromZipStream;
244 info_->def.zwrite_file = WriteToZipStream;
245 info_->def.ztell_file = TellZipStream;
246 info_->def.zseek_file = SeekZipStream;
247 info_->def.zclose_file = CloseZipStream;
248 info_->def.zerror_file = ErrorZipStream;
249 info_->def.opaque = info_.get();
~MemoryZipStream() override
void AddFile(const std::string &filename, const DataVector &data)
Compresses and adds a vector of data to this, associating it with the passed filename.
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
const DataVector GetFileData(const std::string &filename)
Returns the file data for filename.
MemoryZipStream()
Constructs an empty MemoryZipStream.
AllocVector< uint8 > DataVector
bool ContainsFile(const std::string &filename)
Returns whether this contains filename.
Copyright 2016 Google Inc.
const DataVector & GetData() const
Gets the memory buffer backing this.
const AllocatorPtr & GetAllocator() const
Returns the Allocator that was used for the instance.