Example #1
0
        /// <summary>
        /// Constructs a <see cref="SourceText"/> from stream content.
        /// </summary>
        /// <param name="stream">Stream. The stream must be seekable.</param>
        /// <param name="encoding">
        /// Data encoding to use if the stream doesn't start with Byte Order Mark specifying the encoding.
        /// <see cref="Encoding.UTF8"/> if not specified.
        /// </param>
        /// <param name="checksumAlgorithm">
        /// Hash algorithm to use to calculate checksum of the text that's saved to PDB.
        /// </param>
        /// <param name="throwIfBinaryDetected">If the decoded text contains at least two consecutive NUL
        /// characters, then an <see cref="InvalidDataException"/> is thrown.</param>
        /// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="stream"/> doesn't support reading or seeking.
        /// <paramref name="checksumAlgorithm"/> is not supported.
        /// </exception>
        /// <exception cref="DecoderFallbackException">If the given encoding is set to use a throwing decoder as a fallback</exception>
        /// <exception cref="InvalidDataException">Two consecutive NUL characters were detected in the decoded text and <paramref name="throwIfBinaryDetected"/> was true.</exception>
        /// <exception cref="IOException">An I/O error occurs.</exception>
        /// <remarks>Reads from the beginning of the stream. Leaves the stream open.</remarks>
        public static SourceText From(Stream stream, Encoding encoding = null, SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1, bool throwIfBinaryDetected = false)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (!stream.CanRead || !stream.CanSeek)
            {
                throw new ArgumentException(CodeAnalysisResources.StreamMustSupportReadAndSeek, nameof(stream));
            }

            ValidateChecksumAlgorithm(checksumAlgorithm);

            encoding = encoding ?? s_utf8EncodingWithNoBOM;

            // If the resulting string would end up on the large object heap, then use LargeEncodedText.
            if (encoding.GetMaxCharCount((int)stream.Length) >= LargeObjectHeapLimitInChars)
            {
                return(LargeEncodedText.Decode(stream, encoding, checksumAlgorithm, throwIfBinaryDetected));
            }

            string text = Decode(stream, encoding, out encoding);

            if (throwIfBinaryDetected && IsBinary(text))
            {
                throw new InvalidDataException();
            }

            var checksum = CalculateChecksum(stream, checksumAlgorithm);

            return(new StringText(text, encoding, checksum, checksumAlgorithm));
        }
Example #2
0
        /// <summary>
        /// Try to create a <see cref="EncodedStringText"/> from the given stream using the given encoding.
        /// </summary>
        /// <param name="data">The input stream containing the encoded text. The stream will not be closed.</param>
        /// <param name="encoding">The expected encoding of the stream. The actual encoding used may be different if byte order marks are detected.</param>
        /// <param name="checksumAlgorithm">The checksum algorithm to use.</param>
        /// <param name="throwIfBinaryDetected">Throw <see cref="InvalidDataException"/> if binary (non-text) data is detected.</param>
        /// <returns>The <see cref="EncodedStringText"/> decoded from the stream.</returns>
        /// <exception cref="DecoderFallbackException">The decoder was unable to decode the stream with the given encoding.</exception>
        /// <remarks>
        /// internal for unit testing
        /// </remarks>
        internal static SourceText Decode(Stream data, Encoding encoding, SourceHashAlgorithm checksumAlgorithm, bool throwIfBinaryDetected = false)
        {
            data.Seek(0, SeekOrigin.Begin);

            if (data.Length > LargeObjectHeapLimit)
            {
                return(LargeEncodedText.Decode(data, encoding, checksumAlgorithm, throwIfBinaryDetected));
            }

            Encoding actualEncoding;
            ImmutableArray <byte> checksum = default(ImmutableArray <byte>);
            string text;

            byte[] buffer = TryGetByteArrayFromStream(data);
            if (buffer != null)
            {
                text = Decode(buffer, (int)data.Length, encoding, out actualEncoding);

                // Since we have the buffer, compute the checksum here. This saves allocations if we later
                // need to write out debugging information.
                checksum = CalculateChecksum(buffer, offset: 0, count: (int)data.Length, algorithmId: checksumAlgorithm);
            }
            else
            {
                text = Decode(data, encoding, out actualEncoding);
            }

            return(new EncodedStringText(text, actualEncoding, checksum, checksumAlgorithm, throwIfBinary: throwIfBinaryDetected));
        }