Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZMA_Alone/LzmaAlone.cpp, revision 1.1.1.1
1.1 misho 1: // LzmaAlone.cpp
2:
3: #include "StdAfx.h"
4:
5: #include "../../../Common/MyWindows.h"
6: #include "../../../Common/MyInitGuid.h"
7:
8: #include <stdio.h>
9:
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
17:
18: #include "../../../Common/CommandLineParser.h"
19: #include "../../../Common/StringConvert.h"
20: #include "../../../Common/StringToInt.h"
21:
22: // #include "Windows/PropVariant.h"
23:
24: #include "../../Common/FileStreams.h"
25:
26: #include "../LZMA/LZMADecoder.h"
27: #include "../LZMA/LZMAEncoder.h"
28:
29: #include "LzmaBench.h"
30: #include "LzmaRam.h"
31:
32: extern "C"
33: {
34: #include "LzmaRamDecode.h"
35: }
36:
37: using namespace NCommandLineParser;
38:
39: namespace NKey {
40: enum Enum
41: {
42: kHelp1 = 0,
43: kHelp2,
44: kMode,
45: kDictionary,
46: kFastBytes,
47: kLitContext,
48: kLitPos,
49: kPosBits,
50: kMatchFinder,
51: kEOS,
52: kStdIn,
53: kStdOut,
54: kFilter86
55: };
56: }
57:
58: static const CSwitchForm kSwitchForms[] =
59: {
60: { L"?", NSwitchType::kSimple, false },
61: { L"H", NSwitchType::kSimple, false },
62: { L"A", NSwitchType::kUnLimitedPostString, false, 1 },
63: { L"D", NSwitchType::kUnLimitedPostString, false, 1 },
64: { L"FB", NSwitchType::kUnLimitedPostString, false, 1 },
65: { L"LC", NSwitchType::kUnLimitedPostString, false, 1 },
66: { L"LP", NSwitchType::kUnLimitedPostString, false, 1 },
67: { L"PB", NSwitchType::kUnLimitedPostString, false, 1 },
68: { L"MF", NSwitchType::kUnLimitedPostString, false, 1 },
69: { L"EOS", NSwitchType::kSimple, false },
70: { L"SI", NSwitchType::kSimple, false },
71: { L"SO", NSwitchType::kSimple, false },
72: { L"F86", NSwitchType::kSimple, false }
73: };
74:
75: static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]);
76:
77: static void PrintHelp()
78: {
79: fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n"
80: " e: encode file\n"
81: " d: decode file\n"
82: " b: Benchmark\n"
83: "<Switches>\n"
84: " -a{N}: set compression mode - [0, 2], default: 2 (max)\n"
85: " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n"
86: " -fb{N}: set number of fast bytes - [5, 255], default: 128\n"
87: " -lc{N}: set number of literal context bits - [0, 8], default: 3\n"
88: " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n"
89: " -pb{N}: set number of pos bits - [0, 4], default: 2\n"
90: " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2,\n"
91: " pat2h, pat3h, pat4h, hc3, hc4], default: bt4\n"
92: " -eos: write End Of Stream marker\n"
93: " -si: Read data from stdin\n"
94: " -so: Write data to stdout\n"
95: );
96: }
97:
98: static void PrintHelpAndExit(const char *s)
99: {
100: fprintf(stderr, "\nError: %s\n\n", s);
101: PrintHelp();
102: throw -1;
103: }
104:
105: static void IncorrectCommand()
106: {
107: PrintHelpAndExit("Incorrect command");
108: }
109:
110: static void WriteArgumentsToStringList(int numArguments, const char *arguments[],
111: UStringVector &strings)
112: {
113: for(int i = 1; i < numArguments; i++)
114: strings.Add(MultiByteToUnicodeString(arguments[i]));
115: }
116:
117: static bool GetNumber(const wchar_t *s, UInt32 &value)
118: {
119: value = 0;
120: if (MyStringLen(s) == 0)
121: return false;
122: const wchar_t *end;
123: UInt64 res = ConvertStringToUInt64(s, &end);
124: if (*end != L'\0')
125: return false;
126: if (res > 0xFFFFFFFF)
127: return false;
128: value = UInt32(res);
129: return true;
130: }
131:
132: int main2(int n, const char *args[])
133: {
134: fprintf(stderr, "\nLZMA 4.17 Copyright (c) 1999-2004 Igor Pavlov 2005-04-18\n");
135:
136: if (n == 1)
137: {
138: PrintHelp();
139: return 0;
140: }
141:
142: if (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4)
143: {
144: fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile");
145: return 1;
146: }
147:
148: UStringVector commandStrings;
149: WriteArgumentsToStringList(n, args, commandStrings);
150: CParser parser(kNumSwitches);
151: try
152: {
153: parser.ParseStrings(kSwitchForms, commandStrings);
154: }
155: catch(...)
156: {
157: IncorrectCommand();
158: }
159:
160: if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
161: {
162: PrintHelp();
163: return 0;
164: }
165: const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
166:
167: int paramIndex = 0;
168: if (paramIndex >= nonSwitchStrings.Size())
169: IncorrectCommand();
170: const UString &command = nonSwitchStrings[paramIndex++];
171:
172: bool dictionaryIsDefined = false;
173: UInt32 dictionary = 1 << 21;
174: if(parser[NKey::kDictionary].ThereIs)
175: {
176: UInt32 dicLog;
177: if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog))
178: IncorrectCommand();
179: dictionary = 1 << dicLog;
180: dictionaryIsDefined = true;
181: }
182: UString mf = L"BT4";
183: if (parser[NKey::kMatchFinder].ThereIs)
184: mf = parser[NKey::kMatchFinder].PostStrings[0];
185:
186: if (command.CompareNoCase(L"b") == 0)
187: {
188: const UInt32 kNumDefaultItereations = 10;
189: UInt32 numIterations = kNumDefaultItereations;
190: {
191: if (paramIndex < nonSwitchStrings.Size())
192: if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))
193: numIterations = kNumDefaultItereations;
194: }
195: return LzmaBenchmark(stderr, numIterations, dictionary,
196: mf.CompareNoCase(L"BT4") == 0);
197: }
198:
199: bool encodeMode = false;
200: if (command.CompareNoCase(L"e") == 0)
201: encodeMode = true;
202: else if (command.CompareNoCase(L"d") == 0)
203: encodeMode = false;
204: else
205: IncorrectCommand();
206:
207: bool stdInMode = parser[NKey::kStdIn].ThereIs;
208: bool stdOutMode = parser[NKey::kStdOut].ThereIs;
209:
210: CMyComPtr<ISequentialInStream> inStream;
211: CInFileStream *inStreamSpec = 0;
212: if (stdInMode)
213: {
214: inStream = new CStdInFileStream;
215: MY_SET_BINARY_MODE(stdin);
216: }
217: else
218: {
219: if (paramIndex >= nonSwitchStrings.Size())
220: IncorrectCommand();
221: const UString &inputName = nonSwitchStrings[paramIndex++];
222: inStreamSpec = new CInFileStream;
223: inStream = inStreamSpec;
224: if (!inStreamSpec->Open(GetSystemString(inputName)))
225: {
226: fprintf(stderr, "\nError: can not open input file %s\n",
227: (const char *)GetOemString(inputName));
228: return 1;
229: }
230: }
231:
232: CMyComPtr<ISequentialOutStream> outStream;
233: if (stdOutMode)
234: {
235: outStream = new CStdOutFileStream;
236: MY_SET_BINARY_MODE(stdout);
237: }
238: else
239: {
240: if (paramIndex >= nonSwitchStrings.Size())
241: IncorrectCommand();
242: const UString &outputName = nonSwitchStrings[paramIndex++];
243: COutFileStream *outStreamSpec = new COutFileStream;
244: outStream = outStreamSpec;
245: if (!outStreamSpec->Create(GetSystemString(outputName), true))
246: {
247: fprintf(stderr, "\nError: can not open output file %s\n",
248: (const char *)GetOemString(outputName));
249: return 1;
250: }
251: }
252:
253: if (parser[NKey::kFilter86].ThereIs)
254: {
255: // -f86 switch is for x86 filtered mode: BCJ + LZMA.
256: if (parser[NKey::kEOS].ThereIs || stdInMode)
257: throw "Can not use stdin in this mode";
258: UInt64 fileSize;
259: inStreamSpec->File.GetLength(fileSize);
260: if (fileSize > 0xF0000000)
261: throw "File is too big";
262: UInt32 inSize = (UInt32)fileSize;
263: Byte *inBuffer = (Byte *)MyAlloc((size_t)inSize);
264: if (inBuffer == 0)
265: throw "Can not allocate memory";
266:
267: UInt32 processedSize;
268: if (inStream->Read(inBuffer, (UInt32)inSize, &processedSize) != S_OK)
269: throw "Can not read";
270: if ((UInt32)inSize != processedSize)
271: throw "Read size error";
272:
273: Byte *outBuffer;
274: size_t outSizeProcessed;
275: if (encodeMode)
276: {
277: // we allocate 105% of original size for output buffer
278: size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16);
279: outBuffer = (Byte *)MyAlloc((size_t)outSize);
280: if (outBuffer == 0)
281: throw "Can not allocate memory";
282: if (!dictionaryIsDefined)
283: dictionary = 1 << 23;
284: int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed,
285: dictionary, SZ_FILTER_AUTO);
286: if (res != 0)
287: {
288: fprintf(stderr, "\nEncoder error = %d\n", (int)res);
289: return 1;
290: }
291: }
292: else
293: {
294: size_t outSize;
295: if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0)
296: throw "data error";
297: outBuffer = (Byte *)MyAlloc(outSize);
298: if (outBuffer == 0)
299: throw "Can not allocate memory";
300:
301: int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free);
302: if (res != 0)
303: throw "LzmaDecoder error";
304: }
305: if (outStream->Write(outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK)
306: throw "Can not write";
307: MyFree(outBuffer);
308: MyFree(inBuffer);
309: return 0;
310: }
311:
312:
313: UInt64 fileSize;
314: if (encodeMode)
315: {
316: NCompress::NLZMA::CEncoder *encoderSpec =
317: new NCompress::NLZMA::CEncoder;
318: CMyComPtr<ICompressCoder> encoder = encoderSpec;
319:
320: if (!dictionaryIsDefined)
321: dictionary = 1 << 23;
322:
323: UInt32 posStateBits = 2;
324: UInt32 litContextBits = 3; // for normal files
325: // UInt32 litContextBits = 0; // for 32-bit data
326: UInt32 litPosBits = 0;
327: // UInt32 litPosBits = 2; // for 32-bit data
328: UInt32 algorithm = 2;
329: UInt32 numFastBytes = 128;
330:
331: bool eos = parser[NKey::kEOS].ThereIs || stdInMode;
332:
333: if(parser[NKey::kMode].ThereIs)
334: if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm))
335: IncorrectCommand();
336:
337: if(parser[NKey::kFastBytes].ThereIs)
338: if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes))
339: IncorrectCommand();
340: if(parser[NKey::kLitContext].ThereIs)
341: if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits))
342: IncorrectCommand();
343: if(parser[NKey::kLitPos].ThereIs)
344: if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits))
345: IncorrectCommand();
346: if(parser[NKey::kPosBits].ThereIs)
347: if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits))
348: IncorrectCommand();
349:
350: PROPID propIDs[] =
351: {
352: NCoderPropID::kDictionarySize,
353: NCoderPropID::kPosStateBits,
354: NCoderPropID::kLitContextBits,
355: NCoderPropID::kLitPosBits,
356: NCoderPropID::kAlgorithm,
357: NCoderPropID::kNumFastBytes,
358: NCoderPropID::kMatchFinder,
359: NCoderPropID::kEndMarker
360: };
361: const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
362: /*
363: NWindows::NCOM::CPropVariant properties[kNumProps];
364: properties[0] = UInt32(dictionary);
365: properties[1] = UInt32(posStateBits);
366: properties[2] = UInt32(litContextBits);
367:
368: properties[3] = UInt32(litPosBits);
369: properties[4] = UInt32(algorithm);
370: properties[5] = UInt32(numFastBytes);
371: properties[6] = mf;
372: properties[7] = eos;
373: */
374: PROPVARIANT properties[kNumProps];
375: for (int p = 0; p < 6; p++)
376: properties[p].vt = VT_UI4;
377: properties[0].ulVal = UInt32(dictionary);
378: properties[1].ulVal = UInt32(posStateBits);
379: properties[2].ulVal = UInt32(litContextBits);
380: properties[3].ulVal = UInt32(litPosBits);
381: properties[4].ulVal = UInt32(algorithm);
382: properties[5].ulVal = UInt32(numFastBytes);
383:
384: properties[6].vt = VT_BSTR;
385: properties[6].bstrVal = (BSTR)(const wchar_t *)mf;
386:
387: properties[7].vt = VT_BOOL;
388: properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE;
389:
390: if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
391: IncorrectCommand();
392: encoderSpec->WriteCoderProperties(outStream);
393:
394: if (eos || stdInMode)
395: fileSize = (UInt64)(Int64)-1;
396: else
397: inStreamSpec->File.GetLength(fileSize);
398:
399: for (int i = 0; i < 8; i++)
400: {
401: Byte b = Byte(fileSize >> (8 * i));
402: if (outStream->Write(&b, sizeof(b), 0) != S_OK)
403: {
404: fprintf(stderr, "Write error");
405: return 1;
406: }
407: }
408: HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);
409: if (result == E_OUTOFMEMORY)
410: {
411: fprintf(stderr, "\nError: Can not allocate memory\n");
412: return 1;
413: }
414: else if (result != S_OK)
415: {
416: fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result);
417: return 1;
418: }
419: }
420: else
421: {
422: NCompress::NLZMA::CDecoder *decoderSpec =
423: new NCompress::NLZMA::CDecoder;
424: CMyComPtr<ICompressCoder> decoder = decoderSpec;
425: const UInt32 kPropertiesSize = 5;
426: Byte properties[kPropertiesSize];
427: UInt32 processedSize;
428: if (inStream->Read(properties, kPropertiesSize, &processedSize) != S_OK)
429: {
430: fprintf(stderr, "Read error");
431: return 1;
432: }
433: if (processedSize != kPropertiesSize)
434: {
435: fprintf(stderr, "Read error");
436: return 1;
437: }
438: if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK)
439: {
440: fprintf(stderr, "SetDecoderProperties error");
441: return 1;
442: }
443: fileSize = 0;
444: for (int i = 0; i < 8; i++)
445: {
446: Byte b;
447: if (inStream->Read(&b, sizeof(b), &processedSize) != S_OK)
448: {
449: fprintf(stderr, "Read error");
450: return 1;
451: }
452: if (processedSize != 1)
453: {
454: fprintf(stderr, "Read error");
455: return 1;
456: }
457: fileSize |= ((UInt64)b) << (8 * i);
458: }
459: if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK)
460: {
461: fprintf(stderr, "Decoder error");
462: return 1;
463: }
464: }
465: return 0;
466: }
467:
468: int main(int n, const char *args[])
469: {
470: try { return main2(n, args); }
471: catch(const char *s)
472: {
473: fprintf(stderr, "\nError: %s\n", s);
474: return 1;
475: }
476: catch(...)
477: {
478: fprintf(stderr, "\nError\n");
479: return 1;
480: }
481: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>