예제 #1
0
        public static void FormatDecimal(StringBuffer formatter, uint* value, StringView specifier, CachedCulture culture)
        {
            int digits;
            var fmt = ParseFormatSpecifier(specifier, out digits);

            var number = new Number();
            var buffer = stackalloc char[MaxNumberDigits + 1];
            number.Digits = buffer;
            DecimalToNumber(value, ref number);
            if (fmt != 0)
                NumberToString(formatter, ref number, fmt, digits, culture, isDecimal: true);
            else
                NumberToCustomFormatString(formatter, ref number, specifier, culture);
        }
예제 #2
0
        public static void FormatDouble(StringBuffer formatter, double value, StringView specifier, CachedCulture culture)
        {
            int digits;
            int precision = DoublePrecision;
            var fmt = ParseFormatSpecifier(specifier, out digits);

            // ANDing with 0xFFDF has the effect of uppercasing the character
            switch (fmt & 0xFFDF) {
                case 'G':
                    if (digits > 15)
                        precision = 17;
                    break;

                case 'E':
                    if (digits > 14)
                        precision = 17;
                    break;
            }

            var number = new Number();
            var buffer = stackalloc char[MaxFloatingDigits + 1];
            number.Digits = buffer;
            DoubleToNumber(value, precision, ref number);

            if (number.Scale == ScaleNaN) {
                formatter.Append(culture.NaN);
                return;
            }

            if (number.Scale == ScaleInf) {
                if (number.Sign > 0)
                    formatter.Append(culture.NegativeInfinity);
                else
                    formatter.Append(culture.PositiveInfinity);
                return;
            }

            if (fmt != 0)
                NumberToString(formatter, ref number, fmt, digits, culture);
            else
                NumberToCustomFormatString(formatter, ref number, specifier, culture);
        }
예제 #3
0
 static void NumberToCustomFormatString(StringBuffer formatter, ref Number number, StringView specifier, CachedCulture culture)
 {
 }
예제 #4
0
        public static void FormatSByte(StringBuffer formatter, sbyte value, StringView specifier, CachedCulture culture)
        {
            if (value < 0 && !specifier.IsEmpty)
            {
                // if we're negative and doing a hex format, mask out the bits for the conversion
                char c = specifier.Data[0];
                if (c == 'X' || c == 'x')
                {
                    FormatUInt32(formatter, (uint)(value & 0xFF), specifier, culture);
                    return;
                }
            }

            FormatInt32(formatter, value, specifier, culture);
        }
예제 #5
0
        public static void FormatUInt32(StringBuffer formatter, uint value, StringView specifier, CachedCulture culture)
        {
            int digits;
            var fmt = ParseFormatSpecifier(specifier, out digits);

            // ANDing with 0xFFDF has the effect of uppercasing the character
            switch (fmt & 0xFFDF)
            {
            case 'G':
                if (digits > 0)
                {
                    goto default;
                }
                else
                {
                    goto case 'D';
                }

            case 'D':
                UInt32ToDecStr(formatter, value, digits);
                break;

            case 'X':
                // fmt-('X'-'A'+1) gives us the base hex character in either
                // uppercase or lowercase, depending on the casing of fmt
                Int32ToHexStr(formatter, value, fmt - ('X' - 'A' + 10), digits);
                break;

            default:
                var number = new Number();
                var buffer = stackalloc char[MaxNumberDigits + 1];
                number.Digits = buffer;
                UInt32ToNumber(value, ref number);
                if (fmt != 0)
                {
                    NumberToString(formatter, ref number, fmt, digits, culture);
                }
                else
                {
                    NumberToCustomFormatString(formatter, ref number, specifier, culture);
                }
                break;
            }
        }
