DecimalFormatter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / XmlUtils / System / Xml / Xsl / Runtime / DecimalFormatter.cs / 1305376 / DecimalFormatter.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
using System.Diagnostics; 
using System.Globalization;
using System.Text; 

namespace System.Xml.Xsl.Runtime {
    using Res = System.Xml.Utils.Res;
 
    internal class DecimalFormat {
        public NumberFormatInfo info; 
        public char digit; 
        public char zeroDigit;
        public char patternSeparator; 

        internal DecimalFormat(NumberFormatInfo info, char digit, char zeroDigit, char patternSeparator) {
            this.info = info;
            this.digit = digit; 
            this.zeroDigit = zeroDigit;
            this.patternSeparator = patternSeparator; 
        } 
    }
 
    internal class DecimalFormatter {
        private NumberFormatInfo  posFormatInfo;
        private NumberFormatInfo  negFormatInfo;
        private string            posFormat; 
        private string            negFormat;
        private char              zeroDigit; 
 
        // These characters have special meaning for CLR and must be escaped
        // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcustomnumericformatstrings.asp 
        private const string ClrSpecialChars = "0#.,%\u2030Ee\\'\";";

        // This character is used to escape literal (passive) digits '0'..'9'
        private const char EscChar = '\a'; 

        public DecimalFormatter(string formatPicture, DecimalFormat decimalFormat) { 
            Debug.Assert(formatPicture != null && decimalFormat != null); 
            if (formatPicture.Length == 0) {
                throw XsltException.Create(Res.Xslt_InvalidFormat); 
            }

            zeroDigit = decimalFormat.zeroDigit;
            posFormatInfo = (NumberFormatInfo)decimalFormat.info.Clone(); 
            StringBuilder temp = new StringBuilder();
 
            bool integer = true; 
            bool sawPattern = false, sawZeroDigit = false, sawDigit = false, sawDecimalSeparator = false;
            bool digitOrZeroDigit = false; 
            char decimalSeparator = posFormatInfo.NumberDecimalSeparator[0];
            char groupSeparator   = posFormatInfo.NumberGroupSeparator[0];
            char percentSymbol    = posFormatInfo.PercentSymbol[0];
            char perMilleSymbol   = posFormatInfo.PerMilleSymbol[0]; 

            int commaIndex = 0; 
            int groupingSize = 0; 
            int decimalIndex = -1;
            int lastDigitIndex = -1; 

            for (int i = 0; i < formatPicture.Length; i++) {
                char ch = formatPicture[i];
 
                if (ch == decimalFormat.digit) {
                    if (sawZeroDigit && integer) { 
                        throw XsltException.Create(Res.Xslt_InvalidFormat1, formatPicture); 
                    }
                    lastDigitIndex = temp.Length; 
                    sawDigit = digitOrZeroDigit = true;
                    temp.Append('#');
                    continue;
                } 
                if (ch == decimalFormat.zeroDigit) {
                    if (sawDigit && !integer) { 
                        throw XsltException.Create(Res.Xslt_InvalidFormat2, formatPicture); 
                    }
                    lastDigitIndex = temp.Length; 
                    sawZeroDigit = digitOrZeroDigit = true;
                    temp.Append('0');
                    continue;
                } 
                if (ch == decimalFormat.patternSeparator) {
                    if (!digitOrZeroDigit) { 
                        throw XsltException.Create(Res.Xslt_InvalidFormat8); 
                    }
                    if (sawPattern) { 
                        throw XsltException.Create(Res.Xslt_InvalidFormat3, formatPicture);
                    }
                    sawPattern = true;
 
                    if (decimalIndex < 0) {
                        decimalIndex = lastDigitIndex + 1; 
                    } 
                    groupingSize = RemoveTrailingComma(temp, commaIndex, decimalIndex);
 
                    if (groupingSize > 9) {
                        groupingSize = 0;
                    }
                    posFormatInfo.NumberGroupSizes = new int[] { groupingSize }; 
                    if (!sawDecimalSeparator) {
                        posFormatInfo.NumberDecimalDigits = 0; 
                    } 

                    posFormat = temp.ToString(); 

                    temp.Length = 0;
                    decimalIndex = -1;
                    lastDigitIndex = -1; 
                    commaIndex = 0;
                    sawDigit = sawZeroDigit = digitOrZeroDigit = false; 
                    sawDecimalSeparator = false; 
                    integer = true;
                    negFormatInfo = (NumberFormatInfo)decimalFormat.info.Clone(); 
                    negFormatInfo.NegativeSign = string.Empty;
                    continue;
                }
                if (ch == decimalSeparator) { 
                    if (sawDecimalSeparator) {
                        throw XsltException.Create(Res.Xslt_InvalidFormat5, formatPicture); 
                    } 
                    decimalIndex = temp.Length;
                    sawDecimalSeparator = true; 
                    sawDigit = sawZeroDigit = integer = false;
                    temp.Append('.');
                    continue;
                } 
                if (ch == groupSeparator) {
                    commaIndex = temp.Length; 
                    lastDigitIndex = commaIndex; 
                    temp.Append(',');
                    continue; 
                }
                if (ch == percentSymbol) {
                    temp.Append('%');
                    continue; 
                }
                if (ch == perMilleSymbol) { 
                    temp.Append('\u2030'); 
                    continue;
                } 
                if (ch == '\'') {
                    int pos = formatPicture.IndexOf('\'', i + 1);
                    if (pos < 0) {
                        pos = formatPicture.Length - 1; 
                    }
                    temp.Append(formatPicture, i, pos - i + 1); 
                    i = pos; 
                    continue;
                } 
                // Escape literal digits with EscChar, double literal EscChar
                if ('0' <= ch && ch <= '9' || ch == EscChar) {
                    if (decimalFormat.zeroDigit != '0') {
                        temp.Append(EscChar); 
                    }
                } 
                // Escape characters having special meaning for CLR 
                if (ClrSpecialChars.IndexOf(ch) >= 0) {
                    temp.Append('\\'); 
                }
                temp.Append(ch);
            }
 
            if (!digitOrZeroDigit) {
                throw XsltException.Create(Res.Xslt_InvalidFormat8); 
            } 
            NumberFormatInfo formatInfo = sawPattern ? negFormatInfo : posFormatInfo;
 
            if (decimalIndex < 0) {
                decimalIndex = lastDigitIndex + 1;
            }
            groupingSize = RemoveTrailingComma(temp, commaIndex, decimalIndex); 
            if (groupingSize > 9) {
                groupingSize = 0; 
            } 
            formatInfo.NumberGroupSizes = new int[] { groupingSize };
            if (!sawDecimalSeparator) { 
                formatInfo.NumberDecimalDigits = 0;
            }

            if (sawPattern) { 
                negFormat = temp.ToString();
            } else { 
                posFormat = temp.ToString(); 
            }
        } 

