< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 443
Coverable lines: 443
Total lines: 1182
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 256
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%110%
.ctor()100%110%
.ctor(...)0%220%
.ctor(...)0%220%
SetDefaultFallbacks()0%220%
GetByteCount(...)0%880%
GetByteCount(...)0%440%
GetByteCount(...)100%110%
GetBytes(...)0%880%
GetBytes(...)0%12120%
GetBytes(...)100%110%
GetCharCount(...)0%880%
GetCharCount(...)100%110%
GetChars(...)0%12120%
GetChars(...)100%110%
GetString(...)0%880%
GetByteCount(...)0%30300%
GetBytes(...)0%48480%
GetCharCount(...)0%34340%
GetChars(...)0%46460%
GetSurrogate(...)100%110%
GetHighSurrogate(...)100%110%
GetLowSurrogate(...)100%110%
GetDecoder()100%110%
GetEncoder()100%110%
GetMaxByteCount(...)0%440%
GetMaxCharCount(...)0%440%
GetPreamble()0%440%
Equals(...)0%880%
GetHashCode()0%440%
.ctor(...)100%110%
Reset()0%220%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Private.CoreLib/src/System/Text/UTF32Encoding.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//
 5// Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
 6//
 7
 8using System.Diagnostics;
 9using System.Diagnostics.CodeAnalysis;
 10using System.Runtime.InteropServices;
 11
 12namespace System.Text
 13{
 14    // Encodes text into and out of UTF-32.  UTF-32 is a way of writing
 15    // Unicode characters with a single storage unit (32 bits) per character,
 16    //
 17    // The UTF-32 byte order mark is simply the Unicode byte order mark
 18    // (0x00FEFF) written in UTF-32 (0x0000FEFF or 0xFFFE0000).  The byte order
 19    // mark is used mostly to distinguish UTF-32 text from other encodings, and doesn't
 20    // switch the byte orderings.
 21
 22    public sealed class UTF32Encoding : Encoding
 23    {
 24        /*
 25            words   bits    UTF-32 representation
 26            -----   ----    -----------------------------------
 27            1       16      00000000 00000000 xxxxxxxx xxxxxxxx
 28            2       21      00000000 000xxxxx hhhhhhll llllllll
 29            -----   ----    -----------------------------------
 30
 31            Surrogate:
 32            Real Unicode value = (HighSurrogate - 0xD800) * 0x400 + (LowSurrogate - 0xDC00) + 0x10000
 33        */
 34
 35        // Used by Encoding.UTF32/BigEndianUTF32 for lazy initialization
 36        // The initialization code will not be run until a static member of the class is referenced
 037        internal static readonly UTF32Encoding s_default = new UTF32Encoding(bigEndian: false, byteOrderMark: true);
 038        internal static readonly UTF32Encoding s_bigEndianDefault = new UTF32Encoding(bigEndian: true, byteOrderMark: tr
 39
 40        private readonly bool _emitUTF32ByteOrderMark;
 41        private readonly bool _isThrowException;
 42        private readonly bool _bigEndian;
 43
 044        public UTF32Encoding() : this(false, true)
 45        {
 046        }
 47
 48        public UTF32Encoding(bool bigEndian, bool byteOrderMark) :
 049            base(bigEndian ? 12001 : 12000)
 50        {
 051            _bigEndian = bigEndian;
 052            _emitUTF32ByteOrderMark = byteOrderMark;
 053        }
 54
 55        public UTF32Encoding(bool bigEndian, bool byteOrderMark, bool throwOnInvalidCharacters) :
 056            this(bigEndian, byteOrderMark)
 57        {
 058            _isThrowException = throwOnInvalidCharacters;
 59
 60            // Encoding constructor already did this, but it'll be wrong if we're throwing exceptions
 061            if (_isThrowException)
 062                SetDefaultFallbacks();
 063        }
 64
 65        internal sealed override void SetDefaultFallbacks()
 66        {
 67            // For UTF-X encodings, we use a replacement fallback with an empty string
 068            if (_isThrowException)
 69            {
 070                this.encoderFallback = EncoderFallback.ExceptionFallback;
 071                this.decoderFallback = DecoderFallback.ExceptionFallback;
 72            }
 73            else
 74            {
 075                this.encoderFallback = new EncoderReplacementFallback("\xFFFD");
 076                this.decoderFallback = new DecoderReplacementFallback("\xFFFD");
 77            }
 078        }
 79
 80        // The following methods are copied from EncodingNLS.cs.
 81        // Unfortunately EncodingNLS.cs is internal and we're public, so we have to re-implement them here.
 82        // These should be kept in sync for the following classes:
 83        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 84
 85        // Returns the number of bytes required to encode a range of characters in
 86        // a character array.
 87        //
 88        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 89        // So if you fix this, fix the others.  Currently those include:
 90        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 91        // parent method is safe
 92
 93        public override unsafe int GetByteCount(char[] chars, int index, int count)
 94        {
 095            ArgumentNullException.ThrowIfNull(chars);
 96
 097            ArgumentOutOfRangeException.ThrowIfNegative(index);
 098            ArgumentOutOfRangeException.ThrowIfNegative(count);
 99
 0100            if (chars.Length - index < count)
 0101                throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
 102
 103            // If no input, return 0, avoid fixed empty array problem
 0104            if (count == 0)
 0105                return 0;
 106
 107            // Just call the pointer version
 0108            fixed (char* pChars = chars)
 0109                return GetByteCount(pChars + index, count, null);
 110        }
 111
 112        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 113        // So if you fix this, fix the others.  Currently those include:
 114        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 115        // parent method is safe
 116
 117        public override unsafe int GetByteCount(string s)
 118        {
 0119            if (s is null)
 120            {
 0121                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
 122            }
 123
 0124            fixed (char* pChars = s)
 0125                return GetByteCount(pChars, s.Length, null);
 126        }
 127
 128        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 129        // So if you fix this, fix the others.  Currently those include:
 130        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 131
 132        [CLSCompliant(false)]
 133        public override unsafe int GetByteCount(char* chars, int count)
 134        {
 0135            ArgumentNullException.ThrowIfNull(chars);
 136
 0137            ArgumentOutOfRangeException.ThrowIfNegative(count);
 138
 139            // Call it with empty encoder
 0140            return GetByteCount(chars, count, null);
 141        }
 142
 143        // Parent method is safe.
 144        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 145        // So if you fix this, fix the others.  Currently those include:
 146        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 147
 148        public override unsafe int GetBytes(string s, int charIndex, int charCount,
 149                                            byte[] bytes, int byteIndex)
 150        {
 0151            ArgumentNullException.ThrowIfNull(s);
 0152            ArgumentNullException.ThrowIfNull(bytes);
 153
 0154            ArgumentOutOfRangeException.ThrowIfNegative(charIndex);
 0155            ArgumentOutOfRangeException.ThrowIfNegative(charCount);
 156
 0157            if (s.Length - charIndex < charCount)
 0158                throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
 159
 0160            if (byteIndex < 0 || byteIndex > bytes.Length)
 0161                throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_IndexMustBeLessOrEqual);
 162
 0163            int byteCount = bytes.Length - byteIndex;
 164
 0165            fixed (char* pChars = s)
 0166            fixed (byte* pBytes = &MemoryMarshal.GetArrayDataReference(bytes))
 167            {
 0168                return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
 169            }
 170        }
 171
 172        // Encodes a range of characters in a character array into a range of bytes
 173        // in a byte array. An exception occurs if the byte array is not large
 174        // enough to hold the complete encoding of the characters. The
 175        // GetByteCount method can be used to determine the exact number of
 176        // bytes that will be produced for a given range of characters.
 177        // Alternatively, the GetMaxByteCount method can be used to
 178        // determine the maximum number of bytes that will be produced for a given
 179        // number of characters, regardless of the actual character values.
 180        //
 181        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 182        // So if you fix this, fix the others.  Currently those include:
 183        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 184        // parent method is safe
 185
 186        public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
 187                                            byte[] bytes, int byteIndex)
 188        {
 0189            ArgumentNullException.ThrowIfNull(chars);
 0190            ArgumentNullException.ThrowIfNull(bytes);
 191
 0192            ArgumentOutOfRangeException.ThrowIfNegative(charIndex);
 0193            ArgumentOutOfRangeException.ThrowIfNegative(charCount);
 194
 0195            if (chars.Length - charIndex < charCount)
 0196                throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
 197
 0198            if (byteIndex < 0 || byteIndex > bytes.Length)
 0199                throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_IndexMustBeLessOrEqual);
 200
 201            // If nothing to encode return 0, avoid fixed problem
 0202            if (charCount == 0)
 0203                return 0;
 204
 205            // Just call pointer version
 0206            int byteCount = bytes.Length - byteIndex;
 207
 0208            fixed (char* pChars = chars)
 0209            fixed (byte* pBytes = &MemoryMarshal.GetArrayDataReference(bytes))
 210            {
 211                // Remember that byteCount is # to decode, not size of array.
 0212                return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
 213            }
 214        }
 215
 216        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 217        // So if you fix this, fix the others.  Currently those include:
 218        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 219
 220        [CLSCompliant(false)]
 221        public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
 222        {
 0223            ArgumentNullException.ThrowIfNull(chars);
 0224            ArgumentNullException.ThrowIfNull(bytes);
 225
 0226            ArgumentOutOfRangeException.ThrowIfNegative(charCount);
 0227            ArgumentOutOfRangeException.ThrowIfNegative(byteCount);
 228
 0229            return GetBytes(chars, charCount, bytes, byteCount, null);
 230        }
 231
 232        // Returns the number of characters produced by decoding a range of bytes
 233        // in a byte array.
 234        //
 235        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 236        // So if you fix this, fix the others.  Currently those include:
 237        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 238        // parent method is safe
 239
 240        public override unsafe int GetCharCount(byte[] bytes, int index, int count)
 241        {
 0242            ArgumentNullException.ThrowIfNull(bytes);
 243
 0244            ArgumentOutOfRangeException.ThrowIfNegative(index);
 0245            ArgumentOutOfRangeException.ThrowIfNegative(count);
 246
 0247            if (bytes.Length - index < count)
 0248                throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
 249
 250            // If no input just return 0, fixed doesn't like 0 length arrays.
 0251            if (count == 0)
 0252                return 0;
 253
 254            // Just call pointer version
 0255            fixed (byte* pBytes = bytes)
 0256                return GetCharCount(pBytes + index, count, null);
 257        }
 258
 259        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 260        // So if you fix this, fix the others.  Currently those include:
 261        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 262
 263        [CLSCompliant(false)]
 264        public override unsafe int GetCharCount(byte* bytes, int count)
 265        {
 0266            ArgumentNullException.ThrowIfNull(bytes);
 267
 0268            ArgumentOutOfRangeException.ThrowIfNegative(count);
 269
 0270            return GetCharCount(bytes, count, null);
 271        }
 272
 273        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 274        // So if you fix this, fix the others.  Currently those include:
 275        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 276        // parent method is safe
 277
 278        public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
 279                                            char[] chars, int charIndex)
 280        {
 0281            ArgumentNullException.ThrowIfNull(bytes);
 0282            ArgumentNullException.ThrowIfNull(chars);
 283
 0284            ArgumentOutOfRangeException.ThrowIfNegative(byteIndex);
 0285            ArgumentOutOfRangeException.ThrowIfNegative(byteCount);
 286
 0287            if (bytes.Length - byteIndex < byteCount)
 0288                throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
 289
 0290            if (charIndex < 0 || charIndex > chars.Length)
 0291                throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_IndexMustBeLessOrEqual);
 292
 293            // If no input, return 0 & avoid fixed problem
 0294            if (byteCount == 0)
 0295                return 0;
 296
 297            // Just call pointer version
 0298            int charCount = chars.Length - charIndex;
 299
 0300            fixed (byte* pBytes = bytes)
 0301            fixed (char* pChars = &MemoryMarshal.GetArrayDataReference(chars))
 302            {
 303                // Remember that charCount is # to decode, not size of array
 0304                return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
 305            }
 306        }
 307
 308        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 309        // So if you fix this, fix the others.  Currently those include:
 310        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 311
 312        [CLSCompliant(false)]
 313        public override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
 314        {
 0315            ArgumentNullException.ThrowIfNull(bytes);
 0316            ArgumentNullException.ThrowIfNull(chars);
 317
 0318            ArgumentOutOfRangeException.ThrowIfNegative(charCount);
 0319            ArgumentOutOfRangeException.ThrowIfNegative(byteCount);
 320
 0321            return GetChars(bytes, byteCount, chars, charCount, null);
 322        }
 323
 324        // Returns a string containing the decoded representation of a range of
 325        // bytes in a byte array.
 326        //
 327        // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
 328        // So if you fix this, fix the others.  Currently those include:
 329        // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
 330        // parent method is safe
 331
 332        public override unsafe string GetString(byte[] bytes, int index, int count)
 333        {
 0334            ArgumentNullException.ThrowIfNull(bytes);
 335
 0336            ArgumentOutOfRangeException.ThrowIfNegative(index);
 0337            ArgumentOutOfRangeException.ThrowIfNegative(count);
 338
 0339            if (bytes.Length - index < count)
 0340                throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
 341
 342            // Avoid problems with empty input buffer
 0343            if (count == 0) return string.Empty;
 344
 0345            fixed (byte* pBytes = bytes)
 0346                return string.CreateStringFromEncoding(
 0347                    pBytes + index, count, this);
 348        }
 349
 350        //
 351        // End of standard methods copied from EncodingNLS.cs
 352        //
 353        internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS? encoder)
 354        {
 0355            Debug.Assert(chars is not null, "[UTF32Encoding.GetByteCount]chars!=null");
 0356            Debug.Assert(count >= 0, "[UTF32Encoding.GetByteCount]count >=0");
 357
 0358            char* end = chars + count;
 0359            char* charStart = chars;
 0360            int byteCount = 0;
 361
 0362            char highSurrogate = '\0';
 363
 364            // For fallback we may need a fallback buffer
 0365            EncoderFallbackBuffer? fallbackBuffer = null;
 366            char* charsForFallback;
 367
 0368            if (encoder is not null)
 369            {
 0370                highSurrogate = encoder._charLeftOver;
 0371                fallbackBuffer = encoder.FallbackBuffer;
 372
 373                // We mustn't have left over fallback data when counting
 0374                if (fallbackBuffer.Remaining > 0)
 0375                    throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encode
 376            }
 377            else
 378            {
 0379                fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
 380            }
 381
 382            // Set our internal fallback interesting things.
 0383            fallbackBuffer.InternalInitialize(charStart, end, encoder, false);
 384
 385            char ch;
 386        TryAgain:
 387
 0388            while (((ch = fallbackBuffer.InternalGetNextChar()) != 0) || chars < end)
 389            {
 390                // First unwind any fallback
 0391                if (ch == 0)
 392                {
 393                    // No fallback, just get next char
 0394                    ch = *chars;
 0395                    chars++;
 396                }
 397
 398                // Do we need a low surrogate?
 0399                if (highSurrogate != '\0')
 400                {
 401                    //
 402                    // In previous char, we encounter a high surrogate, so we are expecting a low surrogate here.
 403                    //
 0404                    if (char.IsLowSurrogate(ch))
 405                    {
 406                        // They're all legal
 0407                        highSurrogate = '\0';
 408
 409                        //
 410                        // One surrogate pair will be translated into 4 bytes UTF32.
 411                        //
 412
 0413                        byteCount += 4;
 0414                        continue;
 415                    }
 416
 417                    // We are missing our low surrogate, decrement chars and fallback the high surrogate
 418                    // The high surrogate may have come from the encoder, but nothing else did.
 0419                    Debug.Assert(chars > charStart,
 0420                        "[UTF32Encoding.GetByteCount]Expected chars to have advanced if no low surrogate");
 0421                    chars--;
 422
 423                    // Do the fallback
 0424                    charsForFallback = chars;
 0425                    fallbackBuffer.InternalFallback(highSurrogate, ref charsForFallback);
 0426                    chars = charsForFallback;
 427
 428                    // We're going to fallback the old high surrogate.
 0429                    highSurrogate = '\0';
 0430                    continue;
 431                }
 432
 433                // Do we have another high surrogate?
 0434                if (char.IsHighSurrogate(ch))
 435                {
 436                    //
 437                    // We'll have a high surrogate to check next time.
 438                    //
 0439                    highSurrogate = ch;
 0440                    continue;
 441                }
 442
 443                // Check for illegal characters
 0444                if (char.IsLowSurrogate(ch))
 445                {
 446                    // We have a leading low surrogate, do the fallback
 0447                    charsForFallback = chars;
 0448                    fallbackBuffer.InternalFallback(ch, ref charsForFallback);
 0449                    chars = charsForFallback;
 450
 451                    // Try again with fallback buffer
 0452                    continue;
 453                }
 454
 455                // We get to add the character (4 bytes UTF32)
 0456                byteCount += 4;
 457            }
 458
 459            // May have to do our last surrogate
 0460            if ((encoder is null || encoder.MustFlush) && highSurrogate > 0)
 461            {
 462                // We have to do the fallback for the lonely high surrogate
 0463                charsForFallback = chars;
 0464                fallbackBuffer.InternalFallback(highSurrogate, ref charsForFallback);
 0465                chars = charsForFallback;
 466
 0467                highSurrogate = (char)0;
 0468                goto TryAgain;
 469            }
 470
 471            // Check for overflows.
 0472            if (byteCount < 0)
 0473                throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_GetByteCountOverflow);
 474
 475            // Shouldn't have anything in fallback buffer for GetByteCount
 476            // (don't have to check _throwOnOverflow for count)
 0477            Debug.Assert(fallbackBuffer.Remaining == 0,
 0478                "[UTF32Encoding.GetByteCount]Expected empty fallback buffer at end");
 479
 480            // Return our count
 0481            return byteCount;
 482        }
 483
 484        internal override unsafe int GetBytes(char* chars, int charCount,
 485                                                 byte* bytes, int byteCount, EncoderNLS? encoder)
 486        {
 0487            Debug.Assert(chars is not null, "[UTF32Encoding.GetBytes]chars!=null");
 0488            Debug.Assert(bytes is not null, "[UTF32Encoding.GetBytes]bytes!=null");
 0489            Debug.Assert(byteCount >= 0, "[UTF32Encoding.GetBytes]byteCount >=0");
 0490            Debug.Assert(charCount >= 0, "[UTF32Encoding.GetBytes]charCount >=0");
 491
 0492            char* charStart = chars;
 0493            char* charEnd = chars + charCount;
 0494            byte* byteStart = bytes;
 0495            byte* byteEnd = bytes + byteCount;
 496
 0497            char highSurrogate = '\0';
 498
 499            // For fallback we may need a fallback buffer
 0500            EncoderFallbackBuffer? fallbackBuffer = null;
 501            char* charsForFallback;
 502
 0503            if (encoder is not null)
 504            {
 0505                highSurrogate = encoder._charLeftOver;
 0506                fallbackBuffer = encoder.FallbackBuffer;
 507
 508                // We mustn't have left over fallback data when not converting
 0509                if (encoder._throwOnOverflow && fallbackBuffer.Remaining > 0)
 0510                    throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encode
 511            }
 512            else
 513            {
 0514                fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
 515            }
 516
 517            // Set our internal fallback interesting things.
 0518            fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
 519
 520            char ch;
 521        TryAgain:
 522
 0523            while (((ch = fallbackBuffer.InternalGetNextChar()) != 0) || chars < charEnd)
 524            {
 525                // First unwind any fallback
 0526                if (ch == 0)
 527                {
 528                    // No fallback, just get next char
 0529                    ch = *chars;
 0530                    chars++;
 531                }
 532
 533                // Do we need a low surrogate?
 0534                if (highSurrogate != '\0')
 535                {
 536                    //
 537                    // In previous char, we encountered a high surrogate, so we are expecting a low surrogate here.
 538                    //
 0539                    if (char.IsLowSurrogate(ch))
 540                    {
 541                        // Is it a legal one?
 0542                        uint iTemp = GetSurrogate(highSurrogate, ch);
 0543                        highSurrogate = '\0';
 544
 545                        //
 546                        // One surrogate pair will be translated into 4 bytes UTF32.
 547                        //
 0548                        if (bytes + 3 >= byteEnd)
 549                        {
 550                            // Don't have 4 bytes
 0551                            if (fallbackBuffer.bFallingBack)
 552                            {
 0553                                fallbackBuffer.MovePrevious();                  // Aren't using these 2 fallback chars
 0554                                fallbackBuffer.MovePrevious();
 555                            }
 556                            else
 557                            {
 558                                // If we don't have enough room, then either we should've advanced a while
 559                                // or we should have bytes==byteStart and throw below
 0560                                Debug.Assert(chars > charStart + 1 || bytes == byteStart,
 0561                                    "[UnicodeEncoding.GetBytes]Expected chars to have when no room to add surrogate pair
 0562                                chars -= 2;                                       // Aren't using those 2 chars
 563                            }
 0564                            ThrowBytesOverflow(encoder, bytes == byteStart);    // Throw maybe (if no bytes written)
 0565                            highSurrogate = (char)0;                            // Nothing left over (we backed up to st
 0566                            break;
 567                        }
 568
 0569                        if (_bigEndian)
 570                        {
 0571                            *(bytes++) = (byte)(0x00);
 0572                            *(bytes++) = (byte)(iTemp >> 16);       // Implies & 0xFF, which isn't needed cause high are
 0573                            *(bytes++) = (byte)(iTemp >> 8);        // Implies & 0xFF
 0574                            *(bytes++) = (byte)(iTemp);             // Implies & 0xFF
 575                        }
 576                        else
 577                        {
 0578                            *(bytes++) = (byte)(iTemp);             // Implies & 0xFF
 0579                            *(bytes++) = (byte)(iTemp >> 8);        // Implies & 0xFF
 0580                            *(bytes++) = (byte)(iTemp >> 16);       // Implies & 0xFF, which isn't needed cause high are
 0581                            *(bytes++) = (byte)(0x00);
 582                        }
 0583                        continue;
 584                    }
 585
 586                    // We are missing our low surrogate, decrement chars and fallback the high surrogate
 587                    // The high surrogate may have come from the encoder, but nothing else did.
 0588                    Debug.Assert(chars > charStart,
 0589                        "[UTF32Encoding.GetBytes]Expected chars to have advanced if no low surrogate");
 0590                    chars--;
 591
 592                    // Do the fallback
 0593                    charsForFallback = chars;
 0594                    fallbackBuffer.InternalFallback(highSurrogate, ref charsForFallback);
 0595                    chars = charsForFallback;
 596
 597                    // We're going to fallback the old high surrogate.
 0598                    highSurrogate = '\0';
 0599                    continue;
 600                }
 601
 602                // Do we have another high surrogate?, if so remember it
 0603                if (char.IsHighSurrogate(ch))
 604                {
 605                    //
 606                    // We'll have a high surrogate to check next time.
 607                    //
 0608                    highSurrogate = ch;
 0609                    continue;
 610                }
 611
 612                // Check for illegal characters (low surrogate)
 0613                if (char.IsLowSurrogate(ch))
 614                {
 615                    // We have a leading low surrogate, do the fallback
 0616                    charsForFallback = chars;
 0617                    fallbackBuffer.InternalFallback(ch, ref charsForFallback);
 0618                    chars = charsForFallback;
 619
 620                    // Try again with fallback buffer
 0621                    continue;
 622                }
 623
 624                // We get to add the character, yippee.
 0625                if (bytes + 3 >= byteEnd)
 626                {
 627                    // Don't have 4 bytes
 0628                    if (fallbackBuffer.bFallingBack)
 0629                        fallbackBuffer.MovePrevious();                  // Aren't using this fallback char
 630                    else
 631                    {
 632                        // Must've advanced already
 0633                        Debug.Assert(chars > charStart,
 0634                            "[UTF32Encoding.GetBytes]Expected chars to have advanced if normal character");
 0635                        chars--;                                        // Aren't using this char
 636                    }
 0637                    ThrowBytesOverflow(encoder, bytes == byteStart);    // Throw maybe (if no bytes written)
 0638                    break;                                              // Didn't throw, stop
 639                }
 640
 0641                if (_bigEndian)
 642                {
 0643                    *(bytes++) = (byte)(0x00);
 0644                    *(bytes++) = (byte)(0x00);
 0645                    *(bytes++) = (byte)((uint)ch >> 8); // Implies & 0xFF
 0646                    *(bytes++) = (byte)(ch);            // Implies & 0xFF
 647                }
 648                else
 649                {
 0650                    *(bytes++) = (byte)(ch);            // Implies & 0xFF
 0651                    *(bytes++) = (byte)((uint)ch >> 8); // Implies & 0xFF
 0652                    *(bytes++) = (byte)(0x00);
 0653                    *(bytes++) = (byte)(0x00);
 654                }
 655            }
 656
 657            // May have to do our last surrogate
 0658            if ((encoder is null || encoder.MustFlush) && highSurrogate > 0)
 659            {
 660                // We have to do the fallback for the lonely high surrogate
 0661                charsForFallback = chars;
 0662                fallbackBuffer.InternalFallback(highSurrogate, ref charsForFallback);
 0663                chars = charsForFallback;
 664
 0665                highSurrogate = (char)0;
 0666                goto TryAgain;
 667            }
 668
 669            // Fix our encoder if we have one
 0670            Debug.Assert(highSurrogate == 0 || (encoder is not null && !encoder.MustFlush),
 0671                "[UTF32Encoding.GetBytes]Expected encoder to be flushed.");
 672
 0673            if (encoder is not null)
 674            {
 675                // Remember our left over surrogate (or 0 if flushing)
 0676                encoder._charLeftOver = highSurrogate;
 677
 678                // Need # chars used
 0679                encoder._charsUsed = (int)(chars - charStart);
 680            }
 681
 682            // return the new length
 0683            return (int)(bytes - byteStart);
 684        }
 685
 686        internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS? baseDecoder)
 687        {
 0688            Debug.Assert(bytes is not null, "[UTF32Encoding.GetCharCount]bytes!=null");
 0689            Debug.Assert(count >= 0, "[UTF32Encoding.GetCharCount]count >=0");
 690
 0691            UTF32Decoder? decoder = (UTF32Decoder?)baseDecoder;
 692
 693            // None so far!
 0694            int charCount = 0;
 0695            byte* end = bytes + count;
 0696            byte* byteStart = bytes;
 697
 698            // Set up decoder
 0699            int readCount = 0;
 0700            uint iChar = 0;
 701
 702            // For fallback we may need a fallback buffer
 0703            DecoderFallbackBuffer? fallbackBuffer = null;
 704
 705            // See if there's anything in our decoder
 0706            if (decoder is not null)
 707            {
 0708                readCount = decoder.readByteCount;
 0709                iChar = (uint)decoder.iChar;
 0710                fallbackBuffer = decoder.FallbackBuffer;
 711
 712                // Shouldn't have anything in fallback buffer for GetCharCount
 713                // (don't have to check _throwOnOverflow for chars or count)
 0714                Debug.Assert(fallbackBuffer.Remaining == 0,
 0715                    "[UTF32Encoding.GetCharCount]Expected empty fallback buffer at start");
 716            }
 717            else
 718            {
 0719                fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
 720            }
 721
 722            // Set our internal fallback interesting things.
 0723            fallbackBuffer.InternalInitialize(byteStart, null);
 724
 725            // Loop through our input, 4 characters at a time!
 0726            while (bytes < end && charCount >= 0)
 727            {
 728                // Get our next character
 0729                if (_bigEndian)
 730                {
 731                    // Scoot left and add it to the bottom
 0732                    iChar <<= 8;
 0733                    iChar += *(bytes++);
 734                }
 735                else
 736                {
 737                    // Scoot right and add it to the top
 0738                    iChar >>= 8;
 0739                    iChar += (uint)(*(bytes++)) << 24;
 740                }
 741
 0742                readCount++;
 743
 744                // See if we have all the bytes yet
 0745                if (readCount < 4)
 746                    continue;
 747
 748                // Have the bytes
 0749                readCount = 0;
 750
 751                // See if its valid to encode
 0752                if (iChar > 0x10FFFF || (iChar >= 0xD800 && iChar <= 0xDFFF))
 753                {
 754                    // Need to fall back these 4 bytes
 755                    byte[] fallbackBytes;
 0756                    if (_bigEndian)
 757                    {
 0758                        fallbackBytes = [
 0759                            unchecked((byte)(iChar >> 24)), unchecked((byte)(iChar >> 16)),
 0760                            unchecked((byte)(iChar >> 8)), unchecked((byte)(iChar)) ];
 761                    }
 762                    else
 763                    {
 0764                        fallbackBytes = [
 0765                            unchecked((byte)(iChar)), unchecked((byte)(iChar >> 8)),
 0766                            unchecked((byte)(iChar >> 16)), unchecked((byte)(iChar >> 24)) ];
 767                    }
 768
 0769                    charCount += fallbackBuffer.InternalFallback(fallbackBytes, bytes);
 770
 771                    // Ignore the illegal character
 0772                    iChar = 0;
 0773                    continue;
 774                }
 775
 776                // Ok, we have something we can add to our output
 0777                if (iChar >= 0x10000)
 778                {
 779                    // Surrogates take 2
 0780                    charCount++;
 781                }
 782
 783                // Add the rest of the surrogate or our normal character
 0784                charCount++;
 785
 786                // iChar is back to 0
 0787                iChar = 0;
 788            }
 789
 790            // See if we have something left over that has to be decoded
 0791            if (readCount > 0 && (decoder is null || decoder.MustFlush))
 792            {
 793                // Oops, there's something left over with no place to go.
 0794                byte[] fallbackBytes = new byte[readCount];
 0795                if (_bigEndian)
 796                {
 0797                    while (readCount > 0)
 798                    {
 0799                        fallbackBytes[--readCount] = unchecked((byte)iChar);
 0800                        iChar >>= 8;
 801                    }
 802                }
 803                else
 804                {
 0805                    while (readCount > 0)
 806                    {
 0807                        fallbackBytes[--readCount] = unchecked((byte)(iChar >> 24));
 0808                        iChar <<= 8;
 809                    }
 810                }
 811
 0812                charCount += fallbackBuffer.InternalFallback(fallbackBytes, bytes);
 813            }
 814
 815            // Check for overflows.
 0816            if (charCount < 0)
 0817                throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_GetByteCountOverflow);
 818
 819            // Shouldn't have anything in fallback buffer for GetCharCount
 820            // (don't have to check _throwOnOverflow for chars or count)
 0821            Debug.Assert(fallbackBuffer.Remaining == 0,
 0822                "[UTF32Encoding.GetCharCount]Expected empty fallback buffer at end");
 823
 824            // Return our count
 0825            return charCount;
 826        }
 827
 828        internal override unsafe int GetChars(byte* bytes, int byteCount,
 829                                                char* chars, int charCount, DecoderNLS? baseDecoder)
 830        {
 0831            Debug.Assert(chars is not null, "[UTF32Encoding.GetChars]chars!=null");
 0832            Debug.Assert(bytes is not null, "[UTF32Encoding.GetChars]bytes!=null");
 0833            Debug.Assert(byteCount >= 0, "[UTF32Encoding.GetChars]byteCount >=0");
 0834            Debug.Assert(charCount >= 0, "[UTF32Encoding.GetChars]charCount >=0");
 835
 0836            UTF32Decoder? decoder = (UTF32Decoder?)baseDecoder;
 837
 838            // None so far!
 0839            char* charStart = chars;
 0840            char* charEnd = chars + charCount;
 841
 0842            byte* byteStart = bytes;
 0843            byte* byteEnd = bytes + byteCount;
 844
 845            // See if there's anything in our decoder (but don't clear it yet)
 0846            int readCount = 0;
 0847            uint iChar = 0;
 848
 849            // For fallback we may need a fallback buffer
 0850            DecoderFallbackBuffer? fallbackBuffer = null;
 851            char* charsForFallback;
 852
 853            // See if there's anything in our decoder
 0854            if (decoder is not null)
 855            {
 0856                readCount = decoder.readByteCount;
 0857                iChar = (uint)decoder.iChar;
 0858                Debug.Assert(baseDecoder is not null);
 0859                fallbackBuffer = baseDecoder.FallbackBuffer;
 860
 861                // Shouldn't have anything in fallback buffer for GetChars
 862                // (don't have to check _throwOnOverflow for chars)
 0863                Debug.Assert(fallbackBuffer.Remaining == 0,
 0864                    "[UTF32Encoding.GetChars]Expected empty fallback buffer at start");
 865            }
 866            else
 867            {
 0868                fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
 869            }
 870
 871            // Set our internal fallback interesting things.
 0872            fallbackBuffer.InternalInitialize(bytes, chars + charCount);
 873
 874            // Loop through our input, 4 characters at a time!
 0875            while (bytes < byteEnd)
 876            {
 877                // Get our next character
 0878                if (_bigEndian)
 879                {
 880                    // Scoot left and add it to the bottom
 0881                    iChar <<= 8;
 0882                    iChar += *(bytes++);
 883                }
 884                else
 885                {
 886                    // Scoot right and add it to the top
 0887                    iChar >>= 8;
 0888                    iChar += (uint)(*(bytes++)) << 24;
 889                }
 890
 0891                readCount++;
 892
 893                // See if we have all the bytes yet
 0894                if (readCount < 4)
 895                    continue;
 896
 897                // Have the bytes
 0898                readCount = 0;
 899
 900                // See if its valid to encode
 0901                if (iChar > 0x10FFFF || (iChar >= 0xD800 && iChar <= 0xDFFF))
 902                {
 903                    // Need to fall back these 4 bytes
 904                    byte[] fallbackBytes;
 0905                    if (_bigEndian)
 906                    {
 0907                        fallbackBytes = [
 0908                            unchecked((byte)(iChar >> 24)), unchecked((byte)(iChar >> 16)),
 0909                            unchecked((byte)(iChar >> 8)), unchecked((byte)(iChar)) ];
 910                    }
 911                    else
 912                    {
 0913                        fallbackBytes = [
 0914                            unchecked((byte)(iChar)), unchecked((byte)(iChar >> 8)),
 0915                            unchecked((byte)(iChar >> 16)), unchecked((byte)(iChar >> 24)) ];
 916                    }
 917
 918                    // Chars won't be updated unless this works.
 0919                    charsForFallback = chars;
 0920                    bool fallbackResult = fallbackBuffer.InternalFallback(fallbackBytes, bytes, ref charsForFallback);
 0921                    chars = charsForFallback;
 922
 0923                    if (!fallbackResult)
 924                    {
 925                        // Couldn't fallback, throw or wait til next time
 926                        // We either read enough bytes for bytes-=4 to work, or we're
 927                        // going to throw in ThrowCharsOverflow because chars == charStart
 0928                        Debug.Assert(bytes >= byteStart + 4 || chars == charStart,
 0929                            "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (bad surrogate)");
 0930                        bytes -= 4;                                       // get back to where we were
 0931                        iChar = 0;                                        // Remembering nothing
 0932                        fallbackBuffer.InternalReset();
 0933                        ThrowCharsOverflow(decoder, chars == charStart); // Might throw, if no chars output
 0934                        break;                                           // Stop here, didn't throw
 935                    }
 936
 937                    // Ignore the illegal character
 0938                    iChar = 0;
 0939                    continue;
 940                }
 941
 942                // Ok, we have something we can add to our output
 0943                if (iChar >= 0x10000)
 944                {
 945                    // Surrogates take 2
 0946                    if (charEnd - chars < 2)
 947                    {
 948                        // Throwing or stopping
 949                        // We either read enough bytes for bytes-=4 to work, or we're
 950                        // going to throw in ThrowCharsOverflow because chars == charStart
 0951                        Debug.Assert(bytes >= byteStart + 4 || chars == charStart,
 0952                            "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (surrogate)");
 0953                        bytes -= 4;                                       // get back to where we were
 0954                        iChar = 0;                                        // Remembering nothing
 0955                        ThrowCharsOverflow(decoder, chars == charStart); // Might throw, if no chars output
 0956                        break;                                           // Stop here, didn't throw
 957                    }
 958
 0959                    *(chars++) = GetHighSurrogate(iChar);
 0960                    iChar = GetLowSurrogate(iChar);
 961                }
 962                // Bounds check for normal character
 0963                else if (chars >= charEnd)
 964                {
 965                    // Throwing or stopping
 966                    // We either read enough bytes for bytes-=4 to work, or we're
 967                    // going to throw in ThrowCharsOverflow because chars == charStart
 0968                    Debug.Assert(bytes >= byteStart + 4 || chars == charStart,
 0969                        "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (normal char)");
 0970                    bytes -= 4;                                       // get back to where we were
 0971                    iChar = 0;                                        // Remembering nothing
 0972                    ThrowCharsOverflow(decoder, chars == charStart); // Might throw, if no chars output
 0973                    break;                                           // Stop here, didn't throw
 974                }
 975
 976                // Add the rest of the surrogate or our normal character
 0977                *(chars++) = (char)iChar;
 978
 979                // iChar is back to 0
 0980                iChar = 0;
 981            }
 982
 983            // See if we have something left over that has to be decoded
 0984            if (readCount > 0 && (decoder is null || decoder.MustFlush))
 985            {
 986                // Oops, there's something left over with no place to go.
 0987                byte[] fallbackBytes = new byte[readCount];
 0988                int tempCount = readCount;
 0989                if (_bigEndian)
 990                {
 0991                    while (tempCount > 0)
 992                    {
 0993                        fallbackBytes[--tempCount] = unchecked((byte)iChar);
 0994                        iChar >>= 8;
 995                    }
 996                }
 997                else
 998                {
 0999                    while (tempCount > 0)
 1000                    {
 01001                        fallbackBytes[--tempCount] = unchecked((byte)(iChar >> 24));
 01002                        iChar <<= 8;
 1003                    }
 1004                }
 1005
 01006                charsForFallback = chars;
 01007                bool fallbackResult = fallbackBuffer.InternalFallback(fallbackBytes, bytes, ref charsForFallback);
 01008                chars = charsForFallback;
 1009
 01010                if (!fallbackResult)
 1011                {
 1012                    // Couldn't fallback.
 01013                    fallbackBuffer.InternalReset();
 01014                    ThrowCharsOverflow(decoder, chars == charStart); // Might throw, if no chars output
 1015                    // Stop here, didn't throw, backed up, so still nothing in buffer
 1016                }
 1017                else
 1018                {
 1019                    // Don't clear our decoder unless we could fall it back.
 1020                    // If we caught the if above, then we're a convert() and will catch this next time.
 01021                    readCount = 0;
 01022                    iChar = 0;
 1023                }
 1024            }
 1025
 1026            // Remember any left over stuff, clearing buffer as well for MustFlush
 01027            if (decoder is not null)
 1028            {
 01029                decoder.iChar = (int)iChar;
 01030                decoder.readByteCount = readCount;
 01031                decoder._bytesUsed = (int)(bytes - byteStart);
 1032            }
 1033
 1034            // Shouldn't have anything in fallback buffer for GetChars
 1035            // (don't have to check _throwOnOverflow for chars)
 01036            Debug.Assert(fallbackBuffer.Remaining == 0,
 01037                "[UTF32Encoding.GetChars]Expected empty fallback buffer at end");
 1038
 1039            // Return our count
 01040            return (int)(chars - charStart);
 1041        }
 1042
 1043        private static uint GetSurrogate(char cHigh, char cLow)
 1044        {
 01045            return (((uint)cHigh - 0xD800) * 0x400) + ((uint)cLow - 0xDC00) + 0x10000;
 1046        }
 1047
 1048        private static char GetHighSurrogate(uint iChar)
 1049        {
 01050            return (char)((iChar - 0x10000) / 0x400 + 0xD800);
 1051        }
 1052
 1053        private static char GetLowSurrogate(uint iChar)
 1054        {
 01055            return (char)((iChar - 0x10000) % 0x400 + 0xDC00);
 1056        }
 1057
 1058        public override Decoder GetDecoder()
 1059        {
 01060            return new UTF32Decoder(this);
 1061        }
 1062
 1063        public override Encoder GetEncoder()
 1064        {
 01065            return new EncoderNLS(this);
 1066        }
 1067
 1068        public override int GetMaxByteCount(int charCount)
 1069        {
 01070            ArgumentOutOfRangeException.ThrowIfNegative(charCount);
 1071
 1072            // Characters would be # of characters + 1 in case left over high surrogate is ? * max fallback
 01073            long byteCount = (long)charCount + 1;
 1074
 01075            if (EncoderFallback.MaxCharCount > 1)
 01076                byteCount *= EncoderFallback.MaxCharCount;
 1077
 1078            // 4 bytes per char
 01079            byteCount *= 4;
 1080
 01081            if (byteCount > 0x7fffffff)
 01082                throw new ArgumentOutOfRangeException(nameof(charCount), SR.ArgumentOutOfRange_GetByteCountOverflow);
 1083
 01084            return (int)byteCount;
 1085        }
 1086
 1087        public override int GetMaxCharCount(int byteCount)
 1088        {
 01089            ArgumentOutOfRangeException.ThrowIfNegative(byteCount);
 1090
 1091            // A supplementary character becomes 2 surrogate characters, so 4 input bytes becomes 2 chars,
 1092            // plus we may have 1 surrogate char left over if the decoder has 3 bytes in it already for a non-bmp char.
 1093            // Have to add another one because 1/2 == 0, but 3 bytes left over could be 2 char surrogate pair
 01094            int charCount = (byteCount / 2) + 2;
 1095
 1096            // Also consider fallback because our input bytes could be out of range of unicode.
 1097            // Since fallback would fallback 4 bytes at a time, we'll only fall back 1/2 of MaxCharCount.
 01098            if (DecoderFallback.MaxCharCount > 2)
 1099            {
 1100                // Multiply time fallback size
 01101                charCount *= DecoderFallback.MaxCharCount;
 1102
 1103                // We were already figuring 2 chars per 4 bytes, but fallback will be different #
 01104                charCount /= 2;
 1105            }
 1106
 01107            if (charCount > 0x7fffffff)
 01108                throw new ArgumentOutOfRangeException(nameof(byteCount), SR.ArgumentOutOfRange_GetCharCountOverflow);
 1109
 01110            return (int)charCount;
 1111        }
 1112
 1113        public override byte[] GetPreamble()
 1114        {
 01115            if (_emitUTF32ByteOrderMark)
 1116            {
 1117                // Allocate new array to prevent users from modifying it.
 01118                if (_bigEndian)
 1119                {
 01120                    return [0x00, 0x00, 0xFE, 0xFF];
 1121                }
 1122                else
 1123                {
 01124                    return [0xFF, 0xFE, 0x00, 0x00]; // 00 00 FE FF
 1125                }
 1126            }
 1127            else
 01128                return [];
 1129        }
 1130
 1131        public override ReadOnlySpan<byte> Preamble =>
 01132            GetType() != typeof(UTF32Encoding) ? new ReadOnlySpan<byte>(GetPreamble()) : // in case a derived UTF32Encod
 01133            !_emitUTF32ByteOrderMark ? default :
 01134            _bigEndian ? [0x00, 0x00, 0xFE, 0xFF] :
 01135            [0xFF, 0xFE, 0x00, 0x00];
 1136
 1137        public override bool Equals([NotNullWhen(true)] object? value)
 1138        {
 01139            if (value is UTF32Encoding that)
 1140            {
 01141                return (_emitUTF32ByteOrderMark == that._emitUTF32ByteOrderMark) &&
 01142                       (_bigEndian == that._bigEndian) &&
 01143                       (EncoderFallback.Equals(that.EncoderFallback)) &&
 01144                       (DecoderFallback.Equals(that.DecoderFallback));
 1145            }
 1146
 01147            return false;
 1148        }
 1149
 1150        public override int GetHashCode()
 1151        {
 1152            // Not great distribution, but this is relatively unlikely to be used as the key in a hashtable.
 01153            return this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode() +
 01154                   CodePage + (_emitUTF32ByteOrderMark ? 4 : 0) + (_bigEndian ? 8 : 0);
 1155        }
 1156
 1157        private sealed class UTF32Decoder : DecoderNLS
 1158        {
 1159            // Need a place to store any extra bytes we may have picked up
 1160            internal int iChar;
 1161            internal int readByteCount;
 1162
 01163            public UTF32Decoder(UTF32Encoding encoding) : base(encoding)
 1164            {
 1165                // base calls reset
 01166            }
 1167
 1168            public override void Reset()
 1169            {
 01170                this.iChar = 0;
 01171                this.readByteCount = 0;
 01172                _fallbackBuffer?.Reset();
 01173            }
 1174
 1175            // Anything left in our decoder?
 1176            internal override bool HasState =>
 1177                // ReadByteCount is our flag.  (iChar==0 doesn't mean much).
 01178                this.readByteCount != 0;
 1179        }
 1180    }
 1181}
 1182