예제 #6
0
        static void NumberToString(StringBuffer formatter, ref Number number, char format, int maxDigits, CachedCulture culture, bool isDecimal = false)
        {
            // ANDing with 0xFFDF has the effect of uppercasing the character
            switch (format & 0xFFDF)
            {
            case 'C':
            {
                var cultureData = culture.CurrencyData;
                var bufferSize  = cultureData.GetBufferSize(ref maxDigits, number.Scale);
                RoundNumber(ref number, number.Scale + maxDigits);

                var buffer = stackalloc char[bufferSize];
                var ptr    = FormatCurrency(
                    buffer,
                    ref number,
                    maxDigits,
                    cultureData,
                    number.Sign > 0 ? culture.CurrencyNegativePattern : culture.CurrencyPositivePattern,
                    culture.CurrencySymbol
                    );

                formatter.Append(buffer, (int)(ptr - buffer));
                break;
            }

            case 'F':
            {
                var cultureData = culture.FixedData;
                var bufferSize  = cultureData.GetBufferSize(ref maxDigits, number.Scale);
                RoundNumber(ref number, number.Scale + maxDigits);

                var buffer = stackalloc char[bufferSize];
                var ptr    = buffer;
                if (number.Sign > 0)
                {
                    AppendString(&ptr, cultureData.NegativeSign);
                }

                ptr = FormatFixed(ptr, ref number, maxDigits, cultureData);
                formatter.Append(buffer, (int)(ptr - buffer));
                break;
            }

            case 'N':
            {
                var cultureData = culture.NumberData;
                var bufferSize  = cultureData.GetBufferSize(ref maxDigits, number.Scale);
                RoundNumber(ref number, number.Scale + maxDigits);

                var buffer = stackalloc char[bufferSize];
                var ptr    = FormatNumber(
                    buffer,
                    ref number,
                    maxDigits,
                    number.Sign > 0 ? culture.NumberNegativePattern : culture.NumberPositivePattern,
                    cultureData
                    );

                formatter.Append(buffer, (int)(ptr - buffer));
                break;
            }

            case 'E':
            {
                var cultureData = culture.ScientificData;
                var bufferSize  = cultureData.GetBufferSize(ref maxDigits, number.Scale);
                maxDigits++;

                RoundNumber(ref number, maxDigits);

                var buffer = stackalloc char[bufferSize];
                var ptr    = buffer;
                if (number.Sign > 0)
                {
                    AppendString(&ptr, cultureData.NegativeSign);
                }

                ptr = FormatScientific(
                    ptr,
                    ref number,
                    maxDigits,
                    format,         // TODO: fix casing
                    cultureData.DecimalSeparator,
                    culture.PositiveSign,
                    culture.NegativeSign
                    );

                formatter.Append(buffer, (int)(ptr - buffer));
                break;
            }

            case 'P':
            {
                number.Scale += 2;
                var cultureData = culture.PercentData;
                var bufferSize  = cultureData.GetBufferSize(ref maxDigits, number.Scale);
                RoundNumber(ref number, number.Scale + maxDigits);

                var buffer = stackalloc char[bufferSize];
                var ptr    = FormatPercent(
                    buffer,
                    ref number,
                    maxDigits,
                    cultureData,
                    number.Sign > 0 ? culture.PercentNegativePattern : culture.PercentPositivePattern,
                    culture.PercentSymbol
                    );

                formatter.Append(buffer, (int)(ptr - buffer));
                break;
            }

            case 'G':
            {
                var enableRounding = true;
                if (maxDigits < 1)
                {
                    if (isDecimal && maxDigits == -1)
                    {
                        // if we're formatting a decimal, default to 29 digits precision
                        // only for G formatting without a precision specifier
                        maxDigits      = DecimalPrecision;
                        enableRounding = false;
                    }
                    else
                    {
                        maxDigits = number.Precision;
                    }
                }

                var bufferSize = maxDigits + culture.DecimalBufferSize;
                var buffer     = stackalloc char[bufferSize];
                var ptr        = buffer;

                // round for G formatting only if a precision is given
                // we need to handle the minus zero case also
                if (enableRounding)
                {
                    RoundNumber(ref number, maxDigits);
                }
                else if (isDecimal && number.Digits[0] == 0)
                {
                    number.Sign = 0;
                }

                if (number.Sign > 0)
                {
                    AppendString(&ptr, culture.NegativeSign);
                }

                ptr = FormatGeneral(
                    ptr,
                    ref number,
                    maxDigits,
                    (char)(format - ('G' - 'E')),
                    culture.NumberData.DecimalSeparator,
                    culture.PositiveSign,
                    culture.NegativeSign,
                    !enableRounding
                    );

                formatter.Append(buffer, (int)(ptr - buffer));
                break;
            }

            default:
                throw new FormatException(string.Format(SR.UnknownFormatSpecifier, format));
            }
        }