        private static int RemoveTrailingComma(StringBuilder builder, int commaIndex, int decimalIndex) {
            if (commaIndex > 0 && commaIndex == (decimalIndex - 1)) {
                builder.Remove(decimalIndex - 1, 1); 
            } else if (decimalIndex > commaIndex) {
                return decimalIndex - commaIndex - 1; 
            } 
            return 0;
        } 

        public string Format(double value) {
            NumberFormatInfo formatInfo;
            string subPicture; 

            if (value < 0 && negFormatInfo != null) { 
                formatInfo = this.negFormatInfo; 
                subPicture = this.negFormat;
            } else { 
                formatInfo = this.posFormatInfo;
                subPicture = this.posFormat;
            }
 
            string result = value.ToString(subPicture, formatInfo);
 
            if (this.zeroDigit != '0') { 
                StringBuilder builder = new StringBuilder(result.Length);
                int shift = this.zeroDigit - '0'; 
                for (int i = 0; i < result.Length; i++) {
                    char ch = result[i];
                    if ((uint)(ch - '0') <= 9) {
                        ch += (char)shift; 
                    } else if (ch == EscChar) {
                        // This is an escaped literal digit or EscChar, thus unescape it. We make use 
                        // of the fact that no extra EscChar could be inserted by value.ToString(). 
                        Debug.Assert(i+1 < result.Length);
                        ch = result[++i]; 
                        Debug.Assert('0' <= ch && ch <= '9' || ch == EscChar);
                    }
                    builder.Append(ch);
                } 
                result = builder.ToString();
            } 
            return result; 
        }
 
