20
20
************************************************************************
21
21
**
22
22
** Module: u-compress.c
23
- ** Summary: interface to zlib compression
23
+ ** Summary: interface to zlib and or optional lzma compression
24
24
** Section: utility
25
25
** Notes:
26
26
**
27
27
***********************************************************************/
28
28
29
29
#include "sys-core.h"
30
30
#include "sys-zlib.h"
31
+ #ifdef USE_LZMA
32
+ #include "sys-lzma.h"
33
+ #endif // USE_LZMA
34
+
35
+
31
36
32
37
/*
33
38
* This number represents the top file size that,
134
139
//ENABLE_GC;
135
140
return output ;
136
141
}
142
+
143
+ #ifdef USE_LZMA
144
+
145
+ static void * SzAlloc (ISzAllocPtr p , size_t size ) { UNUSED (p ); return malloc (size ); }
146
+ static void SzFree (ISzAllocPtr p , void * address ) { UNUSED (p ); free (address ); }
147
+ const ISzAlloc g_Alloc = { SzAlloc , SzFree };
148
+
149
+ /***********************************************************************
150
+ **
151
+ */ REBSER * CompressLzma (REBSER * input , REBINT index , REBCNT len )
152
+ /*
153
+ ** Compress a binary (only) using LZMA compression.
154
+ ** data
155
+ ** /part
156
+ ** length
157
+ **
158
+ ***********************************************************************/
159
+ {
160
+ REBU64 size ;
161
+ REBU64 size_in = len ;
162
+ REBSER * output ;
163
+ REBINT err ;
164
+ REBYTE * dest ;
165
+ REBYTE out_size [sizeof (REBCNT )];
166
+
167
+ //@@ are these Sterling's magic numbers correct for LZMA too?
168
+ size = LZMA_PROPS_SIZE + size_in + (size_in > STERLINGS_MAGIC_NUMBER ? size_in / 10 + 12 : STERLINGS_MAGIC_FIX );
169
+ output = Make_Binary (size );
170
+
171
+ // so far hardcoded LZMA encoder properties... it would be nice to be able specify these by user if needed.
172
+ CLzmaEncProps props ;
173
+ LzmaEncProps_Init (& props );
174
+ props .level = 5 ;
175
+ props .dictSize = 0 ; // use default value
176
+ props .lc = -1 ; // -1 = default value
177
+ props .lp = -1 ;
178
+ props .pb = -1 ;
179
+ props .fb = -1 ;
180
+ props .numThreads = -1 ;
181
+ // Possible values:
182
+ // int level, /* 0 <= level <= 9, default = 5 */
183
+ // unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
184
+ // int lc, /* 0 <= lc <= 8, default = 3 */
185
+ // int lp, /* 0 <= lp <= 4, default = 0 */
186
+ // int pb, /* 0 <= pb <= 4, default = 2 */
187
+ // int fb, /* 5 <= fb <= 273, default = 32 */
188
+ // int numThreads /* 1 or 2, default = 2 */
189
+
190
+ dest = BIN_HEAD (output );
191
+
192
+ /* header: 5 bytes of LZMA properties */
193
+ REBU64 headerSize = LZMA_PROPS_SIZE ;
194
+ size -= headerSize ;
195
+
196
+ err = LzmaEncode (dest + headerSize , (SizeT * )& size , BIN_HEAD (input ) + index , (SizeT )len , & props , dest , & headerSize , 0 ,
197
+ NULL , & g_Alloc , & g_Alloc );
198
+ //printf("lzmaencode res: %i size: %u headerSize: %u\n", err, size, headerSize);
199
+ if (err ) {
200
+ if (err == SZ_ERROR_MEM ) Trap0 (RE_NO_MEMORY );
201
+ SET_INTEGER (DS_RETURN , err );
202
+ Trap1 (RE_BAD_PRESS , DS_RETURN ); //!!!provide error string descriptions
203
+ }
204
+ size += headerSize ;
205
+ //SET_STR_END(output, size);
206
+ SERIES_TAIL (output ) = size ;
207
+ REBCNT_To_Bytes (out_size , (REBCNT )len ); // Tag the size to the end.
208
+ Append_Series (output , (REBYTE * )out_size , sizeof (REBCNT ));
209
+ if (SERIES_AVAIL (output ) > 1024 ) // Is there wasted space?
210
+ output = Copy_Series (output ); // Trim it down if too big. !!! Revisit this based on mem alloc alg.
211
+ return output ;
212
+ }
213
+
214
+ /***********************************************************************
215
+ **
216
+ */ REBSER * DecompressLzma (REBSER * input , REBCNT index , REBINT len , REBCNT limit )
217
+ /*
218
+ ** Decompress a binary (only).
219
+ **
220
+ ***********************************************************************/
221
+ {
222
+ REBU64 size ;
223
+ REBU64 unpackSize ;
224
+ REBSER * output ;
225
+ REBINT err ;
226
+ REBYTE * dest ;
227
+ REBYTE * src = BIN_HEAD (input ) + index ;
228
+ REBU64 headerSize = LZMA_PROPS_SIZE ;
229
+ ELzmaStatus status = 0 ;
230
+
231
+ if (len < 0 || (index + len > BIN_LEN (input ))) len = BIN_LEN (input ) - index ;
232
+ if (len < 9 ) Trap0 (RE_PAST_END ); // !!! better msg needed
233
+ size = cast (REBU64 , len - LZMA_PROPS_SIZE ); // don't include size of properties
234
+
235
+ // Get the uncompressed size from the end.
236
+ unpackSize = cast (REBU64 , Bytes_To_REBCNT (BIN_SKIP (input , len ) - sizeof (REBCNT )));
237
+ if (limit > 0 && unpackSize > limit ) unpackSize = limit ;
238
+
239
+ output = Make_Binary (unpackSize );
240
+ dest = BIN_HEAD (output );
241
+
242
+ err = LzmaDecode (dest , (SizeT * )& unpackSize , src + LZMA_PROPS_SIZE , (SizeT * )& size , src , headerSize , LZMA_FINISH_ANY , & status , & g_Alloc );
243
+ //printf("lzmadecode res: %i status: %i size: %u\n", err, status, size);
244
+
245
+ if (err ) {
246
+ if (err == SZ_ERROR_MEM ) Trap0 (RE_NO_MEMORY );
247
+ SET_INTEGER (DS_RETURN , err );
248
+ Trap1 (RE_BAD_PRESS , DS_RETURN ); //!!!provide error string descriptions
249
+ }
250
+ SET_STR_END (output , unpackSize );
251
+ SERIES_TAIL (output ) = unpackSize ;
252
+ return output ;
253
+ }
254
+
255
+ #endif //USE_LZMA
0 commit comments