mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-31 07:12:39 -06:00
plugin/zip: Zip: Streaming mode for individual files
git-svn-id: svn://ultimatepp.org/upp/trunk@7421 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
5c9e92b773
commit
ef2bd2b6e4
6 changed files with 135 additions and 214 deletions
|
|
@ -15,7 +15,9 @@ topic "OutFilterStream";
|
|||
[s1;:OutFilterStream`:`:class: [@(0.0.255)3 class][3 _][*3 OutFilterStream][3 _:_][@(0.0.255)3 p
|
||||
ublic][3 _][*@3;3 Stream]&]
|
||||
[s2;%% Adapter Stream that glues an output stream with some filtering
|
||||
object, typically of compression/decompression class.&]
|
||||
object, typically of compression/decompression class. Output
|
||||
stream can also be omitted, in that case OutFilterStream is useful
|
||||
to convert anything capable of consuming data into Stream.&]
|
||||
[s3; &]
|
||||
[ {{10000F(128)G(128)@1 [s0;%% [* Public Member List]]}}&]
|
||||
[s3; &]
|
||||
|
|
@ -26,21 +28,23 @@ call does nothing.&]
|
|||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:OutFilterStream`:`:out: [_^Stream^ Stream]_`*[* out]&]
|
||||
[s2;%% Pointer to the output stream.&]
|
||||
[s2;%% Pointer to the output stream. Can be NULL.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:OutFilterStream`:`:Filter: [_^Callback2^ Callback2]<[@(0.0.255) const]_[@(0.0.255) voi
|
||||
d]_`*, [@(0.0.255) int]>_[* Filter]&]
|
||||
[s2;%% Callback to filter input function.&]
|
||||
[s2;%% Callback to filter input function. This is called when OutFilterStream
|
||||
needs to output a chunk of buffered data.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:OutFilterStream`:`:End: [_^Callback^ Callback]_[* End]&]
|
||||
[s2;%% Callback to filter finalization.&]
|
||||
[s2;%% Callback to filter finalization. Called on closing the stream.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:OutFilterStream`:`:Out`(const void`*`,int`): [@(0.0.255) void]_[* Out]([@(0.0.255) con
|
||||
st]_[@(0.0.255) void]_`*[*@3 ptr], [@(0.0.255) int]_[*@3 size])&]
|
||||
[s2;%% Method serving as filter output.&]
|
||||
[s2;%% Method serving as filter output. Basically performs out`->Put(ptr,
|
||||
size), also keeps track of output bytes written (see GetCount).&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:OutFilterStream`:`:GetCount`(`)const: [@(0.0.255) int64]_[* GetCount]()_[@(0.0.255) co
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "zip.h"
|
||||
|
||||
#ifndef OLD_UNZIP
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void UnZip::ReadDir()
|
||||
|
|
@ -68,7 +66,7 @@ void UnZip::ReadDir()
|
|||
error = false;
|
||||
}
|
||||
|
||||
Time UnZip::GetTime(dword dt)
|
||||
Time UnZip::GetZipTime(dword dt)
|
||||
{
|
||||
Time time;
|
||||
time.year = int16(((dt >> 25) & 0x7f) + 1980);
|
||||
|
|
@ -163,5 +161,3 @@ UnZip::UnZip()
|
|||
UnZip::~UnZip() {}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
#include "zip.h"
|
||||
|
||||
#ifdef OLD_UNZIP
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void UnZip::ReadHeader()
|
||||
{
|
||||
if(zip->Get32le() != 0x04034b50) {
|
||||
eof = true;
|
||||
return;
|
||||
}
|
||||
if(zip->Get16le() > 20) {
|
||||
SetError();
|
||||
return;
|
||||
}
|
||||
bit = zip->Get16le();
|
||||
method = zip->Get16le();
|
||||
|
||||
dword dt = zip->Get32le();
|
||||
|
||||
time.year = int16(((dt >> 25) & 0x7f) + 1980);
|
||||
time.month = byte((dt >> 21) & 0x0f);
|
||||
time.day = byte((dt >> 16) & 0x1f);
|
||||
time.hour = byte((dt >> 11) & 0x1f);
|
||||
time.minute = byte((dt >> 5) & 0x3f);
|
||||
time.second = byte((dt << 1) & 0x3e);
|
||||
|
||||
crc32 = zip->Get32le();
|
||||
csize = zip->Get32le();
|
||||
usize = zip->Get32le();
|
||||
|
||||
dword filelen = zip->Get16le();
|
||||
dword extralen = zip->Get16le();
|
||||
path = zip->Get(filelen);
|
||||
zip->SeekCur(extralen);
|
||||
|
||||
done += 5 * 2 + 5 * 4;
|
||||
}
|
||||
|
||||
void UnZip::SkipFile()
|
||||
{
|
||||
zip->SeekCur(csize);
|
||||
done += csize;
|
||||
ReadHeader();
|
||||
}
|
||||
|
||||
int64 zPress(Stream& out, Stream& in, int64 size, Gate2<int64, int64> progress, bool gzip,
|
||||
bool compress, dword *crc, bool hdr);
|
||||
|
||||
bool UnZip::ReadFile(Stream& out, Gate2<int, int> progress)
|
||||
{
|
||||
dword crc;
|
||||
int l;
|
||||
if(method == 0) {
|
||||
Buffer<byte> temp(65536);
|
||||
int loaded;
|
||||
int count = csize;
|
||||
Crc32Stream crc32;
|
||||
while(count > 0 && (loaded = zip->Get(temp, (int)min<int64>(count, 65536))) > 0) {
|
||||
out.Put(temp, loaded);
|
||||
crc32.Put(temp, loaded);
|
||||
count -= loaded;
|
||||
}
|
||||
if(count > 0) {
|
||||
SetError();
|
||||
return false;
|
||||
}
|
||||
l = csize;
|
||||
crc = crc32;
|
||||
}
|
||||
else
|
||||
if(method == 8)
|
||||
l = (int)zPress(out, *zip, csize, AsGate64(progress), false, false, &crc, false);
|
||||
else {
|
||||
SetError();
|
||||
return false;
|
||||
}
|
||||
if(crc != crc32 || l != usize) {
|
||||
SetError();
|
||||
return false;
|
||||
}
|
||||
done += csize;
|
||||
ReadHeader();
|
||||
return true;
|
||||
}
|
||||
|
||||
String UnZip::ReadFile(Gate2<int, int> progress)
|
||||
{
|
||||
StringStream ss;
|
||||
return ReadFile(ss, progress) ? ss.GetResult() : String::GetVoid();
|
||||
}
|
||||
|
||||
void UnZip::Create(Stream& _zip)
|
||||
{
|
||||
eof = error = false;
|
||||
zip = &_zip;
|
||||
done = 0;
|
||||
ReadHeader();
|
||||
}
|
||||
|
||||
bool UnZip::IsEof() const
|
||||
{
|
||||
return eof || !zip || error || zip->IsEof();
|
||||
}
|
||||
|
||||
bool UnZip::IsFolder() const
|
||||
{
|
||||
return *path.Last() == '/';
|
||||
}
|
||||
|
||||
UnZip::UnZip(Stream& in)
|
||||
{
|
||||
Create(in);
|
||||
}
|
||||
|
||||
UnZip::UnZip()
|
||||
{
|
||||
error = true;
|
||||
zip = NULL;
|
||||
}
|
||||
|
||||
UnZip::~UnZip() {}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
@ -13,37 +13,112 @@ void Zip::WriteFolder(const char *path, Time tm)
|
|||
int64 zPress(Stream& out, Stream& in, int64 size, Gate2<int64, int64> progress, bool gzip,
|
||||
bool compress, dword *crc, bool hdr);
|
||||
|
||||
void Zip::WriteFile(const void *ptr, int size, const char *path, Gate2<int, int> progress, Time tm)
|
||||
|
||||
void Zip::FileHeader(const char *path, Time tm)
|
||||
{
|
||||
File& f = file.Add();
|
||||
File& f = file.Top();
|
||||
f.path = UnixPath(path);
|
||||
StringStream ss;
|
||||
MemReadStream ms(ptr, size);
|
||||
dword crc;
|
||||
zPress(ss, ms, size, AsGate64(progress), false, true, &crc, false);
|
||||
String data = ss.GetResult();
|
||||
const void *r = ~data;
|
||||
int csize = data.GetLength();
|
||||
zip->Put32le(0x04034b50);
|
||||
zip->Put16le(20);
|
||||
zip->Put16le(0);
|
||||
if(data.GetLength() >= size) {
|
||||
r = ptr;
|
||||
csize = size;
|
||||
zip->Put16le(f.method = 0);
|
||||
}
|
||||
else
|
||||
zip->Put16le(f.method = 8);
|
||||
zip->Put16le(f.version);
|
||||
zip->Put16le(f.gpflag);
|
||||
zip->Put16le(f.method);
|
||||
zip->Put32le(f.time = (tm.day << 16) | (tm.month << 21) | ((tm.year - 1980) << 25) |
|
||||
(tm.hour << 11) | (tm.minute << 5) | (tm.second >> 1));
|
||||
zip->Put32le(f.crc = crc);
|
||||
zip->Put32le(f.csize = csize);
|
||||
zip->Put32le(f.usize = size);
|
||||
ASSERT((f.gpflag & 0x8) == 0 || f.crc == 0);
|
||||
zip->Put32le(f.crc);
|
||||
ASSERT((f.gpflag & 0x8) == 0 || f.csize == 0);
|
||||
zip->Put32le(f.csize);
|
||||
ASSERT((f.gpflag & 0x8) == 0 || f.usize == 0);
|
||||
zip->Put32le(f.usize);
|
||||
zip->Put16le(strlen(f.path));
|
||||
zip->Put16le(0);
|
||||
zip->Put(f.path);
|
||||
zip->Put(r, csize);
|
||||
done += 5 * 2 + 5 * 4 + csize + f.path.GetCount();
|
||||
done += 5*2 + 5*4 + f.path.GetCount();
|
||||
}
|
||||
|
||||
void Zip::BeginFile(const char *path, Time tm)
|
||||
{
|
||||
ASSERT(!IsFileOpened());
|
||||
pipeZLib.Create();
|
||||
pipeZLib->WhenOut = THISBACK(PutCompressed);
|
||||
pipeZLib->GZip(false).CRC().NoHeader().Compress();
|
||||
File& f = file.Add();
|
||||
f.version = 21;
|
||||
f.gpflag = 0x8;
|
||||
f.method = 8;
|
||||
f.crc = 0;
|
||||
f.csize = 0;
|
||||
f.usize = 0;
|
||||
FileHeader(path, tm);
|
||||
if (zip->IsError()) WhenError();
|
||||
}
|
||||
|
||||
void Zip::BeginFile(OutFilterStream& oz, const char *path, Time tm)
|
||||
{
|
||||
BeginFile(path, tm);
|
||||
oz.Filter = THISBACK(Put);
|
||||
oz.End = THISBACK(EndFile);
|
||||
}
|
||||
|
||||
void Zip::Put(const void *ptr, int size)
|
||||
{
|
||||
ASSERT(IsFileOpened());
|
||||
File& f = file.Top();
|
||||
pipeZLib->Put(ptr, size);
|
||||
f.usize += size;
|
||||
}
|
||||
|
||||
void Zip::EndFile()
|
||||
{
|
||||
if(!IsFileOpened())
|
||||
return;
|
||||
File& f = file.Top();
|
||||
ASSERT(f.gpflag & 0x8);
|
||||
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();
|
||||
}
|
||||
|
||||
void Zip::PutCompressed(const void *ptr, int size)
|
||||
{
|
||||
ASSERT(IsFileOpened());
|
||||
zip->Put(ptr, size);
|
||||
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)
|
||||
{
|
||||
ASSERT(!IsFileOpened());
|
||||
File& f = file.Add();
|
||||
StringStream ss;
|
||||
MemReadStream ms(ptr, size);
|
||||
|
||||
f.usize = size;
|
||||
zPress(ss, ms, size, AsGate64(progress), false, true, &f.crc, false);
|
||||
|
||||
String data = ss.GetResult();
|
||||
const void *r = ~data;
|
||||
f.csize = data.GetLength();
|
||||
|
||||
f.version = 20;
|
||||
f.gpflag = 0;
|
||||
if(data.GetLength() >= size) {
|
||||
r = ptr;
|
||||
f.csize = size;
|
||||
f.method = 0;
|
||||
}
|
||||
else
|
||||
f.method = 8;
|
||||
FileHeader(path, tm);
|
||||
zip->Put(r, f.csize);
|
||||
done += f.csize;
|
||||
if (zip->IsError()) WhenError();
|
||||
}
|
||||
|
||||
void Zip::WriteFile(const String& s, const char *path, Gate2<int, int> progress, Time tm)
|
||||
|
|
@ -68,8 +143,8 @@ void Zip::Finish()
|
|||
File& f = file[i];
|
||||
zip->Put32le(0x02014b50);
|
||||
zip->Put16le(20);
|
||||
zip->Put16le(20);
|
||||
zip->Put16le(0); // general purpose bit flag
|
||||
zip->Put16le(f.version);
|
||||
zip->Put16le(f.gpflag); // general purpose bit flag
|
||||
zip->Put16le(f.method);
|
||||
zip->Put32le(f.time);
|
||||
zip->Put32le(f.crc);
|
||||
|
|
@ -82,7 +157,7 @@ void Zip::Finish()
|
|||
zip->Put16le(0); // internal file attributes 2 bytes
|
||||
zip->Put32le(0); // external file attributes 4 bytes
|
||||
zip->Put32le(rof); // relative offset of local header 4 bytes
|
||||
rof+=5 * 2 + 5 * 4 + f.csize + f.path.GetCount();
|
||||
rof+=5 * 2 + 5 * 4 + f.csize + f.path.GetCount() + (f.gpflag & 0x8 ? 3*4 : 0);
|
||||
zip->Put(f.path);
|
||||
done += 7 * 4 + 9 * 2 + f.path.GetCount();
|
||||
}
|
||||
|
|
@ -94,6 +169,7 @@ void Zip::Finish()
|
|||
zip->Put32le(done - off); // size of the central directory
|
||||
zip->Put32le(off); //offset of start of central directory with respect to the starting disk number
|
||||
zip->Put16le(0);
|
||||
if (zip->IsError()) WhenError();
|
||||
zip = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifndef OLD_UNZIP
|
||||
|
||||
class UnZip {
|
||||
struct File : Moveable<File> {
|
||||
word bit;
|
||||
|
|
@ -26,7 +24,7 @@ class UnZip {
|
|||
|
||||
void ReadDir();
|
||||
|
||||
static Time GetTime(dword time);
|
||||
static Time GetZipTime(dword time);
|
||||
|
||||
public:
|
||||
bool IsEof() const { return current >= file.GetCount(); }
|
||||
|
|
@ -39,6 +37,7 @@ public:
|
|||
String GetPath(int i) const { return file[i].path; }
|
||||
bool IsFolder(int i) const { return *file[i].path.Last() == '/'; }
|
||||
int GetLength(int i) const { return file[i].usize; }
|
||||
Time GetTime(int i) const { return GetZipTime(file[i].time); }
|
||||
|
||||
void Seek(int i) { ASSERT(i >= 0 && i < file.GetCount()); current = i; }
|
||||
|
||||
|
|
@ -61,52 +60,6 @@ public:
|
|||
virtual ~UnZip();
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class UnZip {
|
||||
Stream *zip;
|
||||
|
||||
bool error;
|
||||
bool eof;
|
||||
String path;
|
||||
word bit;
|
||||
word method;
|
||||
Time time;
|
||||
dword crc32;
|
||||
dword csize;
|
||||
dword usize;
|
||||
dword done;
|
||||
|
||||
void Init();
|
||||
void ReadHeader();
|
||||
void SetError() { error = true; }
|
||||
|
||||
public:
|
||||
bool IsEof() const;
|
||||
operator bool() const { return !IsEof(); }
|
||||
|
||||
bool IsError() const { return error; }
|
||||
|
||||
bool IsFolder() const;
|
||||
String GetPath() const { return path; }
|
||||
int GetLength() const { return usize; }
|
||||
Time GetTime() const { return time; }
|
||||
|
||||
void SkipFile();
|
||||
bool ReadFile(Stream& out, Gate2<int, int> progress = false);
|
||||
String ReadFile(Gate2<int, int> progress = false);
|
||||
|
||||
dword GetPos() { return done; }
|
||||
|
||||
void Create(Stream& in);
|
||||
|
||||
UnZip(Stream& in);
|
||||
UnZip();
|
||||
virtual ~UnZip();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
class FileUnZip : public UnZip {
|
||||
FileIn zip;
|
||||
|
||||
|
|
@ -135,11 +88,15 @@ public:
|
|||
};
|
||||
|
||||
class Zip {
|
||||
typedef Zip CLASSNAME;
|
||||
|
||||
Stream *zip;
|
||||
|
||||
struct File {
|
||||
String path;
|
||||
dword time;
|
||||
int version;
|
||||
int gpflag;
|
||||
int method;
|
||||
dword crc;
|
||||
dword csize;
|
||||
|
|
@ -149,9 +106,25 @@ class Zip {
|
|||
|
||||
dword done;
|
||||
|
||||
One<Zlib> pipeZLib;
|
||||
|
||||
void WriteFile0(const void *ptr, int size, const char *path, Gate2<int, int> progress, Time tm, int method);
|
||||
|
||||
void FileHeader(const char *path, Time tm);
|
||||
|
||||
void PutCompressed(const void *data, int size);
|
||||
|
||||
typedef Zip CLASSNAME;
|
||||
|
||||
public:
|
||||
Callback WhenError;
|
||||
|
||||
void BeginFile(const char *path, Time tm = GetSysTime());
|
||||
void BeginFile(OutFilterStream& oz, const char *path, Time tm = GetSysTime());
|
||||
void Put(const void *data, int size);
|
||||
void EndFile();
|
||||
bool IsFileOpened() const { return pipeZLib; }
|
||||
|
||||
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());
|
||||
|
|
|
|||
|
|
@ -4,6 +4,5 @@ file
|
|||
zip.h,
|
||||
Zip.cpp,
|
||||
UnZip.cpp,
|
||||
UnZipUtil.cpp,
|
||||
UnZipOld.cpp;
|
||||
UnZipUtil.cpp;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue