< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 264
Coverable lines: 264
Total lines: 789
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 216
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Encoding.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.Buffers;
 5using System.Diagnostics;
 6using System.Diagnostics.CodeAnalysis;
 7using System.Runtime.CompilerServices;
 8using System.Runtime.InteropServices;
 9
 10namespace System.Text
 11{
 12    //
 13    // Latin1Encoding is a simple override to optimize the GetString version of Latin1Encoding.
 14    // because of the best fit cases we can't do this when encoding the string, only when decoding
 15    //
 16    internal partial class Latin1Encoding : Encoding
 17    {
 18        // Used by Encoding.Latin1 for lazy initialization
 19        // The initialization code will not be run until a static member of the class is referenced
 020        internal static readonly Latin1EncodingSealed s_default = new Latin1EncodingSealed();
 21
 22        // We only use the best-fit table, of which ASCII is a superset for us.
 023        public Latin1Encoding() : base(ISO_8859_1)
 24        {
 025        }
 26
 027        public override ReadOnlySpan<byte> Preamble => default;
 28
 29        // Default fallback that we'll use.
 30        internal sealed override void SetDefaultFallbacks()
 31        {
 32            // We use best-fit mappings by default when encoding.
 033            encoderFallback = EncoderLatin1BestFitFallback.SingletonInstance;
 034            decoderFallback = DecoderFallback.ReplacementFallback;
 035        }
 36
 37        /*
 38         * GetByteCount - Each Latin-1 char narrows to exactly one byte,
 39         * but fallback mechanism must be consulted for non-Latin-1 chars.
 40         */
 41
 42        public override unsafe int GetByteCount(char* chars, int count)
 43        {
 044            if (chars is null)
 45            {
 046                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.chars);
 47            }
 48
 049            if (count < 0)
 50            {
 051                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRan
 52            }
 53
 054            return GetByteCountCommon(chars, count);
 55        }
 56
 57        public override unsafe int GetByteCount(char[] chars, int index, int count)
 58        {
 059            if (chars is null)
 60            {
 061                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.chars, ExceptionResource.ArgumentNull_Array);
 62            }
 63
 064            if ((index | count) < 0)
 65            {
 066                ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.c
 67            }
 68
 069            if (chars.Length - index < count)
 70            {
 071                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRan
 72            }
 73
 074            fixed (char* pChars = chars)
 75            {
 076                return GetByteCountCommon(pChars + index, count);
 77            }
 78        }
 79
 80        public override unsafe int GetByteCount(ReadOnlySpan<char> chars)
 081        {
 82            // It's ok for us to pass null pointers down to the workhorse below.
 83
 084            fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
 85            {
 086                return GetByteCountCommon(charsPtr, chars.Length);
 87            }
 88        }
 89
 90        public override unsafe int GetByteCount(string s)
 91        {
 092            if (s is null)
 93            {
 094                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
 95            }
 96
 097            fixed (char* pChars = s)
 98            {
 099                return GetByteCountCommon(pChars, s.Length);
 100            }
 101        }
 102
 103        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 104        private unsafe int GetByteCountCommon(char* pChars, int charCount)
 105        {
 106            // Common helper method for all non-EncoderNLS entry points to GetByteCount.
 107            // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16,
 108
 0109            Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer.");
 0110            Debug.Assert(pChars is not null || charCount == 0, "Input pointer shouldn't be null if non-zero length speci
 111
 112            // First call into the fast path.
 113            // Don't bother providing a fallback mechanism; our fast path doesn't use it.
 114
 0115            int totalByteCount = GetByteCountFast(pChars, charCount, fallback: null, out int charsConsumed);
 116
 0117            if (charsConsumed != charCount)
 118            {
 119                // If there's still data remaining in the source buffer, go down the fallback path.
 120                // We need to check for integer overflow since the fallback could change the required
 121                // output count in unexpected ways.
 122
 0123                totalByteCount += GetByteCountWithFallback(pChars, charCount, charsConsumed);
 0124                if (totalByteCount < 0)
 125                {
 0126                    ThrowConversionOverflow();
 127                }
 128            }
 129
 0130            return totalByteCount;
 131        }
 132
 133        [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetByteCountCommon
 134        private protected sealed override unsafe int GetByteCountFast(char* pChars, int charsLength, EncoderFallback? fa
 135        {
 136            // Can we short-circuit the entire calculation? If so, the output byte count
 137            // will exactly match the input char count. Otherwise we need to walk the
 138            // entire input and find the index of the first non-Latin-1 char.
 139
 0140            int byteCount = charsLength;
 141
 0142            if (!FallbackSupportsFastGetByteCount(fallback))
 143            {
 144                // Unrecognized fallback mechanism - count chars manually.
 145
 0146                byteCount = (int)Latin1Utility.GetIndexOfFirstNonLatin1Char(pChars, (uint)charsLength);
 147            }
 148
 0149            charsConsumed = byteCount;
 0150            return byteCount;
 151        }
 152
 153        public override int GetMaxByteCount(int charCount)
 154        {
 0155            ArgumentOutOfRangeException.ThrowIfNegative(charCount);
 156
 157            // Characters would be # of characters + 1 in case high surrogate is ? * max fallback
 0158            long byteCount = (long)charCount + 1;
 159
 0160            if (EncoderFallback.MaxCharCount > 1)
 0161                byteCount *= EncoderFallback.MaxCharCount;
 162
 163            // 1 to 1 for most characters.  Only surrogates with fallbacks have less.
 164
 0165            if (byteCount > 0x7fffffff)
 0166                throw new ArgumentOutOfRangeException(nameof(charCount), SR.ArgumentOutOfRange_GetByteCountOverflow);
 0167            return (int)byteCount;
 168        }
 169
 170        /*
 171         * GetBytes - Each Latin-1 char narrows to exactly one byte,
 172         * but fallback mechanism must be consulted for non-Latin-1 chars.
 173         */
 174
 175        public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
 176        {
 0177            if (chars is null || bytes is null)
 178            {
 0179                ThrowHelper.ThrowArgumentNullException(
 0180                    argument: (chars is null) ? ExceptionArgument.chars : ExceptionArgument.bytes,
 0181                    resource: ExceptionResource.ArgumentNull_Array);
 182            }
 183
 0184            if ((charCount | byteCount) < 0)
 185            {
 0186                ThrowHelper.ThrowArgumentOutOfRangeException(
 0187                    argument: (charCount < 0) ? ExceptionArgument.charCount : ExceptionArgument.byteCount,
 0188                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 189            }
 190
 0191            return GetBytesCommon(chars, charCount, bytes, byteCount);
 192        }
 193
 194        public override unsafe int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
 195        {
 0196            if (chars is null || bytes is null)
 197            {
 0198                ThrowHelper.ThrowArgumentNullException(
 0199                    argument: (chars is null) ? ExceptionArgument.chars : ExceptionArgument.bytes,
 0200                    resource: ExceptionResource.ArgumentNull_Array);
 201            }
 202
 0203            if ((charIndex | charCount) < 0)
 204            {
 0205                ThrowHelper.ThrowArgumentOutOfRangeException(
 0206                    argument: (charIndex < 0) ? ExceptionArgument.charIndex : ExceptionArgument.charCount,
 0207                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 208            }
 209
 0210            if (chars.Length - charIndex < charCount)
 211            {
 0212                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRan
 213            }
 214
 0215            if ((uint)byteIndex > bytes.Length)
 216            {
 0217                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteIndex, ExceptionResource.ArgumentOutO
 218            }
 219
 0220            fixed (char* pChars = chars)
 0221            fixed (byte* pBytes = bytes)
 222            {
 0223                return GetBytesCommon(pChars + charIndex, charCount, pBytes + byteIndex, bytes.Length - byteIndex);
 224            }
 225        }
 226
 227        public override unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
 0228        {
 229            // It's ok for us to operate on null / empty spans.
 230
 0231            fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
 0232            fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
 233            {
 0234                return GetBytesCommon(charsPtr, chars.Length, bytesPtr, bytes.Length);
 235            }
 236        }
 237
 238        /// <inheritdoc/>
 239        public override unsafe bool TryGetBytes(ReadOnlySpan<char> chars, Span<byte> bytes, out int bytesWritten)
 0240        {
 0241            fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
 0242            fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
 243            {
 0244                int written = GetBytesCommon(charsPtr, chars.Length, bytesPtr, bytes.Length, throwForDestinationOverflow
 0245                if (written >= 0)
 246                {
 0247                    bytesWritten = written;
 0248                    return true;
 249                }
 250
 0251                bytesWritten = 0;
 0252                return false;
 253            }
 254        }
 255
 256        public override unsafe int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex)
 257        {
 0258            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
 0265            if ((charIndex | charCount) < 0)
 266            {
 0267                ThrowHelper.ThrowArgumentOutOfRangeException(
 0268                    argument: (charIndex < 0) ? ExceptionArgument.charIndex : ExceptionArgument.charCount,
 0269                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 270            }
 271
 0272            if (s.Length - charIndex < charCount)
 273            {
 0274                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.s, ExceptionResource.ArgumentOutOfRange_I
 275            }
 276
 0277            if ((uint)byteIndex > bytes.Length)
 278            {
 0279                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteIndex, ExceptionResource.ArgumentOutO
 280            }
 281
 0282            fixed (char* pChars = s)
 0283            fixed (byte* pBytes = bytes)
 284            {
 0285                return GetBytesCommon(pChars + charIndex, charCount, pBytes + byteIndex, bytes.Length - byteIndex);
 286            }
 287        }
 288
 289
 290        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 291        private unsafe int GetBytesCommon(char* pChars, int charCount, byte* pBytes, int byteCount, bool throwForDestina
 292        {
 293            // Common helper method for all non-EncoderNLS entry points to GetBytes.
 294            // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16,
 295
 0296            Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer.");
 0297            Debug.Assert(pChars is not null || charCount == 0, "Input pointer shouldn't be null if non-zero length speci
 0298            Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer.");
 0299            Debug.Assert(pBytes is not null || byteCount == 0, "Input pointer shouldn't be null if non-zero length speci
 300
 301            // First call into the fast path.
 302
 0303            int bytesWritten = GetBytesFast(pChars, charCount, pBytes, byteCount, out int charsConsumed);
 304
 0305            if (charsConsumed == charCount)
 306            {
 307                // All elements converted - return immediately.
 308
 0309                return bytesWritten;
 310            }
 311            else
 312            {
 313                // Simple narrowing conversion couldn't operate on entire buffer - invoke fallback.
 314
 0315                return GetBytesWithFallback(pChars, charCount, pBytes, byteCount, charsConsumed, bytesWritten, throwForD
 316            }
 317        }
 318
 319        [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetBytesCommon
 320        private protected sealed override unsafe int GetBytesFast(char* pChars, int charsLength, byte* pBytes, int bytes
 321        {
 0322            int bytesWritten = (int)Latin1Utility.NarrowUtf16ToLatin1(pChars, pBytes, (uint)Math.Min(charsLength, bytesL
 323
 0324            charsConsumed = bytesWritten;
 0325            return bytesWritten;
 326        }
 327
 328
 329        /*
 330         * GetCharCount - Each byte widens to exactly one char, preserving count.
 331         * We never consult the fallback mechanism during decoding.
 332         */
 333
 334        public override unsafe int GetCharCount(byte* bytes, int count)
 335        {
 0336            if (bytes is null)
 337            {
 0338                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes);
 339            }
 340
 0341            if (count < 0)
 342            {
 0343                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRan
 344            }
 345
 0346            return count;
 347        }
 348
 349        public override int GetCharCount(byte[] bytes)
 350        {
 0351            if (bytes is null)
 352            {
 0353                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes);
 354            }
 355
 0356            return bytes.Length;
 357        }
 358
 359        public override int GetCharCount(byte[] bytes, int index, int count)
 360        {
 0361            if (bytes is null)
 362            {
 0363                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes, ExceptionResource.ArgumentNull_Array);
 364            }
 365
 0366            if ((index | count) < 0)
 367            {
 0368                ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.c
 369            }
 370
 0371            if (bytes.Length - index < count)
 372            {
 0373                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRan
 374            }
 375
 0376            return count;
 377        }
 378
 379        public override int GetCharCount(ReadOnlySpan<byte> bytes)
 380        {
 0381            return bytes.Length;
 382        }
 383
 384        private protected override unsafe int GetCharCountFast(byte* pBytes, int bytesLength, DecoderFallback? fallback,
 385        {
 386            // We never consult the fallback mechanism during GetChars.
 387            // A single byte is always widened to a single char, so we'll return
 388            // the byte count as the final char count.
 389
 0390            bytesConsumed = bytesLength;
 0391            return bytesLength;
 392        }
 393
 394        public override int GetMaxCharCount(int byteCount)
 395        {
 396            // Unlike GetMaxByteCount, there won't be any pending surrogates for bytes -> chars conversions.
 397
 0398            if (byteCount < 0)
 399            {
 0400                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteCount, ExceptionResource.ArgumentOutO
 401            }
 402
 0403            return byteCount;
 404        }
 405
 406        /*
 407         * GetChars - Each byte widens to exactly one char, preserving count.
 408         * We never consult the fallback mechanism during decoding.
 409         */
 410
 411        public override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
 412        {
 0413            if (bytes is null || chars is null)
 414            {
 0415                ThrowHelper.ThrowArgumentNullException(
 0416                    argument: (bytes is null) ? ExceptionArgument.bytes : ExceptionArgument.chars,
 0417                    resource: ExceptionResource.ArgumentNull_Array);
 418            }
 419
 0420            if ((byteCount | charCount) < 0)
 421            {
 0422                ThrowHelper.ThrowArgumentOutOfRangeException(
 0423                    argument: (byteCount < 0) ? ExceptionArgument.byteCount : ExceptionArgument.charCount,
 0424                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 425            }
 426
 0427            return GetCharsCommon(bytes, byteCount, chars, charCount);
 428        }
 429
 430        public override unsafe char[] GetChars(byte[] bytes)
 431        {
 0432            if (bytes is null)
 433            {
 0434                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes);
 435            }
 436
 0437            if (bytes.Length == 0)
 438            {
 0439                return [];
 440            }
 441
 442            // Since we're going to fill the entire char[] buffer, we could consider GC.AllocateUninitializedArray.
 443
 0444            char[] chars = new char[bytes.Length];
 445
 0446            fixed (byte* pBytes = bytes)
 0447            fixed (char* pChars = chars)
 448            {
 0449                GetCharsCommon(pBytes, bytes.Length, pChars, chars.Length);
 450            }
 451
 0452            return chars;
 453        }
 454
 455        public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
 456        {
 0457            if (bytes is null || chars is null)
 458            {
 0459                ThrowHelper.ThrowArgumentNullException(
 0460                    argument: (bytes is null) ? ExceptionArgument.bytes : ExceptionArgument.chars,
 0461                    resource: ExceptionResource.ArgumentNull_Array);
 462            }
 463
 0464            if ((byteIndex | byteCount) < 0)
 465            {
 0466                ThrowHelper.ThrowArgumentOutOfRangeException(
 0467                    argument: (byteIndex < 0) ? ExceptionArgument.byteIndex : ExceptionArgument.byteCount,
 0468                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 469            }
 470
 0471            if (bytes.Length - byteIndex < byteCount)
 472            {
 0473                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRan
 474            }
 475
 0476            if ((uint)charIndex > (uint)chars.Length)
 477            {
 0478                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.charIndex, ExceptionResource.ArgumentOutO
 479            }
 480
 0481            fixed (byte* pBytes = bytes)
 0482            fixed (char* pChars = chars)
 483            {
 0484                return GetCharsCommon(pBytes + byteIndex, byteCount, pChars + charIndex, chars.Length - charIndex);
 485            }
 486        }
 487
 488        public override unsafe char[] GetChars(byte[] bytes, int index, int count)
 489        {
 0490            if (bytes is null)
 491            {
 0492                ThrowHelper.ThrowArgumentNullException(
 0493                    argument: ExceptionArgument.bytes,
 0494                    resource: ExceptionResource.ArgumentNull_Array);
 495            }
 496
 0497            if ((index | count) < 0)
 498            {
 0499                ThrowHelper.ThrowArgumentOutOfRangeException(
 0500                    argument: (index < 0) ? ExceptionArgument.index : ExceptionArgument.count,
 0501                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 502            }
 503
 0504            if (bytes.Length - index < count)
 505            {
 0506                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRan
 507            }
 508
 509            // Since we're going to fill the entire char[] buffer, we could consider GC.AllocateUninitializedArray.
 510
 0511            char[] chars = new char[count];
 512
 0513            fixed (byte* pBytes = bytes)
 0514            fixed (char* pChars = chars)
 515            {
 0516                GetCharsCommon(pBytes + index, count, pChars, chars.Length);
 517            }
 518
 0519            return chars;
 520        }
 521
 522        public override unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
 0523        {
 524            // It's ok for us to pass null pointers down to the workhorse below.
 525
 0526            fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
 0527            fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
 528            {
 0529                return GetCharsCommon(bytesPtr, bytes.Length, charsPtr, chars.Length);
 530            }
 531        }
 532
 533        /// <inheritdoc/>
 534        public override unsafe bool TryGetChars(ReadOnlySpan<byte> bytes, Span<char> chars, out int charsWritten)
 535        {
 0536            if (bytes.Length <= chars.Length)
 0537            {
 0538                fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
 0539                fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
 540                {
 0541                    charsWritten = GetCharsCommon(bytesPtr, bytes.Length, charsPtr, chars.Length);
 0542                    return true;
 543                }
 544            }
 545
 0546            charsWritten = 0;
 0547            return false;
 548        }
 549
 550        public override unsafe string GetString(byte[] bytes)
 551        {
 0552            if (bytes is null)
 553            {
 0554                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes);
 555            }
 556
 0557            string result = string.FastAllocateString(bytes.Length);
 0558            fixed (byte* pBytes = bytes)
 0559            fixed (char* pChars = result)
 560            {
 0561                GetCharsCommon(pBytes, bytes.Length, pChars, result.Length);
 562            }
 0563            return result;
 564        }
 565
 566        public override unsafe string GetString(byte[] bytes, int index, int count)
 567        {
 0568            if (bytes is null)
 569            {
 0570                ThrowHelper.ThrowArgumentNullException(
 0571                    argument: ExceptionArgument.bytes,
 0572                    resource: ExceptionResource.ArgumentNull_Array);
 573            }
 574
 0575            if ((index | count) < 0)
 576            {
 0577                ThrowHelper.ThrowArgumentOutOfRangeException(
 0578                    argument: (index < 0) ? ExceptionArgument.index : ExceptionArgument.count,
 0579                    resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
 580            }
 581
 0582            if (bytes.Length - index < count)
 583            {
 0584                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRan
 585            }
 586
 0587            string result = string.FastAllocateString(count);
 0588            fixed (byte* pBytes = bytes)
 0589            fixed (char* pChars = result)
 590            {
 0591                GetCharsCommon(pBytes + index, count, pChars, count);
 592            }
 0593            return result;
 594        }
 595
 596        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 597        private unsafe int GetCharsCommon(byte* pBytes, int byteCount, char* pChars, int charCount)
 598        {
 599            // Common helper method for all non-DecoderNLS entry points to GetChars.
 600            // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16,
 601
 0602            Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer.");
 0603            Debug.Assert(pBytes is not null || byteCount == 0, "Input pointer shouldn't be null if non-zero length speci
 0604            Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer.");
 0605            Debug.Assert(pChars is not null || charCount == 0, "Input pointer shouldn't be null if non-zero length speci
 606
 607            // If we already know ahead of time that the destination buffer isn't large enough to hold
 608            // the widened data, fail immediately.
 609
 0610            if (byteCount > charCount)
 611            {
 0612                ThrowCharsOverflow();
 613            }
 614
 0615            Latin1Utility.WidenLatin1ToUtf16(pBytes, pChars, (uint)byteCount);
 0616            return byteCount;
 617        }
 618
 619        // called by the fallback mechanism
 620        private protected sealed override unsafe int GetCharsFast(byte* pBytes, int bytesLength, char* pChars, int chars
 621        {
 0622            int charsWritten = Math.Min(bytesLength, charsLength);
 0623            Latin1Utility.WidenLatin1ToUtf16(pBytes, pChars, (uint)charsWritten);
 624
 0625            bytesConsumed = charsWritten;
 0626            return charsWritten;
 627        }
 628
 629        public override Decoder GetDecoder()
 630        {
 0631            return new DecoderNLS(this);
 632        }
 633
 634        public override Encoder GetEncoder()
 635        {
 0636            return new EncoderNLS(this);
 637        }
 638
 639        //
 640        // Beginning of methods used by shared fallback logic.
 641        //
 642
 643        internal sealed override bool TryGetByteCount(Rune value, out int byteCount)
 644        {
 645            // We can only process U+0000..U+00FF.
 646            // Everything else must go through the fallback mechanism.
 647
 0648            if (value.Value <= byte.MaxValue)
 649            {
 0650                byteCount = 1;
 0651                return true;
 652            }
 653            else
 654            {
 0655                byteCount = default;
 0656                return false;
 657            }
 658        }
 659
 660        internal sealed override OperationStatus EncodeRune(Rune value, Span<byte> bytes, out int bytesWritten)
 661        {
 662            // We can only process U+0000..U+00FF.
 663            // Everything else must go through the fallback mechanism.
 664
 0665            if (value.Value <= byte.MaxValue)
 666            {
 0667                if (!bytes.IsEmpty)
 668                {
 0669                    bytes[0] = (byte)value.Value;
 0670                    bytesWritten = 1;
 0671                    return OperationStatus.Done;
 672                }
 673                else
 674                {
 0675                    bytesWritten = 0;
 0676                    return OperationStatus.DestinationTooSmall;
 677                }
 678            }
 679            else
 680            {
 0681                bytesWritten = 0;
 0682                return OperationStatus.InvalidData;
 683            }
 684        }
 685
 686        internal sealed override OperationStatus DecodeFirstRune(ReadOnlySpan<byte> bytes, out Rune value, out int bytes
 687        {
 0688            if (!bytes.IsEmpty)
 689            {
 690                // Latin-1 byte
 0691                byte b = bytes[0];
 0692                value = new Rune(b);
 0693                bytesConsumed = 1;
 0694                return OperationStatus.Done;
 695            }
 696            else
 697            {
 698                // No data to decode
 0699                value = Rune.ReplacementChar;
 0700                bytesConsumed = 0;
 0701                return OperationStatus.NeedMoreData;
 702            }
 703        }
 704
 705        //
 706        // End of methods used by shared fallback logic.
 707        //
 708
 709        // True if and only if the encoding only uses single byte code points.  (Ie, ASCII, 1252, etc)
 0710        public override bool IsSingleByte => true;
 711
 712        public override bool IsAlwaysNormalized(NormalizationForm form)
 713        {
 714            // Latin-1 contains precomposed characters, so normal for Form C.
 715            // Since some are composed, not normal for D & KD.
 716            // Also some letters like 0x00A8 (spacing diarisis) have compatibility decompositions, so false for KD & KC.
 717
 718            // Only true for form C.
 0719            return form == NormalizationForm.FormC;
 720        }
 721
 722        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 723        private static bool FallbackSupportsFastGetByteCount(EncoderFallback? fallback)
 724        {
 725            // If the caller didn't provide a fallback mechanism, they wanted us
 726            // to suppress short-circuiting the operation.
 727
 0728            if (fallback is null)
 729            {
 0730                return false;
 731            }
 732
 733            // If we're using the default best-fit fallback mechanism, we know that
 734            // any non-Latin-1 char will get replaced with a Latin-1 byte.
 735
 0736            if (fallback is EncoderLatin1BestFitFallback)
 737            {
 0738                return true;
 739            }
 740
 741            // If we're using a replacement fallback, and if the replacement fallback
 742            // replaces non-Latin-1 chars with Latin-1 bytes, then we know that
 743            // the number of output bytes will match the number of input chars.
 744
 0745            if (fallback is EncoderReplacementFallback replacementFallback
 0746                && replacementFallback.MaxCharCount == 1
 0747                && replacementFallback.DefaultString[0] <= byte.MaxValue)
 748            {
 0749                return true;
 750            }
 751
 752            // Otherwise we don't know the fallback behavior when it sees non-Latin-1
 753            // chars, so we can't assume the number of output bytes will match the
 754            // number of input chars.
 755
 0756            return false;
 757        }
 758    }
 759}
 760

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Encoding.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
 4namespace System.Text
 5{
 6    internal partial class Latin1Encoding : Encoding
 7    {
 8        /// <summary>
 9        /// A special instance of <see cref="Latin1Encoding"/> that is initialized with "don't throw on invalid sequence
 10        /// use best-fit substitution instead" semantics. This type allows for devirtualization of calls made directly
 11        /// off of <see cref="Encoding.Latin1"/>.
 12        /// </summary>
 13        internal sealed class Latin1EncodingSealed : Latin1Encoding
 14        {
 15            public override object Clone()
 16            {
 17                // The base implementation of Encoding.Clone calls object.MemberwiseClone and marks the new object mutab
 18                // We don't want to do this because it violates the invariants we have set for the sealed type.
 19                // Instead, we'll create a new instance of the base Latin1Encoding type and mark it mutable.
 20
 021                return new Latin1Encoding()
 022                {
 023                    IsReadOnly = false
 024                };
 25            }
 26        }
 27    }
 28}
 29

Methods/Properties

.cctor()
.ctor()
Preamble()
SetDefaultFallbacks()
GetByteCount(System.Char*,System.Int32)
GetByteCount(System.Char[],System.Int32,System.Int32)
GetByteCount(System.ReadOnlySpan`1<System.Char>)
GetByteCount(System.String)
GetByteCountCommon(System.Char*,System.Int32)
GetByteCountFast(System.Char*,System.Int32,System.Text.EncoderFallback,System.Int32&)
GetMaxByteCount(System.Int32)
GetBytes(System.Char*,System.Int32,System.Byte*,System.Int32)
GetBytes(System.Char[],System.Int32,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&)
GetBytes(System.String,System.Int32,System.Int32,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)
GetCharCount(System.Byte[])
GetCharCount(System.Byte[],System.Int32,System.Int32)
GetCharCount(System.ReadOnlySpan`1<System.Byte>)
GetCharCountFast(System.Byte*,System.Int32,System.Text.DecoderFallback,System.Int32&)
GetMaxCharCount(System.Int32)
GetChars(System.Byte*,System.Int32,System.Char*,System.Int32)
GetChars(System.Byte[])
GetChars(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)
GetChars(System.Byte[],System.Int32,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&)
GetString(System.Byte[])
GetString(System.Byte[],System.Int32,System.Int32)
GetCharsCommon(System.Byte*,System.Int32,System.Char*,System.Int32)
GetCharsFast(System.Byte*,System.Int32,System.Char*,System.Int32,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&)
IsSingleByte()
IsAlwaysNormalized(System.Text.NormalizationForm)
FallbackSupportsFastGetByteCount(System.Text.EncoderFallback)
Clone()