diff --git a/uppsrc/Core/xxHsh.cpp b/uppsrc/Core/xxHsh.cpp index f0213a8aa..efadbba47 100644 --- a/uppsrc/Core/xxHsh.cpp +++ b/uppsrc/Core/xxHsh.cpp @@ -17,7 +17,6 @@ void xxHashStream::Reset(dword seed) void xxHashStream::Out(const void *data, dword size) { - RTIMING("xxh2"); XXH32_update((XXH32_state_t *)context, data, size); } diff --git a/uppsrc/plugin/lz4/Compress.cpp b/uppsrc/plugin/lz4/Compress.cpp index 85a5bb178..99ccb2531 100644 --- a/uppsrc/plugin/lz4/Compress.cpp +++ b/uppsrc/plugin/lz4/Compress.cpp @@ -1,119 +1,112 @@ #include "lz4.h" -#ifdef flagCOMPLEXLZ4 +#ifndef flagCOMPLEXLZ4 #define LLOG(x) // LOG(x) namespace Upp { -void LZ4CompressStream::Init() +void LZ4CompressStream::Open(Stream& out_) { + out = &out_; ClearError(); pos = 0; - header = false; xxh.Reset(); -#ifdef _MULTITHREADED - outblock = inblock = 0; -#endif - SetupBuffer(); + Alloc(); + pos = 0; + byte h[7]; + Poke32le(h, LZ4F_MAGIC); + h[4] = LZ4F_VERSION | LZ4F_BLOCKINDEPENDENCE | LZ4F_CONTENTCHECKSUM; + h[5] = LZ4F_MAXSIZE_1024KB; + h[6] = xxHash(h + 4, 2) >> 8; + out->Put(h, 7); } -void LZ4CompressStream::FinishBlock(char *outbuf, int clen, const char *origdata, int origsize) +void LZ4CompressStream::Alloc() { - if(IsError() || out && out->IsError()) - return; - if(clen < 0) { - SetError(); - return; - } - if(clen >= origsize) { - Poke32le(outbuf, 0x80000000 | origsize); - memcpy(outbuf + 4, origdata, origsize); - out->Put(outbuf, origsize + 4); - } - else { - Poke32le(outbuf, clen); - out->Put(outbuf, clen + 4); - } + int N = 16; + int sz = concurrent ? N * BLOCK_BYTES : BLOCK_BYTES; + buffer.Alloc(sz); + outbuf.Alloc(N * LZ4_compressBound(BLOCK_BYTES)); + outsz.Alloc(N); + wrlim = ~buffer + sz; + ptr = ~buffer; } -void LZ4CompressStream::SetupBuffer() +void LZ4CompressStream::Concurrent(bool b) { - buffer.SetCount(BLOCK_BYTES); - wrlim = (byte *)~buffer + BLOCK_BYTES; - ptr = (byte *)~buffer; + FlushOut(); + concurrent = b; + Alloc(); } void LZ4CompressStream::FlushOut() { - if(!header) { - byte h[7]; - Poke32le(h, LZ4F_MAGIC); - h[4] = LZ4F_VERSION | LZ4F_BLOCKINDEPENDENCE | LZ4F_CONTENTCHECKSUM; - h[5] = LZ4F_MAXSIZE_1024KB; - h[6] = xxHash(h + 4, 2) >> 8; - out->Put(h, 7); - header = true; - } - if(ptr == (byte *)~buffer) return; - - int origsize = int((char *)ptr - ~buffer); + CoWork co; + + int osz = LZ4_compressBound(BLOCK_BYTES); + byte *t = ~outbuf; + int ii = 0; + for(byte *s = ~buffer; s < ptr; s += BLOCK_BYTES) { + int origsize = min((int)BLOCK_BYTES, int(ptr - s)); + if(concurrent) + co & [=] { + outsz[ii] = LZ4_compress_default((char *)s, (char *)t, origsize, osz); + }; + else + outsz[ii] = LZ4_compress_default((char *)s, (char *)t, origsize, osz); + ii++; + t += osz; + } + + if(concurrent) + co.Finish(); + + byte *s = ~buffer; + t = ~outbuf; + for(int i = 0; i < ii; i++) { + int origsize = min((int)BLOCK_BYTES, int(ptr - s)); + int clen = outsz[i]; + if(clen < 0) { + SetError(); + return; + } + if(clen >= origsize || clen == 0) { + out->Put32le(0x80000000 | origsize); + out->Put(s, origsize); + } + else { + out->Put32le(clen); + out->Put(t, clen); + } + s += BLOCK_BYTES; + t += osz; + } + + int origsize = int(ptr - ~buffer); + xxh.Put(~buffer, origsize); pos += origsize; - WhenPos(pos); - -#ifdef _MULTITHREADED - if(co) { - String bs = buffer; - int inblk = inblock++; - CoWork::Start([=] { - Buffer outbuf(4 + LZ4_compressBound(BLOCK_BYTES)); - int clen = LZ4_compress(~bs, ~outbuf + 4, origsize); - Mutex::Lock __(lock); - while(outblock != inblk) - cond.Wait(lock); - FinishBlock(outbuf, clen, ~bs, origsize); - outblock++; - cond.Broadcast(); - }); - xxh.Put(~bs, origsize); - SetupBuffer(); - } - else -#endif - { - Buffer outbuf(4 + LZ4_compressBound(BLOCK_BYTES)); - xxh.Put(~buffer, origsize); - int clen = LZ4_compress(~buffer, ~outbuf + 4, origsize); - FinishBlock(outbuf, clen, buffer, origsize); - SetupBuffer(); - } + ptr = ~buffer; } void LZ4CompressStream::Close() { ASSERT(compress >= 0); - FlushOut(); -#ifdef _MULTITHREADED - if(co) { - Mutex::Lock __(lock); - while(outblock != inblock) - cond.Wait(lock); + if(out) { + FlushOut(); + out->Put32le(0); + out->Put32le(xxh.Finish()); + out = NULL; } -#endif - byte h[8]; - Poke32le(h, 0); - Poke32le(h + 4, xxh.Finish()); - out->Put(h, 8); - buffer.Clear(); } bool LZ4CompressStream::IsOpen() const { - return (!out || out->IsOpen()) && buffer.GetCount(); + return out && out->IsOpen(); } void LZ4CompressStream::_Put(int w) @@ -133,7 +126,7 @@ void LZ4CompressStream::_Put(const void *data, dword size) while(size > 0) { if(IsError() || out && out->IsError()) return; - dword n = BLOCK_BYTES - int((char *)ptr - ~buffer); + dword n = dword(wrlim - ptr); if(size >= n) { memcpy(ptr, s, n); ptr = wrlim; @@ -152,14 +145,14 @@ void LZ4CompressStream::_Put(const void *data, dword size) LZ4CompressStream::LZ4CompressStream() { #ifdef _MULTITHREADED - co = false; + concurrent = false; #endif out = NULL; - Init(); } LZ4CompressStream::~LZ4CompressStream() { + Close(); } }; diff --git a/uppsrc/plugin/lz4/Compress2.cpp b/uppsrc/plugin/lz4/Compress2.cpp deleted file mode 100644 index 99ccb2531..000000000 --- a/uppsrc/plugin/lz4/Compress2.cpp +++ /dev/null @@ -1,160 +0,0 @@ -#include "lz4.h" - -#ifndef flagCOMPLEXLZ4 - -#define LLOG(x) // LOG(x) - -namespace Upp { - -void LZ4CompressStream::Open(Stream& out_) -{ - out = &out_; - ClearError(); - pos = 0; - xxh.Reset(); - Alloc(); - pos = 0; - byte h[7]; - Poke32le(h, LZ4F_MAGIC); - h[4] = LZ4F_VERSION | LZ4F_BLOCKINDEPENDENCE | LZ4F_CONTENTCHECKSUM; - h[5] = LZ4F_MAXSIZE_1024KB; - h[6] = xxHash(h + 4, 2) >> 8; - out->Put(h, 7); -} - -void LZ4CompressStream::Alloc() -{ - int N = 16; - int sz = concurrent ? N * BLOCK_BYTES : BLOCK_BYTES; - buffer.Alloc(sz); - outbuf.Alloc(N * LZ4_compressBound(BLOCK_BYTES)); - outsz.Alloc(N); - wrlim = ~buffer + sz; - ptr = ~buffer; -} - -void LZ4CompressStream::Concurrent(bool b) -{ - FlushOut(); - concurrent = b; - Alloc(); -} - -void LZ4CompressStream::FlushOut() -{ - if(ptr == (byte *)~buffer) - return; - - CoWork co; - - int osz = LZ4_compressBound(BLOCK_BYTES); - byte *t = ~outbuf; - int ii = 0; - for(byte *s = ~buffer; s < ptr; s += BLOCK_BYTES) { - int origsize = min((int)BLOCK_BYTES, int(ptr - s)); - if(concurrent) - co & [=] { - outsz[ii] = LZ4_compress_default((char *)s, (char *)t, origsize, osz); - }; - else - outsz[ii] = LZ4_compress_default((char *)s, (char *)t, origsize, osz); - ii++; - t += osz; - } - - if(concurrent) - co.Finish(); - - byte *s = ~buffer; - t = ~outbuf; - for(int i = 0; i < ii; i++) { - int origsize = min((int)BLOCK_BYTES, int(ptr - s)); - int clen = outsz[i]; - if(clen < 0) { - SetError(); - return; - } - if(clen >= origsize || clen == 0) { - out->Put32le(0x80000000 | origsize); - out->Put(s, origsize); - } - else { - out->Put32le(clen); - out->Put(t, clen); - } - s += BLOCK_BYTES; - t += osz; - } - - int origsize = int(ptr - ~buffer); - xxh.Put(~buffer, origsize); - pos += origsize; - WhenPos(pos); - ptr = ~buffer; -} - -void LZ4CompressStream::Close() -{ - ASSERT(compress >= 0); - if(out) { - FlushOut(); - out->Put32le(0); - out->Put32le(xxh.Finish()); - out = NULL; - } -} - -bool LZ4CompressStream::IsOpen() const -{ - return out && out->IsOpen(); -} - -void LZ4CompressStream::_Put(int w) -{ - FlushOut(); - *ptr++ = w; -} - -void LZ4CompressStream::_Put(const void *data, dword size) -{ - LLOG("Put " << size); - - ASSERT(compress >= 0); - - const char *s = reinterpret_cast(data); - - while(size > 0) { - if(IsError() || out && out->IsError()) - return; - dword n = dword(wrlim - ptr); - if(size >= n) { - memcpy(ptr, s, n); - ptr = wrlim; - FlushOut(); - size -= n; - s += n; - } - else { - memcpy(ptr, s, size); - ptr += size; - break; - } - } -} - -LZ4CompressStream::LZ4CompressStream() -{ -#ifdef _MULTITHREADED - concurrent = false; -#endif - out = NULL; -} - -LZ4CompressStream::~LZ4CompressStream() -{ - Close(); -} - -}; - -#endif \ No newline at end of file diff --git a/uppsrc/plugin/lz4/Decompress.cpp b/uppsrc/plugin/lz4/Decompress.cpp index dd667465c..7c85935a4 100644 --- a/uppsrc/plugin/lz4/Decompress.cpp +++ b/uppsrc/plugin/lz4/Decompress.cpp @@ -65,7 +65,6 @@ bool LZ4DecompressStream::Open(Stream& in_) bool LZ4DecompressStream::Next() { - RTIMING("Next"); if(ii < count) { pos += dlen; ptr = (byte *)~wb[ii].d; @@ -105,7 +104,6 @@ void LZ4DecompressStream::Fetch() return; } if(!t.c) { - RTIMING("Alloc"); t.c.Alloc(maxblock); t.d.Alloc(maxblock); } @@ -117,12 +115,10 @@ void LZ4DecompressStream::Fetch() } } else { - { RTIMING("GetAll"); if(!in->GetAll(~t.c, t.clen)) { SetError(); return; } - } #ifdef _MULTITHREADED if(concurrent) co & [=, &error] { @@ -135,7 +131,6 @@ void LZ4DecompressStream::Fetch() else #endif { - RTIMING("LZ4 decompress"); t.dlen = LZ4_decompress_safe(~t.c, ~t.d, t.clen, maxblock); if(t.dlen < 0) error = true; @@ -151,10 +146,8 @@ void LZ4DecompressStream::Fetch() if(error) SetError(); else { - for(int i = 0; i < count; i++) { - RTIMING("xxh"); + for(int i = 0; i < count; i++) xxh.Put(wb[i].d, wb[i].dlen); - } if(last) { if(in->Get32le() != xxh.Finish()) SetError(); @@ -187,22 +180,19 @@ int LZ4DecompressStream::_Get() dword LZ4DecompressStream::_Get(void *data, dword size) { - RTIMING("_Get"); byte *t = (byte *)data; while(size) { if(IsError() || in->IsError() || ptr == rdlim && ii == count && eof) break; dword n = dword(rdlim - ptr); if(size < n) { - RTIMING("memcpy1"); memcpy(t, ptr, size); t += size; ptr += size; break; } else { - { RTIMING("memcpy2"); - memcpy(t, ptr, n); } + memcpy(t, ptr, n); t += n; size -= n; ptr = rdlim; diff --git a/uppsrc/plugin/lz4/lz4.h b/uppsrc/plugin/lz4/lz4.h index 42c9c79c5..e11b0a301 100644 --- a/uppsrc/plugin/lz4/lz4.h +++ b/uppsrc/plugin/lz4/lz4.h @@ -24,114 +24,6 @@ enum { LZ4F_MAXSIZE_4096KB = 0x70, }; -class Lz4 { // Filter is deprecated, use Streams instead, will be removed soon - StringBuffer buffer; // to be able to pass as String - int8 compress; - bool error; - - enum { BLOCK_BYTES = 1024 * 1024 }; - - xxHashStream xxh; - int maxblock; - int pos; - int blockchksumsz; - bool header; - byte lz4hdr; - String header_data; - - String out; - -#ifdef _MULTITHREADED - bool parallel; - CoWork co; - Mutex lock; - ConditionVariable cond; - int outblock; - int inblock; -#endif - - void TryHeader(); - - void Init(); - void FinishBlock(char *outbuf, int clen, const char *origdata, int origsize); - void FlushOut(); - - void PutOut(const void *ptr, int size); - -public: - Callback2 WhenOut; - - 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(); } - - void Compress(); - void Decompress(); - -#ifdef _MUTLITHREADED - void Parallel(bool b = true) { parallel = b; } -#endif - - bool IsError() const { return error; } - - Lz4(); - ~Lz4(); -}; - -#ifdef flagCOMPLEXLZ4 -class LZ4CompressStream : public Stream { -public: - virtual void Close(); - virtual bool IsOpen() const; - -protected: - virtual void _Put(int w); - virtual void _Put(const void *data, dword size); - - Stream *out; - - StringBuffer buffer; // to be able to pass it as String - - enum { BLOCK_BYTES = 1024 * 1024 }; - - xxHashStream xxh; - int blockchksumsz; - bool header; - byte lz4hdr; - String header_data; - -#ifdef _MULTITHREADED - bool co; - Mutex lock; - ConditionVariable cond; - int outblock; - int inblock; -#endif - - void Init(); - void SetupBuffer(); - void FinishBlock(char *outbuf, int clen, const char *origdata, int origsize); - void FlushOut(); - -public: - Event WhenPos; - -#ifdef _MULTITHREADED - void Concurrent(bool b = true) { co = b; } -#endif - void Open(Stream& out_) { Init(); out = &out_; } - - LZ4CompressStream(); - LZ4CompressStream(Stream& out) : LZ4CompressStream() { Open(out); } - ~LZ4CompressStream(); -}; -#else class LZ4CompressStream : public Stream { public: virtual void Close(); @@ -171,7 +63,6 @@ public: LZ4CompressStream(Stream& out) : LZ4CompressStream() { Open(out); } ~LZ4CompressStream(); }; -#endif class LZ4DecompressStream : public Stream { public: diff --git a/uppsrc/plugin/lz4/lz4.upp b/uppsrc/plugin/lz4/lz4.upp index 66afcd908..630d04662 100644 --- a/uppsrc/plugin/lz4/lz4.upp +++ b/uppsrc/plugin/lz4/lz4.upp @@ -5,9 +5,7 @@ uses file lz4.h, - lz4upp.cpp, Compress.cpp, - Compress2.cpp, Decompress.cpp, util.cpp, lib\LICENSE, diff --git a/uppsrc/plugin/lz4/lz4upp.cpp b/uppsrc/plugin/lz4/lz4upp.cpp deleted file mode 100644 index bd02c33ef..000000000 --- a/uppsrc/plugin/lz4/lz4upp.cpp +++ /dev/null @@ -1,290 +0,0 @@ -#include "lz4.h" - -#define LLOG(x) // LOG(x) - -namespace Upp { - -void Lz4::Init() -{ - error = false; - pos = 0; - header = false; - xxh.Reset(); -#ifdef _MULTITHREADED - outblock = inblock = 0; -#endif -} - -void Lz4::Compress() -{ - compress = 1; - buffer.SetCount(BLOCK_BYTES); - Init(); -} - -void Lz4::Decompress() -{ - compress = 0; - header_data.Clear(); - Init(); -} - -void Lz4::PutOut(const void *ptr, int size) -{ - LLOG("LZ4 PutOut " << out.GetCount()); - out.Cat((const char *)ptr, (int)size); -} - -void Lz4::FinishBlock(char *outbuf, int clen, const char *origdata, int origsize) -{ - RTIMING("FinishBlock"); - if(error) - return; - if(clen < 0) { - error = true; - return; - } - if(clen >= origsize) { - Poke32le(outbuf, 0x80000000 | origsize); - memcpy(outbuf + 4, origdata, origsize); - WhenOut(outbuf, origsize + 4); - } - else { - Poke32le(outbuf, clen); - WhenOut(outbuf, clen + 4); - } -} - -void Lz4::FlushOut() -{ - if(!header) { - byte h[7]; - Poke32le(h, LZ4F_MAGIC); - h[4] = LZ4F_VERSION | LZ4F_BLOCKINDEPENDENCE | LZ4F_CONTENTCHECKSUM; - h[5] = LZ4F_MAXSIZE_1024KB; - h[6] = xxHash(h + 4, 2) >> 8; - WhenOut(h, 7); - header = true; - maxblock = BLOCK_BYTES; - } - - if(!pos) - return; - - int origsize = pos; - - pos = 0; - -#ifdef _MULTITHREADED - if(parallel) { - String bs = buffer; - int inblk = inblock++; -// DLOG("Scheduling " << inblk); - co.Start([=] { - Buffer outbuf(4 + LZ4_compressBound(maxblock)); - int clen = LZ4_compress(~bs, ~outbuf + 4, origsize); - Mutex::Lock __(lock); - { RTIMING("Waiting for order"); - while(outblock != inblk) - cond.Wait(lock); - } - FinishBlock(outbuf, clen, ~bs, origsize); - outblock++; - cond.Broadcast(); - }); - RTIMING("xxh"); - xxh.Put(~bs, origsize); - buffer.SetCount(BLOCK_BYTES); - } - else -#endif - { - Buffer outbuf(4 + LZ4_compressBound(maxblock)); - xxh.Put(~buffer, origsize); - int clen = LZ4_compress(~buffer, ~outbuf + 4, origsize); - FinishBlock(outbuf, clen, buffer, origsize); - } -} - -void Lz4::End() -{ - ASSERT(compress >= 0); - if(compress) { - FlushOut(); - #ifdef _MULTITHREADED - Mutex::Lock __(lock); - { RTIMING("Waiting for order"); - while(outblock != inblock) - cond.Wait(lock); - } - #endif - byte h[8]; - Poke32le(h, 0); - Poke32le(h + 4, xxh.Finish()); - WhenOut(h, 8); - } - else - if(pos) - error = true; -} - -void Lz4::TryHeader() -{ - if(header_data.GetCount() < 7) - return; - - if(Peek32le(~header_data) != LZ4F_MAGIC) { - error = true; - return; - } - lz4hdr = header_data[4]; - if((lz4hdr & LZ4F_VERSIONMASK) != LZ4F_VERSION) { - error = true; - return; - } - if(!(lz4hdr & LZ4F_BLOCKINDEPENDENCE)) { - error = true; // dependent blocks not supported - return; - } - maxblock = header_data[5]; - maxblock = decode(maxblock & LZ4F_MAXSIZEMASK, - LZ4F_MAXSIZE_64KB, 1024 * 64, - LZ4F_MAXSIZE_256KB, 1024 * 256, - LZ4F_MAXSIZE_1024KB, 1024 * 1024, - LZ4F_MAXSIZE_4096KB, 1024 * 4096, - -1); - if(maxblock < 0) { - error = true; - return; - } - - if((lz4hdr & LZ4F_CONTENTSIZE) && header_data.GetCount() < 15) - return; // need to skip content length - - header = true; - blockchksumsz = 4 * !!(lz4hdr & LZ4F_BLOCKCHECKSUM); - buffer.SetCount(maxblock + 4 + blockchksumsz); -} - -void Lz4::Put(const void *ptr_, int size) -{ - LLOG("Put " << size); - - ASSERT(compress >= 0); - - if(error) - return; - - const char *ptr = reinterpret_cast(ptr_); - - if(compress) { - while(size > 0) { - if(error) - return; - int n = BLOCK_BYTES - pos; - if(size >= n) { - memcpy(~buffer + pos, ptr, n); - pos = BLOCK_BYTES; - FlushOut(); - size -= n; - ptr += n; - } - else { - memcpy(buffer + pos, ptr, size); - pos += size; - break; - } - } - } - else { - while(!header && size > 0 && !error) { - header_data.Cat(*ptr++); - size--; - TryHeader(); - } - while(size > 0 && !error) { // TODO might try to avoid memcpy - if(pos < 4) { // Get length first - int n = min(size, 4 - pos); - memcpy(~buffer + pos, ptr, n); - pos += n; - ptr += n; - size -= n; - } - else { - int count = Peek32le(~buffer); - int len = count & 0x7fffffff; - if(len > maxblock) { - error = true; - break; - } - if(count == 0) { // reached the end - int need = 4 - pos + 4; - if(size >= need) { // we have enough data for final checksum - memcpy(~buffer + pos, ptr, need); - if(Peek32le(~buffer + 4) != xxh.Finish()) { - error = true; - return; - } - size -= need; - ptr += need; - pos = 0; - return; // decompression completed - } - } - else { - int need = len - (pos - 4 - blockchksumsz); - if(size >= need) { // we have enough data to finish the block - memcpy(~buffer + pos, ptr, need); - const char *src = ~buffer + 4; - if(count & 0x80000000) { - WhenOut(src, len); - xxh.Put(src, len); - } - else { - int sz; - Buffer outbuf(maxblock); - sz = LZ4_decompress_safe(src, outbuf, len, maxblock); - if(sz < 0) { - error = true; - return; - } - WhenOut(outbuf, sz); - xxh.Put(outbuf, sz); - } - ptr += need; - size -= need; - pos = 0; - continue; - } - } - memcpy(~buffer + pos, ptr, size); - pos += size; - break; - } - } - } -} - -Lz4::Lz4() -{ - compress = -1; -#ifdef _MULTITHREADED - parallel = false; -#endif - - WhenOut = callback(this, &Lz4::PutOut); -} - -Lz4::~Lz4() -{ -} - -bool IsLZ4(Stream& s) -{ - int64 pos = s.GetPos(); - bool b = s.Get32le() == LZ4F_MAGIC; - s.Seek(pos); - return b; -} - -};