2 LZMA Compress/Decompress tool (LzmaCompress)
4 Based on LZMA SDK 19.00:
5 LzmaUtil.c -- Test application for LZMA compression
6 2019-02-21 : Igor Pavlov : Public domain
8 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #define _CRT_SECURE_NO_WARNINGS
19 #include "Sdk/C/Alloc.h"
20 #include "Sdk/C/7zFile.h"
21 #include "Sdk/C/7zVersion.h"
22 #include "Sdk/C/LzmaDec.h"
23 #include "Sdk/C/LzmaEnc.h"
24 #include "Sdk/C/Bra.h"
25 #include "CommonLib.h"
28 #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
36 const char *kCantReadMessage
= "Can not read input file";
37 const char *kCantWriteMessage
= "Can not write output file";
38 const char *kCantAllocateMessage
= "Can not allocate memory";
39 const char *kDataErrorMessage
= "Data error";
40 const char *kInvalidParamValMessage
= "Invalid parameter value";
42 static BoolInt mQuietMode
= False
;
43 static CONVERTER_TYPE mConType
= NoConverter
;
45 UINT64 mDictionarySize
= 28;
46 UINT64 mCompressionMode
= 2;
48 #define UTILITY_NAME "LzmaCompress"
49 #define UTILITY_MAJOR_VERSION 0
50 #define UTILITY_MINOR_VERSION 2
51 #define INTEL_COPYRIGHT \
52 "Copyright (c) 2009-2018, Intel Corporation. All rights reserved."
53 void PrintHelp(char *buffer
)
56 "\n" UTILITY_NAME
" - " INTEL_COPYRIGHT
"\n"
57 "Based on LZMA Utility " MY_VERSION_COPYRIGHT_DATE
"\n"
58 "\nUsage: LzmaCompress -e|-d [options] <inputFile>\n"
61 " -o FileName, --output FileName: specify the output filename\n"
62 " --f86: enable converter for x86 code\n"
63 " -v, --verbose: increase output messages\n"
64 " -q, --quiet: reduce output messages\n"
65 " --debug [0-9]: set debug level\n"
66 " -a: set compression mode 0 = fast, 1 = normal, default: 1 (normal)\n"
67 " d: sets Dictionary size - [0, 27], default: 24 (16MB)\n"
68 " --version: display the program version and exit\n"
69 " -h, --help: display this help text\n"
73 int PrintError(char *buffer
, const char *message
)
75 strcat(buffer
, "\nError: ");
76 strcat(buffer
, message
);
81 int PrintErrorNumber(char *buffer
, SRes val
)
83 sprintf(buffer
+ strlen(buffer
), "\nError code: %x\n", (unsigned)val
);
87 int PrintUserError(char *buffer
)
89 return PrintError(buffer
, "Incorrect command");
92 void PrintVersion(char *buffer
)
94 sprintf (buffer
, "%s Version %d.%d %s ", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
97 static SRes
Encode(ISeqOutStream
*outStream
, ISeqInStream
*inStream
, UInt64 fileSize
, CLzmaEncProps
*props
)
100 size_t inSize
= (size_t)fileSize
;
103 Byte
*filteredStream
= 0;
107 inBuffer
= (Byte
*)MyAlloc(inSize
);
111 return SZ_ERROR_INPUT_EOF
;
114 if (SeqInStream_Read(inStream
, inBuffer
, inSize
) != SZ_OK
) {
119 // we allocate 105% of original size + 64KB for output buffer
120 outSize
= (size_t)fileSize
/ 20 * 21 + (1 << 16);
121 outBuffer
= (Byte
*)MyAlloc(outSize
);
122 if (outBuffer
== 0) {
129 for (i
= 0; i
< 8; i
++)
130 outBuffer
[i
+ LZMA_PROPS_SIZE
] = (Byte
)(fileSize
>> (8 * i
));
133 if (mConType
!= NoConverter
)
135 filteredStream
= (Byte
*)MyAlloc(inSize
);
136 if (filteredStream
== 0) {
140 memcpy(filteredStream
, inBuffer
, inSize
);
142 if (mConType
== X86Converter
) {
145 x86_Convert_Init(x86State
);
146 x86_Convert(filteredStream
, (SizeT
) inSize
, 0, &x86State
, 1);
152 size_t outSizeProcessed
= outSize
- LZMA_HEADER_SIZE
;
153 size_t outPropsSize
= LZMA_PROPS_SIZE
;
155 res
= LzmaEncode(outBuffer
+ LZMA_HEADER_SIZE
, &outSizeProcessed
,
156 mConType
!= NoConverter
? filteredStream
: inBuffer
, inSize
,
157 props
, outBuffer
, &outPropsSize
, 0,
158 NULL
, &g_Alloc
, &g_Alloc
);
163 outSize
= LZMA_HEADER_SIZE
+ outSizeProcessed
;
166 if (outStream
->Write(outStream
, outBuffer
, outSize
) != outSize
)
167 res
= SZ_ERROR_WRITE
;
172 MyFree(filteredStream
);
177 static SRes
Decode(ISeqOutStream
*outStream
, ISeqInStream
*inStream
, UInt64 fileSize
)
180 size_t inSize
= (size_t)fileSize
;
186 UInt64 outSize64
= 0;
190 if (inSize
< LZMA_HEADER_SIZE
)
191 return SZ_ERROR_INPUT_EOF
;
193 inBuffer
= (Byte
*)MyAlloc(inSize
);
197 if (SeqInStream_Read(inStream
, inBuffer
, inSize
) != SZ_OK
) {
202 for (i
= 0; i
< 8; i
++)
203 outSize64
+= ((UInt64
)inBuffer
[LZMA_PROPS_SIZE
+ i
]) << (i
* 8);
205 outSize
= (size_t)outSize64
;
207 outBuffer
= (Byte
*)MyAlloc(outSize
);
208 if (outBuffer
== 0) {
217 inSizePure
= inSize
- LZMA_HEADER_SIZE
;
218 res
= LzmaDecode(outBuffer
, &outSize
, inBuffer
+ LZMA_HEADER_SIZE
, &inSizePure
,
219 inBuffer
, LZMA_PROPS_SIZE
, LZMA_FINISH_END
, &status
, &g_Alloc
);
224 if (mConType
== X86Converter
)
227 x86_Convert_Init(x86State
);
228 x86_Convert(outBuffer
, (SizeT
) outSize
, 0, &x86State
, 0);
231 if (outStream
->Write(outStream
, outBuffer
, outSize
) != outSize
)
232 res
= SZ_ERROR_WRITE
;
241 int main2(int numArgs
, const char *args
[], char *rs
)
243 CFileSeqInStream inStream
;
244 CFileOutStream outStream
;
247 BoolInt modeWasSet
= False
;
248 const char *inputFile
= NULL
;
249 const char *outputFile
= "file.tmp";
254 LzmaEncProps_Init(&props
);
255 LzmaEncProps_Normalize(&props
);
257 FileSeqInStream_CreateVTable(&inStream
);
258 File_Construct(&inStream
.file
);
260 FileOutStream_CreateVTable(&outStream
);
261 File_Construct(&outStream
.file
);
269 for (param
= 1; param
< numArgs
; param
++) {
270 if (strcmp(args
[param
], "-e") == 0 || strcmp(args
[param
], "-d") == 0) {
271 encodeMode
= (args
[param
][1] == 'e');
273 } else if (strcmp(args
[param
], "--f86") == 0) {
274 mConType
= X86Converter
;
275 } else if (strcmp(args
[param
], "-o") == 0 ||
276 strcmp(args
[param
], "--output") == 0) {
277 if (numArgs
< (param
+ 2)) {
278 return PrintUserError(rs
);
280 outputFile
= args
[++param
];
281 } else if (strcmp(args
[param
], "--debug") == 0) {
282 if (numArgs
< (param
+ 2)) {
283 return PrintUserError(rs
);
286 // For now we silently ignore this parameter to achieve command line
287 // parameter compatibility with other build tools.
290 } else if (strcmp(args
[param
], "-a") == 0) {
291 AsciiStringToUint64(args
[param
+ 1],FALSE
,&mCompressionMode
);
292 if ((mCompressionMode
== 0)||(mCompressionMode
== 1)){
293 props
.algo
= (int)mCompressionMode
;
297 return PrintError(rs
, kInvalidParamValMessage
);
299 } else if (strcmp(args
[param
], "d") == 0) {
300 AsciiStringToUint64(args
[param
+ 1],FALSE
,&mDictionarySize
);
301 if (mDictionarySize
<= 27) {
302 if (mDictionarySize
== 0) {
305 props
.dictSize
= (1 << mDictionarySize
);
310 return PrintError(rs
, kInvalidParamValMessage
);
313 strcmp(args
[param
], "-h") == 0 ||
314 strcmp(args
[param
], "--help") == 0
319 strcmp(args
[param
], "-v") == 0 ||
320 strcmp(args
[param
], "--verbose") == 0
323 // For now we silently ignore this parameter to achieve command line
324 // parameter compatibility with other build tools.
327 strcmp(args
[param
], "-q") == 0 ||
328 strcmp(args
[param
], "--quiet") == 0
331 } else if (strcmp(args
[param
], "--version") == 0) {
334 } else if (inputFile
== NULL
) {
335 inputFile
= args
[param
];
337 return PrintUserError(rs
);
341 if ((inputFile
== NULL
) || !modeWasSet
) {
342 return PrintUserError(rs
);
346 size_t t4
= sizeof(UInt32
);
347 size_t t8
= sizeof(UInt64
);
348 if (t4
!= 4 || t8
!= 8)
349 return PrintError(rs
, "Incorrect UInt32 or UInt64");
352 if (InFile_Open(&inStream
.file
, inputFile
) != 0)
353 return PrintError(rs
, "Can not open input file");
355 if (OutFile_Open(&outStream
.file
, outputFile
) != 0) {
356 File_Close(&inStream
.file
);
357 return PrintError(rs
, "Can not open output file");
360 File_GetLength(&inStream
.file
, &fileSize
);
365 printf("Encoding\n");
367 res
= Encode(&outStream
.vt
, &inStream
.vt
, fileSize
, &props
);
372 printf("Decoding\n");
374 res
= Decode(&outStream
.vt
, &inStream
.vt
, fileSize
);
377 File_Close(&outStream
.file
);
378 File_Close(&inStream
.file
);
382 if (res
== SZ_ERROR_MEM
)
383 return PrintError(rs
, kCantAllocateMessage
);
384 else if (res
== SZ_ERROR_DATA
)
385 return PrintError(rs
, kDataErrorMessage
);
386 else if (res
== SZ_ERROR_WRITE
)
387 return PrintError(rs
, kCantWriteMessage
);
388 else if (res
== SZ_ERROR_READ
)
389 return PrintError(rs
, kCantReadMessage
);
390 return PrintErrorNumber(rs
, res
);
395 int MY_CDECL
main(int numArgs
, const char *args
[])
397 char rs
[2000] = { 0 };
398 int res
= main2(numArgs
, args
, rs
);
399 if (strlen(rs
) > 0) {