1 #include "lz4.h"
2
3 namespace Upp {
4
Open(Stream & out_)5 void LZ4CompressStream::Open(Stream& out_)
6 {
7 out = &out_;
8 ClearError();
9 pos = 0;
10 xxh.Reset();
11 Alloc();
12 pos = 0;
13 byte h[7];
14 Poke32le(h, LZ4F_MAGIC);
15 h[4] = LZ4F_VERSION | LZ4F_BLOCKINDEPENDENCE | LZ4F_CONTENTCHECKSUM;
16 h[5] = LZ4F_MAXSIZE_1024KB;
17 h[6] = xxHash(h + 4, 2) >> 8;
18 out->Put(h, 7);
19 }
20
Alloc()21 void LZ4CompressStream::Alloc()
22 {
23 int N = 16;
24 int sz = concurrent ? N * BLOCK_BYTES : BLOCK_BYTES;
25 buffer.Alloc(sz);
26 outbuf.Alloc(N * LZ4_compressBound(BLOCK_BYTES));
27 outsz.Alloc(N);
28 Stream::buffer = ~buffer;
29 wrlim = ~buffer + sz;
30 ptr = ~buffer;
31 }
32
Co(bool b)33 void LZ4CompressStream::Co(bool b)
34 {
35 FlushOut();
36 concurrent = b;
37 Alloc();
38 }
39
FlushOut()40 void LZ4CompressStream::FlushOut()
41 {
42 if(ptr == (byte *)~buffer)
43 return;
44
45 CoWork co;
46
47 int osz = LZ4_compressBound(BLOCK_BYTES);
48 byte *t = ~outbuf;
49 int ii = 0;
50 for(byte *s = ~buffer; s < ptr; s += BLOCK_BYTES) {
51 int origsize = min((int)BLOCK_BYTES, int(ptr - s));
52 if(concurrent)
53 co & [=] {
54 outsz[ii] = LZ4_compress_default((char *)s, (char *)t, origsize, osz);
55 };
56 else
57 outsz[ii] = LZ4_compress_default((char *)s, (char *)t, origsize, osz);
58 ii++;
59 t += osz;
60 }
61
62 if(concurrent)
63 co.Finish();
64
65 byte *s = ~buffer;
66 t = ~outbuf;
67 for(int i = 0; i < ii; i++) {
68 int origsize = min((int)BLOCK_BYTES, int(ptr - s));
69 int clen = outsz[i];
70 if(clen < 0) {
71 SetError();
72 return;
73 }
74 if(clen >= origsize || clen == 0) {
75 out->Put32le(0x80000000 | origsize);
76 out->Put(s, origsize);
77 }
78 else {
79 out->Put32le(clen);
80 out->Put(t, clen);
81 }
82 s += BLOCK_BYTES;
83 t += osz;
84 }
85
86 int origsize = int(ptr - ~buffer);
87 xxh.Put(~buffer, origsize);
88 pos += origsize;
89 ptr = ~buffer;
90 }
91
Close()92 void LZ4CompressStream::Close()
93 {
94 if(out) {
95 FlushOut();
96 out->Put32le(0);
97 out->Put32le(xxh.Finish());
98 out = NULL;
99 }
100 }
101
IsOpen() const102 bool LZ4CompressStream::IsOpen() const
103 {
104 return out && out->IsOpen();
105 }
106
_Put(int w)107 void LZ4CompressStream::_Put(int w)
108 {
109 FlushOut();
110 *ptr++ = w;
111 }
112
_Put(const void * data,dword size)113 void LZ4CompressStream::_Put(const void *data, dword size)
114 {
115 const char *s = reinterpret_cast<const char *>(data);
116
117 while(size > 0) {
118 if(IsError() || out && out->IsError())
119 return;
120 dword n = dword(wrlim - ptr);
121 if(size >= n) {
122 memcpy(ptr, s, n);
123 ptr = wrlim;
124 FlushOut();
125 size -= n;
126 s += n;
127 }
128 else {
129 memcpy(ptr, s, size);
130 ptr += size;
131 break;
132 }
133 }
134 }
135
LZ4CompressStream()136 LZ4CompressStream::LZ4CompressStream()
137 {
138 style = STRM_WRITE;
139 concurrent = false;
140 out = NULL;
141 }
142
~LZ4CompressStream()143 LZ4CompressStream::~LZ4CompressStream()
144 {
145 Close();
146 }
147
148 };
149