1 /* LzmaUtil.c -- Test application for LZMA compression
2 2018-07-04 : Igor Pavlov : Public domain */
14 #include "7zVersion.h"
18 static const char * const kCantReadMessage
= "Can not read input file";
19 static const char * const kCantWriteMessage
= "Can not write output file";
20 static const char * const kCantAllocateMessage
= "Can not allocate memory";
21 static const char * const kDataErrorMessage
= "Data error";
23 static void PrintHelp(char *buffer
)
26 "\nLZMA-C " MY_VERSION_CPU
" : " MY_COPYRIGHT_DATE
"\n\n"
27 "Usage: lzma <e|d> inputFile outputFile\n"
32 static int PrintError(char *buffer
, const char *message
)
34 strcat(buffer
, "\nError: ");
35 strcat(buffer
, message
);
40 static int PrintErrorNumber(char *buffer
, SRes val
)
42 sprintf(buffer
+ strlen(buffer
), "\nError code: %x\n", (unsigned)val
);
46 static int PrintUserError(char *buffer
)
48 return PrintError(buffer
, "Incorrect command");
52 #define IN_BUF_SIZE (1 << 16)
53 #define OUT_BUF_SIZE (1 << 16)
56 static SRes
Decode2(CLzmaDec
*state
, ISeqOutStream
*outStream
, ISeqInStream
*inStream
,
59 int thereIsSize
= (unpackSize
!= (UInt64
)(Int64
)-1);
60 Byte inBuf
[IN_BUF_SIZE
];
61 Byte outBuf
[OUT_BUF_SIZE
];
62 size_t inPos
= 0, inSize
= 0, outPos
= 0;
69 RINOK(inStream
->Read(inStream
, inBuf
, &inSize
));
74 SizeT inProcessed
= inSize
- inPos
;
75 SizeT outProcessed
= OUT_BUF_SIZE
- outPos
;
76 ELzmaFinishMode finishMode
= LZMA_FINISH_ANY
;
78 if (thereIsSize
&& outProcessed
> unpackSize
)
80 outProcessed
= (SizeT
)unpackSize
;
81 finishMode
= LZMA_FINISH_END
;
84 res
= LzmaDec_DecodeToBuf(state
, outBuf
+ outPos
, &outProcessed
,
85 inBuf
+ inPos
, &inProcessed
, finishMode
, &status
);
87 outPos
+= outProcessed
;
88 unpackSize
-= outProcessed
;
91 if (outStream
->Write(outStream
, outBuf
, outPos
) != outPos
)
92 return SZ_ERROR_WRITE
;
96 if (res
!= SZ_OK
|| (thereIsSize
&& unpackSize
== 0))
99 if (inProcessed
== 0 && outProcessed
== 0)
101 if (thereIsSize
|| status
!= LZMA_STATUS_FINISHED_WITH_MARK
)
102 return SZ_ERROR_DATA
;
110 static SRes
Decode(ISeqOutStream
*outStream
, ISeqInStream
*inStream
)
118 /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
119 unsigned char header
[LZMA_PROPS_SIZE
+ 8];
121 /* Read and parse header */
123 RINOK(SeqInStream_Read(inStream
, header
, sizeof(header
)));
126 for (i
= 0; i
< 8; i
++)
127 unpackSize
+= (UInt64
)header
[LZMA_PROPS_SIZE
+ i
] << (i
* 8);
129 LzmaDec_Construct(&state
);
130 RINOK(LzmaDec_Allocate(&state
, header
, LZMA_PROPS_SIZE
, &g_Alloc
));
131 res
= Decode2(&state
, outStream
, inStream
, unpackSize
);
132 LzmaDec_Free(&state
, &g_Alloc
);
136 static SRes
Encode(ISeqOutStream
*outStream
, ISeqInStream
*inStream
, UInt64 fileSize
, char *rs
)
144 enc
= LzmaEnc_Create(&g_Alloc
);
148 LzmaEncProps_Init(&props
);
149 res
= LzmaEnc_SetProps(enc
, &props
);
153 Byte header
[LZMA_PROPS_SIZE
+ 8];
154 size_t headerSize
= LZMA_PROPS_SIZE
;
157 res
= LzmaEnc_WriteProperties(enc
, header
, &headerSize
);
158 for (i
= 0; i
< 8; i
++)
159 header
[headerSize
++] = (Byte
)(fileSize
>> (8 * i
));
160 if (outStream
->Write(outStream
, header
, headerSize
) != headerSize
)
161 res
= SZ_ERROR_WRITE
;
165 res
= LzmaEnc_Encode(enc
, outStream
, inStream
, NULL
, &g_Alloc
, &g_Alloc
);
168 LzmaEnc_Destroy(enc
, &g_Alloc
, &g_Alloc
);
173 static int main2(int numArgs
, const char *args
[], char *rs
)
175 CFileSeqInStream inStream
;
176 CFileOutStream outStream
;
180 BoolInt useOutFile
= False
;
182 FileSeqInStream_CreateVTable(&inStream
);
183 File_Construct(&inStream
.file
);
185 FileOutStream_CreateVTable(&outStream
);
186 File_Construct(&outStream
.file
);
194 if (numArgs
< 3 || numArgs
> 4 || strlen(args
[1]) != 1)
195 return PrintUserError(rs
);
198 encodeMode
= (c
== 'e' || c
== 'E');
199 if (!encodeMode
&& c
!= 'd' && c
!= 'D')
200 return PrintUserError(rs
);
203 size_t t4
= sizeof(UInt32
);
204 size_t t8
= sizeof(UInt64
);
205 if (t4
!= 4 || t8
!= 8)
206 return PrintError(rs
, "Incorrect UInt32 or UInt64");
209 if (InFile_Open(&inStream
.file
, args
[2]) != 0)
210 return PrintError(rs
, "Can not open input file");
215 if (OutFile_Open(&outStream
.file
, args
[3]) != 0)
216 return PrintError(rs
, "Can not open output file");
224 File_GetLength(&inStream
.file
, &fileSize
);
225 res
= Encode(&outStream
.vt
, &inStream
.vt
, fileSize
, rs
);
229 res
= Decode(&outStream
.vt
, useOutFile
? &inStream
.vt
: NULL
);
233 File_Close(&outStream
.file
);
234 File_Close(&inStream
.file
);
238 if (res
== SZ_ERROR_MEM
)
239 return PrintError(rs
, kCantAllocateMessage
);
240 else if (res
== SZ_ERROR_DATA
)
241 return PrintError(rs
, kDataErrorMessage
);
242 else if (res
== SZ_ERROR_WRITE
)
243 return PrintError(rs
, kCantWriteMessage
);
244 else if (res
== SZ_ERROR_READ
)
245 return PrintError(rs
, kCantReadMessage
);
246 return PrintErrorNumber(rs
, res
);
252 int MY_CDECL
main(int numArgs
, const char *args
[])
254 char rs
[800] = { 0 };
255 int res
= main2(numArgs
, args
, rs
);