dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/Private/NumberFormat C


From: Jonathan Springer <address@hidden>
Subject: [Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/Private/NumberFormat CurrencyFormatter.cs,NONE,1.1 CustomFormatter.cs,NONE,1.1 DecimalFormatter.cs,NONE,1.1 FixedPointFormatter.cs,NONE,1.1 Formatter.cs,NONE,1.1 GeneralFormatter.cs,NONE,1.1 HexadecimalFormatter.cs,NONE,1.1 NumberFormatter.cs,NONE,1.1 PercentFormatter.cs,NONE,1.1 RoundTripFormatter.cs,NONE,1.1 ScientificFormatter.cs,NONE,1.1
Date: Wed, 27 Nov 2002 09:37:29 -0500

Update of /cvsroot/dotgnu-pnet/pnetlib/runtime/System/Private/NumberFormat
In directory subversions:/tmp/cvs-serv18774/runtime/System/Private/NumberFormat

Added Files:
        CurrencyFormatter.cs CustomFormatter.cs DecimalFormatter.cs 
        FixedPointFormatter.cs Formatter.cs GeneralFormatter.cs 
        HexadecimalFormatter.cs NumberFormatter.cs PercentFormatter.cs 
        RoundTripFormatter.cs ScientificFormatter.cs 
Log Message:

New number formatting code.


--- NEW FILE ---
/*
 * CurrencyFormatter.cs - Implementation of the
 *          "System.Private.Formatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Globalization;
using System.Text;

//
//  Currency Formatter - "Cxx" - Valid for only integral types.
internal class CurrencyFormatter : Formatter
{
        private static String FormatPrefixAndSuffix(String value, bool isneg,
                                                                                
                IFormatProvider provider)
        {
                NumberFormatInfo nfi = NumberFormatInfo(provider);
                string ret = null;

                if(isneg)
                {
                        switch(nfi.CurrencyNegativePattern)
                        {
                                case 0:
                                        ret = "(" + nfi.CurrencySymbol + value 
+ ")";
                                        break;

                                case 1:
                                        ret = nfi.NegativeSign + 
nfi.CurrencySymbol + value;
                                        break;

                                case 2:
                                        ret = nfi.CurrencySymbol + 
nfi.NegativeSign + value;
                                        break;

                                case 3:
                                        ret = nfi.CurrencySymbol + value + 
nfi.NegativeSign;
                                        break;

                                case 4:
                                        ret = "(" + value + nfi.CurrencySymbol 
+ ")";
                                        break;

                                case 5:
                                        ret = nfi.NegativeSign + value + 
nfi.CurrencySymbol;
                                        break;

                                case 6:
                                        ret = value + nfi.NegativeSign;
                                        break;

                                case 7:
                                        ret = value + nfi.CurrencySymbol + 
nfi.NegativeSign;
                                        break;

                                case 8:
                                        ret = nfi.NegativeSign + value + " " + 
nfi.CurrencySymbol;
                                        break;

                                case 9:
                                        ret = nfi.NegativeSign + 
nfi.CurrencySymbol + " " + value;
                                        break;

                                case 10:
                                        ret = value + " " + nfi.CurrencySymbol 
+ nfi.NegativeSign;
                                        break;

                                case 11:
                                        ret = nfi.CurrencySymbol + " " + value 
+ nfi.NegativeSign;
                                        break;

                                case 12:
                                        ret = nfi.CurrencySymbol + " " + 
nfi.NegativeSign + value;
                                        break;

                                case 13:
                                        ret = value + nfi.NegativeSign + " " + 
nfi.CurrencySymbol;
                                        break;

                                case 14:
                                        ret = "(" + nfi.CurrencySymbol + " " + 
value + ")";
                                        break;

                                case 15:
                                        ret = "(" + value + " " + 
nfi.CurrencySymbol + ")";
                                        break;
                        }
                }
                else
                {
                        switch(nfi.CurrencyPositivePattern)
                        {
                                case 0:
                                        ret = nfi.CurrencySymbol + value;
                                        break;

                                case 1:
                                        ret = value + nfi.CurrencySymbol;
                                        break;

                                case 2:
                                        ret = nfi.CurrencySymbol + " " + value;
                                        break;

                                case 3:
                                        ret = value + " " + nfi.CurrencySymbol;
                                        break;
                        }
                }
                return ret;
        }

        public CurrencyFormatter(int precision)
        {
                this.precision = precision;
        }

        public override string Format(Object o, IFormatProvider provider)
        {
                //
                //  Create working string
                //
                int precision = (this.precision == -1) ?
                        NumberFormatInfo(provider).CurrencyDecimalDigits : 
this.precision;
                string rawnumber = FormatAnyRound(o, precision);

                //
                //  Test for negative numbers
                //
                bool isNegative = false;
                if (rawnumber[0] == '-')
                {
                        isNegative = true;
                        rawnumber = rawnumber.Substring(1);
                }

                // 
                //  Build out the integral portion of the number
                //
                StringBuilder ret = new StringBuilder(
                                
GroupInteger(rawnumber.Substring(0,rawnumber.IndexOf('.')),
                                        
NumberFormatInfo(provider).CurrencyGroupSizes,
                                        
NumberFormatInfo(provider).CurrencyGroupSeparator));

                //
                //  Add the post-decimal portion.
                //
                if (precision > 0)
                {
                        
ret.Append(NumberFormatInfo(provider).CurrencyDecimalSeparator);
                        ret.Append(
                                        rawnumber.PadRight(
                                                rawnumber.IndexOf('.')+1 + 
precision, '0')
                                        .Substring(rawnumber.IndexOf('.') + 1, 
precision));
                }

                //
                //  Final formatting
                //
                return FormatPrefixAndSuffix(ret.ToString(), isNegative, 
provider);
        }               
} // class CurrencyFormatter

} // namespace System.Private.Format


--- NEW FILE ---
/*
 * CustomFormatter.cs - Implementation of the
 *          "System.Private.Formatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Collections;
using System.Globalization;
using System.Text;

internal class CustomFormatter : Formatter
{
        //
        //  Constants and read-only
        //
        private const char zeroPlaceholder = '0';
        private const char digitPlaceholder = '#';
        private const char decimalSeparator = '.';
        private const char groupSeparator = ',';
        private const char percentagePlaceholder = '%';

        private static readonly char[] engineeringFormat = {'E','e'};
        private static readonly char[] sectionSeparator = {';'};

        //
        //  Stored format information 
        //
        private string originalFormat;

        private string positiveFormat;
        private string negativeFormat;
        private string zeroFormat;
        bool includeNegSign;           //  Should a '-' be included?
        
        //
        //  Constructor - Take custom format string as input.
        //
        public CustomFormatter(string inFormat)
        {
                string[] fmts;

                this.originalFormat = inFormat;
                fmts = originalFormat.Split(sectionSeparator, 3);

                if (fmts.Length == 0)
                {
                        this.positiveFormat = null;
                        this.negativeFormat = null;
                        this.zeroFormat = null;
                        this.includeNegSign = true;
                } 
                else if (fmts.Length == 1)
                {
                        this.positiveFormat = inFormat;
                        this.negativeFormat = inFormat;
                        this.zeroFormat = inFormat;
                        this.includeNegSign = true;
                }
                else if (fmts.Length == 2)
                {
                        this.positiveFormat = fmts[0];
                        this.negativeFormat = fmts[1];
                        this.zeroFormat = fmts[0];
                        this.includeNegSign = false;
                }
                else
                {
                        this.positiveFormat = fmts[0];
                        if (this.negativeFormat == String.Empty)
                        {
                                this.negativeFormat = fmts[0];
                                this.includeNegSign=true;
                        }
                        else
                        {
                                this.negativeFormat = fmts[1];
                                this.includeNegSign=false;
                        }
                        this.zeroFormat = fmts[2];
                }
        }

        private int ScientificStart(string format)
        {
                int ret, pos;

                pos = format.IndexOfAny(engineeringFormat, pos);

                while (pos != -1)
                {
                        ret = pos++;
                        if (format[pos] == '+' || format[pos] == '-') 
                        {
                                pos++;
                        }
                        if (format[pos] == '0') 
                        {
                                return ret;
                        }
                        pos = format.IndexOfAny(engineeringFormat, pos);
                } 

                return -1;
        }

        private string FormatFromSign(int sign)
        {
                string ret = null;

                switch(sign)
                {
                case 1:
                        ret = positiveFormat;
                        break;
                case -1:
                        ret = negativeFormat;
                        break;
                case 0:
                        ret = zeroFormat;
                        break;
                }
                return ret;
        }

        //
        //  FormatRawNumber - Given a string of form 'n*.n*', format it based
        //  upon the custom format.
        //
        private string FormatRawNumber(string value, string format, int sign,
                                                                                
       IFormatProvider provider)
        {
                string rawnumber;
                int firstzero, lastzero;
                int scale = 0;

                //  Locate the decimal point
                int decimalPos = format.IndexOf(decimalSeparator);
                if (decimalPos == -1) decimalPos = format.Length;

                //  Scaling
                int formatindex = decimalPos - 1;
                while (format[formatindex] == groupSeparator)
                {
                        scale += 3;
                        --formatindex;
                }

                if (scale > 0)
                {
                        // Move the decimal point
                        StringBuilder temp 
                                = new 
StringBuilder(value.Substring(0,value.IndexOf('.')));
                        if (temp.Length < scale)
                        {
                                temp.Insert(0,"0",scale - temp.Length);
                        }
                        temp.Insert(temp.Length - scale,'.');
                        temp.Append(value.Substring(value.IndexOf('.')+1));
                        if (includeNegSign && sign == -1)
                        {
                                temp.Insert(0, 
NumberFormatInfo(provider).NegativeSign);
                        }
                        rawnumber = temp.ToString();
                }
                else
                {
                        if (includeNegSign && sign == -1)
                        {
                                StringBuilder temp = new StringBuilder(value);
                                
temp.Insert(0,NumberFormatInfo(provider).NegativeSign);
                                rawnumber = temp.ToString();
                        }
                        else
                        {
                                rawnumber = value;
                        }
                }

                //  Formatting
                int rawindex = rawnumber.IndexOf('.') - 1;
                StringBuilder ret = new StringBuilder();

                while (rawindex >= 0 && formatindex >= 0) {
                        if (format[formatindex] == digitPlaceholder)
                        {
                                ret.Insert(0, rawnumber[rawindex--]);
                        }
                        else if (format[formatindex] == zeroPlaceholder )
                        {
                                // Don't put a negative if a zero should go 
there.
                                if ( rawnumber[rawindex] < '0' || 
rawnumber[rawindex] > '9')
                                {
                                        int i = formatindex + 1;
                                        while (format[i] == ',') ++i;

                                        if (format[i] == '.') 
                                        {
                                                ret.Insert(0,'0');
                                        }
                                        else
                                        {
                                                ret.Insert(0, 
rawnumber[rawindex--]);
                                        }
                                }
                                else
                                {
                                        ret.Insert(0, rawnumber[rawindex--]);
                                }
                        }
                        else if (format[formatindex] == groupSeparator)
                        {
                                ret.Insert(0, 
NumberFormatInfo(provider).NumberGroupSeparator);
                        }
                        else
                        {
                                ret.Insert(0, format[formatindex]);
                        }
                        --formatindex;
                }

                if (rawindex >= 0)
                {
                        ret.Insert(0, rawnumber.Substring(0,rawindex));
                }

                //  Zero pad
                firstzero = format.IndexOf(zeroPlaceholder);
                if (firstzero != -1)
                {
                        while (firstzero <= formatindex)
                        {
                                if (format[formatindex] == digitPlaceholder
                                                || format[formatindex] == 
zeroPlaceholder)
                                {
                                        ret.Insert(0,'0');
                                }
                                else if (format[formatindex] == groupSeparator)
                                {
                                        ret.Insert(0,
                                                
NumberFormatInfo(provider).NumberGroupSeparator);
                                }
                                else
                                {
                                        ret.Insert(0, format[formatindex]);
                                }
                                --formatindex;
                        }
                }

                //  Fill out literal portion
                while (formatindex >= 0)
                {
                        if( !( format[formatindex] == digitPlaceholder
                        || format[formatindex] == zeroPlaceholder
                                        || format[formatindex] == 
groupSeparator ))
                        {
                                ret.Insert(0, format[formatindex]);
                        }
                        --formatindex;
                }

                //  Decimal point dealings
                rawindex = rawnumber.IndexOf('.') + 1;
                formatindex = decimalPos + 1;

                if(decimalPos < format.Length)
                {
                        
ret.Append(NumberFormatInfo(provider).NumberDecimalSeparator);
                }

                while (rawindex < rawnumber.Length && formatindex < 
format.Length) {
                        if (format[formatindex] == digitPlaceholder 
                                        || format[formatindex] == 
zeroPlaceholder )
                        {
                                ret.Append(rawnumber[rawindex++]);
                        }
                        else
                        {
                                ret.Append(format[formatindex]);
                        }
                        ++formatindex;
                }

                // More zero padding
                lastzero = format.LastIndexOf(zeroPlaceholder);

                while (lastzero >= formatindex)
                {
                        if (format[formatindex] == digitPlaceholder
                                        || format[formatindex] == 
zeroPlaceholder)
                        {
                                ret.Append('0');
                        }
                        else
                        {
                                ret.Append(format[formatindex]);
                        }
                        formatindex++;
                }

                while (formatindex < format.Length)
                {
                        if ( !( format[formatindex] == digitPlaceholder
                                                || format[formatindex] == 
zeroPlaceholder ))
                        {
                                ret.Append(format[formatindex]);
                        }
                        ++formatindex;
                }

                return ret.ToString();
        }

        private string FormatScientific(double d, string format, int sign,
                                                                                
                        IFormatProvider provider)
        {
                int exponent = (int)Math.Floor(Math.Log10(d));
                double mantissa = d/Math.Pow(10,exponent);

                int i = ScientificStart(format);

                //  Format the mantissa
                StringBuilder ret = new StringBuilder(
                                FormatFloat(mantissa, format.Substring(1, i), 
sign, provider)
                                                                        + 
format[i++]);

                //  Sign logic
                if (format[i] == '+' && exponent >= 0)
                {
                        ret.Append(NumberFormatInfo(provider).PositiveSign);
                }
                else if (exponent < 0)
                {
                        ret.Append(NumberFormatInfo(provider).NegativeSign);
                }

                if (format[i] == '+' || format[i] == '-')
                {
                        ++i;
                }

                // Place exponent value into string.
                int exponentMin = 0;
                while (i<format.Length && format[i] == '0')
                {
                        ++i; 
                        ++exponentMin;
                }

                //  Format the exponent and append, 
                string exponentString = 
                        Formatter.FormatInteger((ulong)Math.Abs(exponent));
                ret.Append(exponentString.Substring(0, exponentString.Length-1)
                                                                                
                .PadLeft(exponentMin,'0'));
                
                // Fill out the string
                ret.Append(format.Substring(i));

                return ret.ToString();
        }

        private string FormatInteger(ulong value, string format, int sign,
                                                                                
                IFormatProvider provider)
        {
                return FormatRawNumber(Formatter.FormatInteger(value)
                                                                                
                ,format, sign, provider);
        }


        private string FormatFloat(double d, string format, int sign,
                                                                                
                IFormatProvider provider)
        {
                int formatindex, precision;

                formatindex = format.IndexOf('.');
                if (formatindex == -1) {
                        precision = 0;
                }
                else
                {
                        for (formatindex++, precision = 0; 
                                        formatindex < format.Length; 
formatindex++)
                        {
                                if (format[formatindex] == digitPlaceholder ||
                                                format[formatindex] == 
zeroPlaceholder)
                                {
                                        ++precision;
                                }
                        }
                }

                return FormatRawNumber( Formatter.FormatFloat(d, precision+2), 
                                                                                
format, sign, provider);
        }

        private string FormatDecimal(decimal value, string format, int sign,
                                                                                
                IFormatProvider provider)
        {
                if (format.IndexOf(percentagePlaceholder) != -1)
                {
                        return 
FormatRawNumber(Formatter.FormatDecimal(value*100),
                                        format, sign, provider);
                }
                else
                {
                        return FormatRawNumber(Formatter.FormatDecimal(value),
                                        format, sign, provider);
                }
        }

        //
        //  Public access method.
        //
        public override string Format(Object o, IFormatProvider provider)
        {
                if (IsSignedInt(o))
                {
                        long val = OToLong(o);
                        string format = FormatFromSign(Math.Sign(val));
                        if (ScientificStart(format) == -1)
                        {
                                return FormatInteger((ulong)Math.Abs(val),
                                                format, Math.Sign(val), 
provider);
                        }
                        else
                        {
                                return FormatScientific((double)Math.Abs(val),
                                                format, Math.Sign(val), 
provider);
                        }
                }
                else if (IsUnsignedInt(o))
                {
                        ulong val = OToUlong(o);
                        string format = ( (val==0) ? zeroFormat : 
positiveFormat);

                        if (ScientificStart(format) == -1)
                        {
                                return FormatInteger(val, format, val == 0 ? 0 
: 1, provider);
                        }
                        else
                        {
                                return FormatScientific( (double)val,
                                                format, val == 0 ? 0 : 1, 
provider);
                        }
                }
                else if (IsFloat(o))
                {
                        double val = OToDouble(o);
                        string format = FormatFromSign(Math.Sign(val));
                        if (ScientificStart(format) == -1)
                        {
                                return FormatFloat(Math.Abs(val),
                                                format, Math.Sign(val), 
provider);
                        }
                        else
                        {
                                return FormatScientific(Math.Abs(val),
                                                format, Math.Sign(val), 
provider);
                        }
                }
                else if (IsDecimal(o))
                {
                        decimal val = (decimal) o;
                        string format = FormatFromSign(Math.Sign(val));
                        if (ScientificStart(format) == -1)
                        {
                                return FormatDecimal(Math.Abs(val),
                                                format, Math.Sign(val), 
provider);
                        }
                        else
                        {
                                return FormatScientific((double)Math.Abs(val),
                                                format, Math.Sign(val), 
provider);
                        }
                }
                else if (o is IFormattable)
                {
                        return ((IFormattable)o).ToString(originalFormat, 
provider);
                }
                else
                {
                        return o.ToString();
                }
        }

} // class CustomFormatter

} // namespace System.Private.NumberFormat


--- NEW FILE ---

/*
 * DecimalFormatter.cs - Implementation of the
 *          "System.Private.NumberFormat.DecimalFormatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Text;

//
//  Decimal Formatter - "Dxx" - Valid for only integral types.
internal class DecimalFormatter : Formatter
{
        public DecimalFormatter(int precision)
        {
                this.precision = (precision == -1) ? 1 : precision;
        }

        public override string Format(Object o, IFormatProvider provider)
        {
                bool isNegative = false;
                ulong value;
                string rawnumber;
                StringBuilder buf;

                //  Type validation
                if (IsSignedInt(o) && OToLong(o) < 0)
                {
                        isNegative = true;
                        value = (ulong) -OToLong(o);
                }
                else if (IsSignedInt(o) || IsUnsignedInt(o))
                {
                        isNegative = false;
                        value = OToUlong(o);
                }
                else
                {
                        //  This is a bad place to be.
                        throw new FormatException(_("Format_TypeException"));   
                }

                //  Type conversion
                rawnumber=(FormatInteger(value));
                buf = new StringBuilder(rawnumber.Substring(0, 
rawnumber.Length-1));

                //  Padding
                if (buf.Length < precision)
                {
                        buf.Insert(0, "0", precision - buf.Length);
                }

                //  Negative sign
                if (isNegative)
                {
                        buf.Insert(0, NumberFormatInfo(provider).NegativeSign);
                }

                return buf.ToString();
        }               
} // class DecimalFormatter

} // namespace System.Private.NumberFormat


--- NEW FILE ---
/*
 * FixedPointFormatter.cs - Implementation of the
 *          "System.Private.NumberFormat.FixedPointFormatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Globalization;
using System.Text;

internal class FixedPointFormatter : Formatter
{
        public FixedPointFormatter(int precision)
        {
                this.precision = precision;
        }

        public override string Format(Object o, IFormatProvider provider)
        {
                //  Calculate precision
                int precision = (this.precision == -1) ?
                        NumberFormatInfo(provider).NumberDecimalDigits : 
this.precision;

                //  Get string
                string rawnumber = FormatAnyRound(o, precision);
                StringBuilder ret = new StringBuilder();

                if (rawnumber[0] == '-')
                {
                        ret.Append(NumberFormatInfo(provider).NegativeSign);
                        rawnumber = rawnumber.Substring(1);
                }

                if (rawnumber[0] == '.')
                {
                        ret.Append('0');
                }
                else
                {
                        
ret.Append(rawnumber.Substring(0,rawnumber.IndexOf('.')));
                }

                if (precision > 0)
                {
                        
ret.Append(NumberFormatInfo(provider).NumberDecimalSeparator);
                        ret.Append(
                                        
rawnumber.Substring(rawnumber.IndexOf('.')+1, precision));
                }

                return ret.ToString();
        }               
} // class FixedPointFormatter

} // namespace System.Private.NumberFormat


--- NEW FILE ---
/*
 * Formatter.cs - Implementation of the
 *          "System.Private.NumberFormat.Formatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Collections;
using System.Globalization;
using System.Text;

internal abstract class Formatter
{
        // 
----------------------------------------------------------------------
        //  Private static variables for formatter
        //
        private const string validformats = "CcDdEeFfGgNnPpRrXx";
        static private IDictionary formats = new Hashtable();

        // 
----------------------------------------------------------------------
        //  Protected data for other methods
        //
        static protected readonly char[] decimalDigits =
        {'0','1','2','3','4','5','6','7','8','9'};

        // 
----------------------------------------------------------------------
        //  Protected state information
        //
        protected int precision;

        // 
----------------------------------------------------------------------
        //  Protected utility methods
        //
        static protected NumberFormatInfo 
                NumberFormatInfo(IFormatProvider provider)
        {
                return provider == null ?
                        System.Globalization.NumberFormatInfo.CurrentInfo :
                        (NumberFormatInfo) provider.GetFormat(
                                                                
typeof(System.Globalization.NumberFormatInfo));
        }

        static protected bool IsSignedInt(Object o)
        {
                return (o is SByte || o is Int16 || o is Int32 || o is Int64);
        }
        
        static protected bool IsUnsignedInt(Object o)
        {
                return (o is Byte || o is UInt16 || o is UInt32 || o is UInt64);
        }
        
        static protected bool IsFloat(Object o)
        {
                return (o is Single || o is Double);
        }
        
        static protected bool IsDecimal(Object o)
        {
                return (o is Decimal);
        }

        static protected double OToDouble(Object o)
        {
                double ret;

                if (o is Int32)
                {
                        Int32 n = (Int32)o;
                        ret = (double)n;
                }
                else if (o is UInt32)
                {
                        UInt32 n = (UInt32)o;
                        ret = (double)n;
                }
                else if (o is SByte)
                {
                        SByte n = (SByte)o;
                        ret = (double)n;
                }
                else if (o is Byte)
                {
                        Byte n = (Byte)o;
                        ret = (double)n;
                }
                else if (o is Int16)
                {
                        Int16 n = (Int16)o;
                        ret = (double)n;
                }
                else if (o is UInt16)
                {
                        UInt16 n = (UInt16)o;
                        ret = (double)n;
                }
                else if (o is Int64)
                {
                        Int64 n = (Int64)o;
                        ret = (double)n;
                }
                else if (o is UInt64)
                {
                        UInt64 n = (UInt64)o;
                        ret = (double)n;
                }
                else if (o is Single)
                {
                        Single n = (Single)o;
                        ret = (double)n;
                }
                else if (o is Double)
                {
                        ret = (double)o;
                }
                else if (o is Decimal)
                {
                        Decimal n = (Decimal)o;
                        ret = (double)n;
                }
                else
                {
                        throw new FormatException(_("Format_TypeException"));
                }
                return ret;
        }

        static protected ulong OToUlong(Object o)
        {
                ulong ret;

                if (o is Int32)
                {
                        Int32 n = (Int32)o;
                        ret = (ulong)n;
                }
                else if (o is UInt32)
                {
                        UInt32 n = (UInt32)o;
                        ret = (ulong)n;
                }
                else if (o is SByte)
                {
                        SByte n = (SByte)o;
                        ret = (ulong)n;
                }
                else if (o is Byte)
                {
                        Byte n = (Byte)o;
                        ret = (ulong)n;
                }
                else if (o is Int16)
                {
                        Int16 n = (Int16)o;
                        ret = (ulong)n;
                }
                else if (o is UInt16)
                {
                        UInt16 n = (UInt16)o;
                        ret = (ulong)n;
                }
                else if (o is Int64)
                {
                        Int64 n = (Int64)o;
                        ret = (ulong)n;
                }
                else if (o is UInt64)
                {
                        ret = (ulong)o;
                }
                else if (o is Single)
                {
                        Single n = (Single)o;
                        ret = (ulong)n;
                }
                else if (o is Double)
                {
                        Double n = (Double)o;
                        ret = (ulong)n;
                }
                else if (o is Decimal)
                {
                        Decimal n = (Decimal)o;
                        ret = (ulong)n;
                }
                else
                {
                        throw new FormatException(_("Format_TypeException"));
                }
                return ret;
        }

        static protected long OToLong(Object o)
        {
                long ret;

                if (o is Int32)
                {
                        Int32 n = (Int32)o;
                        ret = (long)n;
                }
                else if (o is UInt32)
                {
                        UInt32 n = (UInt32)o;
                        ret = (long)n;
                }
                else if (o is SByte)
                {
                        SByte n = (SByte)o;
                        ret = (long)n;
                }
                else if (o is Byte)
                {
                        Byte n = (Byte)o;
                        ret = (long)n;
                }
                else if (o is Int16)
                {
                        Int16 n = (Int16)o;
                        ret = (long)n;
                }
                else if (o is UInt16)
                {
                        UInt16 n = (UInt16)o;
                        ret = (long)n;
                }
                else if (o is Int64)
                {
                        ret = (long)o;
                }
                else if (o is UInt64)
                {
                        UInt64 n = (UInt64)o;
                        ret = (long)n;
                }
                else if (o is Single)
                {
                        Single n = (Single)o;
                        ret = (long)n;
                }
                else if (o is Double)
                {
                        Double n = (Double)o;
                        ret = (long)n;
                }
                else if (o is Decimal)
                {
                        Decimal n = (Decimal)o;
                        ret = (long)n;
                }
                else
                {
                        throw new FormatException(_("Format_TypeException"));
                }
                return ret;
        }

        static protected string FormatAnyRound(Object o, int precision)
        {
                string ret;

                //  Type validation
                if (IsSignedInt(o) && (OToLong(o) < 0) )
                {
                        ret = "-" + Formatter.FormatInteger((ulong) 
-OToLong(o));
                }
                else if (IsSignedInt(o) || IsUnsignedInt(o))
                {
                        ret = Formatter.FormatInteger(OToUlong(o));
                }
                else if (IsDecimal(o))
                {
                        // Rounding code
                        int i;
                        decimal r;

                        for (int i=0, r=5; i<= precision; i++) 
                        {
                                r /= 10;
                        }

                        if ((decimal)o < 0)
                        {
                                ret = "-" + 
Formatter.FormatDecimal(-((decimal)o)+r);
                        }
                        else
                        {
                                ret = Formatter.FormatDecimal((decimal)o+r);
                        }
                        ret = ret.Substring(0, ret.IndexOf('.')+precision+1);
                }
                else if (IsFloat(o))
                {
                        // Beware rounding code
                        if (OToDouble(o) < 0)
                        {
                                ret = "-" + 
                                        Formatter.FormatFloat(
                                                        -OToDouble(o) + 5 * 
Math.Pow(10, -precision - 1)
                                                        ,precision);
                        }
                        else
                        {
                                ret = Formatter.FormatFloat(
                                                OToDouble(o) + 5 * Math.Pow(10, 
-precision - 1) 
                                                ,precision);
                        }
                }
                else
                {
                        //  This is a bad place to be.
                        throw new FormatException(_("Format_TypeException"));   
                }
                return ret;
        }

        static protected string FormatInteger(ulong value)
        {
                //  Note:  CustomFormatter counts on having the trailing decimal
                //  point.  If you're considering taking it out, think hard.
                
                if (value == 0) return ".";

                StringBuilder ret = new StringBuilder(".");
                ulong work = value;

                while (work > 0) {
                        ret.Insert(0, decimalDigits[work % 10]);
                        work /= 10;
                }

                return ret.ToString();
        }

        static protected string FormatDecimal(decimal value)
        {
                if (value == 0) return ".";

                int [] bits = Decimal.GetBits(value);
            int scale = (bits[3] >> 16) & 0xff;
                decimal work = value * scale;
                StringBuilder ret = new StringBuilder();
            
                while (work >= 0) {
                        ret.Insert(0, decimalDigits, (int)(work % 10), 1);
                        work = Decimal.Truncate(work/10);
                }

                if (ret.Length < scale) {
                        ret.Insert(0, "0", ret.Length - scale);
                }

                ret.Insert(ret.Length - scale, '.');

                return ret.ToString();
        }

        static protected string FormatFloat(double value, int precision)
        {
                if (value == 0.0) return ".";

                StringBuilder ret =
                        new 
StringBuilder(FormatInteger((ulong)Math.Floor(value)));
                double fraction = (value - Math.Floor(value)) * 10.0;

                for (int i=0; i < precision && fraction > 0.0; i++)
                {
                        ret.Append(decimalDigits[(int)Math.Floor(fraction)]);
                        fraction = (fraction - Math.Floor(fraction)) * 10;
                }
                return ret.ToString();
        }

        static protected string GroupInteger(string value, int[] groupSizes,
                                                                                
        string separator)
        {
                if (value == String.Empty) return "0";

                int vindex = value.Length;
                int i = 0;
                StringBuilder ret = new StringBuilder();

                while (vindex > 0)
                {
                        if (vindex - groupSizes[i] <= 0 || groupSizes[i] == 0)
                        {
                                ret.Insert(0, value.Substring(0, vindex));
                                vindex = 0;
                        }
                        else
                        {
                                vindex -= groupSizes[i];
                                ret.Insert(0, value.Substring(vindex, 
groupSizes[i]));
                                ret.Insert(0, separator);
                        }
                        if (i < groupSizes.Length-1) ++i;
                }

                return ret.ToString();
        }
        
        // 
----------------------------------------------------------------------
        //  Public interface
        //

        //
        //  Factory/Singleton method
        //
        public static Formatter CreateFormatter(String format)
        {
                return CreateFormatter(format, null);
        }

        public static Formatter CreateFormatter(String format, IFormatProvider 
p)
        {
                int precision;
                Formatter ret;

                if (format == null)
                {
                        throw new FormatException(_("Format_StringException"));
                }

                //  Search for cached formats
                if (formats[format] != 0)
                {
                        return (Formatter) formats[format];
                }

                // Validate the format.  
                // It should be of the form 'X', 'X9', or 'X99'.
                // If it's not, return a CustomFormatter.
                if (validformats.IndexOf(format[0]) == -1 || format.Length > 3)
                {
                        return new CustomFormatter(format);
                }

                try 
                {
                        precision = (format.Length == 1) ? 
                                -1 : Byte.Parse(format.Substring(1));
                }
                catch (FormatException)
                {
                        return new CustomFormatter(format);
                }
                
                switch(format[0])       // There's always a yucky switch 
somewhere
                {
                case 'C':
                case 'c':
                        ret = new CurrencyFormatter(precision);
                        break;
                
                case 'D':
                case 'd':
                        ret = new DecimalFormatter(precision);
                        break;
                
                case 'E':
                case 'e':
                        ret = new ScientificFormatter(precision, format[0]);
                        break;
                
                case 'F':
                case 'f':
                        ret = new FixedPointFormatter(precision);
                        break;

                case 'G':
                case 'g':
                        ret = new GeneralFormatter(precision, format[0]);
                        break;

                case 'N':
                case 'n':
                        ret = new 
System.Private.NumberFormat.NumberFormatter(precision);
                        break;

                case 'P':
                case 'p':
                        ret = new PercentFormatter(precision);
                        break;
                
                case 'R':
                case 'r':
                        ret = new RoundTripFormatter(precision);
                        break;

                case 'X':
                case 'x':
                        ret = new HexadecimalFormatter(precision, format[0]);
                        break;

                default:
                        ret = new CustomFormatter(format);
                        break;
                }
                return ret;
        }

        //
        //  Public access method.
        //
        public abstract string Format(Object o, IFormatProvider provider);

} // class Formatter

} // namespace System.Private.Format


--- NEW FILE ---
/*
 * GeneralFormatter.cs - Implementation of the
 *          "System.Private.NumberFormat.GeneralFormatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Text;

//
//  General Formatter 
//
internal class GeneralFormatter : Formatter
{
        char Ee;

        public GeneralFormatter(int precision, char Gg)
        {
                this.precision = precision;
                switch(Gg)
                {
                        case 'G':
                                Ee = 'E';
                                break;
                        case 'g':
                                Ee = 'e';
                                break;
                        default:
                                throw new 
FormatException(_("Format_StringException"));
                                break;
                }
        }

        private static int PrecisionOf(Object o) 
        {
                if (o is Int16 || o is UInt16) return 5;
                if (o is Int32 || o is UInt32) return 10;
                if (o is Int64 || o is UInt64) return 19;
                if (o is Single) return 7;
                if (o is Double) return 15;
                if (o is Decimal) return 29;
                throw new FormatException(_("Format_TypeException"));
        }

        public override string Format(Object o, IFormatProvider provider)
        {
                int precision, exponent;

                if (this.precision == -1)
                {
                        precision = PrecisionOf(o);
                }

                exponent = (int) Math.Floor(Math.Log10(OToDouble(o)));

                if (IsSignedInt(o) || IsUnsignedInt(o))
                {
                        if (exponent < precision)
                        {
                                return new FixedPointFormatter(0).Format(o, 
provider);
                        }
                        else
                        {
                                return 
                                        new ScientificFormatter(precision, 
Ee).Format(o, provider);
                        }
                }

                if (exponent >= -4 && exponent < precision)
                {
                        return new FixedPointFormatter(precision).Format(o, 
provider);
                }
                else
                {
                        return new ScientificFormatter(precision, Ee).Format(o, 
provider);
                }
        }               

} // class GeneralFormatter

} // namespace System.Private.NumberFormat


--- NEW FILE ---
/*
 * HexadecimalFormatter.cs - Implementation of the
 *          "System.Private.NumberFormat.HexadecimalFormatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Text;

internal class HexadecimalFormatter : Formatter
{
        //  Hexadecimal digits -- upper and lower case.
        static private readonly char[] ucdigits =
        {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        static private readonly char[] lcdigits =       
        {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};

        //  Return values.
        private char[] digits;

        public HexadecimalFormatter(int precision, char format)
        {
                this.precision = (precision == -1) ? 1 : precision;
                switch (format)
                {
                case 'X':
                        digits = ucdigits;
                        break;
                case 'x':
                        digits = lcdigits;
                        break;
                default:
                        throw new FormatException(_("Format_StringException"));
                        break;
                }
        }

        private string Format (long value)
        {
                if (value >= 0) return Format((ulong) value);

                //  This is a bona-fide negative number, but we're going
                //  to work it in two's complement.
                ulong uvalue;
                StringBuilder buf = new StringBuilder();

                for (uvalue = unchecked((ulong)value);  
                        uvalue < System.UInt64.MaxValue;
                        uvalue = unchecked((ulong) ((long)uvalue) >> 4));  // 
Signed shift
                {
                        buf.Insert(0, digits[uvalue % 16]);
                }

                return buf.ToString().PadLeft(precision, '0');
        }

        private string Format(ulong value)
        {
                ulong uvalue;
                StringBuilder buf = new StringBuilder();

                //  Format the number.
                for (uvalue = value; uvalue > 0; uvalue >>= 4)
                {
                        buf.Insert(0, digits[uvalue % 16]);
                }

                return buf.ToString().PadLeft(precision, '0');
        }

        public override string Format(Object o, IFormatProvider provider)
        {
                bool isNegative = false;
                long value;

                //  Type validation
                if (IsSignedInt(o))
                {
                        return Format(OToLong(o));
                }
                else if (IsUnsignedInt(o))
                {
                        return Format(OToUlong(o));
                }

                //  This is a bad place to be.
                throw new FormatException(_("Format_TypeException"));   
        }               
} // class HexadecimalFormatter

} // namespace System.Private.NumberFormat


--- NEW FILE ---
/*
 * NumberFormatter.cs - Implementation of the
 *          "System.Private.NumberFormat.Formatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Globalization;
using System.Text;

//
//  Number Formatter
internal class NumberFormatter : Formatter
{
        private static String FormatPrefixAndSuffix(String value, bool isneg,
                                                                                
                IFormatProvider provider)
        {
                NumberFormatInfo nfi = NumberFormatInfo(provider);
                string ret;

                if(isneg)
                {
                        switch(nfi.NumberNegativePattern)
                        {
                                case 0:
                                        ret = "(" + value + ")";
                                        break;

                                case 1:
                                        ret = nfi.NegativeSign + value;
                                        break;

                                case 2:
                                        ret = nfi.NegativeSign + " " + value;
                                        break;

                                case 3:
                                        ret = value + nfi.NegativeSign;
                                        break;

                                case 4:
                                        ret = value + " " + nfi.NegativeSign;
                                        break;
                        }
                }
                else
                {
                        ret =  value;
                }
                return ret;
        }

        public NumberFormatter(int precision)
        {
                this.precision = precision;
        }

        public override string Format(Object o, IFormatProvider provider)
        {
                //
                //  Create working string
                //
                int precision = (this.precision == -1) ?
                        NumberFormatInfo(provider).NumberDecimalDigits : 
this.precision;
                string rawnumber = FormatAnyRound(o, precision);

                //
                //  Test for negative numbers
                //
                bool isNegative = false;
                if (rawnumber[0] == '-')
                {
                        isNegative = true;
                        rawnumber = rawnumber.Substring(1);
                }

                // 
                //  Build out the integral portion of the number
                //
                StringBuilder ret = new StringBuilder(
                                
GroupInteger(rawnumber.Substring(0,rawnumber.IndexOf('.')),
                                        
NumberFormatInfo(provider).NumberGroupSizes,
                                        
NumberFormatInfo(provider).NumberGroupSeparator));

                //
                //  Add the post-decimal portion.
                //
                if (precision > 0)
                {
                        
ret.Append(NumberFormatInfo(provider).NumberDecimalSeparator);
                        ret.Append(
                                rawnumber.Substring(rawnumber.IndexOf('.')+1, 
precision));
                }

                //
                //  Final formatting
                //
                return FormatPrefixAndSuffix(ret.ToString(), isNegative, 
provider);
        }               
} // class NumberFormatter

} // namespace System.Private.Format


--- NEW FILE ---
/*
 * PercentFormatter.cs - Implementation of the
 *          "System.Private.NumberFormat.PercentFormatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Globalization;
using System.Text;

//
//  Percent Formatter
internal class PercentFormatter : Formatter
{
        private static String FormatPrefixAndSuffix(String value, bool isneg,
                                                                                
                IFormatProvider provider)
        {
                NumberFormatInfo nfi = NumberFormatInfo(provider);
                string ret;

                if(isneg)
                {
                        switch(nfi.PercentNegativePattern)
                        {
                                case 0:
                                        ret = nfi.NegativeSign + value + " " + 
nfi.PercentSymbol;
                                        break;

                                case 1:
                                        ret = nfi.NegativeSign + value + 
nfi.PercentSymbol;
                                        break;

                                case 2:
                                        ret = nfi.NegativeSign + 
nfi.PercentSymbol + value;
                                        break;
                        }
                }
                else
                {
                        switch(nfi.PercentPositivePattern)
                        {
                                case 0:
                                        ret = value + " " + nfi.PercentSymbol;
                                        break;

                                case 1:
                                        ret = value + nfi.PercentSymbol;
                                        break;

                                case 2:
                                        ret = nfi.PercentSymbol + value;
                                        break;
                        }
                }
                return ret;
        }

        public PercentFormatter(int precision)
        {
                this.precision = precision;
        }

        public override string Format(Object o, IFormatProvider provider)
        {
                //
                //  Create working string
                //
                int precision = (this.precision == -1) ?
                        NumberFormatInfo(provider).NumberDecimalDigits : 
this.precision;
                string rawnumber = FormatAnyRound(o, precision + 2);

                //
                // "Multiply" by 100
                //
                rawnumber = rawnumber.PadRight(rawnumber.IndexOf('.')+3,'0');
                rawnumber = rawnumber.Substring(0,rawnumber.IndexOf('.')) +
                        rawnumber.Substring(rawnumber.IndexOf('.')+1, 2) + "." +
                        rawnumber.Substring(rawnumber.IndexOf('.')+3);

                //
                //  Test for negative numbers
                //
                bool isNegative = false;
                if (rawnumber[0] == '-')
                {
                        isNegative = true;
                        rawnumber = rawnumber.Substring(1);
                }

                // 
                //  Build out the integral portion of the number
                //
                StringBuilder ret = new StringBuilder(
                                
GroupInteger(rawnumber.Substring(0,rawnumber.IndexOf('.')),
                                        
NumberFormatInfo(provider).PercentGroupSizes,
                                        
NumberFormatInfo(provider).PercentGroupSeparator));

                //
                //  Add the post-decimal portion.
                //
                if (precision > 0)
                {
                        
ret.Append(NumberFormatInfo(provider).PercentDecimalSeparator);
                        ret.Append(
                                rawnumber.Substring(rawnumber.IndexOf('.')+1, 
precision));
                }

                //
                //  Final formatting
                //
                return FormatPrefixAndSuffix(ret.ToString(), isNegative, 
provider);
        }               
} // class PercentFormatter

} // namespace System.Private.NumberFormat


--- NEW FILE ---
/*
 * RoundTripFormatter.cs - Implementation of the
 *          "System.Private.NumberFormat.RoundTripFormatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Globalization;
using System.Text;

internal class RoundTripFormatter : Formatter
{
        public RoundTripFormatter(int precision)
        {
                this.precision = 0;
        }

        public override string Format(Object o, IFormatProvider provider)
        {
                //  Calculate precision
                int precision;
                if (o is Single)
                {
                        precision = 9;
                }
                else if (o is Double)
                {
                        precision = 17;
                }
                else
                {
                        throw new FormatException(_("Format_TypeException"));
                }

                //  Get initial number
                string rawnumber = FormatAnyRound(o, precision);
                StringBuilder ret = new StringBuilder();

                if (rawnumber[0] == '-')
                {
                        ret.Append(NumberFormatInfo(provider).NegativeSign);
                        rawnumber = rawnumber.Substring(1);
                }

                if (rawnumber[0] == '.')
                {
                        ret.Append('0');
                }
                else
                {
                        
ret.Append(rawnumber.Substring(0,rawnumber.IndexOf('.')));
                }

                ret.Append(NumberFormatInfo(provider).NumberDecimalSeparator);
                
                ret.Append(rawnumber.Substring(rawnumber.IndexOf('.')+1, 
precision));

                return ret.ToString();
        }               
} // class RoundTripFormatter

} // namespace System.Private.NumberFormat


--- NEW FILE ---
/*
 * ScientificFormatter.cs - Implementation of the
 *          "System.Private.NumberFormat.ScientificFormatter" class.
 *
 * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Private.NumberFormat
{

using System;
using System.Globalization;
using System.Text;

//
//  Scientific Formatter - "Exx" or "exx"
internal class ScientificFormatter : Formatter
{
        private char Ee;

        public ScientificFormatter(int precision, char Ee)
        {
                this.precision = precision == -1 ? 6 : 0;
                this.Ee = Ee;
        }

        public override string Format(Object o, IFormatProvider provider)
        {
                bool isNegative = false;

                double value;

                double mantissa;
                int exponent;

                string rawnumber;
                StringBuilder ret;

                value = OToDouble(o);
                if (value < 0)
                {
                        isNegative = true;
                        value = -value;
                }

                //  Calculate exponent and mantissa
                exponent = (int) Math.Floor(Math.Log10(value));
                mantissa = value / Math.Pow(10, exponent);

                rawnumber = FormatFloat(mantissa, precision);

                ret = new StringBuilder(
                                rawnumber.Substring(0,rawnumber.IndexOf('.')) +
                                
NumberFormatInfo(provider).NumberDecimalSeparator +
                                rawnumber.Substring(rawnumber.IndexOf('.')+1));

                if (isNegative)
                {
                        ret.Insert(0, NumberFormatInfo(provider).NegativeSign);
                }

                ret.Append(this.Ee);
                if (exponent < 0)
                {
                        ret.Append(NumberFormatInfo(provider).NegativeSign);
                }
                else
                {
                        ret.Append(NumberFormatInfo(provider).PositiveSign);
                }
                rawnumber = FormatInteger((ulong)Math.Abs(exponent));
                ret.Append(rawnumber.Substring(0, rawnumber.IndexOf('.'))
                                                                                
                        .PadLeft(3,'0'));

                return ret.ToString();
        }               
} // class ScientificFormatter

} // namespace System.Private.NumberFormat






reply via email to

[Prev in Thread] Current Thread [Next in Thread]