예제 #7
0
        public static void FormatDecimal(StringBuffer formatter, uint *value, StringView specifier, CachedCulture culture)
        {
            int digits;
            var fmt = ParseFormatSpecifier(specifier, out digits);

            var number = new Number();
            var buffer = stackalloc char[MaxNumberDigits + 1];

            number.Digits = buffer;
            DecimalToNumber(value, ref number);
            if (fmt != 0)
            {
                NumberToString(formatter, ref number, fmt, digits, culture, isDecimal: true);
            }
            else
            {
                NumberToCustomFormatString(formatter, ref number, specifier, culture);
            }
        }
예제 #8
0
        public static void FormatDouble(StringBuffer formatter, double value, StringView specifier, CachedCulture culture)
        {
            int digits;
            int precision = DoublePrecision;
            var fmt       = ParseFormatSpecifier(specifier, out digits);

            // ANDing with 0xFFDF has the effect of uppercasing the character
            switch (fmt & 0xFFDF)
            {
            case 'G':
                if (digits > 15)
                {
                    precision = 17;
                }
                break;

            case 'E':
                if (digits > 14)
                {
                    precision = 17;
                }
                break;
            }

            var number = new Number();
            var buffer = stackalloc char[MaxFloatingDigits + 1];

            number.Digits = buffer;
            DoubleToNumber(value, precision, ref number);

            if (number.Scale == ScaleNaN)
            {
                formatter.Append(culture.NaN);
                return;
            }

            if (number.Scale == ScaleInf)
            {
                if (number.Sign > 0)
                {
                    formatter.Append(culture.NegativeInfinity);
                }
                else
                {
                    formatter.Append(culture.PositiveInfinity);
                }
                return;
            }

            if (fmt != 0)
            {
                NumberToString(formatter, ref number, fmt, digits, culture);
            }
            else
            {
                NumberToCustomFormatString(formatter, ref number, specifier, culture);
            }
        }
예제 #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="StringBuffer"/> class.
 /// </summary>
 /// <param name="capacity">The initial size of the string buffer.</param>
 public StringBuffer(int capacity)
 {
     buffer  = new char[capacity];
     culture = CachedCurrentCulture;
 }
예제 #10
0
 static void NumberToCustomFormatString(StringBuffer formatter, ref Number number, StringView specifier, CachedCulture culture)
 {
 }
예제 #11
0
        public static void FormatInt16(StringBuffer formatter, short value, StringView specifier, CachedCulture culture)
        {
            if (value < 0 && !specifier.IsEmpty) {
                // if we're negative and doing a hex format, mask out the bits for the conversion
                char c = specifier.Data[0];
                if (c == 'X' || c == 'x')
                    FormatUInt32(formatter, (uint)(value & 0xFFFF), specifier, culture);
            }

            FormatInt32(formatter, value, specifier, culture);
        }
