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;
            }
        }
Ejemplo n.º 2
0
		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
			}
        }