Summary

Class:System.Buffers.Text.Utf8Parser
Assembly:System.Memory
File(s):C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Boolean.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.Default.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.G.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.Helpers.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.O.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Date.R.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Decimal.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Float.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Guid.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Signed.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Signed.D.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Signed.N.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.D.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.N.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Integer.Unsigned.X.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.Number.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.BigG.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.C.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpan.LittleG.cs
C:\GitHub\corefx\src\System.Memory\src\System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpanSplitter.cs
Covered lines:2871
Uncovered lines:4
Coverable lines:2875
Total lines:4826
Line coverage:99.8%
Branch coverage:96.9%

Metrics

MethodCyclomatic complexity NPath complexity Sequence coverage Branch coverage
TryParse(...)2632100100
TryParse(...)12102410095.24
TryParse(...)732100100
TryParseDateTimeOffsetDefault(...)13512100100
TryParseDateTimeG(...)228192100100
TryCreateDateTimeOffset(...)616100100
TryCreateDateTimeOffset(...)34100100
TryCreateDateTimeOffsetInterpretingDataAsLocalTime(...)2271.43100
TryCreateDateTime(...)11128100100
.cctor()10100100
TryParseDateTimeOffsetO(...)458388608100100
TryParseDateTimeOffsetR(...)46210098.51
TryParse(...)13512100100
TryParse(...)34100100
TryParse(...)22100100
TryParseNormalAsFloatingPoint(...)1251210094.74
TryParseAsSpecialFloatingPoint(...)248100100
TryParse(...)732100100
TryParseGuidN(...)1264100100
TryParseGuidCore(...)22524288100100
TryParse(...)1351210078.95
TryParse(...)1351210078.95
TryParse(...)1351210078.95
TryParse(...)1351210078.95
TryParseSByteD(...)18131072100100
TryParseInt16D(...)222097152100100
TryParseInt32D(...)330100100
TryParseInt64D(...)2316384100100
TryParseSByteN(...)18131072100100
TryParseInt16N(...)18131072100100
TryParseInt32N(...)19262144100100
TryParseInt64N(...)19262144100100
TryParse(...)1351210078.95
TryParse(...)1351210078.95
TryParse(...)1351210078.95
TryParse(...)1351210078.95
TryParseByteD(...)148192100100
TryParseUInt16D(...)18131072100100
TryParseUInt32D(...)31134217728100100
TryParseUInt64D(...)141024100100
TryParseByteN(...)1632768100100
TryParseUInt16N(...)1632768100100
TryParseUInt32N(...)1932768100100
TryParseUInt64N(...)1932768100100
TryParseByteX(...)111024100100
TryParseUInt16X(...)111024100100
TryParseUInt32X(...)111024100100
TryParseUInt64X(...)111024100100
TryParseNumber(...)34268435456100100
TryParseTimeSpanBigG(...)2565536100100
TryParseTimeSpanC(...)1251210094.74
TryParse(...)86410076.92
TryParseTimeSpanFraction(...)13224100100
TryCreateTimeSpan(...)1364100100
TryParseTimeSpanLittleG(...)1025610094.12
TrySplitTimeSpan(...)2432768100100
ParseComponent(...)964100100

