98331b49d63e71f90a27c3501e2164de5b326f5b
[pcsx_rearmed.git] / deps / lzma-16.04 / C / Util / Lzma / LzmaUtil.c
1 /* LzmaUtil.c -- Test application for LZMA compression\r
2 2015-11-08 : Igor Pavlov : Public domain */\r
3 \r
4 #include "../../Precomp.h"\r
5 \r
6 #include <stdio.h>\r
7 #include <stdlib.h>\r
8 #include <string.h>\r
9 \r
10 #include "../../Alloc.h"\r
11 #include "../../7zFile.h"\r
12 #include "../../7zVersion.h"\r
13 #include "../../LzmaDec.h"\r
14 #include "../../LzmaEnc.h"\r
15 \r
16 const char *kCantReadMessage = "Can not read input file";\r
17 const char *kCantWriteMessage = "Can not write output file";\r
18 const char *kCantAllocateMessage = "Can not allocate memory";\r
19 const char *kDataErrorMessage = "Data error";\r
20 \r
21 void PrintHelp(char *buffer)\r
22 {\r
23   strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"\r
24       "\nUsage:  lzma <e|d> inputFile outputFile\n"\r
25              "  e: encode file\n"\r
26              "  d: decode file\n");\r
27 }\r
28 \r
29 int PrintError(char *buffer, const char *message)\r
30 {\r
31   strcat(buffer, "\nError: ");\r
32   strcat(buffer, message);\r
33   strcat(buffer, "\n");\r
34   return 1;\r
35 }\r
36 \r
37 int PrintErrorNumber(char *buffer, SRes val)\r
38 {\r
39   sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);\r
40   return 1;\r
41 }\r
42 \r
43 int PrintUserError(char *buffer)\r
44 {\r
45   return PrintError(buffer, "Incorrect command");\r
46 }\r
47 \r
48 #define IN_BUF_SIZE (1 << 16)\r
49 #define OUT_BUF_SIZE (1 << 16)\r
50 \r
51 static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,\r
52     UInt64 unpackSize)\r
53 {\r
54   int thereIsSize = (unpackSize != (UInt64)(Int64)-1);\r
55   Byte inBuf[IN_BUF_SIZE];\r
56   Byte outBuf[OUT_BUF_SIZE];\r
57   size_t inPos = 0, inSize = 0, outPos = 0;\r
58   LzmaDec_Init(state);\r
59   for (;;)\r
60   {\r
61     if (inPos == inSize)\r
62     {\r
63       inSize = IN_BUF_SIZE;\r
64       RINOK(inStream->Read(inStream, inBuf, &inSize));\r
65       inPos = 0;\r
66     }\r
67     {\r
68       SRes res;\r
69       SizeT inProcessed = inSize - inPos;\r
70       SizeT outProcessed = OUT_BUF_SIZE - outPos;\r
71       ELzmaFinishMode finishMode = LZMA_FINISH_ANY;\r
72       ELzmaStatus status;\r
73       if (thereIsSize && outProcessed > unpackSize)\r
74       {\r
75         outProcessed = (SizeT)unpackSize;\r
76         finishMode = LZMA_FINISH_END;\r
77       }\r
78       \r
79       res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,\r
80         inBuf + inPos, &inProcessed, finishMode, &status);\r
81       inPos += inProcessed;\r
82       outPos += outProcessed;\r
83       unpackSize -= outProcessed;\r
84       \r
85       if (outStream)\r
86         if (outStream->Write(outStream, outBuf, outPos) != outPos)\r
87           return SZ_ERROR_WRITE;\r
88         \r
89       outPos = 0;\r
90       \r
91       if (res != SZ_OK || (thereIsSize && unpackSize == 0))\r
92         return res;\r
93       \r
94       if (inProcessed == 0 && outProcessed == 0)\r
95       {\r
96         if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)\r
97           return SZ_ERROR_DATA;\r
98         return res;\r
99       }\r
100     }\r
101   }\r
102 }\r
103 \r
104 static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)\r
105 {\r
106   UInt64 unpackSize;\r
107   int i;\r
108   SRes res = 0;\r
109 \r
110   CLzmaDec state;\r
111 \r
112   /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */\r
113   unsigned char header[LZMA_PROPS_SIZE + 8];\r
114 \r
115   /* Read and parse header */\r
116 \r
117   RINOK(SeqInStream_Read(inStream, header, sizeof(header)));\r
118 \r
119   unpackSize = 0;\r
120   for (i = 0; i < 8; i++)\r
121     unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);\r
122 \r
123   LzmaDec_Construct(&state);\r
124   RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));\r
125   res = Decode2(&state, outStream, inStream, unpackSize);\r
126   LzmaDec_Free(&state, &g_Alloc);\r
127   return res;\r
128 }\r
129 \r
130 static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)\r
131 {\r
132   CLzmaEncHandle enc;\r
133   SRes res;\r
134   CLzmaEncProps props;\r
135 \r
136   UNUSED_VAR(rs);\r
137 \r
138   enc = LzmaEnc_Create(&g_Alloc);\r
139   if (enc == 0)\r
140     return SZ_ERROR_MEM;\r
141 \r
142   LzmaEncProps_Init(&props);\r
143   res = LzmaEnc_SetProps(enc, &props);\r
144 \r
145   if (res == SZ_OK)\r
146   {\r
147     Byte header[LZMA_PROPS_SIZE + 8];\r
148     size_t headerSize = LZMA_PROPS_SIZE;\r
149     int i;\r
150 \r
151     res = LzmaEnc_WriteProperties(enc, header, &headerSize);\r
152     for (i = 0; i < 8; i++)\r
153       header[headerSize++] = (Byte)(fileSize >> (8 * i));\r
154     if (outStream->Write(outStream, header, headerSize) != headerSize)\r
155       res = SZ_ERROR_WRITE;\r
156     else\r
157     {\r
158       if (res == SZ_OK)\r
159         res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);\r
160     }\r
161   }\r
162   LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);\r
163   return res;\r
164 }\r
165 \r
166 int main2(int numArgs, const char *args[], char *rs)\r
167 {\r
168   CFileSeqInStream inStream;\r
169   CFileOutStream outStream;\r
170   char c;\r
171   int res;\r
172   int encodeMode;\r
173   Bool useOutFile = False;\r
174 \r
175   FileSeqInStream_CreateVTable(&inStream);\r
176   File_Construct(&inStream.file);\r
177 \r
178   FileOutStream_CreateVTable(&outStream);\r
179   File_Construct(&outStream.file);\r
180 \r
181   if (numArgs == 1)\r
182   {\r
183     PrintHelp(rs);\r
184     return 0;\r
185   }\r
186 \r
187   if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)\r
188     return PrintUserError(rs);\r
189 \r
190   c = args[1][0];\r
191   encodeMode = (c == 'e' || c == 'E');\r
192   if (!encodeMode && c != 'd' && c != 'D')\r
193     return PrintUserError(rs);\r
194 \r
195   {\r
196     size_t t4 = sizeof(UInt32);\r
197     size_t t8 = sizeof(UInt64);\r
198     if (t4 != 4 || t8 != 8)\r
199       return PrintError(rs, "Incorrect UInt32 or UInt64");\r
200   }\r
201 \r
202   if (InFile_Open(&inStream.file, args[2]) != 0)\r
203     return PrintError(rs, "Can not open input file");\r
204 \r
205   if (numArgs > 3)\r
206   {\r
207     useOutFile = True;\r
208     if (OutFile_Open(&outStream.file, args[3]) != 0)\r
209       return PrintError(rs, "Can not open output file");\r
210   }\r
211   else if (encodeMode)\r
212     PrintUserError(rs);\r
213 \r
214   if (encodeMode)\r
215   {\r
216     UInt64 fileSize;\r
217     File_GetLength(&inStream.file, &fileSize);\r
218     res = Encode(&outStream.s, &inStream.s, fileSize, rs);\r
219   }\r
220   else\r
221   {\r
222     res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL);\r
223   }\r
224 \r
225   if (useOutFile)\r
226     File_Close(&outStream.file);\r
227   File_Close(&inStream.file);\r
228 \r
229   if (res != SZ_OK)\r
230   {\r
231     if (res == SZ_ERROR_MEM)\r
232       return PrintError(rs, kCantAllocateMessage);\r
233     else if (res == SZ_ERROR_DATA)\r
234       return PrintError(rs, kDataErrorMessage);\r
235     else if (res == SZ_ERROR_WRITE)\r
236       return PrintError(rs, kCantWriteMessage);\r
237     else if (res == SZ_ERROR_READ)\r
238       return PrintError(rs, kCantReadMessage);\r
239     return PrintErrorNumber(rs, res);\r
240   }\r
241   return 0;\r
242 }\r
243 \r
244 int MY_CDECL main(int numArgs, const char *args[])\r
245 {\r
246   char rs[800] = { 0 };\r
247   int res = main2(numArgs, args, rs);\r
248   fputs(rs, stdout);\r
249   return res;\r
250 }\r