You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Utf8Parsing - the remaining 'N' format overloads (#26683)
* Utf8Parsing - the remaining 'N' format overloads
Fixes https://github.com/dotnet/corefx/issues/24986
This is a piece of the Utf8Parser that was punted for time
last year.
There are 8 overloads for each of the 8 integer types.
Int32 was done in a previous PR - this completes the set.
The "N" format prints out integers like this:
`"N2" => 12,345.00`
This parser mimics the behavior of
`int.TryParse(v, NumberStyles.Integer | AllowThousands | AllowDecimalPoint)`
The thing that may look strange is that the parser
allows commas anywhere, not just on the 10^3 digits.
This mimics the desktop api behavior. Comma placement is
culture-dependent and this is an api that is culture-agnostic.
The test data was confirmed on a control implementation
that calls the classic int.TryParse().
* Added comment
* Fix comment typo
// Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior with the classic parse routines
36
+
// (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
37
+
// one digit after the decimal point.)
38
+
if(c==Utf8Constants.Period)
39
+
gotoFractionalPartWithoutLeadingDigits;
40
+
if(!ParserHelpers.IsDigit(c))
41
+
gotoFalseExit;
42
+
answer=c-'0';
43
+
44
+
for(;;)
45
+
{
46
+
index++;
47
+
if((uint)index>=(uint)text.Length)
48
+
gotoDone;
49
+
50
+
c=text[index];
51
+
if(c==Utf8Constants.Comma)
52
+
continue;
53
+
54
+
if(c==Utf8Constants.Period)
55
+
gotoFractionalDigits;
56
+
57
+
if(!ParserHelpers.IsDigit(c))
58
+
gotoDone;
59
+
60
+
answer=answer*10+c-'0';
61
+
62
+
// if sign < 0, (-1 * sign + 1) / 2 = 1
63
+
// else, (-1 * sign + 1) / 2 = 0
64
+
if(answer>sbyte.MaxValue+(-1*sign+1)/2)
65
+
gotoFalseExit;// Overflow
66
+
}
67
+
68
+
FractionalPartWithoutLeadingDigits:// If we got here, we found a decimal point before we found any digits. This is legal as long as there's at least one zero after the decimal point.
69
+
answer=0;
70
+
index++;
71
+
if((uint)index>=(uint)text.Length)
72
+
gotoFalseExit;
73
+
if(text[index]!='0')
74
+
gotoFalseExit;
75
+
76
+
FractionalDigits:// "N" format allows a fractional portion despite being an integer format but only if the post-fraction digits are all 0.
77
+
do
78
+
{
79
+
index++;
80
+
if((uint)index>=(uint)text.Length)
81
+
gotoDone;
82
+
c=text[index];
83
+
}
84
+
while(c=='0');
85
+
86
+
if(ParserHelpers.IsDigit(c))
87
+
gotoFalseExit;// The fractional portion contained a non-zero digit. Treat this as an error, not an early termination.
// Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior with the classic parse routines
128
+
// (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
129
+
// one digit after the decimal point.)
130
+
if(c==Utf8Constants.Period)
131
+
gotoFractionalPartWithoutLeadingDigits;
132
+
if(!ParserHelpers.IsDigit(c))
133
+
gotoFalseExit;
134
+
answer=c-'0';
135
+
136
+
for(;;)
137
+
{
138
+
index++;
139
+
if((uint)index>=(uint)text.Length)
140
+
gotoDone;
141
+
142
+
c=text[index];
143
+
if(c==Utf8Constants.Comma)
144
+
continue;
145
+
146
+
if(c==Utf8Constants.Period)
147
+
gotoFractionalDigits;
148
+
149
+
if(!ParserHelpers.IsDigit(c))
150
+
gotoDone;
151
+
152
+
answer=answer*10+c-'0';
153
+
154
+
// if sign < 0, (-1 * sign + 1) / 2 = 1
155
+
// else, (-1 * sign + 1) / 2 = 0
156
+
if(answer>short.MaxValue+(-1*sign+1)/2)
157
+
gotoFalseExit;// Overflow
158
+
}
159
+
160
+
FractionalPartWithoutLeadingDigits:// If we got here, we found a decimal point before we found any digits. This is legal as long as there's at least one zero after the decimal point.
161
+
answer=0;
162
+
index++;
163
+
if((uint)index>=(uint)text.Length)
164
+
gotoFalseExit;
165
+
if(text[index]!='0')
166
+
gotoFalseExit;
167
+
168
+
FractionalDigits:// "N" format allows a fractional portion despite being an integer format but only if the post-fraction digits are all 0.
169
+
do
170
+
{
171
+
index++;
172
+
if((uint)index>=(uint)text.Length)
173
+
gotoDone;
174
+
c=text[index];
175
+
}
176
+
while(c=='0');
177
+
178
+
if(ParserHelpers.IsDigit(c))
179
+
gotoFalseExit;// The fractional portion contained a non-zero digit. Treat this as an error, not an early termination.
FractionalPartWithoutLeadingDigits:// If we got here, we found a decimal point before we found any digits. This is legal as long as there's at least one zero after the decimal point.
351
+
answer=0;
352
+
index++;
353
+
if((uint)index>=(uint)text.Length)
354
+
gotoFalseExit;
355
+
if(text[index]!='0')
356
+
gotoFalseExit;
357
+
358
+
FractionalDigits:// "N" format allows a fractional portion despite being an integer format but only if the post-fraction digits are all 0.
359
+
do
360
+
{
361
+
index++;
362
+
if((uint)index>=(uint)text.Length)
363
+
gotoDone;
364
+
c=text[index];
365
+
}
366
+
while(c=='0');
367
+
368
+
if(ParserHelpers.IsDigit(c))
369
+
gotoFalseExit;// The fractional portion contained a non-zero digit. Treat this as an error, not an early termination.
0 commit comments