summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lzma/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/lzma/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp')
-rw-r--r--3rdparty/lzma/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp633
1 files changed, 421 insertions, 212 deletions
diff --git a/3rdparty/lzma/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/3rdparty/lzma/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
index e0f4dcba3d4..5ca288f4696 100644
--- a/3rdparty/lzma/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
+++ b/3rdparty/lzma/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -12,7 +12,7 @@
#define MY_SET_BINARY_MODE(file)
#endif
-// #include "../../../Common/MyWindows.h"
+#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../../C/7zVersion.h"
@@ -25,6 +25,7 @@
#include "../../../Windows/System.h"
#endif
+#include "../../../Common/IntToString.h"
#include "../../../Common/CommandLineParser.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/StringToInt.h"
@@ -36,14 +37,41 @@
#include "../../Compress/LzmaEncoder.h"
#include "../../UI/Console/BenchCon.h"
-
+#include "../../UI/Console/ConsoleClose.h"
using namespace NCommandLineParser;
+static const unsigned kDictSizeLog = 24;
+
+static const char *kCopyrightString = "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n\n";
+
+static const char *kHelpString =
+ "Usage: LZMA <command> [inputFile] [outputFile] [<switches>...]\n"
+ "\n"
+ "<command>\n"
+ " e : Encode file\n"
+ " d : Decode file\n"
+ " b : Benchmark\n"
+ "<switches>\n"
+ " -a{N} : set compression mode : [0, 1] : default = 1 (max)\n"
+ " -d{N} : set dictionary size : [12, 30] : default = 24 (16 MiB)\n"
+ " -fb{N} : set number of fast bytes : [5, 273] : default = 128\n"
+ " -mc{N} : set number of cycles for match finder\n"
+ " -lc{N} : set number of literal context bits : [0, 8] : default = 3\n"
+ " -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n"
+ " -pb{N} : set number of pos bits : [0, 4] : default = 2\n"
+ " -mf{M} : set match finder: [hc4, bt2, bt3, bt4] : default = bt4\n"
+ " -mt{N} : set number of CPU threads\n"
+ " -eos : write end of stream marker\n"
+ " -si : read data from stdin\n"
+ " -so : write data to stdout\n";
+
+
static const char *kCantAllocate = "Can not allocate memory";
static const char *kReadError = "Read error";
static const char *kWriteError = "Write error";
+
namespace NKey {
enum Enum
{
@@ -69,101 +97,214 @@ enum Enum
static const CSwitchForm kSwitchForms[] =
{
- { L"?", NSwitchType::kSimple, false },
- { L"H", NSwitchType::kSimple, false },
- { L"MM", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"X", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"A", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"D", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"FB", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"MC", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"LC", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"LP", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"PB", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"MF", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"MT", NSwitchType::kUnLimitedPostString, false, 0 },
- { L"EOS", NSwitchType::kSimple, false },
- { L"SI", NSwitchType::kSimple, false },
- { L"SO", NSwitchType::kSimple, false },
- { L"F86", NSwitchType::kPostChar, false, 0, 0, L"+" }
+ { "?", NSwitchType::kSimple, false },
+ { "H", NSwitchType::kSimple, false },
+ { "MM", NSwitchType::kString, false, 1 },
+ { "X", NSwitchType::kString, false, 1 },
+ { "A", NSwitchType::kString, false, 1 },
+ { "D", NSwitchType::kString, false, 1 },
+ { "FB", NSwitchType::kString, false, 1 },
+ { "MC", NSwitchType::kString, false, 1 },
+ { "LC", NSwitchType::kString, false, 1 },
+ { "LP", NSwitchType::kString, false, 1 },
+ { "PB", NSwitchType::kString, false, 1 },
+ { "MF", NSwitchType::kString, false, 1 },
+ { "MT", NSwitchType::kString, false, 0 },
+ { "EOS", NSwitchType::kSimple, false },
+ { "SI", NSwitchType::kSimple, false },
+ { "SO", NSwitchType::kSimple, false },
+ { "F86", NSwitchType::kChar, false, 0, "+" }
};
-static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]);
-static void PrintMessage(const char *s)
+static void PrintErr(const char *s)
{
fputs(s, stderr);
}
+static void PrintErr_LF(const char *s)
+{
+ PrintErr(s);
+ fputc('\n', stderr);
+}
+
+
+static void PrintError(const char *s)
+{
+ PrintErr("\nERROR: ");
+ PrintErr_LF(s);
+}
+
+static void PrintError2(const char *s1, const wchar_t *s2)
+{
+ PrintError(s1);
+ PrintErr_LF(GetOemString(s2));
+}
+
+static void PrintError_int(const char *s, int code)
+{
+ PrintError(s);
+ char temp[32];
+ ConvertInt64ToString(code, temp);
+ PrintErr("Error code = ");
+ PrintErr_LF(temp);
+}
+
+
+
+static void Print(const char *s)
+{
+ fputs(s, stdout);
+}
+
+static void Print_UInt64(UInt64 v)
+{
+ char temp[32];
+ ConvertUInt64ToString(v, temp);
+ Print(temp);
+}
+
+static void Print_MB(UInt64 v)
+{
+ Print_UInt64(v);
+ Print(" MiB");
+}
+
+static void Print_Size(const char *s, UInt64 v)
+{
+ Print(s);
+ Print_UInt64(v);
+ Print(" (");
+ Print_MB(v >> 20);
+ Print(")\n");
+}
+
+static void PrintTitle()
+{
+ Print(kCopyrightString);
+}
+
static void PrintHelp()
{
- PrintMessage("\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n"
- " e: encode file\n"
- " d: decode file\n"
- " b: Benchmark\n"
- "<Switches>\n"
- " -a{N}: set compression mode - [0, 1], default: 1 (max)\n"
- " -d{N}: set dictionary size - [12, 30], default: 23 (8MB)\n"
- " -fb{N}: set number of fast bytes - [5, 273], default: 128\n"
- " -mc{N}: set number of cycles for match finder\n"
- " -lc{N}: set number of literal context bits - [0, 8], default: 3\n"
- " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n"
- " -pb{N}: set number of pos bits - [0, 4], default: 2\n"
- " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n"
- " -mt{N}: set number of CPU threads\n"
- " -eos: write End Of Stream marker\n"
- " -si: read data from stdin\n"
- " -so: write data to stdout\n"
- );
+ PrintTitle();
+ Print(kHelpString);
}
-static void PrintHelpAndExit(const char *s)
+class CProgressPrint:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
{
- fprintf(stderr, "\nError: %s\n\n", s);
- PrintHelp();
- throw -1;
+ UInt64 _size1;
+ UInt64 _size2;
+public:
+ CProgressPrint(): _size1(0), _size2(0) {}
+
+ void ClosePrint();
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+#define BACK_STR \
+"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
+static const char *kBackSpaces =
+BACK_STR
+" "
+BACK_STR;
+
+
+void CProgressPrint::ClosePrint()
+{
+ Print(kBackSpaces);
}
-static void IncorrectCommand()
+STDMETHODIMP CProgressPrint::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
{
- PrintHelpAndExit("Incorrect command");
+ if (NConsoleClose::TestBreakSignal())
+ return E_ABORT;
+ if (inSize)
+ {
+ UInt64 v1 = *inSize >> 20;
+ UInt64 v2 = _size2;
+ if (outSize)
+ v2 = *outSize >> 20;
+ if (v1 != _size1 || v2 != _size2)
+ {
+ _size1 = v1;
+ _size2 = v2;
+ ClosePrint();
+ Print_MB(_size1);
+ Print(" -> ");
+ Print_MB(_size2);
+ }
+ }
+ return S_OK;
}
-static void WriteArgumentsToStringList(int numArgs, const char *args[], UStringVector &strings)
+
+static void IncorrectCommand()
{
- for (int i = 1; i < numArgs; i++)
- strings.Add(MultiByteToUnicodeString(args[i]));
+ throw "Incorrect command";
}
-static bool GetNumber(const wchar_t *s, UInt32 &value)
+static UInt32 GetNumber(const wchar_t *s)
{
- value = 0;
- if (MyStringLen(s) == 0)
- return false;
const wchar_t *end;
- UInt64 res = ConvertStringToUInt64(s, &end);
- if (*end != L'\0')
- return false;
- if (res > 0xFFFFFFFF)
- return false;
- value = UInt32(res);
- return true;
+ UInt32 v = ConvertStringToUInt32(s, &end);
+ if (*end != 0)
+ IncorrectCommand();
+ return v;
}
-static void ParseUInt32(const CParser &parser, int index, UInt32 &res)
+static void ParseUInt32(const CParser &parser, unsigned index, UInt32 &res)
{
if (parser[index].ThereIs)
- if (!GetNumber(parser[index].PostStrings[0], res))
- IncorrectCommand();
+ res = GetNumber(parser[index].PostStrings[0]);
}
-#define NT_CHECK_FAIL_ACTION PrintMessage("Unsupported Windows version"); return 1;
-int main2(int numArgs, const char *args[])
+static int Error_HRESULT(const char *s, HRESULT res)
{
- NT_CHECK
+ if (res == E_ABORT)
+ {
+ Print("\n\nBreak signaled\n");
+ return 255;
+ }
+
+ PrintError(s);
+
+ if (res == E_OUTOFMEMORY)
+ {
+ PrintErr_LF(kCantAllocate);
+ return 8;
+ }
+ if (res == E_INVALIDARG)
+ {
+ PrintErr_LF("Ununsupported parameter");
+ }
+ else
+ {
+ char temp[32];
+ ConvertUInt32ToHex(res, temp);
+ PrintErr("Error code = 0x");
+ PrintErr_LF(temp);
+ }
+ return 1;
+}
- PrintMessage("\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n");
+#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;
+
+static void AddProp(CObjectVector<CProperty> &props2, const char *name, const wchar_t *val)
+{
+ CProperty &prop = props2.AddNew();
+ prop.Name.SetFromAscii(name);
+ prop.Value = val;
+}
+
+static int main2(int numArgs, const char *args[])
+{
+ NT_CHECK
if (numArgs == 1)
{
@@ -171,19 +312,24 @@ int main2(int numArgs, const char *args[])
return 0;
}
- bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4);
+ /*
+ bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 8);
if (unsupportedTypes)
- {
- PrintMessage("Unsupported base types. Edit Common/Types.h and recompile");
- return 1;
- }
+ throw "Unsupported base types. Edit Common/Types.h and recompile";
+ */
UStringVector commandStrings;
- WriteArgumentsToStringList(numArgs, args, commandStrings);
- CParser parser(kNumSwitches);
+ for (int i = 1; i < numArgs; i++)
+ commandStrings.Add(MultiByteToUnicodeString(args[i]));
+
+ CParser parser(ARRAY_SIZE(kSwitchForms));
try
{
- parser.ParseStrings(kSwitchForms, commandStrings);
+ if (!parser.ParseStrings(kSwitchForms, commandStrings))
+ {
+ PrintError2(parser.ErrorMessage, parser.ErrorLine);
+ return 1;
+ }
}
catch(...)
{
@@ -195,40 +341,41 @@ int main2(int numArgs, const char *args[])
PrintHelp();
return 0;
}
- const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
- int paramIndex = 0;
- if (paramIndex >= nonSwitchStrings.Size())
+ bool stdInMode = parser[NKey::kStdIn].ThereIs;
+ bool stdOutMode = parser[NKey::kStdOut].ThereIs;
+
+ if (!stdOutMode)
+ PrintTitle();
+
+ const UStringVector &params = parser.NonSwitchStrings;
+
+ unsigned paramIndex = 0;
+ if (paramIndex >= params.Size())
IncorrectCommand();
- const UString &command = nonSwitchStrings[paramIndex++];
+ const UString &command = params[paramIndex++];
- CObjectVector<CProperty> props;
+ CObjectVector<CProperty> props2;
bool dictDefined = false;
UInt32 dict = (UInt32)(Int32)-1;
+
if (parser[NKey::kDict].ThereIs)
{
- UInt32 dicLog;
+ UInt32 dictLog;
const UString &s = parser[NKey::kDict].PostStrings[0];
- if (!GetNumber(s, dicLog))
- IncorrectCommand();
- dict = 1 << dicLog;
+ dictLog = GetNumber(s);
+ dict = 1 << dictLog;
dictDefined = true;
- CProperty prop;
- prop.Name = L"d";
- prop.Value = s;
- props.Add(prop);
+ AddProp(props2, "d", s);
}
+
if (parser[NKey::kLevel].ThereIs)
{
- UInt32 level = 5;
const UString &s = parser[NKey::kLevel].PostStrings[0];
- if (!GetNumber(s, level))
- IncorrectCommand();
- CProperty prop;
- prop.Name = L"x";
- prop.Value = s;
- props.Add(prop);
+ /* UInt32 level = */ GetNumber(s);
+ AddProp(props2, "x", s);
}
+
UString mf = L"BT4";
if (parser[NKey::kMatchFinder].ThereIs)
mf = parser[NKey::kMatchFinder].PostStrings[0];
@@ -236,70 +383,64 @@ int main2(int numArgs, const char *args[])
UInt32 numThreads = (UInt32)(Int32)-1;
#ifndef _7ZIP_ST
+
if (parser[NKey::kMultiThread].ThereIs)
{
- UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
const UString &s = parser[NKey::kMultiThread].PostStrings[0];
if (s.IsEmpty())
- numThreads = numCPUs;
+ numThreads = NWindows::NSystem::GetNumberOfProcessors();
else
- if (!GetNumber(s, numThreads))
- IncorrectCommand();
- CProperty prop;
- prop.Name = L"mt";
- prop.Value = s;
- props.Add(prop);
+ numThreads = GetNumber(s);
+ AddProp(props2, "mt", s);
}
+
#endif
+
if (parser[NKey::kMethod].ThereIs)
{
- UString s = parser[NKey::kMethod].PostStrings[0];
+ const UString &s = parser[NKey::kMethod].PostStrings[0];
if (s.IsEmpty() || s[0] != '=')
IncorrectCommand();
- CProperty prop;
- prop.Name = L"m";
- prop.Value = s.Mid(1);
- props.Add(prop);
+ AddProp(props2, "m", s.Ptr(1));
}
- if (command.CompareNoCase(L"b") == 0)
+ if (StringsAreEqualNoCase_Ascii(command, "b"))
{
- const UInt32 kNumDefaultItereations = 1;
- UInt32 numIterations = kNumDefaultItereations;
- {
- if (paramIndex < nonSwitchStrings.Size())
- if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))
- numIterations = kNumDefaultItereations;
- }
- HRESULT res = BenchCon(props, numIterations, stderr);
- if (res != S_OK)
- {
- if (res != E_ABORT)
- {
- PrintMessage("Benchmark Error");
- return 1;
- }
- }
- return 0;
+ UInt32 numIterations = 1;
+ if (paramIndex < params.Size())
+ numIterations = GetNumber(params[paramIndex++]);
+ if (params.Size() != paramIndex)
+ IncorrectCommand();
+
+ HRESULT res = BenchCon(props2, numIterations, stdout);
+
+ if (res == S_OK)
+ return 0;
+ return Error_HRESULT("Benchmark error", res);
+ }
+
+ {
+ UInt32 needParams = 3;
+ if (stdInMode) needParams--;
+ if (stdOutMode) needParams--;
+ if (needParams != params.Size())
+ IncorrectCommand();
}
if (numThreads == (UInt32)(Int32)-1)
numThreads = 1;
bool encodeMode = false;
- if (command.CompareNoCase(L"e") == 0)
+
+ if (StringsAreEqualNoCase_Ascii(command, "e"))
encodeMode = true;
- else if (command.CompareNoCase(L"d") == 0)
- encodeMode = false;
- else
+ else if (!StringsAreEqualNoCase_Ascii(command, "d"))
IncorrectCommand();
- bool stdInMode = parser[NKey::kStdIn].ThereIs;
- bool stdOutMode = parser[NKey::kStdOut].ThereIs;
-
CMyComPtr<ISequentialInStream> inStream;
- CInFileStream *inStreamSpec = 0;
+ CInFileStream *inStreamSpec = NULL;
+
if (stdInMode)
{
inStream = new CStdInFileStream;
@@ -307,21 +448,19 @@ int main2(int numArgs, const char *args[])
}
else
{
- if (paramIndex >= nonSwitchStrings.Size())
- IncorrectCommand();
- const UString &inputName = nonSwitchStrings[paramIndex++];
+ const UString &inputName = params[paramIndex++];
inStreamSpec = new CInFileStream;
inStream = inStreamSpec;
if (!inStreamSpec->Open(us2fs(inputName)))
{
- fprintf(stderr, "\nError: can not open input file %s\n",
- (const char *)GetOemString(inputName));
+ PrintError2("can not open input file", inputName);
return 1;
}
}
CMyComPtr<ISequentialOutStream> outStream;
COutFileStream *outStreamSpec = NULL;
+
if (stdOutMode)
{
outStream = new CStdOutFileStream;
@@ -329,99 +468,148 @@ int main2(int numArgs, const char *args[])
}
else
{
- if (paramIndex >= nonSwitchStrings.Size())
- IncorrectCommand();
- const UString &outputName = nonSwitchStrings[paramIndex++];
+ const UString &outputName = params[paramIndex++];
outStreamSpec = new COutFileStream;
outStream = outStreamSpec;
if (!outStreamSpec->Create(us2fs(outputName), true))
{
- fprintf(stderr, "\nError: can not open output file %s\n",
- (const char *)GetOemString(outputName));
+ PrintError2("can not open output file", outputName);
return 1;
}
}
+ bool fileSizeDefined = false;
+ UInt64 fileSize = 0;
+
+ if (inStreamSpec)
+ {
+ if (!inStreamSpec->File.GetLength(fileSize))
+ throw "Can not get file length";
+ fileSizeDefined = true;
+ if (!stdOutMode)
+ Print_Size("Input size: ", fileSize);
+ }
+
+ if (encodeMode && !dictDefined)
+ {
+ dict = 1 << kDictSizeLog;
+ if (fileSizeDefined)
+ {
+ unsigned i;
+ for (i = 16; i < kDictSizeLog; i++)
+ if ((UInt32)((UInt32)1 << i) >= fileSize)
+ break;
+ dict = (UInt32)1 << i;
+ }
+ }
+
if (parser[NKey::kFilter86].ThereIs)
{
- // -f86 switch is for x86 filtered mode: BCJ + LZMA.
+ /* -f86 switch is for x86 filtered mode: BCJ + LZMA.
+ It uses modified header format.
+ It's not recommended to use -f86 mode now.
+ You can use xz format instead, if you want to use filters */
+
if (parser[NKey::kEOS].ThereIs || stdInMode)
throw "Can not use stdin in this mode";
- UInt64 fileSize;
- inStreamSpec->File.GetLength(fileSize);
- if (fileSize > 0xF0000000)
- throw "File is too big";
+
size_t inSize = (size_t)fileSize;
- Byte *inBuffer = 0;
+
+ if (inSize != fileSize)
+ throw "File is too big";
+
+ Byte *inBuffer = NULL;
+
if (inSize != 0)
{
inBuffer = (Byte *)MyAlloc((size_t)inSize);
- if (inBuffer == 0)
+ if (!inBuffer)
throw kCantAllocate;
}
if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK)
throw "Can not read";
- Byte *outBuffer = 0;
+ Byte *outBuffer = NULL;
size_t outSize;
+
if (encodeMode)
{
// we allocate 105% of original size for output buffer
- outSize = (size_t)fileSize / 20 * 21 + (1 << 16);
+ UInt64 outSize64 = fileSize / 20 * 21 + (1 << 16);
+
+ outSize = (size_t)outSize64;
+
+ if (outSize != outSize64)
+ throw "File is too big";
+
if (outSize != 0)
{
outBuffer = (Byte *)MyAlloc((size_t)outSize);
- if (outBuffer == 0)
+ if (!outBuffer)
throw kCantAllocate;
}
- if (!dictDefined)
- dict = 1 << 23;
+
int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize,
5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO);
+
if (res != 0)
{
- fprintf(stderr, "\nEncoder error = %d\n", (int)res);
+ PrintError_int("Encode error", (int)res);
return 1;
}
}
else
{
UInt64 outSize64;
+
if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0)
throw "data error";
+
outSize = (size_t)outSize64;
if (outSize != outSize64)
- throw "too big";
+ throw "Unpack size is too big";
if (outSize != 0)
{
outBuffer = (Byte *)MyAlloc(outSize);
- if (outBuffer == 0)
+ if (!outBuffer)
throw kCantAllocate;
}
+
int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize);
+
if (inSize != (size_t)fileSize)
throw "incorrect processed size";
if (res != 0)
- throw "LzmaDecoder error";
+ {
+ PrintError_int("Decode error", (int)res);
+ return 1;
+ }
}
+
if (WriteStream(outStream, outBuffer, outSize) != S_OK)
throw kWriteError;
+
MyFree(outBuffer);
MyFree(inBuffer);
- return 0;
}
+ else
+ {
+ CProgressPrint *progressSpec = NULL;
+ CMyComPtr<ICompressProgressInfo> progress;
+
+ if (!stdOutMode)
+ {
+ progressSpec = new CProgressPrint;
+ progress = progressSpec;
+ }
- UInt64 fileSize;
if (encodeMode)
{
NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder;
CMyComPtr<ICompressCoder> encoder = encoderSpec;
- if (!dictDefined)
- dict = 1 << 23;
-
UInt32 pb = 2;
UInt32 lc = 3; // = 0; for 32-bit data
UInt32 lp = 0; // = 2; for 32-bit data
@@ -440,8 +628,7 @@ int main2(int numArgs, const char *args[])
mcDefined = parser[NKey::kMc].ThereIs;
if (mcDefined)
- if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc))
- IncorrectCommand();
+ mc = GetNumber(parser[NKey::kMc].PostStrings[0]);
const PROPID propIDs[] =
{
@@ -456,7 +643,8 @@ int main2(int numArgs, const char *args[])
NCoderPropID::kNumThreads,
NCoderPropID::kMatchFinderCycles,
};
- const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]);
+
+ const unsigned kNumPropsMax = ARRAY_SIZE(propIDs);
PROPVARIANT props[kNumPropsMax];
for (int p = 0; p < 6; p++)
@@ -482,89 +670,110 @@ int main2(int numArgs, const char *args[])
props[9].vt = VT_UI4;
props[9].ulVal = (UInt32)mc;
- int numProps = kNumPropsMax;
+ unsigned numProps = kNumPropsMax;
if (!mcDefined)
numProps--;
- if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK)
- IncorrectCommand();
- encoderSpec->WriteCoderProperties(outStream);
+ HRESULT res = encoderSpec->SetCoderProperties(propIDs, props, numProps);
+ if (res != S_OK)
+ return Error_HRESULT("incorrect encoder properties", res);
- if (eos || stdInMode)
- fileSize = (UInt64)(Int64)-1;
- else
- inStreamSpec->File.GetLength(fileSize);
+ if (encoderSpec->WriteCoderProperties(outStream) != S_OK)
+ throw kWriteError;
- for (int i = 0; i < 8; i++)
- {
- Byte b = Byte(fileSize >> (8 * i));
- if (outStream->Write(&b, 1, 0) != S_OK)
- {
- PrintMessage(kWriteError);
- return 1;
- }
- }
- HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);
- if (result == E_OUTOFMEMORY)
+ bool fileSizeWasUsed = true;
+ if (eos || stdInMode)
{
- PrintMessage("\nError: Can not allocate memory\n");
- return 1;
+ fileSize = (UInt64)(Int64)-1;
+ fileSizeWasUsed = false;
}
- else if (result != S_OK)
+
{
- fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result);
- return 1;
+ Byte temp[8];
+ for (int i = 0; i < 8; i++)
+ temp[i]= (Byte)(fileSize >> (8 * i));
+ if (WriteStream(outStream, temp, 8) != S_OK)
+ throw kWriteError;
}
+
+ res = encoder->Code(inStream, outStream, NULL, NULL, progress);
+ if (progressSpec)
+ progressSpec->ClosePrint();
+
+ if (res != S_OK)
+ return Error_HRESULT("Encoding error", res);
+
+ UInt64 processedSize = encoderSpec->GetInputProcessedSize();
+
+ if (fileSizeWasUsed && processedSize != fileSize)
+ throw "Incorrect size of processed data";
}
else
{
NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder;
CMyComPtr<ICompressCoder> decoder = decoderSpec;
+
decoderSpec->FinishStream = true;
- const UInt32 kPropertiesSize = 5;
+
+ const unsigned kPropertiesSize = 5;
Byte header[kPropertiesSize + 8];
+
if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK)
- {
- PrintMessage(kReadError);
- return 1;
- }
+ throw kReadError;
+
if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK)
- {
- PrintMessage("SetDecoderProperties error");
- return 1;
- }
- fileSize = 0;
+ throw "SetDecoderProperties error";
+
+ UInt64 unpackSize = 0;
for (int i = 0; i < 8; i++)
- fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);
+ unpackSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);
+
+ bool unpackSizeDefined = (unpackSize != (UInt64)(Int64)-1);
+
+ HRESULT res = decoder->Code(inStream, outStream, NULL, unpackSizeDefined ? &unpackSize : NULL, progress);
+ if (progressSpec)
+ progressSpec->ClosePrint();
- if (decoder->Code(inStream, outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) != S_OK)
+ if (res != S_OK)
{
- PrintMessage("Decoder error");
- return 1;
+ if (res == S_FALSE)
+ {
+ PrintError("Decoding error");
+ return 1;
+ }
+ return Error_HRESULT("Decoding error", res);
}
+
+ if (unpackSizeDefined && unpackSize != decoderSpec->GetOutputProcessedSize())
+ throw "incorrect uncompressed size in header";
}
- if (outStreamSpec != NULL)
+ }
+
+ if (!stdOutMode)
+ Print_Size("Output size: ", outStreamSpec->ProcessedSize);
+
+ if (outStreamSpec)
{
if (outStreamSpec->Close() != S_OK)
- {
- PrintMessage("File closing error");
- return 1;
- }
+ throw "File closing error";
}
+
return 0;
}
int MY_CDECL main(int numArgs, const char *args[])
{
+ NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
+
try { return main2(numArgs, args); }
catch (const char *s)
{
- fprintf(stderr, "\nError: %s\n", s);
+ PrintError(s);
return 1;
}
catch(...)
{
- PrintMessage("\nError\n");
+ PrintError("Unknown Error");
return 1;
}
}