5
#include "../../../Common/MyWindows.h"
6
#include "../../../Common/MyInitGuid.h"
10
#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
13
#define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY)
15
#define MY_SET_BINARY_MODE(file)
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 "../PPMD/PPMDDecoder.h"
26
#include "../PPMD/PPMDEncoder.h"
28
using namespace NCommandLineParser;
32
static inline bool IsItWindowsNT()
34
OSVERSIONINFO versionInfo;
35
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
36
if (!::GetVersionEx(&versionInfo))
38
return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
42
static const char *kCantAllocate = "Can not allocate memory";
43
static const char *kReadError = "Read error";
44
static const char *kWriteError = "Write error";
58
static const CSwitchForm kSwitchForms[] =
60
{ L"?", NSwitchType::kSimple, false },
61
{ L"H", NSwitchType::kSimple, false },
62
{ L"O", NSwitchType::kUnLimitedPostString, false, 1 },
63
{ L"M", NSwitchType::kUnLimitedPostString, false, 1 },
64
{ L"SI", NSwitchType::kSimple, false },
65
{ L"SO", NSwitchType::kSimple, false }
68
static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]);
70
static void PrintHelp()
72
fprintf(stderr, "\nUsage: PPMD <e|d> inputFile outputFile [<switches>...]\n"
79
" -o{N}: set order - [4, 32], default: 4\n"
80
" -m{N}: set memory size - [4,512], default: 4 (4 MB)\n"
81
" -si: read data from stdin (only with d)\n"
82
" -so: write data to stdout\n"
86
static void PrintHelpAndExit(const char *s)
88
fprintf(stderr, "\nError: %s\n\n", s);
93
static void IncorrectCommand()
95
PrintHelpAndExit("Incorrect command");
98
static void WriteArgumentsToStringList(int numArguments, const char *arguments[],
99
UStringVector &strings)
101
for(int i = 1; i < numArguments; i++)
102
strings.Add(MultiByteToUnicodeString(arguments[i]));
105
static bool GetNumber(const wchar_t *s, UInt32 &value)
108
if (MyStringLen(s) == 0)
111
UInt64 res = ConvertStringToUInt64(s, &end);
114
if (res > 0xFFFFFFFF)
120
int main2(int n, const char *args[])
123
g_IsNT = IsItWindowsNT();
126
fprintf(stderr, "\nPPMD 4.49 Copyright (c) 1999-2007 Igor Pavlov 2007-07-05\n");
134
bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4);
135
if (unsupportedTypes)
137
fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile");
141
UStringVector commandStrings;
142
WriteArgumentsToStringList(n, args, commandStrings);
143
CParser parser(kNumSwitches);
146
parser.ParseStrings(kSwitchForms, commandStrings);
153
if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
158
const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
161
if (paramIndex >= nonSwitchStrings.Size())
163
const UString &command = nonSwitchStrings[paramIndex++];
166
if (command.CompareNoCase(L"b") == 0)
168
const UInt32 kNumDefaultItereations = 1;
169
UInt32 numIterations = kNumDefaultItereations;
171
if (paramIndex < nonSwitchStrings.Size())
172
if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))
173
numIterations = kNumDefaultItereations;
175
return LzmaBenchCon(stderr, numIterations, numThreads, dictionary);
179
bool encodeMode = false;
180
if (command.CompareNoCase(L"e") == 0)
182
else if (command.CompareNoCase(L"d") == 0)
187
bool stdInMode = parser[NKey::kStdIn].ThereIs;
188
bool stdOutMode = parser[NKey::kStdOut].ThereIs;
190
CMyComPtr<ISequentialInStream> inStream;
191
CInFileStream *inStreamSpec = 0;
194
inStream = new CStdInFileStream;
195
MY_SET_BINARY_MODE(stdin);
199
if (paramIndex >= nonSwitchStrings.Size())
201
const UString &inputName = nonSwitchStrings[paramIndex++];
202
inStreamSpec = new CInFileStream;
203
inStream = inStreamSpec;
204
if (!inStreamSpec->Open(GetSystemString(inputName)))
206
fprintf(stderr, "\nError: can not open input file %s\n",
207
(const char *)GetOemString(inputName));
212
CMyComPtr<ISequentialOutStream> outStream;
215
outStream = new CStdOutFileStream;
216
MY_SET_BINARY_MODE(stdout);
220
if (paramIndex >= nonSwitchStrings.Size())
222
const UString &outputName = nonSwitchStrings[paramIndex++];
223
COutFileStream *outStreamSpec = new COutFileStream;
224
outStream = outStreamSpec;
225
if (!outStreamSpec->Create(GetSystemString(outputName), true))
227
fprintf(stderr, "\nError: can not open output file %s\n",
228
(const char *)GetOemString(outputName));
236
// NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
237
NCompress::NPPMD::CEncoder *encoderSpec = new NCompress::NPPMD::CEncoder;
238
CMyComPtr<ICompressCoder> encoder = encoderSpec;
244
if(parser[NKey::kOrder].ThereIs)
245
if (!GetNumber(parser[NKey::kOrder].PostStrings[0], order))
247
if (order < 4) order = 4;
250
if(parser[NKey::kUsedMemorySize].ThereIs)
251
if (!GetNumber(parser[NKey::kUsedMemorySize].PostStrings[0], memSize))
253
if (memSize < 4 ) memSize = 4;
259
NCoderPropID::kUsedMemorySize,
262
const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]);
264
PROPVARIANT properties[kNumPropsMax];
265
for (int p = 0; p < kNumPropsMax; p++)
266
properties[p].vt = VT_UI4;
268
properties[0].ulVal = memSize * 1024 * 1024; // memory
269
properties[1].ulVal = order;
271
int numProps = kNumPropsMax;
273
if (encoderSpec->SetCoderProperties(propIDs, properties, numProps) != S_OK)
275
encoderSpec->WriteCoderProperties(outStream);
278
if (eos || stdInMode)
279
fileSize = (UInt64)(Int64)-1;
282
inStreamSpec->File.GetLength(fileSize);
284
for (int i = 0; i < 8; i++)
286
Byte b = Byte(fileSize >> (8 * i));
287
if (outStream->Write(&b, 1, 0) != S_OK)
289
fprintf(stderr, kWriteError);
293
HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);
294
if (result == E_OUTOFMEMORY)
296
fprintf(stderr, "\nError: Can not allocate memory\n");
299
else if (result != S_OK)
301
fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result);
307
// NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder;
308
NCompress::NPPMD::CDecoder *decoderSpec = new NCompress::NPPMD::CDecoder;
309
CMyComPtr<ICompressCoder> decoder = decoderSpec;
310
const UInt32 kPropertiesSize = 5;
311
Byte header[kPropertiesSize + 8];
312
if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK)
314
fprintf(stderr, kReadError);
317
if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK)
319
fprintf(stderr, "SetDecoderProperties error");
323
for (int i = 0; i < 8; i++)
324
fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);
326
if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK)
328
fprintf(stderr, "Decoder error");
335
int main(int n, const char *args[])
337
try { return main2(n, args); }
340
fprintf(stderr, "\nError: %s\n", s);
345
fprintf(stderr, "\nError\n");