Example #1
0
        /// <summary>
        /// Reads exactly the specified number of bytes from a stream.
        /// </summary>
        ///
        /// <param name="stream">The stream to read from.</param>
        /// <param name="buffer">The array in which to store bytes.</param>
        /// <param name="offset">The index in <paramref name="buffer"/> of the first byte to
        ///     store.</param>
        /// <param name="count">The number of bytes to store.</param>
        /// <param name="throwIfNoData"><c>true</c> to throw an exception if the end of the stream
        ///     is reached before reading any data. If <c>false</c>, this method returns
        ///     <c>false</c> instead of throwing an exception. An exception is always thrown if
        ///     one or more bytes were read before reaching the end of the stream.</param>
        ///
        /// <returns><c>true</c> if the requested number of bytes were read from the underlying
        ///     stream, or <c>false</c> if the end of the stream was reached without reading any
        ///     bytes and <paramref name="throwIfNoData"/> is <c>true</c>.</returns>
        ///
        /// <exception cref="ArgumentNullException"><paramref name="stream"/> or
        ///     <paramref name="buffer"/> are <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">The specified
        ///     <paramref name="offset"/> and <paramref name="count"/> fall outside the bounds of
        ///     the <paramref name="buffer"/> array.</exception>
        /// <exception cref="EndOfStreamException">The end of the stream was reached before the
        ///     requested number of bytes were read, and <paramref name="throwIfNoData"/> is
        ///     <c>true</c>.</exception>
        /// <exception cref="IOException">An I/O error occurred.</exception>
        /// <exception cref="NotSupportedException">The stream does not support
        ///     reading.</exception>
        /// <exception cref="ObjectDisposedException">The stream object has been
        ///     disposed.</exception>

        public static bool ReadExactly(this Stream stream, byte[] buffer, int offset, int count, bool throwIfNoData)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            ValidationUtilities.ValidateArraySlice(buffer, offset, count,
                                                   nameof(buffer), nameof(offset), nameof(count));

            int totalBytesRead = 0;

            while (count > 0)
            {
                int bytesRead = stream.Read(buffer, offset, count);
                Debug.Assert(bytesRead >= 0 && bytesRead <= count);

                if (bytesRead == 0)
                {
                    if (!throwIfNoData && totalBytesRead == 0)
                    {
                        return(false);
                    }
                    throw new EndOfStreamException();
                }

                count          -= bytesRead;
                offset         += bytesRead;
                totalBytesRead += bytesRead;
            }

            return(true);
        }
Example #2
0
        /// <summary>
        /// Reads concatenated data from the underlying sequence of source readers.
        /// </summary>
        ///
        /// <param name="buffer">The array in which to store data.</param>
        /// <param name="index">The index in <paramref name="buffer"/> of the first byte to
        ///     store.</param>
        /// <param name="count">The maximum number of bytes to store.</param>
        ///
        /// <returns>The actual number of bytes read, which may be less than the amount requested
        ///     or zero if the end of the concatenated sources is reached.</returns>
        ///
        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is
        ///     <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> or
        ///    <paramref name="count"/> are negative or fall outside the array
        ///    bounds.</exception>
        /// <exception cref="IOException">An I/O error occurred.</exception>
        /// <exception cref="ObjectDisposedException">This reader or one or more source readers
        ///     have been disposed.</exception>

        public override int Read(char[] buffer, int index, int count)
        {
            if (_sources == null)
            {
                throw new ObjectDisposedException(GetType().Name);
            }

            ValidationUtilities.ValidateArraySlice(buffer, index, count,
                                                   nameof(buffer), nameof(index), nameof(count));

            int total = 0;

            while (count > 0)
            {
                if (_sources.Count == 0)
                {
                    return(total);
                }
                int bytesRead = _sources.Peek().Read(buffer, index, count);
                if (bytesRead == 0)
                {
                    _sources.Dequeue().Dispose();
                }
                total += bytesRead;
                count -= bytesRead;
                index += bytesRead;
            }

            return(total);
        }
Example #3
0
        /// <summary>
        /// Initializes a new data stream using the specified data.
        /// </summary>
        ///
        /// <param name="data">The array to wrap.</param>
        /// <param name="offset">The index of the first byte to wrap.</param>
        /// <param name="count">The number of bytes to wrap.</param>
        ///
        /// <exception cref="ArgumentNullException"><paramref name="data"/> is
        ///     <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> and/or
        ///      <paramref name="count"/> fall outside the bounds of the array.</exception>

        public ProtocolReader(byte[] data, int offset, int count)
        {
            ValidationUtilities.ValidateArraySlice(data, offset, count,
                                                   nameof(data), nameof(offset), nameof(count));

            _buffer      = data;
            _position    = _originalPosition = offset;
            _endPosition = offset + count;
        }
Example #4
0
        /// <summary>
        /// Updates the CRC value by processing the specified data.
        /// </summary>
        ///
        /// <param name="buffer">An array containing the bytes to process.</param>
        /// <param name="offset">The index in <paramref name="buffer"/> of the first byte to
        ///     process.</param>
        /// <param name="count">The number of bytes to process.</param>
        ///
        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is
        ///     <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">The specified <paramref name="offset"/>
        ///     and <paramref name="count"/> fall outside the bounds of the array.</exception>

        public void Update(byte[] buffer, int offset, int count)
        {
            ValidationUtilities.ValidateArraySlice(buffer, offset, count,
                                                   nameof(buffer), nameof(offset), nameof(count));

            for (int i = 0; i < count; ++i)
            {
                _crc = LOOKUP[(_crc ^ buffer[offset + i]) & 0xFF] ^ (_crc >> 8);
            }
        }
