Example #1
0
 /// <summary>
 /// Writes the string into the stream.
 /// </summary>
 /// <remarks>
 /// This method doesn't encode the length of the string.
 /// </remarks>
 /// <param name="stream">The stream to write into.</param>
 /// <param name="value">The string to be encoded.</param>
 /// <param name="context">The encoding.</param>
 /// <param name="buffer">The buffer allocated by the caller needed for characters encoding.</param>
 /// <exception cref="ArgumentException"><paramref name="buffer"/> is too small for encoding.</exception>
 public static void WriteString(this Stream stream, string value, EncodingContext context, byte[] buffer)
 {
     if (value.Length == 0)
     {
         return;
     }
     //TODO: Should be rewritten for .NET Standard 2.1
     if (context.Encoding.GetByteCount(value) <= buffer.Length)
     {
         stream.Write(buffer, 0, context.Encoding.GetBytes(value, 0, value.Length, buffer, 0));
     }
     else
     {
         var maxChars = buffer.Length / context.Encoding.GetMaxByteCount(1);
         if (maxChars == 0)
         {
             throw new ArgumentException(ExceptionMessages.BufferTooSmall, nameof(buffer));
         }
         var encoder = context.GetEncoder();
         for (int charStart = 0, numLeft = value.Length, charsRead; numLeft > 0; charStart += charsRead, numLeft -= charsRead)
         {
             charsRead = Math.Min(numLeft, maxChars);
             stream.Write(buffer, 0, encoder.GetBytes(value, charStart, charsRead, buffer, charsRead == numLeft));
         }
     }
 }
Example #2
0
 /// <summary>
 /// Writes the string into the stream asynchronously.
 /// </summary>
 /// <remarks>
 /// This method doesn't encode the length of the string.
 /// </remarks>
 /// <param name="stream">The stream to write into.</param>
 /// <param name="value">The string to be encoded.</param>
 /// <param name="context">The encoding context.</param>
 /// <param name="buffer">The buffer allocated by the caller needed for characters encoding.</param>
 /// <param name="token">The token that can be used to cancel the operation.</param>
 /// <returns>The task representing asynchronous state of the operation.</returns>
 /// <exception cref="ArgumentException"><paramref name="buffer"/> is too small for encoding.</exception>
 public static async Task WriteStringAsync(this Stream stream, string value, EncodingContext context, byte[] buffer, CancellationToken token = default)
 {
     if (value.Length == 0)
     {
         return;
     }
     //TODO: Should be rewritten for .NET Standard 2.1
     if (context.Encoding.GetByteCount(value) <= buffer.Length)
     {
         await stream.WriteAsync(buffer, 0, context.Encoding.GetBytes(value, 0, value.Length, buffer, 0), token).ConfigureAwait(false);
     }
     else
     {
         var maxChars = buffer.Length / context.Encoding.GetMaxByteCount(1);
         if (maxChars == 0)
         {
             throw new ArgumentException(ExceptionMessages.BufferTooSmall, nameof(buffer));
         }
         var encoder = context.GetEncoder();
         for (int charStart = 0, numLeft = value.Length, charsRead; numLeft > 0; charStart += charsRead, numLeft -= charsRead)
         {
             charsRead = Math.Min(numLeft, maxChars);
             await stream.WriteAsync(buffer, 0, encoder.GetBytes(value, charStart, charsRead, buffer, charsRead == numLeft), token).ConfigureAwait(false);
         }
     }
 }
        /// <summary>
        /// Encodes the string to bytes and write them to pipe asynchronously.
        /// </summary>
        /// <param name="writer">The pipe writer.</param>
        /// <param name="value">The block of characters to encode.</param>
        /// <param name="context">The text encoding context.</param>
        /// <param name="bufferSize">The buffer size (in bytes) used for encoding.</param>
        /// <param name="lengthFormat">String length encoding format; or <see langword="null"/> to prevent encoding of string length.</param>
        /// <param name="token">The token that can be used to cancel operation.</param>
        /// <returns>The result of operation.</returns>
        /// <exception cref="OperationCanceledException">The operation has been canceled.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="lengthFormat"/> is invalid.</exception>
        /// <exception cref="EndOfStreamException">Pipe closed unexpectedly.</exception>
        public static async ValueTask WriteStringAsync(this PipeWriter writer, ReadOnlyMemory <char> value, EncodingContext context, int bufferSize = 0, LengthFormat?lengthFormat = null, CancellationToken token = default)
        {
            var result = await writer.WriteLengthAsync(value, context.Encoding, lengthFormat, token).ConfigureAwait(false);

            result.ThrowIfCancellationRequested(token);
            if (value.IsEmpty)
            {
                return;
            }
            var encoder = context.GetEncoder();

            for (int charsLeft = value.Length, charsUsed, maxChars, bytesPerChar = context.Encoding.GetMaxByteCount(1); charsLeft > 0; value = value.Slice(charsUsed), charsLeft -= charsUsed)
            {
                if (result.IsCompleted)
                {
                    throw new EndOfStreamException();
                }
                var buffer = writer.GetMemory(bufferSize);
                maxChars  = buffer.Length / bytesPerChar;
                charsUsed = Math.Min(maxChars, charsLeft);
                encoder.Convert(value.Span.Slice(0, charsUsed), buffer.Span, charsUsed == charsLeft, out charsUsed, out var bytesUsed, out _);
                writer.Advance(bytesUsed);
                result = await writer.FlushAsync(token).ConfigureAwait(false);

                result.ThrowIfCancellationRequested(token);
            }
        }