コード例 #1
0
        /// <summary>
        /// Gets the value.
        /// </summary>
        /// <param name="sectionName">Name of the section.</param>
        /// <param name="keyName">Name of the key.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <param name="numberStyles">The number styles.</param>
        /// <param name="numberFormatInfo">The number format information.</param>
        /// <returns></returns>
        public virtual double GetValue(
            string sectionName,
            string keyName,
            double defaultValue,
            NumberStyles numberStyles         = NumberStyles.Float | NumberStyles.AllowThousands | NumberStyles.Number,
            NumberFormatInfo numberFormatInfo = null
            )
        {
            if (!(numberStyles.HasFlag(NumberStyles.Float) || numberStyles.HasFlag(NumberStyles.AllowThousands)))
            {
                numberStyles |= NumberStyles.AllowThousands | NumberStyles.Float;
            }

            var doubleRaw = GetRawValue <string>(sectionName, keyName, null);

            if (string.IsNullOrWhiteSpace(doubleRaw))
            {
                SetValue(sectionName, keyName, defaultValue);
                return(defaultValue);
            }

            if (doubleRaw.Contains("E") && !numberStyles.HasFlag(NumberStyles.AllowExponent))
            {
                numberStyles |= NumberStyles.AllowExponent;
            }

            doubleRaw = doubleRaw.TrimEnd('d', 'D', 'f', 'F');
            return(double.TryParse(doubleRaw, numberStyles, (IFormatProvider)numberFormatInfo ?? Settings.Culture,
                                   out var parsedDouble)
                ? parsedDouble
                : double.Parse(doubleRaw, numberStyles, (IFormatProvider)numberFormatInfo ?? Settings.Culture)); // yeah, throws format exception by design
        }
コード例 #2
0
    internal static bool TryParse(
        string text,
        int start,
        NumberStyles style,
        IFormatProvider provider,
        out double result,
        out int endPos)
    {
        result = 0;
        endPos = start;
        if (string.IsNullOrEmpty(text))
        {
            return(false);
        }
        if (!IsValidFloatingPointStyle(style))
        {
            return(false);
        }
        if (style.HasFlag(NumberStyles.AllowHexSpecifier))
        {
            return(false);
        }
        if (style.HasFlag(NumberStyles.AllowLeadingWhite))
        {
            ReadWhite(text, ref endPos);
        }
        if (char.IsWhiteSpace(text[endPos]))
        {
            return(false);
        }
        if (TryParseDigits(text, endPos, style, provider, out result, out endPos))
        {
            return(true);
        }
        if (provider == null)
        {
            provider = CultureInfo.CurrentCulture;
        }
        var format = NumberFormatInfo.GetInstance(provider);

        if (TryRead(text, ref endPos, format.NaNSymbol))
        {
            result = double.NaN;
            return(true);
        }
        if (TryRead(text, ref endPos, format.PositiveInfinitySymbol))
        {
            result = double.PositiveInfinity;
            return(true);
        }
        if (TryRead(text, ref endPos, format.NegativeInfinitySymbol))
        {
            result = double.NegativeInfinity;
            return(true);
        }
        endPos = start;
        return(false);
    }
コード例 #3
0
    // Try parse a double from digits ignoring +-Inf and NaN
    private static bool TryParseDigits(
        string text,
        int start,
        NumberStyles style,
        IFormatProvider provider,
        out double result,
        out int end)
    {
        end = start;
        var  format = NumberFormatInfo.GetInstance(provider);
        Sign sign;

        if (TryReadSign(text, ref end, format, out sign))
        {
            if (!style.HasFlag(NumberStyles.AllowLeadingSign))
            {
                result = 0;
                return(false);
            }
        }
        TryReadDigits(text, ref end);
        if (TryRead(text, ref end, format.NumberDecimalSeparator))
        {
            if (!style.HasFlag(NumberStyles.AllowDecimalPoint))
            {
                result = 0;
                return(false);
            }
            TryReadDigits(text, ref end);
        }
        if (TryReadExponent(text, ref end))
        {
            if (!style.HasFlag(NumberStyles.AllowExponent))
            {
                result = 0;
                return(false);
            }
            TryReadSign(text, ref end, format, out sign);
            if (TryReadDigits(text, ref end))
            {
                return(TryParseSubString(text, start, ref end, style, provider, out result));
            }
            // This is a tricky spot we read digits followed by (sign) exponent
            // then no digits were thrown. I choose to return the double here.
            // Both alternatives will be wrong in some situations.
            // returning false here would make it impossible to parse 1.2eV
            var backStep = sign == Sign.None
                    ? 1
                    : 2;
            end -= backStep;
            return(TryParseSubString(text, start, ref end, style, provider, out result));
        }
        return(TryParseSubString(text, start, ref end, style, provider, out result));
    }
コード例 #4
0
 /// <summary>
 /// Text プロパティから Value プロパティを更新します。
 /// </summary>
 /// <param name="text">テキストを指定します。</param>
 /// <param name="style">パースするための読取形式を指定します。</param>
 /// <param name="isChangeFromUI">UI からの変更指令の場合に true を指定します。</param>
 private void UpdateValueFromText(string text, NumberStyles style, bool isChangeFromUI = true)
 {
     if (style.HasFlag(NumberStyles.AllowHexSpecifier))
     {
         long temp = 0;
         if (long.TryParse(text, style, CultureInfo.CurrentUICulture, out temp))
         {
             if (isChangeFromUI)
             {
                 this.Value = temp;
             }
             else
             {
                 SetCurrentValue(ValueProperty, (double)temp);
             }
         }
     }
     else
     {
         double value = 0.0;
         if (double.TryParse(text, style, CultureInfo.CurrentUICulture, out value))
         {
             if (isChangeFromUI)
             {
                 this.Value = value;
             }
             else
             {
                 SetCurrentValue(ValueProperty, value);
             }
         }
     }
 }
コード例 #5
0
    internal static double Parse(
        string text,
        int start,
        NumberStyles style,
        IFormatProvider provider,
        out int endPos)
    {
        if (!IsValidFloatingPointStyle(style))
        {
            throw new ArgumentException("Invalid NumberStyles", nameof(style));
        }
        if (style.HasFlag(NumberStyles.AllowHexSpecifier))
        {
            throw new ArgumentException("Hex not supported", nameof(style));
        }
        double result;

        if (TryParse(text, start, style, provider, out result, out endPos))
        {
            return(result);
        }
        var message = $"Expected to find a double starting at index {start}\r\n" +
                      $"String: {text}\r\n" +
                      $"        {new string(' ', start)}^";

        throw new FormatException(message);
    }
コード例 #6
0
        internal static string ToAttributeValue(NumberStyles styles)
        {
            string[] textArray = new string[basicRecArray.Length];
            int      count     = 0;

            // Composite must match exactly
            for (int i = 0; i < compositeRecArray.Length; i++)
            {
                if (styles == compositeRecArray[i].Styles)
                {
                    textArray[count++] = compositeRecArray[i].Text;
                    break;
                }
            }

            if (count > 0)
            {
                return(FtCommaText.Get(textArray, 0, count));
            }
            else
            {
                foreach (BasicRec rec in basicRecArray)
                {
                    if (styles.HasFlag(rec.Flag))
                    {
                        textArray[count++] = rec.Text;
                    }
                }
                return(FtCommaText.Get(textArray, 0, count));
            }
        }
コード例 #7
0
        private static bool IsAllowableCharacter(
            char character,
            string expression,
            int index,
            int startIndex,
            int expressionLength,
            Context context,
            ref NumberStyles numberStyles,
            out Location exponentialLocation)
        {
            exponentialLocation = null;

            if (char.IsDigit(character) || IsValidStart(character, context, numberStyles) && index == startIndex)
            {
                return(true);
            }

            // No more exponential or decimal chars after our first exponential.
            if (!numberStyles.HasFlag(NumberStyles.AllowExponent))
            {
                return(false);
            }

            // If we find an exponential character then carry on to find a valid integer.
            if ((character == 'e' || character == 'E') &&
                char.IsDigit(expression[index - 1]) && // make sure the e is preceded by an actual number.
                index + 1 < expressionLength &&
                IsValidStart(expression[index + 1], context, NumberStyles.Integer))
            {
                exponentialLocation = GetNumberLocation(expression, index + 1, context, NumberStyles.Integer);

                if (exponentialLocation != null)
                {
                    // No need to interact with the numberStyles as supplying the location short circuits.
                    return(true);
                }
            }

            if (numberStyles.HasFlag(NumberStyles.AllowDecimalPoint) && character == context.DecimalSeparator)
            {
                numberStyles &= ~NumberStyles.AllowDecimalPoint;
                return(true);
            }

            return(false);
        }
