< Summary

Information
Class: System.Buffers.Text.Utf8Parser
Assembly: System.Private.CoreLib
File(s): File 1: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Boolean.cs
File 2: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.cs
File 3: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.Default.cs
File 4: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.G.cs
File 5: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.Helpers.cs
File 6: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.O.cs
File 7: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.R.cs
File 8: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Decimal.cs
File 9: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Float.cs
File 10: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Guid.cs
File 11: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Signed.cs
File 12: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Signed.D.cs
File 13: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Signed.N.cs
File 14: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.cs
File 15: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.D.cs
File 16: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.N.cs
File 17: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.X.cs
File 18: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Number.cs
File 19: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.BigG.cs
File 20: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.C.cs
File 21: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.cs
File 22: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.LittleG.cs
File 23: C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpanSplitter.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 2015
Coverable lines: 2015
Total lines: 4933
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 1489
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
File 1: TryParse(...)0%16160%
File 2: TryParse(...)0%22220%
File 2: TryParse(...)0%12120%
File 3: TryParseDateTimeOffsetDefault(...)0%22220%
File 4: TryParseDateTimeG(...)0%42420%
File 5: TryCreateDateTimeOffset(...)0%10100%
File 5: TryCreateDateTimeOffset(...)0%440%
File 5: TryCreateDateTimeOffsetInterpretingDataAsLocalTime(...)0%220%
File 5: TryCreateDateTime(...)0%18180%
File 6: TryParseDateTimeOffsetO(...)0%86860%
File 7: TryParseDateTimeOffsetR(...)0%90900%
File 8: TryParse(...)0%20200%
File 9: TryParse(...)0%220%
File 9: TryParse(...)0%220%
File 9: TryParseNormalAsFloatingPoint(...)0%18180%
File 9: TryParseAsSpecialFloatingPoint(...)0%22220%
File 10: TryParse(...)0%12120%
File 10: TryParseGuidN(...)0%22220%
File 10: TryParseGuidCore(...)0%40400%
File 11: TryParse(...)0%14140%
File 11: TryParse(...)0%14140%
File 11: TryParse(...)0%14140%
File 11: TryParse(...)0%14140%
File 12: TryParseSByteD(...)0%34340%
File 12: TryParseInt16D(...)0%42420%
File 12: TryParseInt32D(...)0%64640%
File 12: TryParseInt64D(...)0%26260%
File 13: TryParseSByteN(...)0%34340%
File 13: TryParseInt16N(...)0%34340%
File 13: TryParseInt32N(...)0%36360%
File 13: TryParseInt64N(...)0%36360%
File 14: TryParse(...)0%14140%
File 14: TryParse(...)0%14140%
File 14: TryParse(...)0%14140%
File 14: TryParse(...)0%14140%
File 15: TryParseByteD(...)0%26260%
File 15: TryParseUInt16D(...)0%34340%
File 15: TryParseUInt32D(...)0%58580%
File 15: TryParseUInt64D(...)0%20200%
File 16: TryParseByteN(...)0%30300%
File 16: TryParseUInt16N(...)0%30300%
File 16: TryParseUInt32N(...)0%34340%
File 16: TryParseUInt64N(...)0%34340%
File 17: TryParseByteX(...)0%20200%
File 17: TryParseUInt16X(...)0%20200%
File 17: TryParseUInt32X(...)0%20200%
File 17: TryParseUInt64X(...)0%20200%
File 18: TryParseNumber(...)0%72720%
File 19: TryParseTimeSpanBigG(...)0%46460%
File 20: TryParseTimeSpanC(...)0%22220%
File 21: TryParse(...)0%14140%
File 21: TryParseTimeSpanFraction(...)0%17170%
File 21: TryCreateTimeSpan(...)0%16160%
File 22: TryParseTimeSpanLittleG(...)0%18180%
File 23: TrySplitTimeSpan(...)0%44440%
File 23: ParseComponent(...)0%14140%

