| 30 | } |
| 31 | |
| 32 | void QuickLZCompress(TVector<char>* dst) { |
| 33 | if (!dst || dst->empty()) |
| 34 | return; |
| 35 | TStringBuf srcdata{dst->data(), dst->size()}; |
| 36 | if (srcdata.size() > MIN_SIZE_TO_PACK || (srcdata.size() >= SIZEOF_SIGNATURE && *(int*)srcdata.data() == N_SIGNATURE)) { |
| 37 | const ICodec* usedCodec = GetCodec(); |
| 38 | TVector<char> packed; |
| 39 | packed.yresize(SIZEOF_SIGNATURE); |
| 40 | *(int*)(packed.data()) = N_SIGNATURE; |
| 41 | /* Blocking for data >2Gb as most codecs don't support such big data chunks. |
| 42 | Stream format as follows: |
| 43 | | signature 4 bytes | LengthOfBlock1 4 bytes | Block1 compressed data | LengthOfBlock2 4 bytes| Block2 compressed data | ... | |
| 44 | */ |
| 45 | for (size_t i = 0; i < srcdata.size(); i += BLOCK_SIZE) { |
| 46 | TStringBuf srcDataBlock{dst->data() + i, Min((size_t)(dst->size() - i), (size_t)BLOCK_SIZE)}; |
| 47 | size_t packedPreviousSize = packed.size(); |
| 48 | packed.yresize(packedPreviousSize + sizeof(TBlockLen) + usedCodec->MaxCompressedLength(srcDataBlock)); |
| 49 | TBlockLen packedBlockSize = usedCodec->Compress(srcDataBlock, (packed.data() + packedPreviousSize + sizeof(TBlockLen))); |
| 50 | *(TBlockLen*)(packed.data() + packedPreviousSize) = packedBlockSize; |
| 51 | packed.yresize(packedPreviousSize + sizeof(TBlockLen) + packedBlockSize); |
| 52 | } |
| 53 | dst->swap(packed); |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | void QuickLZDecompress(TVector<char>* dst) { |
| 58 | if (!dst) { |
no test coverage detected