Пример #1
0
        public void CircularBufferStream_TestReadBytes()
        {
            CircularBufferStream cbs = new CircularBufferStream(3);

            byte[] data = new byte[] { 0, 1, 2 };
            cbs.Write(data, 0, data.Length);

            byte[] outData = new byte[5] {
                88, 88, 88, 88, 88
            };
            Assert.AreEqual(3, cbs.Read(outData, 1, 3));
            CollectionAssert.AreEqual(new byte[] { 88, 0, 1, 2, 88 }, outData);
            Assert.AreEqual(0, cbs.BytesAvailable);
        }
Пример #2
0
        /// <summary>
        /// Provides a filter for compressing a <see cref="Stream"/> with LZMA.
        /// </summary>
        /// <param name="stream">The underlying <see cref="Stream"/> to write the compressed data to.</param>
        /// <param name="bufferSize">The maximum number of uncompressed bytes to buffer. 32k (the step size of <see cref="SevenZip"/>) is a sensible minimum.</param>
        /// <remarks>
        /// This method internally uses multi-threading and a <see cref="CircularBufferStream"/>.
        /// The <paramref name="stream"/> may be closed with a delay.
        /// </remarks>
        private static Stream GetCompressionStream(Stream stream, int bufferSize = 128 * 1024)
        {
            var bufferStream = new CircularBufferStream(bufferSize);
            var encoder      = new Encoder();

            var consumerThread = new Thread(() =>
            {
                try
                {
                    // Write LZMA header
                    encoder.SetCoderProperties(
                        new[] { CoderPropId.DictionarySize, CoderPropId.PosStateBits, CoderPropId.LitContextBits, CoderPropId.LitPosBits, CoderPropId.Algorithm, CoderPropId.NumFastBytes, CoderPropId.MatchFinder, CoderPropId.EndMarker },
                        new object[] { 1 << 23, 2, 3, 0, 2, 128, "bt4", true });
                    encoder.WriteCoderProperties(stream);

                    // Write "uncompressed length" header
                    var uncompressedLengthData = BitConverter.GetBytes(TarLzmaExtractor.UnknownSize);
                    if (!BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(uncompressedLengthData);
                    }
                    stream.Write(uncompressedLengthData);

                    encoder.Code(
                        inStream: bufferStream, outStream: stream,
                        inSize: TarLzmaExtractor.UnknownSize, outSize: TarLzmaExtractor.UnknownSize,
                        progress: null);
                }
                catch (ObjectDisposedException)
                {
                    // If the buffer stream is closed too early the user probably just canceled the compression process
                }
                finally
                {
                    stream.Dispose();
                }
            })
            {
                IsBackground = true
            };

            consumerThread.Start();

            return(new DisposeWarpperStream(bufferStream, disposeHandler: () =>
            {
                bufferStream.DoneWriting();
                consumerThread.Join();
            }));
        }
Пример #3
0
        public void CircularBufferStream_TestReadPointer()
        {
            CircularBufferStream cbs = new CircularBufferStream(3);

            byte[] data = new byte[] { 0, 1, 2 };
            cbs.Write(data, 0, data.Length);

            byte[] outData = new byte[5] {
                88, 88, 88, 88, 88
            };
            IntPtr outDataPtr = Marshal.AllocHGlobal(outData.Length);

            Marshal.Copy(outData, 0, outDataPtr, outData.Length);
            Assert.AreEqual(3, cbs.Read(outDataPtr, outData.Length, 3));
            Marshal.Copy(outDataPtr, outData, 0, outData.Length);
            Marshal.FreeHGlobal(outDataPtr);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 88, 88 }, outData);
            Assert.AreEqual(0, cbs.BytesAvailable);
        }
Пример #4
0
        public void CircularBufferStream_TestRead()
        {
            CircularBufferStream cbs = new CircularBufferStream(3);

            byte[] data = new byte[] { 0, 1, 2 };
            cbs.Write(data, 0, data.Length);
            Assert.AreEqual(3, cbs.BytesAvailable);
            CollectionAssert.AreEqual(data, cbs.Read());
            Assert.AreEqual(0, cbs.BytesAvailable);

            // Write more data than the buffer capacity
            data = new byte[] { 0, 1, 2, 3 };
            cbs.Write(data, 0, data.Length);

            // first element should be overwritten - buffer should contain { 1, 2, 3 }
            Assert.AreEqual(3, cbs.BytesAvailable);
            CollectionAssert.AreEqual(new byte[] { 1, 2, 3 }, cbs.Read());

            Assert.AreEqual(0, cbs.BytesAvailable);
        }
