[Mono-list] Little patch for IntegerFormatter.cs

Gonzalo Paniagua Javier gonzalo@gnome-db.org
Wed, 27 Feb 2002 10:16:40 +0100


--r5Pyd7+fXNt84Ff3
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline

	Hi!

	This is a patch that makes the 2 current tests for custom format
	strings with integer to be ok.

	The new method FormatCustom() still needs a lot of work. I will
	do it.

	Also i discovered a problem with the initialization of
	digitLowerTable and digitUpperTable that causes a
	ValueTypeInitialization to be thrown. The patch includes a
	work-around for this issue.

	The patch is against the 0.9 release.

	Cheers!

--r5Pyd7+fXNt84Ff3
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: attachment; filename="parche-mono.diff"

diff -uwr mcs-0.9/class/corlib/System/IntegerFormatter.cs mymcs-0.9/class/corlib/System/IntegerFormatter.cs
--- mcs-0.9/class/corlib/System/IntegerFormatter.cs	Tue Nov 27 10:44:53 2001
+++ mymcs-0.9/class/corlib/System/IntegerFormatter.cs	Tue Feb 26 22:47:28 2002
@@ -88,20 +88,56 @@
 
 namespace System {
 
-	internal sealed class IntegerFormatter {
+	public sealed class IntegerFormatter {
 
 		private static int maxByteLength = 4;
 		private static int maxShortLength = 6;
 		private static int maxIntLength = 12;
 		private static int maxLongLength = 22;
 
-		private static char[] digitLowerTable = 
-       		{ '0', '1', '2', '3', '4', '5', '6', '7', 
-		  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-
-		private static char[] digitUpperTable = 
-		{ '0', '1', '2', '3', '4', '5', '6', '7', 
-		  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+		private static char[] digitLowerTable;
+/**
+ * This makes a TypeNotInitialized exception be thrown.
+ *		{ '0', '1', '2', '3', '4', '5', '6', '7', 
+ *		  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ */
+
+		private static char[] digitUpperTable;
+/*
+ *		{ '0', '1', '2', '3', '4', '5', '6', '7', 
+ *		  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ */
+
+		static IntegerFormatter ()
+		{
+			int i;
+
+			digitLowerTable = new char[16];
+			digitUpperTable = new char[16];
+
+			for (i = 0; i < 10; i++){
+				digitLowerTable[i] = (char) ('0' + i);
+				digitUpperTable[i] = (char) ('0' + i);
+			}
+
+			char lc = 'a';
+			char uc = 'A';
+			while (i < 16){
+				digitLowerTable[i] = (char) (lc + i);
+				digitUpperTable[i] = (char) (uc + i);
+				i++;
+			}
+		}
+
+		private static bool IsDigit (char c)
+		{
+			return !(c < '0' || c > '9'); 
+		}
+		
+		private static bool IsLetter (char c)
+		{
+			return (c > 'a' && c < 'z') || (c > 'A' && c < 'Z'); 
+		}
 
 		private static bool ParseFormat (string format, out char specifier,  out int precision)
 		{		 		 
@@ -109,27 +145,37 @@
 			specifier = '\0';
 			
 			int length = format.Length;
-			if (length < 1 || length > 3)
+			// TODO: Could an empty string be a custom format string?
+			if (length < 1)
 				return false;
 			
 			char[] chars = format.ToCharArray ();
 			specifier = chars[0];
 
-			if (length == 1) 
+			// TODO: IsLetter() and IsDigit() should be replaced by Char.Is*()
+			if (IsLetter(specifier) && length <= 3) {
+				// Standard numeric format
+				switch (length){
+					case 1:
 				return true;
-			
-			if (length == 2) {
-				if (chars[1] < '0' || chars[1] > '9')
+					case 2:
+						if (!IsDigit(chars[1]))
 					return false;
 				
 				precision = chars[1] - '0';
-			} else {
-				if (chars[1] < '0' || chars[2] < '0' || chars[1] > '9' || chars[2] > '9')
+						return true;
+					case 3:
+						if (!IsDigit(chars[1]) || !IsDigit(chars[2]))
 					return false;
 				
-				precision = (chars[1] - '0') * 10 + (chars[2] - '0');
+						precision = chars[1] - '0';
+						precision = precision * 10 + chars[2] - '0';
+						return true;
+				}
 			}
 			
+			// We've got a custom format string.
+			specifier = 'z';
 			return true;
 		}	 
 
@@ -205,7 +251,7 @@
 			int precision;
 			
 			if (!ParseFormat (format, out specifier, out precision))
-				throw new FormatException (Locale.GetText ("The specified format is invalid"));
+				throw new FormatException (Locale.GetText ("The specified format is invalid: '" + format + "'"));
 			
 			switch(specifier) {
 			case 'c': return FormatCurrency (value, precision, nfi);	
@@ -226,6 +272,7 @@
 			case 'R': throw new FormatException (Locale.GetText ("The specified format cannot be used in this instance"));
 			case 'x': return FormatHexadecimal (value, precision, false);
 			case 'X': return FormatHexadecimal (value, precision, true);
+			case 'z': return FormatCustom (format, value, nfi);
 			default: 
 				throw new FormatException (Locale.GetText ("The specified format is invalid"));
 			}
@@ -263,6 +310,7 @@
 			}			
 		}
 
+		[CLSCompliant(false)]
 		public static string NumberToString (string format, NumberFormatInfo nfi, sbyte value)
 		{
 			char specifier;
@@ -295,6 +343,7 @@
 			}
 		}
 
+		[CLSCompliant(false)]
 		public static string NumberToString (string format, NumberFormatInfo nfi, ushort value)
 		{
 			char specifier;
@@ -327,6 +376,7 @@
 			}
 		}
 
+		[CLSCompliant(false)]
 		public static string NumberToString (string format, NumberFormatInfo nfi, uint value)
 		{
 			char specifier;
@@ -359,6 +409,7 @@
 			}
 		}
 
+		[CLSCompliant(false)]
 		public static string NumberToString (string format, NumberFormatInfo nfi, ulong value)
 		{
 			char specifier;
@@ -390,7 +441,6 @@
 				throw new FormatException (Locale.GetText ("The specified format is invalid"));
 			}
 		}
-
 		// ============ Currency Type Formating ============ //
 
 		//
@@ -3428,5 +3478,42 @@
 			return new string(buffy, position, (size - position));
 		}
 
+		private static string FormatCustom (string format, int value, NumberFormatInfo nfi)
+		{
+			string strnum = FormatGeneral (value, -1, nfi, true);
+			char[] chrnum = strnum.ToCharArray();
+			int lennum = chrnum.Length - 1;
+
+			char[] chrfmt = format.ToCharArray();
+			int lenfmt = chrfmt.Length;
+
+			int size = format.Length + maxIntLength; // Longer than needed
+			char[] buffy = new char[size];
+
+			int position = 0;
+
+			// Create the output string from right to left
+			for (int i = lenfmt-1; i >= 0; i--) {
+				if (chrfmt[i] == '0'){
+					if (i >= lennum && lennum >= 0)
+						buffy[position++] = chrnum[lennum--];
+					else
+						buffy[position++] = '0';
+				}
+
+				if (chrfmt[i] == '#'){
+					if (i >= lennum && lennum >= 0)
+						buffy[position++] = chrnum[lennum--];
+				}
+			}
+
+			// Don't know a better way to reverse characters
+			char [] buffo = new char[position];
+			for (int i = 0; i < position; i++)
+				buffo[position - i - 1] = buffy[i];
+
+			return new string (buffo, 0, position);
+		}
+
 	}
 }

--r5Pyd7+fXNt84Ff3--