コード例 #8
0
        /// <summary>
        /// Gets integer value.
        /// </summary>
        /// <param name="sectionName">Name of the section.</param>
        /// <param name="keyName">Name of the key.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <param name="numberStyles">The number styles.</param>
        /// <param name="numberFormatInfo">The number format information.</param>
        /// <returns></returns>
        public virtual int GetValue(
            string sectionName,
            string keyName,
            int defaultValue,
            NumberStyles numberStyles         = NumberStyles.Number,
            NumberFormatInfo numberFormatInfo = null
            )
        {
            if (!numberStyles.HasFlag(NumberStyles.Number))
            {
                numberStyles |= NumberStyles.Number;
            }

            var integerRaw = GetRawValue <string>(sectionName, keyName, null);

            if (!string.IsNullOrWhiteSpace(integerRaw))
            {
                return(int.TryParse(integerRaw, numberStyles, (IFormatProvider)numberFormatInfo ?? Settings.Culture, out var integerParsed)
                    ? integerParsed
                    : int.Parse(integerRaw, numberStyles, (IFormatProvider)numberFormatInfo ?? Settings.Culture)); // yeah, throws format exception by design
            }
            SetValue(sectionName, keyName, defaultValue);
            return(defaultValue);
        }
コード例 #9
0
 private static bool IsValidStart(char character, Context context, NumberStyles numberStyles) =>
 char.IsDigit(character) ||
 numberStyles.HasFlag(NumberStyles.AllowLeadingSign) && IsSignCharacter(character) ||
 numberStyles.HasFlag(NumberStyles.AllowDecimalPoint) && character == context.DecimalSeparator;
コード例 #10
0
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                object ret = null;

                object source = values[0];

                if (source == DependencyProperty.UnsetValue)
                {
                    return(source);
                }

                TextBox textBox = (TextBox)values[1];
                string  newText = textBox.Text;

                // Получение состояния привязки TextBox
                TextBoxBindingState bindingState = GetBindingState(textBox);
                string oldText = bindingState.OldText;

                // Получение парсера для типа в первой привязке (привязка к Источнику).
                TryParseNumberHandler tryParse = NumericTryParse.GetTryParse(source.GetType());

                // Если парсер получить не удалось, значит первая привязка получила значение недопустимого типа.
                if (tryParse == null)
                {
                    throw InvalidNumberType;
                }

                Debug.Write(GetType().Name + $".Convert.values: {source}, \"{oldText}\", \"{newText}\"");

                // Получение цифрового стиля из параметра. Если он не задан, то используется стиль по умолчанию для этого типа.
                NumberStyles style = NumericTryParse.GetNumberStyle(parameter, values[0].GetType());

                // Проверка причины вызова конвертера.
                switch (bindingState.UpdateSourceState)
                {
                // Метод UpdateSource() не вызывался, значит значение обновляется по привязке от Источника.
                case UpdateSourceStateEnum.NotCalled:

                    // Получение из TextBox числа в том же типе, что получено от Источника (в первой привязке).
                    // И сравнение этого числа с числом Источника.
                    if (tryParse(newText, style, culture, out object target) && target.Equals(source))
                    {
                        // Отменяется присвоение значения привязкой.
                        ret = Binding.DoNothing;
                    }

                    // Иначе возвращается число Источника в текстовом виде в заданной культуре.
                    else
                    {
                        ret = System.Convert.ToString(source, culture);
                    }
                    break;

                // Обновление источника произошло в ходе выполнения метода UpdateSource().
                // Значит в TextBox.Text корректное значение и его надо проверить только на крайние пробелы
                // для режима ввода "Tолько Числа".
                case UpdateSourceStateEnum.Called:
                    if (bindingState.IsNumericOnly)
                    {
                        if (newText.Length < 1 || char.IsWhiteSpace(newText[0]) || char.IsWhiteSpace(newText[newText.Length - 1]))
                        {
                            // Устанавливается флаг обновления по привязке
                            bindingState.TextChangeSource = PropertyChangeSourceEnum.Binding;
                            // Возращается TextBox старое значение.
                            UndoText(textBox, oldText, bindingState.Changes);
                        }
                    }
                    // Отменяется присваивание.
                    ret = Binding.DoNothing;

                    break;

                // После вызова UpdateSource() обновление источника не произошло
                // Значит в TextBox.Text некорректное значение и надо вернуть предыдущее его значение.
                case UpdateSourceStateEnum.CallCanceled:

                    // Устанавливается флаг обновления из конвертера привязки
                    bindingState.TextChangeSource = PropertyChangeSourceEnum.Binding;

                    // Проверяется на пустую строку.
                    // Если она пустая, то надо её заменить на "0".
                    // Это автоматически сделает метод UndoText().
                    if (string.IsNullOrWhiteSpace(newText))
                    {
                        ZeroText(textBox);
                    }

                    else if (!BeginScientific(newText))
                    {
                        // Возращается TextBox старое значение.
                        UndoText(textBox, oldText, bindingState.Changes);
                    }

                    // Сброс флага обновления из конвертера привязки
                    bindingState.TextChangeSource = PropertyChangeSourceEnum.NotBinding;

                    // Проверка строки в TextBox.
                    // Если она корректна, то для сброса валидации надо её же и вернуть
                    if (tryParse(textBox.Text, style, culture, out _))
                    {
                        ret = textBox.Text;
                    }
                    else
                    {
                        // Иначе - отмена присвоения по привязке
                        ret = Binding.DoNothing;
                    }

                    break;

                default:
                    break;
                }

                Debug.WriteLine($"; return: {ret ?? "null"}");

                if (ret is string str && str != textBox.Text)
                {
                    // Устанавливается флаг обновления по привязке
                    bindingState.TextChangeSource = PropertyChangeSourceEnum.Binding;
                }

                return(ret);;

                // Проверка строки на начало научной записи числа
                bool BeginScientific(string text)
                {
                    if (string.IsNullOrWhiteSpace(text))
                    {
                        return(false);
                    }
                    if (style.HasFlag(NumberStyles.AllowExponent))
                    {
                        if (text[text.Length - 1] == 'e' || text[text.Length - 1] == 'E')
                        {
                            text = text.Remove(text.Length - 1, 1);
                        }
                        else if (text.Length > 1 && (text[text.Length - 1] == '-' || text[text.Length - 1] == '+') &&
                                 (text[text.Length - 2] == 'e' || text[text.Length - 2] == 'E'))
                        {
                            text = text.Remove(text.Length - 2, 2);
                        }
                    }
                    return(tryParse(text, style, culture, out _));
                }
            }
