bool ParseVolumeSizes(const UString &s, CRecordVector<UInt64> &values) { values.Clear(); bool prevIsNumber = false; for (unsigned i = 0; i < s.Len();) { wchar_t c = s[i++]; if (c == L' ') continue; if (c == L'-') return true; if (prevIsNumber) { prevIsNumber = false; unsigned numBits = 0; switch (MyCharLower_Ascii(c)) { case 'b': continue; case 'k': numBits = 10; break; case 'm': numBits = 20; break; case 'g': numBits = 30; break; case 't': numBits = 40; break; } if (numBits != 0) { UInt64 &val = values.Back(); if (val >= ((UInt64)1 << (64 - numBits))) return false; val <<= numBits; for (; i < s.Len(); i++) if (s[i] == L' ') break; continue; } } i--; const wchar_t *start = s.Ptr(i); const wchar_t *end; UInt64 val = ConvertStringToUInt64(start, &end); if (start == end) return false; if (val == 0) return false; values.Add(val); prevIsNumber = true; i += (unsigned)(end - start); } return true; }
bool ParseVolumeSizes(const UString &s, CRecordVector<UInt64> &values) { values.Clear(); UStringVector destStrings; SplitString(s, destStrings); bool prevIsNumber = false; for (int i = 0; i < destStrings.Size(); i++) { UString subString = destStrings[i]; subString.MakeUpper(); if (subString.IsEmpty()) return false; if (subString == L"-") return true; if (prevIsNumber) { wchar_t c = subString[0]; UInt64 &value = values.Back(); prevIsNumber = false; switch(c) { case L'B': continue; case L'K': value <<= 10; continue; case L'M': value <<= 20; continue; case L'G': value <<= 30; continue; } } const wchar_t *start = subString; const wchar_t *end; UInt64 value = ConvertStringToUInt64(start, &end); if (start == end) return false; if (value == 0) return false; values.Add(value); prevIsNumber = true; UString rem = subString.Mid((int)(end - start)); if (!rem.IsEmpty()) destStrings.Insert(i + 1, rem); } return true; }
UInt64 GetNumberOfVolumes(UInt64 size, CRecordVector<UInt64> &volSizes) { if (size == 0 || volSizes.Size() == 0) return 1; UInt64 numVolumes = 0; for (int i = 0; i < volSizes.Size(); i++) { UInt64 volSize = volSizes[i]; numVolumes++; if (volSize >= size) return numVolumes; size -= volSize; } UInt64 volSize = volSizes.Back(); if (volSize == 0) return (UInt64)(Int64)-1; return numVolumes + (size - 1) / volSize + 1; }
static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } }
HRESULT CThreadSplit::ProcessVirt() { NFile::NIO::CInFile inFile; if (!inFile.Open(FilePath)) return GetLastError(); NFile::NIO::COutFile outFile; CMyBuffer bufferObject; if (!bufferObject.Allocate(kBufSize)) return E_OUTOFMEMORY; Byte *buffer = (Byte *)(void *)bufferObject; UInt64 curVolSize = 0; CVolSeqName seqName; seqName.SetNumDigits(NumVolumes); UInt64 length; if (!inFile.GetLength(length)) return GetLastError(); CProgressSync &sync = ProgressDialog.Sync; sync.SetProgress(length, 0); UInt64 pos = 0; UInt64 numFiles = 0; int volIndex = 0; for (;;) { UInt64 volSize; if (volIndex < VolumeSizes.Size()) volSize = VolumeSizes[volIndex]; else volSize = VolumeSizes.Back(); UInt32 needSize = (UInt32)(MyMin((UInt64)kBufSize, volSize - curVolSize)); UInt32 processedSize; if (!inFile.Read(buffer, needSize, processedSize)) return GetLastError(); if (processedSize == 0) break; needSize = processedSize; if (curVolSize == 0) { UString name = VolBasePath; name += L'.'; name += seqName.GetNextName(); sync.SetCurrentFileName(name); sync.SetNumFilesCur(numFiles++); if (!outFile.Create(name, false)) { HRESULT res = GetLastError(); ErrorPath1 = name; return res; } } if (!outFile.Write(buffer, needSize, processedSize)) return GetLastError(); if (needSize != processedSize) throw g_Message_FileWriteError; curVolSize += processedSize; if (curVolSize == volSize) { outFile.Close(); if (volIndex < VolumeSizes.Size()) volIndex++; curVolSize = 0; } pos += processedSize; RINOK(sync.SetPosAndCheckPaused(pos)); } sync.SetNumFilesCur(numFiles); return S_OK; }
HRESULT CThreadSplit::ProcessVirt() { NIO::CInFile inFile; if (!inFile.Open(FilePath)) return GetLastError(); CPreAllocOutFile outFile; CMyBuffer buffer; if (!buffer.Allocate(kBufSize)) return E_OUTOFMEMORY; CVolSeqName seqName; seqName.SetNumDigits(NumVolumes); UInt64 length; if (!inFile.GetLength(length)) return GetLastError(); CProgressSync &sync = Sync; sync.Set_NumBytesTotal(length); UInt64 pos = 0; UInt64 prev = 0; UInt64 numFiles = 0; unsigned volIndex = 0; for (;;) { UInt64 volSize; if (volIndex < VolumeSizes.Size()) volSize = VolumeSizes[volIndex]; else volSize = VolumeSizes.Back(); UInt32 needSize = kBufSize; { const UInt64 rem = volSize - outFile.Written; if (needSize > rem) needSize = (UInt32)rem; } UInt32 processedSize; if (!inFile.Read(buffer, needSize, processedSize)) return GetLastError(); if (processedSize == 0) return S_OK; needSize = processedSize; if (outFile.Written == 0) { FString name = VolBasePath; name += '.'; name += us2fs(seqName.GetNextName()); sync.Set_FilePath(fs2us(name)); if (!outFile.File.Create(name, false)) { HRESULT res = GetLastError(); AddErrorPath(name); return res; } UInt64 expectSize = volSize; if (pos < length) { const UInt64 rem = length - pos; if (expectSize > rem) expectSize = rem; } outFile.PreAlloc(expectSize); } if (!outFile.Write(buffer, needSize, processedSize)) return GetLastError(); if (needSize != processedSize) throw g_Message_FileWriteError; pos += processedSize; if (outFile.Written == volSize) { outFile.Close(); sync.Set_NumFilesCur(++numFiles); if (volIndex < VolumeSizes.Size()) volIndex++; } if (pos - prev >= ((UInt32)1 << 22) || outFile.Written == 0) { RINOK(sync.Set_NumBytesCur(pos)); prev = pos; } } }
void Process2() { // NCOM::CComInitializer comInitializer; ProgressDialog->WaitCreating(); NFile::NIO::CInFile inFile; if (!inFile.Open(FilePath)) throw L"Can not open file"; NFile::NIO::COutFile outFile; CMyBuffer bufferObject; if (!bufferObject.Allocate(kBufSize)) throw L"Can not allocate buffer"; Byte *buffer = (Byte *)(void *)bufferObject; UInt64 curVolSize = 0; CVolSeqName seqName; UInt64 length; if (!inFile.GetLength(length)) throw "error"; ProgressDialog->ProgressSynch.SetProgress(length, 0); UInt64 pos = 0; int volIndex = 0; for (;;) { UInt64 volSize; if (volIndex < VolumeSizes.Size()) volSize = VolumeSizes[volIndex]; else volSize = VolumeSizes.Back(); UInt32 needSize = (UInt32)(MyMin((UInt64)kBufSize, volSize - curVolSize)); UInt32 processedSize; if (!inFile.Read(buffer, needSize, processedSize)) throw L"Can not read input file"; if (processedSize == 0) break; needSize = processedSize; if (curVolSize == 0) { UString name = VolBasePath; name += L"."; name += seqName.GetNextName(); if (!outFile.Create(name, false)) throw L"Can not create output file"; ProgressDialog->ProgressSynch.SetCurrentFileName(name); } if (!outFile.Write(buffer, needSize, processedSize)) throw L"Can not write output file"; if (needSize != processedSize) throw L"Can not write output file"; curVolSize += processedSize; if (curVolSize == volSize) { outFile.Close(); if (volIndex < VolumeSizes.Size()) volIndex++; curVolSize = 0; } pos += processedSize; HRESULT res = ProgressDialog->ProgressSynch.SetPosAndCheckPaused(pos); if (res != S_OK) return; } }