From e953bcbd18ee467f4f3696fc739d5319a81ea667 Mon Sep 17 00:00:00 2001 From: cxl Date: Mon, 29 Feb 2016 17:29:34 +0000 Subject: [PATCH] plugin/Zip now supports storing uncompressed files git-svn-id: svn://ultimatepp.org/upp/trunk@9548 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/z.cpp | 2 +- uppsrc/Core/z.h | 5 +-- uppsrc/plugin/z/build_info.h | 9 +++++ uppsrc/plugin/zip/UnZip.cpp | 2 +- uppsrc/plugin/zip/Zip.cpp | 68 +++++++++++++++++++++++++++--------- uppsrc/plugin/zip/zip.h | 12 ++++--- 6 files changed, 73 insertions(+), 25 deletions(-) create mode 100644 uppsrc/plugin/z/build_info.h diff --git a/uppsrc/Core/z.cpp b/uppsrc/Core/z.cpp index ce062d029..34467587c 100644 --- a/uppsrc/Core/z.cpp +++ b/uppsrc/Core/z.cpp @@ -45,7 +45,7 @@ void Crc32Stream::Out(const void *ptr, dword count) crc = crc32(crc, (byte *)ptr, count); } -Crc32Stream::Crc32Stream() +void Crc32Stream::Clear() { crc = crc32(0, NULL, 0); } diff --git a/uppsrc/Core/z.h b/uppsrc/Core/z.h index 03b9040bd..a21feed05 100644 --- a/uppsrc/Core/z.h +++ b/uppsrc/Core/z.h @@ -6,8 +6,9 @@ class Crc32Stream : public OutStream { public: dword Finish() { Flush(); return crc; } operator dword() { return Finish(); } + void Clear(); - Crc32Stream(); + Crc32Stream() { Clear(); } }; dword CRC32(const void *ptr, dword count); @@ -63,7 +64,7 @@ public: String GetGZipName() const { return gzip_name; } String GetGZipComment() const { return gzip_comment; } - Zlib& GZip(bool gzip_ = true) { gzip = gzip_; return *this; } + Zlib& GZip(bool gzip_ = true) { gzip = gzip_; return *this; } Zlib& Header(bool hdr_ = true) { hdr = hdr_; return *this; } Zlib& NoHeader() { return Header(false); } Zlib& CRC(bool b = true) { docrc = b; return *this; } diff --git a/uppsrc/plugin/z/build_info.h b/uppsrc/plugin/z/build_info.h new file mode 100644 index 000000000..4271d4b9e --- /dev/null +++ b/uppsrc/plugin/z/build_info.h @@ -0,0 +1,9 @@ +#define bmYEAR 2016 +#define bmMONTH 2 +#define bmDAY 6 +#define bmHOUR 23 +#define bmMINUTE 2 +#define bmSECOND 31 +#define bmTIME Time(2016, 2, 6, 23, 2, 31) +#define bmMACHINE "MAIN" +#define bmUSER "cxl" diff --git a/uppsrc/plugin/zip/UnZip.cpp b/uppsrc/plugin/zip/UnZip.cpp index 3bddbe2e4..81a322805 100644 --- a/uppsrc/plugin/zip/UnZip.cpp +++ b/uppsrc/plugin/zip/UnZip.cpp @@ -29,7 +29,7 @@ void UnZip::ReadDir() offset = zip->Get32le(); //offset of start of central directory with respect to the starting disk number int commentlen = zip->Get16le(); if(zip->GetPos() + commentlen == zipsize) - break; + break; } pos--; } diff --git a/uppsrc/plugin/zip/Zip.cpp b/uppsrc/plugin/zip/Zip.cpp index 45c4e6233..5dbc07453 100644 --- a/uppsrc/plugin/zip/Zip.cpp +++ b/uppsrc/plugin/zip/Zip.cpp @@ -36,16 +36,22 @@ void Zip::FileHeader(const char *path, Time tm) done += 5*2 + 5*4 + f.path.GetCount(); } -void Zip::BeginFile(const char *path, Time tm) +void Zip::BeginFile(const char *path, Time tm, bool deflate) { ASSERT(!IsFileOpened()); - pipeZLib.Create(); - pipeZLib->WhenOut = THISBACK(PutCompressed); - pipeZLib->GZip(false).CRC().NoHeader().Compress(); + if(deflate) { + pipeZLib.Create(); + pipeZLib->WhenOut = THISBACK(PutCompressed); + pipeZLib->GZip(false).CRC().NoHeader().Compress(); + } + else { + crc32.Clear(); + uncompressed = true; + } File& f = file.Add(); f.version = 21; f.gpflag = 0x8; - f.method = 8; + f.method = deflate ? 8 : 0; f.crc = 0; f.csize = 0; f.usize = 0; @@ -53,9 +59,9 @@ void Zip::BeginFile(const char *path, Time tm) if (zip->IsError()) WhenError(); } -void Zip::BeginFile(OutFilterStream& oz, const char *path, Time tm) +void Zip::BeginFile(OutFilterStream& oz, const char *path, Time tm, bool deflate) { - BeginFile(path, tm); + BeginFile(path, tm, deflate); oz.Filter = THISBACK(Put); oz.End = THISBACK(EndFile); } @@ -64,7 +70,12 @@ void Zip::Put(const void *ptr, int size) { ASSERT(IsFileOpened()); File& f = file.Top(); - pipeZLib->Put(ptr, size); + if(f.method == 0) { + PutCompressed(ptr, size); + crc32.Put(ptr, size); + } + else + pipeZLib->Put(ptr, size); f.usize += size; } @@ -74,27 +85,50 @@ void Zip::EndFile() return; File& f = file.Top(); ASSERT(f.gpflag & 0x8); - pipeZLib->End(); - zip->Put32le(f.crc = pipeZLib->GetCRC()); + if(f.method == 0) + zip->Put32le(f.crc = crc32); + else { + pipeZLib->End(); + zip->Put32le(f.crc = pipeZLib->GetCRC()); + } zip->Put32le(f.csize); zip->Put32le(f.usize); done += 3*4; pipeZLib.Clear(); - if (zip->IsError()) WhenError(); + uncompressed = false; + if(zip->IsError()) WhenError(); } void Zip::PutCompressed(const void *ptr, int size) { ASSERT(IsFileOpened()); zip->Put(ptr, size); - if (zip->IsError()) WhenError(); + if (zip->IsError()) WhenError(); done += size; file.Top().csize += size; } -void Zip::WriteFile(const void *ptr, int size, const char *path, Gate2 progress, Time tm) +void Zip::WriteFile(const void *ptr, int size, const char *path, Gate2 progress, Time tm, bool deflate) { ASSERT(!IsFileOpened()); + if(!deflate) { + BeginFile(path, tm, deflate); + int done = 0; + while(done < size) { + if(progress(done, size)) + return; + int chunk = min(size - done, 65536); + Put((byte *)ptr + done, chunk); + if(zip->IsError()) { + WhenError(); + return; + } + done += chunk; + } + EndFile(); + return; + } + // following code could be implemented using BeginFile/Put/EndFile, but be conservative, keep proven code File& f = file.Add(); StringStream ss; MemReadStream ms(ptr, size); @@ -118,12 +152,12 @@ void Zip::WriteFile(const void *ptr, int size, const char *path, Gate2 FileHeader(path, tm); zip->Put(r, f.csize); done += f.csize; - if (zip->IsError()) WhenError(); + if (zip->IsError()) WhenError(); } -void Zip::WriteFile(const String& s, const char *path, Gate2 progress, Time tm) +void Zip::WriteFile(const String& s, const char *path, Gate2 progress, Time tm, bool deflate) { - WriteFile(~s, s.GetCount(), path, progress, tm); + WriteFile(~s, s.GetCount(), path, progress, tm, deflate); } void Zip::Create(Stream& out) @@ -177,12 +211,14 @@ Zip::Zip() { done = 0; zip = NULL; + uncompressed = false; } Zip::Zip(Stream& out) { done = 0; zip = NULL; + uncompressed = false; Create(out); } diff --git a/uppsrc/plugin/zip/zip.h b/uppsrc/plugin/zip/zip.h index 602e86e61..8e9689e40 100644 --- a/uppsrc/plugin/zip/zip.h +++ b/uppsrc/plugin/zip/zip.h @@ -105,6 +105,8 @@ class Zip { dword done; One pipeZLib; + Crc32Stream crc32; // for uncompressed files + bool uncompressed; void WriteFile0(const void *ptr, int size, const char *path, Gate2 progress, Time tm, int method); @@ -117,15 +119,15 @@ class Zip { public: Callback WhenError; - void BeginFile(const char *path, Time tm = GetSysTime()); - void BeginFile(OutFilterStream& oz, const char *path, Time tm = GetSysTime()); + void BeginFile(const char *path, Time tm = GetSysTime(), bool deflate = true); + void BeginFile(OutFilterStream& oz, const char *path, Time tm = GetSysTime(), bool deflate = true); void Put(const void *data, int size); void EndFile(); - bool IsFileOpened() const { return pipeZLib; } + bool IsFileOpened() const { return pipeZLib || uncompressed; } void WriteFolder(const char *path, Time tm); - void WriteFile(const void *ptr, int size, const char *path, Gate2 progress = false, Time tm = GetSysTime()); - void WriteFile(const String& s, const char *path, Gate2 progress = false, Time tm = GetSysTime()); + void WriteFile(const void *ptr, int size, const char *path, Gate2 progress = false, Time tm = GetSysTime(), bool deflate = true); + void WriteFile(const String& s, const char *path, Gate2 progress = false, Time tm = GetSysTime(), bool deflate = true); void Create(Stream& out); void Finish();