コード例 #11
0
    internal static double Parse(
        string s,
        int start,
        NumberStyles style,
        IFormatProvider provider,
        out int endPos)
    {
        if (!IsValidFloatingPointStyle(style))
        {
            throw new ArgumentException("Invalid NumberStyles", "style");
        }
        if (style.HasFlag(NumberStyles.AllowHexSpecifier))
        {
            throw new ArgumentException("Hex not supported", "style");
        }
        var pos = start;

        if (style.HasFlag(NumberStyles.AllowLeadingWhite))
        {
            ReadWhite(s, ref pos);
        }
        if (provider == null)
        {
            provider = CultureInfo.CurrentCulture;
        }
        var    format = NumberFormatInfo.GetInstance(provider);
        string read;

        if (TryRead(s, ref pos, format.NaNSymbol, out read))
        {
            endPos = pos;
            return(double.NaN);
        }
        if (TryRead(s, ref pos, format.PositiveInfinitySymbol, out read))
        {
            endPos = pos;
            return(double.PositiveInfinity);
        }
        if (TryRead(s, ref pos, format.NegativeInfinitySymbol, out read))
        {
            endPos = pos;
            return(double.NegativeInfinity);
        }
        var sb = new StringBuilder();

        if (TryReadSign(s, ref pos, format, out read))
        {
            if (!style.HasFlag(NumberStyles.AllowLeadingSign))
            {
                throw new FormatException(LeadingSignNotAllowed);
            }
            sb.Append(read);
        }
        ReadDigits(s, ref pos, sb);
        if (TryRead(s, ref pos, format.NumberDecimalSeparator, out read))
        {
            if (!style.HasFlag(NumberStyles.AllowDecimalPoint))
            {
                throw new FormatException(DecimalPointNotAllowed);
            }
            sb.Append(read);
            ReadDigits(s, ref pos, sb);
        }
        string result;
        string exponent;

        if (TryReadExponent(s, ref pos, out exponent))
        {
            if (!style.HasFlag(NumberStyles.AllowExponent))
            {
                throw new FormatException(ExponentNotAllowed);
            }
            sb.Append(exponent);
            string sign;
            if (TryReadSign(s, ref pos, format, out sign))
            {
                sb.Append(sign);
            }
            if (ReadDigits(s, ref pos, sb))
            {
                result = sb.ToString();
            }
            else
            {
                var back = exponent.Length + sign.Length;
                result = sb.ToString(0, sb.Length - back);
                pos   -= back;
            }
        }
        else
        {
            result = sb.ToString();
        }
        var d = double.Parse(result, style, provider);

        endPos = pos;
        return(d);
    }
コード例 #12
0
    internal static bool TryParse(
        string s,
        int start,
        NumberStyles style,
        IFormatProvider provider,
        out double value,
        out int endPos)
    {
        value  = 0;
        endPos = start;
        if (s == null)
        {
            return(false);
        }
        if (!IsValidFloatingPointStyle(style))
        {
            return(false);
        }
        if (style.HasFlag(NumberStyles.AllowHexSpecifier))
        {
            return(false);
        }
        var pos = start;

        if (style.HasFlag(NumberStyles.AllowLeadingWhite))
        {
            ReadWhite(s, ref pos);
        }
        if (char.IsWhiteSpace(s[pos]))
        {
            return(false);
        }
        if (provider == null)
        {
            provider = CultureInfo.CurrentCulture;
        }
        var format = NumberFormatInfo.GetInstance(provider);
        var read   = string.Empty;

        if (TryRead(s, ref pos, format.NaNSymbol, out read))
        {
            endPos = pos;
            value  = double.NaN;
            return(true);
        }
        if (TryRead(s, ref pos, format.PositiveInfinitySymbol, out read))
        {
            endPos = pos;
            value  = double.PositiveInfinity;
            return(true);
        }
        if (TryRead(s, ref pos, format.NegativeInfinitySymbol, out read))
        {
            endPos = pos;
            value  = double.NegativeInfinity;
            return(true);
        }
        var sb = new StringBuilder();

        if (TryReadSign(s, ref pos, format, out read))
        {
            if (!style.HasFlag(NumberStyles.AllowLeadingSign))
            {
                return(false);
            }
            sb.Append(read);
        }
        ReadDigits(s, ref pos, sb);
        if (TryRead(s, ref pos, format.NumberDecimalSeparator, out read))
        {
            if (!style.HasFlag(NumberStyles.AllowDecimalPoint))
            {
                return(false);
            }
            sb.Append(read);
            ReadDigits(s, ref pos, sb);
        }
        string result;
        string exponent;

        if (TryReadExponent(s, ref pos, out exponent))
        {
            if (!style.HasFlag(NumberStyles.AllowExponent))
            {
                return(false);
            }
            sb.Append(exponent);
            string sign;
            if (TryReadSign(s, ref pos, format, out sign))
            {
                sb.Append(sign);
            }
            if (ReadDigits(s, ref pos, sb))
            {
                result = sb.ToString();
            }
            else
            {
                var back = exponent.Length + sign.Length;
                result = sb.ToString(0, sb.Length - back);
                pos   -= back;
            }
        }
        else
        {
            result = sb.ToString();
        }
        endPos = pos;
        return(double.TryParse(result, style, provider, out value));
    }
