diff options
Diffstat (limited to '3rdparty/lzma/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp')
-rw-r--r-- | 3rdparty/lzma/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp | 633 |
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 ¶ms = 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; } } |