123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- /*##############################################################################
- HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ############################################################################## */
- #include "platform.h"
- #include "jfcmp.hpp"
- #include "jlz4.hpp"
- #include "lz4.h"
- /* Format:
- size32_t totalexpsize;
- { size32_t subcmpsize; bytes subcmpdata; }
- size32_t trailsize; bytes traildata; // unexpanded
- */
- class jlib_decl CLZ4Compressor : public CFcmpCompressor
- {
- virtual void setinmax()
- {
- inmax = blksz-outlen-sizeof(size32_t);
- if (inmax<256)
- trailing = true; // too small to bother compressing
- else
- {
- trailing = false;
- size32_t slack = LZ4_COMPRESSBOUND(inmax) - inmax;
- int inmax2 = inmax - (slack + sizeof(size32_t));
- if (inmax2<256)
- trailing = true;
- else
- inmax = inmax2;
- }
- }
- virtual void flushcommitted()
- {
- // only does non trailing
- if (trailing)
- return;
- size32_t toflush = (inlenblk==COMMITTED)?inlen:inlenblk;
- if (toflush == 0)
- return;
- if (toflush < 256)
- {
- trailing = true;
- return;
- }
- size32_t outSzRequired = outlen+sizeof(size32_t)*2+LZ4_COMPRESSBOUND(toflush);
- if (!dynamicOutSz)
- assertex(outSzRequired<=blksz);
- else
- {
- if (outSzRequired>dynamicOutSz)
- {
- verifyex(outBufMb->ensureCapacity(outBufStart+outSzRequired));
- dynamicOutSz = outBufMb->capacity();
- outbuf = ((byte *)outBufMb->bufferBase()+outBufStart);
- }
- }
- size32_t *cmpsize = (size32_t *)(outbuf+outlen);
- byte *out = (byte *)(cmpsize+1);
- *cmpsize = LZ4_compress_default((const char *)inbuf, (char *)out, toflush, LZ4_COMPRESSBOUND(toflush));
- if (*cmpsize && *cmpsize<toflush)
- {
- *(size32_t *)outbuf += toflush;
- outlen += *cmpsize+sizeof(size32_t);
- if (inlenblk==COMMITTED)
- inlen = 0;
- else
- {
- inlen -= inlenblk;
- memmove(inbuf,inbuf+toflush,inlen);
- }
- setinmax();
- return;
- }
- trailing = true;
- }
- };
- class jlib_decl CLZ4Expander : public CFcmpExpander
- {
- public:
- virtual void expand(void *buf)
- {
- if (!outlen)
- return;
- if (buf)
- {
- if (bufalloc)
- free(outbuf);
- bufalloc = 0;
- outbuf = (unsigned char *)buf;
- }
- else if (outlen>bufalloc)
- {
- if (bufalloc)
- free(outbuf);
- bufalloc = outlen;
- outbuf = (unsigned char *)malloc(bufalloc);
- if (!outbuf)
- throw MakeStringException(MSGAUD_operator,0, "Out of memory in LZ4Expander::expand, requesting %d bytes", bufalloc);
- }
- size32_t done = 0;
- for (;;)
- {
- const size32_t szchunk = *in;
- in++;
- if (szchunk+done<outlen)
- {
- size32_t written = LZ4_decompress_safe((const char *)in, (char *)((byte *)buf+done), szchunk, outlen-done);
- done += written;
- if (!written||(done>outlen))
- throw MakeStringException(0, "LZ4Expander - corrupt data(1) %d %d",written,szchunk);
- }
- else
- {
- if (szchunk+done!=outlen)
- throw MakeStringException(0, "LZ4Expander - corrupt data(2) %d %d",szchunk,outlen);
- memcpy((byte *)buf+done,in,szchunk);
- break;
- }
- in = (const size32_t *)(((const byte *)in)+szchunk);
- }
- }
- };
- void LZ4CompressToBuffer(MemoryBuffer & out, size32_t len, const void * src)
- {
- size32_t outbase = out.length();
- out.append(len);
- DelayedMarker<size32_t> cmpSzMarker(out);
- void *cmpData = out.reserve(LZ4_COMPRESSBOUND(len));
- if (len < 64)
- memcpy(cmpData, src, len);
- else
- {
- size32_t cmpSz = LZ4_compress_default((const char *)src, (char *)cmpData, len, LZ4_COMPRESSBOUND(len));
- if (!cmpSz)
- memcpy(cmpData, src, len);
- else
- len = cmpSz;
- }
- cmpSzMarker.write(len);
- out.setLength(outbase+len+sizeof(size32_t)*2);
- }
- void LZ4DecompressToBuffer(MemoryBuffer & out, const void * src)
- {
- size32_t *sz = (size32_t *)src;
- size32_t expsz = *(sz++);
- size32_t cmpsz = *(sz++);
- void *o = out.reserve(expsz);
- if (cmpsz!=expsz)
- {
- size32_t written = LZ4_decompress_safe((const char *)sz, (char *)o, cmpsz, expsz);
- if (written!=expsz)
- throw MakeStringException(0, "LZ4DecompressToBuffer - corrupt data(1) %d %d",written,expsz);
- }
- else
- memcpy(o,sz,expsz);
- }
- void LZ4DecompressToBuffer(MemoryBuffer & out, MemoryBuffer & in)
- {
- size32_t expsz;
- size32_t cmpsz;
- in.read(expsz).read(cmpsz);
- void *o = out.reserve(expsz);
- if (cmpsz!=expsz)
- {
- size32_t written = LZ4_decompress_safe((const char *)in.readDirect(cmpsz), (char *)o, cmpsz, expsz);
- if (written!=expsz)
- throw MakeStringException(0, "LZ4DecompressToBuffer - corrupt data(3) %d %d",written,expsz);
- }
- else
- memcpy(o,in.readDirect(cmpsz),expsz);
- }
- void LZ4DecompressToAttr(MemoryAttr & out, const void * src)
- {
- size32_t *sz = (size32_t *)src;
- size32_t expsz = *(sz++);
- size32_t cmpsz = *(sz++);
- void *o = out.allocate(expsz);
- if (cmpsz!=expsz)
- {
- size32_t written = LZ4_decompress_safe((const char *)sz, (char *)o, cmpsz, expsz);
- if (written!=expsz)
- throw MakeStringException(0, "LZ4DecompressToBuffer - corrupt data(2) %d %d",written,expsz);
- }
- else
- memcpy(o,sz,expsz);
- }
- void LZ4DecompressToBuffer(MemoryAttr & out, MemoryBuffer & in)
- {
- size32_t expsz;
- size32_t cmpsz;
- in.read(expsz).read(cmpsz);
- void *o = out.allocate(expsz);
- if (cmpsz!=expsz)
- {
- size32_t written = LZ4_decompress_safe((const char *)in.readDirect(cmpsz), (char *)o, cmpsz, expsz);
- if (written!=expsz)
- throw MakeStringException(0, "LZ4DecompressToBuffer - corrupt data(4) %d %d",written,expsz);
- }
- else
- memcpy(o,in.readDirect(cmpsz),expsz);
- }
- ICompressor *createLZ4Compressor()
- {
- return new CLZ4Compressor;
- }
- IExpander *createLZ4Expander()
- {
- return new CLZ4Expander;
- }
- #define LZ4STRMCOMPRESSEDFILEFLAG (I64C(0xc129b02d53545e91))
- class CLZ4Stream : public CFcmpStream
- {
- bool load()
- {
- bufpos = 0;
- bufsize = 0;
- if (expOffset==expSize)
- return false;
- size32_t sz[2];
- if (baseio->read(cmpOffset,sizeof(size32_t)*2,&sz)!=sizeof(size32_t)*2)
- return false;
- bufsize = sz[0];
- if (!bufsize)
- return false;
- cmpOffset += sizeof(size32_t)*2;
- if (ma.length()<bufsize)
- ma.allocate(bufsize);
- MemoryAttr cmpma;
- byte *cmpbuf = (byte *)cmpma.allocate(sz[1]);
- if (baseio->read(cmpOffset,sz[1],cmpbuf)!=sz[1])
- throw MakeStringException(-1,"CLZ4Stream: file corrupt.1");
- size32_t amnt = LZ4_decompress_safe((const char *)cmpbuf, (char *)ma.bufferBase(), sz[1], bufsize);
- if (amnt!=bufsize)
- throw MakeStringException(-1,"CLZ4Stream: file corrupt.2");
- cmpOffset += sz[1];
- return true;
- }
- void save()
- {
- if (bufsize)
- {
- MemoryAttr dstma;
- byte *dst = (byte *)dstma.allocate(sizeof(size32_t)*2+LZ4_COMPRESSBOUND(bufsize));
- size32_t sz = LZ4_compress_default((const char *)ma.get(), (char *)(sizeof(size32_t)*2+dst), bufsize, LZ4_COMPRESSBOUND(bufsize));
- if (!sz)
- {
- sz = bufsize;
- memcpy((sizeof(size32_t)*2+dst), ma.get(), bufsize);
- }
- memcpy(dst,&bufsize,sizeof(size32_t));
- memcpy(dst+sizeof(size32_t),&sz,sizeof(size32_t));
- baseio->write(cmpOffset,sz+sizeof(size32_t)*2,dst);
- cmpOffset += sz+sizeof(size32_t)*2;
- }
- bufsize = 0;
- }
- public:
- CLZ4Stream() { compType = LZ4STRMCOMPRESSEDFILEFLAG; }
- virtual ~CLZ4Stream() { flush(); }
- };
- IFileIOStream *createLZ4StreamRead(IFileIO *base)
- {
- Owned<CLZ4Stream> strm = new CLZ4Stream();
- if (strm->attach(base))
- return strm.getClear();
- return NULL;
- }
- IFileIOStream *createLZ4StreamWrite(IFileIO *base)
- {
- Owned<CLZ4Stream> strm = new CLZ4Stream();
- strm->create(base);
- return strm.getClear();
- }
|