123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using SevenZip;
- namespace SevenRepacker
- {
- //SOURCE: https://stackoverflow.com/a/3729877/2430943 With modify
- public class BridgeStream : Stream
- {
- private readonly long? _length;
- private readonly SevenZipExtractor _inArchive;
- private readonly int _archiveIndex;
- private bool _isInit;
- private readonly BlockingCollection<byte[]> _blocks;
- private byte[] _currentBlock;
- private int _currentBlockIndex;
- public BridgeStream(int streamWriteCountCache, long? length, SevenZipExtractor inArchive, int archiveIndex)
- {
- _length = length;
- _inArchive = inArchive;
- _archiveIndex = archiveIndex;
- _blocks = new BlockingCollection<byte[]>(streamWriteCountCache);
- }
- public override bool CanTimeout => false;
- public override bool CanRead => true;
- /// <summary>
- /// FAKE!
- /// </summary>
- public override bool CanSeek => true;
- public override bool CanWrite => true;
- public override long Length => _length ?? throw new NotSupportedException();
- public override void Flush() { }
- public long TotalBytesWritten { get; private set; }
- public int WriteCount { get; private set; }
- public override long Position
- {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw new NotSupportedException();
- }
- public override void SetLength(long value)
- {
- throw new NotSupportedException();
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- ValidateBufferArgs(buffer, offset, count);
- if (!_isInit)
- {
- Task.Run(() =>
- {
- _inArchive.ExtractFile(_archiveIndex, this);
- CompleteWriting();
- });
- _isInit = true;
- }
- int bytesRead = 0;
- while (true)
- {
- if (_currentBlock != null)
- {
- int copy = Math.Min(count - bytesRead, _currentBlock.Length - _currentBlockIndex);
- Array.Copy(_currentBlock, _currentBlockIndex, buffer, offset + bytesRead, copy);
- _currentBlockIndex += copy;
- bytesRead += copy;
- if (_currentBlock.Length <= _currentBlockIndex)
- {
- _currentBlock = null;
- _currentBlockIndex = 0;
- }
- if (bytesRead == count)
- return bytesRead;
- }
- if (!_blocks.TryTake(out _currentBlock, Timeout.Infinite))
- return bytesRead;
- }
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- ValidateBufferArgs(buffer, offset, count);
- var newBuf = new byte[count];
- Array.Copy(buffer, offset, newBuf, 0, count);
- _blocks.Add(newBuf);
- TotalBytesWritten += count;
- WriteCount++;
- }
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
- if (disposing)
- {
- _blocks.Dispose();
- }
- }
- public override void Close()
- {
- CompleteWriting();
- base.Close();
- }
- public void CompleteWriting()
- {
- _blocks.CompleteAdding();
- }
- private static void ValidateBufferArgs(byte[] buffer, int offset, int count)
- {
- if (buffer == null)
- throw new ArgumentNullException("buffer");
- if (offset < 0)
- throw new ArgumentOutOfRangeException("offset");
- if (count < 0)
- throw new ArgumentOutOfRangeException("count");
- if (buffer.Length - offset < count)
- throw new ArgumentException("buffer.Length - offset < count");
- }
- }
- }
|