< Summary

Line coverage
33%
Covered lines: 100
Uncovered lines: 195
Coverable lines: 295
Total lines: 1072
Line coverage: 33.8%
Branch coverage
17%
Covered branches: 40
Total branches: 230
Branch coverage: 17.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
File 1: .cctor()100%11100%
File 1: .ctor()100%11100%
File 1: .ctor(...)100%11100%
File 1: .ctor(...)0%220%
File 1: SetDefaultFallbacks()50%2266.66%
File 1: GetByteCount(...)0%12120%
File 1: GetByteCount(...)50%4475%
File 1: GetByteCount(...)0%440%
File 1: GetByteCount(...)100%110%
File 1: GetByteCountCommon(...)33.33%6662.5%
File 1: GetByteCountFast(...)50%2285.71%
File 1: GetBytes(...)40%202046.66%
File 1: GetBytes(...)0%22220%
File 1: GetBytes(...)0%10100%
File 1: GetBytes(...)100%11100%
File 1: TryGetBytes(...)0%220%
File 1: GetBytesCommon(...)50%6687.5%
File 1: GetBytesFast(...)100%11100%
File 1: GetCharCount(...)0%12120%
File 1: GetCharCount(...)50%4460%
File 1: GetCharCount(...)100%11100%
File 1: GetChars(...)0%22220%
File 1: GetChars(...)30%101033.33%
File 1: GetChars(...)100%11100%
File 1: TryGetChars(...)0%220%
File 1: GetCharsCommon(...)66.66%66100%
File 1: GetCharsFast(...)100%11100%
File 1: GetCharsWithFallback(...)66.66%1212100%
File 1: GetString(...)0%14140%
File 1: GetCharCountCommon(...)66.66%6687.5%
File 1: GetCharCountFast(...)100%11100%
File 1: GetDecoder()100%110%
File 1: GetEncoder()100%11100%
File 1: TryGetByteCount(...)100%110%
File 1: EncodeRune(...)0%220%
File 1: DecodeFirstRune(...)100%11100%
File 1: GetMaxByteCount(...)0%440%
File 1: GetMaxCharCount(...)0%440%
File 1: GetPreamble()0%220%
File 1: Equals(...)0%660%
File 1: GetHashCode()100%110%
File 2: .ctor(...)100%11100%
File 2: Clone()100%11100%
File 2: GetBytes(...)0%440%
File 2: GetBytesForSmallInput(...)0%440%
File 2: GetMaxByteCount(...)50%2266.66%
File 2: ThrowArgumentException(System.Int32)0%220%
File 2: GetMaxCharCount(...)0%220%
File 2: ThrowArgumentException(System.Int32)0%220%
File 2: GetString(...)0%440%
File 2: GetStringForSmallInput(...)0%660%
File 2: TryGetBytes(...)100%110%
File 2: ReadUtf8(...)100%110%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Private.CoreLib/src/System/Text/UTF8Encoding.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4// The worker functions in this file was optimized for performance. If you make changes
 5// you should use care to consider all of the interesting cases.
 6
 7// The code of all worker functions in this file is written twice: Once as a slow loop, and the
 8// second time as a fast loop. The slow loops handles all special cases, throws exceptions, etc.
 9// The fast loops attempts to blaze through as fast as possible with optimistic range checks,
 10// processing multiple characters at a time, and falling back to the slow loop for all special cases.
 11
 12using System.Buffers;
 13using System.Diagnostics;
 14using System.Diagnostics.CodeAnalysis;
 15using System.Runtime.CompilerServices;
 16using System.Runtime.InteropServices;
 17using System.Text.Unicode;
 18
 19namespace System.Text
 20{
 21    // Encodes text into and out of UTF-8.  UTF-8 is a way of writing
 22    // Unicode characters with variable numbers of bytes per character,
 23    // optimized for the lower 127 ASCII characters.  It's an efficient way
 24    // of encoding US English in an internationalizable way.
 25    //
 26    // Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
 27    //
 28    // The UTF-8 byte order mark is simply the Unicode byte order mark
 29    // (0xFEFF) written in UTF-8 (0xEF 0xBB 0xBF).  The byte order mark is
 30    // used mostly to distinguish UTF-8 text from other encodings, and doesn't
 31    // switch the byte orderings.
 32
 33    public partial class UTF8Encoding : Encoding
 34    {
 35        /*
 36            bytes   bits    UTF-8 representation
 37            -----   ----    -----------------------------------
 38            1        7      0vvvvvvv
 39            2       11      110vvvvv 10vvvvvv
 40            3       16      1110vvvv 10vvvvvv 10vvvvvv
 41            4       21      11110vvv 10vvvvvv 10vvvvvv 10vvvvvv
 42            -----   ----    -----------------------------------
 43
 44            Surrogate:
 45            Real Unicode value = (HighSurrogate - 0xD800) * 0x400 + (LowSurrogate - 0xDC00) + 0x10000
 46        */
 47
 48        private const int UTF8_CODEPAGE = 65001;
 49
 50        /// <summary>
 51        /// Transcoding to UTF-8 bytes from UTF-16 input chars will result in a maximum 3:1 expansion.
 52        /// </summary>
 53        /// <remarks>
 54        /// Supplementary code points are expanded to UTF-8 from UTF-16 at a 4:2 ratio,
 55        /// so 3:1 is still the correct value for maximum expansion.
 56        /// </remarks>
 57        private const int MaxUtf8BytesPerChar = 3;
 58
 59
 60        // Used by Encoding.UTF8 for lazy initialization
 61        // The initialization code will not be run until a static member of the class is referenced
 162        internal static readonly UTF8EncodingSealed s_default = new UTF8EncodingSealed(encoderShouldEmitUTF8Identifier: 
 63
 164        internal static ReadOnlySpan<byte> PreambleSpan => [0xEF, 0xBB, 0xBF];
 65
 66        // Yes, the idea of emitting U+FEFF as a UTF-8 identifier has made it into
 67        // the standard.
 68        private readonly bool _emitUTF8Identifier;
 69
 70        private readonly bool _isThrowException;
 71
 72
 73        public UTF8Encoding() :
 374            base(UTF8_CODEPAGE)
 75        {
 376        }
 77
 78
 79        public UTF8Encoding(bool encoderShouldEmitUTF8Identifier) :
 380            this()
 81        {
 382            _emitUTF8Identifier = encoderShouldEmitUTF8Identifier;
 383        }
 84
 85
 86        public UTF8Encoding(bool encoderShouldEmitUTF8Identifier, bool throwOnInvalidBytes) :
 087            this(encoderShouldEmitUTF8Identifier)
 88        {
 089            _isThrowException = throwOnInvalidBytes;
 90
 91            // Encoding's constructor already did this, but it'll be wrong if we're throwing exceptions
 092            if (_isThrowException)
 093                SetDefaultFallbacks();
 094        }
 95
 96        internal sealed override void SetDefaultFallbacks()
 97        {
 98            // For UTF-X encodings, we use a replacement fallback with an empty string
 399            if (_isThrowException)
 100            {
 0101                this.encoderFallback = EncoderFallback.ExceptionFallback;
 0102                this.decoderFallback = DecoderFallback.ExceptionFallback;
 103            }
 104            else
 105            {
 3106                this.encoderFallback = new EncoderReplacementFallback("\xFFFD");
 3107                this.decoderFallback = new DecoderReplacementFallback("\xFFFD");
 108            }
 3109        }
 110
 111
 112        // WARNING: GetByteCount(string chars)
 113        // WARNING: has different variable names than EncodingNLS.cs, so this can't just be cut & pasted,
 114        // WARNING: otherwise it'll break VB's way of declaring these.
 115        //
 116        // The following methods are copied from EncodingNLS.cs.
 117        // Unfortunately EncodingNLS.cs is internal and we're public, so we have to re-implement them here.
 118        // These should be kept in sync for the following classes:
 119        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 120
 121        // Returns the number of bytes required to encode a range of characters in
 122        // a character array.
 123        //
 124        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 125        // So if you fix this, fix the others.  Currently those include:
 126        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 127        // parent method is safe
 128
 129        public override unsafe int GetByteCount(char[] chars, int index, int count)
 130        {
 0131            if (chars is null)
 132            {
 0133                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.chars, ExceptionResource.ArgumentNull_Array);
 134            }
 135
 0136            if ((index | count) < 0)
 137            {
 0138                ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.c
 139            }
 140
 0141            if (chars.Length - index < count)
 142            {
 0143                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRan
 144            }
 145
 0146            fixed (char* pChars = chars)
 147            {
 0148                return GetByteCountCommon(pChars + index, count);
 149            }
 150        }
 151
 152        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 153        // So if you fix this, fix the others.  Currently those include:
 154        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 155        // parent method is safe
 156
 157        public override unsafe int GetByteCount(string chars)
 158        {
 16159            if (chars is null)
 160            {
 0161                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.chars);
 162            }
 163
 16164            fixed (char* pChars = chars)
 165            {
 16166                return GetByteCountCommon(pChars, chars.Length);
 167            }
 168        }
 169
 170        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 171        // So if you fix this, fix the others.  Currently those include:
 172        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 173
 174        [CLSCompliant(false)]
 175        public override unsafe int GetByteCount(char* chars, int count)
 176        {
 0177            if (chars is null)
 178            {
 0179                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.chars);
 180            }
 181
 0182            if (count < 0)
 183            {
 0184                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRan
 185            }
 186
 0187            return GetByteCountCommon(chars, count);
 188        }
 189
 190        public override unsafe int GetByteCount(ReadOnlySpan<char> chars)
 0191        {
 192            // It's ok for us to pass null pointers down to the workhorse below.
 193
 0194            fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
 195            {
 0196                return GetByteCountCommon(charsPtr, chars.Length);
 197            }
 198        }
 199
 200        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 201        private unsafe int GetByteCountCommon(char* pChars, int charCount)
 202        {
 203            // Common helper method for all non-EncoderNLS entry points to GetByteCount.
 204            // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16,
 205
 16206            Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer.");
 16207            Debug.Assert(pChars is not null || charCount == 0, "Input pointer shouldn't be null if non-zero length speci
 208
 209            // First call into the fast path.
 210            // Don't bother providing a fallback mechanism; our fast path doesn't use it.
 211
 16212            int totalByteCount = GetByteCountFast(pChars, charCount, fallback: null, out int charsConsumed);
 213
 16214            if (charsConsumed != charCount)
 215            {
 216                // If there's still data remaining in the source buffer, go down the fallback path.
 217                // We need to check for integer overflow since the fallback could change the required
 218                // output count in unexpected ways.
 219
 0220                totalByteCount += GetByteCountWithFallback(pChars, charCount, charsConsumed);
 0221                if (totalByteCount < 0)
 222                {
 0223                    ThrowConversionOverflow();
 224                }
 225            }
 226
 16227            return totalByteCount;
 228        }
 229
 230        [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetCharCountCommon
 231        private protected sealed override unsafe int GetByteCountFast(char* pChars, int charsLength, EncoderFallback? fa
 232        {
 233            // The number of UTF-8 code units may exceed the number of UTF-16 code units,
 234            // so we'll need to check for overflow before casting to Int32.
 235
 16236            char* ptrToFirstInvalidChar = Utf16Utility.GetPointerToFirstInvalidChar(pChars, charsLength, out long utf8Co
 237
 16238            int tempCharsConsumed = (int)(ptrToFirstInvalidChar - pChars);
 16239            charsConsumed = tempCharsConsumed;
 240
 16241            long totalUtf8Bytes = tempCharsConsumed + utf8CodeUnitCountAdjustment;
 16242            if ((ulong)totalUtf8Bytes > int.MaxValue)
 243            {
 0244                ThrowConversionOverflow();
 245            }
 246
 16247            return (int)totalUtf8Bytes;
 248        }
 249
 250        // Parent method is safe.
 251        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 252        // So if you fix this, fix the others.  Currently those include:
 253        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 254
 255        public override unsafe int GetBytes(string s, int charIndex, int charCount,
 256                                              byte[] bytes, int byteIndex)
 257        {
 5258            if (s is null || bytes is null)
 259            {
 0260                ThrowHelper.ThrowArgumentNullException(
 0261                    argument: (s is null) ? ExceptionArgument.s : ExceptionArgument.bytes,
 0262                    resource: ExceptionResource.ArgumentNull_Array);
 263            }
 264
 5265            if ((charIndex | charCount) < 0)
 266            {
 0267                ThrowHelper.ThrowArgumentOutOfRangeException(
 0268                    argument: (charIndex < 0) ? ExceptionArgument.charIndex : ExceptionArgument.charCount,
 0269                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 270            }
 271
 5272            if (s.Length - charIndex < charCount)
 273            {
 0274                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.s, ExceptionResource.ArgumentOutOfRange_I
 275            }
 276
 5277            if ((uint)byteIndex > bytes.Length)
 278            {
 0279                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteIndex, ExceptionResource.ArgumentOutO
 280            }
 281
 5282            fixed (char* pChars = s)
 5283            fixed (byte* pBytes = bytes)
 284            {
 5285                return GetBytesCommon(pChars + charIndex, charCount, pBytes + byteIndex, bytes.Length - byteIndex);
 286            }
 287        }
 288
 289        // Encodes a range of characters in a character array into a range of bytes
 290        // in a byte array. An exception occurs if the byte array is not large
 291        // enough to hold the complete encoding of the characters. The
 292        // GetByteCount method can be used to determine the exact number of
 293        // bytes that will be produced for a given range of characters.
 294        // Alternatively, the GetMaxByteCount method can be used to
 295        // determine the maximum number of bytes that will be produced for a given
 296        // number of characters, regardless of the actual character values.
 297        //
 298        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 299        // So if you fix this, fix the others.  Currently those include:
 300        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 301        // parent method is safe
 302
 303        public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
 304                                               byte[] bytes, int byteIndex)
 305        {
 0306            if (chars is null || bytes is null)
 307            {
 0308                ThrowHelper.ThrowArgumentNullException(
 0309                    argument: (chars is null) ? ExceptionArgument.chars : ExceptionArgument.bytes,
 0310                    resource: ExceptionResource.ArgumentNull_Array);
 311            }
 312
 0313            if ((charIndex | charCount) < 0)
 314            {
 0315                ThrowHelper.ThrowArgumentOutOfRangeException(
 0316                    argument: (charIndex < 0) ? ExceptionArgument.charIndex : ExceptionArgument.charCount,
 0317                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 318            }
 319
 0320            if (chars.Length - charIndex < charCount)
 321            {
 0322                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRan
 323            }
 324
 0325            if ((uint)byteIndex > bytes.Length)
 326            {
 0327                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteIndex, ExceptionResource.ArgumentOutO
 328            }
 329
 0330            fixed (char* pChars = chars)
 0331            fixed (byte* pBytes = bytes)
 332            {
 0333                return GetBytesCommon(pChars + charIndex, charCount, pBytes + byteIndex, bytes.Length - byteIndex);
 334            }
 335        }
 336
 337        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 338        // So if you fix this, fix the others.  Currently those include:
 339        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 340
 341        [CLSCompliant(false)]
 342        public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
 343        {
 0344            if (chars is null || bytes is null)
 345            {
 0346                ThrowHelper.ThrowArgumentNullException(
 0347                    argument: (chars is null) ? ExceptionArgument.chars : ExceptionArgument.bytes,
 0348                    resource: ExceptionResource.ArgumentNull_Array);
 349            }
 350
 0351            if ((charCount | byteCount) < 0)
 352            {
 0353                ThrowHelper.ThrowArgumentOutOfRangeException(
 0354                    argument: (charCount < 0) ? ExceptionArgument.charCount : ExceptionArgument.byteCount,
 0355                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 356            }
 357
 0358            return GetBytesCommon(chars, charCount, bytes, byteCount);
 359        }
 360
 361        public override unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
 350362        {
 363            // It's ok for us to operate on null / empty spans.
 364
 350365            fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
 350366            fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
 367            {
 350368                return GetBytesCommon(charsPtr, chars.Length, bytesPtr, bytes.Length);
 369            }
 370        }
 371
 372        /// <inheritdoc/>
 373        public override unsafe bool TryGetBytes(ReadOnlySpan<char> chars, Span<byte> bytes, out int bytesWritten)
 0374        {
 0375            fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
 0376            fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
 377            {
 0378                int written = GetBytesCommon(charsPtr, chars.Length, bytesPtr, bytes.Length, throwForDestinationOverflow
 0379                if (written >= 0)
 380                {
 0381                    bytesWritten = written;
 0382                    return true;
 383                }
 384
 0385                bytesWritten = 0;
 0386                return false;
 387            }
 388        }
 389
 390        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 391        private unsafe int GetBytesCommon(char* pChars, int charCount, byte* pBytes, int byteCount, bool throwForDestina
 392        {
 393            // Common helper method for all non-EncoderNLS entry points to GetBytes.
 394            // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16,
 395
 355396            Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer.");
 355397            Debug.Assert(pChars is not null || charCount == 0, "Input pointer shouldn't be null if non-zero length speci
 355398            Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer.");
 355399            Debug.Assert(pBytes is not null || byteCount == 0, "Input pointer shouldn't be null if non-zero length speci
 400
 401            // First call into the fast path.
 402
 355403            int bytesWritten = GetBytesFast(pChars, charCount, pBytes, byteCount, out int charsConsumed);
 404
 355405            if (charsConsumed == charCount)
 406            {
 407                // All elements converted - return immediately.
 408
 355409                return bytesWritten;
 410            }
 411            else
 412            {
 413                // Simple narrowing conversion couldn't operate on entire buffer - invoke fallback.
 414
 0415                return GetBytesWithFallback(pChars, charCount, pBytes, byteCount, charsConsumed, bytesWritten, throwForD
 416            }
 417        }
 418
 419        [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetBytesCommon
 420        private protected sealed override unsafe int GetBytesFast(char* pChars, int charsLength, byte* pBytes, int bytes
 421        {
 422            // We don't care about the exact OperationStatus value returned by the workhorse routine; we only
 423            // care if the workhorse was able to consume the entire input payload. If we're unable to do so,
 424            // we'll handle the remainder in the fallback routine.
 425
 358426            Utf8Utility.TranscodeToUtf8(pChars, charsLength, pBytes, bytesLength, out char* pInputBufferRemaining, out b
 427
 358428            charsConsumed = (int)(pInputBufferRemaining - pChars);
 358429            return (int)(pOutputBufferRemaining - pBytes);
 430        }
 431
 432        // Returns the number of characters produced by decoding a range of bytes
 433        // in a byte array.
 434        //
 435        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 436        // So if you fix this, fix the others.  Currently those include:
 437        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 438        // parent method is safe
 439
 440        public override unsafe int GetCharCount(byte[] bytes, int index, int count)
 441        {
 0442            if (bytes is null)
 443            {
 0444                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes, ExceptionResource.ArgumentNull_Array);
 445            }
 446
 0447            if ((index | count) < 0)
 448            {
 0449                ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.c
 450            }
 451
 0452            if (bytes.Length - index < count)
 453            {
 0454                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRan
 455            }
 456
 0457            fixed (byte* pBytes = bytes)
 458            {
 0459                return GetCharCountCommon(pBytes + index, count);
 460            }
 461        }
 462
 463        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 464        // So if you fix this, fix the others.  Currently those include:
 465        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 466
 467        [CLSCompliant(false)]
 468        public override unsafe int GetCharCount(byte* bytes, int count)
 469        {
 6497470            if (bytes is null)
 471            {
 0472                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes, ExceptionResource.ArgumentNull_Array);
 473            }
 474
 6497475            if (count < 0)
 476            {
 0477                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRan
 478            }
 479
 6497480            return GetCharCountCommon(bytes, count);
 481        }
 482
 483        public override unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
 5051484        {
 485            // It's ok for us to pass null pointers down to the workhorse routine.
 486
 5051487            fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
 488            {
 5051489                return GetCharCountCommon(bytesPtr, bytes.Length);
 490            }
 491        }
 492
 493        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 494        // So if you fix this, fix the others.  Currently those include:
 495        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 496        // parent method is safe
 497
 498        public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
 499                                              char[] chars, int charIndex)
 500        {
 0501            if (bytes is null || chars is null)
 502            {
 0503                ThrowHelper.ThrowArgumentNullException(
 0504                    argument: (bytes is null) ? ExceptionArgument.bytes : ExceptionArgument.chars,
 0505                    resource: ExceptionResource.ArgumentNull_Array);
 506            }
 507
 0508            if ((byteIndex | byteCount) < 0)
 509            {
 0510                ThrowHelper.ThrowArgumentOutOfRangeException(
 0511                    argument: (byteIndex < 0) ? ExceptionArgument.byteIndex : ExceptionArgument.byteCount,
 0512                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 513            }
 514
 0515            if (bytes.Length - byteIndex < byteCount)
 516            {
 0517                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRan
 518            }
 519
 0520            if ((uint)charIndex > (uint)chars.Length)
 521            {
 0522                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.charIndex, ExceptionResource.ArgumentOutO
 523            }
 524
 0525            fixed (byte* pBytes = bytes)
 0526            fixed (char* pChars = chars)
 527            {
 0528                return GetCharsCommon(pBytes + byteIndex, byteCount, pChars + charIndex, chars.Length - charIndex);
 529            }
 530        }
 531
 532        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 533        // So if you fix this, fix the others.  Currently those include:
 534        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 535
 536        [CLSCompliant(false)]
 537        public override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
 538        {
 6497539            if (bytes is null || chars is null)
 540            {
 0541                ThrowHelper.ThrowArgumentNullException(
 0542                    argument: (bytes is null) ? ExceptionArgument.bytes : ExceptionArgument.chars,
 0543                    resource: ExceptionResource.ArgumentNull_Array);
 544            }
 545
 6497546            if ((byteCount | charCount) < 0)
 547            {
 0548                ThrowHelper.ThrowArgumentOutOfRangeException(
 0549                    argument: (byteCount < 0) ? ExceptionArgument.byteCount : ExceptionArgument.charCount,
 0550                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 551            }
 552
 6497553            return GetCharsCommon(bytes, byteCount, chars, charCount);
 554        }
 555
 556        public override unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
 5390557        {
 558            // It's ok for us to pass null pointers down to the workhorse below.
 559
 5390560            fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
 5390561            fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
 562            {
 5390563                return GetCharsCommon(bytesPtr, bytes.Length, charsPtr, chars.Length);
 564            }
 565        }
 566
 567        /// <inheritdoc/>
 568        public override unsafe bool TryGetChars(ReadOnlySpan<byte> bytes, Span<char> chars, out int charsWritten)
 0569        {
 0570            fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
 0571            fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
 572            {
 0573                int written = GetCharsCommon(bytesPtr, bytes.Length, charsPtr, chars.Length, throwForDestinationOverflow
 0574                if (written >= 0)
 575                {
 0576                    charsWritten = written;
 0577                    return true;
 578                }
 579
 0580                charsWritten = 0;
 0581                return false;
 582            }
 583        }
 584
 585        // WARNING:  If we throw an error, then System.Resources.ResourceReader calls this method.
 586        //           So if we're really broken, then that could also throw an error... recursively.
 587        //           So try to make sure GetChars can at least process all uses by
 588        //           System.Resources.ResourceReader!
 589        //
 590        // Note:  We throw exceptions on individually encoded surrogates and other non-shortest forms.
 591        //        If exceptions aren't turned on, then we drop all non-shortest &individual surrogates.
 592        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 593        private unsafe int GetCharsCommon(byte* pBytes, int byteCount, char* pChars, int charCount, bool throwForDestina
 594        {
 595            // Common helper method for all non-DecoderNLS entry points to GetChars.
 596            // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16,
 597
 11887598            Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer.");
 11887599            Debug.Assert(pBytes is not null || byteCount == 0, "Input pointer shouldn't be null if non-zero length speci
 11887600            Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer.");
 11887601            Debug.Assert(pChars is not null || charCount == 0, "Input pointer shouldn't be null if non-zero length speci
 602
 603            // First call into the fast path.
 604
 11887605            int charsWritten = GetCharsFast(pBytes, byteCount, pChars, charCount, out int bytesConsumed);
 606
 11887607            if (bytesConsumed == byteCount)
 608            {
 609                // All elements converted - return immediately.
 610
 2249611                return charsWritten;
 612            }
 613            else
 614            {
 615                // Simple narrowing conversion couldn't operate on entire buffer - invoke fallback.
 616
 9638617                return GetCharsWithFallback(pBytes, byteCount, pChars, charCount, bytesConsumed, charsWritten, throwForD
 618            }
 619        }
 620
 621        [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetCharsCommon
 622        private protected sealed override unsafe int GetCharsFast(byte* pBytes, int bytesLength, char* pChars, int chars
 623        {
 624            // We don't care about the exact OperationStatus value returned by the workhorse routine; we only
 625            // care if the workhorse was able to consume the entire input payload. If we're unable to do so,
 626            // we'll handle the remainder in the fallback routine.
 627
 342630628            Utf8Utility.TranscodeToUtf16(pBytes, bytesLength, pChars, charsLength, out byte* pInputBufferRemaining, out 
 629
 342630630            bytesConsumed = (int)(pInputBufferRemaining - pBytes);
 342630631            return (int)(pOutputBufferRemaining - pChars);
 632        }
 633
 634        private protected sealed override int GetCharsWithFallback(ReadOnlySpan<byte> bytes, int originalBytesLength, Sp
 635        {
 636            // We special-case DecoderReplacementFallback if it's telling us to write a single U+FFFD char,
 637            // since we believe this to be relatively common and we can handle it more efficiently than
 638            // the base implementation.
 639
 9638640            if (((decoder is null) ? this.DecoderFallback : decoder.Fallback) is DecoderReplacementFallback replacementF
 9638641                && replacementFallback.MaxCharCount == 1
 9638642                && replacementFallback.DefaultString[0] == UnicodeUtility.ReplacementChar)
 643            {
 644                // Don't care about the exact OperationStatus, just how much of the payload we were able
 645                // to process.
 646
 4819647                Utf8.ToUtf16(bytes, chars, out int bytesRead, out int charsWritten, replaceInvalidSequences: true, isFin
 648
 649                // Slice off how much we consumed / wrote.
 650
 4819651                bytes = bytes.Slice(bytesRead);
 4819652                chars = chars.Slice(charsWritten);
 653            }
 654
 655            // If we couldn't go through our fast fallback mechanism, or if we still have leftover
 656            // data because we couldn't consume everything in the loop above, we need to go down the
 657            // slow fallback path.
 658
 9638659            if (bytes.IsEmpty)
 660            {
 4819661                return originalCharsLength - chars.Length; // total number of chars written
 662            }
 663            else
 664            {
 4819665                return base.GetCharsWithFallback(bytes, originalBytesLength, chars, originalCharsLength, decoder, throwF
 666            }
 667        }
 668
 669        // Returns a string containing the decoded representation of a range of
 670        // bytes in a byte array.
 671        //
 672        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 673        // So if you fix this, fix the others.  Currently those include:
 674        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 675        // parent method is safe
 676
 677        public override unsafe string GetString(byte[] bytes, int index, int count)
 678        {
 0679            if (bytes is null)
 680            {
 0681                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes, ExceptionResource.ArgumentNull_Array);
 682            }
 683
 0684            if ((index | count) < 0)
 685            {
 0686                ThrowHelper.ThrowArgumentOutOfRangeException(
 0687                    argument: (index < 0) ? ExceptionArgument.index : ExceptionArgument.count,
 0688                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 689            }
 690
 0691            if (bytes.Length - index < count)
 692            {
 0693                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRan
 694            }
 695
 696            // Avoid problems with empty input buffer
 0697            if (count == 0)
 0698                return string.Empty;
 699
 0700            fixed (byte* pBytes = bytes)
 701            {
 0702                return string.CreateStringFromEncoding(pBytes + index, count, this);
 703            }
 704        }
 705
 706        //
 707        // End of standard methods copied from EncodingNLS.cs
 708        //
 709
 710        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 711        private unsafe int GetCharCountCommon(byte* pBytes, int byteCount)
 712        {
 713            // Common helper method for all non-DecoderNLS entry points to GetCharCount.
 714            // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16,
 715
 11548716            Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer.");
 11548717            Debug.Assert(pBytes is not null || byteCount == 0, "Input pointer shouldn't be null if non-zero length speci
 718
 719            // First call into the fast path.
 720            // Don't bother providing a fallback mechanism; our fast path doesn't use it.
 721
 11548722            int totalCharCount = GetCharCountFast(pBytes, byteCount, fallback: null, out int bytesConsumed);
 723
 11548724            if (bytesConsumed != byteCount)
 725            {
 726                // If there's still data remaining in the source buffer, go down the fallback path.
 727                // We need to check for integer overflow since the fallback could change the required
 728                // output count in unexpected ways.
 729
 9638730                totalCharCount += GetCharCountWithFallback(pBytes, byteCount, bytesConsumed);
 9638731                if (totalCharCount < 0)
 732                {
 0733                    ThrowConversionOverflow();
 734                }
 735            }
 736
 11548737            return totalCharCount;
 738        }
 739
 740        [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetCharCountCommon
 741        private protected sealed override unsafe int GetCharCountFast(byte* pBytes, int bytesLength, DecoderFallback? fa
 742        {
 743            // The number of UTF-16 code units will never exceed the number of UTF-8 code units,
 744            // so the addition at the end of this method will not overflow.
 745
 673034746            byte* ptrToFirstInvalidByte = Utf8Utility.GetPointerToFirstInvalidByte(pBytes, bytesLength, out int utf16Cod
 747
 673034748            int tempBytesConsumed = (int)(ptrToFirstInvalidByte - pBytes);
 673034749            bytesConsumed = tempBytesConsumed;
 750
 673034751            return tempBytesConsumed + utf16CodeUnitCountAdjustment;
 752        }
 753
 754        public override Decoder GetDecoder()
 755        {
 0756            return new DecoderNLS(this);
 757        }
 758
 759
 760        public override Encoder GetEncoder()
 761        {
 1762            return new EncoderNLS(this);
 763        }
 764
 765        //
 766        // Beginning of methods used by shared fallback logic.
 767        //
 768
 769        internal sealed override bool TryGetByteCount(Rune value, out int byteCount)
 770        {
 771            // All well-formed Rune instances can be converted to 1..4 UTF-8 code units.
 772
 0773            byteCount = value.Utf8SequenceLength;
 0774            return true;
 775        }
 776
 777        internal sealed override OperationStatus EncodeRune(Rune value, Span<byte> bytes, out int bytesWritten)
 778        {
 779            // All well-formed Rune instances can be encoded as 1..4 UTF-8 code units.
 780            // If there's an error, it's because the destination was too small.
 781
 0782            return value.TryEncodeToUtf8(bytes, out bytesWritten) ? OperationStatus.Done : OperationStatus.DestinationTo
 783        }
 784
 785        internal sealed override OperationStatus DecodeFirstRune(ReadOnlySpan<byte> bytes, out Rune value, out int bytes
 786        {
 1000650787            return Rune.DecodeFromUtf8(bytes, out value, out bytesConsumed);
 788        }
 789
 790        //
 791        // End of methods used by shared fallback logic.
 792        //
 793
 794        public override int GetMaxByteCount(int charCount)
 795        {
 0796            ArgumentOutOfRangeException.ThrowIfNegative(charCount);
 797
 798            // GetMaxByteCount assumes that the caller might have a stateful Encoder instance. If the
 799            // Encoder instance already has a captured high surrogate, then one of two things will
 800            // happen:
 801            //
 802            // - The next char is a low surrogate, at which point the two chars together result in 4
 803            //   UTF-8 bytes in the output; or
 804            // - The next char is not a low surrogate (or the input reaches EOF), at which point the
 805            //   standalone captured surrogate will go through the fallback routine.
 806            //
 807            // The second case is the worst-case scenario for expansion, so it's what we use for any
 808            // pessimistic "max byte count" calculation: assume there's a captured surrogate and that
 809            // it must fall back.
 810
 0811            long byteCount = (long)charCount + 1; // +1 to account for captured surrogate, per above
 812
 0813            if (EncoderFallback.MaxCharCount > 1)
 0814                byteCount *= EncoderFallback.MaxCharCount;
 815
 0816            byteCount *= MaxUtf8BytesPerChar;
 817
 0818            if (byteCount > 0x7fffffff)
 0819                throw new ArgumentOutOfRangeException(nameof(charCount), SR.ArgumentOutOfRange_GetByteCountOverflow);
 820
 0821            return (int)byteCount;
 822        }
 823
 824
 825        public override int GetMaxCharCount(int byteCount)
 826        {
 0827            ArgumentOutOfRangeException.ThrowIfNegative(byteCount);
 828
 829            // GetMaxCharCount assumes that the caller might have a stateful Decoder instance. If the
 830            // Decoder instance already has a captured partial UTF-8 subsequence, then one of two
 831            // thngs will happen:
 832            //
 833            // - The next byte(s) won't complete the subsequence but will instead be consumed into
 834            //   the Decoder's internal state, resulting in no character output; or
 835            // - The next byte(s) will complete the subsequence, and the previously captured
 836            //   subsequence and the next byte(s) will result in 1 - 2 chars output; or
 837            // - The captured subsequence will be treated as a singular ill-formed subsequence, at
 838            //   which point the captured subsequence will go through the fallback routine.
 839            //   (See The Unicode Standard, Sec. 3.9 for more information on this.)
 840            //
 841            // The third case is the worst-case scenario for expansion, since it means 0 bytes of
 842            // new input could cause any existing captured state to expand via fallback. So it's
 843            // what we'll use for any pessimistic "max char count" calculation.
 844
 0845            long charCount = ((long)byteCount + 1); // +1 to account for captured subsequence, as above
 846
 847            // Non-shortest form would fall back, so get max count from fallback.
 848            // So would 11... followed by 11..., so you could fall back every byte
 0849            if (DecoderFallback.MaxCharCount > 1)
 850            {
 0851                charCount *= DecoderFallback.MaxCharCount;
 852            }
 853
 0854            if (charCount > 0x7fffffff)
 0855                throw new ArgumentOutOfRangeException(nameof(byteCount), SR.ArgumentOutOfRange_GetCharCountOverflow);
 856
 0857            return (int)charCount;
 858        }
 859
 860
 861        public override byte[] GetPreamble()
 862        {
 0863            if (_emitUTF8Identifier)
 864            {
 865                // Allocate new array to prevent users from modifying it.
 0866                return [0xEF, 0xBB, 0xBF];
 867            }
 868            else
 0869                return [];
 870        }
 871
 872        public override ReadOnlySpan<byte> Preamble =>
 0873            GetType() != typeof(UTF8Encoding) ? new ReadOnlySpan<byte>(GetPreamble()) : // in case a derived UTF8Encodin
 0874            _emitUTF8Identifier ? PreambleSpan :
 0875            default;
 876
 877        public override bool Equals([NotNullWhen(true)] object? value)
 878        {
 0879            if (value is UTF8Encoding that)
 880            {
 0881                return (_emitUTF8Identifier == that._emitUTF8Identifier) &&
 0882                       (EncoderFallback.Equals(that.EncoderFallback)) &&
 0883                       (DecoderFallback.Equals(that.DecoderFallback));
 884            }
 0885            return false;
 886        }
 887
 888
 889        public override int GetHashCode()
 890        {
 891            // Not great distribution, but this is relatively unlikely to be used as the key in a hashtable.
 0892            return this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode() +
 0893                   UTF8_CODEPAGE + (_emitUTF8Identifier ? 1 : 0);
 894        }
 895    }
 896}
 897

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Private.CoreLib/src/System/Text/UTF8Encoding.Sealed.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Diagnostics;
 5using System.Runtime.CompilerServices;
 6using System.Runtime.InteropServices;
 7
 8namespace System.Text
 9{
 10    public partial class UTF8Encoding
 11    {
 12        /// <summary>
 13        /// A special instance of <see cref="UTF8Encoding"/> that is initialized with "don't throw on invalid sequences;
 14        /// perform <see cref="Rune.ReplacementChar"/> substitution instead" semantics. This type allows for devirtualiz
 15        /// of calls made directly off of <see cref="Encoding.UTF8"/>. See https://github.com/dotnet/coreclr/pull/9230.
 16        /// </summary>
 17        internal sealed class UTF8EncodingSealed : UTF8Encoding
 18        {
 19            /// <summary>
 20            /// Maximum number of input elements we'll allow for going through the fast one-pass stackalloc code paths.
 21            /// </summary>
 22            private const int MaxSmallInputElementCount = 32;
 23
 424            public UTF8EncodingSealed(bool encoderShouldEmitUTF8Identifier) : base(encoderShouldEmitUTF8Identifier) { }
 25
 126            public override ReadOnlySpan<byte> Preamble => _emitUTF8Identifier ? PreambleSpan : default;
 27
 28            public override object Clone()
 29            {
 30                // The base implementation of Encoding.Clone calls object.MemberwiseClone and marks the new object mutab
 31                // We don't want to do this because it violates the invariants we have set for the sealed type.
 32                // Instead, we'll create a new instance of the base UTF8Encoding type and mark it mutable.
 33
 134                return new UTF8Encoding(_emitUTF8Identifier)
 135                {
 136                    IsReadOnly = false
 137                };
 38            }
 39
 40            public override byte[] GetBytes(string s)
 41            {
 42                // This method is short and can be inlined, meaning that the null check below
 43                // might be elided if the JIT can prove not-null at the call site.
 44
 045                if (s?.Length <= MaxSmallInputElementCount)
 46                {
 047                    return GetBytesForSmallInput(s);
 48                }
 49                else
 50                {
 051                    return base.GetBytes(s!); // make the base method responsible for the null check
 52                }
 53            }
 54
 55            private unsafe byte[] GetBytesForSmallInput(string s)
 56            {
 057                Debug.Assert(s != null);
 058                Debug.Assert(s.Length <= MaxSmallInputElementCount);
 59
 060                byte* pDestination = stackalloc byte[MaxSmallInputElementCount * MaxUtf8BytesPerChar];
 61
 062                int sourceLength = s.Length; // hoist this to avoid having the JIT auto-insert null checks
 63                int bytesWritten;
 64
 065                fixed (char* pSource = s)
 66                {
 067                    bytesWritten = GetBytesCommon(pSource, sourceLength, pDestination, MaxSmallInputElementCount * MaxUt
 068                    Debug.Assert(0 <= bytesWritten && bytesWritten <= s.Length * MaxUtf8BytesPerChar);
 69                }
 70
 071                return new Span<byte>(ref *pDestination, bytesWritten).ToArray(); // this overload of Span ctor doesn't 
 72            }
 73
 74            public override int GetMaxByteCount(int charCount)
 75            {
 76                // This is a specialization of UTF8Encoding.GetMaxByteCount
 77                // with the assumption that the default replacement fallback
 78                // emits 3 fallback bytes ([ EF BF BD ] = '\uFFFD') per
 79                // malformed input char in the worst case.
 80
 381                if ((uint)charCount > (int.MaxValue / MaxUtf8BytesPerChar) - 1)
 82                {
 83                    // Move the throw out of the hot path to allow for inlining.
 084                    ThrowArgumentException(charCount);
 85                    static void ThrowArgumentException(int charCount)
 86                    {
 087                        throw new ArgumentOutOfRangeException(
 088                            paramName: nameof(charCount),
 089                            message: (charCount < 0) ? SR.ArgumentOutOfRange_NeedNonNegNum : SR.ArgumentOutOfRange_GetBy
 90                    }
 91                }
 92
 393                return (charCount * MaxUtf8BytesPerChar) + MaxUtf8BytesPerChar;
 94            }
 95
 96            public override int GetMaxCharCount(int byteCount)
 97            {
 98                // This is a specialization of UTF8Encoding.GetMaxCharCount
 99                // with the assumption that the default replacement fallback
 100                // emits one fallback char ('\uFFFD') per malformed input
 101                // byte in the worst case.
 102
 0103                if ((uint)byteCount > int.MaxValue - 1)
 104                {
 105                    // Move the throw out of the hot path to allow for inlining.
 0106                    ThrowArgumentException(byteCount);
 107                    static void ThrowArgumentException(int byteCount)
 108                    {
 0109                        throw new ArgumentOutOfRangeException(
 0110                            paramName: nameof(byteCount),
 0111                            message: (byteCount < 0) ? SR.ArgumentOutOfRange_NeedNonNegNum : SR.ArgumentOutOfRange_GetCh
 112                    }
 113                }
 114
 0115                return byteCount + 1;
 116            }
 117
 118            public override string GetString(byte[] bytes)
 119            {
 120                // This method is short and can be inlined, meaning that the null check below
 121                // might be elided if the JIT can prove not-null at the call site.
 122
 0123                if (bytes?.Length <= MaxSmallInputElementCount)
 124                {
 0125                    return GetStringForSmallInput(bytes);
 126                }
 127                else
 128                {
 0129                    return base.GetString(bytes!); // make the base method responsible for the null check
 130                }
 131            }
 132
 133            private unsafe string GetStringForSmallInput(byte[] bytes)
 134            {
 0135                Debug.Assert(bytes != null);
 0136                Debug.Assert(bytes.Length <= MaxSmallInputElementCount);
 137
 0138                char* pDestination = stackalloc char[MaxSmallInputElementCount]; // each byte produces at most one char
 139
 0140                int sourceLength = bytes.Length; // hoist this to avoid having the JIT auto-insert null checks
 141                int charsWritten;
 142
 0143                fixed (byte* pSource = bytes)
 144                {
 0145                    charsWritten = GetCharsCommon(pSource, sourceLength, pDestination, MaxSmallInputElementCount);
 0146                    Debug.Assert(0 <= charsWritten && charsWritten <= sourceLength); // should never have more output ch
 147                }
 148
 0149                return new string(new ReadOnlySpan<char>(ref *pDestination, charsWritten)); // this overload of ROS ctor
 150            }
 151
 152            /// <inheritdoc/>
 153            public override bool TryGetBytes(ReadOnlySpan<char> chars, Span<byte> bytes, out int bytesWritten)
 154            {
 0155                return base.TryGetBytes(chars, bytes, out bytesWritten);
 156            }
 157
 158            /// <summary>Same as Encoding.UTF8.TryGetBytes, except with refs, returning the number of bytes written (or 
 159            [MethodImpl(MethodImplOptions.NoInlining)]
 160            [Intrinsic] // Can be unrolled by JIT
 161            internal static unsafe int ReadUtf8(ref char input, int inputLength, ref byte output, int outputLength)
 0162            {
 0163                fixed (char* pInput = &input)
 0164                fixed (byte* pOutput = &output)
 165                {
 0166                    return s_default.GetBytesCommon(
 0167                        pInput, inputLength,
 0168                        pOutput, outputLength,
 0169                        throwForDestinationOverflow: false);
 170                }
 171            }
 172        }
 173    }
 174}
 175

Methods/Properties

.cctor()
PreambleSpan()
.ctor()
.ctor(System.Boolean)
.ctor(System.Boolean,System.Boolean)
SetDefaultFallbacks()
GetByteCount(System.Char[],System.Int32,System.Int32)
GetByteCount(System.String)
GetByteCount(System.Char*,System.Int32)
GetByteCount(System.ReadOnlySpan`1<System.Char>)
GetByteCountCommon(System.Char*,System.Int32)
GetByteCountFast(System.Char*,System.Int32,System.Text.EncoderFallback,System.Int32&)
GetBytes(System.String,System.Int32,System.Int32,System.Byte[],System.Int32)
GetBytes(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32)
GetBytes(System.Char*,System.Int32,System.Byte*,System.Int32)
GetBytes(System.ReadOnlySpan`1<System.Char>,System.Span`1<System.Byte>)
TryGetBytes(System.ReadOnlySpan`1<System.Char>,System.Span`1<System.Byte>,System.Int32&)
GetBytesCommon(System.Char*,System.Int32,System.Byte*,System.Int32,System.Boolean)
GetBytesFast(System.Char*,System.Int32,System.Byte*,System.Int32,System.Int32&)
GetCharCount(System.Byte[],System.Int32,System.Int32)
GetCharCount(System.Byte*,System.Int32)
GetCharCount(System.ReadOnlySpan`1<System.Byte>)
GetChars(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)
GetChars(System.Byte*,System.Int32,System.Char*,System.Int32)
GetChars(System.ReadOnlySpan`1<System.Byte>,System.Span`1<System.Char>)
TryGetChars(System.ReadOnlySpan`1<System.Byte>,System.Span`1<System.Char>,System.Int32&)
GetCharsCommon(System.Byte*,System.Int32,System.Char*,System.Int32,System.Boolean)
GetCharsFast(System.Byte*,System.Int32,System.Char*,System.Int32,System.Int32&)
GetCharsWithFallback(System.ReadOnlySpan`1<System.Byte>,System.Int32,System.Span`1<System.Char>,System.Int32,System.Text.DecoderNLS,System.Boolean)
GetString(System.Byte[],System.Int32,System.Int32)
GetCharCountCommon(System.Byte*,System.Int32)
GetCharCountFast(System.Byte*,System.Int32,System.Text.DecoderFallback,System.Int32&)
GetDecoder()
GetEncoder()
TryGetByteCount(System.Text.Rune,System.Int32&)
EncodeRune(System.Text.Rune,System.Span`1<System.Byte>,System.Int32&)
DecodeFirstRune(System.ReadOnlySpan`1<System.Byte>,System.Text.Rune&,System.Int32&)
GetMaxByteCount(System.Int32)
GetMaxCharCount(System.Int32)
GetPreamble()
Preamble()
Equals(System.Object)
GetHashCode()
.ctor(System.Boolean)
Preamble()
Clone()
GetBytes(System.String)
GetBytesForSmallInput(System.String)
GetMaxByteCount(System.Int32)
ThrowArgumentException(System.Int32)
GetMaxCharCount(System.Int32)
ThrowArgumentException(System.Int32)
GetString(System.Byte[])
GetStringForSmallInput(System.Byte[])
TryGetBytes(System.ReadOnlySpan`1<System.Char>,System.Span`1<System.Byte>,System.Int32&)
ReadUtf8(System.Char&,System.Int32,System.Byte&,System.Int32)