File(s)

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        /// <summary>
 10        /// Parses a Boolean at the start of a Utf8 string.
 11        /// </summary>
 12        /// <param name="text">The Utf8 string to parse</param>
 13        /// <param name="value">Receives the parsed value</param>
 14        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 15        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 16        /// <returns>
 17        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 18        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 19        /// </returns>
 20        /// <remarks>
 21        /// Formats supported:
 22        ///     G (default)   True/False
 23        ///     l             true/false
 24        /// </remarks>
 25        /// <exceptions>
 26        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 27        /// </exceptions>
 28        public static bool TryParse(ReadOnlySpan<byte> text, out bool value, out int bytesConsumed, char standardFormat 
 129        {
 130            if (!(standardFormat == default(char) || standardFormat == 'G' || standardFormat == 'l'))
 131                return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 32
 133            if (text.Length >= 4)
 134            {
 135                if ((text[0] == 'T' || text[0] == 't') &&
 136                    (text[1] == 'R' || text[1] == 'r') &&
 137                    (text[2] == 'U' || text[2] == 'u') &&
 138                    (text[3] == 'E' || text[3] == 'e'))
 139                {
 140                    bytesConsumed = 4;
 141                    value = true;
 142                    return true;
 43                }
 144                if (text.Length >= 5)
 145                {
 146                    if ((text[0] == 'F' || text[0] == 'f') &&
 147                        (text[1] == 'A' || text[1] == 'a') &&
 148                        (text[2] == 'L' || text[2] == 'l') &&
 149                        (text[3] == 'S' || text[3] == 's') &&
 150                        (text[4] == 'E' || text[4] == 'e'))
 151                    {
 152                        bytesConsumed = 5;
 153                        value = false;
 154                        return true;
 55                    }
 156                }
 157            }
 158            bytesConsumed = 0;
 159            value = default;
 160            return false;
 161        }
 62    }
 63}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5using System.Diagnostics;
 6
 7namespace System.Buffers.Text
 8{
 9    public static partial class Utf8Parser
 10    {
 11        /// <summary>
 12        /// Parses a DateTime at the start of a Utf8 string.
 13        /// </summary>
 14        /// <param name="text">The Utf8 string to parse</param>
 15        /// <param name="value">Receives the parsed value</param>
 16        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 17        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 18        /// <returns>
 19        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 20        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 21        /// </returns>
 22        /// <remarks>
 23        /// Formats supported:
 24        ///     default       05/25/2017 10:30:15 -08:00
 25        ///     G             05/25/2017 10:30:15
 26        ///     R             Tue, 03 Jan 2017 08:08:05 GMT       (RFC 1123)
 27        ///     l             tue, 03 jan 2017 08:08:05 gmt       (Lowercase RFC 1123)
 28        ///     O             2017-06-12T05:30:45.7680000-07:00   (Round-trippable)
 29        /// </remarks>
 30        /// <exceptions>
 31        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 32        /// </exceptions>
 33        public static bool TryParse(ReadOnlySpan<byte> text, out DateTime value, out int bytesConsumed, char standardFor
 134        {
 135            switch (standardFormat)
 36            {
 37                case 'R':
 138                    {
 139                        if (!TryParseDateTimeOffsetR(text, NoFlipCase, out DateTimeOffset dateTimeOffset, out bytesConsu
 140                        {
 141                            value = default;
 142                            return false;
 43                        }
 144                        value = dateTimeOffset.DateTime;  // (returns a DateTimeKind.Unspecified to match DateTime.Parse
 145                        return true;
 46                    }
 47
 48                case 'l':
 149                    {
 150                        if (!TryParseDateTimeOffsetR(text, FlipCase, out DateTimeOffset dateTimeOffset, out bytesConsume
 151                        {
 152                            value = default;
 153                            return false;
 54                        }
 155                        value = dateTimeOffset.DateTime;  // (returns a DateTimeKind.Unspecified to match DateTime.Parse
 156                        return true;
 57                    }
 58
 59                case 'O':
 160                    {
 61                        // Emulates DateTime.ParseExact(text, "O", CultureInfo.InvariantCulture, DateTimeStyles.Roundtri
 62                        // In particular, the formatted string "encodes" the DateTimeKind according to the following tab
 63                        //
 64                        //         2017-06-12T05:30:45.7680000       - Unspecified
 65                        //         2017-06-12T05:30:45.7680000+00:00 - Local
 66                        //         2017-06-12T05:30:45.7680000Z      - Utc
 67
 168                        if (!TryParseDateTimeOffsetO(text, out DateTimeOffset dateTimeOffset, out bytesConsumed, out Dat
 169                        {
 170                            value = default;
 171                            bytesConsumed = 0;
 172                            return false;
 73                        }
 74
 175                        switch (kind)
 76                        {
 77                            case DateTimeKind.Local:
 178                                value = dateTimeOffset.LocalDateTime;
 179                                break;
 80                            case DateTimeKind.Utc:
 181                                value = dateTimeOffset.UtcDateTime;
 182                                break;
 83                            default:
 184                                Debug.Assert(kind == DateTimeKind.Unspecified);
 185                                value = dateTimeOffset.DateTime;
 186                                break;
 87                        }
 88
 189                        return true;
 90                    }
 91
 92                case (default):
 93                case 'G':
 194                    return TryParseDateTimeG(text, out value, out _, out bytesConsumed);
 95
 96                default:
 197                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 98            }
 199        }
 100
 101        /// <summary>
 102        /// Parses a DateTimeOffset at the start of a Utf8 string.
 103        /// </summary>
 104        /// <param name="text">The Utf8 string to parse</param>
 105        /// <param name="value">Receives the parsed value</param>
 106        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 107        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 108        /// <returns>
 109        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 110        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 111        /// </returns>
 112        /// <remarks>
 113        /// Formats supported:
 114        ///     G  (default)  05/25/2017 10:30:15
 115        ///     R             Tue, 03 Jan 2017 08:08:05 GMT       (RFC 1123)
 116        ///     l             tue, 03 jan 2017 08:08:05 gmt       (Lowercase RFC 1123)
 117        ///     O             2017-06-12T05:30:45.7680000-07:00   (Round-trippable)
 118        /// </remarks>
 119        /// <exceptions>
 120        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 121        /// </exceptions>
 122        public static bool TryParse(ReadOnlySpan<byte> text, out DateTimeOffset value, out int bytesConsumed, char stand
 1123        {
 1124            switch (standardFormat)
 125            {
 126                case 'R':
 1127                    return TryParseDateTimeOffsetR(text, NoFlipCase, out value, out bytesConsumed);
 128
 129                case 'l':
 1130                    return TryParseDateTimeOffsetR(text, FlipCase, out value, out bytesConsumed);
 131
 132                case 'O':
 1133                    return TryParseDateTimeOffsetO(text, out value, out bytesConsumed, out _);
 134
 135                case (default):
 1136                    return TryParseDateTimeOffsetDefault(text, out value, out bytesConsumed);
 137
 138                case 'G':
 1139                    return TryParseDateTimeG(text, out DateTime _, out value, out bytesConsumed);
 140
 141                default:
 1142                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 143            }
 1144        }
 145
 146        private const uint FlipCase = 0x00000020u;  // XOR mask to flip the case of a letter.
 147        private const uint NoFlipCase = 0x00000000u;
 148    }
 149}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        //
 10        // ToString() format for DateTimeOffset. Does not have a corresponding format symbol but it
 11        // is the "G" format postpended with the UTC offset.
 12        //
 13        // 01234567890123456789012345
 14        // --------------------------
 15        // 05/25/2017 10:30:15 -08:00
 16        //
 17        private static bool TryParseDateTimeOffsetDefault(ReadOnlySpan<byte> text, out DateTimeOffset value, out int byt
 118        {
 119            if (text.Length < 26)
 120            {
 121                bytesConsumed = 0;
 122                value = default;
 123                return false;
 24            }
 25
 126            if (!TryParseDateTimeG(text, out DateTime dateTime, out _, out _))
 127            {
 128                bytesConsumed = 0;
 129                value = default;
 130                return false;
 31            }
 32
 133            if (text[19] != Utf8Constants.Space)
 134            {
 135                bytesConsumed = 0;
 136                value = default;
 137                return false;
 38            }
 39
 140            byte sign = text[20];
 141            if (sign != Utf8Constants.Plus && sign != Utf8Constants.Minus)
 142            {
 143                bytesConsumed = 0;
 144                value = default;
 145                return false;
 46            }
 47
 48            int offsetHours;
 149            {
 150                uint digit1 = text[21] - 48u; // '0'
 151                uint digit2 = text[22] - 48u; // '0'
 52
 153                if (digit1 > 9 || digit2 > 9)
 154                {
 155                    bytesConsumed = 0;
 156                    value = default;
 157                    return false;
 58                }
 59
 160                offsetHours = (int)(digit1 * 10 + digit2);
 161            }
 62
 163            if (text[23] != Utf8Constants.Colon)
 164            {
 165                bytesConsumed = 0;
 166                value = default;
 167                return false;
 68            }
 69
 70            int offsetMinutes;
 171            {
 172                uint digit1 = text[24] - 48u; // '0'
 173                uint digit2 = text[25] - 48u; // '0'
 74
 175                if (digit1 > 9 || digit2 > 9)
 176                {
 177                    bytesConsumed = 0;
 178                    value = default;
 179                    return false;
 80                }
 81
 182                offsetMinutes = (int)(digit1 * 10 + digit2);
 183            }
 84
 185            TimeSpan offset = new TimeSpan(hours: offsetHours, minutes: offsetMinutes, seconds: 0);
 186            if (sign == Utf8Constants.Minus)
 187            {
 188                offset = -offset;
 189            }
 90
 191            if (!TryCreateDateTimeOffset(dateTime: dateTime, offsetNegative: sign == Utf8Constants.Minus, offsetHours: o
 192            {
 193                bytesConsumed = 0;
 194                value = default;
 195                return false;
 96            }
 97
 198            bytesConsumed = 26;
 199            return true;
 1100        }
 101    }
 102}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5using System.Diagnostics;
 6
 7namespace System.Buffers.Text
 8{
 9    public static partial class Utf8Parser
 10    {
 11        //
 12        // 'G' format for DateTime.
 13        //
 14        //   0123456789012345678
 15        //   ---------------------------------
 16        //   05/25/2017 10:30:15
 17        //
 18        private static bool TryParseDateTimeG(ReadOnlySpan<byte> text, out DateTime value, out DateTimeOffset valueAsOff
 119        {
 120            if (text.Length < 19)
 121            {
 122                bytesConsumed = 0;
 123                value = default;
 124                valueAsOffset = default;
 125                return false;
 26            }
 27
 28            int month;
 129            {
 130                uint digit1 = text[0] - 48u; // '0'
 131                uint digit2 = text[1] - 48u; // '0'
 32
 133                if (digit1 > 9 || digit2 > 9)
 134                {
 135                    bytesConsumed = 0;
 136                    value = default;
 137                    valueAsOffset = default;
 138                    return false;
 39                }
 40
 141                month = (int)(digit1 * 10 + digit2);
 142            }
 43
 144            if (text[2] != Utf8Constants.Slash)
 145            {
 146                bytesConsumed = 0;
 147                value = default;
 148                valueAsOffset = default;
 149                return false;
 50            }
 51
 52            int day;
 153            {
 154                uint digit1 = text[3] - 48u; // '0'
 155                uint digit2 = text[4] - 48u; // '0'
 56
 157                if (digit1 > 9 || digit2 > 9)
 158                {
 159                    bytesConsumed = 0;
 160                    value = default;
 161                    valueAsOffset = default;
 162                    return false;
 63                }
 64
 165                day = (int)(digit1 * 10 + digit2);
 166            }
 67
 168            if (text[5] != Utf8Constants.Slash)
 169            {
 170                bytesConsumed = 0;
 171                value = default;
 172                valueAsOffset = default;
 173                return false;
 74            }
 75
 76            int year;
 177            {
 178                uint digit1 = text[6] - 48u; // '0'
 179                uint digit2 = text[7] - 48u; // '0'
 180                uint digit3 = text[8] - 48u; // '0'
 181                uint digit4 = text[9] - 48u; // '0'
 82
 183                if (digit1 > 9 || digit2 > 9 || digit3 > 9 || digit4 > 9)
 184                {
 185                    bytesConsumed = 0;
 186                    value = default;
 187                    valueAsOffset = default;
 188                    return false;
 89                }
 90
 191                year = (int)(digit1 * 1000 + digit2 * 100 + digit3 * 10 + digit4);
 192            }
 93
 194            if (text[10] != Utf8Constants.Space)
 195            {
 196                bytesConsumed = 0;
 197                value = default;
 198                valueAsOffset = default;
 199                return false;
 100            }
 101
 102            int hour;
 1103            {
 1104                uint digit1 = text[11] - 48u; // '0'
 1105                uint digit2 = text[12] - 48u; // '0'
 106
 1107                if (digit1 > 9 || digit2 > 9)
 1108                {
 1109                    bytesConsumed = 0;
 1110                    value = default;
 1111                    valueAsOffset = default;
 1112                    return false;
 113                }
 114
 1115                hour = (int)(digit1 * 10 + digit2);
 1116            }
 117
 1118            if (text[13] != Utf8Constants.Colon)
 1119            {
 1120                bytesConsumed = 0;
 1121                value = default;
 1122                valueAsOffset = default;
 1123                return false;
 124            }
 125
 126            int minute;
 1127            {
 1128                uint digit1 = text[14] - 48u; // '0'
 1129                uint digit2 = text[15] - 48u; // '0'
 130
 1131                if (digit1 > 9 || digit2 > 9)
 1132                {
 1133                    bytesConsumed = 0;
 1134                    value = default;
 1135                    valueAsOffset = default;
 1136                    return false;
 137                }
 138
 1139                minute = (int)(digit1 * 10 + digit2);
 1140            }
 141
 1142            if (text[16] != Utf8Constants.Colon)
 1143            {
 1144                bytesConsumed = 0;
 1145                value = default;
 1146                valueAsOffset = default;
 1147                return false;
 148            }
 149
 150            int second;
 1151            {
 1152                uint digit1 = text[17] - 48u; // '0'
 1153                uint digit2 = text[18] - 48u; // '0'
 154
 1155                if (digit1 > 9 || digit2 > 9)
 1156                {
 1157                    bytesConsumed = 0;
 1158                    value = default;
 1159                    valueAsOffset = default;
 1160                    return false;
 161                }
 162
 1163                second = (int)(digit1 * 10 + digit2);
 1164            }
 165
 1166            if (!TryCreateDateTimeOffsetInterpretingDataAsLocalTime(year: year, month: month, day: day, hour: hour, minu
 1167            {
 1168                bytesConsumed = 0;
 1169                value = default;
 1170                valueAsOffset = default;
 1171                return false;
 172            }
 173
 1174            bytesConsumed = 19;
 1175            value = valueAsOffset.DateTime;
 1176            return true;
 1177        }
 178    }
 179}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5using System.Diagnostics;
 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
 115        {
 116            if (((uint)offsetHours) > Utf8Constants.DateTimeMaxUtcOffsetHours)
 117            {
 118                value = default;
 119                return false;
 20            }
 21
 122            if (((uint)offsetMinutes) > 59)
 123            {
 124                value = default;
 125                return false;
 26            }
 27
 128            if (offsetHours == Utf8Constants.DateTimeMaxUtcOffsetHours && offsetMinutes != 0)
 129            {
 130                value = default;
 131                return false;
 32            }
 33
 134            long offsetTicks = (((long)offsetHours) * 3600 + ((long)offsetMinutes) * 60) * TimeSpan.TicksPerSecond;
 135            if (offsetNegative)
 136            {
 137                offsetTicks = -offsetTicks;
 138            }
 39
 40            try
 141            {
 142                value = new DateTimeOffset(ticks: dateTime.Ticks, offset: new TimeSpan(ticks: offsetTicks));
 143            }
 144            catch (ArgumentOutOfRangeException)
 145            {
 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
 148                value = default;
 149                return false;
 50            }
 51
 152            return true;
 153        }
 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 
 159        {
 160            if (!TryCreateDateTime(year: year, month: month, day: day, hour: hour, minute: minute, second: second, fract
 161            {
 162                value = default;
 163                return false;
 64            }
 65
 166            if (!TryCreateDateTimeOffset(dateTime: dateTime, offsetNegative: offsetNegative, offsetHours: offsetHours, o
 167            {
 168                value = default;
 169                return false;
 70            }
 71
 172            return true;
 173        }
 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
 179        {
 180            if (!TryCreateDateTime(year: year, month: month, day: day, hour: hour, minute: minute, second: second, fract
 181            {
 182                value = default;
 183                return false;
 84            }
 85
 86            try
 187            {
 188                value = new DateTimeOffset(dateTime);
 189            }
 090            catch (ArgumentOutOfRangeException)
 091            {
 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
 199            return true;
 1100        }
 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
 1106        {
 1107            if (year == 0)
 1108            {
 1109                value = default;
 1110                return false;
 111            }
 112
 1113            Debug.Assert(year <= 9999); // All of our callers to date parse the year from fixed 4-digit fields so this v
 114
 1115            if ((((uint)month) - 1) >= 12)
 1116            {
 1117                value = default;
 1118                return false;
 119            }
 120
 1121            uint dayMinusOne = ((uint)day) - 1;
 1122            if (dayMinusOne >= 28 && dayMinusOne >= DateTime.DaysInMonth(year, month))
 1123            {
 1124                value = default;
 1125                return false;
 126            }
 127
 1128            if (((uint)hour) > 23)
 1129            {
 1130                value = default;
 1131                return false;
 132            }
 133
 1134            if (((uint)minute) > 59)
 1135            {
 1136                value = default;
 1137                return false;
 138            }
 139
 1140            if (((uint)second) > 59)
 1141            {
 1142                value = default;
 1143                return false;
 144            }
 145
 1146            Debug.Assert(fraction >= 0 && fraction <= Utf8Constants.MaxDateTimeFraction); // All of our callers to date 
 147
 1148            int[] days = DateTime.IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365;
 1149            int yearMinusOne = year - 1;
 1150            int totalDays = (yearMinusOne * 365) + (yearMinusOne / 4) - (yearMinusOne / 100) + (yearMinusOne / 400) + da
 1151            long ticks = totalDays * TimeSpan.TicksPerDay;
 1152            int totalSeconds = (hour * 3600) + (minute * 60) + second;
 1153            ticks += totalSeconds * TimeSpan.TicksPerSecond;
 1154            ticks += fraction;
 1155            value = new DateTime(ticks: ticks, kind: kind);
 1156            return true;
 1157        }
 158
 1159        private static readonly int[] s_daysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
 1160        private static readonly int[] s_daysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
 161    }
 162}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5using System.Diagnostics;
 6
 7namespace System.Buffers.Text
 8{
 9    public static partial class Utf8Parser
 10    {
 11        //
 12        // Roundtrippable format. One of
 13        //
 14        //   012345678901234567890123456789012
 15        //   ---------------------------------
 16        //   2017-06-12T05:30:45.7680000-07:00
 17        //   2017-06-12T05:30:45.7680000Z           (Z is short for "+00:00" but also distinguishes DateTimeKind.Utc fro
 18        //   2017-06-12T05:30:45.7680000            (interpreted as local time wrt to current time zone)
 19        //
 20        private static bool TryParseDateTimeOffsetO(ReadOnlySpan<byte> text, out DateTimeOffset value, out int bytesCons
 121        {
 122            if (text.Length < 27)
 123            {
 124                value = default;
 125                bytesConsumed = 0;
 126                kind = default;
 127                return false;
 28            }
 29
 30            int year;
 131            {
 132                uint digit1 = text[0] - 48u; // '0'
 133                uint digit2 = text[1] - 48u; // '0'
 134                uint digit3 = text[2] - 48u; // '0'
 135                uint digit4 = text[3] - 48u; // '0'
 36
 137                if (digit1 > 9 || digit2 > 9 || digit3 > 9 || digit4 > 9)
 138                {
 139                    value = default;
 140                    bytesConsumed = 0;
 141                    kind = default;
 142                    return false;
 43                }
 44
 145                year = (int)(digit1 * 1000 + digit2 * 100 + digit3 * 10 + digit4);
 146            }
 47
 148            if (text[4] != Utf8Constants.Hyphen)
 149            {
 150                value = default;
 151                bytesConsumed = 0;
 152                kind = default;
 153                return false;
 54            }
 55
 56            int month;
 157            {
 158                uint digit1 = text[5] - 48u; // '0'
 159                uint digit2 = text[6] - 48u; // '0'
 60
 161                if (digit1 > 9 || digit2 > 9)
 162                {
 163                    value = default;
 164                    bytesConsumed = 0;
 165                    kind = default;
 166                    return false;
 67                }
 68
 169                month = (int)(digit1 * 10 + digit2);
 170            }
 71
 172            if (text[7] != Utf8Constants.Hyphen)
 173            {
 174                value = default;
 175                bytesConsumed = 0;
 176                kind = default;
 177                return false;
 78            }
 79
 80            int day;
 181            {
 182                uint digit1 = text[8] - 48u; // '0'
 183                uint digit2 = text[9] - 48u; // '0'
 84
 185                if (digit1 > 9 || digit2 > 9)
 186                {
 187                    value = default;
 188                    bytesConsumed = 0;
 189                    kind = default;
 190                    return false;
 91                }
 92
 193                day = (int)(digit1 * 10 + digit2);
 194            }
 95
 196            if (text[10] != 'T')
 197            {
 198                value = default;
 199                bytesConsumed = 0;
 1100                kind = default;
 1101                return false;
 102            }
 103
 104            int hour;
 1105            {
 1106                uint digit1 = text[11] - 48u; // '0'
 1107                uint digit2 = text[12] - 48u; // '0'
 108
 1109                if (digit1 > 9 || digit2 > 9)
 1110                {
 1111                    value = default;
 1112                    bytesConsumed = 0;
 1113                    kind = default;
 1114                    return false;
 115                }
 116
 1117                hour = (int)(digit1 * 10 + digit2);
 1118            }
 119
 1120            if (text[13] != Utf8Constants.Colon)
 1121            {
 1122                value = default;
 1123                bytesConsumed = 0;
 1124                kind = default;
 1125                return false;
 126            }
 127
 128            int minute;
 1129            {
 1130                uint digit1 = text[14] - 48u; // '0'
 1131                uint digit2 = text[15] - 48u; // '0'
 132
 1133                if (digit1 > 9 || digit2 > 9)
 1134                {
 1135                    value = default;
 1136                    bytesConsumed = 0;
 1137                    kind = default;
 1138                    return false;
 139                }
 140
 1141                minute = (int)(digit1 * 10 + digit2);
 1142            }
 143
 1144            if (text[16] != Utf8Constants.Colon)
 1145            {
 1146                value = default;
 1147                bytesConsumed = 0;
 1148                kind = default;
 1149                return false;
 150            }
 151
 152            int second;
 1153            {
 1154                uint digit1 = text[17] - 48u; // '0'
 1155                uint digit2 = text[18] - 48u; // '0'
 156
 1157                if (digit1 > 9 || digit2 > 9)
 1158                {
 1159                    value = default;
 1160                    bytesConsumed = 0;
 1161                    kind = default;
 1162                    return false;
 163                }
 164
 1165                second = (int)(digit1 * 10 + digit2);
 1166            }
 167
 1168            if (text[19] != Utf8Constants.Period)
 1169            {
 1170                value = default;
 1171                bytesConsumed = 0;
 1172                kind = default;
 1173                return false;
 174            }
 175
 176            int fraction;
 1177            {
 1178                uint digit1 = text[20] - 48u; // '0'
 1179                uint digit2 = text[21] - 48u; // '0'
 1180                uint digit3 = text[22] - 48u; // '0'
 1181                uint digit4 = text[23] - 48u; // '0'
 1182                uint digit5 = text[24] - 48u; // '0'
 1183                uint digit6 = text[25] - 48u; // '0'
 1184                uint digit7 = text[26] - 48u; // '0'
 185
 1186                if (digit1 > 9 || digit2 > 9 || digit3 > 9 || digit4 > 9 || digit5 > 9 || digit6 > 9 || digit7 > 9)
 1187                {
 1188                    value = default;
 1189                    bytesConsumed = 0;
 1190                    kind = default;
 1191                    return false;
 192                }
 193
 1194                fraction = (int)(digit1 * 1000000 + digit2 * 100000 + digit3 * 10000 + digit4 * 1000 + digit5 * 100 + di
 1195            }
 196
 1197            byte offsetChar = (text.Length <= 27) ? default : text[27];
 1198            if (offsetChar != 'Z' && offsetChar != Utf8Constants.Plus && offsetChar != Utf8Constants.Minus)
 1199            {
 1200                if (!TryCreateDateTimeOffsetInterpretingDataAsLocalTime(year: year, month: month, day: day, hour: hour, 
 1201                {
 1202                    value = default;
 1203                    bytesConsumed = 0;
 1204                    kind = default;
 1205                    return false;
 206                }
 1207                bytesConsumed = 27;
 1208                kind = DateTimeKind.Unspecified;
 1209                return true;
 210            }
 211
 1212            if (offsetChar == 'Z')
 1213            {
 214                // Same as specifying an offset of "+00:00", except that DateTime's Kind gets set to UTC rather than Loc
 1215                if (!TryCreateDateTimeOffset(year: year, month: month, day: day, hour: hour, minute: minute, second: sec
 1216                {
 1217                    value = default;
 1218                    bytesConsumed = 0;
 1219                    kind = default;
 1220                    return false;
 221                }
 222
 1223                bytesConsumed = 28;
 1224                kind = DateTimeKind.Utc;
 1225                return true;
 226            }
 227
 1228            Debug.Assert(offsetChar == Utf8Constants.Plus || offsetChar == Utf8Constants.Minus);
 1229            if (text.Length < 33)
 1230            {
 1231                value = default;
 1232                bytesConsumed = 0;
 1233                kind = default;
 1234                return false;
 235            }
 236
 237            int offsetHours;
 1238            {
 1239                uint digit1 = text[28] - 48u; // '0'
 1240                uint digit2 = text[29] - 48u; // '0'
 241
 1242                if (digit1 > 9 || digit2 > 9)
 1243                {
 1244                    value = default;
 1245                    bytesConsumed = 0;
 1246                    kind = default;
 1247                    return false;
 248                }
 249
 1250                offsetHours = (int)(digit1 * 10 + digit2);
 1251            }
 252
 1253            if (text[30] != Utf8Constants.Colon)
 1254            {
 1255                value = default;
 1256                bytesConsumed = 0;
 1257                kind = default;
 1258                return false;
 259            }
 260
 261            int offsetMinutes;
 1262            {
 1263                uint digit1 = text[31] - 48u; // '0'
 1264                uint digit2 = text[32] - 48u; // '0'
 265
 1266                if (digit1 > 9 || digit2 > 9)
 1267                {
 1268                    value = default;
 1269                    bytesConsumed = 0;
 1270                    kind = default;
 1271                    return false;
 272                }
 273
 1274                offsetMinutes = (int)(digit1 * 10 + digit2);
 1275            }
 276
 1277            if (!TryCreateDateTimeOffset(year: year, month: month, day: day, hour: hour, minute: minute, second: second,
 1278            {
 1279                value = default;
 1280                bytesConsumed = 0;
 1281                kind = default;
 1282                return false;
 283            }
 284
 1285            bytesConsumed = 33;
 1286            kind = DateTimeKind.Local;
 1287            return true;
 1288        }
 289    }
 290}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        //
 10        // Parse an RFC1123 date string.
 11        //
 12        // 01234567890123456789012345678
 13        // -----------------------------
 14        // Tue, 03 Jan 2017 08:08:05 GMT
 15        //
 16        private static bool TryParseDateTimeOffsetR(ReadOnlySpan<byte> text, uint caseFlipXorMask, out DateTimeOffset da
 117        {
 118            if (text.Length < 29)
 119            {
 120                bytesConsumed = 0;
 121                dateTimeOffset = default;
 122                return false;
 23            }
 24
 25            DayOfWeek dayOfWeek;
 126            {
 127                uint dow0 = text[0] ^ caseFlipXorMask;
 128                uint dow1 = text[1];
 129                uint dow2 = text[2];
 130                uint comma = text[3];
 131                uint dowString = (dow0 << 24) | (dow1 << 16) | (dow2 << 8) | comma;
 132                switch (dowString)
 33                {
 234                    case 0x53756E2c /* 'Sun,' */: dayOfWeek = DayOfWeek.Sunday; break;
 235                    case 0x4d6f6e2c /* 'Mon,' */: dayOfWeek = DayOfWeek.Monday; break;
 236                    case 0x5475652c /* 'Tue,' */: dayOfWeek = DayOfWeek.Tuesday; break;
 237                    case 0x5765642c /* 'Wed,' */: dayOfWeek = DayOfWeek.Wednesday; break;
 238                    case 0x5468752c /* 'Thu,' */: dayOfWeek = DayOfWeek.Thursday; break;
 239                    case 0x4672692c /* 'Fri,' */: dayOfWeek = DayOfWeek.Friday; break;
 240                    case 0x5361742c /* 'Sat,' */: dayOfWeek = DayOfWeek.Saturday; break;
 41                    default:
 142                        bytesConsumed = 0;
 143                        dateTimeOffset = default;
 144                        return false;
 45                }
 146            }
 47
 148            if (text[4] != Utf8Constants.Space)
 149            {
 150                bytesConsumed = 0;
 151                dateTimeOffset = default;
 152                return false;
 53            }
 54
 55            int day;
 156            {
 157                uint digit1 = text[5] - 48u; // '0'
 158                uint digit2 = text[6] - 48u; // '0'
 59
 160                if (digit1 > 9 || digit2 > 9)
 161                {
 162                    bytesConsumed = 0;
 163                    dateTimeOffset = default;
 164                    return false;
 65                }
 66
 167                day = (int)(digit1 * 10 + digit2);
 168            }
 69
 170            if (text[7] != Utf8Constants.Space)
 171            {
 172                bytesConsumed = 0;
 173                dateTimeOffset = default;
 174                return false;
 75            }
 76
 77            int month;
 178            {
 179                uint mon0 = text[8] ^ caseFlipXorMask;
 180                uint mon1 = text[9];
 181                uint mon2 = text[10];
 182                uint space = text[11];
 183                uint monthString = (mon0 << 24) | (mon1 << 16) | (mon2 << 8) | space;
 184                switch (monthString)
 85                {
 286                    case 0x4a616e20 /* 'Jan ' */ : month = 1; break;
 287                    case 0x46656220 /* 'Feb ' */ : month = 2; break;
 288                    case 0x4d617220 /* 'Mar ' */ : month = 3; break;
 289                    case 0x41707220 /* 'Apr ' */ : month = 4; break;
 290                    case 0x4d617920 /* 'May ' */ : month = 5; break;
 291                    case 0x4a756e20 /* 'Jun ' */ : month = 6; break;
 292                    case 0x4a756c20 /* 'Jul ' */ : month = 7; break;
 293                    case 0x41756720 /* 'Aug ' */ : month = 8; break;
 294                    case 0x53657020 /* 'Sep ' */ : month = 9; break;
 295                    case 0x4f637420 /* 'Oct ' */ : month = 10; break;
 296                    case 0x4e6f7620 /* 'Nov ' */ : month = 11; break;
 297                    case 0x44656320 /* 'Dec ' */ : month = 12; break;
 98                    default:
 199                        bytesConsumed = 0;
 1100                        dateTimeOffset = default;
 1101                        return false;
 102                }
 1103            }
 104
 105            int year;
 1106            {
 1107                uint digit1 = text[12] - 48u; // '0'
 1108                uint digit2 = text[13] - 48u; // '0'
 1109                uint digit3 = text[14] - 48u; // '0'
 1110                uint digit4 = text[15] - 48u; // '0'
 111
 1112                if (digit1 > 9 || digit2 > 9 || digit3 > 9 || digit4 > 9)
 1113                {
 1114                    bytesConsumed = 0;
 1115                    dateTimeOffset = default;
 1116                    return false;
 117                }
 118
 1119                year = (int)(digit1 * 1000 + digit2 * 100 + digit3 * 10 + digit4);
 1120            }
 121
 1122            if (text[16] != Utf8Constants.Space)
 1123            {
 1124                bytesConsumed = 0;
 1125                dateTimeOffset = default;
 1126                return false;
 127            }
 128
 129            int hour;
 1130            {
 1131                uint digit1 = text[17] - 48u; // '0'
 1132                uint digit2 = text[18] - 48u; // '0'
 133
 1134                if (digit1 > 9 || digit2 > 9)
 1135                {
 1136                    bytesConsumed = 0;
 1137                    dateTimeOffset = default;
 1138                    return false;
 139                }
 140
 1141                hour = (int)(digit1 * 10 + digit2);
 1142            }
 143
 1144            if (text[19] != Utf8Constants.Colon)
 1145            {
 1146                bytesConsumed = 0;
 1147                dateTimeOffset = default;
 1148                return false;
 149            }
 150
 151            int minute;
 1152            {
 1153                uint digit1 = text[20] - 48u; // '0'
 1154                uint digit2 = text[21] - 48u; // '0'
 155
 1156                if (digit1 > 9 || digit2 > 9)
 1157                {
 1158                    bytesConsumed = 0;
 1159                    dateTimeOffset = default;
 1160                    return false;
 161                }
 162
 1163                minute = (int)(digit1 * 10 + digit2);
 1164            }
 165
 1166            if (text[22] != Utf8Constants.Colon)
 1167            {
 1168                bytesConsumed = 0;
 1169                dateTimeOffset = default;
 1170                return false;
 171            }
 172
 173            int second;
 1174            {
 1175                uint digit1 = text[23] - 48u; // '0'
 1176                uint digit2 = text[24] - 48u; // '0'
 177
 1178                if (digit1 > 9 || digit2 > 9)
 1179                {
 1180                    bytesConsumed = 0;
 1181                    dateTimeOffset = default;
 1182                    return false;
 183                }
 184
 1185                second = (int)(digit1 * 10 + digit2);
 1186            }
 187
 1188            {
 1189                uint space = text[25];
 1190                uint g = text[26] ^ caseFlipXorMask;
 1191                uint m = text[27] ^ caseFlipXorMask;
 1192                uint t = text[28] ^ caseFlipXorMask;
 1193                uint gmtString = (space << 24) | (g << 16) | (m << 8) | t;
 1194                if (gmtString != 0x20474d54 /* ' GMT' */)
 1195                {
 1196                    bytesConsumed = 0;
 1197                    dateTimeOffset = default;
 1198                    return false;
 199                }
 1200            }
 201
 1202            if (!TryCreateDateTimeOffset(year: year, month: month, day: day, hour: hour, minute: minute, second: second,
 1203            {
 1204                bytesConsumed = 0;
 1205                dateTimeOffset = default;
 1206                return false;
 207            }
 208
 1209            if (dayOfWeek != dateTimeOffset.DayOfWeek)
 1210            {
 211                // If we got here, the day of week did not match the actual date.
 1212                bytesConsumed = 0;
 1213                dateTimeOffset = default;
 1214                return false;
 215            }
 216
 1217            bytesConsumed = 29;
 1218            return true;
 1219        }
 220    }
 221}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        /// <summary>
 10        /// Parses a Decimal at the start of a Utf8 string.
 11        /// </summary>
 12        /// <param name="text">The Utf8 string to parse</param>
 13        /// <param name="value">Receives the parsed value</param>
 14        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 15        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 16        /// <returns>
 17        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 18        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 19        /// </returns>
 20        /// <remarks>
 21        /// Formats supported:
 22        ///     G/g  (default)
 23        ///     F/f             12.45       Fixed point
 24        ///     E/e             1.245000e1  Exponential
 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> text, out decimal value, out int bytesConsumed, char standardForm
 130        {
 31            ParseNumberOptions options;
 132            switch (standardFormat)
 33            {
 34                case (default):
 35                case 'G':
 36                case 'g':
 37                case 'E':
 38                case 'e':
 139                    options = ParseNumberOptions.AllowExponent;
 140                    break;
 41
 42                case 'F':
 43                case 'f':
 144                    options = default;
 145                    break;
 46
 47                default:
 148                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 49            }
 50
 151            NumberBuffer number = default;
 152            if (!TryParseNumber(text, ref number, out bytesConsumed, options, out bool textUsedExponentNotation))
 153            {
 154                value = default;
 155                return false;
 56            }
 57
 158            if ((!textUsedExponentNotation) && (standardFormat == 'E' || standardFormat == 'e'))
 159            {
 160                value = default;
 161                bytesConsumed = 0;
 162                return false;
 63            }
 64
 65            // More compat with .NET behavior - whether or not a 0 keeps the negative sign depends on whether it an "int
 166            if (number.Digits[0] == 0 && number.Scale == 0)
 167            {
 168                number.IsNegative = false;
 169            }
 70
 171            value = default;
 172            if (!Number.NumberBufferToDecimal(ref number, ref value))
 173            {
 174                value = default;
 175                bytesConsumed = 0;
 176                return false;
 77            }
 78
 179            return true;
 180        }
 81    }
 82}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        /// <summary>
 10        /// Parses a Single at the start of a Utf8 string.
 11        /// </summary>
 12        /// <param name="text">The Utf8 string to parse</param>
 13        /// <param name="value">Receives the parsed value</param>
 14        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 15        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 16        /// <returns>
 17        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 18        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 19        /// </returns>
 20        /// <remarks>
 21        /// Formats supported:
 22        ///     G/g  (default)
 23        ///     F/f             12.45       Fixed point
 24        ///     E/e             1.245000e1  Exponential
 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> text, out float value, out int bytesConsumed, char standardFormat
 130        {
 131            if (TryParseNormalAsFloatingPoint(text, out double d, out bytesConsumed, standardFormat))
 132            {
 133                value = (float)d;
 134                if (float.IsInfinity(value))
 135                {
 136                    value = default;
 137                    bytesConsumed = 0;
 138                    return false;
 39                }
 140                return true;
 41            }
 42
 143            return TryParseAsSpecialFloatingPoint<float>(text, float.PositiveInfinity, float.NegativeInfinity, float.NaN
 144        }
 45
 46        /// <summary>
 47        /// Parses a Double at the start of a Utf8 string.
 48        /// </summary>
 49        /// <param name="text">The Utf8 string to parse</param>
 50        /// <param name="value">Receives the parsed value</param>
 51        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 52        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 53        /// <returns>
 54        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 55        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 56        /// </returns>
 57        /// <remarks>
 58        /// Formats supported:
 59        ///     G/g  (default)
 60        ///     F/f             12.45       Fixed point
 61        ///     E/e             1.245000e1  Exponential
 62        /// </remarks>
 63        /// <exceptions>
 64        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 65        /// </exceptions>
 66        public static bool TryParse(ReadOnlySpan<byte> text, out double value, out int bytesConsumed, char standardForma
 167        {
 168            if (TryParseNormalAsFloatingPoint(text, out value, out bytesConsumed, standardFormat))
 169                return true;
 70
 171            return TryParseAsSpecialFloatingPoint<double>(text, double.PositiveInfinity, double.NegativeInfinity, double
 172        }
 73
 74        //
 75        // Attempt to parse the regular floating points (the ones without names like "Infinity" and "NaN")
 76        //
 77        private static bool TryParseNormalAsFloatingPoint(ReadOnlySpan<byte> text, out double value, out int bytesConsum
 178        {
 79            ParseNumberOptions options;
 180            switch (standardFormat)
 81            {
 82                case (default):
 83                case 'G':
 84                case 'g':
 85                case 'E':
 86                case 'e':
 187                    options = ParseNumberOptions.AllowExponent;
 188                    break;
 89
 90                case 'F':
 91                case 'f':
 192                    options = default;
 193                    break;
 94
 95                default:
 196                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 97            }
 98
 199            NumberBuffer number = default;
 1100            if (!TryParseNumber(text, ref number, out bytesConsumed, options, out bool textUsedExponentNotation))
 1101            {
 1102                value = default;
 1103                return false;
 104            }
 105
 1106            if ((!textUsedExponentNotation) && (standardFormat == 'E' || standardFormat == 'e'))
 1107            {
 1108                value = default;
 1109                bytesConsumed = 0;
 1110                return false;
 111            }
 112
 1113            if (number.Digits[0] == 0)
 1114            {
 1115                number.IsNegative = false;
 1116            }
 117
 1118            if (!Number.NumberBufferToDouble(ref number, out value))
 1119            {
 1120                value = default;
 1121                bytesConsumed = 0;
 1122                return false;
 123            }
 124
 1125            return true;
 1126        }
 127
 128        //
 129        // Assuming the text doesn't look like a normal floating point, we attempt to parse it as one the special floati
 130        //
 131        private static bool TryParseAsSpecialFloatingPoint<T>(ReadOnlySpan<byte> text, T positiveInfinity, T negativeInf
 1132        {
 1133            if (text.Length >= 8 &&
 1134                text[0] == 'I' && text[1] == 'n' && text[2] == 'f' && text[3] == 'i' &&
 1135                text[4] == 'n' && text[5] == 'i' && text[6] == 't' && text[7] == 'y')
 1136            {
 1137                value = positiveInfinity;
 1138                bytesConsumed = 8;
 1139                return true;
 140            }
 141
 1142            if (text.Length >= 9 &&
 1143                text[0] == Utf8Constants.Minus &&
 1144                text[1] == 'I' && text[2] == 'n' && text[3] == 'f' && text[4] == 'i' &&
 1145                text[5] == 'n' && text[6] == 'i' && text[7] == 't' && text[8] == 'y')
 1146            {
 1147                value = negativeInfinity;
 1148                bytesConsumed = 9;
 1149                return true;
 150            }
 151
 1152            if (text.Length >= 3 &&
 1153                text[0] == 'N' && text[1] == 'a' && text[2] == 'N')
 1154            {
 1155                value = nan;
 1156                bytesConsumed = 3;
 1157                return true;
 158            }
 159
 1160            value = default;
 1161            bytesConsumed = 0;
 1162            return false;
 1163        }
 164    }
 165}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        /// <summary>
 10        /// Parses a Guid at the start of a Utf8 string.
 11        /// </summary>
 12        /// <param name="text">The Utf8 string to parse</param>
 13        /// <param name="value">Receives the parsed value</param>
 14        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 15        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 16        /// <returns>
 17        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 18        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 19        /// </returns>
 20        /// <remarks>
 21        /// Formats supported:
 22        ///     D (default)     nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn
 23        ///     B               {nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn}
 24        ///     P               (nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn)
 25        ///     N               nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
 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> text, out Guid value, out int bytesConsumed, char standardFormat 
 131        {
 132            switch (standardFormat)
 33            {
 34                case (default):
 35                case 'D':
 136                    return TryParseGuidCore(text, false, ' ', ' ', out value, out bytesConsumed);
 37                case 'B':
 138                    return TryParseGuidCore(text, true, '{', '}', out value, out bytesConsumed);
 39                case 'P':
 140                    return TryParseGuidCore(text, true, '(', ')', out value, out bytesConsumed);
 41                case 'N':
 142                    return TryParseGuidN(text, out value, out bytesConsumed);
 43                default:
 144                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 45            }
 146        }
 47
 48        // nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn (not very Guid-like, but the format is what it is...)
 49        private static bool TryParseGuidN(ReadOnlySpan<byte> text, out Guid value, out int bytesConsumed)
 150        {
 151            if (text.Length < 32)
 152            {
 153                value = default;
 154                bytesConsumed = 0;
 155                return false;
 56            }
 57
 158            if (!TryParseUInt32X(text.Slice(0, 8), out uint i1, out int justConsumed) || justConsumed != 8)
 159            {
 160                value = default;
 161                bytesConsumed = 0;
 162                return false; // 8 digits
 63            }
 64
 165            if (!TryParseUInt16X(text.Slice(8, 4), out ushort i2, out justConsumed) || justConsumed != 4)
 166            {
 167                value = default;
 168                bytesConsumed = 0;
 169                return false; // next 4 digits
 70            }
 71
 172            if (!TryParseUInt16X(text.Slice(12, 4), out ushort i3, out justConsumed) || justConsumed != 4)
 173            {
 174                value = default;
 175                bytesConsumed = 0;
 176                return false; // next 4 digits
 77            }
 78
 179            if (!TryParseUInt16X(text.Slice(16, 4), out ushort i4, out justConsumed) || justConsumed != 4)
 180            {
 181                value = default;
 182                bytesConsumed = 0;
 183                return false; // next 4 digits
 84            }
 85
 186            if (!TryParseUInt64X(text.Slice(20), out ulong i5, out justConsumed) || justConsumed != 12)
 187            {
 188                value = default;
 189                bytesConsumed = 0;
 190                return false; // next 4 digits
 91            }
 92
 193            bytesConsumed = 32;
 194            value = new Guid((int)i1, (short)i2, (short)i3, (byte)(i4 >> 8), (byte)i4,
 195                (byte)(i5 >> 40), (byte)(i5 >> 32), (byte)(i5 >> 24), (byte)(i5 >> 16), (byte)(i5 >> 8), (byte)i5);
 196            return true;
 197        }
 98
 99        // {8-4-4-4-12}, where number is the number of hex digits, and {/} are ends.
 100        private static bool TryParseGuidCore(ReadOnlySpan<byte> text, bool ends, char begin, char end, out Guid value, o
 1101        {
 1102            int expectedCodingUnits = 36 + (ends ? 2 : 0); // 32 hex digits + 4 delimiters + 2 optional ends
 103
 1104            if (text.Length < expectedCodingUnits)
 1105            {
 1106                value = default;
 1107                bytesConsumed = 0;
 1108                return false;
 109            }
 110
 1111            if (ends)
 1112            {
 1113                if (text[0] != begin)
 1114                {
 1115                    value = default;
 1116                    bytesConsumed = 0;
 1117                    return false;
 118                }
 119
 1120                text = text.Slice(1); // skip begining
 1121            }
 122
 1123            if (!TryParseUInt32X(text, out uint i1, out int justConsumed))
 1124            {
 1125                value = default;
 1126                bytesConsumed = 0;
 1127                return false;
 128            }
 129
 1130            if (justConsumed != 8)
 1131            {
 1132                value = default;
 1133                bytesConsumed = 0;
 1134                return false; // 8 digits
 135            }
 136
 1137            if (text[justConsumed] != '-')
 1138            {
 1139                value = default;
 1140                bytesConsumed = 0;
 1141                return false;
 142            }
 143
 1144            text = text.Slice(9); // justConsumed + 1 for delimiter
 145
 1146            if (!TryParseUInt16X(text, out ushort i2, out justConsumed))
 1147            {
 1148                value = default;
 1149                bytesConsumed = 0;
 1150                return false;
 151            }
 152
 1153            if (justConsumed != 4)
 1154            {
 1155                value = default;
 1156                bytesConsumed = 0;
 1157                return false; // 4 digits
 158            }
 159
 1160            if (text[justConsumed] != '-')
 1161            {
 1162                value = default;
 1163                bytesConsumed = 0;
 1164                return false;
 165            }
 166
 1167            text = text.Slice(5); // justConsumed + 1 for delimiter
 168
 1169            if (!TryParseUInt16X(text, out ushort i3, out justConsumed))
 1170            {
 1171                value = default;
 1172                bytesConsumed = 0;
 1173                return false;
 174            }
 175
 1176            if (justConsumed != 4)
 1177            {
 1178                value = default;
 1179                bytesConsumed = 0;
 1180                return false; // 4 digits
 181            }
 182
 1183            if (text[justConsumed] != '-')
 1184            {
 1185                value = default;
 1186                bytesConsumed = 0;
 1187                return false;
 188            }
 189
 1190            text = text.Slice(5); // justConsumed + 1 for delimiter
 191
 1192            if (!TryParseUInt16X(text, out ushort i4, out justConsumed))
 1193            {
 1194                value = default;
 1195                bytesConsumed = 0;
 1196                return false;
 197            }
 198
 1199            if (justConsumed != 4)
 1200            {
 1201                value = default;
 1202                bytesConsumed = 0;
 1203                return false; // 4 digits
 204            }
 205
 1206            if (text[justConsumed] != '-')
 1207            {
 1208                value = default;
 1209                bytesConsumed = 0;
 1210                return false;
 211            }
 212
 1213            text = text.Slice(5);// justConsumed + 1 for delimiter
 214
 1215            if (!TryParseUInt64X(text, out ulong i5, out justConsumed))
 1216            {
 1217                value = default;
 1218                bytesConsumed = 0;
 1219                return false;
 220            }
 221
 1222            if (justConsumed != 12)
 1223            {
 1224                value = default;
 1225                bytesConsumed = 0;
 1226                return false; // 12 digits
 227            }
 228
 1229            if (ends && text[justConsumed] != end)
 1230            {
 1231                value = default;
 1232                bytesConsumed = 0;
 1233                return false;
 234            }
 235
 1236            bytesConsumed = expectedCodingUnits;
 1237            value = new Guid((int)i1, (short)i2, (short)i3, (byte)(i4 >> 8), (byte)i4,
 1238                (byte)(i5 >> 40), (byte)(i5 >> 32), (byte)(i5 >> 24), (byte)(i5 >> 16), (byte)(i5 >> 8), (byte)i5);
 239
 1240            return true;
 1241        }
 242    }
 243}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5#if !netstandard
 6using Internal.Runtime.CompilerServices;
 7#else
 8using System.Runtime.CompilerServices;
 9#endif
 10
 11namespace System.Buffers.Text
 12{
 13    /// <summary>
 14    /// Methods to parse common data types to Utf8 strings.
 15    /// </summary>
 16    public static partial class Utf8Parser
 17    {
 18        /// <summary>
 19        /// Parses a SByte at the start of a Utf8 string.
 20        /// </summary>
 21        /// <param name="text">The Utf8 string to parse</param>
 22        /// <param name="value">Receives the parsed value</param>
 23        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 24        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 25        /// <returns>
 26        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 27        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 28        /// </returns>
 29        /// <remarks>
 30        /// Formats supported:
 31        ///     G/g (default)
 32        ///     D/d             32767
 33        ///     N/n             32,767
 34        ///     X/x             7fff
 35        /// </remarks>
 36        /// <exceptions>
 37        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 38        /// </exceptions>
 39        [CLSCompliant(false)]
 40        public static bool TryParse(ReadOnlySpan<byte> text, out sbyte value, out int bytesConsumed, char standardFormat
 141        {
 142            switch (standardFormat)
 43            {
 44                case (default):
 45                case 'g':
 46                case 'G':
 47                case 'd':
 48                case 'D':
 149                    return TryParseSByteD(text, out value, out bytesConsumed);
 50
 51                case 'n':
 52                case 'N':
 153                    return TryParseSByteN(text, out value, out bytesConsumed);
 54
 55                case 'x':
 56                case 'X':
 157                    value = default;
 158                    return TryParseByteX(text, out Unsafe.As<sbyte, byte>(ref value), out bytesConsumed);
 59
 60                default:
 161                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 62            }
 163        }
 64
 65        /// <summary>
 66        /// Parses an Int16 at the start of a Utf8 string.
 67        /// </summary>
 68        /// <param name="text">The Utf8 string to parse</param>
 69        /// <param name="value">Receives the parsed value</param>
 70        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 71        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 72        /// <returns>
 73        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 74        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 75        /// </returns>
 76        /// <remarks>
 77        /// Formats supported:
 78        ///     G/g (default)
 79        ///     D/d             32767
 80        ///     N/n             32,767
 81        ///     X/x             7fff
 82        /// </remarks>
 83        /// <exceptions>
 84        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 85        /// </exceptions>
 86        public static bool TryParse(ReadOnlySpan<byte> text, out short value, out int bytesConsumed, char standardFormat
 187        {
 188            switch (standardFormat)
 89            {
 90                case (default):
 91                case 'g':
 92                case 'G':
 93                case 'd':
 94                case 'D':
 195                    return TryParseInt16D(text, out value, out bytesConsumed);
 96
 97                case 'n':
 98                case 'N':
 199                    return TryParseInt16N(text, out value, out bytesConsumed);
 100
 101                case 'x':
 102                case 'X':
 1103                    value = default;
 1104                    return TryParseUInt16X(text, out Unsafe.As<short, ushort>(ref value), out bytesConsumed);
 105
 106                default:
 1107                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 108            }
 1109        }
 110
 111        /// <summary>
 112        /// Parses an Int32 at the start of a Utf8 string.
 113        /// </summary>
 114        /// <param name="text">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        public static bool TryParse(ReadOnlySpan<byte> text, out int value, out int bytesConsumed, char standardFormat =
 1133        {
 1134            switch (standardFormat)
 135            {
 136                case (default):
 137                case 'g':
 138                case 'G':
 139                case 'd':
 140                case 'D':
 1141                    return TryParseInt32D(text, out value, out bytesConsumed);
 142
 143                case 'n':
 144                case 'N':
 1145                    return TryParseInt32N(text, out value, out bytesConsumed);
 146
 147                case 'x':
 148                case 'X':
 1149                    value = default;
 1150                    return TryParseUInt32X(text, out Unsafe.As<int, uint>(ref value), out bytesConsumed);
 151
 152                default:
 1153                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 154            }
 1155        }
 156
 157        /// <summary>
 158        /// Parses an Int64 at the start of a Utf8 string.
 159        /// </summary>
 160        /// <param name="text">The Utf8 string to parse</param>
 161        /// <param name="value">Receives the parsed value</param>
 162        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 163        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 164        /// <returns>
 165        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 166        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 167        /// </returns>
 168        /// <remarks>
 169        /// Formats supported:
 170        ///     G/g (default)
 171        ///     D/d             32767
 172        ///     N/n             32,767
 173        ///     X/x             7fff
 174        /// </remarks>
 175        /// <exceptions>
 176        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 177        /// </exceptions>
 178        public static bool TryParse(ReadOnlySpan<byte> text, out long value, out int bytesConsumed, char standardFormat 
 1179        {
 1180            switch (standardFormat)
 181            {
 182                case (default):
 183                case 'g':
 184                case 'G':
 185                case 'd':
 186                case 'D':
 1187                    return TryParseInt64D(text, out value, out bytesConsumed);
 188
 189                case 'n':
 190                case 'N':
 1191                    return TryParseInt64N(text, out value, out bytesConsumed);
 192
 193                case 'x':
 194                case 'X':
 1195                    value = default;
 1196                    return TryParseUInt64X(text, out Unsafe.As<long, ulong>(ref value), out bytesConsumed);
 197
 198                default:
 1199                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 200            }
 1201        }
 202    }
 203}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        private static bool TryParseSByteD(ReadOnlySpan<byte> text, out sbyte value, out int bytesConsumed)
 110        {
 111            if (text.Length < 1)
 112                goto FalseExit;
 13
 114            int sign = 1;
 115            int index = 0;
 116            int num = text[index];
 117            if (num == '-')
 118            {
 119                sign = -1;
 120                index++;
 121                if ((uint)index >= (uint)text.Length)
 122                    goto FalseExit;
 123                num = text[index];
 124            }
 125            else if (num == '+')
 126            {
 127                index++;
 128                if ((uint)index >= (uint)text.Length)
 129                    goto FalseExit;
 130                num = text[index];
 131            }
 32
 133            int answer = 0;
 34
 135            if (ParserHelpers.IsDigit(num))
 136            {
 137                if (num == '0')
 138                {
 39                    do
 140                    {
 141                        index++;
 142                        if ((uint)index >= (uint)text.Length)
 143                            goto Done;
 144                        num = text[index];
 245                    } while (num == '0');
 146                    if (!ParserHelpers.IsDigit(num))
 147                        goto Done;
 148                }
 49
 150                answer = num - '0';
 151                index++;
 52
 153                if ((uint)index >= (uint)text.Length)
 154                    goto Done;
 155                num = text[index];
 156                if (!ParserHelpers.IsDigit(num))
 157                    goto Done;
 158                index++;
 159                answer = 10 * answer + num - '0';
 60
 61                // Potential overflow
 162                if ((uint)index >= (uint)text.Length)
 163                    goto Done;
 164                num = text[index];
 165                if (!ParserHelpers.IsDigit(num))
 166                    goto Done;
 167                index++;
 168                answer = answer * 10 + num - '0';
 69                // if sign < 0, (-1 * sign + 1) / 2 = 1
 70                // else, (-1 * sign + 1) / 2 = 0
 171                if ((uint)answer > (uint)sbyte.MaxValue + (-1 * sign + 1) / 2)
 172                    goto FalseExit; // Overflow
 73
 174                if ((uint)index >= (uint)text.Length)
 175                    goto Done;
 176                if (!ParserHelpers.IsDigit(text[index]))
 177                    goto Done;
 78
 79                // Guaranteed overflow
 180                goto FalseExit;
 81            }
 82
 183        FalseExit:
 184            bytesConsumed = default;
 185            value = default;
 186            return false;
 87
 188        Done:
 189            bytesConsumed = index;
 190            value = (sbyte)(answer * sign);
 191            return true;
 192        }
 93
 94        private static bool TryParseInt16D(ReadOnlySpan<byte> text, out short value, out int bytesConsumed)
 195        {
 196            if (text.Length < 1)
 197                goto FalseExit;
 98
 199            int sign = 1;
 1100            int index = 0;
 1101            int num = text[index];
 1102            if (num == '-')
 1103            {
 1104                sign = -1;
 1105                index++;
 1106                if ((uint)index >= (uint)text.Length)
 1107                    goto FalseExit;
 1108                num = text[index];
 1109            }
 1110            else if (num == '+')
 1111            {
 1112                index++;
 1113                if ((uint)index >= (uint)text.Length)
 1114                    goto FalseExit;
 1115                num = text[index];
 1116            }
 117
 1118            int answer = 0;
 119
 1120            if (ParserHelpers.IsDigit(num))
 1121            {
 1122                if (num == '0')
 1123                {
 124                    do
 1125                    {
 1126                        index++;
 1127                        if ((uint)index >= (uint)text.Length)
 1128                            goto Done;
 1129                        num = text[index];
 2130                    } while (num == '0');
 1131                    if (!ParserHelpers.IsDigit(num))
 1132                        goto Done;
 1133                }
 134
 1135                answer = num - '0';
 1136                index++;
 137
 1138                if ((uint)index >= (uint)text.Length)
 1139                    goto Done;
 1140                num = text[index];
 1141                if (!ParserHelpers.IsDigit(num))
 1142                    goto Done;
 1143                index++;
 1144                answer = 10 * answer + num - '0';
 145
 1146                if ((uint)index >= (uint)text.Length)
 1147                    goto Done;
 1148                num = text[index];
 1149                if (!ParserHelpers.IsDigit(num))
 1150                    goto Done;
 1151                index++;
 1152                answer = 10 * answer + num - '0';
 153
 1154                if ((uint)index >= (uint)text.Length)
 1155                    goto Done;
 1156                num = text[index];
 1157                if (!ParserHelpers.IsDigit(num))
 1158                    goto Done;
 1159                index++;
 1160                answer = 10 * answer + num - '0';
 161
 162                // Potential overflow
 1163                if ((uint)index >= (uint)text.Length)
 1164                    goto Done;
 1165                num = text[index];
 1166                if (!ParserHelpers.IsDigit(num))
 1167                    goto Done;
 1168                index++;
 1169                answer = answer * 10 + num - '0';
 170                // if sign < 0, (-1 * sign + 1) / 2 = 1
 171                // else, (-1 * sign + 1) / 2 = 0
 1172                if ((uint)answer > (uint)short.MaxValue + (-1 * sign + 1) / 2)
 1173                    goto FalseExit; // Overflow
 174
 1175                if ((uint)index >= (uint)text.Length)
 1176                    goto Done;
 1177                if (!ParserHelpers.IsDigit(text[index]))
 1178                    goto Done;
 179
 180                // Guaranteed overflow
 1181                goto FalseExit;
 182            }
 183
 1184        FalseExit:
 1185            bytesConsumed = default;
 1186            value = default;
 1187            return false;
 188
 1189        Done:
 1190            bytesConsumed = index;
 1191            value = (short)(answer * sign);
 1192            return true;
 1193        }
 194
 195        private static bool TryParseInt32D(ReadOnlySpan<byte> text, out int value, out int bytesConsumed)
 1196        {
 1197            if (text.Length < 1)
 1198                goto FalseExit;
 199
 1200            int sign = 1;
 1201            int index = 0;
 1202            int num = text[index];
 1203            if (num == '-')
 1204            {
 1205                sign = -1;
 1206                index++;
 1207                if ((uint)index >= (uint)text.Length)
 1208                    goto FalseExit;
 1209                num = text[index];
 1210            }
 1211            else if (num == '+')
 1212            {
 1213                index++;
 1214                if ((uint)index >= (uint)text.Length)
 1215                    goto FalseExit;
 1216                num = text[index];
 1217            }
 218
 1219            int answer = 0;
 220
 1221            if (ParserHelpers.IsDigit(num))
 1222            {
 1223                if (num == '0')
 1224                {
 225                    do
 1226                    {
 1227                        index++;
 1228                        if ((uint)index >= (uint)text.Length)
 1229                            goto Done;
 1230                        num = text[index];
 2231                    } while (num == '0');
 1232                    if (!ParserHelpers.IsDigit(num))
 1233                        goto Done;
 1234                }
 235
 1236                answer = num - '0';
 1237                index++;
 238
 1239                if ((uint)index >= (uint)text.Length)
 1240                    goto Done;
 1241                num = text[index];
 1242                if (!ParserHelpers.IsDigit(num))
 1243                    goto Done;
 1244                index++;
 1245                answer = 10 * answer + num - '0';
 246
 1247                if ((uint)index >= (uint)text.Length)
 1248                    goto Done;
 1249                num = text[index];
 1250                if (!ParserHelpers.IsDigit(num))
 1251                    goto Done;
 1252                index++;
 1253                answer = 10 * answer + num - '0';
 254
 1255                if ((uint)index >= (uint)text.Length)
 1256                    goto Done;
 1257                num = text[index];
 1258                if (!ParserHelpers.IsDigit(num))
 1259                    goto Done;
 1260                index++;
 1261                answer = 10 * answer + num - '0';
 262
 1263                if ((uint)index >= (uint)text.Length)
 1264                    goto Done;
 1265                num = text[index];
 1266                if (!ParserHelpers.IsDigit(num))
 1267                    goto Done;
 1268                index++;
 1269                answer = 10 * answer + num - '0';
 270
 1271                if ((uint)index >= (uint)text.Length)
 1272                    goto Done;
 1273                num = text[index];
 1274                if (!ParserHelpers.IsDigit(num))
 1275                    goto Done;
 1276                index++;
 1277                answer = 10 * answer + num - '0';
 278
 1279                if ((uint)index >= (uint)text.Length)
 1280                    goto Done;
 1281                num = text[index];
 1282                if (!ParserHelpers.IsDigit(num))
 1283                    goto Done;
 1284                index++;
 1285                answer = 10 * answer + num - '0';
 286
 1287                if ((uint)index >= (uint)text.Length)
 1288                    goto Done;
 1289                num = text[index];
 1290                if (!ParserHelpers.IsDigit(num))
 1291                    goto Done;
 1292                index++;
 1293                answer = 10 * answer + num - '0';
 294
 1295                if ((uint)index >= (uint)text.Length)
 1296                    goto Done;
 1297                num = text[index];
 1298                if (!ParserHelpers.IsDigit(num))
 1299                    goto Done;
 1300                index++;
 1301                answer = 10 * answer + num - '0';
 302
 303                // Potential overflow
 1304                if ((uint)index >= (uint)text.Length)
 1305                    goto Done;
 1306                num = text[index];
 1307                if (!ParserHelpers.IsDigit(num))
 1308                    goto Done;
 1309                index++;
 1310                if (answer > int.MaxValue / 10)
 1311                    goto FalseExit; // Overflow
 1312                answer = answer * 10 + num - '0';
 313                // if sign < 0, (-1 * sign + 1) / 2 = 1
 314                // else, (-1 * sign + 1) / 2 = 0
 1315                if ((uint)answer > (uint)int.MaxValue + (-1 * sign + 1) / 2)
 1316                    goto FalseExit; // Overflow
 317
 1318                if ((uint)index >= (uint)text.Length)
 1319                    goto Done;
 1320                if (!ParserHelpers.IsDigit(text[index]))
 1321                    goto Done;
 322
 323                // Guaranteed overflow
 1324                goto FalseExit;
 325            }
 326
 1327        FalseExit:
 1328            bytesConsumed = default;
 1329            value = default;
 1330            return false;
 331
 1332        Done:
 1333            bytesConsumed = index;
 1334            value = answer * sign;
 1335            return true;
 1336        }
 337
 338        private static bool TryParseInt64D(ReadOnlySpan<byte> text, out long value, out int bytesConsumed)
 1339        {
 1340            if (text.Length < 1)
 1341            {
 1342                bytesConsumed = 0;
 1343                value = default;
 1344                return false;
 345            }
 346
 1347            int indexOfFirstDigit = 0;
 1348            int sign = 1;
 1349            if (text[0] == '-')
 1350            {
 1351                indexOfFirstDigit = 1;
 1352                sign = -1;
 353
 1354                if (text.Length <= indexOfFirstDigit)
 1355                {
 1356                    bytesConsumed = 0;
 1357                    value = default;
 1358                    return false;
 359                }
 1360            }
 1361            else if (text[0] == '+')
 1362            {
 1363                indexOfFirstDigit = 1;
 364
 1365                if (text.Length <= indexOfFirstDigit)
 1366                {
 1367                    bytesConsumed = 0;
 1368                    value = default;
 1369                    return false;
 370                }
 1371            }
 372
 1373            int overflowLength = ParserHelpers.Int64OverflowLength + indexOfFirstDigit;
 374
 375            // Parse the first digit separately. If invalid here, we need to return false.
 1376            long firstDigit = text[indexOfFirstDigit] - 48; // '0'
 1377            if (firstDigit < 0 || firstDigit > 9)
 1378            {
 1379                bytesConsumed = 0;
 1380                value = default;
 1381                return false;
 382            }
 1383            ulong parsedValue = (ulong)firstDigit;
 384
 1385            if (text.Length < overflowLength)
 1386            {
 387                // Length is less than Parsers.Int64OverflowLength; overflow is not possible
 3388                for (int index = indexOfFirstDigit + 1; index < text.Length; index++)
 1389                {
 1390                    long nextDigit = text[index] - 48; // '0'
 1391                    if (nextDigit < 0 || nextDigit > 9)
 1392                    {
 1393                        bytesConsumed = index;
 1394                        value = ((long)parsedValue) * sign;
 1395                        return true;
 396                    }
 1397                    parsedValue = parsedValue * 10 + (ulong)nextDigit;
 1398                }
 1399            }
 400            else
 1401            {
 402                // Length is greater than Parsers.Int64OverflowLength; overflow is only possible after Parsers.Int64Over
 403                // digits. There may be no overflow after Parsers.Int64OverflowLength if there are leading zeroes.
 3404                for (int index = indexOfFirstDigit + 1; index < overflowLength - 1; index++)
 1405                {
 1406                    long nextDigit = text[index] - 48; // '0'
 1407                    if (nextDigit < 0 || nextDigit > 9)
 1408                    {
 1409                        bytesConsumed = index;
 1410                        value = ((long)parsedValue) * sign;
 1411                        return true;
 412                    }
 1413                    parsedValue = parsedValue * 10 + (ulong)nextDigit;
 1414                }
 3415                for (int index = overflowLength - 1; index < text.Length; index++)
 1416                {
 1417                    long nextDigit = text[index] - 48; // '0'
 1418                    if (nextDigit < 0 || nextDigit > 9)
 1419                    {
 1420                        bytesConsumed = index;
 1421                        value = ((long)parsedValue) * sign;
 1422                        return true;
 423                    }
 424                    // If parsedValue > (long.MaxValue / 10), any more appended digits will cause overflow.
 425                    // if parsedValue == (long.MaxValue / 10), any nextDigit greater than 7 or 8 (depending on sign) imp
 1426                    bool positive = sign > 0;
 1427                    bool nextDigitTooLarge = nextDigit > 8 || (positive && nextDigit > 7);
 1428                    if (parsedValue > long.MaxValue / 10 || parsedValue == long.MaxValue / 10 && nextDigitTooLarge)
 1429                    {
 1430                        bytesConsumed = 0;
 1431                        value = default;
 1432                        return false;
 433                    }
 1434                    parsedValue = parsedValue * 10 + (ulong)nextDigit;
 1435                }
 1436            }
 437
 1438            bytesConsumed = text.Length;
 1439            value = ((long)parsedValue) * sign;
 1440            return true;
 1441        }
 442    }
 443}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        private static bool TryParseSByteN(ReadOnlySpan<byte> text, out sbyte value, out int bytesConsumed)
 110        {
 111            if (text.Length < 1)
 112                goto FalseExit;
 13
 114            int sign = 1;
 115            int index = 0;
 116            int c = text[index];
 117            if (c == '-')
 118            {
 119                sign = -1;
 120                index++;
 121                if ((uint)index >= (uint)text.Length)
 122                    goto FalseExit;
 123                c = text[index];
 124            }
 125            else if (c == '+')
 126            {
 127                index++;
 128                if ((uint)index >= (uint)text.Length)
 129                    goto FalseExit;
 130                c = text[index];
 131            }
 32
 33            int answer;
 34
 35            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 36            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 37            // one digit after the decimal point.)
 138            if (c == Utf8Constants.Period)
 139                goto FractionalPartWithoutLeadingDigits;
 140            if (!ParserHelpers.IsDigit(c))
 141                goto FalseExit;
 142            answer = c - '0';
 43
 44            for (; ; )
 145            {
 146                index++;
 147                if ((uint)index >= (uint)text.Length)
 148                    goto Done;
 49
 150                c = text[index];
 151                if (c == Utf8Constants.Comma)
 152                    continue;
 53
 154                if (c == Utf8Constants.Period)
 155                    goto FractionalDigits;
 56
 157                if (!ParserHelpers.IsDigit(c))
 158                    goto Done;
 59
 160                answer = answer * 10 + c - '0';
 61
 62                // if sign < 0, (-1 * sign + 1) / 2 = 1
 63                // else, (-1 * sign + 1) / 2 = 0
 164                if (answer > sbyte.MaxValue + (-1 * sign + 1) / 2)
 165                    goto FalseExit; // Overflow
 166            }
 67
 168FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This is lega
 169            answer = 0;
 170            index++;
 171            if ((uint)index >= (uint)text.Length)
 172                goto FalseExit;
 173            if (text[index] != '0')
 174                goto FalseExit;
 75
 176FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post-fractio
 77            do
 178            {
 179                index++;
 180                if ((uint)index >= (uint)text.Length)
 181                    goto Done;
 182                c = text[index];
 183            }
 184            while (c == '0');
 85
 186            if (ParserHelpers.IsDigit(c))
 187                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 188            goto Done;
 89
 190FalseExit:
 191            bytesConsumed = default;
 192            value = default;
 193            return false;
 94
 195Done:
 196            bytesConsumed = index;
 197            value = (sbyte)(answer * sign);
 198            return true;
 199        }
 100
 101        private static bool TryParseInt16N(ReadOnlySpan<byte> text, out short value, out int bytesConsumed)
 1102        {
 1103            if (text.Length < 1)
 1104                goto FalseExit;
 105
 1106            int sign = 1;
 1107            int index = 0;
 1108            int c = text[index];
 1109            if (c == '-')
 1110            {
 1111                sign = -1;
 1112                index++;
 1113                if ((uint)index >= (uint)text.Length)
 1114                    goto FalseExit;
 1115                c = text[index];
 1116            }
 1117            else if (c == '+')
 1118            {
 1119                index++;
 1120                if ((uint)index >= (uint)text.Length)
 1121                    goto FalseExit;
 1122                c = text[index];
 1123            }
 124
 125            int answer;
 126
 127            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 128            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 129            // one digit after the decimal point.)
 1130            if (c == Utf8Constants.Period)
 1131                goto FractionalPartWithoutLeadingDigits;
 1132            if (!ParserHelpers.IsDigit(c))
 1133                goto FalseExit;
 1134            answer = c - '0';
 135
 136            for (; ; )
 1137            {
 1138                index++;
 1139                if ((uint)index >= (uint)text.Length)
 1140                    goto Done;
 141
 1142                c = text[index];
 1143                if (c == Utf8Constants.Comma)
 1144                    continue;
 145
 1146                if (c == Utf8Constants.Period)
 1147                    goto FractionalDigits;
 148
 1149                if (!ParserHelpers.IsDigit(c))
 1150                    goto Done;
 151
 1152                answer = answer * 10 + c - '0';
 153
 154                // if sign < 0, (-1 * sign + 1) / 2 = 1
 155                // else, (-1 * sign + 1) / 2 = 0
 1156                if (answer > short.MaxValue + (-1 * sign + 1) / 2)
 1157                    goto FalseExit; // Overflow
 1158            }
 159
 1160FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This is lega
 1161            answer = 0;
 1162            index++;
 1163            if ((uint)index >= (uint)text.Length)
 1164                goto FalseExit;
 1165            if (text[index] != '0')
 1166                goto FalseExit;
 167
 1168FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post-fractio
 169            do
 1170            {
 1171                index++;
 1172                if ((uint)index >= (uint)text.Length)
 1173                    goto Done;
 1174                c = text[index];
 1175            }
 1176            while (c == '0');
 177
 1178            if (ParserHelpers.IsDigit(c))
 1179                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 1180            goto Done;
 181
 1182FalseExit:
 1183            bytesConsumed = default;
 1184            value = default;
 1185            return false;
 186
 1187Done:
 1188            bytesConsumed = index;
 1189            value = (short)(answer * sign);
 1190            return true;
 1191        }
 192
 193        private static bool TryParseInt32N(ReadOnlySpan<byte> text, out int value, out int bytesConsumed)
 1194        {
 1195            if (text.Length < 1)
 1196                goto FalseExit;
 197
 1198            int sign = 1;
 1199            int index = 0;
 1200            int c = text[index];
 1201            if (c == '-')
 1202            {
 1203                sign = -1;
 1204                index++;
 1205                if ((uint)index >= (uint)text.Length)
 1206                    goto FalseExit;
 1207                c = text[index];
 1208            }
 1209            else if (c == '+')
 1210            {
 1211                index++;
 1212                if ((uint)index >= (uint)text.Length)
 1213                    goto FalseExit;
 1214                c = text[index];
 1215            }
 216
 217            int answer;
 218
 219            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 220            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 221            // one digit after the decimal point.)
 1222            if (c == Utf8Constants.Period)
 1223                goto FractionalPartWithoutLeadingDigits;
 1224            if (!ParserHelpers.IsDigit(c))
 1225                goto FalseExit;
 1226            answer = c - '0';
 227
 228            for (; ; )
 1229            {
 1230                index++;
 1231                if ((uint)index >= (uint)text.Length)
 1232                    goto Done;
 233
 1234                c = text[index];
 1235                if (c == Utf8Constants.Comma)
 1236                    continue;
 237
 1238                if (c == Utf8Constants.Period)
 1239                    goto FractionalDigits;
 240
 1241                if (!ParserHelpers.IsDigit(c))
 1242                    goto Done;
 243
 1244                if (((uint)answer) > int.MaxValue / 10)
 1245                    goto FalseExit;
 246
 1247                answer = answer * 10 + c - '0';
 248
 249                // if sign < 0, (-1 * sign + 1) / 2 = 1
 250                // else, (-1 * sign + 1) / 2 = 0
 1251                if ((uint)answer > (uint)int.MaxValue + (-1 * sign + 1) / 2)
 1252                    goto FalseExit; // Overflow
 1253            }
 254
 1255FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This is lega
 1256            answer = 0;
 1257            index++;
 1258            if ((uint)index >= (uint)text.Length)
 1259                goto FalseExit;
 1260            if (text[index] != '0')
 1261                goto FalseExit;
 262
 1263FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post-fractio
 264            do
 1265            {
 1266                index++;
 1267                if ((uint)index >= (uint)text.Length)
 1268                    goto Done;
 1269                c = text[index];
 1270            }
 1271            while (c == '0');
 272
 1273            if (ParserHelpers.IsDigit(c))
 1274                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 1275            goto Done;
 276
 1277FalseExit:
 1278            bytesConsumed = default;
 1279            value = default;
 1280            return false;
 281
 1282Done:
 1283            bytesConsumed = index;
 1284            value = answer * sign;
 1285            return true;
 1286        }
 287
 288        private static bool TryParseInt64N(ReadOnlySpan<byte> text, out long value, out int bytesConsumed)
 1289        {
 1290            if (text.Length < 1)
 1291                goto FalseExit;
 292
 1293            int sign = 1;
 1294            int index = 0;
 1295            int c = text[index];
 1296            if (c == '-')
 1297            {
 1298                sign = -1;
 1299                index++;
 1300                if ((uint)index >= (uint)text.Length)
 1301                    goto FalseExit;
 1302                c = text[index];
 1303            }
 1304            else if (c == '+')
 1305            {
 1306                index++;
 1307                if ((uint)index >= (uint)text.Length)
 1308                    goto FalseExit;
 1309                c = text[index];
 1310            }
 311
 312            long answer;
 313
 314            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 315            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 316            // one digit after the decimal point.)
 1317            if (c == Utf8Constants.Period)
 1318                goto FractionalPartWithoutLeadingDigits;
 1319            if (!ParserHelpers.IsDigit(c))
 1320                goto FalseExit;
 1321            answer = c - '0';
 322
 323            for (; ; )
 1324            {
 1325                index++;
 1326                if ((uint)index >= (uint)text.Length)
 1327                    goto Done;
 328
 1329                c = text[index];
 1330                if (c == Utf8Constants.Comma)
 1331                    continue;
 332
 1333                if (c == Utf8Constants.Period)
 1334                    goto FractionalDigits;
 335
 1336                if (!ParserHelpers.IsDigit(c))
 1337                    goto Done;
 338
 1339                if (((ulong)answer) > long.MaxValue / 10)
 1340                    goto FalseExit;
 341
 1342                answer = answer * 10 + c - '0';
 343
 344                // if sign < 0, (-1 * sign + 1) / 2 = 1
 345                // else, (-1 * sign + 1) / 2 = 0
 1346                if ((ulong)answer > (ulong)(long.MaxValue + (-1 * sign + 1) / 2))
 1347                    goto FalseExit; // Overflow
 1348            }
 349
 1350FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This is lega
 1351            answer = 0;
 1352            index++;
 1353            if ((uint)index >= (uint)text.Length)
 1354                goto FalseExit;
 1355            if (text[index] != '0')
 1356                goto FalseExit;
 357
 1358FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post-fractio
 359            do
 1360            {
 1361                index++;
 1362                if ((uint)index >= (uint)text.Length)
 1363                    goto Done;
 1364                c = text[index];
 1365            }
 1366            while (c == '0');
 367
 1368            if (ParserHelpers.IsDigit(c))
 1369                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 1370            goto Done;
 371
 1372FalseExit:
 1373            bytesConsumed = default;
 1374            value = default;
 1375            return false;
 376
 1377Done:
 1378            bytesConsumed = index;
 1379            value = answer * sign;
 1380            return true;
 1381        }
 382    }
 383}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        /// <summary>
 10        /// Parses a Byte at the start of a Utf8 string.
 11        /// </summary>
 12        /// <param name="text">The Utf8 string to parse</param>
 13        /// <param name="value">Receives the parsed value</param>
 14        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 15        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 16        /// <returns>
 17        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 18        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 19        /// </returns>
 20        /// <remarks>
 21        /// Formats supported:
 22        ///     G/g (default)
 23        ///     D/d             32767
 24        ///     N/n             32,767
 25        ///     X/x             7fff
 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> text, out byte value, out int bytesConsumed, char standardFormat 
 131        {
 132            switch (standardFormat)
 33            {
 34                case (default):
 35                case 'g':
 36                case 'G':
 37                case 'd':
 38                case 'D':
 139                    return TryParseByteD(text, out value, out bytesConsumed);
 40
 41                case 'n':
 42                case 'N':
 143                    return TryParseByteN(text, out value, out bytesConsumed);
 44
 45                case 'x':
 46                case 'X':
 147                    return TryParseByteX(text, out value, out bytesConsumed);
 48
 49                default:
 150                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 51            }
 152        }
 53
 54        /// <summary>
 55        /// Parses a UInt16 at the start of a Utf8 string.
 56        /// </summary>
 57        /// <param name="text">The Utf8 string to parse</param>
 58        /// <param name="value">Receives the parsed value</param>
 59        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 60        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 61        /// <returns>
 62        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 63        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 64        /// </returns>
 65        /// <remarks>
 66        /// Formats supported:
 67        ///     G/g (default)
 68        ///     D/d             32767
 69        ///     N/n             32,767
 70        ///     X/x             7fff
 71        /// </remarks>
 72        /// <exceptions>
 73        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 74        /// </exceptions>
 75        [CLSCompliant(false)]
 76        public static bool TryParse(ReadOnlySpan<byte> text, out ushort value, out int bytesConsumed, char standardForma
 177        {
 178            switch (standardFormat)
 79            {
 80                case (default):
 81                case 'g':
 82                case 'G':
 83                case 'd':
 84                case 'D':
 185                    return TryParseUInt16D(text, out value, out bytesConsumed);
 86
 87                case 'n':
 88                case 'N':
 189                    return TryParseUInt16N(text, out value, out bytesConsumed);
 90
 91                case 'x':
 92                case 'X':
 193                    return TryParseUInt16X(text, out value, out bytesConsumed);
 94
 95                default:
 196                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 97            }
 198        }
 99
 100        /// <summary>
 101        /// Parses a UInt32 at the start of a Utf8 string.
 102        /// </summary>
 103        /// <param name="text">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/g (default)
 114        ///     D/d             32767
 115        ///     N/n             32,767
 116        ///     X/x             7fff
 117        /// </remarks>
 118        /// <exceptions>
 119        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 120        /// </exceptions>
 121        [CLSCompliant(false)]
 122        public static bool TryParse(ReadOnlySpan<byte> text, out uint value, out int bytesConsumed, char standardFormat 
 1123        {
 1124            switch (standardFormat)
 125            {
 126                case (default):
 127                case 'g':
 128                case 'G':
 129                case 'd':
 130                case 'D':
 1131                    return TryParseUInt32D(text, out value, out bytesConsumed);
 132
 133                case 'n':
 134                case 'N':
 1135                    return TryParseUInt32N(text, out value, out bytesConsumed);
 136
 137                case 'x':
 138                case 'X':
 1139                    return TryParseUInt32X(text, out value, out bytesConsumed);
 140
 141                default:
 1142                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 143            }
 1144        }
 145
 146        /// <summary>
 147        /// Parses a UInt64 at the start of a Utf8 string.
 148        /// </summary>
 149        /// <param name="text">The Utf8 string to parse</param>
 150        /// <param name="value">Receives the parsed value</param>
 151        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 152        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 153        /// <returns>
 154        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 155        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 156        /// </returns>
 157        /// <remarks>
 158        /// Formats supported:
 159        ///     G/g (default)
 160        ///     D/d             32767
 161        ///     N/n             32,767
 162        ///     X/x             7fff
 163        /// </remarks>
 164        /// <exceptions>
 165        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 166        /// </exceptions>
 167        [CLSCompliant(false)]
 168        public static bool TryParse(ReadOnlySpan<byte> text, out ulong value, out int bytesConsumed, char standardFormat
 1169        {
 1170            switch (standardFormat)
 171            {
 172                case (default):
 173                case 'g':
 174                case 'G':
 175                case 'd':
 176                case 'D':
 1177                    return TryParseUInt64D(text, out value, out bytesConsumed);
 178
 179                case 'n':
 180                case 'N':
 1181                    return TryParseUInt64N(text, out value, out bytesConsumed);
 182
 183                case 'x':
 184                case 'X':
 1185                    return TryParseUInt64X(text, out value, out bytesConsumed);
 186
 187                default:
 1188                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 189            }
 1190        }
 191    }
 192}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        private static bool TryParseByteD(ReadOnlySpan<byte> text, out byte value, out int bytesConsumed)
 110        {
 111            if (text.Length < 1)
 112                goto FalseExit;
 13
 114            int index = 0;
 115            int num = text[index];
 116            int answer = 0;
 17
 118            if (ParserHelpers.IsDigit(num))
 119            {
 120                if (num == '0')
 121                {
 22                    do
 123                    {
 124                        index++;
 125                        if ((uint)index >= (uint)text.Length)
 126                            goto Done;
 127                        num = text[index];
 228                    } while (num == '0');
 129                    if (!ParserHelpers.IsDigit(num))
 130                        goto Done;
 131                }
 32
 133                answer = num - '0';
 134                index++;
 35
 136                if ((uint)index >= (uint)text.Length)
 137                    goto Done;
 138                num = text[index];
 139                if (!ParserHelpers.IsDigit(num))
 140                    goto Done;
 141                index++;
 142                answer = 10 * answer + num - '0';
 43
 44                // Potential overflow
 145                if ((uint)index >= (uint)text.Length)
 146                    goto Done;
 147                num = text[index];
 148                if (!ParserHelpers.IsDigit(num))
 149                    goto Done;
 150                index++;
 151                answer = answer * 10 + num - '0';
 152                if ((uint)answer > byte.MaxValue)
 153                    goto FalseExit; // Overflow
 54
 155                if ((uint)index >= (uint)text.Length)
 156                    goto Done;
 157                if (!ParserHelpers.IsDigit(text[index]))
 158                    goto Done;
 59
 60                // Guaranteed overflow
 161                goto FalseExit;
 62            }
 63
 164        FalseExit:
 165            bytesConsumed = default;
 166            value = default;
 167            return false;
 68
 169        Done:
 170            bytesConsumed = index;
 171            value = (byte)answer;
 172            return true;
 173        }
 74
 75        private static bool TryParseUInt16D(ReadOnlySpan<byte> text, out ushort value, out int bytesConsumed)
 176        {
 177            if (text.Length < 1)
 178                goto FalseExit;
 79
 180            int index = 0;
 181            int num = text[index];
 182            int answer = 0;
 83
 184            if (ParserHelpers.IsDigit(num))
 185            {
 186                if (num == '0')
 187                {
 88                    do
 189                    {
 190                        index++;
 191                        if ((uint)index >= (uint)text.Length)
 192                            goto Done;
 193                        num = text[index];
 294                    } while (num == '0');
 195                    if (!ParserHelpers.IsDigit(num))
 196                        goto Done;
 197                }
 98
 199                answer = num - '0';
 1100                index++;
 101
 1102                if ((uint)index >= (uint)text.Length)
 1103                    goto Done;
 1104                num = text[index];
 1105                if (!ParserHelpers.IsDigit(num))
 1106                    goto Done;
 1107                index++;
 1108                answer = 10 * answer + num - '0';
 109
 1110                if ((uint)index >= (uint)text.Length)
 1111                    goto Done;
 1112                num = text[index];
 1113                if (!ParserHelpers.IsDigit(num))
 1114                    goto Done;
 1115                index++;
 1116                answer = 10 * answer + num - '0';
 117
 1118                if ((uint)index >= (uint)text.Length)
 1119                    goto Done;
 1120                num = text[index];
 1121                if (!ParserHelpers.IsDigit(num))
 1122                    goto Done;
 1123                index++;
 1124                answer = 10 * answer + num - '0';
 125
 126                // Potential overflow
 1127                if ((uint)index >= (uint)text.Length)
 1128                    goto Done;
 1129                num = text[index];
 1130                if (!ParserHelpers.IsDigit(num))
 1131                    goto Done;
 1132                index++;
 1133                answer = answer * 10 + num - '0';
 1134                if ((uint)answer > ushort.MaxValue)
 1135                    goto FalseExit; // Overflow
 136
 1137                if ((uint)index >= (uint)text.Length)
 1138                    goto Done;
 1139                if (!ParserHelpers.IsDigit(text[index]))
 1140                    goto Done;
 141
 142                // Guaranteed overflow
 1143                goto FalseExit;
 144            }
 145
 1146        FalseExit:
 1147            bytesConsumed = default;
 1148            value = default;
 1149            return false;
 150
 1151        Done:
 1152            bytesConsumed = index;
 1153            value = (ushort)answer;
 1154            return true;
 1155        }
 156
 157        private static bool TryParseUInt32D(ReadOnlySpan<byte> text, out uint value, out int bytesConsumed)
 1158        {
 1159            if (text.Length < 1)
 1160                goto FalseExit;
 161
 1162            int index = 0;
 1163            int num = text[index];
 1164            int answer = 0;
 165
 1166            if (ParserHelpers.IsDigit(num))
 1167            {
 1168                if (num == '0')
 1169                {
 170                    do
 1171                    {
 1172                        index++;
 1173                        if ((uint)index >= (uint)text.Length)
 1174                            goto Done;
 1175                        num = text[index];
 2176                    } while (num == '0');
 1177                    if (!ParserHelpers.IsDigit(num))
 1178                        goto Done;
 1179                }
 180
 1181                answer = num - '0';
 1182                index++;
 183
 1184                if ((uint)index >= (uint)text.Length)
 1185                    goto Done;
 1186                num = text[index];
 1187                if (!ParserHelpers.IsDigit(num))
 1188                    goto Done;
 1189                index++;
 1190                answer = 10 * answer + num - '0';
 191
 1192                if ((uint)index >= (uint)text.Length)
 1193                    goto Done;
 1194                num = text[index];
 1195                if (!ParserHelpers.IsDigit(num))
 1196                    goto Done;
 1197                index++;
 1198                answer = 10 * answer + num - '0';
 199
 1200                if ((uint)index >= (uint)text.Length)
 1201                    goto Done;
 1202                num = text[index];
 1203                if (!ParserHelpers.IsDigit(num))
 1204                    goto Done;
 1205                index++;
 1206                answer = 10 * answer + num - '0';
 207
 1208                if ((uint)index >= (uint)text.Length)
 1209                    goto Done;
 1210                num = text[index];
 1211                if (!ParserHelpers.IsDigit(num))
 1212                    goto Done;
 1213                index++;
 1214                answer = 10 * answer + num - '0';
 215
 1216                if ((uint)index >= (uint)text.Length)
 1217                    goto Done;
 1218                num = text[index];
 1219                if (!ParserHelpers.IsDigit(num))
 1220                    goto Done;
 1221                index++;
 1222                answer = 10 * answer + num - '0';
 223
 1224                if ((uint)index >= (uint)text.Length)
 1225                    goto Done;
 1226                num = text[index];
 1227                if (!ParserHelpers.IsDigit(num))
 1228                    goto Done;
 1229                index++;
 1230                answer = 10 * answer + num - '0';
 231
 1232                if ((uint)index >= (uint)text.Length)
 1233                    goto Done;
 1234                num = text[index];
 1235                if (!ParserHelpers.IsDigit(num))
 1236                    goto Done;
 1237                index++;
 1238                answer = 10 * answer + num - '0';
 239
 1240                if ((uint)index >= (uint)text.Length)
 1241                    goto Done;
 1242                num = text[index];
 1243                if (!ParserHelpers.IsDigit(num))
 1244                    goto Done;
 1245                index++;
 1246                answer = 10 * answer + num - '0';
 247
 248                // Potential overflow
 1249                if ((uint)index >= (uint)text.Length)
 1250                    goto Done;
 1251                num = text[index];
 1252                if (!ParserHelpers.IsDigit(num))
 1253                    goto Done;
 1254                index++;
 1255                if (((uint)answer) > uint.MaxValue / 10 || (((uint)answer) == uint.MaxValue / 10 && num > '5'))
 1256                    goto FalseExit; // Overflow
 1257                answer = answer * 10 + num - '0';
 258
 1259                if ((uint)index >= (uint)text.Length)
 1260                    goto Done;
 1261                if (!ParserHelpers.IsDigit(text[index]))
 1262                    goto Done;
 263
 264                // Guaranteed overflow
 1265                goto FalseExit;
 266            }
 267
 1268        FalseExit:
 1269            bytesConsumed = default;
 1270            value = default;
 1271            return false;
 272
 1273        Done:
 1274            bytesConsumed = index;
 1275            value = (uint)answer;
 1276            return true;
 1277        }
 278
 279        private static bool TryParseUInt64D(ReadOnlySpan<byte> text, out ulong value, out int bytesConsumed)
 1280        {
 1281            if (text.Length < 1)
 1282            {
 1283                bytesConsumed = 0;
 1284                value = default;
 1285                return false;
 286            }
 287
 288            // Parse the first digit separately. If invalid here, we need to return false.
 1289            ulong firstDigit = text[0] - 48u; // '0'
 1290            if (firstDigit > 9)
 1291            {
 1292                bytesConsumed = 0;
 1293                value = default;
 1294                return false;
 295            }
 1296            ulong parsedValue = firstDigit;
 297
 1298            if (text.Length < ParserHelpers.Int64OverflowLength)
 1299            {
 300                // Length is less than Parsers.Int64OverflowLength; overflow is not possible
 3301                for (int index = 1; index < text.Length; index++)
 1302                {
 1303                    ulong nextDigit = text[index] - 48u; // '0'
 1304                    if (nextDigit > 9)
 1305                    {
 1306                        bytesConsumed = index;
 1307                        value = parsedValue;
 1308                        return true;
 309                    }
 1310                    parsedValue = parsedValue * 10 + nextDigit;
 1311                }
 1312            }
 313            else
 1314            {
 315                // Length is greater than Parsers.Int64OverflowLength; overflow is only possible after Parsers.Int64Over
 316                // digits. There may be no overflow after Parsers.Int64OverflowLength if there are leading zeroes.
 3317                for (int index = 1; index < ParserHelpers.Int64OverflowLength - 1; index++)
 1318                {
 1319                    ulong nextDigit = text[index] - 48u; // '0'
 1320                    if (nextDigit > 9)
 1321                    {
 1322                        bytesConsumed = index;
 1323                        value = parsedValue;
 1324                        return true;
 325                    }
 1326                    parsedValue = parsedValue * 10 + nextDigit;
 1327                }
 3328                for (int index = ParserHelpers.Int64OverflowLength - 1; index < text.Length; index++)
 1329                {
 1330                    ulong nextDigit = text[index] - 48u; // '0'
 1331                    if (nextDigit > 9)
 1332                    {
 1333                        bytesConsumed = index;
 1334                        value = parsedValue;
 1335                        return true;
 336                    }
 337                    // If parsedValue > (ulong.MaxValue / 10), any more appended digits will cause overflow.
 338                    // if parsedValue == (ulong.MaxValue / 10), any nextDigit greater than 5 implies overflow.
 1339                    if (parsedValue > ulong.MaxValue / 10 || (parsedValue == ulong.MaxValue / 10 && nextDigit > 5))
 1340                    {
 1341                        bytesConsumed = 0;
 1342                        value = default;
 1343                        return false;
 344                    }
 1345                    parsedValue = parsedValue * 10 + nextDigit;
 1346                }
 1347            }
 348
 1349            bytesConsumed = text.Length;
 1350            value = parsedValue;
 1351            return true;
 1352        }
 353    }
 354}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    //
 8    // Parsing unsigned integers for the 'N' format. Emulating int.TryParse(NumberStyles.AllowThousands | NumberStyles.I
 9    //
 10    public static partial class Utf8Parser
 11    {
 12        private static bool TryParseByteN(ReadOnlySpan<byte> text, out byte value, out int bytesConsumed)
 113        {
 114            if (text.Length < 1)
 115                goto FalseExit;
 16
 117            int index = 0;
 118            int c = text[index];
 119            if (c == '+')
 120            {
 121                index++;
 122                if ((uint)index >= (uint)text.Length)
 123                    goto FalseExit;
 124                c = text[index];
 125            }
 26
 27            int answer;
 28
 29            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 30            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 31            // one digit after the decimal point.)
 132            if (c == Utf8Constants.Period)
 133                goto FractionalPartWithoutLeadingDigits;
 134            if (!ParserHelpers.IsDigit(c))
 135                goto FalseExit;
 136            answer = c - '0';
 37
 38            for (; ; )
 139            {
 140                index++;
 141                if ((uint)index >= (uint)text.Length)
 142                    goto Done;
 43
 144                c = text[index];
 145                if (c == Utf8Constants.Comma)
 146                    continue;
 47
 148                if (c == Utf8Constants.Period)
 149                    goto FractionalDigits;
 50
 151                if (!ParserHelpers.IsDigit(c))
 152                    goto Done;
 53
 154                answer = answer * 10 + c - '0';
 55
 156                if (answer > byte.MaxValue)
 157                    goto FalseExit; // Overflow
 158            }
 59
 160FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This is lega
 161            answer = 0;
 162            index++;
 163            if ((uint)index >= (uint)text.Length)
 164                goto FalseExit;
 165            if (text[index] != '0')
 166                goto FalseExit;
 67
 168FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post-fractio
 69            do
 170            {
 171                index++;
 172                if ((uint)index >= (uint)text.Length)
 173                    goto Done;
 174                c = text[index];
 175            }
 176            while (c == '0');
 77
 178            if (ParserHelpers.IsDigit(c))
 179                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 180            goto Done;
 81
 182FalseExit:
 183            bytesConsumed = default;
 184            value = default;
 185            return false;
 86
 187Done:
 188            bytesConsumed = index;
 189            value = (byte)answer;
 190            return true;
 191        }
 92
 93        private static bool TryParseUInt16N(ReadOnlySpan<byte> text, out ushort value, out int bytesConsumed)
 194        {
 195            if (text.Length < 1)
 196                goto FalseExit;
 97
 198            int index = 0;
 199            int c = text[index];
 1100            if (c == '+')
 1101            {
 1102                index++;
 1103                if ((uint)index >= (uint)text.Length)
 1104                    goto FalseExit;
 1105                c = text[index];
 1106            }
 107
 108            int answer;
 109
 110            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 111            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 112            // one digit after the decimal point.)
 1113            if (c == Utf8Constants.Period)
 1114                goto FractionalPartWithoutLeadingDigits;
 1115            if (!ParserHelpers.IsDigit(c))
 1116                goto FalseExit;
 1117            answer = c - '0';
 118
 119            for (; ; )
 1120            {
 1121                index++;
 1122                if ((uint)index >= (uint)text.Length)
 1123                    goto Done;
 124
 1125                c = text[index];
 1126                if (c == Utf8Constants.Comma)
 1127                    continue;
 128
 1129                if (c == Utf8Constants.Period)
 1130                    goto FractionalDigits;
 131
 1132                if (!ParserHelpers.IsDigit(c))
 1133                    goto Done;
 134
 1135                answer = answer * 10 + c - '0';
 136
 1137                if (answer > ushort.MaxValue)
 1138                    goto FalseExit; // Overflow
 1139            }
 140
 1141FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This is lega
 1142            answer = 0;
 1143            index++;
 1144            if ((uint)index >= (uint)text.Length)
 1145                goto FalseExit;
 1146            if (text[index] != '0')
 1147                goto FalseExit;
 148
 1149FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post-fractio
 150            do
 1151            {
 1152                index++;
 1153                if ((uint)index >= (uint)text.Length)
 1154                    goto Done;
 1155                c = text[index];
 1156            }
 1157            while (c == '0');
 158
 1159            if (ParserHelpers.IsDigit(c))
 1160                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 1161            goto Done;
 162
 1163FalseExit:
 1164            bytesConsumed = default;
 1165            value = default;
 1166            return false;
 167
 1168Done:
 1169            bytesConsumed = index;
 1170            value = (ushort)answer;
 1171            return true;
 1172        }
 173
 174        private static bool TryParseUInt32N(ReadOnlySpan<byte> text, out uint value, out int bytesConsumed)
 1175        {
 1176            if (text.Length < 1)
 1177                goto FalseExit;
 178
 1179            int index = 0;
 1180            int c = text[index];
 1181            if (c == '+')
 1182            {
 1183                index++;
 1184                if ((uint)index >= (uint)text.Length)
 1185                    goto FalseExit;
 1186                c = text[index];
 1187            }
 188
 189            int answer;
 190
 191            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 192            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 193            // one digit after the decimal point.)
 1194            if (c == Utf8Constants.Period)
 1195                goto FractionalPartWithoutLeadingDigits;
 1196            if (!ParserHelpers.IsDigit(c))
 1197                goto FalseExit;
 1198            answer = c - '0';
 199
 200            for (; ; )
 1201            {
 1202                index++;
 1203                if ((uint)index >= (uint)text.Length)
 1204                    goto Done;
 205
 1206                c = text[index];
 1207                if (c == Utf8Constants.Comma)
 1208                    continue;
 209
 1210                if (c == Utf8Constants.Period)
 1211                    goto FractionalDigits;
 212
 1213                if (!ParserHelpers.IsDigit(c))
 1214                    goto Done;
 215
 1216                if (((uint)answer) > uint.MaxValue / 10 || (((uint)answer) == uint.MaxValue / 10 && c > '5'))
 1217                    goto FalseExit; // Overflow
 218
 1219                answer = answer * 10 + c - '0';
 1220            }
 221
 1222FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This is lega
 1223            answer = 0;
 1224            index++;
 1225            if ((uint)index >= (uint)text.Length)
 1226                goto FalseExit;
 1227            if (text[index] != '0')
 1228                goto FalseExit;
 229
 1230FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post-fractio
 231            do
 1232            {
 1233                index++;
 1234                if ((uint)index >= (uint)text.Length)
 1235                    goto Done;
 1236                c = text[index];
 1237            }
 1238            while (c == '0');
 239
 1240            if (ParserHelpers.IsDigit(c))
 1241                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 1242            goto Done;
 243
 1244FalseExit:
 1245            bytesConsumed = default;
 1246            value = default;
 1247            return false;
 248
 1249Done:
 1250            bytesConsumed = index;
 1251            value = (uint)answer;
 1252            return true;
 1253        }
 254
 255        private static bool TryParseUInt64N(ReadOnlySpan<byte> text, out ulong value, out int bytesConsumed)
 1256        {
 1257            if (text.Length < 1)
 1258                goto FalseExit;
 259
 1260            int index = 0;
 1261            int c = text[index];
 1262            if (c == '+')
 1263            {
 1264                index++;
 1265                if ((uint)index >= (uint)text.Length)
 1266                    goto FalseExit;
 1267                c = text[index];
 1268            }
 269
 270            long answer;
 271
 272            // Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior wit
 273            // (at least one digit must precede any commas, and a string without any digits prior to the decimal point m
 274            // one digit after the decimal point.)
 1275            if (c == Utf8Constants.Period)
 1276                goto FractionalPartWithoutLeadingDigits;
 1277            if (!ParserHelpers.IsDigit(c))
 1278                goto FalseExit;
 1279            answer = c - '0';
 280
 281            for (; ; )
 1282            {
 1283                index++;
 1284                if ((uint)index >= (uint)text.Length)
 1285                    goto Done;
 286
 1287                c = text[index];
 1288                if (c == Utf8Constants.Comma)
 1289                    continue;
 290
 1291                if (c == Utf8Constants.Period)
 1292                    goto FractionalDigits;
 293
 1294                if (!ParserHelpers.IsDigit(c))
 1295                    goto Done;
 296
 1297                if (((ulong)answer) > ulong.MaxValue / 10 || (((ulong)answer) == ulong.MaxValue / 10 && c > '5'))
 1298                    goto FalseExit; // Overflow
 299
 1300                answer = answer * 10 + c - '0';
 1301            }
 302
 1303FractionalPartWithoutLeadingDigits: // If we got here, we found a decimal point before we found any digits. This is lega
 1304            answer = 0;
 1305            index++;
 1306            if ((uint)index >= (uint)text.Length)
 1307                goto FalseExit;
 1308            if (text[index] != '0')
 1309                goto FalseExit;
 310
 1311FractionalDigits: // "N" format allows a fractional portion despite being an integer format but only if the post-fractio
 312            do
 1313            {
 1314                index++;
 1315                if ((uint)index >= (uint)text.Length)
 1316                    goto Done;
 1317                c = text[index];
 1318            }
 1319            while (c == '0');
 320
 1321            if (ParserHelpers.IsDigit(c))
 1322                goto FalseExit; // The fractional portion contained a non-zero digit. Treat this as an error, not an ear
 1323            goto Done;
 324
 1325FalseExit:
 1326            bytesConsumed = default;
 1327            value = default;
 1328            return false;
 329
 1330Done:
 1331            bytesConsumed = index;
 1332            value = (ulong)answer;
 1333            return true;
 1334        }
 335    }
 336}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        private static bool TryParseByteX(ReadOnlySpan<byte> text, out byte value, out int bytesConsumed)
 110        {
 111            if (text.Length < 1)
 112            {
 113                bytesConsumed = 0;
 114                value = default;
 115                return false;
 16            }
 17            byte nextCharacter;
 18            byte nextDigit;
 19
 20            // Cache Parsers.s_HexLookup in order to avoid static constructor checks
 121            byte[] hexLookup = ParserHelpers.s_hexLookup;
 22
 23            // Parse the first digit separately. If invalid here, we need to return false.
 124            nextCharacter = text[0];
 125            nextDigit = hexLookup[nextCharacter];
 126            if (nextDigit == 0xFF)
 127            {
 128                bytesConsumed = 0;
 129                value = default;
 130                return false;
 31            }
 132            uint parsedValue = nextDigit;
 33
 134            if (text.Length <= ParserHelpers.ByteOverflowLengthHex)
 135            {
 36                // Length is less than or equal to Parsers.ByteOverflowLengthHex; overflow is not possible
 337                for (int index = 1; index < text.Length; index++)
 138                {
 139                    nextCharacter = text[index];
 140                    nextDigit = hexLookup[nextCharacter];
 141                    if (nextDigit == 0xFF)
 142                    {
 143                        bytesConsumed = index;
 144                        value = (byte)(parsedValue);
 145                        return true;
 46                    }
 147                    parsedValue = (parsedValue << 4) + nextDigit;
 148                }
 149            }
 50            else
 151            {
 52                // Length is greater than Parsers.ByteOverflowLengthHex; overflow is only possible after Parsers.ByteOve
 53                // digits. There may be no overflow after Parsers.ByteOverflowLengthHex if there are leading zeroes.
 354                for (int index = 1; index < ParserHelpers.ByteOverflowLengthHex; index++)
 155                {
 156                    nextCharacter = text[index];
 157                    nextDigit = hexLookup[nextCharacter];
 158                    if (nextDigit == 0xFF)
 159                    {
 160                        bytesConsumed = index;
 161                        value = (byte)(parsedValue);
 162                        return true;
 63                    }
 164                    parsedValue = (parsedValue << 4) + nextDigit;
 165                }
 366                for (int index = ParserHelpers.ByteOverflowLengthHex; index < text.Length; index++)
 167                {
 168                    nextCharacter = text[index];
 169                    nextDigit = hexLookup[nextCharacter];
 170                    if (nextDigit == 0xFF)
 171                    {
 172                        bytesConsumed = index;
 173                        value = (byte)(parsedValue);
 174                        return true;
 75                    }
 76                    // If we try to append a digit to anything larger than byte.MaxValue / 0x10, there will be overflow
 177                    if (parsedValue > byte.MaxValue / 0x10)
 178                    {
 179                        bytesConsumed = 0;
 180                        value = default;
 181                        return false;
 82                    }
 183                    parsedValue = (parsedValue << 4) + nextDigit;
 184                }
 185            }
 86
 187            bytesConsumed = text.Length;
 188            value = (byte)(parsedValue);
 189            return true;
 190        }
 91
 92        private static bool TryParseUInt16X(ReadOnlySpan<byte> text, out ushort value, out int bytesConsumed)
 193        {
 194            if (text.Length < 1)
 195            {
 196                bytesConsumed = 0;
 197                value = default;
 198                return false;
 99            }
 100            byte nextCharacter;
 101            byte nextDigit;
 102
 103            // Cache Parsers.s_HexLookup in order to avoid static constructor checks
 1104            byte[] hexLookup = ParserHelpers.s_hexLookup;
 105
 106            // Parse the first digit separately. If invalid here, we need to return false.
 1107            nextCharacter = text[0];
 1108            nextDigit = hexLookup[nextCharacter];
 1109            if (nextDigit == 0xFF)
 1110            {
 1111                bytesConsumed = 0;
 1112                value = default;
 1113                return false;
 114            }
 1115            uint parsedValue = nextDigit;
 116
 1117            if (text.Length <= ParserHelpers.Int16OverflowLengthHex)
 1118            {
 119                // Length is less than or equal to Parsers.Int16OverflowLengthHex; overflow is not possible
 3120                for (int index = 1; index < text.Length; index++)
 1121                {
 1122                    nextCharacter = text[index];
 1123                    nextDigit = hexLookup[nextCharacter];
 1124                    if (nextDigit == 0xFF)
 1125                    {
 1126                        bytesConsumed = index;
 1127                        value = (ushort)(parsedValue);
 1128                        return true;
 129                    }
 1130                    parsedValue = (parsedValue << 4) + nextDigit;
 1131                }
 1132            }
 133            else
 1134            {
 135                // Length is greater than Parsers.Int16OverflowLengthHex; overflow is only possible after Parsers.Int16O
 136                // digits. There may be no overflow after Parsers.Int16OverflowLengthHex if there are leading zeroes.
 3137                for (int index = 1; index < ParserHelpers.Int16OverflowLengthHex; index++)
 1138                {
 1139                    nextCharacter = text[index];
 1140                    nextDigit = hexLookup[nextCharacter];
 1141                    if (nextDigit == 0xFF)
 1142                    {
 1143                        bytesConsumed = index;
 1144                        value = (ushort)(parsedValue);
 1145                        return true;
 146                    }
 1147                    parsedValue = (parsedValue << 4) + nextDigit;
 1148                }
 3149                for (int index = ParserHelpers.Int16OverflowLengthHex; index < text.Length; index++)
 1150                {
 1151                    nextCharacter = text[index];
 1152                    nextDigit = hexLookup[nextCharacter];
 1153                    if (nextDigit == 0xFF)
 1154                    {
 1155                        bytesConsumed = index;
 1156                        value = (ushort)(parsedValue);
 1157                        return true;
 158                    }
 159                    // If we try to append a digit to anything larger than ushort.MaxValue / 0x10, there will be overflo
 1160                    if (parsedValue > ushort.MaxValue / 0x10)
 1161                    {
 1162                        bytesConsumed = 0;
 1163                        value = default;
 1164                        return false;
 165                    }
 1166                    parsedValue = (parsedValue << 4) + nextDigit;
 1167                }
 1168            }
 169
 1170            bytesConsumed = text.Length;
 1171            value = (ushort)(parsedValue);
 1172            return true;
 1173        }
 174
 175        private static bool TryParseUInt32X(ReadOnlySpan<byte> text, out uint value, out int bytesConsumed)
 1176        {
 1177            if (text.Length < 1)
 1178            {
 1179                bytesConsumed = 0;
 1180                value = default;
 1181                return false;
 182            }
 183            byte nextCharacter;
 184            byte nextDigit;
 185
 186            // Cache Parsers.s_HexLookup in order to avoid static constructor checks
 1187            byte[] hexLookup = ParserHelpers.s_hexLookup;
 188
 189            // Parse the first digit separately. If invalid here, we need to return false.
 1190            nextCharacter = text[0];
 1191            nextDigit = hexLookup[nextCharacter];
 1192            if (nextDigit == 0xFF)
 1193            {
 1194                bytesConsumed = 0;
 1195                value = default;
 1196                return false;
 197            }
 1198            uint parsedValue = nextDigit;
 199
 1200            if (text.Length <= ParserHelpers.Int32OverflowLengthHex)
 1201            {
 202                // Length is less than or equal to Parsers.Int32OverflowLengthHex; overflow is not possible
 3203                for (int index = 1; index < text.Length; index++)
 1204                {
 1205                    nextCharacter = text[index];
 1206                    nextDigit = hexLookup[nextCharacter];
 1207                    if (nextDigit == 0xFF)
 1208                    {
 1209                        bytesConsumed = index;
 1210                        value = parsedValue;
 1211                        return true;
 212                    }
 1213                    parsedValue = (parsedValue << 4) + nextDigit;
 1214                }
 1215            }
 216            else
 1217            {
 218                // Length is greater than Parsers.Int32OverflowLengthHex; overflow is only possible after Parsers.Int32O
 219                // digits. There may be no overflow after Parsers.Int32OverflowLengthHex if there are leading zeroes.
 3220                for (int index = 1; index < ParserHelpers.Int32OverflowLengthHex; index++)
 1221                {
 1222                    nextCharacter = text[index];
 1223                    nextDigit = hexLookup[nextCharacter];
 1224                    if (nextDigit == 0xFF)
 1225                    {
 1226                        bytesConsumed = index;
 1227                        value = parsedValue;
 1228                        return true;
 229                    }
 1230                    parsedValue = (parsedValue << 4) + nextDigit;
 1231                }
 3232                for (int index = ParserHelpers.Int32OverflowLengthHex; index < text.Length; index++)
 1233                {
 1234                    nextCharacter = text[index];
 1235                    nextDigit = hexLookup[nextCharacter];
 1236                    if (nextDigit == 0xFF)
 1237                    {
 1238                        bytesConsumed = index;
 1239                        value = parsedValue;
 1240                        return true;
 241                    }
 242                    // If we try to append a digit to anything larger than uint.MaxValue / 0x10, there will be overflow
 1243                    if (parsedValue > uint.MaxValue / 0x10)
 1244                    {
 1245                        bytesConsumed = 0;
 1246                        value = default;
 1247                        return false;
 248                    }
 1249                    parsedValue = (parsedValue << 4) + nextDigit;
 1250                }
 1251            }
 252
 1253            bytesConsumed = text.Length;
 1254            value = parsedValue;
 1255            return true;
 1256        }
 257
 258        private static bool TryParseUInt64X(ReadOnlySpan<byte> text, out ulong value, out int bytesConsumed)
 1259        {
 1260            if (text.Length < 1)
 1261            {
 1262                bytesConsumed = 0;
 1263                value = default;
 1264                return false;
 265            }
 266            byte nextCharacter;
 267            byte nextDigit;
 268
 269            // Cache Parsers.s_HexLookup in order to avoid static constructor checks
 1270            byte[] hexLookup = ParserHelpers.s_hexLookup;
 271
 272            // Parse the first digit separately. If invalid here, we need to return false.
 1273            nextCharacter = text[0];
 1274            nextDigit = hexLookup[nextCharacter];
 1275            if (nextDigit == 0xFF)
 1276            {
 1277                bytesConsumed = 0;
 1278                value = default;
 1279                return false;
 280            }
 1281            ulong parsedValue = nextDigit;
 282
 1283            if (text.Length <= ParserHelpers.Int64OverflowLengthHex)
 1284            {
 285                // Length is less than or equal to Parsers.Int64OverflowLengthHex; overflow is not possible
 3286                for (int index = 1; index < text.Length; index++)
 1287                {
 1288                    nextCharacter = text[index];
 1289                    nextDigit = hexLookup[nextCharacter];
 1290                    if (nextDigit == 0xFF)
 1291                    {
 1292                        bytesConsumed = index;
 1293                        value = parsedValue;
 1294                        return true;
 295                    }
 1296                    parsedValue = (parsedValue << 4) + nextDigit;
 1297                }
 1298            }
 299            else
 1300            {
 301                // Length is greater than Parsers.Int64OverflowLengthHex; overflow is only possible after Parsers.Int64O
 302                // digits. There may be no overflow after Parsers.Int64OverflowLengthHex if there are leading zeroes.
 3303                for (int index = 1; index < ParserHelpers.Int64OverflowLengthHex; index++)
 1304                {
 1305                    nextCharacter = text[index];
 1306                    nextDigit = hexLookup[nextCharacter];
 1307                    if (nextDigit == 0xFF)
 1308                    {
 1309                        bytesConsumed = index;
 1310                        value = parsedValue;
 1311                        return true;
 312                    }
 1313                    parsedValue = (parsedValue << 4) + nextDigit;
 1314                }
 3315                for (int index = ParserHelpers.Int64OverflowLengthHex; index < text.Length; index++)
 1316                {
 1317                    nextCharacter = text[index];
 1318                    nextDigit = hexLookup[nextCharacter];
 1319                    if (nextDigit == 0xFF)
 1320                    {
 1321                        bytesConsumed = index;
 1322                        value = parsedValue;
 1323                        return true;
 324                    }
 325                    // If we try to append a digit to anything larger than ulong.MaxValue / 0x10, there will be overflow
 1326                    if (parsedValue > ulong.MaxValue / 0x10)
 1327                    {
 1328                        bytesConsumed = 0;
 1329                        value = default;
 1330                        return false;
 331                    }
 1332                    parsedValue = (parsedValue << 4) + nextDigit;
 1333                }
 1334            }
 335
 1336            bytesConsumed = text.Length;
 1337            value = parsedValue;
 1338            return true;
 1339        }
 340    }
 341}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5using System.Diagnostics;
 6
 7namespace System.Buffers.Text
 8{
 9    public static partial class Utf8Parser
 10    {
 11        [Flags]
 12        private enum ParseNumberOptions
 13        {
 14            AllowExponent = 0x00000001,
 15        }
 16
 17        private static bool TryParseNumber(ReadOnlySpan<byte> text, ref NumberBuffer number, out int bytesConsumed, Pars
 118        {
 119            Debug.Assert(number.Digits[0] == 0 && number.Scale == 0 && !number.IsNegative, "Number not initialized to de
 20
 121            textUsedExponentNotation = false;
 22
 123            if (text.Length == 0)
 124            {
 125                bytesConsumed = 0;
 126                return false;
 27            }
 28
 129            Span<byte> digits = number.Digits;
 30
 131            int srcIndex = 0;
 132            int dstIndex = 0;
 33
 34            // Consume the leading sign if any.
 135            byte c = text[srcIndex];
 136            switch (c)
 37            {
 38                case Utf8Constants.Minus:
 139                    number.IsNegative = true;
 140                    goto case Utf8Constants.Plus;
 41
 42                case Utf8Constants.Plus:
 143                    srcIndex++;
 144                    if (srcIndex == text.Length)
 145                    {
 146                        bytesConsumed = 0;
 147                        return false;
 48                    }
 149                    c = text[srcIndex];
 150                    break;
 51
 52                default:
 153                    break;
 54            }
 55
 156            int startIndexDigitsBeforeDecimal = srcIndex;
 57
 58            // Throw away any leading zeroes
 159            while (srcIndex != text.Length)
 160            {
 161                c = text[srcIndex];
 162                if (c != '0')
 163                    break;
 164                srcIndex++;
 165            }
 66
 167            if (srcIndex == text.Length)
 168            {
 169                digits[0] = 0;
 170                number.Scale = 0;
 171                bytesConsumed = srcIndex;
 172                number.CheckConsistency();
 173                return true;
 74            }
 75
 176            int startIndexNonLeadingDigitsBeforeDecimal = srcIndex;
 177            while (srcIndex != text.Length)
 178            {
 179                c = text[srcIndex];
 180                if ((c - 48u) > 9)
 181                    break;
 182                srcIndex++;
 183            }
 84
 185            int numDigitsBeforeDecimal = srcIndex - startIndexDigitsBeforeDecimal;
 186            int numNonLeadingDigitsBeforeDecimal = srcIndex - startIndexNonLeadingDigitsBeforeDecimal;
 87
 188            Debug.Assert(dstIndex == 0);
 189            int numNonLeadingDigitsBeforeDecimalToCopy = Math.Min(numNonLeadingDigitsBeforeDecimal, NumberBuffer.BufferS
 190            text.Slice(startIndexNonLeadingDigitsBeforeDecimal, numNonLeadingDigitsBeforeDecimalToCopy).CopyTo(digits);
 191            dstIndex = numNonLeadingDigitsBeforeDecimalToCopy;
 192            number.Scale = numNonLeadingDigitsBeforeDecimal;
 93
 194            if (srcIndex == text.Length)
 195            {
 196                bytesConsumed = srcIndex;
 197                number.CheckConsistency();
 198                return true;
 99            }
 100
 1101            int numDigitsAfterDecimal = 0;
 1102            if (c == Utf8Constants.Period)
 1103            {
 104                //
 105                // Parse the digits after the decimal point.
 106                //
 107
 1108                srcIndex++;
 1109                int startIndexDigitsAfterDecimal = srcIndex;
 1110                while (srcIndex != text.Length)
 1111                {
 1112                    c = text[srcIndex];
 1113                    if ((c - 48u) > 9)
 1114                        break;
 1115                    srcIndex++;
 1116                }
 1117                numDigitsAfterDecimal = srcIndex - startIndexDigitsAfterDecimal;
 118
 1119                int startIndexOfDigitsAfterDecimalToCopy = startIndexDigitsAfterDecimal;
 1120                if (dstIndex == 0)
 1121                {
 122                    // Not copied any digits to the Number struct yet. This means we must continue discarding leading ze
 1123                    while (startIndexOfDigitsAfterDecimalToCopy < srcIndex && text[startIndexOfDigitsAfterDecimalToCopy]
 1124                    {
 1125                        number.Scale--;
 1126                        startIndexOfDigitsAfterDecimalToCopy++;
 1127                    }
 1128                }
 129
 1130                int numDigitsAfterDecimalToCopy = Math.Min(srcIndex - startIndexOfDigitsAfterDecimalToCopy, NumberBuffer
 1131                text.Slice(startIndexOfDigitsAfterDecimalToCopy, numDigitsAfterDecimalToCopy).CopyTo(digits.Slice(dstInd
 1132                dstIndex += numDigitsAfterDecimalToCopy;
 133                // We "should" really NUL terminate, but there are multiple places we'd have to do this and it is a prec
 134
 1135                if (srcIndex == text.Length)
 1136                {
 1137                    if (numDigitsBeforeDecimal == 0 && numDigitsAfterDecimal == 0)
 1138                    {
 139                        // For compatibility. You can say "5." and ".5" but you can't say "."
 1140                        bytesConsumed = 0;
 1141                        return false;
 142                    }
 143
 1144                    bytesConsumed = srcIndex;
 1145                    number.CheckConsistency();
 1146                    return true;
 147                }
 1148            }
 149
 1150            if (numDigitsBeforeDecimal == 0 && numDigitsAfterDecimal == 0)
 1151            {
 1152                bytesConsumed = 0;
 1153                return false;
 154            }
 155
 1156            if ((c & ~0x20u) != 'E')
 1157            {
 1158                bytesConsumed = srcIndex;
 1159                number.CheckConsistency();
 1160                return true;
 161            }
 162
 163            //
 164            // Parse the exponent after the "E"
 165            //
 1166            textUsedExponentNotation = true;
 1167            srcIndex++;
 168
 1169            if ((options & ParseNumberOptions.AllowExponent) == 0)
 1170            {
 1171                bytesConsumed = 0;
 1172                return false;
 173            }
 174
 1175            if (srcIndex == text.Length)
 1176            {
 1177                bytesConsumed = 0;
 1178                return false;
 179            }
 180
 1181            bool exponentIsNegative = false;
 1182            c = text[srcIndex];
 1183            switch (c)
 184            {
 185                case Utf8Constants.Minus:
 1186                    exponentIsNegative = true;
 1187                    goto case Utf8Constants.Plus;
 188
 189                case Utf8Constants.Plus:
 1190                    srcIndex++;
 1191                    if (srcIndex == text.Length)
 1192                    {
 1193                        bytesConsumed = 0;
 1194                        return false;
 195                    }
 1196                    c = text[srcIndex];
 1197                    break;
 198
 199                default:
 1200                    break;
 201            }
 202
 1203            if (!Utf8Parser.TryParseUInt32D(text.Slice(srcIndex), out uint absoluteExponent, out int bytesConsumedByExpo
 1204            {
 1205                bytesConsumed = 0;
 1206                return false;
 207            }
 208
 1209            srcIndex += bytesConsumedByExponent;
 210
 1211            if (exponentIsNegative)
 1212            {
 1213                if (number.Scale < int.MinValue + (long)absoluteExponent)
 1214                {
 215                    // A scale underflow means all non-zero digits are all so far to the right of the decimal point, no
 216                    // number format we have will be able to see them. Just pin the scale at the absolute minimum
 217                    // and let the converter produce a 0 with the max precision available for that type.
 1218                    number.Scale = int.MinValue;
 1219                }
 220                else
 1221                {
 1222                    number.Scale -= (int)absoluteExponent;
 1223                }
 1224            }
 225            else
 1226            {
 1227                if (number.Scale > int.MaxValue - (long)absoluteExponent)
 1228                {
 1229                    bytesConsumed = 0;
 1230                    return false;
 231                }
 1232                number.Scale += (int)absoluteExponent;
 1233            }
 234
 1235            bytesConsumed = srcIndex;
 1236            number.CheckConsistency();
 1237            return true;
 1238        }
 239    }
 240}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        private static bool TryParseTimeSpanBigG(ReadOnlySpan<byte> text, out TimeSpan value, out int bytesConsumed)
 110        {
 111            int srcIndex = 0;
 112            byte c = default;
 113            while (srcIndex != text.Length)
 114            {
 115                c = text[srcIndex];
 116                if (!(c == ' ' || c == '\t'))
 117                    break;
 118                srcIndex++;
 119            }
 20
 121            if (srcIndex == text.Length)
 122            {
 123                value = default;
 124                bytesConsumed = 0;
 125                return false;
 26            }
 27
 128            bool isNegative = false;
 129            if (c == Utf8Constants.Minus)
 130            {
 131                isNegative = true;
 132                srcIndex++;
 133                if (srcIndex == text.Length)
 134                {
 135                    value = default;
 136                    bytesConsumed = 0;
 137                    return false;
 38                }
 139            }
 40
 141            if (!TryParseUInt32D(text.Slice(srcIndex), out uint days, out int justConsumed))
 142            {
 143                value = default;
 144                bytesConsumed = 0;
 145                return false;
 46            }
 147            srcIndex += justConsumed;
 48
 149            if (srcIndex == text.Length || text[srcIndex++] != Utf8Constants.Colon)
 150            {
 151                value = default;
 152                bytesConsumed = 0;
 153                return false;
 54            }
 55
 156            if (!TryParseUInt32D(text.Slice(srcIndex), out uint hours, out justConsumed))
 157            {
 158                value = default;
 159                bytesConsumed = 0;
 160                return false;
 61            }
 162            srcIndex += justConsumed;
 63
 164            if (srcIndex == text.Length || text[srcIndex++] != Utf8Constants.Colon)
 165            {
 166                value = default;
 167                bytesConsumed = 0;
 168                return false;
 69            }
 70
 171            if (!TryParseUInt32D(text.Slice(srcIndex), out uint minutes, out justConsumed))
 172            {
 173                value = default;
 174                bytesConsumed = 0;
 175                return false;
 76            }
 177            srcIndex += justConsumed;
 78
 179            if (srcIndex == text.Length || text[srcIndex++] != Utf8Constants.Colon)
 180            {
 181                value = default;
 182                bytesConsumed = 0;
 183                return false;
 84            }
 85
 186            if (!TryParseUInt32D(text.Slice(srcIndex), out uint seconds, out justConsumed))
 187            {
 188                value = default;
 189                bytesConsumed = 0;
 190                return false;
 91            }
 192            srcIndex += justConsumed;
 93
 194            if (srcIndex == text.Length || text[srcIndex++] != Utf8Constants.Period)
 195            {
 196                value = default;
 197                bytesConsumed = 0;
 198                return false;
 99            }
 100
 1101            if (!TryParseTimeSpanFraction(text.Slice(srcIndex), out uint fraction, out justConsumed))
 1102            {
 1103                value = default;
 1104                bytesConsumed = 0;
 1105                return false;
 106            }
 107
 1108            srcIndex += justConsumed;
 109
 1110            if (!TryCreateTimeSpan(isNegative: isNegative, days: days, hours: hours, minutes: minutes, seconds: seconds,
 1111            {
 1112                value = default;
 1113                bytesConsumed = 0;
 1114                return false;
 115            }
 116
 117            //
 118            // There cannot legally be a sixth number. If the next character is a period or colon, treat this as a error
 119            // to indicate the start of a sixth number. Otherwise, treat as end of parse with data left over.
 120            //
 1121            if (srcIndex != text.Length && (text[srcIndex] == Utf8Constants.Period || text[srcIndex] == Utf8Constants.Co
 1122            {
 1123                value = default;
 1124                bytesConsumed = 0;
 1125                return false;
 126            }
 127
 1128            bytesConsumed = srcIndex;
 1129            return true;
 1130        }
 131    }
 132}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        private static bool TryParseTimeSpanC(ReadOnlySpan<byte> text, out TimeSpan value, out int bytesConsumed)
 110        {
 111            TimeSpanSplitter s = default;
 112            if (!s.TrySplitTimeSpan(text, periodUsedToSeparateDay: true, out bytesConsumed))
 113            {
 114                value = default;
 115                return false;
 16            }
 17
 118            bool isNegative = s.IsNegative;
 19
 20            bool success;
 121            switch (s.Separators)
 22            {
 23                case 0x00000000: // dd
 124                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: 0, minutes: 0, seconds: 0, fr
 125                    break;
 26
 27                case 0x01000000: // hh:mm
 128                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: 0,
 129                    break;
 30
 31                case 0x02010000: // dd.hh:mm
 132                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: s.V2, minutes: s.V3, seconds:
 133                    break;
 34
 35                case 0x01010000: // hh:mm:ss
 136                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: s.
 137                    break;
 38
 39                case 0x02010100: // dd.hh:mm:ss
 140                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: s.V2, minutes: s.V3, seconds:
 141                    break;
 42
 43                case 0x01010200: // hh:mm:ss.fffffff
 144                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: s.
 145                    break;
 46
 47                case 0x02010102: // dd.hh:mm:ss.fffffff
 148                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: s.V2, minutes: s.V3, seconds:
 149                    break;
 50
 51                default:
 152                    value = default;
 153                    success = false;
 154                    break;
 55            }
 56
 157            if (!success)
 158            {
 159                bytesConsumed = 0;
 160                return false;
 61            }
 62
 163            return true;
 164        }
 65    }
 66}
 67

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5using System.Diagnostics;
 6
 7namespace System.Buffers.Text
 8{
 9    public static partial class Utf8Parser
 10    {
 11        /// <summary>
 12        /// Parses a TimeSpan at the start of a Utf8 string.
 13        /// </summary>
 14        /// <param name="text">The Utf8 string to parse</param>
 15        /// <param name="value">Receives the parsed value</param>
 16        /// <param name="bytesConsumed">On a successful parse, receives the length in bytes of the substring that was pa
 17        /// <param name="standardFormat">Expected format of the Utf8 string</param>
 18        /// <returns>
 19        /// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
 20        /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set
 21        /// </returns>
 22        /// <remarks>
 23        /// Formats supported:
 24        ///     c/t/T (default) [-][d.]hh:mm:ss[.fffffff]             (constant format)
 25        ///     G               [-]d:hh:mm:ss.fffffff                 (general long)
 26        ///     g               [-][d:]h:mm:ss[.f[f[f[f[f[f[f[]]]]]]] (general short)
 27        /// </remarks>
 28        /// <exceptions>
 29        /// <cref>System.FormatException</cref> if the format is not valid for this data type.
 30        /// </exceptions>
 31        public static bool TryParse(ReadOnlySpan<byte> text, out TimeSpan value, out int bytesConsumed, char standardFor
 132        {
 133            switch (standardFormat)
 34            {
 35                case (default):
 36                case 'c':
 37                case 't':
 38                case 'T':
 139                    return TryParseTimeSpanC(text, out value, out bytesConsumed);
 40
 41                case 'G':
 142                    return TryParseTimeSpanBigG(text, out value, out bytesConsumed);
 43
 44                case 'g':
 145                    return TryParseTimeSpanLittleG(text, out value, out bytesConsumed);
 46
 47                default:
 148                    return ThrowHelper.TryParseThrowFormatException(out value, out bytesConsumed);
 49            }
 150        }
 51
 52        /// <summary>
 53        /// Parse the fraction portion of a TimeSpan. Must be 1..7 digits. If fewer than 7, zeroes are implied to the ri
 54        /// parser rejects the string (even if the extra digits are all zeroes.)
 55        /// </summary>
 56        private static bool TryParseTimeSpanFraction(ReadOnlySpan<byte> text, out uint value, out int bytesConsumed)
 157        {
 158            int srcIndex = 0;
 59
 160            if (srcIndex == text.Length)
 161            {
 162                value = default;
 163                bytesConsumed = 0;
 164                return false;
 65            }
 66
 167            uint digit = text[srcIndex] - 48u; // '0'
 168            if (digit > 9)
 169            {
 170                value = default;
 171                bytesConsumed = 0;
 172                return false;
 73            }
 174            srcIndex++;
 75
 176            uint fraction = digit;
 177            int digitCount = 1;
 78
 179            while (srcIndex != text.Length)
 180            {
 181                digit = text[srcIndex] - 48u; // '0'
 182                if (digit > 9)
 183                    break;
 184                srcIndex++;
 185                digitCount++;
 186                if (digitCount > Utf8Constants.DateTimeNumFractionDigits)
 187                {
 88                    // Yes, TimeSpan fraction parsing is that picky.
 189                    value = default;
 190                    bytesConsumed = 0;
 191                    return false;
 92                }
 193                fraction = 10 * fraction + digit;
 194            }
 95
 196            switch (digitCount)
 97            {
 98                case 7:
 199                    break;
 100
 101                case 6:
 1102                    fraction *= 10;
 1103                    break;
 104
 105                case 5:
 1106                    fraction *= 100;
 1107                    break;
 108
 109                case 4:
 1110                    fraction *= 1000;
 1111                    break;
 112
 113                case 3:
 1114                    fraction *= 10000;
 1115                    break;
 116
 117                case 2:
 1118                    fraction *= 100000;
 1119                    break;
 120
 121                default:
 1122                    Debug.Assert(digitCount == 1);
 1123                    fraction *= 1000000;
 1124                    break;
 125            }
 126
 1127            value = fraction;
 1128            bytesConsumed = srcIndex;
 1129            return true;
 1130        }
 131
 132        /// <summary>
 133        /// Overflow-safe TryCreateTimeSpan
 134        /// </summary>
 135        private static bool TryCreateTimeSpan(bool isNegative, uint days, uint hours, uint minutes, uint seconds, uint f
 1136        {
 137            const long MaxMilliSeconds = long.MaxValue / TimeSpan.TicksPerMillisecond;
 138            const long MinMilliSeconds = long.MinValue / TimeSpan.TicksPerMillisecond;
 139
 1140            Debug.Assert(days >= 0 && hours >= 0 && minutes >= 0 && seconds >= 00 && fraction >= 0);
 1141            if (hours > 23 || minutes > 59 || seconds > 59)
 1142            {
 1143                timeSpan = default;
 1144                return false;
 145            }
 146
 1147            Debug.Assert(fraction <= Utf8Constants.MaxDateTimeFraction); // This value comes from TryParseTimeSpanFracti
 148
 1149            long millisecondsWithoutFraction = (((long)days) * 3600 * 24 + ((long)hours) * 3600 + ((long)minutes) * 60 +
 150
 151            long ticks;
 1152            if (isNegative)
 1153            {
 1154                millisecondsWithoutFraction = -millisecondsWithoutFraction;
 1155                if (millisecondsWithoutFraction < MinMilliSeconds)
 1156                {
 1157                    timeSpan = default;
 1158                    return false;
 159                }
 160
 1161                long ticksWithoutFraction = millisecondsWithoutFraction * TimeSpan.TicksPerMillisecond;
 1162                if (ticksWithoutFraction < long.MinValue + fraction)
 1163                {
 1164                    timeSpan = default;
 1165                    return false;
 166                }
 167
 1168                ticks = ticksWithoutFraction - fraction;
 1169            }
 170            else
 1171            {
 1172                if (millisecondsWithoutFraction > MaxMilliSeconds)
 1173                {
 1174                    timeSpan = default;
 1175                    return false;
 176                }
 177
 1178                long ticksWithoutFraction = millisecondsWithoutFraction * TimeSpan.TicksPerMillisecond;
 1179                if (ticksWithoutFraction > long.MaxValue - fraction)
 1180                {
 1181                    timeSpan = default;
 1182                    return false;
 183                }
 184
 1185                ticks = ticksWithoutFraction + fraction;
 1186            }
 187
 1188            timeSpan = new TimeSpan(ticks);
 1189            return true;
 1190        }
 191    }
 192}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5namespace System.Buffers.Text
 6{
 7    public static partial class Utf8Parser
 8    {
 9        private static bool TryParseTimeSpanLittleG(ReadOnlySpan<byte> text, out TimeSpan value, out int bytesConsumed)
 110        {
 111            TimeSpanSplitter s = default;
 112            if (!s.TrySplitTimeSpan(text, periodUsedToSeparateDay: false, out bytesConsumed))
 113            {
 114                value = default;
 115                return false;
 16            }
 17
 118            bool isNegative = s.IsNegative;
 19
 20            bool success;
 121            switch (s.Separators)
 22            {
 23                case 0x00000000: // dd
 124                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: 0, minutes: 0, seconds: 0, fr
 125                    break;
 26
 27                case 0x01000000: // hh:mm
 128                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: 0,
 129                    break;
 30
 31                case 0x01010000: // hh:mm:ss
 132                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: s.
 133                    break;
 34
 35                case 0x01010100: // dd:hh:mm:ss
 136                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: s.V2, minutes: s.V3, seconds:
 137                    break;
 38
 39                case 0x01010200: // hh:mm:ss.fffffff
 140                    success = TryCreateTimeSpan(isNegative: isNegative, days: 0, hours: s.V1, minutes: s.V2, seconds: s.
 141                    break;
 42
 43                case 0x01010102: // dd:hh:mm:ss.fffffff
 144                    success = TryCreateTimeSpan(isNegative: isNegative, days: s.V1, hours: s.V2, minutes: s.V3, seconds:
 145                    break;
 46
 47                default:
 148                    value = default;
 149                    success = false;
 150                    break;
 51            }
 52
 153            if (!success)
 154            {
 155                bytesConsumed = 0;
 156                return false;
 57            }
 58
 159            return true;
 160        }
 61    }
 62}

C:\GitHub\corefx\src\System.Memory\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// See the LICENSE file in the project root for more information.
 4
 5using System.Diagnostics;
 6
 7namespace System.Buffers.Text
 8{
 9    public static partial class Utf8Parser
 10    {
 11        private enum ComponentParseResult : byte
 12        {
 13            // Do not change or add values in this enum unless you review every use of the TimeSpanSplitter.Separators f
 14            // ComponentParseResults" encoded as a 32-bit integer with each of its four bytes containing one of 0 (NoMor
 15            // (So a value of 0x01010200 means the string parsed as "nn:nn:nn.nnnnnnn")
 16            NoMoreData = 0,
 17            Colon = 1,
 18            Period = 2,
 19            ParseFailure = 3,
 20        }
 21
 22        private struct TimeSpanSplitter
 23        {
 24            public uint V1;
 25            public uint V2;
 26            public uint V3;
 27            public uint V4;
 28            public uint V5;
 29
 30            public bool IsNegative;
 31
 32            // Encodes an "array of four ComponentParseResults" as a 32-bit integer with each of its four bytes containi
 33            // (So a value of 0x01010200 means the string parsed as "nn:nn:nn.nnnnnnn")
 34            public uint Separators;
 35
 36            public bool TrySplitTimeSpan(ReadOnlySpan<byte> text, bool periodUsedToSeparateDay, out int bytesConsumed)
 137            {
 138                int srcIndex = 0;
 139                byte c = default;
 40
 41                // Unlike many other data types, TimeSpan allow leading whitespace.
 142                while (srcIndex != text.Length)
 143                {
 144                    c = text[srcIndex];
 145                    if (!(c == ' ' || c == '\t'))
 146                        break;
 147                    srcIndex++;
 148                }
 49
 150                if (srcIndex == text.Length)
 151                {
 152                    bytesConsumed = 0;
 153                    return false;
 54                }
 55
 56                // Check for an option negative sign. ('+' is not allowed.)
 157                if (c == Utf8Constants.Minus)
 158                {
 159                    IsNegative = true;
 160                    srcIndex++;
 161                    if (srcIndex == text.Length)
 162                    {
 163                        bytesConsumed = 0;
 164                        return false;
 65                    }
 166                }
 67
 68                // From here, we terminate on anything that's not a digit, ':' or '.' The '.' is only allowed after at l
 69                // been specified. If we see it earlier, we'll assume that's an error and fail out rather than treating 
 70
 71                //
 72                // Timespan has to start with a number - parse the first one.
 73                //
 174                if (!TryParseUInt32D(text.Slice(srcIndex), out V1, out int justConsumed))
 175                {
 176                    bytesConsumed = 0;
 177                    return false;
 78                }
 179                srcIndex += justConsumed;
 80
 81                ComponentParseResult result;
 82
 83                //
 84                // Split out the second number (if any) For the 'c' format, a period might validly appear here as it;s u
 85                // the fraction is always the fourth component at earliest, so if we do see a period at this stage, alwa
 86                // a fraction.
 87                //
 188                result = ParseComponent(text, neverParseAsFraction: periodUsedToSeparateDay, ref srcIndex, out V2);
 189                if (result == ComponentParseResult.ParseFailure)
 190                {
 191                    bytesConsumed = 0;
 192                    return false;
 93                }
 194                else if (result == ComponentParseResult.NoMoreData)
 195                {
 196                    bytesConsumed = srcIndex;
 197                    return true;
 98                }
 99                else
 1100                {
 1101                    Debug.Assert(result == ComponentParseResult.Colon || result == ComponentParseResult.Period);
 1102                    Separators |= ((uint)result) << 24;
 1103                }
 104
 105                //
 106                // Split out the third number (if any)
 107                //
 1108                result = ParseComponent(text, false, ref srcIndex, out V3);
 1109                if (result == ComponentParseResult.ParseFailure)
 1110                {
 1111                    bytesConsumed = 0;
 1112                    return false;
 113                }
 1114                else if (result == ComponentParseResult.NoMoreData)
 1115                {
 1116                    bytesConsumed = srcIndex;
 1117                    return true;
 118                }
 119                else
 1120                {
 1121                    Debug.Assert(result == ComponentParseResult.Colon || result == ComponentParseResult.Period);
 1122                    Separators |= ((uint)result) << 16;
 1123                }
 124
 125                //
 126                // Split out the fourth number (if any)
 127                //
 1128                result = ParseComponent(text, false, ref srcIndex, out V4);
 1129                if (result == ComponentParseResult.ParseFailure)
 1130                {
 1131                    bytesConsumed = 0;
 1132                    return false;
 133                }
 1134                else if (result == ComponentParseResult.NoMoreData)
 1135                {
 1136                    bytesConsumed = srcIndex;
 1137                    return true;
 138                }
 139                else
 1140                {
 1141                    Debug.Assert(result == ComponentParseResult.Colon || result == ComponentParseResult.Period);
 1142                    Separators |= ((uint)result) << 8;
 1143                }
 144
 145                //
 146                // Split out the fifth number (if any)
 147                //
 1148                result = ParseComponent(text, false, ref srcIndex, out V5);
 1149                if (result == ComponentParseResult.ParseFailure)
 1150                {
 1151                    bytesConsumed = 0;
 1152                    return false;
 153                }
 1154                else if (result == ComponentParseResult.NoMoreData)
 1155                {
 1156                    bytesConsumed = srcIndex;
 1157                    return true;
 158                }
 159                else
 1160                {
 1161                    Debug.Assert(result == ComponentParseResult.Colon || result == ComponentParseResult.Period);
 1162                    Separators |= (uint)result;
 1163                }
 164
 165                //
 166                // There cannot legally be a sixth number. If the next character is a period or colon, treat this as a e
 167                // to indicate the start of a sixth number. Otherwise, treat as end of parse with data left over.
 168                //
 1169                if (srcIndex != text.Length && (text[srcIndex] == Utf8Constants.Period || text[srcIndex] == Utf8Constant
 1170                {
 1171                    bytesConsumed = 0;
 1172                    return false;
 173                }
 174
 1175                bytesConsumed = srcIndex;
 1176                return true;
 1177            }
 178
 179            //
 180            // Look for a separator followed by an unsigned integer.
 181            //
 182            private static ComponentParseResult ParseComponent(ReadOnlySpan<byte> text, bool neverParseAsFraction, ref i
 1183            {
 1184                if (srcIndex == text.Length)
 1185                {
 1186                    value = default;
 1187                    return ComponentParseResult.NoMoreData;
 188                }
 189
 1190                byte c = text[srcIndex];
 1191                if (c == Utf8Constants.Colon || (c == Utf8Constants.Period && neverParseAsFraction))
 1192                {
 1193                    srcIndex++;
 194
 1195                    if (!TryParseUInt32D(text.Slice(srcIndex), out value, out int bytesConsumed))
 1196                    {
 1197                        value = default;
 1198                        return ComponentParseResult.ParseFailure;
 199                    }
 200
 1201                    srcIndex += bytesConsumed;
 1202                    return c == Utf8Constants.Colon ? ComponentParseResult.Colon : ComponentParseResult.Period;
 203                }
 1204                else if (c == Utf8Constants.Period)
 1205                {
 1206                    srcIndex++;
 207
 1208                    if (!TryParseTimeSpanFraction(text.Slice(srcIndex), out value, out int bytesConsumed))
 1209                    {
 1210                        value = default;
 1211                        return ComponentParseResult.ParseFailure;
 212                    }
 213
 1214                    srcIndex += bytesConsumed;
 1215                    return ComponentParseResult.Period;
 216                }
 217                else
 1218                {
 1219                    value = default;
 1220                    return ComponentParseResult.NoMoreData;
 221                }
 1222            }
 223        }
 224    }
 225}

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&)
.cctor()
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.Double&,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.Boolean,System.Char,System.Char,System.Guid&,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.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&)