public static bool TryParseUInt32(byte[] text, int index, EncodingData encoding, TextFormat numericFormat,
            out uint value, out int bytesConsumed)
		{
			// Precondition replacement
            if (text.Length < 1 || index < 0 || index >= text.Length)
            {
                value = default(uint);
                bytesConsumed = 0;
                return false;
            }

            value = default(uint);
            bytesConsumed = 0;

            if (encoding.IsInvariantUtf8)
            {
                for (int byteIndex = index; byteIndex < text.Length; byteIndex++) // loop through the byte array
                {
                    byte nextByteVal = (byte)(text[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 > UInt32.MaxValue / 10)
                    {
                        value = default(uint);
                        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 == UInt32.MaxValue / 10 &&  nextByteVal >= 6) // overflow
                    {
                        value = default(uint);
                        bytesConsumed = 0;
                        return false;
                    }

                    value = (uint)(value * 10 + nextByteVal); // left shift the value and add the nextByte
                    bytesConsumed++;
                }
				return true;
            }
            else if (encoding.IsInvariantUtf16)
            {
                for (int byteIndex = index; byteIndex < text.Length - 1; byteIndex += 2) // loop through the byte array two bytes at a time for UTF-16
                {
                    byte byteAfterNext = text[byteIndex + 1];
                    byte nextByteVal = (byte)(text[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 > UInt32.MaxValue / 10)
                    {
                        value = default(uint);
                        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 == UInt32.MaxValue / 10 &&  nextByteVal >= 6) // overflow
                    {
                        value = default(uint);
                        bytesConsumed = 0;
                        return false;
                    }

                    value = (uint)(value * 10 + nextByteVal); // left shift the value and add the nextByte
                    bytesConsumed += 2;
                }
                return true;
            }
			else
            {
                while (bytesConsumed + index < text.Length)
                {
                    uint result;
					int consumed;
                    bool success = encoding.TryParseSymbol(text.Slice(bytesConsumed + index), out result, out consumed);

                    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 > UInt32.MaxValue / 10)
                    {
                        value = default(uint);
                        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 == UInt32.MaxValue / 10 && result >= 6) // overflow
                    {
                        value = default(uint);
                        bytesConsumed = 0;
                        return false;
                    }

                    value = (uint)(value * 10 + result); // left shift the value and add the nextByte
                    bytesConsumed += consumed;
                }

                return true;
            }
        }
Esempio n. 2
0
        public static bool TryParseUInt64(ReadOnlySpan <byte> text, out ulong value, out int bytesConsumed, TextFormat format = default(TextFormat), EncodingData encoding = default(EncodingData))
        {
            if (encoding == default(EncodingData))
            {
                encoding = EncodingData.InvariantUtf8;
            }

            if (!format.IsDefault && format.HasPrecision)
            {
                throw new NotImplementedException("Format with precision not supported.");
            }

            if (encoding.IsInvariantUtf8)
            {
                if (format.IsHexadecimal)
                {
                    return(InvariantUtf8.Hex.TryParseUInt64(text, out value, out bytesConsumed));
                }
                else
                {
                    return(InvariantUtf8.TryParseUInt64(text, out value, out bytesConsumed));
                }
            }
            else if (encoding.IsInvariantUtf16)
            {
                ReadOnlySpan <char> utf16Text = text.Cast <byte, char>();
                int  charsConsumed;
                bool result;
                if (format.IsHexadecimal)
                {
                    result = InvariantUtf16.Hex.TryParseUInt64(utf16Text, out value, out charsConsumed);
                }
                else
                {
                    result = InvariantUtf16.TryParseUInt64(utf16Text, out value, out charsConsumed);
                }
                bytesConsumed = charsConsumed * sizeof(char);
                return(result);
            }

            if (format.IsHexadecimal)
            {
                throw new NotImplementedException("The only supported encodings for hexadecimal parsing are InvariantUtf8 and InvariantUtf16.");
            }

            if (!(format.IsDefault || format.Symbol == 'G' || format.Symbol == 'g'))
            {
                throw new NotImplementedException(String.Format("Format '{0}' not supported.", format.Symbol));
            }

            uint nextSymbol;
            int  thisSymbolConsumed;

            if (!encoding.TryParseSymbol(text, out nextSymbol, out thisSymbolConsumed))
            {
                value         = default(ulong);
                bytesConsumed = 0;
                return(false);
            }

            if (nextSymbol > 9)
            {
                value         = default(ulong);
                bytesConsumed = 0;
                return(false);
            }

            ulong parsedValue = nextSymbol;
            int   index       = thisSymbolConsumed;

            while (index < text.Length)
            {
                bool success = encoding.TryParseSymbol(text.Slice(index), out nextSymbol, out thisSymbolConsumed);
                if (!success || nextSymbol > 9)
                {
                    bytesConsumed = index;
                    value         = (ulong)parsedValue;
                    return(true);
                }

                // If parsedValue > (ulong.MaxValue / 10), any more appended digits will cause overflow.
                // if parsedValue == (ulong.MaxValue / 10), any nextDigit greater than 5 implies overflow.
                if (parsedValue > ulong.MaxValue / 10 || (parsedValue == ulong.MaxValue / 10 && nextSymbol > 5))
                {
                    bytesConsumed = 0;
                    value         = default(ulong);
                    return(false);
                }

                index      += thisSymbolConsumed;
                parsedValue = parsedValue * 10 + nextSymbol;
            }

            bytesConsumed = text.Length;
            value         = (ulong)parsedValue;
            return(true);
        }
Esempio n. 3
0
        public static bool TryParseInt64(ReadOnlySpan <byte> text, out long value, out int bytesConsumed, EncodingData encoding = default(EncodingData), TextFormat format = default(TextFormat))
        {
            if (format.HasPrecision)
            {
                throw new NotImplementedException("Format with precision not supported.");
            }

            if (encoding.IsInvariantUtf8)
            {
                if (format.IsHexadecimal)
                {
                    return(InvariantUtf8.Hex.TryParseInt64(text, out value, out bytesConsumed));
                }
                else
                {
                    return(InvariantUtf8.TryParseInt64(text, out value, out bytesConsumed));
                }
            }
            else if (encoding.IsInvariantUtf16)
            {
                ReadOnlySpan <char> utf16Text = text.Cast <byte, char>();
                int  charsConsumed;
                bool result;
                if (format.IsHexadecimal)
                {
                    result = InvariantUtf16.Hex.TryParseInt64(utf16Text, out value, out charsConsumed);
                }
                else
                {
                    result = InvariantUtf16.TryParseInt64(utf16Text, out value, out charsConsumed);
                }
                bytesConsumed = charsConsumed * sizeof(char);
                return(result);
            }

            if (format.IsHexadecimal)
            {
                throw new NotImplementedException("The only supported encodings for hexadecimal parsing are InvariantUtf8 and InvariantUtf16.");
            }

            if (!(format.IsDefault || format.Symbol == 'G' || format.Symbol == 'g'))
            {
                throw new NotImplementedException(String.Format("Format '{0}' not supported.", format.Symbol));
            }

            uint nextSymbol;
            int  thisSymbolConsumed;

            if (!encoding.TryParseSymbol(text, out nextSymbol, out thisSymbolConsumed))
            {
                value         = default(long);
                bytesConsumed = 0;
                return(false);
            }

            int sign = 1;

            if ((EncodingData.Symbol)nextSymbol == EncodingData.Symbol.MinusSign)
            {
                sign = -1;
            }

            int signConsumed = 0;

            if ((EncodingData.Symbol)nextSymbol == EncodingData.Symbol.PlusSign || (EncodingData.Symbol)nextSymbol == EncodingData.Symbol.MinusSign)
            {
                signConsumed = thisSymbolConsumed;
                if (!encoding.TryParseSymbol(text.Slice(signConsumed), out nextSymbol, out thisSymbolConsumed))
                {
                    value         = default(long);
                    bytesConsumed = 0;
                    return(false);
                }
            }

            if (nextSymbol > 9)
            {
                value         = default(long);
                bytesConsumed = 0;
                return(false);
            }

            long parsedValue = (long)nextSymbol;
            int  index       = signConsumed + thisSymbolConsumed;

            while (index < text.Length)
            {
                bool success = encoding.TryParseSymbol(text.Slice(index), out nextSymbol, out thisSymbolConsumed);
                if (!success || nextSymbol > 9)
                {
                    bytesConsumed = index;
                    value         = (long)(parsedValue * sign);
                    return(true);
                }

                // If parsedValue > (long.MaxValue / 10), any more appended digits will cause overflow.
                // if parsedValue == (long.MaxValue / 10), any nextDigit greater than 7 or 8 (depending on sign) implies overflow.
                bool positive          = sign > 0;
                bool nextDigitTooLarge = nextSymbol > 8 || (positive && nextSymbol > 7);
                if (parsedValue > long.MaxValue / 10 || (parsedValue == long.MaxValue / 10 && nextDigitTooLarge))
                {
                    bytesConsumed = 0;
                    value         = default(long);
                    return(false);
                }

                index      += thisSymbolConsumed;
                parsedValue = parsedValue * 10 + (long)nextSymbol;
            }

            bytesConsumed = text.Length;
            value         = (long)(parsedValue * sign);
            return(true);
        }
		public static bool TryParseInt16(byte[] text, int index, EncodingData encoding, TextFormat numericFormat,
            out short value, out int bytesConsumed)
        {
            // Precondition replacement
            if (text.Length < 1 || index < 0 || index >= text.Length)
            {
                value = default(short);
                bytesConsumed = 0;
                return false;
            }

            value = default(short);
            bytesConsumed = 0;
            bool negative = false;
            bool signed = false;

            if (encoding.IsInvariantUtf8)
            {
                if (text[index] == '-')
                {
                    negative = true;
                    signed = true;
                    index++;
                    bytesConsumed++;
                }
                else if (text[index] == '+')
                {
                    signed = true;
                    index++;
                    bytesConsumed++;
                }

                for (int byteIndex = index; byteIndex < text.Length; byteIndex++) // loop through the byte array
                {
                    byte nextByteVal = (byte)(text[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 = (short)-value;
								if (value > 0)
								{
									value = 0;
									bytesConsumed = 0;
									return false;
								}
                            }
                            return true; // otherwise return true
                        }
                    }
                    else if (value > Int16.MaxValue / 10) // overflow
                    {
                        value = default(short);
                        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 == Int16.MaxValue / 10 &&  nextByteVal >= 8 + (negative ? 1 : 0) ) // overflow
                    {
                        value = default(short);
                        bytesConsumed = 0;
                        return false;
                    }
                    value = (short)(value * 10 + nextByteVal); // parse the current digit to a short 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 = (short)-value;
					if (value > 0)
					{
						value = 0;
						bytesConsumed = 0;
						return false;
					}
				}
                return true;
            }
            else if (encoding.IsInvariantUtf16)
            {
                if (text[index] == '-' && text[index + 1] == 0)
                {
                    negative = true;
                    signed = true;
                    index += 2;
                    bytesConsumed += 2;
                }
                else if (text[index] == '+' && text[index + 1] == 0)
                {
                    signed = true;
                    index += 2;
                    bytesConsumed += 2;
                }

                for (int byteIndex = index; byteIndex < text.Length - 1; byteIndex += 2) // loop through the byte array two bytes at a time for UTF-16
                {
                    byte byteAfterNext = text[byteIndex + 1];
                    byte nextByteVal = (byte)(text[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 = (short)-value;
								if (value > 0)
								{
									value = 0;
									bytesConsumed = 0;
									return false;
								}
							}
                            return true; // otherwise return true
                        }
                    }
                    else if (value > Int16.MaxValue / 10) // overflow
                    {
                        value = default(short);
                        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 == Int16.MaxValue / 10 &&  nextByteVal >= 8 + (negative ? 1 : 0) ) // overflow
                    {
                        value = default(short);
                        bytesConsumed = 0;
                        return false;
                    }
                    value = (short)(value * 10 + nextByteVal); // parse the current digit to a short 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 = (short)-value;
					if (value > 0)
					{
						value = 0;
						bytesConsumed = 0;
						return false;
					}
				}
                return true;
            }
			else
			{
				int codeUnitsConsumed = 0;
                while (bytesConsumed + index < text.Length)
                {
                    uint result;
					int consumed;
                    bool success = encoding.TryParseSymbol(text.Slice(bytesConsumed + index), out result, out consumed);

                    if (!success || result > 9)
                    {
						if (bytesConsumed == 0 && result == (int)EncodingData.Symbol.MinusSign)
						{
							negative = true;
							signed = true;
                            bytesConsumed += consumed;
							codeUnitsConsumed++;
						}
						else if (bytesConsumed == 0 && result == (int)EncodingData.Symbol.PlusSign)
						{
							negative = true;
							signed = true;
                            bytesConsumed += consumed;
						}
						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 = (short)-value;
								if (value > 0)
								{
									value = 0;
									bytesConsumed = 0;
									return false;
								}
                            }
                            return true; // otherwise return true
                        }
                    }
                    else if (value > Int16.MaxValue / 10)
                    {
                        value = default(short);
                        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 == Int16.MaxValue / 10 &&  result >= 8 + (negative ? 1 : 0) ) // overflow
                    {
                        value = default(short);
                        bytesConsumed = 0;
                        return false;
                    }
					else
					{
						value = (short)(value * 10 + result); // left shift the value and add the nextByte
						bytesConsumed += consumed;
						codeUnitsConsumed++;
					}
                }

				if (negative) // We check if the value is negative at the very end to save on comp time
                {
                    value = (short)-value;
					if (value > 0)
					{
						value = default(short);
						bytesConsumed = 0;
						return false;
					}
                }
                return true; // otherwise return true
			}
        }