コード例 #13
0
        // UTF-8 / ASCII inputs.
        unsafe static internal ParsedNumberString ParseNumberString(byte *p, byte *pend, NumberStyles expectedFormat = NumberStyles.Float, byte decimal_separator = (byte)'.')
        {
            ParsedNumberString answer = new ParsedNumberString();

            answer.valid           = false;
            answer.too_many_digits = false;
            byte *pstart = p;

            answer.negative = (*p == '-');
            if ((*p == '-') || (*p == '+'))
            {
                ++p;
                if (p == pend)
                {
                    return(answer);
                }
                if (!Utils.is_integer(*p, out uint _) && (*p != decimal_separator))
                { // a  sign must be followed by an integer or the dot
                    return(answer);
                }
            }
            byte *start_digits = p;

            ulong i = 0; // an unsigned int avoids signed overflows (which are bad)

            while ((p != pend) && Utils.is_integer(*p, out uint digit))
            {
                // a multiplication by 10 is cheaper than an arbitrary integer
                // multiplication
                i = 10 * i + digit; // might overflow, we will handle the overflow later
                ++p;
            }
            byte *end_of_integer_part = p;
            long  digit_count         = (long)(end_of_integer_part - start_digits);
            long  exponent            = 0;

            if ((p != pend) && (*p == decimal_separator))
            {
                ++p;
                if ((p + 8 <= pend) && Utils.is_made_of_eight_digits_fast(p))
                {
                    i  = i * 100000000 + Utils.parse_eight_digits_unrolled(p);
                    p += 8;
                    if ((p + 8 <= pend) && Utils.is_made_of_eight_digits_fast(p))
                    {
                        i  = i * 100000000 + Utils.parse_eight_digits_unrolled(p);
                        p += 8;
                    }
                }
                while ((p != pend) && Utils.is_integer(*p, out uint digit))
                {
                    ++p;
                    i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
                }
                exponent     = end_of_integer_part + 1 - p;
                digit_count -= exponent;
            }
            // we must have encountered at least one integer!
            if (digit_count == 0)
            {
                return(answer);
            }
            long exp_number = 0;      // explicit exponential part

            if (expectedFormat.HasFlag(NumberStyles.AllowExponent) && (p != pend) && (('e' == *p) || ('E' == *p)))
            {
                byte *location_of_e = p;
                ++p;
                bool neg_exp = false;
                if ((p != pend) && ('-' == *p))
                {
                    neg_exp = true;
                    ++p;
                }
                else if ((p != pend) && ('+' == *p))
                {
                    ++p;
                }
                if ((p == pend) || !Utils.is_integer(*p, out uint _))
                {
                    if (!expectedFormat.HasFlag(NumberStyles.AllowDecimalPoint))
                    {
                        // We are in error.
                        return(answer);
                    }
                    // Otherwise, we will be ignoring the 'e'.
                    p = location_of_e;
                }
                else
                {
                    while ((p != pend) && Utils.is_integer(*p, out uint cdigit))
                    {
                        if (exp_number < 0x10000)
                        {
                            exp_number = 10 * exp_number + cdigit;
                        }
                        ++p;
                    }
                    if (neg_exp)
                    {
                        exp_number = -exp_number;
                    }
                    exponent += exp_number;
                }
            }
            else
            {
                // If it scientific and not fixed, we have to bail out.
                if (expectedFormat.HasFlag(NumberStyles.AllowExponent) && !expectedFormat.HasFlag(NumberStyles.AllowDecimalPoint))
                {
                    return(answer);
                }
            }
            answer.valid = true;
            answer.characters_consumed = (int)(p - pstart);

            // If we frequently had to deal with long strings of digits,
            // we could extend our code by using a 128-bit integer instead
            // of a 64-bit integer. However, this is uncommon.
            //
            // We can deal with up to 19 digits.
            if (digit_count > 19)
            { // this is uncommon
              // It is possible that the integer had an overflow.
              // We have to handle the case where we have 0.0000somenumber.
              // We need to be mindful of the case where we only have zeroes...
              // E.g., 0.000000000...000.
                byte *start = start_digits;
                while ((start != pend) && (*start == '0' || *start == decimal_separator))
                {
                    if (*start == '0')
                    {
                        digit_count--;
                    }
                    start++;
                }
                if (digit_count > 19)
                {
                    answer.too_many_digits = true;
                    // Let us start again, this time, avoiding overflows.
                    i = 0;
                    p = start_digits;
                    const ulong minimal_nineteen_digit_integer = 1000000000000000000;
                    while ((i < minimal_nineteen_digit_integer) && (p != pend) && Utils.is_integer(*p, out uint digit))
                    {
                        i = i * 10 + digit;
                        ++p;
                    }
                    if (i >= minimal_nineteen_digit_integer)
                    { // We have a big integers
                        exponent = end_of_integer_part - p + exp_number;
                    }
                    else
                    {        // We have a value with a fractional component.
                        p++; // skip the '.'
                        byte *first_after_period = p;
                        while ((i < minimal_nineteen_digit_integer) && (p != pend) && Utils.is_integer(*p, out uint digit))
                        {
                            i = i * 10 + digit;
                            ++p;
                        }
                        exponent = first_after_period - p + exp_number;
                    }
                    // We have now corrected both exponent and i, to a truncated value
                }
            }
            answer.exponent = exponent;
            answer.mantissa = i;
            return(answer);
        }
コード例 #14
0
 /// <summary>
 /// Text プロパティから Value プロパティを更新します。
 /// </summary>
 /// <param name="text">テキストを指定します。</param>
 /// <param name="style">パースするための読取形式を指定します。</param>
 /// <param name="isChangeFromUI">UI からの変更指令の場合に true を指定します。</param>
 private void UpdateValueFromText(string text, NumberStyles style, bool isChangeFromUI = true)
 {
     if (style.HasFlag(NumberStyles.AllowHexSpecifier))
     {
         long temp = 0;
         if (long.TryParse(text, style, CultureInfo.CurrentUICulture, out temp))
         {
             if (isChangeFromUI)
             {
                 this.Value = temp;
             }
             else
             {
                 SetCurrentValue(ValueProperty, (double)temp);
             }
         }
     }
     else
     {
         double value = 0.0;
         if (double.TryParse(text, style, CultureInfo.CurrentUICulture, out value))
         {
             if (isChangeFromUI)
             {
                 this.Value = value;
             }
             else
             {
                 SetCurrentValue(ValueProperty, value);
             }
         }
     }
 }
コード例 #15
0
		public static bool TryParse(string text, NumberStyles style, IFormatProvider provider, out BigInteger value)
		{
			bool parsedSuccessfully = false;
			value = BigInteger.Zero;

			// Use long's TryParse routine first because it will handle most common
			// input values more quickly and thoroughly than my code below will.
			if (long.TryParse(text, style, provider, out long longValue))
			{
				value = longValue;
				parsedSuccessfully = true;
			}
			else if (!string.IsNullOrWhiteSpace(text))
			{
				// The input wasn't parsible with a long, which has a range of
				// -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.
				// So either the input is a big number, or it's poorly formed.
				// I'll try to parse it as simply as possible, but I'm not going
				// to try to handle all of the supported NumberStyles and formats.
				// Note: According to Int64.TryParse, .NET looks for patterns
				// in the following order, so I'll stick to that too roughly:
				// [ws][$][sign][digits,]digits[.fractional_digits][e[sign]exponential_digits][ws]
				NumberFormatInfo numFmt = NumberFormatInfo.GetInstance(provider);
				if (style.HasFlag(NumberStyles.AllowLeadingWhite))
				{
					text = text.TrimStart();
				}

				if (style.HasFlag(NumberStyles.AllowTrailingWhite))
				{
					text = text.TrimEnd();
				}

				if (style.HasFlag(NumberStyles.AllowCurrencySymbol) && text.StartsWith(numFmt.CurrencySymbol, StringComparison.CurrentCulture))
				{
					text = text.Substring(numFmt.CurrencySymbol.Length);
				}

				bool negativeValue = false;
				if (style.HasFlag(NumberStyles.AllowLeadingSign) && text.StartsWith(numFmt.NegativeSign, StringComparison.CurrentCulture))
				{
					negativeValue = true;
					text = text.Substring(numFmt.NegativeSign.Length);
				}
				else if (style.HasFlag(NumberStyles.AllowTrailingSign) && text.EndsWith(numFmt.NegativeSign, StringComparison.CurrentCulture))
				{
					negativeValue = true;
					text = text.Substring(0, text.Length - numFmt.NegativeSign.Length);
				}

				// Note: I'm ignoring NumberStyles.AllowParentheses.
				if (style.HasFlag(NumberStyles.AllowThousands))
				{
					// This is weak.  I'm not checking group sizes at all.
					text = text.Replace(numFmt.PercentGroupSeparator, string.Empty);
				}

				if (style.HasFlag(NumberStyles.AllowDecimalPoint))
				{
					// If it contains a decimal point, then it must have only zeros after that.
					// Otherwise, we'll just treat the whole thing as an empty string.
					text = HandleBigIntegerWithDecimalPoint(text, numFmt);
				}

				// By now, we're hopefully down to just decimal or hex digits.
				if (style.HasFlag(NumberStyles.AllowHexSpecifier))
				{
					parsedSuccessfully = TryParseDigits(text, 16, out value);
				}
				else
				{
					parsedSuccessfully = TryParseDigits(text, 10, out value);
				}

				if (parsedSuccessfully && negativeValue)
				{
					value = BigInteger.Negate(value);
				}
			}

			return parsedSuccessfully;
		}
