private Stream GetCachedDecoderStream(CArchiveDatabaseEx _db, int folderIndex, IPasswordProvider pw) { Stream s; if (!_cachedStreams.TryGetValue(folderIndex, out s)) { CFolder folderInfo = _db.Folders[folderIndex]; int packStreamIndex = _db.Folders[folderIndex].FirstPackStreamId; long folderStartPackPos = _db.GetFolderStreamPos(folderIndex, 0); List<long> packSizes = new List<long>(); for (int j = 0; j < folderInfo.PackStreams.Count; j++) packSizes.Add(_db.PackSizes[packStreamIndex + j]); s = DecoderStreamHelper.CreateDecoderStream(_stream, folderStartPackPos, packSizes.ToArray(), folderInfo, pw); if (!s.CanSeek) s = new ManagedLzma._7zip.Decoder.FileBufferedDecoderStream(s); _cachedStreams.Add(folderIndex, s); } return s; }
public void Extract(CArchiveDatabaseEx _db, int[] indices, IPasswordProvider pw) { int numItems; bool allFilesMode = (indices == null); if (allFilesMode) numItems = _db.Files.Count; else numItems = indices.Length; if (numItems == 0) return; List<CExtractFolderInfo> extractFolderInfoVector = new List<CExtractFolderInfo>(); for (int i = 0; i < numItems; i++) { int fileIndex = allFilesMode ? i : indices[i]; int folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == -1) { extractFolderInfoVector.Add(new CExtractFolderInfo(fileIndex, -1)); continue; } if (extractFolderInfoVector.Count == 0 || folderIndex != extractFolderInfoVector.Last().FolderIndex) extractFolderInfoVector.Add(new CExtractFolderInfo(-1, folderIndex)); CExtractFolderInfo efi = extractFolderInfoVector.Last(); int startIndex = _db.FolderStartFileIndex[folderIndex]; for (int index = efi.ExtractStatuses.Count; index <= fileIndex - startIndex; index++) efi.ExtractStatuses.Add(index == fileIndex - startIndex); } foreach (CExtractFolderInfo efi in extractFolderInfoVector) { int startIndex; if (efi.FileIndex != -1) startIndex = efi.FileIndex; else startIndex = _db.FolderStartFileIndex[efi.FolderIndex]; var outStream = new FolderUnpackStream(_db, 0, startIndex, efi.ExtractStatuses); if (efi.FileIndex != -1) continue; int folderIndex = efi.FolderIndex; CFolder folderInfo = _db.Folders[folderIndex]; int packStreamIndex = _db.Folders[folderIndex].FirstPackStreamId; long folderStartPackPos = _db.GetFolderStreamPos(folderIndex, 0); List<long> packSizes = new List<long>(); for (int j = 0; j < folderInfo.PackStreams.Count; j++) packSizes.Add(_db.PackSizes[packStreamIndex + j]); // TODO: If the decoding fails the last file may be extracted incompletely. Delete it? Stream s = DecoderStreamHelper.CreateDecoderStream(_stream, folderStartPackPos, packSizes.ToArray(), folderInfo, pw); byte[] buffer = new byte[4 << 10]; for (;;) { int processed = s.Read(buffer, 0, buffer.Length); if (processed == 0) break; outStream.Write(buffer, 0, processed); } } }