        public static string Format(double value, string formatPicture, DecimalFormat decimalFormat) {
            return new DecimalFormatter(formatPicture, decimalFormat).Format(value);
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
using System.Diagnostics; 
using System.Globalization;
using System.Text; 

namespace System.Xml.Xsl.Runtime {
    using Res = System.Xml.Utils.Res;
 
    internal class DecimalFormat {
        public NumberFormatInfo info; 
        public char digit; 
        public char zeroDigit;
        public char patternSeparator; 

        internal DecimalFormat(NumberFormatInfo info, char digit, char zeroDigit, char patternSeparator) {
            this.info = info;
            this.digit = digit; 
            this.zeroDigit = zeroDigit;
            this.patternSeparator = patternSeparator; 
        } 
    }
 
    internal class DecimalFormatter {
        private NumberFormatInfo  posFormatInfo;
        private NumberFormatInfo  negFormatInfo;
        private string            posFormat; 
        private string            negFormat;
        private char              zeroDigit; 
 
        // These characters have special meaning for CLR and must be escaped
        // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcustomnumericformatstrings.asp 
        private const string ClrSpecialChars = "0#.,%\u2030Ee\\'\";";

        // This character is used to escape literal (passive) digits '0'..'9'
        private const char EscChar = '\a'; 

        public DecimalFormatter(string formatPicture, DecimalFormat decimalFormat) { 
            Debug.Assert(formatPicture != null && decimalFormat != null); 
            if (formatPicture.Length == 0) {
                throw XsltException.Create(Res.Xslt_InvalidFormat); 
            }

            zeroDigit = decimalFormat.zeroDigit;
            posFormatInfo = (NumberFormatInfo)decimalFormat.info.Clone(); 
            StringBuilder temp = new StringBuilder();
 
            bool integer = true; 
            bool sawPattern = false, sawZeroDigit = false, sawDigit = false, sawDecimalSeparator = false;
            bool digitOrZeroDigit = false; 
            char decimalSeparator = posFormatInfo.NumberDecimalSeparator[0];
            char groupSeparator   = posFormatInfo.NumberGroupSeparator[0];
            char percentSymbol    = posFormatInfo.PercentSymbol[0];
            char perMilleSymbol   = posFormatInfo.PerMilleSymbol[0]; 

            int commaIndex = 0; 
            int groupingSize = 0; 
            int decimalIndex = -1;
            int lastDigitIndex = -1; 

            for (int i = 0; i < formatPicture.Length; i++) {
                char ch = formatPicture[i];
 
                if (ch == decimalFormat.digit) {
                    if (sawZeroDigit && integer) { 
                        throw XsltException.Create(Res.Xslt_InvalidFormat1, formatPicture); 
                    }
                    lastDigitIndex = temp.Length; 
                    sawDigit = digitOrZeroDigit = true;
                    temp.Append('#');
                    continue;
                } 
                if (ch == decimalFormat.zeroDigit) {
                    if (sawDigit && !integer) { 
                        throw XsltException.Create(Res.Xslt_InvalidFormat2, formatPicture); 
                    }
                    lastDigitIndex = temp.Length; 
                    sawZeroDigit = digitOrZeroDigit = true;
                    temp.Append('0');
                    continue;
                } 
                if (ch == decimalFormat.patternSeparator) {
                    if (!digitOrZeroDigit) { 
                        throw XsltException.Create(Res.Xslt_InvalidFormat8); 
                    }
                    if (sawPattern) { 
                        throw XsltException.Create(Res.Xslt_InvalidFormat3, formatPicture);
                    }
                    sawPattern = true;
 
                    if (decimalIndex < 0) {
                        decimalIndex = lastDigitIndex + 1; 
                    } 
                    groupingSize = RemoveTrailingComma(temp, commaIndex, decimalIndex);
 
                    if (groupingSize > 9) {
                        groupingSize = 0;
                    }
                    posFormatInfo.NumberGroupSizes = new int[] { groupingSize }; 
                    if (!sawDecimalSeparator) {
                        posFormatInfo.NumberDecimalDigits = 0; 
                    } 

                    posFormat = temp.ToString(); 

                    temp.Length = 0;
                    decimalIndex = -1;
                    lastDigitIndex = -1; 
                    commaIndex = 0;
                    sawDigit = sawZeroDigit = digitOrZeroDigit = false; 
                    sawDecimalSeparator = false; 
                    integer = true;
                    negFormatInfo = (NumberFormatInfo)decimalFormat.info.Clone(); 
                    negFormatInfo.NegativeSign = string.Empty;
                    continue;
                }
                if (ch == decimalSeparator) { 
                    if (sawDecimalSeparator) {
                        throw XsltException.Create(Res.Xslt_InvalidFormat5, formatPicture); 
                    } 
                    decimalIndex = temp.Length;
                    sawDecimalSeparator = true; 
                    sawDigit = sawZeroDigit = integer = false;
                    temp.Append('.');
                    continue;
                } 
                if (ch == groupSeparator) {
                    commaIndex = temp.Length; 
                    lastDigitIndex = commaIndex; 
                    temp.Append(',');
                    continue; 
                }
                if (ch == percentSymbol) {
                    temp.Append('%');
                    continue; 
                }
                if (ch == perMilleSymbol) { 
                    temp.Append('\u2030'); 
                    continue;
                } 
                if (ch == '\'') {
                    int pos = formatPicture.IndexOf('\'', i + 1);
                    if (pos < 0) {
                        pos = formatPicture.Length - 1; 
                    }
                    temp.Append(formatPicture, i, pos - i + 1); 
                    i = pos; 
                    continue;
                } 
                // Escape literal digits with EscChar, double literal EscChar
                if ('0' <= ch && ch <= '9' || ch == EscChar) {
                    if (decimalFormat.zeroDigit != '0') {
                        temp.Append(EscChar); 
                    }
                } 
                // Escape characters having special meaning for CLR 
                if (ClrSpecialChars.IndexOf(ch) >= 0) {
                    temp.Append('\\'); 
                }
                temp.Append(ch);
            }
 
            if (!digitOrZeroDigit) {
                throw XsltException.Create(Res.Xslt_InvalidFormat8); 
            } 
            NumberFormatInfo formatInfo = sawPattern ? negFormatInfo : posFormatInfo;
 
            if (decimalIndex < 0) {
                decimalIndex = lastDigitIndex + 1;
            }
            groupingSize = RemoveTrailingComma(temp, commaIndex, decimalIndex); 
            if (groupingSize > 9) {
                groupingSize = 0; 
            } 
            formatInfo.NumberGroupSizes = new int[] { groupingSize };
            if (!sawDecimalSeparator) { 
                formatInfo.NumberDecimalDigits = 0;
            }

            if (sawPattern) { 
                negFormat = temp.ToString();
            } else { 
                posFormat = temp.ToString(); 
            }
        } 

        private static int RemoveTrailingComma(StringBuilder builder, int commaIndex, int decimalIndex) {
            if (commaIndex > 0 && commaIndex == (decimalIndex - 1)) {
                builder.Remove(decimalIndex - 1, 1); 
            } else if (decimalIndex > commaIndex) {
                return decimalIndex - commaIndex - 1; 
            } 
            return 0;
        } 

        public string Format(double value) {
            NumberFormatInfo formatInfo;
            string subPicture; 

            if (value < 0 && negFormatInfo != null) { 
                formatInfo = this.negFormatInfo; 
                subPicture = this.negFormat;
            } else { 
                formatInfo = this.posFormatInfo;
                subPicture = this.posFormat;
            }
 
            string result = value.ToString(subPicture, formatInfo);
 
            if (this.zeroDigit != '0') { 
                StringBuilder builder = new StringBuilder(result.Length);
                int shift = this.zeroDigit - '0'; 
                for (int i = 0; i < result.Length; i++) {
                    char ch = result[i];
                    if ((uint)(ch - '0') <= 9) {
                        ch += (char)shift; 
                    } else if (ch == EscChar) {
                        // This is an escaped literal digit or EscChar, thus unescape it. We make use 
                        // of the fact that no extra EscChar could be inserted by value.ToString(). 
                        Debug.Assert(i+1 < result.Length);
                        ch = result[++i]; 
                        Debug.Assert('0' <= ch && ch <= '9' || ch == EscChar);
                    }
                    builder.Append(ch);
                } 
                result = builder.ToString();
            } 
            return result; 
        }
 
        public static string Format(double value, string formatPicture, DecimalFormat decimalFormat) {
            return new DecimalFormatter(formatPicture, decimalFormat).Format(value);
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK