Exemplo n.º 1
0
Arquivo: G.cs Projeto: murven/Loyc
        /// <inheritdoc cref="TryParseInt(string, ref int, out int, int, bool)"/>
        public static bool TryParseInt(ref UString input, out long result, int radix = 10, ParseFlag flags = 0)
        {
            if ((flags & ParseFlag.SkipSpacesInFront) != 0)
            {
                input = SkipSpaces(input);
            }
            UString s = input;

            bool negative = false;
            char c        = s[0, '\0'];

            if (c == '-' || c == '+')
            {
                negative = c == '-';
                s        = s.Slice(1);
            }

            ulong resultU = 0;
            int   numDigits;
            bool  ok = TryParseUInt(ref s, ref resultU, radix, flags, out numDigits);

            result = negative ? -(long)resultU : (long)resultU;
            if (numDigits != 0)
            {
                input = s;
            }
            return(ok && ((result < 0) == negative || result == 0));
        }
Exemplo n.º 2
0
Arquivo: G.cs Projeto: murven/Loyc
        /// <summary>Returns a string with any spaces and tabs removed from the beginning.</summary>
        public static UString SkipSpaces(UString s)
        {
            char c;

            while ((c = s[0, '\0']) == ' ' || c == '\t')
            {
                s = s.Slice(1);
            }
            return(s);
        }
Exemplo n.º 3
0
Arquivo: G.cs Projeto: murven/Loyc
        static bool TryParseUInt(ref UString s, ref ulong result, int radix, ParseFlag flags, out int numDigits)
        {
            numDigits = 0;
            if ((flags & ParseFlag.SkipSpacesInFront) != 0)
            {
                s = SkipSpaces(s);
            }

            bool overflow = false;
            int  oldStart = s.InternalStart;

            for (;; s = s.Slice(1))
            {
                char c     = s[0, '\0'];
                uint digit = (uint)Base36DigitValue(c);
                if (digit >= radix)
                {
                    if ((c == ' ' || c == '\t') && (flags & ParseFlag.SkipSpacesInsideNumber) != 0)
                    {
                        continue;
                    }
                    else if (c == '_' && (flags & ParseFlag.SkipUnderscores) != 0)
                    {
                        continue;
                    }
                    else
                    {
                        break;
                    }
                }

                ulong next;
                try {
                    next = checked (result * (uint)radix + digit);
                } catch (OverflowException) {
                    overflow = true;
                    if ((flags & ParseFlag.StopBeforeOverflow) != 0)
                    {
                        return(false);
                    }
                    next = result * (uint)radix + digit;
                }
                numDigits++;
                result = next;
            }
            return(!overflow && numDigits > 0);
        }
Exemplo n.º 4
0
Arquivo: G.cs Projeto: murven/Loyc
        public static int TryParseHex(ref UString s, out int value)
        {
            value = 0;
            int len = 0;

            for (;; len++, s = s.Slice(1))
            {
                int digit = HexDigitValue(s[0, '\0']);
                if (digit == -1)
                {
                    return(len);
                }
                else
                {
                    value = value * 16 + digit;
                }
            }
        }
Exemplo n.º 5
0
Arquivo: G.cs Projeto: murven/Loyc
 private static int SkipExtraDigits(ref UString s, int radix, ParseFlag flags)
 {
     for (int skipped = 0;; skipped++, s = s.Slice(1))
     {
         char c     = s[0, '\0'];
         uint digit = (uint)Base36DigitValue(c);
         if (digit >= radix)
         {
             if ((c == ' ' || c == '\t') && (flags & ParseFlag.SkipSpacesInsideNumber) != 0)
             {
                 continue;
             }
             else if (c == '_' && (flags & ParseFlag.SkipUnderscores) != 0)
             {
                 continue;
             }
             else
             {
                 return(skipped);
             }
         }
     }
 }