Пример #5
0
        /// <summary>
        /// Provides a filter for decompressing an LZMA encoded <see cref="Stream"/>.
        /// </summary>
        /// <param name="stream">The underlying <see cref="Stream"/> providing the compressed data.</param>
        /// <param name="bufferSize">The maximum number of uncompressed bytes to buffer. 32k (the step size of <see cref="SevenZip"/>) is a sensible minimum.</param>
        /// <exception cref="IOException">The <paramref name="stream"/> doesn't start with a valid 5-bit LZMA header.</exception>
        /// <remarks>
        /// This method internally uses multi-threading and a <see cref="CircularBufferStream"/>.
        /// The <paramref name="stream"/> may be closed with a delay.
        /// </remarks>
        internal static Stream GetDecompressionStream(Stream stream, int bufferSize = 128 * 1024)
        {
            var bufferStream = new CircularBufferStream(bufferSize);
            var decoder      = new Decoder();

            // Read LZMA header
            if (stream.CanSeek)
            {
                stream.Position = 0;
            }
            try
            {
                decoder.SetDecoderProperties(stream.Read(5));
            }
            #region Error handling
            catch (IOException ex)
            {
                // Wrap exception to add context
                throw new IOException(Resources.ArchiveInvalid, ex);
            }
            catch (ApplicationException ex)
            {
                // Wrap exception since only certain exception types are allowed
                throw new IOException(Resources.ArchiveInvalid, ex);
            }
            #endregion

            // Read "uncompressed length" header
            var uncompressedLengthData = stream.Read(8);
            if (!BitConverter.IsLittleEndian)
            {
                Array.Reverse(uncompressedLengthData);
            }
            long uncompressedLength = BitConverter.ToInt64(uncompressedLengthData, startIndex: 0);

            bufferStream.SetLength((uncompressedLength == UnknownSize)
                ? (long)(stream.Length * 1.5)
                : uncompressedLength);

            var producerThread = new Thread(() =>
            {
                try
                {
                    decoder.Code(
                        inStream: stream, outStream: bufferStream,
                        inSize: UnknownSize, outSize: uncompressedLength,
                        progress: null);
                }
                catch (ThreadAbortException)
                {}
                catch (ObjectDisposedException)
                {
                    // If the buffer stream is closed too early the user probably just canceled the extraction process
                }
                catch (ApplicationException ex)
                {
                    bufferStream.RelayErrorToReader(new IOException(ex.Message, ex));
                }
                finally
                {
                    bufferStream.DoneWriting();
                }
            })
            {
                IsBackground = true
            };
            producerThread.Start();

            return(new DisposeWarpperStream(bufferStream, disposeHandler: () =>
            {
                producerThread.Abort();
                producerThread.Join();
                stream.Dispose();
            }));
        }
Пример #6
0
        protected override void OnHandler(ParameterHandlerInfo info)
        {
            Core.Log.Warning("Starting MEMORY STREAMS TEST");


            Core.Log.WriteEmptyLine();
            Core.Log.InfoBasic("Press Enter to Start RecycleMemoryStream Test.");
            Console.ReadLine();
            var xbuffer = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            using (Watch.Create("RecycleMemoryStream"))
            {
                for (var m = 0; m < 50000; m++)
                {
                    using (var rms = new RecycleMemoryStream())
                    {
                        for (var x = 0; x < 1; x++)
                        {
                            for (int i = 0; i < 10000; i++)
                            {
                                rms.Write(xbuffer, 0, xbuffer.Length);
                            }
                        }
                        rms.Position = 0;
                        for (var x = 0; x < 10; x++)
                        {
                            for (int i = 0; i < 2000; i++)
                            {
                                var bt = rms.ReadByte();
                            }
                        }
                    }
                }
            }
            Core.Log.WriteEmptyLine();
            Core.Log.InfoBasic("Press Enter to Start MemoryStream Test.");
            Console.ReadLine();
            using (Watch.Create("MemoryStream"))
            {
                for (var m = 0; m < 50000; m++)
                {
                    using (var rms = new MemoryStream())
                    {
                        for (var x = 0; x < 1; x++)
                        {
                            for (var i = 0; i < 10000; i++)
                            {
                                rms.Write(xbuffer, 0, xbuffer.Length);
                            }
                        }
                        rms.Position = 0;
                        for (var x = 0; x < 10; x++)
                        {
                            for (var i = 0; i < 2000; i++)
                            {
                                var bt = rms.ReadByte();
                            }
                        }
                    }
                }
            }



            Core.Log.WriteEmptyLine();
            Core.Log.InfoBasic("Press Enter to Start CircularBufferStream Test. Press Enter Again to finish the test.");
            Console.ReadLine();
            using (var cbs = new CircularBufferStream(50))
            {
                var cts = new CancellationTokenSource();
                Task.Run(async() =>
                {
                    var i = 0;
                    while (!cts.Token.IsCancellationRequested)
                    {
                        i++;
                        cbs.WriteBytes(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 });
                        if (i % 50 == 0)
                        {
                            Core.Log.InfoMedium("Write {0}", i);
                        }
                        await Task.Delay(1, cts.Token).ConfigureAwait(false);
                    }
                });
                Task.Run(async() =>
                {
                    var i      = 0;
                    var buffer = new byte[15];
                    while (!cts.Token.IsCancellationRequested)
                    {
                        i++;
                        cbs.Read(buffer, 0, 7);
                        if (i % 50 == 0)
                        {
                            Core.Log.InfoMedium("Read {0}", i);
                        }
                        await Task.Delay(1, cts.Token).ConfigureAwait(false);
                    }
                });
                Console.ReadLine();
                cts.Cancel();
            }



            Core.Log.WriteEmptyLine();
            Core.Log.InfoBasic("Press Enter to Start SharedMemoryStream Test. Press Enter Again to finish the test.");
            Console.ReadLine();
            using (var sharedms = new SharedMemoryStream("test", 2000))
            {
                var cts = new CancellationTokenSource();
                Task.Run(async() =>
                {
                    var i = 0;
                    while (!cts.Token.IsCancellationRequested)
                    {
                        i++;
                        sharedms.WriteBytes(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 });
                        if (i % 50 == 0)
                        {
                            Core.Log.InfoMedium("Write {0}", i);
                        }
                        await Task.Delay(1, cts.Token).ConfigureAwait(false);
                    }
                });
                Task.Run(async() =>
                {
                    var i      = 0;
                    var buffer = new byte[15];
                    while (!cts.Token.IsCancellationRequested)
                    {
                        i++;
                        sharedms.Read(buffer, 0, 7);
                        if (i % 50 == 0)
                        {
                            Core.Log.InfoMedium("Read {0}", i);
                        }
                        await Task.Delay(1, cts.Token).ConfigureAwait(false);
                    }
                });
                Console.ReadLine();
            }
        }
