Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / 3rdparty / seven_zip / LzmaUtil.c
blob6bdb2ad6c2cb2403345f2b5264a7e3068c8a341f
1 /* LzmaUtil.c -- Test application for LZMA compression
2 2018-07-04 : Igor Pavlov : Public domain */
4 #include "Precomp.h"
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
10 #include "CpuArch.h"
12 #include "Alloc.h"
13 #include "7zFile.h"
14 #include "7zVersion.h"
15 #include "LzmaDec.h"
16 #include "LzmaEnc.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)
25 strcat(buffer,
26 "\nLZMA-C " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"
27 "Usage: lzma <e|d> inputFile outputFile\n"
28 " e: encode file\n"
29 " d: decode file\n");
32 static int PrintError(char *buffer, const char *message)
34 strcat(buffer, "\nError: ");
35 strcat(buffer, message);
36 strcat(buffer, "\n");
37 return 1;
40 static int PrintErrorNumber(char *buffer, SRes val)
42 sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
43 return 1;
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,
57 UInt64 unpackSize)
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;
63 LzmaDec_Init(state);
64 for (;;)
66 if (inPos == inSize)
68 inSize = IN_BUF_SIZE;
69 RINOK(inStream->Read(inStream, inBuf, &inSize));
70 inPos = 0;
73 SRes res;
74 SizeT inProcessed = inSize - inPos;
75 SizeT outProcessed = OUT_BUF_SIZE - outPos;
76 ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
77 ELzmaStatus status;
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);
86 inPos += inProcessed;
87 outPos += outProcessed;
88 unpackSize -= outProcessed;
90 if (outStream)
91 if (outStream->Write(outStream, outBuf, outPos) != outPos)
92 return SZ_ERROR_WRITE;
94 outPos = 0;
96 if (res != SZ_OK || (thereIsSize && unpackSize == 0))
97 return res;
99 if (inProcessed == 0 && outProcessed == 0)
101 if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
102 return SZ_ERROR_DATA;
103 return res;
110 static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
112 UInt64 unpackSize;
113 int i;
114 SRes res = 0;
116 CLzmaDec state;
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)));
125 unpackSize = 0;
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);
133 return res;
136 static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
138 CLzmaEncHandle enc;
139 SRes res;
140 CLzmaEncProps props;
142 UNUSED_VAR(rs);
144 enc = LzmaEnc_Create(&g_Alloc);
145 if (enc == 0)
146 return SZ_ERROR_MEM;
148 LzmaEncProps_Init(&props);
149 res = LzmaEnc_SetProps(enc, &props);
151 if (res == SZ_OK)
153 Byte header[LZMA_PROPS_SIZE + 8];
154 size_t headerSize = LZMA_PROPS_SIZE;
155 int i;
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;
162 else
164 if (res == SZ_OK)
165 res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
168 LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
169 return res;
173 static int main2(int numArgs, const char *args[], char *rs)
175 CFileSeqInStream inStream;
176 CFileOutStream outStream;
177 char c;
178 int res;
179 int encodeMode;
180 BoolInt useOutFile = False;
182 FileSeqInStream_CreateVTable(&inStream);
183 File_Construct(&inStream.file);
185 FileOutStream_CreateVTable(&outStream);
186 File_Construct(&outStream.file);
188 if (numArgs == 1)
190 PrintHelp(rs);
191 return 0;
194 if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)
195 return PrintUserError(rs);
197 c = args[1][0];
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");
212 if (numArgs > 3)
214 useOutFile = True;
215 if (OutFile_Open(&outStream.file, args[3]) != 0)
216 return PrintError(rs, "Can not open output file");
218 else if (encodeMode)
219 PrintUserError(rs);
221 if (encodeMode)
223 UInt64 fileSize;
224 File_GetLength(&inStream.file, &fileSize);
225 res = Encode(&outStream.vt, &inStream.vt, fileSize, rs);
227 else
229 res = Decode(&outStream.vt, useOutFile ? &inStream.vt : NULL);
232 if (useOutFile)
233 File_Close(&outStream.file);
234 File_Close(&inStream.file);
236 if (res != SZ_OK)
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);
248 return 0;
252 int MY_CDECL main(int numArgs, const char *args[])
254 char rs[800] = { 0 };
255 int res = main2(numArgs, args, rs);
256 fputs(rs, stdout);
257 return res;