Exemplo n.º 6
0
Arquivo: G.cs Projeto: murven/Loyc
        /// <summary>Low-level method that identifies the parts of a float literal
        /// of arbitrary base (typically base 2, 10, or 16) with no prefix or
        /// suffix, such as <c>2.Cp0</c> (which means 2.75 in base 16).</summary>
        /// <param name="radix">Base of the number to parse; must be between 2
        /// and 36.</param>
        /// <param name="mantissa">Integer magnitude of the number.</param>
        /// <param name="exponentBase2">Base-2 exponent to apply, as specified by
        /// the 'p' suffix, or 0 if there is no 'p' suffix..</param>
        /// <param name="exponentBase10">Base-10 exponent to apply, as specified by
        /// the 'e' suffix, or 0 if there is no 'e' suffix..</param>
        /// <param name="exponentBaseR">Base-radix exponent to apply. This number
        /// is based on the front part of the number only (not including the 'p' or
        /// 'e' suffix). Negative values represent digits after the decimal point,
        /// while positive numbers represent 64-bit overflow. For example, if the
        /// input is <c>12.3456</c> with <c>radix=10</c>, the output will be
        /// <c>mantissa=123456</c> and <c>exponentBaseR=-4</c>. If the input is
        /// <c>0123_4567_89AB_CDEF_1234.5678</c> with <c>radix=16</c>, the mantissa
        /// overflows, and the result is <c>mantissa = 0x1234_5678_9ABC_DEF1</c>
        /// with <c>exponentBaseR=3</c>.</param>
        /// <param name="numDigits">Set to the number of digits in the number, not
        /// including the exponent part.</param>
        /// <param name="flags">Alters parsing behavior, see <see cref="ParseFlags"/>.</param>
        /// <remarks>
        /// The syntax required is
        /// <code>
        ///   ( '+'|'-' )?
        ///   ( Digits ('.' Digits?)? | '.' Digits )
        ///   ( ('p'|'P') ('-'|'+')? DecimalDigits+ )?
        ///   ( ('e'|'E') ('-'|'+')? DecimalDigits+ )?
        /// </code>
        /// where Digits refers to one digits in the requested base, possibly
        /// including underscores or spaces if the flags allow it; similarly,
        /// DecimalDigits refers to base-10 digits and is also affected by the
        /// flags.
        /// <para/>
        /// Returns false if there was an error interpreting the input.
        /// <para/>
        /// To keep the parser relatively simple, it does not roll back in case of
        /// error the way the int parser does. For example, given the input "23p",
        /// the 'p' is consumed and causes the method to return false, even though
        /// the parse could have been successful if it had ignored the 'p'.
        /// </remarks>
        public static bool TryParseFloatParts(ref UString source, int radix, out bool negative, out ulong mantissa, out int exponentBaseR, out int exponentBase2, out int exponentBase10, out int numDigits, ParseFlag flags = 0)
        {
            flags |= G.ParseFlag.StopBeforeOverflow;

            if ((flags & ParseFlag.SkipSpacesInFront) != 0)
            {
                source = SkipSpaces(source);
            }

            negative = false;
            char c = source[0, '\0'];

            if (c == '-' || c == '+')
            {
                negative = c == '-';
                source   = source.Slice(1);
            }

            int numDigits2 = 0;

            mantissa       = 0;
            exponentBase2  = 0;
            exponentBase10 = 0;
            exponentBaseR  = 0;

            bool success = TryParseUInt(ref source, ref mantissa, radix, flags, out numDigits);

            if (!success)             // possible overflow, extra digits remain if so
            {
                numDigits += (exponentBaseR = SkipExtraDigits(ref source, radix, flags));
            }

            c = source[0, '\0'];
            if (c == '.' || (c == ',' && (flags & ParseFlag.AllowCommaDecimalPoint) != 0))
            {
                source = source.Slice(1);
                if (exponentBaseR == 0)
                {
                    success = TryParseUInt(ref source, ref mantissa, radix, flags, out numDigits2);
                    if ((numDigits += numDigits2) == 0)
                    {
                        return(false);
                    }
                    exponentBaseR = -numDigits2;
                }
                else
                {
                    Debug.Assert(!success);
                }
                if (!success)                 // possible overflow, extra digits remain if so
                {
                    numDigits += SkipExtraDigits(ref source, radix, flags);
                }
                c = source[0, '\0'];
            }

            if (numDigits == 0)
            {
                return(false);
            }

            success = true;
            if (c == 'p' || c == 'P')
            {
                source  = source.Slice(1);
                success = TryParseInt(ref source, out exponentBase2, 10, flags) && success;
                c       = source[0, '\0'];
            }
            if (c == 'e' || c == 'E')
            {
                source  = source.Slice(1);
                success = TryParseInt(ref source, out exponentBase10, 10, flags) && success;
            }
            return(success);
        }