BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src-rt / linux / linux-2.6 / scripts / squashfs / lzma / C / 7zip / Compress / LZMA_Alone / LzmaAlone.cpp
blob52149033478de028e9e241026e945b53a699bc64
1 // LzmaAlone.cpp
3 #include "StdAfx.h"
5 #include "../../../Common/MyWindows.h"
6 #include "../../../Common/MyInitGuid.h"
8 #include <stdio.h>
10 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
11 #include <fcntl.h>
12 #include <io.h>
13 #define MY_SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
14 #else
15 #define MY_SET_BINARY_MODE(file)
16 #endif
18 #include "../../../Common/CommandLineParser.h"
19 #include "../../../Common/StringConvert.h"
20 #include "../../../Common/StringToInt.h"
22 #include "../../Common/FileStreams.h"
23 #include "../../Common/StreamUtils.h"
25 #include "../LZMA/LZMADecoder.h"
26 #include "../LZMA/LZMAEncoder.h"
28 #include "LzmaBench.h"
29 #include "LzmaRam.h"
31 extern "C"
33 #include "LzmaRamDecode.h"
36 using namespace NCommandLineParser;
38 #ifdef _WIN32
39 bool g_IsNT = false;
40 static inline bool IsItWindowsNT()
42 OSVERSIONINFO versionInfo;
43 versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
44 if (!::GetVersionEx(&versionInfo))
45 return false;
46 return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
48 #endif
50 static const char *kCantAllocate = "Can not allocate memory";
51 static const char *kReadError = "Read error";
52 static const char *kWriteError = "Write error";
54 namespace NKey {
55 enum Enum
57 kHelp1 = 0,
58 kHelp2,
59 kMode,
60 kDictionary,
61 kFastBytes,
62 kLitContext,
63 kLitPos,
64 kPosBits,
65 kMatchFinder,
66 kEOS,
67 kStdIn,
68 kStdOut,
69 kFilter86
73 static const CSwitchForm kSwitchForms[] =
75 { L"?", NSwitchType::kSimple, false },
76 { L"H", NSwitchType::kSimple, false },
77 { L"A", NSwitchType::kUnLimitedPostString, false, 1 },
78 { L"D", NSwitchType::kUnLimitedPostString, false, 1 },
79 { L"FB", NSwitchType::kUnLimitedPostString, false, 1 },
80 { L"LC", NSwitchType::kUnLimitedPostString, false, 1 },
81 { L"LP", NSwitchType::kUnLimitedPostString, false, 1 },
82 { L"PB", NSwitchType::kUnLimitedPostString, false, 1 },
83 { L"MF", NSwitchType::kUnLimitedPostString, false, 1 },
84 { L"EOS", NSwitchType::kSimple, false },
85 { L"SI", NSwitchType::kSimple, false },
86 { L"SO", NSwitchType::kSimple, false },
87 { L"F86", NSwitchType::kSimple, false }
90 static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]);
92 static void PrintHelp()
94 fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n"
95 " e: encode file\n"
96 " d: decode file\n"
97 " b: Benchmark\n"
98 "<Switches>\n"
99 " -a{N}: set compression mode - [0, 2], default: 2 (max)\n"
100 " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n"
101 " -fb{N}: set number of fast bytes - [5, 273], default: 128\n"
102 " -lc{N}: set number of literal context bits - [0, 8], default: 3\n"
103 " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n"
104 " -pb{N}: set number of pos bits - [0, 4], default: 2\n"
105 " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2,\n"
106 " pat2h, pat3h, pat4h, hc3, hc4], default: bt4\n"
107 " -eos: write End Of Stream marker\n"
108 " -si: read data from stdin\n"
109 " -so: write data to stdout\n"
113 static void PrintHelpAndExit(const char *s)
115 fprintf(stderr, "\nError: %s\n\n", s);
116 PrintHelp();
117 throw -1;
120 static void IncorrectCommand()
122 PrintHelpAndExit("Incorrect command");
125 static void WriteArgumentsToStringList(int numArguments, const char *arguments[],
126 UStringVector &strings)
128 for(int i = 1; i < numArguments; i++)
129 strings.Add(MultiByteToUnicodeString(arguments[i]));
132 static bool GetNumber(const wchar_t *s, UInt32 &value)
134 value = 0;
135 if (MyStringLen(s) == 0)
136 return false;
137 const wchar_t *end;
138 UInt64 res = ConvertStringToUInt64(s, &end);
139 if (*end != L'\0')
140 return false;
141 if (res > 0xFFFFFFFF)
142 return false;
143 value = UInt32(res);
144 return true;
147 int main2(int n, const char *args[])
149 #ifdef _WIN32
150 g_IsNT = IsItWindowsNT();
151 #endif
153 fprintf(stderr, "\nLZMA 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n");
155 if (n == 1)
157 PrintHelp();
158 return 0;
161 if (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4)
163 fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile");
164 return 1;
167 UStringVector commandStrings;
168 WriteArgumentsToStringList(n, args, commandStrings);
169 CParser parser(kNumSwitches);
172 parser.ParseStrings(kSwitchForms, commandStrings);
174 catch(...)
176 IncorrectCommand();
179 if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
181 PrintHelp();
182 return 0;
184 const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
186 int paramIndex = 0;
187 if (paramIndex >= nonSwitchStrings.Size())
188 IncorrectCommand();
189 const UString &command = nonSwitchStrings[paramIndex++];
191 bool dictionaryIsDefined = false;
192 UInt32 dictionary = 1 << 21;
193 if(parser[NKey::kDictionary].ThereIs)
195 UInt32 dicLog;
196 if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog))
197 IncorrectCommand();
198 dictionary = 1 << dicLog;
199 dictionaryIsDefined = true;
201 UString mf = L"BT4";
202 if (parser[NKey::kMatchFinder].ThereIs)
203 mf = parser[NKey::kMatchFinder].PostStrings[0];
205 if (command.CompareNoCase(L"b") == 0)
207 const UInt32 kNumDefaultItereations = 10;
208 UInt32 numIterations = kNumDefaultItereations;
210 if (paramIndex < nonSwitchStrings.Size())
211 if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))
212 numIterations = kNumDefaultItereations;
214 return LzmaBenchmark(stderr, numIterations, dictionary,
215 mf.CompareNoCase(L"BT4") == 0);
218 bool encodeMode = false;
219 if (command.CompareNoCase(L"e") == 0)
220 encodeMode = true;
221 else if (command.CompareNoCase(L"d") == 0)
222 encodeMode = false;
223 else
224 IncorrectCommand();
226 bool stdInMode = parser[NKey::kStdIn].ThereIs;
227 bool stdOutMode = parser[NKey::kStdOut].ThereIs;
229 CMyComPtr<ISequentialInStream> inStream;
230 CInFileStream *inStreamSpec = 0;
231 if (stdInMode)
233 inStream = new CStdInFileStream;
234 MY_SET_BINARY_MODE(stdin);
236 else
238 if (paramIndex >= nonSwitchStrings.Size())
239 IncorrectCommand();
240 const UString &inputName = nonSwitchStrings[paramIndex++];
241 inStreamSpec = new CInFileStream;
242 inStream = inStreamSpec;
243 if (!inStreamSpec->Open(GetSystemString(inputName)))
245 fprintf(stderr, "\nError: can not open input file %s\n",
246 (const char *)GetOemString(inputName));
247 return 1;
251 CMyComPtr<ISequentialOutStream> outStream;
252 if (stdOutMode)
254 outStream = new CStdOutFileStream;
255 MY_SET_BINARY_MODE(stdout);
257 else
259 if (paramIndex >= nonSwitchStrings.Size())
260 IncorrectCommand();
261 const UString &outputName = nonSwitchStrings[paramIndex++];
262 COutFileStream *outStreamSpec = new COutFileStream;
263 outStream = outStreamSpec;
264 if (!outStreamSpec->Create(GetSystemString(outputName), true))
266 fprintf(stderr, "\nError: can not open output file %s\n",
267 (const char *)GetOemString(outputName));
268 return 1;
272 if (parser[NKey::kFilter86].ThereIs)
274 // -f86 switch is for x86 filtered mode: BCJ + LZMA.
275 if (parser[NKey::kEOS].ThereIs || stdInMode)
276 throw "Can not use stdin in this mode";
277 UInt64 fileSize;
278 inStreamSpec->File.GetLength(fileSize);
279 if (fileSize > 0xF0000000)
280 throw "File is too big";
281 UInt32 inSize = (UInt32)fileSize;
282 Byte *inBuffer = 0;
283 if (inSize != 0)
285 inBuffer = (Byte *)MyAlloc((size_t)inSize);
286 if (inBuffer == 0)
287 throw kCantAllocate;
290 UInt32 processedSize;
291 if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK)
292 throw "Can not read";
293 if ((UInt32)inSize != processedSize)
294 throw "Read size error";
296 Byte *outBuffer = 0;
297 size_t outSizeProcessed;
298 if (encodeMode)
300 // we allocate 105% of original size for output buffer
301 size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16);
302 if (outSize != 0)
304 outBuffer = (Byte *)MyAlloc((size_t)outSize);
305 if (outBuffer == 0)
306 throw kCantAllocate;
308 if (!dictionaryIsDefined)
309 dictionary = 1 << 23;
310 int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed,
311 dictionary, SZ_FILTER_AUTO);
312 if (res != 0)
314 fprintf(stderr, "\nEncoder error = %d\n", (int)res);
315 return 1;
318 else
320 size_t outSize;
321 if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0)
322 throw "data error";
323 if (outSize != 0)
325 outBuffer = (Byte *)MyAlloc(outSize);
326 if (outBuffer == 0)
327 throw kCantAllocate;
329 int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free);
330 if (res != 0)
331 throw "LzmaDecoder error";
333 if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK)
334 throw kWriteError;
335 MyFree(outBuffer);
336 MyFree(inBuffer);
337 return 0;
341 UInt64 fileSize;
342 if (encodeMode)
344 NCompress::NLZMA::CEncoder *encoderSpec =
345 new NCompress::NLZMA::CEncoder;
346 CMyComPtr<ICompressCoder> encoder = encoderSpec;
348 if (!dictionaryIsDefined)
349 dictionary = 1 << 23;
351 UInt32 posStateBits = 2;
352 UInt32 litContextBits = 3; // for normal files
353 // UInt32 litContextBits = 0; // for 32-bit data
354 UInt32 litPosBits = 0;
355 // UInt32 litPosBits = 2; // for 32-bit data
356 UInt32 algorithm = 2;
357 UInt32 numFastBytes = 128;
359 bool eos = parser[NKey::kEOS].ThereIs || stdInMode;
361 if(parser[NKey::kMode].ThereIs)
362 if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm))
363 IncorrectCommand();
365 if(parser[NKey::kFastBytes].ThereIs)
366 if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes))
367 IncorrectCommand();
368 if(parser[NKey::kLitContext].ThereIs)
369 if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits))
370 IncorrectCommand();
371 if(parser[NKey::kLitPos].ThereIs)
372 if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits))
373 IncorrectCommand();
374 if(parser[NKey::kPosBits].ThereIs)
375 if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits))
376 IncorrectCommand();
378 PROPID propIDs[] =
380 NCoderPropID::kDictionarySize,
381 NCoderPropID::kPosStateBits,
382 NCoderPropID::kLitContextBits,
383 NCoderPropID::kLitPosBits,
384 NCoderPropID::kAlgorithm,
385 NCoderPropID::kNumFastBytes,
386 NCoderPropID::kMatchFinder,
387 NCoderPropID::kEndMarker
389 const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
391 NWindows::NCOM::CPropVariant properties[kNumProps];
392 properties[0] = UInt32(dictionary);
393 properties[1] = UInt32(posStateBits);
394 properties[2] = UInt32(litContextBits);
396 properties[3] = UInt32(litPosBits);
397 properties[4] = UInt32(algorithm);
398 properties[5] = UInt32(numFastBytes);
399 properties[6] = mf;
400 properties[7] = eos;
402 PROPVARIANT properties[kNumProps];
403 for (int p = 0; p < 6; p++)
404 properties[p].vt = VT_UI4;
405 properties[0].ulVal = UInt32(dictionary);
406 properties[1].ulVal = UInt32(posStateBits);
407 properties[2].ulVal = UInt32(litContextBits);
408 properties[3].ulVal = UInt32(litPosBits);
409 properties[4].ulVal = UInt32(algorithm);
410 properties[5].ulVal = UInt32(numFastBytes);
412 properties[6].vt = VT_BSTR;
413 properties[6].bstrVal = (BSTR)(const wchar_t *)mf;
415 properties[7].vt = VT_BOOL;
416 properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE;
418 if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
419 IncorrectCommand();
420 encoderSpec->WriteCoderProperties(outStream);
422 if (eos || stdInMode)
423 fileSize = (UInt64)(Int64)-1;
424 else
425 inStreamSpec->File.GetLength(fileSize);
427 for (int i = 0; i < 8; i++)
429 Byte b = Byte(fileSize >> (8 * i));
430 if (outStream->Write(&b, 1, 0) != S_OK)
432 fprintf(stderr, kWriteError);
433 return 1;
436 HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);
437 if (result == E_OUTOFMEMORY)
439 fprintf(stderr, "\nError: Can not allocate memory\n");
440 return 1;
442 else if (result != S_OK)
444 fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result);
445 return 1;
448 else
450 NCompress::NLZMA::CDecoder *decoderSpec =
451 new NCompress::NLZMA::CDecoder;
452 CMyComPtr<ICompressCoder> decoder = decoderSpec;
453 const UInt32 kPropertiesSize = 5;
454 Byte properties[kPropertiesSize];
455 UInt32 processedSize;
456 if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK)
458 fprintf(stderr, kReadError);
459 return 1;
461 if (processedSize != kPropertiesSize)
463 fprintf(stderr, kReadError);
464 return 1;
466 if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK)
468 fprintf(stderr, "SetDecoderProperties error");
469 return 1;
471 fileSize = 0;
472 for (int i = 0; i < 8; i++)
474 Byte b;
475 if (inStream->Read(&b, 1, &processedSize) != S_OK)
477 fprintf(stderr, kReadError);
478 return 1;
480 if (processedSize != 1)
482 fprintf(stderr, kReadError);
483 return 1;
485 fileSize |= ((UInt64)b) << (8 * i);
487 if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK)
489 fprintf(stderr, "Decoder error");
490 return 1;
493 return 0;
496 int main(int n, const char *args[])
498 try { return main2(n, args); }
499 catch(const char *s)
501 fprintf(stderr, "\nError: %s\n", s);
502 return 1;
504 catch(...)
506 fprintf(stderr, "\nError\n");
507 return 1;