plugin/Zip now supports storing uncompressed files

git-svn-id: svn://ultimatepp.org/upp/trunk@9548 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2016-02-29 17:29:34 +00:00
parent 0db1b4237b
commit e953bcbd18
6 changed files with 73 additions and 25 deletions

View file

@ -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);
}

View file

@ -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; }

View file

@ -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"

View file

@ -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--;
}

View file

@ -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<int, int> progress, Time tm)
void Zip::WriteFile(const void *ptr, int size, const char *path, Gate2<int, int> 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<int, int>
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<int, int> progress, Time tm)
void Zip::WriteFile(const String& s, const char *path, Gate2<int, int> 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);
}

View file

@ -105,6 +105,8 @@ class Zip {
dword done;
One<Zlib> pipeZLib;
Crc32Stream crc32; // for uncompressed files
bool uncompressed;
void WriteFile0(const void *ptr, int size, const char *path, Gate2<int, int> 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<int, int> progress = false, Time tm = GetSysTime());
void WriteFile(const String& s, const char *path, Gate2<int, int> progress = false, Time tm = GetSysTime());
void WriteFile(const void *ptr, int size, const char *path, Gate2<int, int> progress = false, Time tm = GetSysTime(), bool deflate = true);
void WriteFile(const String& s, const char *path, Gate2<int, int> progress = false, Time tm = GetSysTime(), bool deflate = true);
void Create(Stream& out);
void Finish();