예제 #12
0
        static void NumberToString(StringBuffer formatter, ref Number number, char format, int maxDigits, CachedCulture culture, bool isDecimal = false)
        {
            // ANDing with 0xFFDF has the effect of uppercasing the character
            switch (format & 0xFFDF) {
                case 'C':
                    {
                        var cultureData = culture.CurrencyData;
                        var bufferSize = cultureData.GetBufferSize(ref maxDigits, number.Scale);
                        RoundNumber(ref number, number.Scale + maxDigits);

                        var buffer = stackalloc char[bufferSize];
                        var ptr = FormatCurrency(
                            buffer,
                            ref number,
                            maxDigits,
                            cultureData,
                            number.Sign > 0 ? culture.CurrencyNegativePattern : culture.CurrencyPositivePattern,
                            culture.CurrencySymbol
                        );

                        formatter.Append(buffer, (int)(ptr - buffer));
                        break;
                    }

                case 'F':
                    {
                        var cultureData = culture.FixedData;
                        var bufferSize = cultureData.GetBufferSize(ref maxDigits, number.Scale);
                        RoundNumber(ref number, number.Scale + maxDigits);

                        var buffer = stackalloc char[bufferSize];
                        var ptr = buffer;
                        if (number.Sign > 0)
                            AppendString(&ptr, cultureData.NegativeSign);

                        ptr = FormatFixed(ptr, ref number, maxDigits, cultureData);
                        formatter.Append(buffer, (int)(ptr - buffer));
                        break;
                    }

                case 'N':
                    {
                        var cultureData = culture.NumberData;
                        var bufferSize = cultureData.GetBufferSize(ref maxDigits, number.Scale);
                        RoundNumber(ref number, number.Scale + maxDigits);

                        var buffer = stackalloc char[bufferSize];
                        var ptr = FormatNumber(
                            buffer,
                            ref number,
                            maxDigits,
                            number.Sign > 0 ? culture.NumberNegativePattern : culture.NumberPositivePattern,
                            cultureData
                        );

                        formatter.Append(buffer, (int)(ptr - buffer));
                        break;
                    }

                case 'E':
                    {
                        var cultureData = culture.ScientificData;
                        var bufferSize = cultureData.GetBufferSize(ref maxDigits, number.Scale);
                        maxDigits++;

                        RoundNumber(ref number, maxDigits);

                        var buffer = stackalloc char[bufferSize];
                        var ptr = buffer;
                        if (number.Sign > 0)
                            AppendString(&ptr, cultureData.NegativeSign);

                        ptr = FormatScientific(
                            ptr,
                            ref number,
                            maxDigits,
                            format, // TODO: fix casing
                            cultureData.DecimalSeparator,
                            culture.PositiveSign,
                            culture.NegativeSign
                        );

                        formatter.Append(buffer, (int)(ptr - buffer));
                        break;
                    }

                case 'P':
                    {
                        number.Scale += 2;
                        var cultureData = culture.PercentData;
                        var bufferSize = cultureData.GetBufferSize(ref maxDigits, number.Scale);
                        RoundNumber(ref number, number.Scale + maxDigits);

                        var buffer = stackalloc char[bufferSize];
                        var ptr = FormatPercent(
                            buffer,
                            ref number,
                            maxDigits,
                            cultureData,
                            number.Sign > 0 ? culture.PercentNegativePattern : culture.PercentPositivePattern,
                            culture.PercentSymbol
                        );

                        formatter.Append(buffer, (int)(ptr - buffer));
                        break;
                    }

                case 'G':
                    {
                        var enableRounding = true;
                        if (maxDigits < 1) {
                            if (isDecimal && maxDigits == -1) {
                                // if we're formatting a decimal, default to 29 digits precision
                                // only for G formatting without a precision specifier
                                maxDigits = DecimalPrecision;
                                enableRounding = false;
                            }
                            else
                                maxDigits = number.Precision;
                        }

                        var bufferSize = maxDigits + culture.DecimalBufferSize;
                        var buffer = stackalloc char[bufferSize];
                        var ptr = buffer;

                        // round for G formatting only if a precision is given
                        // we need to handle the minus zero case also
                        if (enableRounding)
                            RoundNumber(ref number, maxDigits);
                        else if (isDecimal && number.Digits[0] == 0)
                            number.Sign = 0;

                        if (number.Sign > 0)
                            AppendString(&ptr, culture.NegativeSign);

                        ptr = FormatGeneral(
                            ptr,
                            ref number,
                            maxDigits,
                            (char)(format - ('G' - 'E')),
                            culture.NumberData.DecimalSeparator,
                            culture.PositiveSign,
                            culture.NegativeSign,
                            !enableRounding
                        );

                        formatter.Append(buffer, (int)(ptr - buffer));
                        break;
                    }

                default:
                    throw new FormatException(string.Format(SR.UnknownFormatSpecifier, format));
            }
        }
예제 #13
0
        public static void FormatUInt64(StringBuffer formatter, ulong value, StringView specifier, CachedCulture culture)
        {
            int digits;
            var fmt = ParseFormatSpecifier(specifier, out digits);

            // ANDing with 0xFFDF has the effect of uppercasing the character
            switch (fmt & 0xFFDF) {
                case 'G':
                    if (digits > 0)
                        goto default;
                    else
                        goto case 'D';

                case 'D':
                    UInt64ToDecStr(formatter, value, digits);
                    break;

                case 'X':
                    // fmt-('X'-'A'+1) gives us the base hex character in either
                    // uppercase or lowercase, depending on the casing of fmt
                    Int64ToHexStr(formatter, value, fmt - ('X' - 'A' + 10), digits);
                    break;

                default:
                    var number = new Number();
                    var buffer = stackalloc char[MaxNumberDigits + 1];
                    number.Digits = buffer;
                    UInt64ToNumber(value, ref number);
                    if (fmt != 0)
                        NumberToString(formatter, ref number, fmt, digits, culture);
                    else
                        NumberToCustomFormatString(formatter, ref number, specifier, culture);
                    break;
            }
        }