Example #5
0
        /// <summary>
        /// Asynchronously reads up to <paramref name="count"/> bytes from the underlying stream
        /// at the current subset position.
        /// </summary>
        ///
        /// <param name="buffer">The array in which to store bytes.</param>
        /// <param name="offset">The index in <paramref name="buffer"/> of the first byte to
        ///     store.</param>
        /// <param name="count">The maximum number of bytes to read and store.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        ///
        /// <returns>The number of bytes actually read and stored, which may be less than
        ///     <paramref name="count"/> or zero if the end of the stream has been
        ///     reached.</returns>
        ///
        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is
        ///     <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> or
        ///     <paramref name="count"/> exceed the bounds of
        ///     <paramref name="buffer"/>.</exception>
        /// <exception cref="IOException">An I/O error occurred.</exception>
        /// <exception cref="ObjectDisposedException">This object or the underlying stream have
        ///     been disposed.</exception>

        public override async Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            ValidationUtilities.ValidateArraySlice(buffer, offset, count,
                                                   nameof(buffer), nameof(offset), nameof(count));

            ThrowIfDisposed();

            if (_locker != null)
            {
                Monitor.Enter(_locker);
            }

            try
            {
                if (_position > _length)
                {
                    return(0);
                }
                if (_length - _position <= int.MaxValue)
                {
                    count = Math.Min(count, (int)(_length - _position));
                }
                if (count == 0)
                {
                    return(0);
                }
                if (_stream.Position != _offset + _position)
                {
                    _stream.Seek(_offset + _position, SeekOrigin.Begin);
                }
                int bytesRead = await _stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);

                _position += bytesRead;
                return(bytesRead);
            }

            finally
            {
                if (_locker != null)
                {
                    Monitor.Exit(_locker);
                }
            }
        }
Example #6
0
        /// <summary>
        /// Reads exactly the specified number of bytes from a stream.
        /// </summary>
        ///
        /// <param name="stream">The stream to read from.</param>
        /// <param name="buffer">The array in which to store bytes.</param>
        /// <param name="offset">The index in <paramref name="buffer"/> of the first byte to
        ///     store.</param>
        /// <param name="count">The number of bytes to store.</param>
        /// <param name="throwIfNoData"><c>true</c> to throw an exception if the end of the stream
        ///     is reached before reading any data. If <c>false</c>, this method returns
        ///     <c>false</c> instead of throwing an exception. An exception is always thrown if
        ///     one or more bytes were read before reaching the end of the stream.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        ///
        /// <returns><c>true</c> if the requested number of bytes were read from the underlying
        ///     stream, or <c>false</c> if the end of the stream was reached without reading any
        ///     bytes and <paramref name="throwIfNoData"/> is <c>true</c>.</returns>
        ///
        /// <exception cref="ArgumentNullException"><paramref name="stream"/>,
        ///     <paramref name="buffer"/> or <paramref name="cancellationToken"/> are
        ///     <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">The specified
        ///     <paramref name="offset"/> and <paramref name="count"/> fall outside the bounds of
        ///     the <paramref name="buffer"/> array.</exception>
        /// <exception cref="EndOfStreamException">The end of the stream was reached before the
        ///     requested number of bytes were read, and <paramref name="throwIfNoData"/> is
        ///     <c>true</c>.</exception>
        /// <exception cref="IOException">An I/O error occurred.</exception>
        /// <exception cref="NotSupportedException">The stream does not support
        ///     reading.</exception>
        /// <exception cref="ObjectDisposedException">The stream object has been
        ///     disposed.</exception>

        public static async Task <bool> ReadExactlyAsync(this Stream stream,
                                                         byte[] buffer, int offset, int count, bool throwIfNoData,
                                                         CancellationToken cancellationToken)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }

            ValidationUtilities.ValidateArraySlice(buffer, offset, count,
                                                   nameof(buffer), nameof(offset), nameof(count));

            int totalBytesRead = 0;

            while (count > 0)
            {
                int bytesRead = await stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);

                Debug.Assert(bytesRead >= 0 && bytesRead <= count);

                if (bytesRead == 0)
                {
                    if (!throwIfNoData && totalBytesRead == 0)
                    {
                        return(false);
                    }
                    throw new EndOfStreamException();
                }

                count          -= bytesRead;
                offset         += bytesRead;
                totalBytesRead += bytesRead;
            }

            return(true);
        }
Example #7
0
        /// <summary>
        /// Parses the specified data and returns a <see cref="BitmapImage"/>.
        /// </summary>
        ///
        /// <param name="data">An array containing the image data bytes.</param>
        /// <param name="offset">The index in <paramref name="data"/> of the first image data
        ///     byte.</param>
        /// <param name="count">The number of image data bytes.</param>
        ///
        /// <returns>A new <see cref="BitmapImage"/> object.</returns>
        ///
        /// <exception cref="ArgumentNullException"><paramref name="data"/> is
        ///     <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> and
        ///     <paramref name="count"/> are outside the bounds of the array.</exception>
        /// <exception cref="InvalidDataException">The image data cannot be
        ///     parsed.</exception>

        public static BitmapImage ParseBitmap(byte[] data, int offset, int count)
        {
            ValidationUtilities.ValidateArraySlice(data, offset, count,
                                                   nameof(data), nameof(offset), nameof(count));

            using (MemoryStream memory = new MemoryStream(data, offset, count))
            {
                try
                {
                    BitmapImage image = new BitmapImage();
                    image.BeginInit();
                    image.CacheOption  = BitmapCacheOption.OnLoad;
                    image.StreamSource = memory;
                    image.EndInit();
                    return(image);
                }

                catch (Exception ex)
                {
                    throw new InvalidDataException("Failed to parse image data", ex);
                }
            }
        }