コード例 #16
0
ファイル: Converters.cs プロジェクト: Necromonicon/MyWowTools
        /// <summary>
        /// Converts numeric's string representation to type.
        /// </summary>
        /// <typeparam name="T">The type which string representation is given.</typeparam>
        /// <param name="representation">The string representation of type.</param>
        /// <returns>The converted value.</returns>
        /// <param name="throwException">Indicates whether an exception should be thrown if the conversion fails.</param>
        /// <exception cref="System.ArgumentException">String representation cannot be converted to numeric.</exception>
        public static T ToNumeric <T>(this string representation, bool throwException)
            where T : IConvertible
        {
            bool         error;
            IConvertible value   = 0.0f;
            CultureInfo  culture = CultureInfo.InvariantCulture;

            if (string.IsNullOrEmpty(representation))
            {
                error = true;
                goto _end;
            }

            representation = representation.Trim();

            NumberStyles style = NumberStyles.None;

            if (representation.StartsWith("0x"))
            {
                style         |= NumberStyles.AllowHexSpecifier;
                representation = representation.Substring(2);
            }

            switch (representation[representation.Length - 1])
            {
            case 'h':
            case 'H':
                representation = representation.Substring(0, representation.Length - 1);
                style         |= NumberStyles.AllowHexSpecifier;
                break;

            case 'u':
            case 'U':
                representation = representation.Substring(0, representation.Length - 1);
                break;

            default:
                if (!style.HasFlag(NumberStyles.AllowHexSpecifier))
                {
                    style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent | NumberStyles.AllowLeadingSign;
                }
                break;
            }

            if ((style & NumberStyles.AllowDecimalPoint) != 0)
            {
                double double_value;
                error = !(
                    double.TryParse(representation, style, culture = CultureInfo.InvariantCulture, out double_value) ||
                    double.TryParse(representation, style, culture = CultureInfo.CurrentCulture, out double_value) ||
                    double.TryParse(representation, style, culture = CultureInfo.GetCultureInfo("en-US"), out double_value)
                    );
                value = double_value;
            }
            else
            {
                long long_value;
                error = !(
                    long.TryParse(representation, style, culture = CultureInfo.InvariantCulture, out long_value) ||
                    long.TryParse(representation, style, culture = CultureInfo.CurrentCulture, out long_value) ||
                    long.TryParse(representation, style, culture = CultureInfo.GetCultureInfo("en-US"), out long_value)
                    );
                value = long_value;
            }

_end:
            if (error)
            {
                if (throwException)
                {
                    throw new ArgumentException("Provided string cannot be converted to the specified type.", "representation");
                }
                else
                {
                    value = 0.0f;
                }
            }

            T ret;

            try
            {
                ret = (T)value.ToType(typeof(T), culture);
            }
            catch
            {
                if (throwException)
                {
                    throw;
                }
                else
                {
                    ret = default(T);
                }
            }

            return(ret);
        }