Exemplo n.º 1
0
        public static bool TryParseInt32(ReadOnlySpan <byte> text, out int value, out int bytesConsumed, StandardFormat format = default, SymbolTable symbolTable = null)
        {
            bool isDefault = format.IsDefault;

            symbolTable = symbolTable ?? SymbolTable.InvariantUtf8;

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

            bool isHex = Parsers.IsHexFormat(format);

            if (symbolTable == SymbolTable.InvariantUtf8)
            {
                return(isHex ? Utf8Parser.TryParse(text, out value, out bytesConsumed, 'X') :
                       Utf8Parser.TryParse(text, out value, out bytesConsumed));
            }
            else if (symbolTable == SymbolTable.InvariantUtf16)
            {
                /*return isHex ? InvariantUtf16.Hex.TryParseInt32(text, out value, out bytesConsumed) :
                 *  InvariantUtf16.TryParseInt32(text, out value, out bytesConsumed);*/
                ReadOnlySpan <char> utf16Text = MemoryMarshal.Cast <byte, char>(text);
                bool result = isHex ? Utf16Parser.Hex.TryParseInt32(utf16Text, out value, out int charactersConsumed) :
                              Utf16Parser.TryParseInt32(utf16Text, out value, out charactersConsumed);
                bytesConsumed = charactersConsumed * sizeof(char);
                return(result);
            }

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

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

            int textLength = text.Length;

            if (textLength < 1)
            {
                goto FalseExit;
            }

            if (!symbolTable.TryParse(text, out SymbolTable.Symbol symbol, out int consumed))
            {
                goto FalseExit;
            }

            sbyte sign  = 1;
            int   index = 0;

            if (symbol == SymbolTable.Symbol.MinusSign)
            {
                sign   = -1;
                index += consumed;
                if (index >= textLength)
                {
                    goto FalseExit;
                }
                if (!symbolTable.TryParse(text.Slice(index), out symbol, out consumed))
                {
                    goto FalseExit;
                }
            }
            else if (symbol == SymbolTable.Symbol.PlusSign)
            {
                index += consumed;
                if (index >= textLength)
                {
                    goto FalseExit;
                }
                if (!symbolTable.TryParse(text.Slice(index), out symbol, out consumed))
                {
                    goto FalseExit;
                }
            }

            int answer = 0;

            if (Parsers.IsValid(symbol))
            {
                int numBytes = consumed;
                if (symbol == SymbolTable.Symbol.D0)
                {
                    do
                    {
                        index += consumed;
                        if (index >= textLength)
                        {
                            goto Done;
                        }
                        if (!symbolTable.TryParse(text.Slice(index), out symbol, out consumed))
                        {
                            goto Done;
                        }
                    } while (symbol == SymbolTable.Symbol.D0);
                    if (!Parsers.IsValid(symbol))
                    {
                        goto Done;
                    }
                }

                int firstNonZeroDigitIndex = index;
                if (textLength - firstNonZeroDigitIndex < Parsers.Int32OverflowLength * numBytes)
                {
                    do
                    {
                        answer = answer * 10 + (int)symbol;
                        index += consumed;
                        if (index >= textLength)
                        {
                            goto Done;
                        }
                        if (!symbolTable.TryParse(text.Slice(index), out symbol, out consumed))
                        {
                            goto Done;
                        }
                    } while (Parsers.IsValid(symbol));
                }
                else
                {
                    do
                    {
                        answer = answer * 10 + (int)symbol;
                        index += consumed;
                        if (index - firstNonZeroDigitIndex == (Parsers.Int32OverflowLength - 1) * numBytes)
                        {
                            if (!symbolTable.TryParse(text.Slice(index), out symbol, out consumed))
                            {
                                goto Done;
                            }
                            if (Parsers.IsValid(symbol))
                            {
                                if (Parsers.WillOverFlow(answer, (int)symbol, sign))
                                {
                                    goto FalseExit;
                                }
                                answer = answer * 10 + (int)symbol;
                                index += consumed;
                            }
                            goto Done;
                        }
                        if (!symbolTable.TryParse(text.Slice(index), out symbol, out consumed))
                        {
                            goto Done;
                        }
                    } while (Parsers.IsValid(symbol));
                }
                goto Done;
            }

FalseExit:
            bytesConsumed = 0;
            value         = 0;
            return(false);

Done:
            bytesConsumed = index;
            value         = answer * sign;
            return(true);
        }