mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Core: Zlib gzip support
git-svn-id: svn://ultimatepp.org/upp/trunk@4733 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
e333617ab1
commit
a89c7d9cd6
7 changed files with 304 additions and 27 deletions
|
|
@ -196,6 +196,22 @@ enum
|
|||
typedef int SOCKET;
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#include <plugin/z/lib/zlib.h>
|
||||
#include <plugin/z/lib/zutil.h>
|
||||
#else
|
||||
#include <zlib.h>
|
||||
|
||||
#ifndef DEF_MEM_LEVEL
|
||||
#define DEF_MEM_LEVEL 8
|
||||
#endif
|
||||
|
||||
#ifndef OS_CODE
|
||||
#define OS_CODE 0x03
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
|
|
|
|||
|
|
@ -54,16 +54,11 @@ class TcpSocket {
|
|||
|
||||
public:
|
||||
Callback WhenWait;
|
||||
|
||||
TcpSocket& Timeout(int ms) { timeout = ms; global = false; return *this; }
|
||||
TcpSocket& GlobalTimeout(int ms);
|
||||
TcpSocket& Blocking() { return Timeout(Null); }
|
||||
|
||||
static String GetHostName();
|
||||
|
||||
int GetDone() const { return done; }
|
||||
|
||||
TcpSocket();
|
||||
~TcpSocket() { Close(); }
|
||||
|
||||
static void Init();
|
||||
|
||||
bool IsOpen() const { return socket != INVALID_SOCKET; }
|
||||
|
|
@ -114,7 +109,12 @@ public:
|
|||
bool PutAll(const char *s, int len) { return Put(s, len) == len; }
|
||||
bool PutAll(const String& s) { return Put(s) == s.GetCount(); }
|
||||
|
||||
static String GetHostName();
|
||||
TcpSocket& Timeout(int ms) { timeout = ms; global = false; return *this; }
|
||||
TcpSocket& GlobalTimeout(int ms);
|
||||
TcpSocket& Blocking() { return Timeout(Null); }
|
||||
|
||||
TcpSocket();
|
||||
~TcpSocket() { Close(); }
|
||||
};
|
||||
|
||||
struct HttpHeader {
|
||||
|
|
|
|||
|
|
@ -1,20 +1,7 @@
|
|||
#include "Core.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#include <plugin/z/lib/zlib.h>
|
||||
#include <plugin/z/lib/zutil.h>
|
||||
#else
|
||||
#include <zlib.h>
|
||||
|
||||
#ifndef DEF_MEM_LEVEL
|
||||
#define DEF_MEM_LEVEL 8
|
||||
#endif
|
||||
|
||||
#ifndef OS_CODE
|
||||
#define OS_CODE 0x03
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#define LDUMP(x) // DDUMP(x)
|
||||
#define LLOG(x) // DLOG(x)
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
|
@ -43,6 +30,8 @@ enum
|
|||
RESERVED = 0xE0, /* bits 5..7: reserved */
|
||||
};
|
||||
|
||||
static byte sGZip_header[10] = { GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED, 0, 0, 0, 0, 0, 0, OS_CODE };
|
||||
|
||||
void Crc32Stream::Out(const void *ptr, dword count)
|
||||
{
|
||||
crc = crc32(crc, (byte *)ptr, count);
|
||||
|
|
@ -65,6 +54,227 @@ dword CRC32(const String& s)
|
|||
return CRC32(~s, s.GetLength());
|
||||
}
|
||||
|
||||
void Zlib::Begin()
|
||||
{
|
||||
Free();
|
||||
error = false;
|
||||
if(docrc || gzip)
|
||||
crc = crc32(0, NULL, 0);
|
||||
out.Clear();
|
||||
}
|
||||
|
||||
void Zlib::Compress()
|
||||
{
|
||||
Begin();
|
||||
if(deflateInit2(&z, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
|
||||
hdr && !gzip ? MAX_WBITS : -MAX_WBITS, DEF_MEM_LEVEL,
|
||||
Z_DEFAULT_STRATEGY) != Z_OK)
|
||||
Panic("deflateInit2 failed");
|
||||
mode = DEFLATE;
|
||||
if(gzip)
|
||||
WhenOut(sGZip_header, 10);
|
||||
}
|
||||
|
||||
void Zlib::Decompress()
|
||||
{
|
||||
Begin();
|
||||
if(inflateInit2(&z, hdr && !gzip ? +MAX_WBITS : -MAX_WBITS) != Z_OK)
|
||||
Panic("inflateInit2 failed");
|
||||
mode = INFLATE;
|
||||
}
|
||||
|
||||
void Zlib::Pump(bool finish)
|
||||
{
|
||||
if(error)
|
||||
return;
|
||||
if(gzip_footer)
|
||||
return;
|
||||
ASSERT(mode);
|
||||
LDUMP(mode);
|
||||
if(!output)
|
||||
output.Alloc(chunk);
|
||||
for(;;) {
|
||||
LLOG("---");
|
||||
LDUMP(z.avail_in);
|
||||
int code;
|
||||
z.avail_out = chunk;
|
||||
z.next_out = output;
|
||||
code = (mode == DEFLATE ? deflate : inflate)(&z, finish ? Z_FINISH : Z_NO_FLUSH);
|
||||
LDUMP(code);
|
||||
LDUMP(z.avail_in);
|
||||
LDUMP(z.avail_out);
|
||||
int count = chunk - z.avail_out;
|
||||
LDUMP(count);
|
||||
LDUMP(count);
|
||||
if(count) {
|
||||
if((docrc || gzip) && mode == INFLATE)
|
||||
crc = crc32(crc, output, count);
|
||||
WhenOut((const char *)~output, count);
|
||||
if(mode == INFLATE)
|
||||
total += count;
|
||||
}
|
||||
if(mode == INFLATE && code == Z_STREAM_END) {
|
||||
gzip_footer = true;
|
||||
break;
|
||||
}
|
||||
if(mode == INFLATE ? code == Z_BUF_ERROR : count == 0)
|
||||
break;
|
||||
if(code != Z_OK && code != Z_STREAM_END) {
|
||||
LLOG("ERROR " << code);
|
||||
Free();
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Zlib::GzipHeader(const char *ptr, int size)
|
||||
{
|
||||
int pos = 10;
|
||||
if(pos > size)
|
||||
return 0;
|
||||
int flags = ptr[3];
|
||||
if(ptr[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
|
||||
error = true;
|
||||
return 0;
|
||||
}
|
||||
if(flags & EXTRA_FIELD) {
|
||||
if(pos + 2 > size)
|
||||
return 0;
|
||||
int len = MAKEWORD(ptr[pos], ptr[pos + 1]);
|
||||
if(len < 0) {
|
||||
error = true;
|
||||
return 0;
|
||||
}
|
||||
if((pos += len + 2) > size)
|
||||
return 0;
|
||||
}
|
||||
for(int i = !!(flags & ORIG_NAME) + !!(flags & COMMENT); i > 0; i--) {
|
||||
while(ptr[pos])
|
||||
if(++pos > size)
|
||||
return 0;
|
||||
if(++pos > size)
|
||||
return 0;
|
||||
}
|
||||
if(flags & HEAD_CRC)
|
||||
if((pos += 2) > size)
|
||||
return 0;
|
||||
return pos;
|
||||
}
|
||||
|
||||
void Zlib::Put0(const char *ptr, int size)
|
||||
{
|
||||
if(error)
|
||||
return;
|
||||
ASSERT(mode);
|
||||
if(size <= 0)
|
||||
return;
|
||||
if(gzip && !gzip_done && mode == INFLATE) {
|
||||
if(gzip_hs.GetCount()) {
|
||||
gzip_hs.Cat(ptr, size);
|
||||
ptr = ~gzip_hs;
|
||||
size = gzip_hs.GetCount();
|
||||
}
|
||||
int pos = GzipHeader(ptr, size);
|
||||
if(!pos) {
|
||||
if(gzip_hs.GetCount() == 0)
|
||||
gzip_hs.Cat(ptr, size);
|
||||
return;
|
||||
}
|
||||
|
||||
gzip_done = true;
|
||||
size -= pos;
|
||||
ptr += pos;
|
||||
}
|
||||
|
||||
if(size <= 0)
|
||||
return;
|
||||
|
||||
if(mode == DEFLATE) {
|
||||
total += size;
|
||||
if(docrc || gzip)
|
||||
crc = crc32(crc, (const Bytef *)ptr, size);
|
||||
}
|
||||
|
||||
z.next_in = (Bytef *)ptr;
|
||||
z.avail_in = size;
|
||||
Pump(Z_NO_FLUSH);
|
||||
}
|
||||
|
||||
void Zlib::Put(const void *ptr, dword size)
|
||||
{
|
||||
if(error)
|
||||
return;
|
||||
const char *p = reinterpret_cast<const char *>(ptr);
|
||||
while(size) {
|
||||
LLOG("Put " << size);
|
||||
int psz = (int) min(size, dword(INT_MAX / 4));
|
||||
Put0(p, size);
|
||||
size -= psz;
|
||||
p += psz;
|
||||
}
|
||||
}
|
||||
|
||||
void Zlib::PutOut(const void *ptr, dword size)
|
||||
{
|
||||
out.Cat((const char *)ptr, (int)size);
|
||||
LDUMP(out.GetCount());
|
||||
}
|
||||
|
||||
void Zlib::End()
|
||||
{
|
||||
LLOG("End");
|
||||
if(mode != INFLATE || !gzip || gzip_done)
|
||||
Pump(Z_FINISH);
|
||||
if(gzip && mode == DEFLATE) {
|
||||
char h[8];
|
||||
Poke32le(h, crc);
|
||||
Poke32le(h + 4, total);
|
||||
WhenOut(h, 8);
|
||||
}
|
||||
Free();
|
||||
}
|
||||
|
||||
void Zlib::Free()
|
||||
{
|
||||
if(mode == INFLATE)
|
||||
inflateEnd(&z);
|
||||
if(mode == DEFLATE)
|
||||
deflateEnd(&z);
|
||||
mode = NONE;
|
||||
gzip_hs.Clear();
|
||||
gzip_done = false;
|
||||
gzip_footer = false;
|
||||
total = 0;
|
||||
}
|
||||
|
||||
Zlib& Zlib::ChunkSize(int n)
|
||||
{
|
||||
ASSERT(n < INT_MAX / 4);
|
||||
output.Clear();
|
||||
chunk = n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Zlib::Zlib()
|
||||
{
|
||||
z.zalloc = zalloc_new;
|
||||
z.zfree = zfree_new;
|
||||
z.opaque = 0;
|
||||
docrc = false;
|
||||
crc = 0;
|
||||
hdr = true;
|
||||
WhenOut = callback(this, &Zlib::PutOut);
|
||||
mode = NONE;
|
||||
gzip = false;
|
||||
}
|
||||
|
||||
Zlib::~Zlib()
|
||||
{
|
||||
if(mode)
|
||||
End();
|
||||
}
|
||||
|
||||
static int sZpress(Stream& out, Stream& in, int size, Gate2<int, int> progress, bool nohdr, dword *crc,
|
||||
bool compress)
|
||||
{
|
||||
|
|
@ -169,8 +379,7 @@ String ZDecompress(const String& s, Gate2<int, int> progress)
|
|||
|
||||
int GZCompress(Stream& out, Stream& in, int size, Gate2<int, int> progress)
|
||||
{
|
||||
static byte gzip_header[10] = { GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED, 0, 0, 0, 0, 0, 0, OS_CODE };
|
||||
out.Put(gzip_header, 10);
|
||||
out.Put(sGZip_header, 10);
|
||||
dword crc;
|
||||
int sz = ZCompress(out, in, size, progress, true, &crc);
|
||||
out.Put32le(crc);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,55 @@ public:
|
|||
dword CRC32(const void *ptr, dword count);
|
||||
dword CRC32(const String& s);
|
||||
|
||||
class Zlib {
|
||||
enum { NONE, DEFLATE, INFLATE };
|
||||
|
||||
z_stream z;
|
||||
Buffer<Bytef> output;
|
||||
int chunk;
|
||||
int mode;
|
||||
dword crc;
|
||||
int total;
|
||||
bool docrc;
|
||||
bool hdr;
|
||||
bool error;
|
||||
bool gzip;
|
||||
bool gzip_done;
|
||||
bool gzip_footer;
|
||||
String gzip_hs;
|
||||
|
||||
void PutOut(const void *ptr, dword size);
|
||||
void Pump(bool finish);
|
||||
void Begin();
|
||||
void Free();
|
||||
void Put0(const char *ptr, int size);
|
||||
int GzipHeader(const char *ptr, int size);
|
||||
|
||||
public:
|
||||
Callback2<const void *, dword> WhenOut;
|
||||
String out;
|
||||
|
||||
dword GetCrc() const { return crc; }
|
||||
|
||||
bool IsError() const { return error; }
|
||||
|
||||
void Compress();
|
||||
void Decompress();
|
||||
void Put(const void *ptr, dword size);
|
||||
void Put(const String& s) { Put(~s, s.GetCount()); }
|
||||
void End();
|
||||
|
||||
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; }
|
||||
Zlib& NoCrc() { return Crc(false); }
|
||||
Zlib& ChunkSize(int n);
|
||||
|
||||
Zlib();
|
||||
~Zlib();
|
||||
};
|
||||
|
||||
int ZCompress(Stream& out, Stream& in, int size, Gate2<int, int> progress = false, bool nohdr = false, dword *crc = NULL);
|
||||
int ZDecompress(Stream& out, Stream& in, int size, Gate2<int, int> progress = false, bool nohdr = false, dword *crc = NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
#ifndef _Web_icpp_init_stub
|
||||
#define _Web_icpp_init_stub
|
||||
#include "Core/init"
|
||||
#define BLITZ_INDEX__ F812213f29e8b190fead32d3e1aa22ad7
|
||||
#include "Web/SSL/init"
|
||||
#define BLITZ_INDEX__ F173e4988d70c85ab4a78f4702f196919
|
||||
#include "Web_init.icpp"
|
||||
#undef BLITZ_INDEX__
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ uses
|
|||
plugin/astyle,
|
||||
usvn,
|
||||
TextDiffCtrl,
|
||||
TabBar;
|
||||
TabBar,
|
||||
Web/SSL;
|
||||
|
||||
uses(POSIX) ide\SrcUpdater;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,5 +17,6 @@
|
|||
#include "usvn/init"
|
||||
#include "TextDiffCtrl/init"
|
||||
#include "TabBar/init"
|
||||
#include "Web/SSL/init"
|
||||
#include "ide\SrcUpdater/init"
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue