1 /* LzmaUtil.c -- Test application for LZMA compression
2 2008-11-23 : Igor Pavlov : Public domain */
4 #define _CRT_SECURE_NO_WARNINGS
11 #include "../7zFile.h"
12 #include "../7zVersion.h"
13 #include "../LzmaDec.h"
14 #include "../LzmaEnc.h"
16 const char *kCantReadMessage
= "Can not read input file";
17 const char *kCantWriteMessage
= "Can not write output file";
18 const char *kCantAllocateMessage
= "Can not allocate memory";
19 const char *kDataErrorMessage
= "Data error";
21 static void *SzAlloc(void *p
, size_t size
) { p
= p
; return MyAlloc(size
); }
22 static void SzFree(void *p
, void *address
) { p
= p
; MyFree(address
); }
23 static ISzAlloc g_Alloc
= { SzAlloc
, SzFree
};
25 void PrintHelp(char *buffer
)
27 strcat(buffer
, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE
"\n"
28 "\nUsage: lzma <e|d> inputFile outputFile\n"
33 int PrintError(char *buffer
, const char *message
)
35 strcat(buffer
, "\nError: ");
36 strcat(buffer
, message
);
41 int PrintErrorNumber(char *buffer
, SRes val
)
43 sprintf(buffer
+ strlen(buffer
), "\nError code: %x\n", (unsigned)val
);
47 int PrintUserError(char *buffer
)
49 return PrintError(buffer
, "Incorrect command");
52 #define IN_BUF_SIZE (1 << 16)
53 #define OUT_BUF_SIZE (1 << 16)
55 static SRes
Decode2(CLzmaDec
*state
, ISeqOutStream
*outStream
, ISeqInStream
*inStream
,
58 int thereIsSize
= (unpackSize
!= (UInt64
)(Int64
)-1);
59 Byte inBuf
[IN_BUF_SIZE
];
60 Byte outBuf
[OUT_BUF_SIZE
];
61 size_t inPos
= 0, inSize
= 0, outPos
= 0;
68 RINOK(inStream
->Read(inStream
, inBuf
, &inSize
));
73 SizeT inProcessed
= inSize
- inPos
;
74 SizeT outProcessed
= OUT_BUF_SIZE
- outPos
;
75 ELzmaFinishMode finishMode
= LZMA_FINISH_ANY
;
77 if (thereIsSize
&& outProcessed
> unpackSize
)
79 outProcessed
= (SizeT
)unpackSize
;
80 finishMode
= LZMA_FINISH_END
;
83 res
= LzmaDec_DecodeToBuf(state
, outBuf
+ outPos
, &outProcessed
,
84 inBuf
+ inPos
, &inProcessed
, finishMode
, &status
);
86 outPos
+= outProcessed
;
87 unpackSize
-= outProcessed
;
90 if (outStream
->Write(outStream
, outBuf
, outPos
) != outPos
)
91 return SZ_ERROR_WRITE
;
95 if (res
!= SZ_OK
|| thereIsSize
&& unpackSize
== 0)
98 if (inProcessed
== 0 && outProcessed
== 0)
100 if (thereIsSize
|| status
!= LZMA_STATUS_FINISHED_WITH_MARK
)
101 return SZ_ERROR_DATA
;
108 static SRes
Decode(ISeqOutStream
*outStream
, ISeqInStream
*inStream
)
116 /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
117 unsigned char header
[LZMA_PROPS_SIZE
+ 8];
119 /* Read and parse header */
121 RINOK(SeqInStream_Read(inStream
, header
, sizeof(header
)));
124 for (i
= 0; i
< 8; i
++)
125 unpackSize
+= (UInt64
)header
[LZMA_PROPS_SIZE
+ i
] << (i
* 8);
127 LzmaDec_Construct(&state
);
128 RINOK(LzmaDec_Allocate(&state
, header
, LZMA_PROPS_SIZE
, &g_Alloc
));
129 res
= Decode2(&state
, outStream
, inStream
, unpackSize
);
130 LzmaDec_Free(&state
, &g_Alloc
);
134 static SRes
Encode(ISeqOutStream
*outStream
, ISeqInStream
*inStream
, UInt64 fileSize
, char *rs
)
142 enc
= LzmaEnc_Create(&g_Alloc
);
146 LzmaEncProps_Init(&props
);
147 res
= LzmaEnc_SetProps(enc
, &props
);
151 Byte header
[LZMA_PROPS_SIZE
+ 8];
152 size_t headerSize
= LZMA_PROPS_SIZE
;
155 res
= LzmaEnc_WriteProperties(enc
, header
, &headerSize
);
156 for (i
= 0; i
< 8; i
++)
157 header
[headerSize
++] = (Byte
)(fileSize
>> (8 * i
));
158 if (outStream
->Write(outStream
, header
, headerSize
) != headerSize
)
159 res
= SZ_ERROR_WRITE
;
163 res
= LzmaEnc_Encode(enc
, outStream
, inStream
, NULL
, &g_Alloc
, &g_Alloc
);
166 LzmaEnc_Destroy(enc
, &g_Alloc
, &g_Alloc
);
170 int main2(int numArgs
, const char *args
[], char *rs
)
172 CFileSeqInStream inStream
;
173 CFileOutStream outStream
;
177 Bool useOutFile
= False
;
179 FileSeqInStream_CreateVTable(&inStream
);
180 File_Construct(&inStream
.file
);
182 FileOutStream_CreateVTable(&outStream
);
183 File_Construct(&outStream
.file
);
191 if (numArgs
< 3 || numArgs
> 4 || strlen(args
[1]) != 1)
192 return PrintUserError(rs
);
195 encodeMode
= (c
== 'e' || c
== 'E');
196 if (!encodeMode
&& c
!= 'd' && c
!= 'D')
197 return PrintUserError(rs
);
200 size_t t4
= sizeof(UInt32
);
201 size_t t8
= sizeof(UInt64
);
202 if (t4
!= 4 || t8
!= 8)
203 return PrintError(rs
, "Incorrect UInt32 or UInt64");
206 if (InFile_Open(&inStream
.file
, args
[2]) != 0)
207 return PrintError(rs
, "Can not open input file");
212 if (OutFile_Open(&outStream
.file
, args
[3]) != 0)
213 return PrintError(rs
, "Can not open output file");
221 File_GetLength(&inStream
.file
, &fileSize
);
222 res
= Encode(&outStream
.s
, &inStream
.s
, fileSize
, rs
);
226 res
= Decode(&outStream
.s
, useOutFile
? &inStream
.s
: NULL
);
230 File_Close(&outStream
.file
);
231 File_Close(&inStream
.file
);
235 if (res
== SZ_ERROR_MEM
)
236 return PrintError(rs
, kCantAllocateMessage
);
237 else if (res
== SZ_ERROR_DATA
)
238 return PrintError(rs
, kDataErrorMessage
);
239 else if (res
== SZ_ERROR_WRITE
)
240 return PrintError(rs
, kCantWriteMessage
);
241 else if (res
== SZ_ERROR_READ
)
242 return PrintError(rs
, kCantReadMessage
);
243 return PrintErrorNumber(rs
, res
);
248 int MY_CDECL
main(int numArgs
, const char *args
[])
250 char rs
[800] = { 0 };
251 int res
= main2(numArgs
, args
, rs
);