File(s)

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Boolean.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.Binary;
 5
 6namespace System.Buffers.Text
 7{
 8    public static partial class Utf8Parser
 9    {
 10        /// <summary>
 11        /// Parses a Boolean at the start of a Utf8 string.
 12        /// </summary>
 13        /// <param name="source">The Utf8 string to parse</param>
 14        /// <param name="value">Receives the parsed value</param>
 15        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 16        /// <param name="standardFormat">Expected format of the Utf8 string. Supported formats are <c>'G'</c>, <c>'l'</c
 17        /// <returns>
 18        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 19        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 20        /// </returns>
 21        /// <remarks>
 22        /// The parsing is case insensitive. The format parameter is validated to ensure it is supported; however, all s
 23        /// </remarks>
 24        /// <exceptions>
 25        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 26        /// </exceptions>
 27        public static bool TryParse(ReadOnlySpan<byte> source, out bool value, out int bytesConsumed, char standardForma
 28        {
 029            if (!(standardFormat == default(char) || standardFormat == 'G' || standardFormat == 'l'))
 030                ThrowHelper.ThrowFormatException_BadFormatSpecifier();
 31
 032            if (source.Length >= 4)
 33            {
 034                int dw = BinaryPrimitives.ReadInt32LittleEndian(source) & ~0x20202020;
 035                if (dw == 0x45555254 /* 'EURT' */)
 36                {
 037                    bytesConsumed = 4;
 038                    value = true;
 039                    return true;
 40                }
 41
 042                if (source.Length > 4)
 43                {
 044                    if (dw == 0x534c4146 /* 'SLAF' */ && (source[4] & ~0x20) == 'E')
 45                    {
 046                        bytesConsumed = 5;
 047                        value = false;
 048                        return true;
 49                    }
 50                }
 51            }
 52
 053            bytesConsumed = 0;
 054            value = default;
 055            return false;
 56        }
 57    }
 58}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.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;
 5
 6namespace System.Buffers.Text
 7{
 8    public static partial class Utf8Parser
 9    {
 10        /// <summary>
 11        /// Parses a DateTime at the start of a Utf8 string.
 12        /// </summary>
 13        /// <param name="source">The Utf8 string to parse</param>
 14        /// <param name="value">Receives the parsed value</param>
 15        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 16        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 17        /// <returns>
 18        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 19        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 20        /// </returns>
 21        /// <remarks>
 22        /// Formats supported:
 23        ///     default       05/25/2017 10:30:15 -08:00
 24        ///     G             05/25/2017 10:30:15
 25        ///     R             Tue, 03 Jan 2017 08:08:05 GMT       (RFC 1123)
 26        ///     l             tue, 03 jan 2017 08:08:05 gmt       (Lowercase RFC 1123)
 27        ///     O             2017-06-12T05:30:45.7680000-07:00   (Round-trippable)
 28        /// </remarks>
 29        /// <exceptions>
 30        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 31        /// </exceptions>
 32        public static bool TryParse(ReadOnlySpan<byte> source, out DateTime value, out int bytesConsumed, char standardF
 33        {
 34            switch (standardFormat)
 35            {
 36                case 'R':
 37                    {
 038                        if (!TryParseDateTimeOffsetR(source, NoFlipCase, out DateTimeOffset dateTimeOffset, out bytesCon
 39                        {
 040                            value = default;
 041                            return false;
 42                        }
 043                        value = dateTimeOffset.DateTime;  // (returns a DateTimeKind.Unspecified to match DateTime.Parse
 044                        return true;
 45                    }
 46
 47                case 'l':
 48                    {
 049                        if (!TryParseDateTimeOffsetR(source, FlipCase, out DateTimeOffset dateTimeOffset, out bytesConsu
 50                        {
 051                            value = default;
 052                            return false;
 53                        }
 054                        value = dateTimeOffset.DateTime;  // (returns a DateTimeKind.Unspecified to match DateTime.Parse
 055                        return true;
 56                    }
 57
 58                case 'O':
 59                    {
 60                        // Emulates DateTime.ParseExact(text, "O", CultureInfo.InvariantCulture, DateTimeStyles.Roundtri
 61                        // In particular, the formatted string "encodes" the DateTimeKind according to the following tab
 62                        //
 63                        //         2017-06-12T05:30:45.7680000       - Unspecified
 64                        //         2017-06-12T05:30:45.7680000+00:00 - Local
 65                        //         2017-06-12T05:30:45.7680000Z      - Utc
 66
 067                        if (!TryParseDateTimeOffsetO(source, out DateTimeOffset dateTimeOffset, out bytesConsumed, out D
 68                        {
 069                            value = default;
 070                            bytesConsumed = 0;
 071                            return false;
 72                        }
 73
 74                        switch (kind)
 75                        {
 76                            case DateTimeKind.Local:
 077                                value = dateTimeOffset.LocalDateTime;
 078                                break;
 79                            case DateTimeKind.Utc:
 080                                value = dateTimeOffset.UtcDateTime;
 081                                break;
 82                            default:
 083                                Debug.Assert(kind == DateTimeKind.Unspecified);
 084                                value = dateTimeOffset.DateTime;
 85                                break;
 86                        }
 87
 088                        return true;
 89                    }
 90
 91                case default(char):
 92                case 'G':
 093                    return TryParseDateTimeG(source, out value, out _, out bytesConsumed);
 94
 95                default:
 096                    return ParserHelpers.TryParseThrowFormatException(out value, out bytesConsumed);
 97            }
 98        }
 99
 100        /// <summary>
 101        /// Parses a DateTimeOffset at the start of a Utf8 string.
 102        /// </summary>
 103        /// <param name="source">The Utf8 string to parse</param>
 104        /// <param name="value">Receives the parsed value</param>
 105        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 106        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 107        /// <returns>
 108        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 109        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 110        /// </returns>
 111        /// <remarks>
 112        /// Formats supported:
 113        ///     G  (default)  05/25/2017 10:30:15
 114        ///     R             Tue, 03 Jan 2017 08:08:05 GMT       (RFC 1123)
 115        ///     l             tue, 03 jan 2017 08:08:05 gmt       (Lowercase RFC 1123)
 116        ///     O             2017-06-12T05:30:45.7680000-07:00   (Round-trippable)
 117        /// </remarks>
 118        /// <exceptions>
 119        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 120        /// </exceptions>
 121        public static bool TryParse(ReadOnlySpan<byte> source, out DateTimeOffset value, out int bytesConsumed, char sta
 122        {
 0123            return standardFormat switch
 0124            {
 0125                'R' => TryParseDateTimeOffsetR(source, NoFlipCase, out value, out bytesConsumed),
 0126                'l' => TryParseDateTimeOffsetR(source, FlipCase, out value, out bytesConsumed),
 0127                'O' => TryParseDateTimeOffsetO(source, out value, out bytesConsumed, out _),
 0128                default(char) => TryParseDateTimeOffsetDefault(source, out value, out bytesConsumed),
 0129                'G' => TryParseDateTimeG(source, out DateTime _, out value, out bytesConsumed),
 0130                _ => ParserHelpers.TryParseThrowFormatException(out value, out bytesConsumed),
 0131            };
 132        }
 133
 134        private const uint FlipCase = 0x00000020u;  // XOR mask to flip the case of a letter.
 135        private const uint NoFlipCase = 0x00000000u;
 136    }
 137}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.Default.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        //
 9        // ToString() format for DateTimeOffset. Does not have a corresponding format symbol but it
 10        // is the "G" format postpended with the UTC offset.
 11        //
 12        // 01234567890123456789012345
 13        // --------------------------
 14        // 05/25/2017 10:30:15 -08:00
 15        //
 16        private static bool TryParseDateTimeOffsetDefault(ReadOnlySpan<byte> source, out DateTimeOffset value, out int b
 17        {
 018            if (source.Length < 26)
 19            {
 020                bytesConsumed = 0;
 021                value = default;
 022                return false;
 23            }
 24
 025            if (!TryParseDateTimeG(source, out DateTime dateTime, out _, out _))
 26            {
 027                bytesConsumed = 0;
 028                value = default;
 029                return false;
 30            }
 31
 032            if (source[19] != Utf8Constants.Space)
 33            {
 034                bytesConsumed = 0;
 035                value = default;
 036                return false;
 37            }
 38
 039            byte sign = source[20];
 040            if (sign != Utf8Constants.Plus && sign != Utf8Constants.Minus)
 41            {
 042                bytesConsumed = 0;
 043                value = default;
 044                return false;
 45            }
 46
 47            int offsetHours;
 48            {
 049                uint digit1 = source[21] - 48u; // '0'
 050                uint digit2 = source[22] - 48u; // '0'
 51
 052                if (digit1 > 9 || digit2 > 9)
 53                {
 054                    bytesConsumed = 0;
 055                    value = default;
 056                    return false;
 57                }
 58
 059                offsetHours = (int)(digit1 * 10 + digit2);
 60            }
 61
 062            if (source[23] != Utf8Constants.Colon)
 63            {
 064                bytesConsumed = 0;
 065                value = default;
 066                return false;
 67            }
 68
 69            int offsetMinutes;
 70            {
 071                uint digit1 = source[24] - 48u; // '0'
 072                uint digit2 = source[25] - 48u; // '0'
 73
 074                if (digit1 > 9 || digit2 > 9)
 75                {
 076                    bytesConsumed = 0;
 077                    value = default;
 078                    return false;
 79                }
 80
 081                offsetMinutes = (int)(digit1 * 10 + digit2);
 82            }
 83
 084            if (!TryCreateDateTimeOffset(dateTime: dateTime, offsetNegative: sign == Utf8Constants.Minus, offsetHours: o
 85            {
 086                bytesConsumed = 0;
 087                value = default;
 088                return false;
 89            }
 90
 091            bytesConsumed = 26;
 092            return true;
 93        }
 94    }
 95}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.G.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        //
 9        // 'G' format for DateTime.
 10        //
 11        //   0123456789012345678
 12        //   ---------------------------------
 13        //   05/25/2017 10:30:15
 14        //
 15        private static bool TryParseDateTimeG(ReadOnlySpan<byte> source, out DateTime value, out DateTimeOffset valueAsO
 16        {
 017            if (source.Length < 19)
 18            {
 019                bytesConsumed = 0;
 020                value = default;
 021                valueAsOffset = default;
 022                return false;
 23            }
 24
 25            int month;
 26            {
 027                uint digit1 = source[0] - 48u; // '0'
 028                uint digit2 = source[1] - 48u; // '0'
 29
 030                if (digit1 > 9 || digit2 > 9)
 31                {
 032                    bytesConsumed = 0;
 033                    value = default;
 034                    valueAsOffset = default;
 035                    return false;
 36                }
 37
 038                month = (int)(digit1 * 10 + digit2);
 39            }
 40
 041            if (source[2] != Utf8Constants.Slash)
 42            {
 043                bytesConsumed = 0;
 044                value = default;
 045                valueAsOffset = default;
 046                return false;
 47            }
 48
 49            int day;
 50            {
 051                uint digit1 = source[3] - 48u; // '0'
 052                uint digit2 = source[4] - 48u; // '0'
 53
 054                if (digit1 > 9 || digit2 > 9)
 55                {
 056                    bytesConsumed = 0;
 057                    value = default;
 058                    valueAsOffset = default;
 059                    return false;
 60                }
 61
 062                day = (int)(digit1 * 10 + digit2);
 63            }
 64
 065            if (source[5] != Utf8Constants.Slash)
 66            {
 067                bytesConsumed = 0;
 068                value = default;
 069                valueAsOffset = default;
 070                return false;
 71            }
 72
 73            int year;
 74            {
 075                uint digit1 = source[6] - 48u; // '0'
 076                uint digit2 = source[7] - 48u; // '0'
 077                uint digit3 = source[8] - 48u; // '0'
 078                uint digit4 = source[9] - 48u; // '0'
 79
 080                if (digit1 > 9 || digit2 > 9 || digit3 > 9 || digit4 > 9)
 81                {
 082                    bytesConsumed = 0;
 083                    value = default;
 084                    valueAsOffset = default;
 085                    return false;
 86                }
 87
 088                year = (int)(digit1 * 1000 + digit2 * 100 + digit3 * 10 + digit4);
 89            }
 90
 091            if (source[10] != Utf8Constants.Space)
 92            {
 093                bytesConsumed = 0;
 094                value = default;
 095                valueAsOffset = default;
 096                return false;
 97            }
 98
 99            int hour;
 100            {
 0101                uint digit1 = source[11] - 48u; // '0'
 0102                uint digit2 = source[12] - 48u; // '0'
 103
 0104                if (digit1 > 9 || digit2 > 9)
 105                {
 0106                    bytesConsumed = 0;
 0107                    value = default;
 0108                    valueAsOffset = default;
 0109                    return false;
 110                }
 111
 0112                hour = (int)(digit1 * 10 + digit2);
 113            }
 114
 0115            if (source[13] != Utf8Constants.Colon)
 116            {
 0117                bytesConsumed = 0;
 0118                value = default;
 0119                valueAsOffset = default;
 0120                return false;
 121            }
 122
 123            int minute;
 124            {
 0125                uint digit1 = source[14] - 48u; // '0'
 0126                uint digit2 = source[15] - 48u; // '0'
 127
 0128                if (digit1 > 9 || digit2 > 9)
 129                {
 0130                    bytesConsumed = 0;
 0131                    value = default;
 0132                    valueAsOffset = default;
 0133                    return false;
 134                }
 135
 0136                minute = (int)(digit1 * 10 + digit2);
 137            }
 138
 0139            if (source[16] != Utf8Constants.Colon)
 140            {
 0141                bytesConsumed = 0;
 0142                value = default;
 0143                valueAsOffset = default;
 0144                return false;
 145            }
 146
 147            int second;
 148            {
 0149                uint digit1 = source[17] - 48u; // '0'
 0150                uint digit2 = source[18] - 48u; // '0'
 151
 0152                if (digit1 > 9 || digit2 > 9)
 153                {
 0154                    bytesConsumed = 0;
 0155                    value = default;
 0156                    valueAsOffset = default;
 0157                    return false;
 158                }
 159
 0160                second = (int)(digit1 * 10 + digit2);
 161            }
 162
 0163            if (!TryCreateDateTimeOffsetInterpretingDataAsLocalTime(year: year, month: month, day: day, hour: hour, minu
 164            {
 0165                bytesConsumed = 0;
 0166                value = default;
 0167                valueAsOffset = default;
 0168                return false;
 169            }
 170
 0171            bytesConsumed = 19;
 0172            value = valueAsOffset.DateTime;
 0173            return true;
 174        }
 175    }
 176}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.Helpers.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.Globalization;
 6
 7namespace System.Buffers.Text
 8{
 9    public static partial class Utf8Parser
 10    {
 11        /// <summary>
 12        /// Overflow-safe DateTimeOffset factory.
 13        /// </summary>
 14        private static bool TryCreateDateTimeOffset(DateTime dateTime, bool offsetNegative, int offsetHours, int offsetM
 15        {
 016            if (((uint)offsetHours) > Utf8Constants.DateTimeMaxUtcOffsetHours)
 17            {
 018                value = default;
 019                return false;
 20            }
 21
 022            if (((uint)offsetMinutes) > 59)
 23            {
 024                value = default;
 025                return false;
 26            }
 27
 028            if (offsetHours == Utf8Constants.DateTimeMaxUtcOffsetHours && offsetMinutes != 0)
 29            {
 030                value = default;
 031                return false;
 32            }
 33
 034            long offsetTicks = (((long)offsetHours) * 3600 + ((long)offsetMinutes) * 60) * TimeSpan.TicksPerSecond;
 035            if (offsetNegative)
 36            {
 037                offsetTicks = -offsetTicks;
 38            }
 39
 40            try
 41            {
 042                value = new DateTimeOffset(ticks: dateTime.Ticks, offset: new TimeSpan(ticks: offsetTicks));
 043            }
 044            catch (ArgumentOutOfRangeException)
 45            {
 46                // If we got here, the combination of the DateTime + UTC offset strayed outside the 1..9999 year range. 
 47                // that it's better to catch the exception rather than replicate DateTime's range checking (which it's g
 048                value = default;
 049                return false;
 50            }
 51
 052            return true;
 053        }
 54
 55        /// <summary>
 56        /// Overflow-safe DateTimeOffset factory.
 57        /// </summary>
 58        private static bool TryCreateDateTimeOffset(int year, int month, int day, int hour, int minute, int second, int 
 59        {
 060            if (!TryCreateDateTime(year: year, month: month, day: day, hour: hour, minute: minute, second: second, fract
 61            {
 062                value = default;
 063                return false;
 64            }
 65
 066            if (!TryCreateDateTimeOffset(dateTime: dateTime, offsetNegative: offsetNegative, offsetHours: offsetHours, o
 67            {
 068                value = default;
 069                return false;
 70            }
 71
 072            return true;
 73        }
 74
 75        /// <summary>
 76        /// Overflow-safe DateTimeOffset/Local time conversion factory.
 77        /// </summary>
 78        private static bool TryCreateDateTimeOffsetInterpretingDataAsLocalTime(int year, int month, int day, int hour, i
 79        {
 080            if (!TryCreateDateTime(year: year, month: month, day: day, hour: hour, minute: minute, second: second, fract
 81            {
 082                value = default;
 083                return false;
 84            }
 85
 86            try
 87            {
 088                value = new DateTimeOffset(dateTime);
 089            }
 090            catch (ArgumentOutOfRangeException)
 91            {
 92                // If we got here, the combination of the DateTime + UTC offset strayed outside the 1..9999 year range. 
 93                // that it's better to catch the exception rather than replicate DateTime's range checking (which it's g
 94
 095                value = default;
 096                return false;
 97            }
 98
 099            return true;
 0100        }
 101
 102        /// <summary>
 103        /// Overflow-safe DateTime factory.
 104        /// </summary>
 105        private static bool TryCreateDateTime(int year, int month, int day, int hour, int minute, int second, int fracti
 106        {
 0107            if (year == 0)
 108            {
 0109                value = default;
 0110                return false;
 111            }
 112
 0113            Debug.Assert(year <= 9999); // All of our callers to date parse the year from fixed 4-digit fields so this v
 114
 0115            if ((((uint)month) - 1) >= 12)
 116            {
 0117                value = default;
 0118                return false;
 119            }
 120
 0121            uint dayMinusOne = ((uint)day) - 1;
 0122            if (dayMinusOne >= 28 && dayMinusOne >= DateTime.DaysInMonth(year, month))
 123            {
 0124                value = default;
 0125                return false;
 126            }
 127
 0128            if (((uint)hour) > 23)
 129            {
 0130                value = default;
 0131                return false;
 132            }
 133
 0134            if (((uint)minute) > 59)
 135            {
 0136                value = default;
 0137                return false;
 138            }
 139
 0140            if (((uint)second) > 59)
 141            {
 0142                value = default;
 0143                return false;
 144            }
 145
 0146            Debug.Assert(fraction >= 0 && fraction <= Utf8Constants.MaxDateTimeFraction); // All of our callers to date 
 147
 0148            ReadOnlySpan<int> days = DateTime.IsLeapYear(year) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.Da
 0149            int yearMinusOne = year - 1;
 0150            int totalDays = (yearMinusOne * 365) + (yearMinusOne / 4) - (yearMinusOne / 100) + (yearMinusOne / 400) + da
 0151            long ticks = totalDays * TimeSpan.TicksPerDay;
 0152            int totalSeconds = (hour * 3600) + (minute * 60) + second;
 0153            ticks += totalSeconds * TimeSpan.TicksPerSecond;
 0154            ticks += fraction;
 0155            value = new DateTime(ticks: ticks, kind: kind);
 0156            return true;
 157        }
 158    }
 159}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.O.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;
 5
 6namespace System.Buffers.Text
 7{
 8    public static partial class Utf8Parser
 9    {
 10        //
 11        // Roundtrippable format. One of
 12        //
 13        //   012345678901234567890123456789012
 14        //   ---------------------------------
 15        //   2017-06-12T05:30:45.7680000-07:00
 16        //   2017-06-12T05:30:45.7680000Z           (Z is short for "+00:00" but also distinguishes DateTimeKind.Utc fro
 17        //   2017-06-12T05:30:45.7680000            (interpreted as local time wrt to current time zone)
 18        //
 19        private static bool TryParseDateTimeOffsetO(ReadOnlySpan<byte> source, out DateTimeOffset value, out int bytesCo
 20        {
 021            if (source.Length < 27)
 22            {
 023                value = default;
 024                bytesConsumed = 0;
 025                kind = default;
 026                return false;
 27            }
 28
 29            int year;
 30            {
 031                uint digit1 = source[0] - 48u; // '0'
 032                uint digit2 = source[1] - 48u; // '0'
 033                uint digit3 = source[2] - 48u; // '0'
 034                uint digit4 = source[3] - 48u; // '0'
 35
 036                if (digit1 > 9 || digit2 > 9 || digit3 > 9 || digit4 > 9)
 37                {
 038                    value = default;
 039                    bytesConsumed = 0;
 040                    kind = default;
 041                    return false;
 42                }
 43
 044                year = (int)(digit1 * 1000 + digit2 * 100 + digit3 * 10 + digit4);
 45            }
 46
 047            if (source[4] != Utf8Constants.Hyphen)
 48            {
 049                value = default;
 050                bytesConsumed = 0;
 051                kind = default;
 052                return false;
 53            }
 54
 55            int month;
 56            {
 057                uint digit1 = source[5] - 48u; // '0'
 058                uint digit2 = source[6] - 48u; // '0'
 59
 060                if (digit1 > 9 || digit2 > 9)
 61                {
 062                    value = default;
 063                    bytesConsumed = 0;
 064                    kind = default;
 065                    return false;
 66                }
 67
 068                month = (int)(digit1 * 10 + digit2);
 69            }
 70
 071            if (source[7] != Utf8Constants.Hyphen)
 72            {
 073                value = default;
 074                bytesConsumed = 0;
 075                kind = default;
 076                return false;
 77            }
 78
 79            int day;
 80            {
 081                uint digit1 = source[8] - 48u; // '0'
 082                uint digit2 = source[9] - 48u; // '0'
 83
 084                if (digit1 > 9 || digit2 > 9)
 85                {
 086                    value = default;
 087                    bytesConsumed = 0;
 088                    kind = default;
 089                    return false;
 90                }
 91
 092                day = (int)(digit1 * 10 + digit2);
 93            }
 94
 095            if (source[10] != 'T')
 96            {
 097                value = default;
 098                bytesConsumed = 0;
 099                kind = default;
 0100                return false;
 101            }
 102
 103            int hour;
 104            {
 0105                uint digit1 = source[11] - 48u; // '0'
 0106                uint digit2 = source[12] - 48u; // '0'
 107
 0108                if (digit1 > 9 || digit2 > 9)
 109                {
 0110                    value = default;
 0111                    bytesConsumed = 0;
 0112                    kind = default;
 0113                    return false;
 114                }
 115
 0116                hour = (int)(digit1 * 10 + digit2);
 117            }
 118
 0119            if (source[13] != Utf8Constants.Colon)
 120            {
 0121                value = default;
 0122                bytesConsumed = 0;
 0123                kind = default;
 0124                return false;
 125            }
 126
 127            int minute;
 128            {
 0129                uint digit1 = source[14] - 48u; // '0'
 0130                uint digit2 = source[15] - 48u; // '0'
 131
 0132                if (digit1 > 9 || digit2 > 9)
 133                {
 0134                    value = default;
 0135                    bytesConsumed = 0;
 0136                    kind = default;
 0137                    return false;
 138                }
 139
 0140                minute = (int)(digit1 * 10 + digit2);
 141            }
 142
 0143            if (source[16] != Utf8Constants.Colon)
 144            {
 0145                value = default;
 0146                bytesConsumed = 0;
 0147                kind = default;
 0148                return false;
 149            }
 150
 151            int second;
 152            {
 0153                uint digit1 = source[17] - 48u; // '0'
 0154                uint digit2 = source[18] - 48u; // '0'
 155
 0156                if (digit1 > 9 || digit2 > 9)
 157                {
 0158                    value = default;
 0159                    bytesConsumed = 0;
 0160                    kind = default;
 0161                    return false;
 162                }
 163
 0164                second = (int)(digit1 * 10 + digit2);
 165            }
 166
 0167            if (source[19] != Utf8Constants.Period)
 168            {
 0169                value = default;
 0170                bytesConsumed = 0;
 0171                kind = default;
 0172                return false;
 173            }
 174
 175            int fraction;
 176            {
 0177                uint digit1 = source[20] - 48u; // '0'
 0178                uint digit2 = source[21] - 48u; // '0'
 0179                uint digit3 = source[22] - 48u; // '0'
 0180                uint digit4 = source[23] - 48u; // '0'
 0181                uint digit5 = source[24] - 48u; // '0'
 0182                uint digit6 = source[25] - 48u; // '0'
 0183                uint digit7 = source[26] - 48u; // '0'
 184
 0185                if (digit1 > 9 || digit2 > 9 || digit3 > 9 || digit4 > 9 || digit5 > 9 || digit6 > 9 || digit7 > 9)
 186                {
 0187                    value = default;
 0188                    bytesConsumed = 0;
 0189                    kind = default;
 0190                    return false;
 191                }
 192
 0193                fraction = (int)(digit1 * 1000000 + digit2 * 100000 + digit3 * 10000 + digit4 * 1000 + digit5 * 100 + di
 194            }
 195
 0196            byte offsetChar = (source.Length <= 27) ? default : source[27];
 0197            if (offsetChar != 'Z' && offsetChar != Utf8Constants.Plus && offsetChar != Utf8Constants.Minus)
 198            {
 0199                if (!TryCreateDateTimeOffsetInterpretingDataAsLocalTime(year: year, month: month, day: day, hour: hour, 
 200                {
 0201                    value = default;
 0202                    bytesConsumed = 0;
 0203                    kind = default;
 0204                    return false;
 205                }
 0206                bytesConsumed = 27;
 0207                kind = DateTimeKind.Unspecified;
 0208                return true;
 209            }
 210
 0211            if (offsetChar == 'Z')
 212            {
 213                // Same as specifying an offset of "+00:00", except that DateTime's Kind gets set to UTC rather than Loc
 0214                if (!TryCreateDateTimeOffset(year: year, month: month, day: day, hour: hour, minute: minute, second: sec
 215                {
 0216                    value = default;
 0217                    bytesConsumed = 0;
 0218                    kind = default;
 0219                    return false;
 220                }
 221
 0222                bytesConsumed = 28;
 0223                kind = DateTimeKind.Utc;
 0224                return true;
 225            }
 226
 0227            Debug.Assert(offsetChar == Utf8Constants.Plus || offsetChar == Utf8Constants.Minus);
 0228            if (source.Length < 33)
 229            {
 0230                value = default;
 0231                bytesConsumed = 0;
 0232                kind = default;
 0233                return false;
 234            }
 235
 236            int offsetHours;
 237            {
 0238                uint digit1 = source[28] - 48u; // '0'
 0239                uint digit2 = source[29] - 48u; // '0'
 240
 0241                if (digit1 > 9 || digit2 > 9)
 242                {
 0243                    value = default;
 0244                    bytesConsumed = 0;
 0245                    kind = default;
 0246                    return false;
 247                }
 248
 0249                offsetHours = (int)(digit1 * 10 + digit2);
 250            }
 251
 0252            if (source[30] != Utf8Constants.Colon)
 253            {
 0254                value = default;
 0255                bytesConsumed = 0;
 0256                kind = default;
 0257                return false;
 258            }
 259
 260            int offsetMinutes;
 261            {
 0262                uint digit1 = source[31] - 48u; // '0'
 0263                uint digit2 = source[32] - 48u; // '0'
 264
 0265                if (digit1 > 9 || digit2 > 9)
 266                {
 0267                    value = default;
 0268                    bytesConsumed = 0;
 0269                    kind = default;
 0270                    return false;
 271                }
 272
 0273                offsetMinutes = (int)(digit1 * 10 + digit2);
 274            }
 275
 0276            if (!TryCreateDateTimeOffset(year: year, month: month, day: day, hour: hour, minute: minute, second: second,
 277            {
 0278                value = default;
 0279                bytesConsumed = 0;
 0280                kind = default;
 0281                return false;
 282            }
 283
 0284            bytesConsumed = 33;
 0285            kind = DateTimeKind.Local;
 0286            return true;
 287        }
 288    }
 289}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.R.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        //
 9        // Parse an RFC1123 date string.
 10        //
 11        // 01234567890123456789012345678
 12        // -----------------------------
 13        // Tue, 03 Jan 2017 08:08:05 GMT
 14        //
 15        private static bool TryParseDateTimeOffsetR(ReadOnlySpan<byte> source, uint caseFlipXorMask, out DateTimeOffset 
 16        {
 017            if (source.Length < 29)
 18            {
 019                bytesConsumed = 0;
 020                dateTimeOffset = default;
 021                return false;
 22            }
 23
 24            DayOfWeek dayOfWeek;
 25            {
 026                uint dow0 = source[0] ^ caseFlipXorMask;
 027                uint dow1 = source[1];
 028                uint dow2 = source[2];
 029                uint comma = source[3];
 030                uint dowString = (dow0 << 24) | (dow1 << 16) | (dow2 << 8) | comma;
 31                switch (dowString)
 32                {
 033                    case 0x53756E2c /* 'Sun,' */: dayOfWeek = DayOfWeek.Sunday; break;
 034                    case 0x4d6f6e2c /* 'Mon,' */: dayOfWeek = DayOfWeek.Monday; break;
 035                    case 0x5475652c /* 'Tue,' */: dayOfWeek = DayOfWeek.Tuesday; break;
 036                    case 0x5765642c /* 'Wed,' */: dayOfWeek = DayOfWeek.Wednesday; break;
 037                    case 0x5468752c /* 'Thu,' */: dayOfWeek = DayOfWeek.Thursday; break;
 038                    case 0x4672692c /* 'Fri,' */: dayOfWeek = DayOfWeek.Friday; break;
 039                    case 0x5361742c /* 'Sat,' */: dayOfWeek = DayOfWeek.Saturday; break;
 40                    default:
 041                        bytesConsumed = 0;
 042                        dateTimeOffset = default;
 043                        return false;
 44                }
 45            }
 46
 047            if (source[4] != Utf8Constants.Space)
 48            {
 049                bytesConsumed = 0;
 050                dateTimeOffset = default;
 051                return false;
 52            }
 53
 54            int day;
 55            {
 056                uint digit1 = source[5] - 48u; // '0'
 057                uint digit2 = source[6] - 48u; // '0'
 58
 059                if (digit1 > 9 || digit2 > 9)
 60                {
 061                    bytesConsumed = 0;
 062                    dateTimeOffset = default;
 063                    return false;
 64                }
 65
 066                day = (int)(digit1 * 10 + digit2);
 67            }
 68
 069            if (source[7] != Utf8Constants.Space)
 70            {
 071                bytesConsumed = 0;
 072                dateTimeOffset = default;
 073                return false;
 74            }
 75
 76            int month;
 77            {
 078                uint mon0 = source[8] ^ caseFlipXorMask;
 079                uint mon1 = source[9];
 080                uint mon2 = source[10];
 081                uint space = source[11];
 082                uint monthString = (mon0 << 24) | (mon1 << 16) | (mon2 << 8) | space;
 83                switch (monthString)
 84                {
 085                    case 0x4a616e20: /* 'Jan ' */ month = 1; break;
 086                    case 0x46656220: /* 'Feb ' */ month = 2; break;
 087                    case 0x4d617220: /* 'Mar ' */ month = 3; break;
 088                    case 0x41707220: /* 'Apr ' */ month = 4; break;
 089                    case 0x4d617920: /* 'May ' */ month = 5; break;
 090                    case 0x4a756e20: /* 'Jun ' */ month = 6; break;
 091                    case 0x4a756c20: /* 'Jul ' */ month = 7; break;
 092                    case 0x41756720: /* 'Aug ' */ month = 8; break;
 093                    case 0x53657020: /* 'Sep ' */ month = 9; break;
 094                    case 0x4f637420: /* 'Oct ' */ month = 10; break;
 095                    case 0x4e6f7620: /* 'Nov ' */ month = 11; break;
 096                    case 0x44656320: /* 'Dec ' */ month = 12; break;
 97                    default:
 098                        bytesConsumed = 0;
 099                        dateTimeOffset = default;
 0100                        return false;
 101                }
 102            }
 103
 104            int year;
 105            {
 0106                uint digit1 = source[12] - 48u; // '0'
 0107                uint digit2 = source[13] - 48u; // '0'
 0108                uint digit3 = source[14] - 48u; // '0'
 0109                uint digit4 = source[15] - 48u; // '0'
 110
 0111                if (digit1 > 9 || digit2 > 9 || digit3 > 9 || digit4 > 9)
 112                {
 0113                    bytesConsumed = 0;
 0114                    dateTimeOffset = default;
 0115                    return false;
 116                }
 117
 0118                year = (int)(digit1 * 1000 + digit2 * 100 + digit3 * 10 + digit4);
 119            }
 120
 0121            if (source[16] != Utf8Constants.Space)
 122            {
 0123                bytesConsumed = 0;
 0124                dateTimeOffset = default;
 0125                return false;
 126            }
 127
 128            int hour;
 129            {
 0130                uint digit1 = source[17] - 48u; // '0'
 0131                uint digit2 = source[18] - 48u; // '0'
 132
 0133                if (digit1 > 9 || digit2 > 9)
 134                {
 0135                    bytesConsumed = 0;
 0136                    dateTimeOffset = default;
 0137                    return false;
 138                }
 139
 0140                hour = (int)(digit1 * 10 + digit2);
 141            }
 142
 0143            if (source[19] != Utf8Constants.Colon)
 144            {
 0145                bytesConsumed = 0;
 0146                dateTimeOffset = default;
 0147                return false;
 148            }
 149
 150            int minute;
 151            {
 0152                uint digit1 = source[20] - 48u; // '0'
 0153                uint digit2 = source[21] - 48u; // '0'
 154
 0155                if (digit1 > 9 || digit2 > 9)
 156                {
 0157                    bytesConsumed = 0;
 0158                    dateTimeOffset = default;
 0159                    return false;
 160                }
 161
 0162                minute = (int)(digit1 * 10 + digit2);
 163            }
 164
 0165            if (source[22] != Utf8Constants.Colon)
 166            {
 0167                bytesConsumed = 0;
 0168                dateTimeOffset = default;
 0169                return false;
 170            }
 171
 172            int second;
 173            {
 0174                uint digit1 = source[23] - 48u; // '0'
 0175                uint digit2 = source[24] - 48u; // '0'
 176
 0177                if (digit1 > 9 || digit2 > 9)
 178                {
 0179                    bytesConsumed = 0;
 0180                    dateTimeOffset = default;
 0181                    return false;
 182                }
 183
 0184                second = (int)(digit1 * 10 + digit2);
 185            }
 186
 187            {
 0188                uint space = source[25];
 0189                uint g = source[26] ^ caseFlipXorMask;
 0190                uint m = source[27] ^ caseFlipXorMask;
 0191                uint t = source[28] ^ caseFlipXorMask;
 0192                uint gmtString = (space << 24) | (g << 16) | (m << 8) | t;
 0193                if (gmtString != 0x20474d54 /* ' GMT' */)
 194                {
 0195                    bytesConsumed = 0;
 0196                    dateTimeOffset = default;
 0197                    return false;
 198                }
 199            }
 200
 0201            if (!TryCreateDateTimeOffset(year: year, month: month, day: day, hour: hour, minute: minute, second: second,
 202            {
 0203                bytesConsumed = 0;
 0204                dateTimeOffset = default;
 0205                return false;
 206            }
 207
 0208            if (dayOfWeek != dateTimeOffset.DayOfWeek)
 209            {
 210                // If we got here, the day of week did not match the actual date.
 0211                bytesConsumed = 0;
 0212                dateTimeOffset = default;
 0213                return false;
 214            }
 215
 0216            bytesConsumed = 29;
 0217            return true;
 218        }
 219    }
 220}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Decimal.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        /// <summary>
 9        /// Parses a Decimal at the start of a Utf8 string.
 10        /// </summary>
 11        /// <param name="source">The Utf8 string to parse</param>
 12        /// <param name="value">Receives the parsed value</param>
 13        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 14        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 15        /// <returns>
 16        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 17        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 18        /// </returns>
 19        /// <remarks>
 20        /// Formats supported:
 21        ///     G/g  (default)
 22        ///     F/f             12.45       Fixed point
 23        ///     E/e             1.245000e1  Exponential
 24        /// </remarks>
 25        /// <exceptions>
 26        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 27        /// </exceptions>
 28        public static unsafe bool TryParse(ReadOnlySpan<byte> source, out decimal value, out int bytesConsumed, char sta
 29        {
 30            ParseNumberOptions options;
 31            switch (standardFormat)
 32            {
 33                case default(char):
 34                case 'G':
 35                case 'g':
 36                case 'E':
 37                case 'e':
 038                    options = ParseNumberOptions.AllowExponent;
 039                    break;
 40
 41                case 'F':
 42                case 'f':
 043                    options = default;
 044                    break;
 45
 46                default:
 047                    return ParserHelpers.TryParseThrowFormatException(out value, out bytesConsumed);
 48            }
 49
 050            Number.NumberBuffer number = new Number.NumberBuffer(Number.NumberBufferKind.Decimal, stackalloc byte[Number
 51
 052            if (!TryParseNumber(source, ref number, out bytesConsumed, options, out bool textUsedExponentNotation))
 53            {
 054                value = default;
 055                return false;
 56            }
 57
 058            if ((!textUsedExponentNotation) && (standardFormat == 'E' || standardFormat == 'e'))
 59            {
 060                value = default;
 061                bytesConsumed = 0;
 062                return false;
 63            }
 64
 065            value = default;
 66
 067            if (!Number.TryNumberToDecimal(ref number, ref value))
 68            {
 069                value = default;
 070                bytesConsumed = 0;
 071                return false;
 72            }
 73
 074            return true;
 75        }
 76    }
 77}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Float.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.Binary;
 5
 6namespace System.Buffers.Text
 7{
 8    public static partial class Utf8Parser
 9    {
 10        /// <summary>
 11        /// Parses a Single at the start of a Utf8 string.
 12        /// </summary>
 13        /// <param name="source">The Utf8 string to parse</param>
 14        /// <param name="value">Receives the parsed value</param>
 15        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 16        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 17        /// <returns>
 18        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 19        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 20        /// </returns>
 21        /// <remarks>
 22        /// Formats supported:
 23        ///     G/g  (default)
 24        ///     F/f             12.45       Fixed point
 25        ///     E/e             1.245000e1  Exponential
 26        /// </remarks>
 27        /// <exceptions>
 28        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 29        /// </exceptions>
 30        public static unsafe bool TryParse(ReadOnlySpan<byte> source, out float value, out int bytesConsumed, char stand
 31        {
 032            Number.NumberBuffer number = new Number.NumberBuffer(Number.NumberBufferKind.FloatingPoint, stackalloc byte[
 33
 034            if (TryParseNormalAsFloatingPoint(source, ref number, out bytesConsumed, standardFormat))
 35            {
 036                value = Number.NumberToFloat<float>(ref number);
 037                return true;
 38            }
 39
 040            return TryParseAsSpecialFloatingPoint(source, float.PositiveInfinity, float.NegativeInfinity, float.NaN, out
 41        }
 42
 43        /// <summary>
 44        /// Parses a Double at the start of a Utf8 string.
 45        /// </summary>
 46        /// <param name="source">The Utf8 string to parse</param>
 47        /// <param name="value">Receives the parsed value</param>
 48        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 49        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 50        /// <returns>
 51        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 52        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 53        /// </returns>
 54        /// <remarks>
 55        /// Formats supported:
 56        ///     G/g  (default)
 57        ///     F/f             12.45       Fixed point
 58        ///     E/e             1.245000e1  Exponential
 59        /// </remarks>
 60        /// <exceptions>
 61        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 62        /// </exceptions>
 63        public static unsafe bool TryParse(ReadOnlySpan<byte> source, out double value, out int bytesConsumed, char stan
 64        {
 065            Number.NumberBuffer number = new Number.NumberBuffer(Number.NumberBufferKind.FloatingPoint, stackalloc byte[
 66
 067            if (TryParseNormalAsFloatingPoint(source, ref number, out bytesConsumed, standardFormat))
 68            {
 069                value = Number.NumberToFloat<double>(ref number);
 070                return true;
 71            }
 72
 073            return TryParseAsSpecialFloatingPoint(source, double.PositiveInfinity, double.NegativeInfinity, double.NaN, 
 74        }
 75
 76        //
 77        // Attempt to parse the regular floating points (the ones without names like "Infinity" and "NaN")
 78        //
 79        private static bool TryParseNormalAsFloatingPoint(ReadOnlySpan<byte> source, ref Number.NumberBuffer number, out
 80        {
 81            ParseNumberOptions options;
 82            switch (standardFormat)
 83            {
 84                case default(char):
 85                case 'G':
 86                case 'g':
 87                case 'E':
 88                case 'e':
 089                    options = ParseNumberOptions.AllowExponent;
 090                    break;
 91                case 'F':
 92                case 'f':
 093                    options = default;
 094                    break;
 95                default:
 096                    return ParserHelpers.TryParseThrowFormatException(out bytesConsumed);
 97            }
 098            if (!TryParseNumber(source, ref number, out bytesConsumed, options, out bool textUsedExponentNotation))
 99            {
 0100                return false;
 101            }
 0102            if ((!textUsedExponentNotation) && (standardFormat == 'E' || standardFormat == 'e'))
 103            {
 0104                bytesConsumed = 0;
 0105                return false;
 106            }
 0107            return true;
 108        }
 109
 110        //
 111        // Assuming the text doesn't look like a normal floating point, we attempt to parse it as one the special floati
 112        //
 113        private static bool TryParseAsSpecialFloatingPoint<T>(ReadOnlySpan<byte> source, T positiveInfinity, T negativeI
 114        {
 0115            int srcIndex = 0;
 0116            int remaining = source.Length;
 0117            bool isNegative = false;
 118
 119            // We need at least 4 characters to process a sign
 0120            if (remaining >= 4)
 121            {
 0122                byte c = source[srcIndex];
 123
 124                switch (c)
 125                {
 126                    case Utf8Constants.Minus:
 127                    {
 0128                        isNegative = true;
 129                        goto case Utf8Constants.Plus;
 130                    }
 131
 132                    case Utf8Constants.Plus:
 133                    {
 0134                        srcIndex++;
 0135                        remaining--;
 136                        break;
 137                    }
 138                }
 139            }
 140
 141            // We can efficiently do an ASCII IsLower check by xor'ing with the expected
 142            // result and validating that it returns either 0 or exactly 0x20 (which is the
 143            // delta between lowercase and uppercase ASCII characters).
 144
 0145            if (remaining >= 3)
 146            {
 0147                if ((((source[srcIndex] ^ (byte)('n')) & ~0x20) == 0) &&
 0148                    (((source[srcIndex + 1] ^ (byte)('a')) & ~0x20) == 0) &&
 0149                    (((source[srcIndex + 2] ^ (byte)('n')) & ~0x20) == 0))
 150                {
 0151                    value = nan;
 0152                    bytesConsumed = 3 + srcIndex;
 0153                    return true;
 154                }
 155
 0156                if (remaining >= 8)
 157                {
 158                    const int infi = 0x69666E69;
 0159                    int diff = (BinaryPrimitives.ReadInt32LittleEndian(source.Slice(srcIndex)) ^ infi);
 160
 0161                    if ((diff & ~0x20202020) == 0)
 162                    {
 163                        const int nity = 0x7974696E;
 0164                        diff = (BinaryPrimitives.ReadInt32LittleEndian(source.Slice(srcIndex + 4)) ^ nity);
 165
 0166                        if ((diff & ~0x20202020) == 0)
 167                        {
 0168                            value = isNegative ? negativeInfinity : positiveInfinity;
 0169                            bytesConsumed = 8 + srcIndex;
 0170                            return true;
 171                        }
 172                    }
 173                }
 174            }
 175
 0176            value = default;
 0177            bytesConsumed = 0;
 0178            return false;
 179        }
 180    }
 181}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Guid.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        /// <summary>
 9        /// Parses a Guid at the start of a Utf8 string.
 10        /// </summary>
 11        /// <param name="source">The Utf8 string to parse</param>
 12        /// <param name="value">Receives the parsed value</param>
 13        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 14        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 15        /// <returns>
 16        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 17        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 18        /// </returns>
 19        /// <remarks>
 20        /// Formats supported:
 21        ///     D (default)     nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn
 22        ///     B               {nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn}
 23        ///     P               (nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn)
 24        ///     N               nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
 25        /// </remarks>
 26        /// <exceptions>
 27        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 28        /// </exceptions>
 29        public static bool TryParse(ReadOnlySpan<byte> source, out Guid value, out int bytesConsumed, char standardForma
 30        {
 31        FastPath:
 032            if (standardFormat == default)
 33            {
 034                return TryParseGuidCore(source, out value, out bytesConsumed, ends: 0);
 35            }
 36
 37            switch (standardFormat)
 38            {
 39                case 'D':
 040                    standardFormat = default;
 041                    goto FastPath;
 42                case 'B':
 043                    return TryParseGuidCore(source, out value, out bytesConsumed, ends: '{' | ('}' << 8));
 44                case 'P':
 045                    return TryParseGuidCore(source, out value, out bytesConsumed, ends: '(' | (')' << 8));
 46                case 'N':
 047                    return TryParseGuidN(source, out value, out bytesConsumed);
 48                default:
 049                    return ParserHelpers.TryParseThrowFormatException(source, out value, out bytesConsumed);
 50            }
 51        }
 52
 53        // nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn (not very Guid-like, but the format is what it is...)
 54        private static bool TryParseGuidN(ReadOnlySpan<byte> text, out Guid value, out int bytesConsumed)
 55        {
 056            if (text.Length < 32)
 57            {
 058                value = default;
 059                bytesConsumed = 0;
 060                return false;
 61            }
 62
 063            if (!TryParseUInt32X(text.Slice(0, 8), out uint i1, out int justConsumed) || justConsumed != 8)
 64            {
 065                value = default;
 066                bytesConsumed = 0;
 067                return false; // 8 digits
 68            }
 69
 070            if (!TryParseUInt16X(text.Slice(8, 4), out ushort i2, out justConsumed) || justConsumed != 4)
 71            {
 072                value = default;
 073                bytesConsumed = 0;
 074                return false; // next 4 digits
 75            }
 76
 077            if (!TryParseUInt16X(text.Slice(12, 4), out ushort i3, out justConsumed) || justConsumed != 4)
 78            {
 079                value = default;
 080                bytesConsumed = 0;
 081                return false; // next 4 digits
 82            }
 83
 084            if (!TryParseUInt16X(text.Slice(16, 4), out ushort i4, out justConsumed) || justConsumed != 4)
 85            {
 086                value = default;
 087                bytesConsumed = 0;
 088                return false; // next 4 digits
 89            }
 90
 091            if (!TryParseUInt64X(text.Slice(20), out ulong i5, out justConsumed) || justConsumed != 12)
 92            {
 093                value = default;
 094                bytesConsumed = 0;
 095                return false; // next 4 digits
 96            }
 97
 098            bytesConsumed = 32;
 099            value = new Guid((int)i1, (short)i2, (short)i3, (byte)(i4 >> 8), (byte)i4,
 0100                (byte)(i5 >> 40), (byte)(i5 >> 32), (byte)(i5 >> 24), (byte)(i5 >> 16), (byte)(i5 >> 8), (byte)i5);
 0101            return true;
 102        }
 103
 104        // {8-4-4-4-12}, where number is the number of hex digits, and {/} are ends.
 105        private static bool TryParseGuidCore(ReadOnlySpan<byte> source, out Guid value, out int bytesConsumed, int ends)
 106        {
 0107            int expectedCodingUnits = 36 + ((ends != 0) ? 2 : 0); // 32 hex digits + 4 delimiters + 2 optional ends
 108
 0109            if (source.Length < expectedCodingUnits)
 110            {
 0111                value = default;
 0112                bytesConsumed = 0;
 0113                return false;
 114            }
 115
 116            // The 'ends' parameter is a 16-bit value where the byte denoting the starting
 117            // brace is at byte position 0 and the byte denoting the closing brace is at
 118            // byte position 1. If no braces are expected, has value 0.
 119            // Default: ends = 0
 120            //  Braces: ends = "}{"
 121            //  Parens: ends = ")("
 122
 0123            if (ends != 0)
 124            {
 0125                if (source[0] != (byte)ends)
 126                {
 0127                    value = default;
 0128                    bytesConsumed = 0;
 0129                    return false;
 130                }
 131
 0132                source = source.Slice(1); // skip beginning
 0133                ends >>= 8; // shift the closing brace to byte position 0
 134            }
 135
 0136            if (!TryParseUInt32X(source, out uint i1, out int justConsumed))
 137            {
 0138                value = default;
 0139                bytesConsumed = 0;
 0140                return false;
 141            }
 142
 0143            if (justConsumed != 8)
 144            {
 0145                value = default;
 0146                bytesConsumed = 0;
 0147                return false; // 8 digits
 148            }
 149
 0150            if (source[justConsumed] != '-')
 151            {
 0152                value = default;
 0153                bytesConsumed = 0;
 0154                return false;
 155            }
 156
 0157            source = source.Slice(9); // justConsumed + 1 for delimiter
 158
 0159            if (!TryParseUInt16X(source, out ushort i2, out justConsumed))
 160            {
 0161                value = default;
 0162                bytesConsumed = 0;
 0163                return false;
 164            }
 165
 0166            if (justConsumed != 4)
 167            {
 0168                value = default;
 0169                bytesConsumed = 0;
 0170                return false; // 4 digits
 171            }
 172
 0173            if (source[justConsumed] != '-')
 174            {
 0175                value = default;
 0176                bytesConsumed = 0;
 0177                return false;
 178            }
 179
 0180            source = source.Slice(5); // justConsumed + 1 for delimiter
 181
 0182            if (!TryParseUInt16X(source, out ushort i3, out justConsumed))
 183            {
 0184                value = default;
 0185                bytesConsumed = 0;
 0186                return false;
 187            }
 188
 0189            if (justConsumed != 4)
 190            {
 0191                value = default;
 0192                bytesConsumed = 0;
 0193                return false; // 4 digits
 194            }
 195
 0196            if (source[justConsumed] != '-')
 197            {
 0198                value = default;
 0199                bytesConsumed = 0;
 0200                return false;
 201            }
 202
 0203            source = source.Slice(5); // justConsumed + 1 for delimiter
 204
 0205            if (!TryParseUInt16X(source, out ushort i4, out justConsumed))
 206            {
 0207                value = default;
 0208                bytesConsumed = 0;
 0209                return false;
 210            }
 211
 0212            if (justConsumed != 4)
 213            {
 0214                value = default;
 0215                bytesConsumed = 0;
 0216                return false; // 4 digits
 217            }
 218
 0219            if (source[justConsumed] != '-')
 220            {
 0221                value = default;
 0222                bytesConsumed = 0;
 0223                return false;
 224            }
 225
 0226            source = source.Slice(5); // justConsumed + 1 for delimiter
 227
 0228            if (!TryParseUInt64X(source, out ulong i5, out justConsumed))
 229            {
 0230                value = default;
 0231                bytesConsumed = 0;
 0232                return false;
 233            }
 234
 0235            if (justConsumed != 12)
 236            {
 0237                value = default;
 0238                bytesConsumed = 0;
 0239                return false; // 12 digits
 240            }
 241
 0242            if (ends != 0 && source[justConsumed] != (byte)ends)
 243            {
 0244                value = default;
 0245                bytesConsumed = 0;
 0246                return false;
 247            }
 248
 0249            bytesConsumed = expectedCodingUnits;
 0250            value = new Guid((int)i1, (short)i2, (short)i3, (byte)(i4 >> 8), (byte)i4,
 0251                (byte)(i5 >> 40), (byte)(i5 >> 32), (byte)(i5 >> 24), (byte)(i5 >> 16), (byte)(i5 >> 8), (byte)i5);
 252
 0253            return true;
 254        }
 255    }
 256}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Signed.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.Runtime.CompilerServices;
 5
 6namespace System.Buffers.Text
 7{
 8    /// <summary>
 9    /// Methods to parse common data types to Utf8 strings.
 10    /// </summary>
 11    public static partial class Utf8Parser
 12    {
 13        /// <summary>
 14        /// Parses a SByte at the start of a Utf8 string.
 15        /// </summary>
 16        /// <param name="source">The Utf8 string to parse</param>
 17        /// <param name="value">Receives the parsed value</param>
 18        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 19        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 20        /// <returns>
 21        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 22        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 23        /// </returns>
 24        /// <remarks>
 25        /// Formats supported:
 26        ///     G/g (default)
 27        ///     D/d             32767
 28        ///     N/n             32,767
 29        ///     X/x             7fff
 30        /// </remarks>
 31        /// <exceptions>
 32        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 33        /// </exceptions>
 34        [CLSCompliant(false)]
 35        public static bool TryParse(ReadOnlySpan<byte> source, out sbyte value, out int bytesConsumed, char standardForm
 36        {
 37        FastPath:
 038            if (standardFormat == default)
 39            {
 040                return TryParseSByteD(source, out value, out bytesConsumed);
 41            }
 42
 43            // There's small but measurable overhead when entering the switch block below.
 44            // We optimize for the default case by hoisting it above the switch block.
 45
 046            switch (standardFormat | 0x20) // convert to lowercase
 47            {
 48                case 'g':
 49                case 'd':
 50                case 'r':
 051                    standardFormat = default;
 052                    goto FastPath;
 53
 54                case 'n':
 055                    return TryParseSByteN(source, out value, out bytesConsumed);
 56
 57                case 'x':
 058                    Unsafe.SkipInit(out value); // will be populated by TryParseByteX
 059                    return TryParseByteX(source, out Unsafe.As<sbyte, byte>(ref value), out bytesConsumed);
 60
 61                default:
 062                    return ParserHelpers.TryParseThrowFormatException(source, out value, out bytesConsumed);
 63            }
 64        }
 65
 66        /// <summary>
 67        /// Parses an Int16 at the start of a Utf8 string.
 68        /// </summary>
 69        /// <param name="source">The Utf8 string to parse</param>
 70        /// <param name="value">Receives the parsed value</param>
 71        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 72        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 73        /// <returns>
 74        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 75        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 76        /// </returns>
 77        /// <remarks>
 78        /// Formats supported:
 79        ///     G/g (default)
 80        ///     D/d             32767
 81        ///     N/n             32,767
 82        ///     X/x             7fff
 83        /// </remarks>
 84        /// <exceptions>
 85        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 86        /// </exceptions>
 87        public static bool TryParse(ReadOnlySpan<byte> source, out short value, out int bytesConsumed, char standardForm
 88        {
 89        FastPath:
 090            if (standardFormat == default)
 91            {
 092                return TryParseInt16D(source, out value, out bytesConsumed);
 93            }
 94
 95            // There's small but measurable overhead when entering the switch block below.
 96            // We optimize for the default case by hoisting it above the switch block.
 97
 098            switch (standardFormat | 0x20) // convert to lowercase
 99            {
 100                case 'g':
 101                case 'd':
 102                case 'r':
 0103                    standardFormat = default;
 0104                    goto FastPath;
 105
 106                case 'n':
 0107                    return TryParseInt16N(source, out value, out bytesConsumed);
 108
 109                case 'x':
 0110                    Unsafe.SkipInit(out value); // will be populated by TryParseUInt16X
 0111                    return TryParseUInt16X(source, out Unsafe.As<short, ushort>(ref value), out bytesConsumed);
 112
 113                default:
 0114                    return ParserHelpers.TryParseThrowFormatException(source, out value, out bytesConsumed);
 115            }
 116        }
 117
 118        /// <summary>
 119        /// Parses an Int32 at the start of a Utf8 string.
 120        /// </summary>
 121        /// <param name="source">The Utf8 string to parse</param>
 122        /// <param name="value">Receives the parsed value</param>
 123        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 124        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 125        /// <returns>
 126        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 127        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 128        /// </returns>
 129        /// <remarks>
 130        /// Formats supported:
 131        ///     G/g (default)
 132        ///     D/d             32767
 133        ///     N/n             32,767
 134        ///     X/x             7fff
 135        /// </remarks>
 136        /// <exceptions>
 137        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 138        /// </exceptions>
 139        public static bool TryParse(ReadOnlySpan<byte> source, out int value, out int bytesConsumed, char standardFormat
 140        {
 141        FastPath:
 0142            if (standardFormat == default)
 143            {
 0144                return TryParseInt32D(source, out value, out bytesConsumed);
 145            }
 146
 147            // There's small but measurable overhead when entering the switch block below.
 148            // We optimize for the default case by hoisting it above the switch block.
 149
 0150            switch (standardFormat | 0x20) // convert to lowercase
 151            {
 152                case 'g':
 153                case 'd':
 154                case 'r':
 0155                    standardFormat = default;
 0156                    goto FastPath;
 157
 158                case 'n':
 0159                    return TryParseInt32N(source, out value, out bytesConsumed);
 160
 161                case 'x':
 0162                    Unsafe.SkipInit(out value); // will be populated by TryParseUInt32X
 0163                    return TryParseUInt32X(source, out Unsafe.As<int, uint>(ref value), out bytesConsumed);
 164
 165                default:
 0166                    return ParserHelpers.TryParseThrowFormatException(source, out value, out bytesConsumed);
 167            }
 168        }
 169
 170        /// <summary>
 171        /// Parses an Int64 at the start of a Utf8 string.
 172        /// </summary>
 173        /// <param name="source">The Utf8 string to parse</param>
 174        /// <param name="value">Receives the parsed value</param>
 175        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 176        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 177        /// <returns>
 178        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 179        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 180        /// </returns>
 181        /// <remarks>
 182        /// Formats supported:
 183        ///     G/g (default)
 184        ///     D/d             32767
 185        ///     N/n             32,767
 186        ///     X/x             7fff
 187        /// </remarks>
 188        /// <exceptions>
 189        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 190        /// </exceptions>
 191        public static bool TryParse(ReadOnlySpan<byte> source, out long value, out int bytesConsumed, char standardForma
 192        {
 193        FastPath:
 0194            if (standardFormat == default)
 195            {
 0196                return TryParseInt64D(source, out value, out bytesConsumed);
 197            }
 198
 199            // There's small but measurable overhead when entering the switch block below.
 200            // We optimize for the default case by hoisting it above the switch block.
 201
 0202            switch (standardFormat | 0x20) // convert to lowercase
 203            {
 204                case 'g':
 205                case 'd':
 206                case 'r':
 0207                    standardFormat = default;
 0208                    goto FastPath;
 209
 210                case 'n':
 0211                    return TryParseInt64N(source, out value, out bytesConsumed);
 212
 213                case 'x':
 0214                    Unsafe.SkipInit(out value); // will be populated by TryParseUInt64X
 0215                    return TryParseUInt64X(source, out Unsafe.As<long, ulong>(ref value), out bytesConsumed);
 216
 217                default:
 0218                    return ParserHelpers.TryParseThrowFormatException(source, out value, out bytesConsumed);
 219            }
 220        }
 221    }
 222}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Signed.D.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        private static bool TryParseSByteD(ReadOnlySpan<byte> source, out sbyte value, out int bytesConsumed)
 9        {
 010            if (source.Length < 1)
 11                goto FalseExit;
 12
 013            int sign = 1;
 014            int index = 0;
 015            int num = source[index];
 016            if (num == '-')
 17            {
 018                sign = -1;
 019                index++;
 020                if ((uint)index >= (uint)source.Length)
 21                    goto FalseExit;
 022                num = source[index];
 23            }
 024            else if (num == '+')
 25            {
 026                index++;
 027                if ((uint)index >= (uint)source.Length)
 28                    goto FalseExit;
 029                num = source[index];
 30            }
 31
 032            int answer = 0;
 33
 034            if (ParserHelpers.IsDigit(num))
 35            {
 036                if (num == '0')
 37                {
 38                    do
 39                    {
 040                        index++;
 041                        if ((uint)index >= (uint)source.Length)
 42                            goto Done;
 043                        num = source[index];
 044                    } while (num == '0');
 045                    if (!ParserHelpers.IsDigit(num))
 46                        goto Done;
 47                }
 48
 049                answer = num - '0';
 050                index++;
 51
 052                if ((uint)index >= (uint)source.Length)
 53                    goto Done;
 054                num = source[index];
 055                if (!ParserHelpers.IsDigit(num))
 56                    goto Done;
 057                index++;
 058                answer = 10 * answer + num - '0';
 59
 60                // Potential overflow
 061                if ((uint)index >= (uint)source.Length)
 62                    goto Done;
 063                num = source[index];
 064                if (!ParserHelpers.IsDigit(num))
 65                    goto Done;
 066                index++;
 067                answer = answer * 10 + num - '0';
 68                // if sign < 0, (-1 * sign + 1) / 2 = 1
 69                // else, (-1 * sign + 1) / 2 = 0
 070                if ((uint)answer > (uint)sbyte.MaxValue + (-1 * sign + 1) / 2)
 71                    goto FalseExit; // Overflow
 72
 073                if ((uint)index >= (uint)source.Length)
 74                    goto Done;
 075                if (!ParserHelpers.IsDigit(source[index]))
 76                    goto Done;
 77
 78                // Guaranteed overflow
 79                goto FalseExit;
 80            }
 81
 82        FalseExit:
 083            bytesConsumed = default;
 084            value = default;
 085            return false;
 86
 87        Done:
 088            bytesConsumed = index;
 089            value = (sbyte)(answer * sign);
 090            return true;
 91        }
 92
 93        private static bool TryParseInt16D(ReadOnlySpan<byte> source, out short value, out int bytesConsumed)
 94        {
 095            if (source.Length < 1)
 96                goto FalseExit;
 97
 098            int sign = 1;
 099            int index = 0;
 0100            int num = source[index];
 0101            if (num == '-')
 102            {
 0103                sign = -1;
 0104                index++;
 0105                if ((uint)index >= (uint)source.Length)
 106                    goto FalseExit;
 0107                num = source[index];
 108            }
 0109            else if (num == '+')
 110            {
 0111                index++;
 0112                if ((uint)index >= (uint)source.Length)
 113                    goto FalseExit;
 0114                num = source[index];
 115            }
 116
 0117            int answer = 0;
 118
 0119            if (ParserHelpers.IsDigit(num))
 120            {
 0121                if (num == '0')
 122                {
 123                    do
 124                    {
 0125                        index++;
 0126                        if ((uint)index >= (uint)source.Length)
 127                            goto Done;
 0128                        num = source[index];
 0129                    } while (num == '0');
 0130                    if (!ParserHelpers.IsDigit(num))
 131                        goto Done;
 132                }
 133
 0134                answer = num - '0';
 0135                index++;
 136
 0137                if ((uint)index >= (uint)source.Length)
 138                    goto Done;
 0139                num = source[index];
 0140                if (!ParserHelpers.IsDigit(num))
 141                    goto Done;
 0142                index++;
 0143                answer = 10 * answer + num - '0';
 144
 0145                if ((uint)index >= (uint)source.Length)
 146                    goto Done;
 0147                num = source[index];
 0148                if (!ParserHelpers.IsDigit(num))
 149                    goto Done;
 0150                index++;
 0151                answer = 10 * answer + num - '0';
 152
 0153                if ((uint)index >= (uint)source.Length)
 154                    goto Done;
 0155                num = source[index];
 0156                if (!ParserHelpers.IsDigit(num))
 157                    goto Done;
 0158                index++;
 0159                answer = 10 * answer + num - '0';
 160
 161                // Potential overflow
 0162                if ((uint)index >= (uint)source.Length)
 163                    goto Done;
 0164                num = source[index];
 0165                if (!ParserHelpers.IsDigit(num))
 166                    goto Done;
 0167                index++;
 0168                answer = answer * 10 + num - '0';
 169                // if sign < 0, (-1 * sign + 1) / 2 = 1
 170                // else, (-1 * sign + 1) / 2 = 0
 0171                if ((uint)answer > (uint)short.MaxValue + (-1 * sign + 1) / 2)
 172                    goto FalseExit; // Overflow
 173
 0174                if ((uint)index >= (uint)source.Length)
 175                    goto Done;
 0176                if (!ParserHelpers.IsDigit(source[index]))
 177                    goto Done;
 178
 179                // Guaranteed overflow
 180                goto FalseExit;
 181            }
 182
 183        FalseExit:
 0184            bytesConsumed = default;
 0185            value = default;
 0186            return false;
 187
 188        Done:
 0189            bytesConsumed = index;
 0190            value = (short)(answer * sign);
 0191            return true;
 192        }
 193
 194        private static bool TryParseInt32D(ReadOnlySpan<byte> source, out int value, out int bytesConsumed)
 195        {
 0196            if (source.Length < 1)
 197                goto FalseExit;
 198
 0199            int sign = 1;
 0200            int index = 0;
 0201            int num = source[index];
 0202            if (num == '-')
 203            {
 0204                sign = -1;
 0205                index++;
 0206                if ((uint)index >= (uint)source.Length)
 207                    goto FalseExit;
 0208                num = source[index];
 209            }
 0210            else if (num == '+')
 211            {
 0212                index++;
 0213                if ((uint)index >= (uint)source.Length)
 214                    goto FalseExit;
 0215                num = source[index];
 216            }
 217
 0218            int answer = 0;
 219
 0220            if (ParserHelpers.IsDigit(num))
 221            {
 0222                if (num == '0')
 223                {
 224                    do
 225                    {
 0226                        index++;
 0227                        if ((uint)index >= (uint)source.Length)
 228                            goto Done;
 0229                        num = source[index];
 0230                    } while (num == '0');
 0231                    if (!ParserHelpers.IsDigit(num))
 232                        goto Done;
 233                }
 234
 0235                answer = num - '0';
 0236                index++;
 237
 0238                if ((uint)index >= (uint)source.Length)
 239                    goto Done;
 0240                num = source[index];
 0241                if (!ParserHelpers.IsDigit(num))
 242                    goto Done;
 0243                index++;
 0244                answer = 10 * answer + num - '0';
 245
 0246                if ((uint)index >= (uint)source.Length)
 247                    goto Done;
 0248                num = source[index];
 0249                if (!ParserHelpers.IsDigit(num))
 250                    goto Done;
 0251                index++;
 0252                answer = 10 * answer + num - '0';
 253
 0254                if ((uint)index >= (uint)source.Length)
 255                    goto Done;
 0256                num = source[index];
 0257                if (!ParserHelpers.IsDigit(num))
 258                    goto Done;
 0259                index++;
 0260                answer = 10 * answer + num - '0';
 261
 0262                if ((uint)index >= (uint)source.Length)
 263                    goto Done;
 0264                num = source[index];
 0265                if (!ParserHelpers.IsDigit(num))
 266                    goto Done;
 0267                index++;
 0268                answer = 10 * answer + num - '0';
 269
 0270                if ((uint)index >= (uint)source.Length)
 271                    goto Done;
 0272                num = source[index];
 0273                if (!ParserHelpers.IsDigit(num))
 274                    goto Done;
 0275                index++;
 0276                answer = 10 * answer + num - '0';
 277
 0278                if ((uint)index >= (uint)source.Length)
 279                    goto Done;
 0280                num = source[index];
 0281                if (!ParserHelpers.IsDigit(num))
 282                    goto Done;
 0283                index++;
 0284                answer = 10 * answer + num - '0';
 285
 0286                if ((uint)index >= (uint)source.Length)
 287                    goto Done;
 0288                num = source[index];
 0289                if (!ParserHelpers.IsDigit(num))
 290                    goto Done;
 0291                index++;
 0292                answer = 10 * answer + num - '0';
 293
 0294                if ((uint)index >= (uint)source.Length)
 295                    goto Done;
 0296                num = source[index];
 0297                if (!ParserHelpers.IsDigit(num))
 298                    goto Done;
 0299                index++;
 0300                answer = 10 * answer + num - '0';
 301
 302                // Potential overflow
 0303                if ((uint)index >= (uint)source.Length)
 304                    goto Done;
 0305                num = source[index];
 0306                if (!ParserHelpers.IsDigit(num))
 307                    goto Done;
 0308                index++;
 0309                if (answer > int.MaxValue / 10)
 310                    goto FalseExit; // Overflow
 0311                answer = answer * 10 + num - '0';
 312                // if sign < 0, (-1 * sign + 1) / 2 = 1
 313                // else, (-1 * sign + 1) / 2 = 0
 0314                if ((uint)answer > (uint)int.MaxValue + (-1 * sign + 1) / 2)
 315                    goto FalseExit; // Overflow
 316
 0317                if ((uint)index >= (uint)source.Length)
 318                    goto Done;
 0319                if (!ParserHelpers.IsDigit(source[index]))
 320                    goto Done;
 321
 322                // Guaranteed overflow
 323                goto FalseExit;
 324            }
 325
 326        FalseExit:
 0327            bytesConsumed = default;
 0328            value = default;
 0329            return false;
 330
 331        Done:
 0332            bytesConsumed = index;
 0333            value = answer * sign;
 0334            return true;
 335        }
 336
 337        private static bool TryParseInt64D(ReadOnlySpan<byte> source, out long value, out int bytesConsumed)
 338        {
 0339            long sign = 0; // 0 if the value is positive, -1 if the value is negative
 0340            int idx = 0;
 341
 342            // We use 'nuint' for the firstChar and nextChar data types in this method because
 343            // it gives us a free early zero-extension to 64 bits when running on a 64-bit platform.
 344
 345            nuint firstChar;
 346            while (true)
 347            {
 0348                if ((uint)idx >= (uint)source.Length) { goto FalseExit; }
 0349                firstChar = (uint)source[idx] - '0';
 0350                if ((uint)firstChar <= 9) { break; }
 351
 352                // We saw something that wasn't a digit. If it's a '+' or a '-',
 353                // we'll set the 'sign' value appropriately and resume the "read
 354                // first char" loop from the next index. If this loops more than
 355                // once (idx != 0), it means we saw a sign character followed by
 356                // a non-digit character, which should be considered an error.
 357
 0358                if (idx != 0)
 359                {
 360                    goto FalseExit;
 361                }
 362
 0363                idx++;
 364
 0365                if ((uint)firstChar == unchecked((uint)('-' - '0')))
 366                {
 0367                    sign--; // set to -1
 368                }
 0369                else if ((uint)firstChar != unchecked((uint)('+' - '0')))
 370                {
 0371                    goto FalseExit; // not a digit, not '-', and not '+'; fail
 372                }
 373            }
 374
 0375            ulong parsedValue = firstChar;
 0376            int overflowLength = ParserHelpers.Int64OverflowLength + idx; // +idx to account for any sign char we read
 0377            idx++;
 378
 379            // At this point, we successfully read a single digit character.
 380            // The only failure condition from here on out is integer overflow.
 381
 0382            if (source.Length < overflowLength)
 383            {
 384                // If the input span is short enough such that integer overflow isn't an issue,
 385                // don't bother performing overflow checks. Just keep shifting in new digits
 386                // until we see a non-digit character or until we've exhausted our input buffer.
 387
 0388                while (true)
 389                {
 0390                    if ((uint)idx >= (uint)source.Length) { break; } // EOF
 0391                    nuint nextChar = (uint)source[idx] - '0';
 0392                    if ((uint)nextChar > 9) { break; } // not a digit
 0393                    parsedValue = parsedValue * 10 + nextChar;
 0394                    idx++;
 395                }
 396            }
 397            else
 398            {
 0399                while (true)
 400                {
 0401                    if ((uint)idx >= (uint)source.Length) { break; } // EOF
 0402                    nuint nextChar = (uint)source[idx] - '0';
 0403                    if ((uint)nextChar > 9) { break; } // not a digit
 0404                    idx++;
 405
 406                    // The const below is the smallest unsigned x for which "x * 10 + 9"
 407                    // might overflow long.MaxValue. If the current accumulator is below
 408                    // this const, there's no risk of overflowing.
 409
 410                    const ulong OverflowRisk = 0x0CCC_CCCC_CCCC_CCCCul;
 411
 0412                    if (parsedValue < OverflowRisk)
 413                    {
 0414                        parsedValue = parsedValue * 10 + nextChar;
 0415                        continue;
 416                    }
 417
 418                    // If the current accumulator is exactly equal to the const above,
 419                    // then "accumulator * 10 + 7" is the highest we can go without overflowing
 420                    // long.MaxValue. (If we know the value is negative, we can instead allow
 421                    // +8, since the range of negative numbers is one higher than the range of
 422                    // positive numbers.) This also implies that if the current accumulator
 423                    // is higher than the const above, there's no hope that we'll succeed,
 424                    // so we may as well just fail now.
 425                    //
 426                    // The (nextChar + sign) trick below works because sign is 0 or -1,
 427                    // so if sign is -1 then this actually checks that nextChar > 8.
 428                    // n.b. signed arithmetic below because nextChar may be 0.
 429
 0430                    if (parsedValue != OverflowRisk || (int)nextChar + (int)sign > 7)
 431                    {
 432                        goto FalseExit;
 433                    }
 434
 0435                    parsedValue = OverflowRisk * 10 + nextChar;
 436                }
 437            }
 438
 439            // 'sign' is 0 for non-negative and -1 for negative. This allows us to perform
 440            // cheap arithmetic + bitwise operations to mimic a multiplication by 1 or -1
 441            // without incurring the cost of an actual multiplication operation.
 442            //
 443            // If sign = 0,  this becomes value = (parsedValue ^  0) -   0  = parsedValue
 444            // If sign = -1, this becomes value = (parsedValue ^ -1) - (-1) = ~parsedValue + 1 = -parsedValue
 445
 0446            bytesConsumed = idx;
 0447            value = ((long)parsedValue ^ sign) - sign;
 0448            return true;
 449
 450        FalseExit:
 0451            bytesConsumed = 0;
 0452            value = default;
 0453            return false;
 454        }
 455    }
 456}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Signed.N.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        private static bool TryParseSByteN(ReadOnlySpan<byte> source, out sbyte value, out int bytesConsumed)
 9        {
 010            if (source.Length < 1)
 11                goto FalseExit;
 12
 013            int sign = 1;
 014            int index = 0;
 015            int c = source[index];
 016            if (c == '-')
 17            {
 018                sign = -1;
 019                index++;
 020                if ((uint)index >= (uint)source.Length)
 21                    goto FalseExit;
 022                c = source[index];
 23            }
 024            else if (c == '+')
 25            {
 026                index++;
 027                if ((uint)index >= (uint)source.Length)
 28                    goto FalseExit;
 029                c = source[index];
 30            }
 31
 32            int answer;
 33
 34            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 35            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 36            // one digit after the decimal point.)
 037            if (c == Utf8Constants.Period)
 38                goto FractionalPartWithoutLeadingDigits;
 039            if (!ParserHelpers.IsDigit(c))
 40                goto FalseExit;
 041            answer = c - '0';
 42
 43            while (true)
 44            {
 045                index++;
 046                if ((uint)index >= (uint)source.Length)
 47                    goto Done;
 48
 049                c = source[index];
 050                if (c == Utf8Constants.Comma)
 51                    continue;
 52
 053                if (c == Utf8Constants.Period)
 54                    goto FractionalDigits;
 55
 056                if (!ParserHelpers.IsDigit(c))
 57                    goto Done;
 58
 059                answer = answer * 10 + c - '0';
 60
 61                // if sign < 0, (-1 * sign + 1) / 2 = 1
 62                // else, (-1 * sign + 1) / 2 = 0
 063                if (answer > sbyte.MaxValue + (-1 * sign + 1) / 2)
 064                    goto FalseExit; // Overflow
 65            }
 66
 67        FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This
 068            answer = 0;
 069            index++;
 070            if ((uint)index >= (uint)source.Length)
 71                goto FalseExit;
 072            if (source[index] != '0')
 73                goto FalseExit;
 74
 75        FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post
 76            do
 77            {
 078                index++;
 079                if ((uint)index >= (uint)source.Length)
 80                    goto Done;
 081                c = source[index];
 82            }
 083            while (c == '0');
 84
 085            if (ParserHelpers.IsDigit(c))
 86                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 87            goto Done;
 88
 89        FalseExit:
 090            bytesConsumed = default;
 091            value = default;
 092            return false;
 93
 94        Done:
 095            bytesConsumed = index;
 096            value = (sbyte)(answer * sign);
 097            return true;
 98        }
 99
 100        private static bool TryParseInt16N(ReadOnlySpan<byte> source, out short value, out int bytesConsumed)
 101        {
 0102            if (source.Length < 1)
 103                goto FalseExit;
 104
 0105            int sign = 1;
 0106            int index = 0;
 0107            int c = source[index];
 0108            if (c == '-')
 109            {
 0110                sign = -1;
 0111                index++;
 0112                if ((uint)index >= (uint)source.Length)
 113                    goto FalseExit;
 0114                c = source[index];
 115            }
 0116            else if (c == '+')
 117            {
 0118                index++;
 0119                if ((uint)index >= (uint)source.Length)
 120                    goto FalseExit;
 0121                c = source[index];
 122            }
 123
 124            int answer;
 125
 126            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 127            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 128            // one digit after the decimal point.)
 0129            if (c == Utf8Constants.Period)
 130                goto FractionalPartWithoutLeadingDigits;
 0131            if (!ParserHelpers.IsDigit(c))
 132                goto FalseExit;
 0133            answer = c - '0';
 134
 135            while (true)
 136            {
 0137                index++;
 0138                if ((uint)index >= (uint)source.Length)
 139                    goto Done;
 140
 0141                c = source[index];
 0142                if (c == Utf8Constants.Comma)
 143                    continue;
 144
 0145                if (c == Utf8Constants.Period)
 146                    goto FractionalDigits;
 147
 0148                if (!ParserHelpers.IsDigit(c))
 149                    goto Done;
 150
 0151                answer = answer * 10 + c - '0';
 152
 153                // if sign < 0, (-1 * sign + 1) / 2 = 1
 154                // else, (-1 * sign + 1) / 2 = 0
 0155                if (answer > short.MaxValue + (-1 * sign + 1) / 2)
 0156                    goto FalseExit; // Overflow
 157            }
 158
 159        FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This
 0160            answer = 0;
 0161            index++;
 0162            if ((uint)index >= (uint)source.Length)
 163                goto FalseExit;
 0164            if (source[index] != '0')
 165                goto FalseExit;
 166
 167        FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post
 168            do
 169            {
 0170                index++;
 0171                if ((uint)index >= (uint)source.Length)
 172                    goto Done;
 0173                c = source[index];
 174            }
 0175            while (c == '0');
 176
 0177            if (ParserHelpers.IsDigit(c))
 178                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 179            goto Done;
 180
 181        FalseExit:
 0182            bytesConsumed = default;
 0183            value = default;
 0184            return false;
 185
 186        Done:
 0187            bytesConsumed = index;
 0188            value = (short)(answer * sign);
 0189            return true;
 190        }
 191
 192        private static bool TryParseInt32N(ReadOnlySpan<byte> source, out int value, out int bytesConsumed)
 193        {
 0194            if (source.Length < 1)
 195                goto FalseExit;
 196
 0197            int sign = 1;
 0198            int index = 0;
 0199            int c = source[index];
 0200            if (c == '-')
 201            {
 0202                sign = -1;
 0203                index++;
 0204                if ((uint)index >= (uint)source.Length)
 205                    goto FalseExit;
 0206                c = source[index];
 207            }
 0208            else if (c == '+')
 209            {
 0210                index++;
 0211                if ((uint)index >= (uint)source.Length)
 212                    goto FalseExit;
 0213                c = source[index];
 214            }
 215
 216            int answer;
 217
 218            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 219            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 220            // one digit after the decimal point.)
 0221            if (c == Utf8Constants.Period)
 222                goto FractionalPartWithoutLeadingDigits;
 0223            if (!ParserHelpers.IsDigit(c))
 224                goto FalseExit;
 0225            answer = c - '0';
 226
 227            while (true)
 228            {
 0229                index++;
 0230                if ((uint)index >= (uint)source.Length)
 231                    goto Done;
 232
 0233                c = source[index];
 0234                if (c == Utf8Constants.Comma)
 235                    continue;
 236
 0237                if (c == Utf8Constants.Period)
 238                    goto FractionalDigits;
 239
 0240                if (!ParserHelpers.IsDigit(c))
 241                    goto Done;
 242
 0243                if (((uint)answer) > int.MaxValue / 10)
 244                    goto FalseExit;
 245
 0246                answer = answer * 10 + c - '0';
 247
 248                // if sign < 0, (-1 * sign + 1) / 2 = 1
 249                // else, (-1 * sign + 1) / 2 = 0
 0250                if ((uint)answer > (uint)int.MaxValue + (-1 * sign + 1) / 2)
 0251                    goto FalseExit; // Overflow
 252            }
 253
 254        FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This
 0255            answer = 0;
 0256            index++;
 0257            if ((uint)index >= (uint)source.Length)
 258                goto FalseExit;
 0259            if (source[index] != '0')
 260                goto FalseExit;
 261
 262        FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post
 263            do
 264            {
 0265                index++;
 0266                if ((uint)index >= (uint)source.Length)
 267                    goto Done;
 0268                c = source[index];
 269            }
 0270            while (c == '0');
 271
 0272            if (ParserHelpers.IsDigit(c))
 273                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 274            goto Done;
 275
 276        FalseExit:
 0277            bytesConsumed = default;
 0278            value = default;
 0279            return false;
 280
 281        Done:
 0282            bytesConsumed = index;
 0283            value = answer * sign;
 0284            return true;
 285        }
 286
 287        private static bool TryParseInt64N(ReadOnlySpan<byte> source, out long value, out int bytesConsumed)
 288        {
 0289            if (source.Length < 1)
 290                goto FalseExit;
 291
 0292            int sign = 1;
 0293            int index = 0;
 0294            int c = source[index];
 0295            if (c == '-')
 296            {
 0297                sign = -1;
 0298                index++;
 0299                if ((uint)index >= (uint)source.Length)
 300                    goto FalseExit;
 0301                c = source[index];
 302            }
 0303            else if (c == '+')
 304            {
 0305                index++;
 0306                if ((uint)index >= (uint)source.Length)
 307                    goto FalseExit;
 0308                c = source[index];
 309            }
 310
 311            long answer;
 312
 313            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 314            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 315            // one digit after the decimal point.)
 0316            if (c == Utf8Constants.Period)
 317                goto FractionalPartWithoutLeadingDigits;
 0318            if (!ParserHelpers.IsDigit(c))
 319                goto FalseExit;
 0320            answer = c - '0';
 321
 322            while (true)
 323            {
 0324                index++;
 0325                if ((uint)index >= (uint)source.Length)
 326                    goto Done;
 327
 0328                c = source[index];
 0329                if (c == Utf8Constants.Comma)
 330                    continue;
 331
 0332                if (c == Utf8Constants.Period)
 333                    goto FractionalDigits;
 334
 0335                if (!ParserHelpers.IsDigit(c))
 336                    goto Done;
 337
 0338                if (((ulong)answer) > long.MaxValue / 10)
 339                    goto FalseExit;
 340
 0341                answer = answer * 10 + c - '0';
 342
 343                // if sign < 0, (-1 * sign + 1) / 2 = 1
 344                // else, (-1 * sign + 1) / 2 = 0
 0345                if ((ulong)answer > (ulong)(long.MaxValue + (-1 * sign + 1) / 2))
 0346                    goto FalseExit; // Overflow
 347            }
 348
 349        FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This
 0350            answer = 0;
 0351            index++;
 0352            if ((uint)index >= (uint)source.Length)
 353                goto FalseExit;
 0354            if (source[index] != '0')
 355                goto FalseExit;
 356
 357        FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post
 358            do
 359            {
 0360                index++;
 0361                if ((uint)index >= (uint)source.Length)
 362                    goto Done;
 0363                c = source[index];
 364            }
 0365            while (c == '0');
 366
 0367            if (ParserHelpers.IsDigit(c))
 368                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 369            goto Done;
 370
 371        FalseExit:
 0372            bytesConsumed = default;
 0373            value = default;
 0374            return false;
 375
 376        Done:
 0377            bytesConsumed = index;
 0378            value = answer * sign;
 0379            return true;
 380        }
 381    }
 382}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        /// <summary>
 9        /// Parses a Byte at the start of a Utf8 string.
 10        /// </summary>
 11        /// <param name="source">The Utf8 string to parse</param>
 12        /// <param name="value">Receives the parsed value</param>
 13        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 14        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 15        /// <returns>
 16        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 17        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 18        /// </returns>
 19        /// <remarks>
 20        /// Formats supported:
 21        ///     G/g (default)
 22        ///     D/d             32767
 23        ///     N/n             32,767
 24        ///     X/x             7fff
 25        /// </remarks>
 26        /// <exceptions>
 27        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 28        /// </exceptions>
 29        public static bool TryParse(ReadOnlySpan<byte> source, out byte value, out int bytesConsumed, char standardForma
 30        {
 31        FastPath:
 032            if (standardFormat == default)
 33            {
 034                return TryParseByteD(source, out value, out bytesConsumed);
 35            }
 36
 37            // There's small but measurable overhead when entering the switch block below.
 38            // We optimize for the default case by hoisting it above the switch block.
 39
 040            switch (standardFormat | 0x20) // convert to lowercase
 41            {
 42                case 'g':
 43                case 'd':
 44                case 'r':
 045                    standardFormat = default;
 046                    goto FastPath;
 47
 48                case 'n':
 049                    return TryParseByteN(source, out value, out bytesConsumed);
 50
 51                case 'x':
 052                    return TryParseByteX(source, out value, out bytesConsumed);
 53
 54                default:
 055                    return ParserHelpers.TryParseThrowFormatException(source, out value, out bytesConsumed);
 56            }
 57        }
 58
 59        /// <summary>
 60        /// Parses a UInt16 at the start of a Utf8 string.
 61        /// </summary>
 62        /// <param name="source">The Utf8 string to parse</param>
 63        /// <param name="value">Receives the parsed value</param>
 64        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 65        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 66        /// <returns>
 67        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 68        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 69        /// </returns>
 70        /// <remarks>
 71        /// Formats supported:
 72        ///     G/g (default)
 73        ///     D/d             32767
 74        ///     N/n             32,767
 75        ///     X/x             7fff
 76        /// </remarks>
 77        /// <exceptions>
 78        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 79        /// </exceptions>
 80        [CLSCompliant(false)]
 81        public static bool TryParse(ReadOnlySpan<byte> source, out ushort value, out int bytesConsumed, char standardFor
 82        {
 83        FastPath:
 084            if (standardFormat == default)
 85            {
 086                return TryParseUInt16D(source, out value, out bytesConsumed);
 87            }
 88
 89            // There's small but measurable overhead when entering the switch block below.
 90            // We optimize for the default case by hoisting it above the switch block.
 91
 092            switch (standardFormat | 0x20) // convert to lowercase
 93            {
 94                case 'g':
 95                case 'd':
 96                case 'r':
 097                    standardFormat = default;
 098                    goto FastPath;
 99
 100                case 'n':
 0101                    return TryParseUInt16N(source, out value, out bytesConsumed);
 102
 103                case 'x':
 0104                    return TryParseUInt16X(source, out value, out bytesConsumed);
 105
 106                default:
 0107                    return ParserHelpers.TryParseThrowFormatException(source, out value, out bytesConsumed);
 108            }
 109        }
 110
 111        /// <summary>
 112        /// Parses a UInt32 at the start of a Utf8 string.
 113        /// </summary>
 114        /// <param name="source">The Utf8 string to parse</param>
 115        /// <param name="value">Receives the parsed value</param>
 116        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 117        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 118        /// <returns>
 119        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 120        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 121        /// </returns>
 122        /// <remarks>
 123        /// Formats supported:
 124        ///     G/g (default)
 125        ///     D/d             32767
 126        ///     N/n             32,767
 127        ///     X/x             7fff
 128        /// </remarks>
 129        /// <exceptions>
 130        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 131        /// </exceptions>
 132        [CLSCompliant(false)]
 133        public static bool TryParse(ReadOnlySpan<byte> source, out uint value, out int bytesConsumed, char standardForma
 134        {
 135        FastPath:
 0136            if (standardFormat == default)
 137            {
 0138                return TryParseUInt32D(source, out value, out bytesConsumed);
 139            }
 140
 141            // There's small but measurable overhead when entering the switch block below.
 142            // We optimize for the default case by hoisting it above the switch block.
 143
 0144            switch (standardFormat | 0x20) // convert to lowercase
 145            {
 146                case 'g':
 147                case 'd':
 148                case 'r':
 0149                    standardFormat = default;
 0150                    goto FastPath;
 151
 152                case 'n':
 0153                    return TryParseUInt32N(source, out value, out bytesConsumed);
 154
 155                case 'x':
 0156                    return TryParseUInt32X(source, out value, out bytesConsumed);
 157
 158                default:
 0159                    return ParserHelpers.TryParseThrowFormatException(source, out value, out bytesConsumed);
 160            }
 161        }
 162
 163        /// <summary>
 164        /// Parses a UInt64 at the start of a Utf8 string.
 165        /// </summary>
 166        /// <param name="source">The Utf8 string to parse</param>
 167        /// <param name="value">Receives the parsed value</param>
 168        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 169        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 170        /// <returns>
 171        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 172        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 173        /// </returns>
 174        /// <remarks>
 175        /// Formats supported:
 176        ///     G/g (default)
 177        ///     D/d             32767
 178        ///     N/n             32,767
 179        ///     X/x             7fff
 180        /// </remarks>
 181        /// <exceptions>
 182        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 183        /// </exceptions>
 184        [CLSCompliant(false)]
 185        public static bool TryParse(ReadOnlySpan<byte> source, out ulong value, out int bytesConsumed, char standardForm
 186        {
 187        FastPath:
 0188            if (standardFormat == default)
 189            {
 0190                return TryParseUInt64D(source, out value, out bytesConsumed);
 191            }
 192
 193            // There's small but measurable overhead when entering the switch block below.
 194            // We optimize for the default case by hoisting it above the switch block.
 195
 0196            switch (standardFormat | 0x20) // convert to lowercase
 197            {
 198                case 'g':
 199                case 'd':
 200                case 'r':
 0201                    standardFormat = default;
 0202                    goto FastPath;
 203
 204                case 'n':
 0205                    return TryParseUInt64N(source, out value, out bytesConsumed);
 206
 207                case 'x':
 0208                    return TryParseUInt64X(source, out value, out bytesConsumed);
 209
 210                default:
 0211                    return ParserHelpers.TryParseThrowFormatException(source, out value, out bytesConsumed);
 212            }
 213        }
 214    }
 215}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.D.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        private static bool TryParseByteD(ReadOnlySpan<byte> source, out byte value, out int bytesConsumed)
 9        {
 010            if (source.Length < 1)
 11                goto FalseExit;
 12
 013            int index = 0;
 014            int num = source[index];
 015            int answer = 0;
 16
 017            if (ParserHelpers.IsDigit(num))
 18            {
 019                if (num == '0')
 20                {
 21                    do
 22                    {
 023                        index++;
 024                        if ((uint)index >= (uint)source.Length)
 25                            goto Done;
 026                        num = source[index];
 027                    } while (num == '0');
 028                    if (!ParserHelpers.IsDigit(num))
 29                        goto Done;
 30                }
 31
 032                answer = num - '0';
 033                index++;
 34
 035                if ((uint)index >= (uint)source.Length)
 36                    goto Done;
 037                num = source[index];
 038                if (!ParserHelpers.IsDigit(num))
 39                    goto Done;
 040                index++;
 041                answer = 10 * answer + num - '0';
 42
 43                // Potential overflow
 044                if ((uint)index >= (uint)source.Length)
 45                    goto Done;
 046                num = source[index];
 047                if (!ParserHelpers.IsDigit(num))
 48                    goto Done;
 049                index++;
 050                answer = answer * 10 + num - '0';
 051                if ((uint)answer > byte.MaxValue)
 52                    goto FalseExit; // Overflow
 53
 054                if ((uint)index >= (uint)source.Length)
 55                    goto Done;
 056                if (!ParserHelpers.IsDigit(source[index]))
 57                    goto Done;
 58
 59                // Guaranteed overflow
 60                goto FalseExit;
 61            }
 62
 63        FalseExit:
 064            bytesConsumed = default;
 065            value = default;
 066            return false;
 67
 68        Done:
 069            bytesConsumed = index;
 070            value = (byte)answer;
 071            return true;
 72        }
 73
 74        private static bool TryParseUInt16D(ReadOnlySpan<byte> source, out ushort value, out int bytesConsumed)
 75        {
 076            if (source.Length < 1)
 77                goto FalseExit;
 78
 079            int index = 0;
 080            int num = source[index];
 081            int answer = 0;
 82
 083            if (ParserHelpers.IsDigit(num))
 84            {
 085                if (num == '0')
 86                {
 87                    do
 88                    {
 089                        index++;
 090                        if ((uint)index >= (uint)source.Length)
 91                            goto Done;
 092                        num = source[index];
 093                    } while (num == '0');
 094                    if (!ParserHelpers.IsDigit(num))
 95                        goto Done;
 96                }
 97
 098                answer = num - '0';
 099                index++;
 100
 0101                if ((uint)index >= (uint)source.Length)
 102                    goto Done;
 0103                num = source[index];
 0104                if (!ParserHelpers.IsDigit(num))
 105                    goto Done;
 0106                index++;
 0107                answer = 10 * answer + num - '0';
 108
 0109                if ((uint)index >= (uint)source.Length)
 110                    goto Done;
 0111                num = source[index];
 0112                if (!ParserHelpers.IsDigit(num))
 113                    goto Done;
 0114                index++;
 0115                answer = 10 * answer + num - '0';
 116
 0117                if ((uint)index >= (uint)source.Length)
 118                    goto Done;
 0119                num = source[index];
 0120                if (!ParserHelpers.IsDigit(num))
 121                    goto Done;
 0122                index++;
 0123                answer = 10 * answer + num - '0';
 124
 125                // Potential overflow
 0126                if ((uint)index >= (uint)source.Length)
 127                    goto Done;
 0128                num = source[index];
 0129                if (!ParserHelpers.IsDigit(num))
 130                    goto Done;
 0131                index++;
 0132                answer = answer * 10 + num - '0';
 0133                if ((uint)answer > ushort.MaxValue)
 134                    goto FalseExit; // Overflow
 135
 0136                if ((uint)index >= (uint)source.Length)
 137                    goto Done;
 0138                if (!ParserHelpers.IsDigit(source[index]))
 139                    goto Done;
 140
 141                // Guaranteed overflow
 142                goto FalseExit;
 143            }
 144
 145        FalseExit:
 0146            bytesConsumed = default;
 0147            value = default;
 0148            return false;
 149
 150        Done:
 0151            bytesConsumed = index;
 0152            value = (ushort)answer;
 0153            return true;
 154        }
 155
 156        private static bool TryParseUInt32D(ReadOnlySpan<byte> source, out uint value, out int bytesConsumed)
 157        {
 0158            if (source.Length < 1)
 159                goto FalseExit;
 160
 0161            int index = 0;
 0162            int num = source[index];
 0163            int answer = 0;
 164
 0165            if (ParserHelpers.IsDigit(num))
 166            {
 0167                if (num == '0')
 168                {
 169                    do
 170                    {
 0171                        index++;
 0172                        if ((uint)index >= (uint)source.Length)
 173                            goto Done;
 0174                        num = source[index];
 0175                    } while (num == '0');
 0176                    if (!ParserHelpers.IsDigit(num))
 177                        goto Done;
 178                }
 179
 0180                answer = num - '0';
 0181                index++;
 182
 0183                if ((uint)index >= (uint)source.Length)
 184                    goto Done;
 0185                num = source[index];
 0186                if (!ParserHelpers.IsDigit(num))
 187                    goto Done;
 0188                index++;
 0189                answer = 10 * answer + num - '0';
 190
 0191                if ((uint)index >= (uint)source.Length)
 192                    goto Done;
 0193                num = source[index];
 0194                if (!ParserHelpers.IsDigit(num))
 195                    goto Done;
 0196                index++;
 0197                answer = 10 * answer + num - '0';
 198
 0199                if ((uint)index >= (uint)source.Length)
 200                    goto Done;
 0201                num = source[index];
 0202                if (!ParserHelpers.IsDigit(num))
 203                    goto Done;
 0204                index++;
 0205                answer = 10 * answer + num - '0';
 206
 0207                if ((uint)index >= (uint)source.Length)
 208                    goto Done;
 0209                num = source[index];
 0210                if (!ParserHelpers.IsDigit(num))
 211                    goto Done;
 0212                index++;
 0213                answer = 10 * answer + num - '0';
 214
 0215                if ((uint)index >= (uint)source.Length)
 216                    goto Done;
 0217                num = source[index];
 0218                if (!ParserHelpers.IsDigit(num))
 219                    goto Done;
 0220                index++;
 0221                answer = 10 * answer + num - '0';
 222
 0223                if ((uint)index >= (uint)source.Length)
 224                    goto Done;
 0225                num = source[index];
 0226                if (!ParserHelpers.IsDigit(num))
 227                    goto Done;
 0228                index++;
 0229                answer = 10 * answer + num - '0';
 230
 0231                if ((uint)index >= (uint)source.Length)
 232                    goto Done;
 0233                num = source[index];
 0234                if (!ParserHelpers.IsDigit(num))
 235                    goto Done;
 0236                index++;
 0237                answer = 10 * answer + num - '0';
 238
 0239                if ((uint)index >= (uint)source.Length)
 240                    goto Done;
 0241                num = source[index];
 0242                if (!ParserHelpers.IsDigit(num))
 243                    goto Done;
 0244                index++;
 0245                answer = 10 * answer + num - '0';
 246
 247                // Potential overflow
 0248                if ((uint)index >= (uint)source.Length)
 249                    goto Done;
 0250                num = source[index];
 0251                if (!ParserHelpers.IsDigit(num))
 252                    goto Done;
 0253                index++;
 0254                if (((uint)answer) > uint.MaxValue / 10 || (((uint)answer) == uint.MaxValue / 10 && num > '5'))
 255                    goto FalseExit; // Overflow
 0256                answer = answer * 10 + num - '0';
 257
 0258                if ((uint)index >= (uint)source.Length)
 259                    goto Done;
 0260                if (!ParserHelpers.IsDigit(source[index]))
 261                    goto Done;
 262
 263                // Guaranteed overflow
 264                goto FalseExit;
 265            }
 266
 267        FalseExit:
 0268            bytesConsumed = default;
 0269            value = default;
 0270            return false;
 271
 272        Done:
 0273            bytesConsumed = index;
 0274            value = (uint)answer;
 0275            return true;
 276        }
 277
 278        private static bool TryParseUInt64D(ReadOnlySpan<byte> source, out ulong value, out int bytesConsumed)
 279        {
 0280            if (source.IsEmpty)
 281            {
 282                goto FalseExit;
 283            }
 284
 285            // We use 'nuint' for the firstDigit and nextChar data types in this method because
 286            // it gives us a free early zero-extension to 64 bits when running on a 64-bit platform.
 287            //
 288            // Parse the first digit separately. If invalid here, we need to return false.
 289
 0290            nuint firstDigit = (uint)source[0] - '0';
 0291            if ((uint)firstDigit > 9) { goto FalseExit; }
 0292            ulong parsedValue = firstDigit;
 293
 294            // At this point, we successfully read a single digit character.
 295            // The only failure condition from here on out is integer overflow.
 296
 0297            int idx = 1;
 0298            if (source.Length < ParserHelpers.UInt64OverflowLength)
 299            {
 300                // If the input span is short enough such that integer overflow isn't an issue,
 301                // don't bother performing overflow checks. Just keep shifting in new digits
 302                // until we see a non-digit character or until we've exhausted our input buffer.
 303
 0304                while (true)
 305                {
 0306                    if ((uint)idx >= (uint)source.Length) { break; } // EOF
 0307                    nuint nextChar = (uint)source[idx] - '0';
 0308                    if ((uint)nextChar > 9) { break; } // not a digit
 0309                    parsedValue = parsedValue * 10 + nextChar;
 0310                    idx++;
 311                }
 312            }
 313            else
 314            {
 0315                while (true)
 316                {
 0317                    if ((uint)idx >= (uint)source.Length) { break; } // EOF
 0318                    nuint nextChar = (uint)source[idx] - '0';
 0319                    if ((uint)nextChar > 9) { break; } // not a digit
 0320                    idx++;
 321
 322                    // The const below is the smallest unsigned x for which "x * 10 + 9"
 323                    // might overflow ulong.MaxValue. If the current accumulator is below
 324                    // this const, there's no risk of overflowing.
 325
 326                    const ulong OverflowRisk = 0x1999_9999_9999_9999ul;
 327
 0328                    if (parsedValue < OverflowRisk)
 329                    {
 0330                        parsedValue = parsedValue * 10 + nextChar;
 0331                        continue;
 332                    }
 333
 334                    // If the current accumulator is exactly equal to the const above,
 335                    // then "accumulator * 10 + 5" is the highest we can go without overflowing
 336                    // ulong.MaxValue. This also implies that if the current accumulator
 337                    // is higher than the const above, there's no hope that we'll succeed,
 338                    // so we may as well just fail now.
 339
 0340                    if (parsedValue != OverflowRisk || (uint)nextChar > 5)
 341                    {
 342                        goto FalseExit;
 343                    }
 344
 0345                    parsedValue = OverflowRisk * 10 + nextChar;
 346                }
 347            }
 348
 0349            bytesConsumed = idx;
 0350            value = parsedValue;
 0351            return true;
 352
 353        FalseExit:
 0354            bytesConsumed = 0;
 0355            value = default;
 0356            return false;
 357        }
 358    }
 359}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.N.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.Buffers.Text
 5{
 6    //
 7    // Parsing unsigned integers for the 'N' format. Emulating int.TryParse(NumberStyles.AllowThousands | NumberStyles.I
 8    //
 9    public static partial class Utf8Parser
 10    {
 11        private static bool TryParseByteN(ReadOnlySpan<byte> source, out byte value, out int bytesConsumed)
 12        {
 013            if (source.Length < 1)
 14                goto FalseExit;
 15
 016            int index = 0;
 017            int c = source[index];
 018            if (c == '+')
 19            {
 020                index++;
 021                if ((uint)index >= (uint)source.Length)
 22                    goto FalseExit;
 023                c = source[index];
 24            }
 25
 26            int answer;
 27
 28            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 29            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 30            // one digit after the decimal point.)
 031            if (c == Utf8Constants.Period)
 32                goto FractionalPartWithoutLeadingDigits;
 033            if (!ParserHelpers.IsDigit(c))
 34                goto FalseExit;
 035            answer = c - '0';
 36
 37            while (true)
 38            {
 039                index++;
 040                if ((uint)index >= (uint)source.Length)
 41                    goto Done;
 42
 043                c = source[index];
 044                if (c == Utf8Constants.Comma)
 45                    continue;
 46
 047                if (c == Utf8Constants.Period)
 48                    goto FractionalDigits;
 49
 050                if (!ParserHelpers.IsDigit(c))
 51                    goto Done;
 52
 053                answer = answer * 10 + c - '0';
 54
 055                if (answer > byte.MaxValue)
 056                    goto FalseExit; // Overflow
 57            }
 58
 59        FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This
 060            answer = 0;
 061            index++;
 062            if ((uint)index >= (uint)source.Length)
 63                goto FalseExit;
 064            if (source[index] != '0')
 65                goto FalseExit;
 66
 67        FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post
 68            do
 69            {
 070                index++;
 071                if ((uint)index >= (uint)source.Length)
 72                    goto Done;
 073                c = source[index];
 74            }
 075            while (c == '0');
 76
 077            if (ParserHelpers.IsDigit(c))
 78                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 79            goto Done;
 80
 81        FalseExit:
 082            bytesConsumed = default;
 083            value = default;
 084            return false;
 85
 86        Done:
 087            bytesConsumed = index;
 088            value = (byte)answer;
 089            return true;
 90        }
 91
 92        private static bool TryParseUInt16N(ReadOnlySpan<byte> source, out ushort value, out int bytesConsumed)
 93        {
 094            if (source.Length < 1)
 95                goto FalseExit;
 96
 097            int index = 0;
 098            int c = source[index];
 099            if (c == '+')
 100            {
 0101                index++;
 0102                if ((uint)index >= (uint)source.Length)
 103                    goto FalseExit;
 0104                c = source[index];
 105            }
 106
 107            int answer;
 108
 109            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 110            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 111            // one digit after the decimal point.)
 0112            if (c == Utf8Constants.Period)
 113                goto FractionalPartWithoutLeadingDigits;
 0114            if (!ParserHelpers.IsDigit(c))
 115                goto FalseExit;
 0116            answer = c - '0';
 117
 118            while (true)
 119            {
 0120                index++;
 0121                if ((uint)index >= (uint)source.Length)
 122                    goto Done;
 123
 0124                c = source[index];
 0125                if (c == Utf8Constants.Comma)
 126                    continue;
 127
 0128                if (c == Utf8Constants.Period)
 129                    goto FractionalDigits;
 130
 0131                if (!ParserHelpers.IsDigit(c))
 132                    goto Done;
 133
 0134                answer = answer * 10 + c - '0';
 135
 0136                if (answer > ushort.MaxValue)
 0137                    goto FalseExit; // Overflow
 138            }
 139
 140        FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This
 0141            answer = 0;
 0142            index++;
 0143            if ((uint)index >= (uint)source.Length)
 144                goto FalseExit;
 0145            if (source[index] != '0')
 146                goto FalseExit;
 147
 148        FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post
 149            do
 150            {
 0151                index++;
 0152                if ((uint)index >= (uint)source.Length)
 153                    goto Done;
 0154                c = source[index];
 155            }
 0156            while (c == '0');
 157
 0158            if (ParserHelpers.IsDigit(c))
 159                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 160            goto Done;
 161
 162        FalseExit:
 0163            bytesConsumed = default;
 0164            value = default;
 0165            return false;
 166
 167        Done:
 0168            bytesConsumed = index;
 0169            value = (ushort)answer;
 0170            return true;
 171        }
 172
 173        private static bool TryParseUInt32N(ReadOnlySpan<byte> source, out uint value, out int bytesConsumed)
 174        {
 0175            if (source.Length < 1)
 176                goto FalseExit;
 177
 0178            int index = 0;
 0179            int c = source[index];
 0180            if (c == '+')
 181            {
 0182                index++;
 0183                if ((uint)index >= (uint)source.Length)
 184                    goto FalseExit;
 0185                c = source[index];
 186            }
 187
 188            int answer;
 189
 190            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 191            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 192            // one digit after the decimal point.)
 0193            if (c == Utf8Constants.Period)
 194                goto FractionalPartWithoutLeadingDigits;
 0195            if (!ParserHelpers.IsDigit(c))
 196                goto FalseExit;
 0197            answer = c - '0';
 198
 0199            while (true)
 200            {
 0201                index++;
 0202                if ((uint)index >= (uint)source.Length)
 203                    goto Done;
 204
 0205                c = source[index];
 0206                if (c == Utf8Constants.Comma)
 207                    continue;
 208
 0209                if (c == Utf8Constants.Period)
 210                    goto FractionalDigits;
 211
 0212                if (!ParserHelpers.IsDigit(c))
 213                    goto Done;
 214
 0215                if (((uint)answer) > uint.MaxValue / 10 || (((uint)answer) == uint.MaxValue / 10 && c > '5'))
 216                    goto FalseExit; // Overflow
 217
 0218                answer = answer * 10 + c - '0';
 219            }
 220
 221        FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This
 0222            answer = 0;
 0223            index++;
 0224            if ((uint)index >= (uint)source.Length)
 225                goto FalseExit;
 0226            if (source[index] != '0')
 227                goto FalseExit;
 228
 229        FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post
 230            do
 231            {
 0232                index++;
 0233                if ((uint)index >= (uint)source.Length)
 234                    goto Done;
 0235                c = source[index];
 236            }
 0237            while (c == '0');
 238
 0239            if (ParserHelpers.IsDigit(c))
 240                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 241            goto Done;
 242
 243        FalseExit:
 0244            bytesConsumed = default;
 0245            value = default;
 0246            return false;
 247
 248        Done:
 0249            bytesConsumed = index;
 0250            value = (uint)answer;
 0251            return true;
 252        }
 253
 254        private static bool TryParseUInt64N(ReadOnlySpan<byte> source, out ulong value, out int bytesConsumed)
 255        {
 0256            if (source.Length < 1)
 257                goto FalseExit;
 258
 0259            int index = 0;
 0260            int c = source[index];
 0261            if (c == '+')
 262            {
 0263                index++;
 0264                if ((uint)index >= (uint)source.Length)
 265                    goto FalseExit;
 0266                c = source[index];
 267            }
 268
 269            long answer;
 270
 271            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 272            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 273            // one digit after the decimal point.)
 0274            if (c == Utf8Constants.Period)
 275                goto FractionalPartWithoutLeadingDigits;
 0276            if (!ParserHelpers.IsDigit(c))
 277                goto FalseExit;
 0278            answer = c - '0';
 279
 0280            while (true)
 281            {
 0282                index++;
 0283                if ((uint)index >= (uint)source.Length)
 284                    goto Done;
 285
 0286                c = source[index];
 0287                if (c == Utf8Constants.Comma)
 288                    continue;
 289
 0290                if (c == Utf8Constants.Period)
 291                    goto FractionalDigits;
 292
 0293                if (!ParserHelpers.IsDigit(c))
 294                    goto Done;
 295
 0296                if (((ulong)answer) > ulong.MaxValue / 10 || (((ulong)answer) == ulong.MaxValue / 10 && c > '5'))
 297                    goto FalseExit; // Overflow
 298
 0299                answer = answer * 10 + c - '0';
 300            }
 301
 302        FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This
 0303            answer = 0;
 0304            index++;
 0305            if ((uint)index >= (uint)source.Length)
 306                goto FalseExit;
 0307            if (source[index] != '0')
 308                goto FalseExit;
 309
 310        FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post
 311            do
 312            {
 0313                index++;
 0314                if ((uint)index >= (uint)source.Length)
 315                    goto Done;
 0316                c = source[index];
 317            }
 0318            while (c == '0');
 319
 0320            if (ParserHelpers.IsDigit(c))
 321                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 322            goto Done;
 323
 324        FalseExit:
 0325            bytesConsumed = default;
 0326            value = default;
 0327            return false;
 328
 329        Done:
 0330            bytesConsumed = index;
 0331            value = (ulong)answer;
 0332            return true;
 333        }
 334    }
 335}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.X.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        private static bool TryParseByteX(ReadOnlySpan<byte> source, out byte value, out int bytesConsumed)
 9        {
 010            if (source.Length < 1)
 11            {
 012                bytesConsumed = 0;
 013                value = default;
 014                return false;
 15            }
 16            byte nextCharacter;
 17            byte nextDigit;
 18
 019            ReadOnlySpan<byte> hexLookup = HexConverter.CharToHexLookup;
 20
 21            // Parse the first digit separately. If invalid here, we need to return false.
 022            nextCharacter = source[0];
 023            nextDigit = hexLookup[nextCharacter];
 024            if (nextDigit == 0xFF)
 25            {
 026                bytesConsumed = 0;
 027                value = default;
 028                return false;
 29            }
 030            uint parsedValue = nextDigit;
 31
 032            if (source.Length <= ParserHelpers.ByteOverflowLengthHex)
 33            {
 34                // Length is less than or equal to Parsers.ByteOverflowLengthHex; overflow is not possible
 035                for (int index = 1; index < source.Length; index++)
 36                {
 037                    nextCharacter = source[index];
 038                    nextDigit = hexLookup[nextCharacter];
 039                    if (nextDigit == 0xFF)
 40                    {
 041                        bytesConsumed = index;
 042                        value = (byte)(parsedValue);
 043                        return true;
 44                    }
 045                    parsedValue = (parsedValue << 4) + nextDigit;
 46                }
 47            }
 48            else
 49            {
 50                // Length is greater than Parsers.ByteOverflowLengthHex; overflow is only possible after Parsers.ByteOve
 51                // digits. There may be no overflow after Parsers.ByteOverflowLengthHex if there are leading zeroes.
 052                for (int index = 1; index < ParserHelpers.ByteOverflowLengthHex; index++)
 53                {
 054                    nextCharacter = source[index];
 055                    nextDigit = hexLookup[nextCharacter];
 056                    if (nextDigit == 0xFF)
 57                    {
 058                        bytesConsumed = index;
 059                        value = (byte)(parsedValue);
 060                        return true;
 61                    }
 062                    parsedValue = (parsedValue << 4) + nextDigit;
 63                }
 064                for (int index = ParserHelpers.ByteOverflowLengthHex; index < source.Length; index++)
 65                {
 066                    nextCharacter = source[index];
 067                    nextDigit = hexLookup[nextCharacter];
 068                    if (nextDigit == 0xFF)
 69                    {
 070                        bytesConsumed = index;
 071                        value = (byte)(parsedValue);
 072                        return true;
 73                    }
 74                    // If we try to append a digit to anything larger than byte.MaxValue / 0x10, there will be overflow
 075                    if (parsedValue > byte.MaxValue / 0x10)
 76                    {
 077                        bytesConsumed = 0;
 078                        value = default;
 079                        return false;
 80                    }
 081                    parsedValue = (parsedValue << 4) + nextDigit;
 82                }
 83            }
 84
 085            bytesConsumed = source.Length;
 086            value = (byte)(parsedValue);
 087            return true;
 88        }
 89
 90        private static bool TryParseUInt16X(ReadOnlySpan<byte> source, out ushort value, out int bytesConsumed)
 91        {
 092            if (source.Length < 1)
 93            {
 094                bytesConsumed = 0;
 095                value = default;
 096                return false;
 97            }
 98            byte nextCharacter;
 99            byte nextDigit;
 100
 0101            ReadOnlySpan<byte> hexLookup = HexConverter.CharToHexLookup;
 102
 103            // Parse the first digit separately. If invalid here, we need to return false.
 0104            nextCharacter = source[0];
 0105            nextDigit = hexLookup[nextCharacter];
 0106            if (nextDigit == 0xFF)
 107            {
 0108                bytesConsumed = 0;
 0109                value = default;
 0110                return false;
 111            }
 0112            uint parsedValue = nextDigit;
 113
 0114            if (source.Length <= ParserHelpers.Int16OverflowLengthHex)
 115            {
 116                // Length is less than or equal to Parsers.Int16OverflowLengthHex; overflow is not possible
 0117                for (int index = 1; index < source.Length; index++)
 118                {
 0119                    nextCharacter = source[index];
 0120                    nextDigit = hexLookup[nextCharacter];
 0121                    if (nextDigit == 0xFF)
 122                    {
 0123                        bytesConsumed = index;
 0124                        value = (ushort)(parsedValue);
 0125                        return true;
 126                    }
 0127                    parsedValue = (parsedValue << 4) + nextDigit;
 128                }
 129            }
 130            else
 131            {
 132                // Length is greater than Parsers.Int16OverflowLengthHex; overflow is only possible after Parsers.Int16O
 133                // digits. There may be no overflow after Parsers.Int16OverflowLengthHex if there are leading zeroes.
 0134                for (int index = 1; index < ParserHelpers.Int16OverflowLengthHex; index++)
 135                {
 0136                    nextCharacter = source[index];
 0137                    nextDigit = hexLookup[nextCharacter];
 0138                    if (nextDigit == 0xFF)
 139                    {
 0140                        bytesConsumed = index;
 0141                        value = (ushort)(parsedValue);
 0142                        return true;
 143                    }
 0144                    parsedValue = (parsedValue << 4) + nextDigit;
 145                }
 0146                for (int index = ParserHelpers.Int16OverflowLengthHex; index < source.Length; index++)
 147                {
 0148                    nextCharacter = source[index];
 0149                    nextDigit = hexLookup[nextCharacter];
 0150                    if (nextDigit == 0xFF)
 151                    {
 0152                        bytesConsumed = index;
 0153                        value = (ushort)(parsedValue);
 0154                        return true;
 155                    }
 156                    // If we try to append a digit to anything larger than ushort.MaxValue / 0x10, there will be overflo
 0157                    if (parsedValue > ushort.MaxValue / 0x10)
 158                    {
 0159                        bytesConsumed = 0;
 0160                        value = default;
 0161                        return false;
 162                    }
 0163                    parsedValue = (parsedValue << 4) + nextDigit;
 164                }
 165            }
 166
 0167            bytesConsumed = source.Length;
 0168            value = (ushort)(parsedValue);
 0169            return true;
 170        }
 171
 172        private static bool TryParseUInt32X(ReadOnlySpan<byte> source, out uint value, out int bytesConsumed)
 173        {
 0174            if (source.Length < 1)
 175            {
 0176                bytesConsumed = 0;
 0177                value = default;
 0178                return false;
 179            }
 180            byte nextCharacter;
 181            byte nextDigit;
 182
 0183            ReadOnlySpan<byte> hexLookup = HexConverter.CharToHexLookup;
 184
 185            // Parse the first digit separately. If invalid here, we need to return false.
 0186            nextCharacter = source[0];
 0187            nextDigit = hexLookup[nextCharacter];
 0188            if (nextDigit == 0xFF)
 189            {
 0190                bytesConsumed = 0;
 0191                value = default;
 0192                return false;
 193            }
 0194            uint parsedValue = nextDigit;
 195
 0196            if (source.Length <= ParserHelpers.Int32OverflowLengthHex)
 197            {
 198                // Length is less than or equal to Parsers.Int32OverflowLengthHex; overflow is not possible
 0199                for (int index = 1; index < source.Length; index++)
 200                {
 0201                    nextCharacter = source[index];
 0202                    nextDigit = hexLookup[nextCharacter];
 0203                    if (nextDigit == 0xFF)
 204                    {
 0205                        bytesConsumed = index;
 0206                        value = parsedValue;
 0207                        return true;
 208                    }
 0209                    parsedValue = (parsedValue << 4) + nextDigit;
 210                }
 211            }
 212            else
 213            {
 214                // Length is greater than Parsers.Int32OverflowLengthHex; overflow is only possible after Parsers.Int32O
 215                // digits. There may be no overflow after Parsers.Int32OverflowLengthHex if there are leading zeroes.
 0216                for (int index = 1; index < ParserHelpers.Int32OverflowLengthHex; index++)
 217                {
 0218                    nextCharacter = source[index];
 0219                    nextDigit = hexLookup[nextCharacter];
 0220                    if (nextDigit == 0xFF)
 221                    {
 0222                        bytesConsumed = index;
 0223                        value = parsedValue;
 0224                        return true;
 225                    }
 0226                    parsedValue = (parsedValue << 4) + nextDigit;
 227                }
 0228                for (int index = ParserHelpers.Int32OverflowLengthHex; index < source.Length; index++)
 229                {
 0230                    nextCharacter = source[index];
 0231                    nextDigit = hexLookup[nextCharacter];
 0232                    if (nextDigit == 0xFF)
 233                    {
 0234                        bytesConsumed = index;
 0235                        value = parsedValue;
 0236                        return true;
 237                    }
 238                    // If we try to append a digit to anything larger than uint.MaxValue / 0x10, there will be overflow
 0239                    if (parsedValue > uint.MaxValue / 0x10)
 240                    {
 0241                        bytesConsumed = 0;
 0242                        value = default;
 0243                        return false;
 244                    }
 0245                    parsedValue = (parsedValue << 4) + nextDigit;
 246                }
 247            }
 248
 0249            bytesConsumed = source.Length;
 0250            value = parsedValue;
 0251            return true;
 252        }
 253
 254        private static bool TryParseUInt64X(ReadOnlySpan<byte> source, out ulong value, out int bytesConsumed)
 255        {
 0256            if (source.Length < 1)
 257            {
 0258                bytesConsumed = 0;
 0259                value = default;
 0260                return false;
 261            }
 262            byte nextCharacter;
 263            byte nextDigit;
 264
 0265            ReadOnlySpan<byte> hexLookup = HexConverter.CharToHexLookup;
 266
 267            // Parse the first digit separately. If invalid here, we need to return false.
 0268            nextCharacter = source[0];
 0269            nextDigit = hexLookup[nextCharacter];
 0270            if (nextDigit == 0xFF)
 271            {
 0272                bytesConsumed = 0;
 0273                value = default;
 0274                return false;
 275            }
 0276            ulong parsedValue = nextDigit;
 277
 0278            if (source.Length <= ParserHelpers.Int64OverflowLengthHex)
 279            {
 280                // Length is less than or equal to Parsers.Int64OverflowLengthHex; overflow is not possible
 0281                for (int index = 1; index < source.Length; index++)
 282                {
 0283                    nextCharacter = source[index];
 0284                    nextDigit = hexLookup[nextCharacter];
 0285                    if (nextDigit == 0xFF)
 286                    {
 0287                        bytesConsumed = index;
 0288                        value = parsedValue;
 0289                        return true;
 290                    }
 0291                    parsedValue = (parsedValue << 4) + nextDigit;
 292                }
 293            }
 294            else
 295            {
 296                // Length is greater than Parsers.Int64OverflowLengthHex; overflow is only possible after Parsers.Int64O
 297                // digits. There may be no overflow after Parsers.Int64OverflowLengthHex if there are leading zeroes.
 0298                for (int index = 1; index < ParserHelpers.Int64OverflowLengthHex; index++)
 299                {
 0300                    nextCharacter = source[index];
 0301                    nextDigit = hexLookup[nextCharacter];
 0302                    if (nextDigit == 0xFF)
 303                    {
 0304                        bytesConsumed = index;
 0305                        value = parsedValue;
 0306                        return true;
 307                    }
 0308                    parsedValue = (parsedValue << 4) + nextDigit;
 309                }
 0310                for (int index = ParserHelpers.Int64OverflowLengthHex; index < source.Length; index++)
 311                {
 0312                    nextCharacter = source[index];
 0313                    nextDigit = hexLookup[nextCharacter];
 0314                    if (nextDigit == 0xFF)
 315                    {
 0316                        bytesConsumed = index;
 0317                        value = parsedValue;
 0318                        return true;
 319                    }
 320                    // If we try to append a digit to anything larger than ulong.MaxValue / 0x10, there will be overflow
 0321                    if (parsedValue > ulong.MaxValue / 0x10)
 322                    {
 0323                        bytesConsumed = 0;
 0324                        value = default;
 0325                        return false;
 326                    }
 0327                    parsedValue = (parsedValue << 4) + nextDigit;
 328                }
 329            }
 330
 0331            bytesConsumed = source.Length;
 0332            value = parsedValue;
 0333            return true;
 334        }
 335    }
 336}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Number.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;
 5
 6namespace System.Buffers.Text
 7{
 8    public static partial class Utf8Parser
 9    {
 10        [Flags]
 11        private enum ParseNumberOptions
 12        {
 13            AllowExponent = 0x00000001,
 14        }
 15
 16        private static bool TryParseNumber(ReadOnlySpan<byte> source, ref Number.NumberBuffer number, out int bytesConsu
 17        {
 018            Debug.Assert(number.DigitsCount == 0);
 019            Debug.Assert(number.Scale == 0);
 020            Debug.Assert(!number.IsNegative);
 021            Debug.Assert(!number.HasNonZeroTail);
 22
 023            number.CheckConsistency();
 024            textUsedExponentNotation = false;
 25
 026            if (source.Length == 0)
 27            {
 028                bytesConsumed = 0;
 029                return false;
 30            }
 31
 032            Span<byte> digits = number.Digits;
 33
 034            int srcIndex = 0;
 035            int dstIndex = 0;
 36
 37            // Consume the leading sign if any.
 038            byte c = source[srcIndex];
 39            switch (c)
 40            {
 41                case Utf8Constants.Minus:
 042                    number.IsNegative = true;
 43                    goto case Utf8Constants.Plus;
 44
 45                case Utf8Constants.Plus:
 046                    srcIndex++;
 047                    if (srcIndex >= source.Length)
 48                    {
 049                        bytesConsumed = 0;
 050                        return false;
 51                    }
 052                    c = source[srcIndex];
 53                    break;
 54
 55                default:
 56                    break;
 57            }
 58
 059            int startIndexDigitsBeforeDecimal = srcIndex;
 060            int digitCount = 0;
 061            int maxDigitCount = digits.Length - 1;
 62
 63            // Throw away any leading zeroes
 064            while (srcIndex < source.Length)
 65            {
 066                c = source[srcIndex];
 067                if (c != '0')
 68                    break;
 069                srcIndex++;
 70            }
 71
 072            if (srcIndex == source.Length)
 73            {
 074                bytesConsumed = srcIndex;
 075                number.CheckConsistency();
 076                return true;
 77            }
 78
 079            int startIndexNonLeadingDigitsBeforeDecimal = srcIndex;
 80
 081            int hasNonZeroTail = 0;
 082            while (srcIndex < source.Length)
 83            {
 084                c = source[srcIndex];
 085                int value = (byte)(c - (byte)('0'));
 86
 087                if (value > 9)
 88                {
 89                    break;
 90                }
 91
 092                srcIndex++;
 093                digitCount++;
 94
 095                if (digitCount >= maxDigitCount)
 96                {
 97                    // For decimal and binary floating-point numbers, we only
 98                    // need to store digits up to maxDigCount. However, we still
 99                    // need to keep track of whether any additional digits past
 100                    // maxDigCount were non-zero, as that can impact rounding
 101                    // for an input that falls evenly between two representable
 102                    // results.
 103
 0104                    hasNonZeroTail |= value;
 105                }
 106            }
 0107            number.HasNonZeroTail = (hasNonZeroTail != 0);
 108
 0109            int numDigitsBeforeDecimal = srcIndex - startIndexDigitsBeforeDecimal;
 0110            int numNonLeadingDigitsBeforeDecimal = srcIndex - startIndexNonLeadingDigitsBeforeDecimal;
 111
 0112            Debug.Assert(dstIndex == 0);
 0113            int numNonLeadingDigitsBeforeDecimalToCopy = Math.Min(numNonLeadingDigitsBeforeDecimal, maxDigitCount);
 0114            source.Slice(startIndexNonLeadingDigitsBeforeDecimal, numNonLeadingDigitsBeforeDecimalToCopy).CopyTo(digits)
 0115            dstIndex = numNonLeadingDigitsBeforeDecimalToCopy;
 0116            number.Scale = numNonLeadingDigitsBeforeDecimal;
 117
 0118            if (srcIndex == source.Length)
 119            {
 0120                digits[dstIndex] = 0;
 0121                number.DigitsCount = dstIndex;
 0122                bytesConsumed = srcIndex;
 0123                number.CheckConsistency();
 0124                return true;
 125            }
 126
 0127            int numDigitsAfterDecimal = 0;
 0128            if (c == Utf8Constants.Period)
 129            {
 130                //
 131                // Parse the digits after the decimal point.
 132                //
 133
 0134                srcIndex++;
 0135                int startIndexDigitsAfterDecimal = srcIndex;
 136
 0137                while (srcIndex < source.Length)
 138                {
 0139                    c = source[srcIndex];
 0140                    int value = (byte)(c - (byte)('0'));
 141
 0142                    if (value > 9)
 143                    {
 144                        break;
 145                    }
 146
 0147                    srcIndex++;
 0148                    digitCount++;
 149
 0150                    if (digitCount >= maxDigitCount)
 151                    {
 152                        // For decimal and binary floating-point numbers, we only
 153                        // need to store digits up to maxDigCount. However, we still
 154                        // need to keep track of whether any additional digits past
 155                        // maxDigCount were non-zero, as that can impact rounding
 156                        // for an input that falls evenly between two representable
 157                        // results.
 158
 0159                        hasNonZeroTail |= value;
 160                    }
 161                }
 0162                number.HasNonZeroTail = (hasNonZeroTail != 0);
 163
 0164                numDigitsAfterDecimal = srcIndex - startIndexDigitsAfterDecimal;
 165
 0166                int startIndexOfDigitsAfterDecimalToCopy = startIndexDigitsAfterDecimal;
 0167                if (dstIndex == 0)
 168                {
 169                    // Not copied any digits to the Number struct yet. This means we must continue discarding leading ze
 0170                    while (startIndexOfDigitsAfterDecimalToCopy < srcIndex && source[startIndexOfDigitsAfterDecimalToCop
 171                    {
 0172                        number.Scale--;
 0173                        startIndexOfDigitsAfterDecimalToCopy++;
 174                    }
 175                }
 176
 0177                int numDigitsAfterDecimalToCopy = Math.Min(srcIndex - startIndexOfDigitsAfterDecimalToCopy, maxDigitCoun
 0178                source.Slice(startIndexOfDigitsAfterDecimalToCopy, numDigitsAfterDecimalToCopy).CopyTo(digits.Slice(dstI
 0179                dstIndex += numDigitsAfterDecimalToCopy;
 180                // We "should" really NUL terminate, but there are multiple places we'd have to do this and it is a prec
 181
 0182                if (srcIndex == source.Length)
 183                {
 0184                    if (numDigitsBeforeDecimal == 0 && numDigitsAfterDecimal == 0)
 185                    {
 186                        // For compatibility. You can say "5." and ".5" but you can't say "."
 0187                        bytesConsumed = 0;
 0188                        return false;
 189                    }
 190
 0191                    digits[dstIndex] = 0;
 0192                    number.DigitsCount = dstIndex;
 0193                    bytesConsumed = srcIndex;
 0194                    number.CheckConsistency();
 0195                    return true;
 196                }
 197            }
 198
 0199            if (numDigitsBeforeDecimal == 0 && numDigitsAfterDecimal == 0)
 200            {
 0201                bytesConsumed = 0;
 0202                return false;
 203            }
 204
 0205            if ((c & ~0x20u) != 'E')
 206            {
 0207                digits[dstIndex] = 0;
 0208                number.DigitsCount = dstIndex;
 0209                bytesConsumed = srcIndex;
 0210                number.CheckConsistency();
 0211                return true;
 212            }
 213
 214            //
 215            // Parse the exponent after the "E"
 216            //
 0217            textUsedExponentNotation = true;
 0218            srcIndex++;
 219
 0220            if ((options & ParseNumberOptions.AllowExponent) == 0)
 221            {
 0222                bytesConsumed = 0;
 0223                return false;
 224            }
 225
 0226            if (srcIndex == source.Length)
 227            {
 0228                bytesConsumed = 0;
 0229                return false;
 230            }
 231
 0232            bool exponentIsNegative = false;
 0233            c = source[srcIndex];
 234            switch (c)
 235            {
 236                case Utf8Constants.Minus:
 0237                    exponentIsNegative = true;
 238                    goto case Utf8Constants.Plus;
 239
 240                case Utf8Constants.Plus:
 0241                    srcIndex++;
 0242                    if (srcIndex == source.Length)
 243                    {
 0244                        bytesConsumed = 0;
 0245                        return false;
 246                    }
 0247                    c = source[srcIndex];
 248                    break;
 249
 250                default:
 251                    break;
 252            }
 253
 254            // If the next character isn't a digit, an exponent wasn't specified
 0255            if ((byte)(c - (byte)('0')) > 9)
 256            {
 0257                bytesConsumed = 0;
 0258                return false;
 259            }
 260
 0261            if (!TryParseUInt32D(source.Slice(srcIndex), out uint absoluteExponent, out int bytesConsumedByExponent))
 262            {
 263                // Since we found at least one digit, we know that any failure to parse means we had an
 264                // exponent that was larger than uint.MaxValue, and we can just eat characters until the end
 0265                absoluteExponent = uint.MaxValue;
 266
 267                // This also means that we know there was at least 10 characters and we can "eat" those, and
 268                // continue eating digits from there
 0269                srcIndex += 10;
 270
 0271                while (srcIndex < source.Length)
 272                {
 0273                    c = source[srcIndex];
 0274                    int value = (byte)(c - (byte)('0'));
 275
 0276                    if (value > 9)
 277                    {
 278                        break;
 279                    }
 280
 0281                    srcIndex++;
 282                }
 283            }
 284
 0285            srcIndex += bytesConsumedByExponent;
 286
 0287            if (exponentIsNegative)
 288            {
 0289                if (number.Scale < int.MinValue + (long)absoluteExponent)
 290                {
 291                    // A scale underflow means all non-zero digits are all so far to the right of the decimal point, no
 292                    // number format we have will be able to see them. Just pin the scale at the absolute minimum
 293                    // and let the converter produce a 0 with the max precision available for that type.
 0294                    number.Scale = int.MinValue;
 295                }
 296                else
 297                {
 0298                    number.Scale -= (int)absoluteExponent;
 299                }
 300            }
 301            else
 302            {
 0303                if (number.Scale > int.MaxValue - (long)absoluteExponent)
 304                {
 305                    // A scale overflow means all non-zero digits are all so far to the right of the decimal point, no
 306                    // number format we have will be able to see them. Just pin the scale at the absolute maximum
 307                    // and let the converter produce a 0 with the max precision available for that type.
 0308                    number.Scale = int.MaxValue;
 309                }
 310                else
 311                {
 0312                    number.Scale += (int)absoluteExponent;
 313                }
 314            }
 315
 0316            digits[dstIndex] = 0;
 0317            number.DigitsCount = dstIndex;
 0318            bytesConsumed = srcIndex;
 0319            number.CheckConsistency();
 0320            return true;
 321        }
 322    }
 323}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.BigG.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        private static bool TryParseTimeSpanBigG(ReadOnlySpan<byte> source, out TimeSpan value, out int bytesConsumed)
 9        {
 010            int srcIndex = 0;
 011            byte c = default;
 012            while (srcIndex < source.Length)
 13            {
 014                c = source[srcIndex];
 015                if (!(c == ' ' || c == '\t'))
 16                    break;
 017                srcIndex++;
 18            }
 19
 020            if (srcIndex == source.Length)
 21            {
 022                value = default;
 023                bytesConsumed = 0;
 024                return false;
 25            }
 26
 027            bool isNegative = false;
 028            if (c == Utf8Constants.Minus)
 29            {
 030                isNegative = true;
 031                srcIndex++;
 032                if (srcIndex == source.Length)
 33                {
 034                    value = default;
 035                    bytesConsumed = 0;
 036                    return false;
 37                }
 38            }
 39
 040            if (!TryParseUInt32D(source.Slice(srcIndex), out uint days, out int justConsumed))
 41            {
 042                value = default;
 043                bytesConsumed = 0;
 044                return false;
 45            }
 046            srcIndex += justConsumed;
 47
 048            if (srcIndex == source.Length || source[srcIndex++] != Utf8Constants.Colon)
 49            {
 050                value = default;
 051                bytesConsumed = 0;
 052                return false;
 53            }
 54
 055            if (!TryParseUInt32D(source.Slice(srcIndex), out uint hours, out justConsumed))
 56            {
 057                value = default;
 058                bytesConsumed = 0;
 059                return false;
 60            }
 061            srcIndex += justConsumed;
 62
 063            if (srcIndex == source.Length || source[srcIndex++] != Utf8Constants.Colon)
 64            {
 065                value = default;
 066                bytesConsumed = 0;
 067                return false;
 68            }
 69
 070            if (!TryParseUInt32D(source.Slice(srcIndex), out uint minutes, out justConsumed))
 71            {
 072                value = default;
 073                bytesConsumed = 0;
 074                return false;
 75            }
 076            srcIndex += justConsumed;
 77
 078            if (srcIndex == source.Length || source[srcIndex++] != Utf8Constants.Colon)
 79            {
 080                value = default;
 081                bytesConsumed = 0;
 082                return false;
 83            }
 84
 085            if (!TryParseUInt32D(source.Slice(srcIndex), out uint seconds, out justConsumed))
 86            {
 087                value = default;
 088                bytesConsumed = 0;
 089                return false;
 90            }
 091            srcIndex += justConsumed;
 92
 093            if (srcIndex == source.Length || source[srcIndex++] != Utf8Constants.Period)
 94            {
 095                value = default;
 096                bytesConsumed = 0;
 097                return false;
 98            }
 99
 0100            if (!TryParseTimeSpanFraction(source.Slice(srcIndex), out uint fraction, out justConsumed))
 101            {
 0102                value = default;
 0103                bytesConsumed = 0;
 0104                return false;
 105            }
 106
 0107            srcIndex += justConsumed;
 108
 0109            if (!TryCreateTimeSpan(isNegative: isNegative, days: days, hours: hours, minutes: minutes, seconds: seconds,
 110            {
 0111                value = default;
 0112                bytesConsumed = 0;
 0113                return false;
 114            }
 115
 116            //
 117            // There cannot legally be a sixth number. If the next character is a period or colon, treat this as a error
 118            // to indicate the start of a sixth number. Otherwise, treat as end of parse with data left over.
 119            //
 0120            if (srcIndex != source.Length && (source[srcIndex] == Utf8Constants.Period || source[srcIndex] == Utf8Consta
 121            {
 0122                value = default;
 0123                bytesConsumed = 0;
 0124                return false;
 125            }
 126
 0127            bytesConsumed = srcIndex;
 0128            return true;
 129        }
 130    }
 131}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.C.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        private static bool TryParseTimeSpanC(ReadOnlySpan<byte> source, out TimeSpan value, out int bytesConsumed)
 9        {
 010            TimeSpanSplitter s = default;
 011            if (!s.TrySplitTimeSpan(source, periodUsedToSeparateDay: true, out bytesConsumed))
 12            {
 013                value = default;
 014                return false;
 15            }
 16
 017            bool isNegative = s.IsNegative;
 18
 19            bool success;
 020            switch (s.Separators)
 21            {
 22                case 0x00000000: // dd
 023                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: 0, minutes: 0, seconds: 0, fr
 024                    break;
 25
 26                case 0x01000000: // hh:mm
 027                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: 0,
 028                    break;
 29
 30                case 0x02010000: // dd.hh:mm
 031                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: s.V2, minutes: s.V3, seconds:
 032                    break;
 33
 34                case 0x01010000: // hh:mm:ss
 035                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: s.
 036                    break;
 37
 38                case 0x02010100: // dd.hh:mm:ss
 039                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: s.V2, minutes: s.V3, seconds:
 040                    break;
 41
 42                case 0x01010200: // hh:mm:ss.fffffff
 043                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: s.
 044                    break;
 45
 46                case 0x02010102: // dd.hh:mm:ss.fffffff
 047                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: s.V2, minutes: s.V3, seconds:
 048                    break;
 49
 50                default:
 051                    value = default;
 052                    success = false;
 53                    break;
 54            }
 55
 056            if (!success)
 57            {
 058                bytesConsumed = 0;
 059                return false;
 60            }
 61
 062            return true;
 63        }
 64    }
 65}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.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;
 5
 6namespace System.Buffers.Text
 7{
 8    public static partial class Utf8Parser
 9    {
 10        /// <summary>
 11        /// Parses a TimeSpan at the start of a Utf8 string.
 12        /// </summary>
 13        /// <param name="source">The Utf8 string to parse</param>
 14        /// <param name="value">Receives the parsed value</param>
 15        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 16        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 17        /// <returns>
 18        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 19        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 20        /// </returns>
 21        /// <remarks>
 22        /// Formats supported:
 23        ///     c/t/T (default) [-][d.]hh:mm:ss[.fffffff]             (constant format)
 24        ///     G               [-]d:hh:mm:ss.fffffff                 (general long)
 25        ///     g               [-][d:]h:mm:ss[.f[f[f[f[f[f[f[]]]]]]] (general short)
 26        /// </remarks>
 27        /// <exceptions>
 28        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 29        /// </exceptions>
 30        public static bool TryParse(ReadOnlySpan<byte> source, out TimeSpan value, out int bytesConsumed, char standardF
 031            standardFormat switch
 032            {
 033                default(char) or 'c' or 't' or 'T' => TryParseTimeSpanC(source, out value, out bytesConsumed),
 034                'G' => TryParseTimeSpanBigG(source, out value, out bytesConsumed),
 035                'g' => TryParseTimeSpanLittleG(source, out value, out bytesConsumed),
 036                _ => ParserHelpers.TryParseThrowFormatException(out value, out bytesConsumed),
 037            };
 38
 39        /// <summary>
 40        /// Parse the fraction portion of a TimeSpan. Must be 1..7 digits. If fewer than 7, zeroes are implied to the ri
 41        /// parser rejects the string (even if the extra digits are all zeroes.)
 42        /// </summary>
 43        private static bool TryParseTimeSpanFraction(ReadOnlySpan<byte> source, out uint value, out int bytesConsumed)
 44        {
 045            int srcIndex = 0;
 46
 047            if (srcIndex == source.Length)
 48            {
 049                value = default;
 050                bytesConsumed = 0;
 051                return false;
 52            }
 53
 054            uint digit = source[srcIndex] - 48u; // '0'
 055            if (digit > 9)
 56            {
 057                value = default;
 058                bytesConsumed = 0;
 059                return false;
 60            }
 061            srcIndex++;
 62
 063            uint fraction = digit;
 064            int digitCount = 1;
 65
 066            while (srcIndex < source.Length)
 67            {
 068                digit = source[srcIndex] - 48u; // '0'
 069                if (digit > 9)
 70                    break;
 071                srcIndex++;
 072                digitCount++;
 073                if (digitCount > Utf8Constants.DateTimeNumFractionDigits)
 74                {
 75                    // Yes, TimeSpan fraction parsing is that picky.
 076                    value = default;
 077                    bytesConsumed = 0;
 078                    return false;
 79                }
 080                fraction = 10 * fraction + digit;
 81            }
 82
 83            switch (digitCount)
 84            {
 85                case 7:
 86                    break;
 87
 88                case 6:
 089                    fraction *= 10;
 090                    break;
 91
 92                case 5:
 093                    fraction *= 100;
 094                    break;
 95
 96                case 4:
 097                    fraction *= 1000;
 098                    break;
 99
 100                case 3:
 0101                    fraction *= 10000;
 0102                    break;
 103
 104                case 2:
 0105                    fraction *= 100000;
 0106                    break;
 107
 108                default:
 0109                    Debug.Assert(digitCount == 1);
 0110                    fraction *= 1000000;
 111                    break;
 112            }
 113
 0114            value = fraction;
 0115            bytesConsumed = srcIndex;
 0116            return true;
 117        }
 118
 119        /// <summary>
 120        /// Overflow-safe TryCreateTimeSpan
 121        /// </summary>
 122        private static bool TryCreateTimeSpan(bool isNegative, uint days, uint hours, uint minutes, uint seconds, uint f
 123        {
 124            const long MaxMilliSeconds = long.MaxValue / TimeSpan.TicksPerMillisecond;
 125            const long MinMilliSeconds = long.MinValue / TimeSpan.TicksPerMillisecond;
 126
 0127            if (hours > 23 || minutes > 59 || seconds > 59)
 128            {
 0129                timeSpan = default;
 0130                return false;
 131            }
 132
 0133            Debug.Assert(fraction <= Utf8Constants.MaxDateTimeFraction); // This value comes from TryParseTimeSpanFracti
 134
 0135            long millisecondsWithoutFraction = (((long)days) * 3600 * 24 + ((long)hours) * 3600 + ((long)minutes) * 60 +
 136
 137            long ticks;
 0138            if (isNegative)
 139            {
 0140                millisecondsWithoutFraction = -millisecondsWithoutFraction;
 0141                if (millisecondsWithoutFraction < MinMilliSeconds)
 142                {
 0143                    timeSpan = default;
 0144                    return false;
 145                }
 146
 0147                long ticksWithoutFraction = millisecondsWithoutFraction * TimeSpan.TicksPerMillisecond;
 0148                if (ticksWithoutFraction < long.MinValue + fraction)
 149                {
 0150                    timeSpan = default;
 0151                    return false;
 152                }
 153
 0154                ticks = ticksWithoutFraction - fraction;
 155            }
 156            else
 157            {
 0158                if (millisecondsWithoutFraction > MaxMilliSeconds)
 159                {
 0160                    timeSpan = default;
 0161                    return false;
 162                }
 163
 0164                long ticksWithoutFraction = millisecondsWithoutFraction * TimeSpan.TicksPerMillisecond;
 0165                if (ticksWithoutFraction > long.MaxValue - fraction)
 166                {
 0167                    timeSpan = default;
 0168                    return false;
 169                }
 170
 0171                ticks = ticksWithoutFraction + fraction;
 172            }
 173
 0174            timeSpan = new TimeSpan(ticks);
 0175            return true;
 176        }
 177    }
 178}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.LittleG.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.Buffers.Text
 5{
 6    public static partial class Utf8Parser
 7    {
 8        private static bool TryParseTimeSpanLittleG(ReadOnlySpan<byte> source, out TimeSpan value, out int bytesConsumed
 9        {
 010            TimeSpanSplitter s = default;
 011            if (!s.TrySplitTimeSpan(source, periodUsedToSeparateDay: false, out bytesConsumed))
 12            {
 013                value = default;
 014                return false;
 15            }
 16
 017            bool isNegative = s.IsNegative;
 18
 19            bool success;
 020            switch (s.Separators)
 21            {
 22                case 0x00000000: // dd
 023                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: 0, minutes: 0, seconds: 0, fr
 024                    break;
 25
 26                case 0x01000000: // hh:mm
 027                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: 0,
 028                    break;
 29
 30                case 0x01010000: // hh:mm:ss
 031                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: s.
 032                    break;
 33
 34                case 0x01010100: // dd:hh:mm:ss
 035                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: s.V2, minutes: s.V3, seconds:
 036                    break;
 37
 38                case 0x01010200: // hh:mm:ss.fffffff
 039                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: s.
 040                    break;
 41
 42                case 0x01010102: // dd:hh:mm:ss.fffffff
 043                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: s.V2, minutes: s.V3, seconds:
 044                    break;
 45
 46                default:
 047                    value = default;
 048                    success = false;
 49                    break;
 50            }
 51
 052            if (!success)
 53            {
 054                bytesConsumed = 0;
 055                return false;
 56            }
 57
 058            return true;
 59        }
 60    }
 61}

C:\h\w\9FD50923\w\C0A20A61\e\runtime-utils\Runner\runtime\src\libraries\System.Private.CoreLib\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpanSplitter.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;
 5
 6namespace System.Buffers.Text
 7{
 8    public static partial class Utf8Parser
 9    {
 10        private enum ComponentParseResult : byte
 11        {
 12            // Do not change or add values in this enum unless you review every use of the TimeSpanSplitter.Separators f
 13            // ComponentParseResults" encoded as a 32-bit integer with each of its four bytes containing one of 0 (NoMor
 14            // (So a value of 0x01010200 means the string parsed as "nn:nn:nn.nnnnnnn")
 15            NoMoreData = 0,
 16            Colon = 1,
 17            Period = 2,
 18            ParseFailure = 3,
 19        }
 20
 21        private struct TimeSpanSplitter
 22        {
 23            public uint V1;
 24            public uint V2;
 25            public uint V3;
 26            public uint V4;
 27            public uint V5;
 28
 29            public bool IsNegative;
 30
 31            // Encodes an "array of four ComponentParseResults" as a 32-bit integer with each of its four bytes containi
 32            // (So a value of 0x01010200 means the string parsed as "nn:nn:nn.nnnnnnn")
 33            public uint Separators;
 34
 35            public bool TrySplitTimeSpan(ReadOnlySpan<byte> source, bool periodUsedToSeparateDay, out int bytesConsumed)
 36            {
 037                int srcIndex = 0;
 038                byte c = default;
 39
 40                // Unlike many other data types, TimeSpan allow leading whitespace.
 041                while (srcIndex < source.Length)
 42                {
 043                    c = source[srcIndex];
 044                    if (!(c == ' ' || c == '\t'))
 45                        break;
 046                    srcIndex++;
 47                }
 48
 049                if (srcIndex == source.Length)
 50                {
 051                    bytesConsumed = 0;
 052                    return false;
 53                }
 54
 55                // Check for an option negative sign. ('+' is not allowed.)
 056                if (c == Utf8Constants.Minus)
 57                {
 058                    IsNegative = true;
 059                    srcIndex++;
 060                    if (srcIndex == source.Length)
 61                    {
 062                        bytesConsumed = 0;
 063                        return false;
 64                    }
 65                }
 66
 67                // From here, we terminate on anything that's not a digit, ':' or '.' The '.' is only allowed after at l
 68                // been specified. If we see it earlier, we'll assume that's an error and fail out rather than treating 
 69
 70                //
 71                // Timespan has to start with a number - parse the first one.
 72                //
 073                if (!TryParseUInt32D(source.Slice(srcIndex), out V1, out int justConsumed))
 74                {
 075                    bytesConsumed = 0;
 076                    return false;
 77                }
 078                srcIndex += justConsumed;
 79
 80                //
 81                // Split out the second number (if any) For the 'c' format, a period might validly appear here as it;s u
 82                // the fraction is always the fourth component at earliest, so if we do see a period at this stage, alwa
 83                // a fraction.
 84                //
 085                ComponentParseResult result = ParseComponent(source, neverParseAsFraction: periodUsedToSeparateDay, ref 
 086                if (result == ComponentParseResult.ParseFailure)
 87                {
 088                    bytesConsumed = 0;
 089                    return false;
 90                }
 091                else if (result == ComponentParseResult.NoMoreData)
 92                {
 093                    bytesConsumed = srcIndex;
 094                    return true;
 95                }
 96                else
 97                {
 098                    Debug.Assert(result == ComponentParseResult.Colon || result == ComponentParseResult.Period);
 099                    Separators |= ((uint)result) << 24;
 100                }
 101
 102                //
 103                // Split out the third number (if any)
 104                //
 0105                result = ParseComponent(source, false, ref srcIndex, out V3);
 0106                if (result == ComponentParseResult.ParseFailure)
 107                {
 0108                    bytesConsumed = 0;
 0109                    return false;
 110                }
 0111                else if (result == ComponentParseResult.NoMoreData)
 112                {
 0113                    bytesConsumed = srcIndex;
 0114                    return true;
 115                }
 116                else
 117                {
 0118                    Debug.Assert(result == ComponentParseResult.Colon || result == ComponentParseResult.Period);
 0119                    Separators |= ((uint)result) << 16;
 120                }
 121
 122                //
 123                // Split out the fourth number (if any)
 124                //
 0125                result = ParseComponent(source, false, ref srcIndex, out V4);
 0126                if (result == ComponentParseResult.ParseFailure)
 127                {
 0128                    bytesConsumed = 0;
 0129                    return false;
 130                }
 0131                else if (result == ComponentParseResult.NoMoreData)
 132                {
 0133                    bytesConsumed = srcIndex;
 0134                    return true;
 135                }
 136                else
 137                {
 0138                    Debug.Assert(result == ComponentParseResult.Colon || result == ComponentParseResult.Period);
 0139                    Separators |= ((uint)result) << 8;
 140                }
 141
 142                //
 143                // Split out the fifth number (if any)
 144                //
 0145                result = ParseComponent(source, false, ref srcIndex, out V5);
 0146                if (result == ComponentParseResult.ParseFailure)
 147                {
 0148                    bytesConsumed = 0;
 0149                    return false;
 150                }
 0151                else if (result == ComponentParseResult.NoMoreData)
 152                {
 0153                    bytesConsumed = srcIndex;
 0154                    return true;
 155                }
 156                else
 157                {
 0158                    Debug.Assert(result == ComponentParseResult.Colon || result == ComponentParseResult.Period);
 0159                    Separators |= (uint)result;
 160                }
 161
 162                //
 163                // There cannot legally be a sixth number. If the next character is a period or colon, treat this as a e
 164                // to indicate the start of a sixth number. Otherwise, treat as end of parse with data left over.
 165                //
 0166                if (srcIndex != source.Length && (source[srcIndex] == Utf8Constants.Period || source[srcIndex] == Utf8Co
 167                {
 0168                    bytesConsumed = 0;
 0169                    return false;
 170                }
 171
 0172                bytesConsumed = srcIndex;
 0173                return true;
 174            }
 175
 176            //
 177            // Look for a separator followed by an unsigned integer.
 178            //
 179            private static ComponentParseResult ParseComponent(ReadOnlySpan<byte> source, bool neverParseAsFraction, ref
 180            {
 0181                if (srcIndex == source.Length)
 182                {
 0183                    value = default;
 0184                    return ComponentParseResult.NoMoreData;
 185                }
 186
 0187                byte c = source[srcIndex];
 0188                if (c == Utf8Constants.Colon || (c == Utf8Constants.Period && neverParseAsFraction))
 189                {
 0190                    srcIndex++;
 191
 0192                    if (!TryParseUInt32D(source.Slice(srcIndex), out value, out int bytesConsumed))
 193                    {
 0194                        value = default;
 0195                        return ComponentParseResult.ParseFailure;
 196                    }
 197
 0198                    srcIndex += bytesConsumed;
 0199                    return c == Utf8Constants.Colon ? ComponentParseResult.Colon : ComponentParseResult.Period;
 200                }
 0201                else if (c == Utf8Constants.Period)
 202                {
 0203                    srcIndex++;
 204
 0205                    if (!TryParseTimeSpanFraction(source.Slice(srcIndex), out value, out int bytesConsumed))
 206                    {
 0207                        value = default;
 0208                        return ComponentParseResult.ParseFailure;
 209                    }
 210
 0211                    srcIndex += bytesConsumed;
 0212                    return ComponentParseResult.Period;
 213                }
 214                else
 215                {
 0216                    value = default;
 0217                    return ComponentParseResult.NoMoreData;
 218                }
 219            }
 220        }
 221    }
 222}

Methods/Properties

TryParse(System.ReadOnlySpan`1<System.Byte>,System.Boolean&,System.Int32&,System.Char)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.DateTime&,System.Int32&,System.Char)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.DateTimeOffset&,System.Int32&,System.Char)
TryParseDateTimeOffsetDefault(System.ReadOnlySpan`1<System.Byte>,System.DateTimeOffset&,System.Int32&)
TryParseDateTimeG(System.ReadOnlySpan`1<System.Byte>,System.DateTime&,System.DateTimeOffset&,System.Int32&)
TryCreateDateTimeOffset(System.DateTime,System.Boolean,System.Int32,System.Int32,System.DateTimeOffset&)
TryCreateDateTimeOffset(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Boolean,System.Int32,System.Int32,System.DateTimeOffset&)
TryCreateDateTimeOffsetInterpretingDataAsLocalTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.DateTimeOffset&)
TryCreateDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.DateTimeKind,System.DateTime&)
TryParseDateTimeOffsetO(System.ReadOnlySpan`1<System.Byte>,System.DateTimeOffset&,System.Int32&,System.DateTimeKind&)
TryParseDateTimeOffsetR(System.ReadOnlySpan`1<System.Byte>,System.UInt32,System.DateTimeOffset&,System.Int32&)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.Decimal&,System.Int32&,System.Char)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.Single&,System.Int32&,System.Char)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.Double&,System.Int32&,System.Char)
TryParseNormalAsFloatingPoint(System.ReadOnlySpan`1<System.Byte>,System.Number/NumberBuffer&,System.Int32&,System.Char)
TryParseAsSpecialFloatingPoint(System.ReadOnlySpan`1<System.Byte>,T,T,T,T&,System.Int32&)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.Guid&,System.Int32&,System.Char)
TryParseGuidN(System.ReadOnlySpan`1<System.Byte>,System.Guid&,System.Int32&)
TryParseGuidCore(System.ReadOnlySpan`1<System.Byte>,System.Guid&,System.Int32&,System.Int32)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.SByte&,System.Int32&,System.Char)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.Int16&,System.Int32&,System.Char)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.Int32&,System.Int32&,System.Char)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.Int64&,System.Int32&,System.Char)
TryParseSByteD(System.ReadOnlySpan`1<System.Byte>,System.SByte&,System.Int32&)
TryParseInt16D(System.ReadOnlySpan`1<System.Byte>,System.Int16&,System.Int32&)
TryParseInt32D(System.ReadOnlySpan`1<System.Byte>,System.Int32&,System.Int32&)
TryParseInt64D(System.ReadOnlySpan`1<System.Byte>,System.Int64&,System.Int32&)
TryParseSByteN(System.ReadOnlySpan`1<System.Byte>,System.SByte&,System.Int32&)
TryParseInt16N(System.ReadOnlySpan`1<System.Byte>,System.Int16&,System.Int32&)
TryParseInt32N(System.ReadOnlySpan`1<System.Byte>,System.Int32&,System.Int32&)
TryParseInt64N(System.ReadOnlySpan`1<System.Byte>,System.Int64&,System.Int32&)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.Byte&,System.Int32&,System.Char)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.UInt16&,System.Int32&,System.Char)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.UInt32&,System.Int32&,System.Char)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.UInt64&,System.Int32&,System.Char)
TryParseByteD(System.ReadOnlySpan`1<System.Byte>,System.Byte&,System.Int32&)
TryParseUInt16D(System.ReadOnlySpan`1<System.Byte>,System.UInt16&,System.Int32&)
TryParseUInt32D(System.ReadOnlySpan`1<System.Byte>,System.UInt32&,System.Int32&)
TryParseUInt64D(System.ReadOnlySpan`1<System.Byte>,System.UInt64&,System.Int32&)
TryParseByteN(System.ReadOnlySpan`1<System.Byte>,System.Byte&,System.Int32&)
TryParseUInt16N(System.ReadOnlySpan`1<System.Byte>,System.UInt16&,System.Int32&)
TryParseUInt32N(System.ReadOnlySpan`1<System.Byte>,System.UInt32&,System.Int32&)
TryParseUInt64N(System.ReadOnlySpan`1<System.Byte>,System.UInt64&,System.Int32&)
TryParseByteX(System.ReadOnlySpan`1<System.Byte>,System.Byte&,System.Int32&)
TryParseUInt16X(System.ReadOnlySpan`1<System.Byte>,System.UInt16&,System.Int32&)
TryParseUInt32X(System.ReadOnlySpan`1<System.Byte>,System.UInt32&,System.Int32&)
TryParseUInt64X(System.ReadOnlySpan`1<System.Byte>,System.UInt64&,System.Int32&)
TryParseNumber(System.ReadOnlySpan`1<System.Byte>,System.Number/NumberBuffer&,System.Int32&,System.Buffers.Text.Utf8Parser/ParseNumberOptions,System.Boolean&)
TryParseTimeSpanBigG(System.ReadOnlySpan`1<System.Byte>,System.TimeSpan&,System.Int32&)
TryParseTimeSpanC(System.ReadOnlySpan`1<System.Byte>,System.TimeSpan&,System.Int32&)
TryParse(System.ReadOnlySpan`1<System.Byte>,System.TimeSpan&,System.Int32&,System.Char)
TryParseTimeSpanFraction(System.ReadOnlySpan`1<System.Byte>,System.UInt32&,System.Int32&)
TryCreateTimeSpan(System.Boolean,System.UInt32,System.UInt32,System.UInt32,System.UInt32,System.UInt32,System.TimeSpan&)
TryParseTimeSpanLittleG(System.ReadOnlySpan`1<System.Byte>,System.TimeSpan&,System.Int32&)
TrySplitTimeSpan(System.ReadOnlySpan`1<System.Byte>,System.Boolean,System.Int32&)
ParseComponent(System.ReadOnlySpan`1<System.Byte>,System.Boolean,System.Int32&,System.UInt32&)