Пример #7
0
        /// <summary>
        /// Provides a filter for decompressing an LZMA encoded <see cref="Stream"/>.
        /// </summary>
        /// <param name="stream">The underlying <see cref="Stream"/> providing the compressed data.</param>
        /// <param name="bufferSize">The maximum number of uncompressed bytes to buffer. 32k (the step size of <see cref="SevenZip"/>) is a sensible minimum.</param>
        /// <exception cref="IOException">The <paramref name="stream"/> doesn't start with a valid 5-bit LZMA header.</exception>
        /// <remarks>
        /// This method internally uses multi-threading and a <see cref="CircularBufferStream"/>.
        /// The <paramref name="stream"/> may be closed with a delay.
        /// </remarks>
        private static Stream GetDecompressionStream(Stream stream, int bufferSize = 128 * 1024)
        {
            var bufferStream = new CircularBufferStream(bufferSize);
            var decoder      = new Decoder();

            // Read LZMA header
            if (stream.CanSeek)
            {
                stream.Position = 0;
            }
            var properties = new byte[5];

            if (stream.Read(properties, 0, 5) != 5)
            { // Stream too short
                throw new IOException(Resources.ArchiveInvalid);
            }
            try
            {
                decoder.SetDecoderProperties(properties);
            }
            #region Error handling
            catch (ApplicationException ex)
            {
                // Wrap exception since only certain exception types are allowed
                throw new IOException(Resources.ArchiveInvalid, ex);
            }
            #endregion

            // Detmerine uncompressed length
            long uncompressedLength = 0;
            if (BitConverter.IsLittleEndian)
            {
                for (int i = 0; i < 8; i++)
                {
                    int v = stream.ReadByte();
                    if (v < 0)
                    {
                        throw new IOException(Resources.ArchiveInvalid);
                    }

                    uncompressedLength |= ((long)(byte)v) << (8 * i);
                }
            }

            // If the uncompressed length is unknown, use original size * 1.5 as an estimate
            unchecked
            {
                bufferStream.SetLength(uncompressedLength == -1 ? stream.Length : (long)(uncompressedLength * 1.5));
            }

            // Initialize the producer thread that will deliver uncompressed data
            var thread = new Thread(() =>
            {
                try
                {
                    decoder.Code(stream, bufferStream, stream.Length, uncompressedLength, null);
                }
                #region Error handling
                catch (ThreadAbortException)
                {}
                catch (ObjectDisposedException)
                {
                    // If the buffer stream is closed too early the user probably just canceled the extraction process
                }
                catch (ApplicationException ex)
                {
                    // Wrap exception since only certain exception types are allowed
                    bufferStream.RelayErrorToReader(new IOException(ex.Message, ex));
                }
                #endregion

                finally
                {
                    bufferStream.DoneWriting();
                }
            })
            {
                IsBackground = true
            };
            thread.Start();

            return(new DisposeWarpperStream(bufferStream, () =>
            {
                // Stop producer thread when the buffer stream is closed
                thread.Abort();
                thread.Join();

                stream.Dispose();
            }));
        }