[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [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,
Jonathan Springer <address@hidden> <=