public static bool TryParse(byte[] utf8Text, int index, FormattingData cultureAndEncodingInfo, Format.Parsed numericFormat, out ulong value, out int bytesConsumed) { // Precondition replacement if (utf8Text.Length < 1 || index < 0 || index >= utf8Text.Length) { value = default(ulong); bytesConsumed = 0; return false; } value = default(ulong); bytesConsumed = 0; if (cultureAndEncodingInfo.IsInvariantUtf8) { for (int byteIndex = index; byteIndex < utf8Text.Length; byteIndex++) // loop through the byte array { byte nextByteVal = (byte)(utf8Text[byteIndex] - '0'); if (nextByteVal > 9) // if nextByteVal > 9, we know it is not a digit because any value less than '0' will overflow // to greater than 9 since byte is an unsigned type. { if (bytesConsumed == 0) // check to see if we've processed any digits at all { return false; } else { return true; // otherwise return true } } else if (value > UInt64.MaxValue / 10) { value = default(ulong); bytesConsumed = 0; return false; } // This next check uses a hardcoded 6 because the max values for unsigned types all end in 5s. else if (value == UInt64.MaxValue / 10 && nextByteVal >= 6) // overflow { value = default(ulong); bytesConsumed = 0; return false; } value = (ulong)(value * 10 + nextByteVal); // left shift the value and add the nextByte bytesConsumed++; } return true; } else if (cultureAndEncodingInfo.IsInvariantUtf16) { for (int byteIndex = index; byteIndex < utf8Text.Length - 1; byteIndex += 2) // loop through the byte array two bytes at a time for UTF-16 { byte byteAfterNext = utf8Text[byteIndex + 1]; byte nextByteVal = (byte)(utf8Text[byteIndex] - '0'); if (nextByteVal > 9 || byteAfterNext != 0) // if the second byte isn't zero, this isn't an ASCII-equivalent code unit and we can quit here // if nextByteVal > 9, we know it is not a digit because any value less than '0' will overflow // to greater than 9 since byte is an unsigned type. { if (bytesConsumed == 0) // check to see if we've processed any digits at all { return false; } else { return true; // otherwise return true } } else if (value > UInt64.MaxValue / 10) { value = default(ulong); bytesConsumed = 0; return false; } // This next check uses a hardcoded 6 because the max values for unsigned types all end in 5s. else if (value == UInt64.MaxValue / 10 && nextByteVal >= 6) // overflow { value = default(ulong); bytesConsumed = 0; return false; } value = (ulong)(value * 10 + nextByteVal); // left shift the value and add the nextByte bytesConsumed += 2; } return true; } else { int byteIndex = index; while (byteIndex < utf8Text.Length) { uint result; int oldIndex = byteIndex; bool success = cultureAndEncodingInfo.TryParseNextCodingUnit(ref utf8Text, ref byteIndex, out result); if (!success || result > 9) { if (bytesConsumed == 0) // check to see if we've processed any digits at all { return false; } else { return true; // otherwise return true } } else if (value > UInt64.MaxValue / 10) { value = default(ulong); bytesConsumed = 0; return false; } // This next check uses a hardcoded 6 because the max values for unsigned types all end in 5s. else if (value == UInt64.MaxValue / 10 && result >= 6) // overflow { value = default(ulong); bytesConsumed = 0; return false; } value = (ulong)(value * 10 + result); // left shift the value and add the nextByte bytesConsumed += byteIndex - oldIndex; } return true; } }
public static bool TryParse(byte[] utf8Text, int index, FormattingData cultureAndEncodingInfo, Format.Parsed numericFormat, out int value, out int bytesConsumed) { // Precondition replacement if (utf8Text.Length < 1 || index < 0 || index >= utf8Text.Length) { value = default(int); bytesConsumed = 0; return false; } value = default(int); bytesConsumed = 0; bool negative = false; bool signed = false; if (cultureAndEncodingInfo.IsInvariantUtf8) { if (utf8Text[index] == '-') { negative = true; signed = true; index++; bytesConsumed++; } else if (utf8Text[index] == '+') { signed = true; index++; bytesConsumed++; } for (int byteIndex = index; byteIndex < utf8Text.Length; byteIndex++) // loop through the byte array { byte nextByteVal = (byte)(utf8Text[byteIndex] - '0'); if (nextByteVal > 9) // if nextByteVal > 9, we know it is not a digit because any value less than '0' will overflow // to greater than 9 since byte is an unsigned type. { if (bytesConsumed == 1 && signed) // if the first character happened to be a '-' or a '+', we reset the byte counter so logic proceeds as normal. { bytesConsumed = 0; } if (bytesConsumed == 0) // check to see if we've processed any digits at all { return false; } else { if (negative) // We check if the value is negative at the very end to save on comp time { value = (int)-value; if (value > 0) { value = 0; bytesConsumed = 0; return false; } } return true; // otherwise return true } } else if (value > Int32.MaxValue / 10) // overflow { value = default(int); bytesConsumed = 0; return false; } // This next check uses a hardcoded 8 because the max values for unsigned types all end in 7s. // The min values all end in 8s, which is why that addition exists. else if (value == Int32.MaxValue / 10 && nextByteVal >= 8 + (negative ? 1 : 0) ) // overflow { value = default(int); bytesConsumed = 0; return false; } value = (int)(value * 10 + nextByteVal); // parse the current digit to a int and add it to the left-shifted value bytesConsumed++; // increment the number of bytes consumed, then loop } if (negative) // We check if the value is negative at the very end to save on comp time { value = (int)-value; if (value > 0) { value = 0; bytesConsumed = 0; return false; } } return true; } else if (cultureAndEncodingInfo.IsInvariantUtf16) { if (utf8Text[index] == '-' && utf8Text[index + 1] == 0) { negative = true; signed = true; index += 2; bytesConsumed += 2; } else if (utf8Text[index] == '+' && utf8Text[index + 1] == 0) { signed = true; index += 2; bytesConsumed += 2; } for (int byteIndex = index; byteIndex < utf8Text.Length - 1; byteIndex += 2) // loop through the byte array two bytes at a time for UTF-16 { byte byteAfterNext = utf8Text[byteIndex + 1]; byte nextByteVal = (byte)(utf8Text[byteIndex] - '0'); if (nextByteVal > 9 || byteAfterNext != 0) // if the second byte isn't zero, this isn't an ASCII-equivalent code unit and we can quit here // if nextByteVal > 9, we know it is not a digit because any value less than '0' will overflow // to greater than 9 since byte is an unsigned type. { if (bytesConsumed == 2 && signed) // if the first character happened to be a '-' or a '+', we reset the byte counter so logic proceeds as normal { bytesConsumed = 0; } if (bytesConsumed == 0) // check to see if we've processed any digits at all { return false; } else { if (negative) // We check if the value is negative at the very end to save on comp time { value = (int)-value; if (value > 0) { value = 0; bytesConsumed = 0; return false; } } return true; // otherwise return true } } else if (value > Int32.MaxValue / 10) // overflow { value = default(int); bytesConsumed = 0; return false; } // This next check uses a hardcoded 8 because the max values for unsigned types all end in 7s. // The min values all end in 8s, which is why that addition exists. else if (value == Int32.MaxValue / 10 && nextByteVal >= 8 + (negative ? 1 : 0) ) // overflow { value = default(int); bytesConsumed = 0; return false; } value = (int)(value * 10 + nextByteVal); // parse the current digit to a int and add it to the left-shifted value bytesConsumed += 2; // increment the number of bytes consumed, then loop } if (negative) // We check if the value is negative at the very end to save on comp time { value = (int)-value; if (value > 0) { value = 0; bytesConsumed = 0; return false; } } return true; } else { int byteIndex = index; int codeUnitsConsumed = 0; while (byteIndex < utf8Text.Length) { uint result; int oldIndex = byteIndex; bool success = cultureAndEncodingInfo.TryParseNextCodingUnit(ref utf8Text, ref byteIndex, out result); if (!success || result > 9) { if (bytesConsumed == 0 && result == (int)FormattingData.Symbol.MinusSign) { negative = true; signed = true; bytesConsumed += byteIndex - oldIndex; codeUnitsConsumed++; } else if (bytesConsumed == 0 && result == (int)FormattingData.Symbol.PlusSign) { negative = true; signed = true; bytesConsumed += byteIndex - oldIndex; } else if (codeUnitsConsumed == 1 && signed) // if the first character happened to be a '-' or a '+', we reset the byte counter so logic proceeds as normal. { bytesConsumed = 0; return false; } else if (bytesConsumed == 0) // check to see if we've processed any digits at all { return false; } else { if (negative) // We check if the value is negative at the very end to save on comp time { value = (int)-value; if (value > 0) { value = 0; bytesConsumed = 0; return false; } } return true; // otherwise return true } } else if (value > Int32.MaxValue / 10) { value = default(int); bytesConsumed = 0; return false; } // This next check uses a hardcoded 8 because the max values for unsigned types all end in 7s. // The min values all end in 8s, which is why that addition exists. else if (value == Int32.MaxValue / 10 && result >= 8 + (negative ? 1 : 0) ) // overflow { value = default(int); bytesConsumed = 0; return false; } else { value = (int)(value * 10 + result); // left shift the value and add the nextByte bytesConsumed += byteIndex - oldIndex; codeUnitsConsumed++; } } if (negative) // We check if the value is negative at the very end to save on comp time { value = (int)-value; if (value > 0) { value = default(int); bytesConsumed = 0; return false; } } return true; // otherwise return true } }