diff options
Diffstat (limited to 'CPP/7zip/UI/Console/HashCon.cpp')
-rw-r--r-- | CPP/7zip/UI/Console/HashCon.cpp | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp new file mode 100644 index 00000000..273f21c8 --- /dev/null +++ b/CPP/7zip/UI/Console/HashCon.cpp @@ -0,0 +1,274 @@ +// HashCon.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/ErrorMsg.h" + +#include "ConsoleClose.h" +#include "HashCon.h" + +static const wchar_t *kEmptyFileAlias = L"[Content]"; + +static const char *kScanningMessage = "Scanning"; + +HRESULT CHashCallbackConsole::CheckBreak() +{ + return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; +} + +HRESULT CHashCallbackConsole::StartScanning() +{ + (*OutStream) << kScanningMessage; + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */) +{ + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) +{ + return CanNotFindError_Base(name, systemError); +} + +HRESULT CHashCallbackConsole::FinishScanning() +{ + (*OutStream) << endl << endl; + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::SetNumFiles(UInt64 /* numFiles */) +{ + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::SetTotal(UInt64 size) +{ + if (EnablePercents) + m_PercentPrinter.SetTotal(size); + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue) +{ + if (completeValue && EnablePercents) + { + m_PercentPrinter.SetRatio(*completeValue); + m_PercentPrinter.PrintRatio(); + } + return CheckBreak(); +} + +static void AddMinuses(AString &s, unsigned num) +{ + for (unsigned i = 0; i < num; i++) + s += '-'; +} + +static void SetSpaces(char *s, int num) +{ + for (int i = 0; i < num; i++) + s[i] = ' '; +} + +static void SetSpacesAndNul(char *s, int num) +{ + SetSpaces(s, num); + s[num] = 0; +} + +static void AddSpaces(UString &s, int num) +{ + for (int i = 0; i < num; i++) + s += ' '; +} + +static const int kSizeField_Len = 13; +static const int kNameField_Len = 12; + +static unsigned GetColumnWidth(unsigned digestSize) +{ + unsigned width = digestSize * 2; + const unsigned kMinColumnWidth = 8; + return width < kMinColumnWidth ? kMinColumnWidth: width; +} + +void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector<CHasherState> &hashers) +{ + AString s; + for (unsigned i = 0; i < hashers.Size(); i++) + { + const CHasherState &h = hashers[i]; + AddMinuses(s, GetColumnWidth(h.DigestSize)); + s += ' '; + } + AddMinuses(s, kSizeField_Len); + s += " "; + AddMinuses(s, kNameField_Len); + m_PercentPrinter.PrintString(s); + m_PercentPrinter.PrintNewLine(); +} + +HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb) +{ + UString s; + FOR_VECTOR (i, hb.Hashers) + { + const CHasherState &h = hb.Hashers[i]; + s += h.Name; + AddSpaces(s, (int)GetColumnWidth(h.DigestSize) - h.Name.Len() + 1); + } + UString s2 = L"Size"; + AddSpaces(s, kSizeField_Len - s2.Len()); + s += s2; + s += L" "; + s += L"Name"; + m_PercentPrinter.PrintString(s); + m_PercentPrinter.PrintNewLine(); + PrintSeparatorLine(hb.Hashers); + return CheckBreak(); +} + +HRESULT CHashCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) +{ + FailedCodes.Add(systemError); + FailedFiles.Add(name); + // if (systemError == ERROR_SHARING_VIOLATION) + { + m_PercentPrinter.PrintString(name); + m_PercentPrinter.PrintString(": WARNING: "); + m_PercentPrinter.PrintString(NWindows::NError::MyFormatMessage(systemError)); + return S_FALSE; + } + // return systemError; +} + +HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */) +{ + m_FileName = name; + return CheckBreak(); +} + +void CHashCallbackConsole::PrintResultLine(UInt64 fileSize, + const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash) +{ + FOR_VECTOR (i, hashers) + { + const CHasherState &h = hashers[i]; + + char s[k_HashCalc_DigestSize_Max * 2 + 64]; + s[0] = 0; + if (showHash) + AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize); + SetSpacesAndNul(s + strlen(s), (int)GetColumnWidth(h.DigestSize) - (int)strlen(s) + 1); + m_PercentPrinter.PrintString(s); + } + char s[64]; + s[0] = 0; + char *p = s; + if (showHash && fileSize != 0) + { + p = s + 32; + ConvertUInt64ToString(fileSize, p); + int numSpaces = kSizeField_Len - (int)strlen(p); + if (numSpaces > 0) + { + p -= numSpaces; + SetSpaces(p, numSpaces); + } + } + else + SetSpacesAndNul(s, kSizeField_Len - (int)strlen(s)); + unsigned len = (unsigned)strlen(p); + p[len] = ' '; + p[len + 1] = ' '; + p[len + 2] = 0; + m_PercentPrinter.PrintString(p); +} + +HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) +{ + PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash); + if (m_FileName.IsEmpty()) + m_PercentPrinter.PrintString(kEmptyFileAlias); + else + m_PercentPrinter.PrintString(m_FileName); + m_PercentPrinter.PrintNewLine(); + return S_OK; +} + +static const char *k_DigestTitles[] = +{ + " :" + , " for data: " + , " for data and names: " + , " for streams and names: " +}; + +static void PrintSum(CStdOutStream &p, const CHasherState &h, unsigned digestIndex) +{ + char s[k_HashCalc_DigestSize_Max * 2 + 64]; + UString name = h.Name; + AddSpaces(name, 6 - (int)name.Len()); + p << name; + p << k_DigestTitles[digestIndex]; + s[0] = 0; + AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize); + p << s; + p << "\n"; +} + + +void PrintHashStat(CStdOutStream &p, const CHashBundle &hb) +{ + FOR_VECTOR (i, hb.Hashers) + { + const CHasherState &h = hb.Hashers[i]; + p << "\n"; + PrintSum(p, h, k_HashCalc_Index_DataSum); + if (hb.NumFiles != 1 || hb.NumDirs != 0) + PrintSum(p, h, k_HashCalc_Index_NamesSum); + if (hb.NumAltStreams != 0) + PrintSum(p, h, k_HashCalc_Index_StreamsSum); + } +} + +void CHashCallbackConsole::PrintProperty(const char *name, UInt64 value) +{ + char s[32]; + s[0] = ':'; + s[1] = ' '; + ConvertUInt64ToString(value, s + 2); + m_PercentPrinter.PrintString(name); + m_PercentPrinter.PrintString(s); + m_PercentPrinter.PrintNewLine(); +} + +HRESULT CHashCallbackConsole::AfterLastFile(const CHashBundle &hb) +{ + PrintSeparatorLine(hb.Hashers); + + PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true); + m_PercentPrinter.PrintNewLine(); + m_PercentPrinter.PrintNewLine(); + + if (hb.NumFiles != 1 || hb.NumDirs != 0) + { + if (hb.NumDirs != 0) + PrintProperty("Folders", hb.NumDirs); + PrintProperty("Files", hb.NumFiles); + } + PrintProperty("Size", hb.FilesSize); + if (hb.NumAltStreams != 0) + { + PrintProperty("AltStreams", hb.NumAltStreams); + PrintProperty("AltStreams size", hb.AltStreamsSize); + } + PrintHashStat(*m_PercentPrinter.OutStream, hb); + m_PercentPrinter.PrintNewLine(); + return S_OK; +} |