Use Utf8Parser instead of custom code (#1200)

This commit is contained in:
BrennanConroy 2017-12-12 11:55:48 -08:00 committed by GitHub
parent 66ab939cff
commit 588d9cdb11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 2 additions and 93 deletions

View File

@ -2,13 +2,13 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Buffers.Text;
using System.Text;
namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
{
public static class LengthPrefixedTextMessageParser
{
private const int Int32OverflowLength = 10;
private const char FieldDelimiter = ':';
private const char MessageDelimiter = ';';
@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
var lengthSpan = buffer.Slice(0, index);
if (!TryParseInt32(lengthSpan, out length, out var bytesConsumed) || bytesConsumed < lengthSpan.Length)
if (!Utf8Parser.TryParse(buffer, out length, out var bytesConsumed) || bytesConsumed < lengthSpan.Length)
{
throw new FormatException($"Invalid length: '{Encoding.UTF8.GetString(lengthSpan.ToArray())}'");
}
@ -90,96 +90,5 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Encoders
return true;
}
private static bool TryParseInt32(ReadOnlySpan<byte> text, out int value, out int bytesConsumed)
{
if (text.Length < 1)
{
bytesConsumed = 0;
value = default;
return false;
}
int indexOfFirstDigit = 0;
int sign = 1;
if (text[0] == '-')
{
indexOfFirstDigit = 1;
sign = -1;
}
else if (text[0] == '+')
{
indexOfFirstDigit = 1;
}
int overflowLength = Int32OverflowLength + indexOfFirstDigit;
// Parse the first digit separately. If invalid here, we need to return false.
int firstDigit = text[indexOfFirstDigit] - 48; // '0'
if (firstDigit < 0 || firstDigit > 9)
{
bytesConsumed = 0;
value = default;
return false;
}
int parsedValue = firstDigit;
if (text.Length < overflowLength)
{
// Length is less than Int32OverflowLength; overflow is not possible
for (int index = indexOfFirstDigit + 1; index < text.Length; index++)
{
int nextDigit = text[index] - 48; // '0'
if (nextDigit < 0 || nextDigit > 9)
{
bytesConsumed = index;
value = parsedValue * sign;
return true;
}
parsedValue = parsedValue * 10 + nextDigit;
}
}
else
{
// Length is greater than Int32OverflowLength; overflow is only possible after Int32OverflowLength
// digits. There may be no overflow after Int32OverflowLength if there are leading zeroes.
for (int index = indexOfFirstDigit + 1; index < overflowLength - 1; index++)
{
int nextDigit = text[index] - 48; // '0'
if (nextDigit < 0 || nextDigit > 9)
{
bytesConsumed = index;
value = parsedValue * sign;
return true;
}
parsedValue = parsedValue * 10 + nextDigit;
}
for (int index = overflowLength - 1; index < text.Length; index++)
{
int nextDigit = text[index] - 48; // '0'
if (nextDigit < 0 || nextDigit > 9)
{
bytesConsumed = index;
value = parsedValue * sign;
return true;
}
// If parsedValue > (int.MaxValue / 10), any more appended digits will cause overflow.
// if parsedValue == (int.MaxValue / 10), any nextDigit greater than 7 or 8 (depending on sign) implies overflow.
bool positive = sign > 0;
bool nextDigitTooLarge = nextDigit > 8 || (positive && nextDigit > 7);
if (parsedValue > int.MaxValue / 10 || parsedValue == int.MaxValue / 10 && nextDigitTooLarge)
{
bytesConsumed = 0;
value = default;
return false;
}
parsedValue = parsedValue * 10 + nextDigit;
}
}
bytesConsumed = text.Length;
value = parsedValue * sign;
return true;
}
}
}