mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
plugin/bz2: Streaming support
git-svn-id: svn://ultimatepp.org/upp/trunk@11739 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
0443a21f96
commit
4e945630e0
2 changed files with 272 additions and 18 deletions
|
|
@ -1,7 +1,91 @@
|
|||
#ifndef __Plugin_BZ2__
|
||||
#define __Plugin_BZ2__
|
||||
|
||||
#ifdef flagWIN32
|
||||
#include "lib/bzlib.h"
|
||||
#else
|
||||
#include <bzlib.h>
|
||||
#endif
|
||||
|
||||
namespace Upp {
|
||||
|
||||
namespace bz2 {
|
||||
class Lib {
|
||||
enum { NONE, DEFLATE, INFLATE };
|
||||
|
||||
bz_stream z;
|
||||
Buffer<char> output;
|
||||
int chunk;
|
||||
int mode;
|
||||
int total;
|
||||
int compression_level;
|
||||
bool error;
|
||||
bool rdall;
|
||||
bool eos;
|
||||
String out;
|
||||
|
||||
void SetError(bool v) { error = v; }
|
||||
void PutOut(const void *ptr, int size);
|
||||
void Pump(bool finish);
|
||||
void Begin();
|
||||
void Free();
|
||||
int GzipHeader(const char *ptr, int size);
|
||||
void Init();
|
||||
|
||||
public:
|
||||
Event<const void *, int> WhenOut;
|
||||
|
||||
void Compress();
|
||||
void Decompress(bool all = true);
|
||||
void Put(const void *ptr, int size);
|
||||
void Put(const String& s) { Put(~s, s.GetCount()); }
|
||||
void End();
|
||||
void Clear();
|
||||
|
||||
const String& Get() const { return out; }
|
||||
operator const String&() const { return out; }
|
||||
const String& operator~() const { return out; }
|
||||
void ClearOut() { out.Clear(); }
|
||||
|
||||
bool IsError() const { return error; }
|
||||
bool IsEOS() const { return eos; }
|
||||
|
||||
Lib& ChunkSize(int n);
|
||||
Lib& Level(int compression_lvl) { compression_level = compression_lvl; return *this; }
|
||||
|
||||
Lib();
|
||||
~Lib();
|
||||
};
|
||||
|
||||
class CompressStream : public OutFilterStream {
|
||||
Lib z;
|
||||
|
||||
public:
|
||||
void Open(Stream& out) { z.Compress(); Set(out, z); }
|
||||
|
||||
Lib& ChunkSize(int n) { return z.ChunkSize(n); }
|
||||
Lib& Level(int compression_lvl) { return z.Level(compression_lvl); }
|
||||
|
||||
CompressStream() {}
|
||||
CompressStream(Stream& out) { Open(out); }
|
||||
~CompressStream() { Close(); }
|
||||
};
|
||||
|
||||
class DecompressStream : public InFilterStream {
|
||||
Lib z;
|
||||
|
||||
public:
|
||||
void Open(Stream& in) { z.Decompress(); Set(in, z); }
|
||||
Lib& ChunkSize(int n) { return z.ChunkSize(n); }
|
||||
|
||||
DecompressStream() {}
|
||||
DecompressStream(Stream& out) { Open(out); }
|
||||
~DecompressStream() { Close(); }
|
||||
};
|
||||
}
|
||||
|
||||
typedef bz2::CompressStream BZ2CompressStream;
|
||||
typedef bz2::DecompressStream BZ2DecompressStream;
|
||||
|
||||
void BZ2Compress(Stream& out, Stream& in, Gate<int, int> progress = Null);
|
||||
void BZ2Decompress(Stream& out, Stream& in, Gate<int, int> progress = Null);
|
||||
|
|
|
|||
|
|
@ -1,22 +1,192 @@
|
|||
#include <Core/Core.h>
|
||||
#include <plugin/bz2/bz2.h>
|
||||
|
||||
#ifdef flagWIN32
|
||||
#include "lib/bzlib.h"
|
||||
#else
|
||||
#include <bzlib.h>
|
||||
#endif
|
||||
#define LDUMP(x) // DDUMP(x)
|
||||
#define LLOG(x) // DLOG(x)
|
||||
|
||||
namespace Upp {
|
||||
|
||||
static void* bzalloc_new(void *opaque, int items, int size)
|
||||
{
|
||||
return new byte[items * size];
|
||||
}
|
||||
|
||||
static void bzfree_new(void *opaque, void *addr)
|
||||
{
|
||||
delete[] (byte *)addr;
|
||||
namespace bz2 {
|
||||
static void* bzalloc_new(void *opaque, int items, int size)
|
||||
{
|
||||
return new byte[items * size];
|
||||
}
|
||||
|
||||
static void bzfree_new(void *opaque, void *addr)
|
||||
{
|
||||
delete[] (byte *)addr;
|
||||
}
|
||||
|
||||
|
||||
void Lib::Begin()
|
||||
{
|
||||
Free();
|
||||
SetError(false);
|
||||
out.Clear();
|
||||
}
|
||||
|
||||
void Lib::Compress()
|
||||
{
|
||||
Begin();
|
||||
if(BZ2_bzCompressInit(&z, compression_level, 0, 30) != BZ_OK)
|
||||
Panic("BZ2_bzCompressInit failed");
|
||||
mode = DEFLATE;
|
||||
}
|
||||
|
||||
void Lib::Decompress(bool all)
|
||||
{
|
||||
Begin();
|
||||
rdall = all;
|
||||
eos = false;
|
||||
if(BZ2_bzDecompressInit(&z, 0, 0) != BZ_OK)
|
||||
Panic("BZ2_bzDecompressInit failed");
|
||||
mode = INFLATE;
|
||||
}
|
||||
|
||||
void Lib::Pump(bool finish)
|
||||
{
|
||||
if(error)
|
||||
return;
|
||||
ASSERT(mode);
|
||||
if(!output)
|
||||
output.Alloc(chunk);
|
||||
if (mode == INFLATE) {
|
||||
z.avail_out = chunk;
|
||||
z.next_out = output;
|
||||
while (z.avail_in) {
|
||||
const int code = BZ2_bzDecompress(&z);
|
||||
const int count = chunk - z.avail_out;
|
||||
if(count) {
|
||||
WhenOut((const char *)~output, count);
|
||||
if (error) {
|
||||
Free();
|
||||
break;
|
||||
}
|
||||
total += count;
|
||||
z.avail_out = chunk;
|
||||
z.next_out = output;
|
||||
}
|
||||
if(code == BZ_STREAM_END) {
|
||||
if (rdall) {
|
||||
BZ2_bzDecompressEnd(&z);
|
||||
if(BZ2_bzDecompressInit(&z, 0, 0) != BZ_OK)
|
||||
Panic("BZ2_bzDecompressInit failed");
|
||||
}
|
||||
else
|
||||
eos = true;
|
||||
}
|
||||
if(code != BZ_OK && code != BZ_STREAM_END) {
|
||||
LLOG("BZLIB ERROR " << code);
|
||||
Free();
|
||||
SetError(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const int flush = finish ? BZ_FINISH : BZ_RUN;
|
||||
z.avail_out = chunk;
|
||||
z.next_out = output;
|
||||
while (z.avail_in) {
|
||||
const int code = BZ2_bzCompress(&z, flush);
|
||||
const int count = chunk - z.avail_out;
|
||||
if(count) {
|
||||
WhenOut((const char *)~output, count);
|
||||
if (error) {
|
||||
Free();
|
||||
break;
|
||||
}
|
||||
z.avail_out = chunk;
|
||||
z.next_out = output;
|
||||
}
|
||||
if(code != BZ_RUN_OK && code != BZ_FINISH_OK) {
|
||||
LLOG("BZLIB ERROR " << code);
|
||||
Free();
|
||||
SetError(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Lib::Put(const void *ptr, int size)
|
||||
{
|
||||
if(error)
|
||||
return;
|
||||
LLOG("BZLIB Put " << size);
|
||||
const char *p = reinterpret_cast<const char *>(ptr);
|
||||
while(size) {
|
||||
int psz = (int) min(size, INT_MAX / 4);
|
||||
if(mode == DEFLATE)
|
||||
total += size;
|
||||
z.next_in = const_cast<char *>(p);
|
||||
z.avail_in = size;
|
||||
Pump(false);
|
||||
size -= psz;
|
||||
p += psz;
|
||||
}
|
||||
}
|
||||
|
||||
void Lib::PutOut(const void *ptr, int size)
|
||||
{
|
||||
LLOG("BZLIB PutOut " << out.GetCount());
|
||||
out.Cat((const char *)ptr, (int)size);
|
||||
}
|
||||
|
||||
void Lib::End()
|
||||
{
|
||||
LLOG("BZLIB End");
|
||||
if(mode != INFLATE)
|
||||
Pump(true);
|
||||
Free();
|
||||
}
|
||||
|
||||
void Lib::Free()
|
||||
{
|
||||
if(mode == INFLATE)
|
||||
BZ2_bzDecompressEnd(&z);
|
||||
else if(mode == DEFLATE)
|
||||
BZ2_bzCompressEnd(&z);
|
||||
mode = NONE;
|
||||
total = 0;
|
||||
}
|
||||
|
||||
void Lib::Init()
|
||||
{
|
||||
mode = NONE;
|
||||
SetError(false);
|
||||
rdall = true;
|
||||
eos = false;
|
||||
Zero(z);
|
||||
}
|
||||
|
||||
void Lib::Clear()
|
||||
{
|
||||
Free();
|
||||
Init();
|
||||
}
|
||||
|
||||
Lib& Lib::ChunkSize(int n)
|
||||
{
|
||||
ASSERT(n < INT_MAX / 4);
|
||||
output.Clear();
|
||||
chunk = n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Lib::Lib()
|
||||
{
|
||||
Init();
|
||||
z.bzalloc = bzalloc_new;
|
||||
z.bzfree = bzfree_new;
|
||||
z.opaque = 0;
|
||||
chunk = 4096;
|
||||
WhenOut = callback(this, &Lib::PutOut);
|
||||
compression_level = 9;
|
||||
}
|
||||
|
||||
Lib::~Lib()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
}
|
||||
|
||||
void BZ2Decompress(Stream& out, Stream& in, Gate<int, int> progress)
|
||||
|
|
@ -28,8 +198,8 @@ void BZ2Decompress(Stream& out, Stream& in, Gate<int, int> progress)
|
|||
return;
|
||||
bz_stream z;
|
||||
Zero(z);
|
||||
z.bzalloc = bzalloc_new;
|
||||
z.bzfree = bzfree_new;
|
||||
z.bzalloc = bz2::bzalloc_new;
|
||||
z.bzfree = bz2::bzfree_new;
|
||||
z.opaque = 0;
|
||||
if(BZ2_bzDecompressInit(&z, 0, 0) != BZ_OK)
|
||||
{
|
||||
|
|
@ -80,8 +250,8 @@ void BZ2Compress(Stream& out, Stream& in, Gate<int, int> progress)
|
|||
enum { BUF_SIZE = 65536 };
|
||||
Buffer<char> input(BUF_SIZE), output(BUF_SIZE);
|
||||
bz_stream z;
|
||||
z.bzalloc = bzalloc_new;
|
||||
z.bzfree = bzfree_new;
|
||||
z.bzalloc = bz2::bzalloc_new;
|
||||
z.bzfree = bz2::bzfree_new;
|
||||
z.opaque = 0;
|
||||
if(BZ2_bzCompressInit(&z, 9, 0, 30) != BZ_OK)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue