Browse Source

2004-10-08 Atsushi Enomoto <[email protected]>

	* DateTime.cs : Performance fix. ParseExact() implementation should
	  avoid s = s.Substring(1).

svn path=/trunk/mcs/; revision=34782
Atsushi Eno 21 years ago
parent
commit
5877fcb71d
2 changed files with 86 additions and 79 deletions
  1. 5 0
      mcs/class/corlib/System/ChangeLog
  2. 81 79
      mcs/class/corlib/System/DateTime.cs

+ 5 - 0
mcs/class/corlib/System/ChangeLog

@@ -1,3 +1,8 @@
+2004-10-08  Atsushi Enomoto  <[email protected]>
+
+	* DateTime.cs : Performance fix. ParseExact() implementation should
+	  avoid s = s.Substring(1).
+
 2004-10-08  Atsushi Enomoto  <[email protected]>
 
 	* DateTime.cs : When it it not exact parse, 'Z' is allowed as a suffix

+ 81 - 79
mcs/class/corlib/System/DateTime.cs

@@ -726,7 +726,8 @@ namespace System
 			return ParseExact (s, format, fp, DateTimeStyles.None);
 		}
 
-		internal static int _ParseNumber (string s, int digits,
+		internal static int _ParseNumber (string s, int valuePos,
+						  int digits,
 						  bool leadingzero,
 						  bool sloppy_parsing,
 						  bool next_not_digit,
@@ -739,7 +740,7 @@ namespace System
 
 			if (!leadingzero) {
 				int real_digits = 0;
-				for (i = 0; i < s.Length && i < digits; i++) {
+				for (i = valuePos; i < s.Length && i < digits + valuePos; i++) {
 					if (!Char.IsDigit (s[i]))
 						break;
 
@@ -749,20 +750,20 @@ namespace System
 				digits = real_digits;
 			}
 
-			if (s.Length < digits) {
+			if (s.Length - valuePos < digits) {
 				num_parsed = -1;
 				return 0;
 			}
 
-			if (s.Length > digits &&
+			if (s.Length - valuePos > digits &&
 			    next_not_digit &&
-			    Char.IsDigit (s[digits])) {
+			    Char.IsDigit (s[digits + valuePos])) {
 				/* More digits left over */
 				num_parsed = -1;
 				return(0);
 			}
 
-			for (i = 0; i < digits; i++) {
+			for (i = valuePos; i < digits + valuePos; i++) {
 				char c = s[i];
 				if (!Char.IsDigit (c)) {
 					num_parsed = -1;
@@ -776,16 +777,16 @@ namespace System
 			return number;
 		}
 
-		internal static int _ParseEnum (string s, string[] values, out int num_parsed)
+		internal static int _ParseEnum (string s, int sPos, string[] values, out int num_parsed)
 		{
 			int i;
 
 			for (i = 0; i < values.Length; i++) {
-				if (s.Length < values[i].Length)
+				if (s.Length - sPos < values[i].Length)
 					continue;
 				else if (values [i].Length == 0)
 					continue;
-				String tmp = s.Substring (0, values[i].Length);
+				String tmp = s.Substring (sPos, values[i].Length);
 				if (String.Compare (tmp, values[i], true) == 0) {
 					num_parsed = values[i].Length;
 					return i;
@@ -796,12 +797,12 @@ namespace System
 			return -1;
 		}
 
-		internal static bool _ParseString (string s, int maxlength, string value, out int num_parsed)
+		internal static bool _ParseString (string s, int sPos, int maxlength, string value, out int num_parsed)
 		{
 			if (maxlength <= 0)
 				maxlength = value.Length;
 
-			if (String.Compare (s, 0, value, 0, maxlength, true, CultureInfo.InvariantCulture) == 0) {
+			if (String.Compare (s, sPos, value, 0, maxlength, true, CultureInfo.InvariantCulture) == 0) {
 				num_parsed = maxlength;
 				return true;
 			}
@@ -810,7 +811,7 @@ namespace System
 			return false;
 		}
 
-		internal static bool _DoParse (string s, string format, bool exact,
+		private static bool _DoParse (string s, string format, bool exact,
 					       out DateTime result,
 					       DateTimeFormatInfo dfi,
 					       DateTimeStyles style,
@@ -819,6 +820,7 @@ namespace System
 			bool useutc = false, use_localtime = true;
 			bool use_invariant = false;
 			bool sloppy_parsing = false;
+			int valuePos = 0;
 			if (format.Length == 1)
 				format = _GetStandardPattern (format [0], dfi, out useutc, out use_invariant);
 			else if (!exact && format.IndexOf ("GMT") >= 0)
@@ -827,12 +829,12 @@ namespace System
 			if ((style & DateTimeStyles.AllowLeadingWhite) != 0) {
 				format = format.TrimStart (null);
 
-				s = s.TrimStart (null);
+				s = s.TrimStart (null); // it could be optimized, but will make little good.
 			}
 
 			if ((style & DateTimeStyles.AllowTrailingWhite) != 0) {
 				format = format.TrimEnd (null);
-				s = s.TrimEnd (null);
+				s = s.TrimEnd (null); // it could be optimized, but will make little good.
 			}
 
 			if (use_invariant)
@@ -841,7 +843,7 @@ namespace System
 			if ((style & DateTimeStyles.AllowInnerWhite) != 0)
 				sloppy_parsing = true;
 
-			char[] chars = format.ToCharArray ();
+			string chars = format;
 			int len = format.Length, pos = 0, num = 0;
 
 			int day = -1, dayofweek = -1, month = -1, year = -1;
@@ -854,7 +856,7 @@ namespace System
 			result = new DateTime (0);
 			while (pos+num < len)
 			{
-				if (s.Length == 0)
+				if (s.Length == valuePos)
 					break;
 
 				if (chars[pos] == '\'') {
@@ -863,11 +865,11 @@ namespace System
 						if (chars[pos+num] == '\'')
 							break;
 
-						if (s.Length == 0)
+						if (valuePos == s.Length)
 							return false;
-						if (s[0] != chars[pos+num])
+						if (s [valuePos] != chars [pos + num])
 							return false;
-						s = s.Substring (1);
+						valuePos++;
 
 						num++;
 					}
@@ -883,11 +885,11 @@ namespace System
 						if (chars[pos+num] == '"')
 							break;
 
-						if (s.Length == 0)
+						if (valuePos == s.Length)
 							return false;
-						if (s[0] != chars[pos+num])
+						if (s [valuePos] != chars[pos+num])
 							return false;
-						s = s.Substring (1);
+						valuePos++;
 
 						num++;
 					}
@@ -901,10 +903,10 @@ namespace System
 					if (pos+1 >= len)
 						return false;
 
-					if (s[0] != chars[pos+num])
+					if (s [valuePos] != chars [pos + num])
 						return false;
-					s = s.Substring (1);
-					if (s.Length == 0)
+					valuePos++;
+					if (valuePos == s.Length)
 						return false;
 
 					pos++;
@@ -912,8 +914,8 @@ namespace System
 				} else if (chars[pos] == '%') {
 					pos++;
 					continue;
-				} else if (Char.IsWhiteSpace (s[0])) {
-					s = s.Substring (1);
+				} else if (Char.IsWhiteSpace (s [valuePos])) {
+					valuePos++;
 
 					if (Char.IsWhiteSpace (chars[pos])) {
 						pos++;
@@ -922,14 +924,14 @@ namespace System
 
 					if (exact && (style & DateTimeStyles.AllowInnerWhite) == 0)
 						return false;
-					int ws = 0;
+					int ws = valuePos;
 					while (ws < s.Length) {
 						if (Char.IsWhiteSpace (s [ws]))
 							ws++;
 						else
 							break;
 					}
-					s = s.Substring (ws);
+					valuePos = ws;
 				}
 
 
@@ -965,14 +967,14 @@ namespace System
 					if (day != -1)
 						return false;
 					if (num == 0)
-						day = _ParseNumber (s, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+						day = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
 					else if (num == 1)
-						day = _ParseNumber (s, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+						day = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
 					else if (num == 2)
-						dayofweek = _ParseEnum (s, dfi.AbbreviatedDayNames, out num_parsed);
+						dayofweek = _ParseEnum (s, valuePos, dfi.AbbreviatedDayNames, out num_parsed);
 					else
 					{
-						dayofweek = _ParseEnum (s, dfi.DayNames, out num_parsed);
+						dayofweek = _ParseEnum (s, valuePos, dfi.DayNames, out num_parsed);
 						num = 3;
 					}
 					break;
@@ -980,14 +982,14 @@ namespace System
 					if (month != -1)
 						return false;
 					if (num == 0)
-						month = _ParseNumber (s, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+						month = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
 					else if (num == 1)
-						month = _ParseNumber (s, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+						month = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
 					else if (num == 2)
-						month = _ParseEnum (s, dfi.AbbreviatedMonthNames , out num_parsed) + 1;
+						month = _ParseEnum (s, valuePos, dfi.AbbreviatedMonthNames , out num_parsed) + 1;
 					else
 					{
-						month = _ParseEnum (s, dfi.MonthNames, out num_parsed) + 1;
+						month = _ParseEnum (s, valuePos, dfi.MonthNames, out num_parsed) + 1;
 						num = 3;
 					}
 					break;
@@ -996,14 +998,14 @@ namespace System
 						return false;
 
 					if (num == 0) {
-						year = _ParseNumber (s, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+						year = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
 					} else if (num < 3) {
-						year = _ParseNumber (s, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+						year = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
 					} else {
-						year = _ParseNumber (s, 4, false, sloppy_parsing, next_not_digit, out num_parsed);
-						if ((year >= 1000) && (num_parsed == 4) && (!longYear) && (s.Length > 4)) {
+						year = _ParseNumber (s, valuePos, 4, false, sloppy_parsing, next_not_digit, out num_parsed);
+						if ((year >= 1000) && (num_parsed == 4) && (!longYear) && (s.Length > 4 + valuePos)) {
 							int np = 0;
-							int ly = _ParseNumber (s, 5, false, sloppy_parsing, next_not_digit, out np);
+							int ly = _ParseNumber (s, valuePos, 5, false, sloppy_parsing, next_not_digit, out np);
 							longYear = (ly > 9999);
 						}
 						num = 3;
@@ -1017,10 +1019,10 @@ namespace System
 					if (hour != -1)
 						return false;
 					if (num == 0)
-						hour = _ParseNumber (s, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+						hour = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
 					else
 					{
-						hour = _ParseNumber (s, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+						hour = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
 						num = 1;
 					}
 
@@ -1034,10 +1036,10 @@ namespace System
 					if ((hour != -1) || (ampm >= 0))
 						return false;
 					if (num == 0)
-						hour = _ParseNumber (s, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+						hour = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
 					else
 					{
-						hour = _ParseNumber (s, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+						hour = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
 						num = 1;
 					}
 					if (hour >= 24)
@@ -1049,10 +1051,10 @@ namespace System
 					if (minute != -1)
 						return false;
 					if (num == 0)
-						minute = _ParseNumber (s, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+						minute = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
 					else
 					{
-						minute = _ParseNumber (s, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+						minute = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
 						num = 1;
 					}
 					if (minute >= 60)
@@ -1063,10 +1065,10 @@ namespace System
 					if (second != -1)
 						return false;
 					if (num == 0)
-						second = _ParseNumber (s, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+						second = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
 					else
 					{
-						second = _ParseNumber (s, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+						second = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
 						num = 1;
 					}
 					if (second >= 60)
@@ -1077,7 +1079,7 @@ namespace System
 					if (fractionalSeconds != -1)
 						return false;
 					num = Math.Min (num, 6);
-					double decimalNumber = (double) _ParseNumber (s, num+1, true, sloppy_parsing, next_not_digit, out num_parsed);
+					double decimalNumber = (double) _ParseNumber (s, valuePos, num+1, true, sloppy_parsing, next_not_digit, out num_parsed);
 					if (num_parsed == -1)
 						return false;
 
@@ -1089,18 +1091,18 @@ namespace System
 						return false;
 					if (num == 0)
 					{
-						if (_ParseString (s, 1, dfi.AMDesignator, out num_parsed))
+						if (_ParseString (s, valuePos, 1, dfi.AMDesignator, out num_parsed))
 							ampm = 0;
-						else if (_ParseString (s, 1, dfi.PMDesignator, out num_parsed))
+						else if (_ParseString (s, valuePos, 1, dfi.PMDesignator, out num_parsed))
 							ampm = 1;
 						else
 							return false;
 					}
 					else
 					{
-						if (_ParseString (s, 0, dfi.AMDesignator, out num_parsed))
+						if (_ParseString (s, valuePos, 0, dfi.AMDesignator, out num_parsed))
 							ampm = 0;
-						else if (_ParseString (s, 0, dfi.PMDesignator, out num_parsed))
+						else if (_ParseString (s, valuePos, 0, dfi.PMDesignator, out num_parsed))
 							ampm = 1;
 						else
 							return false;
@@ -1110,29 +1112,29 @@ namespace System
 				case 'z':
 					if (tzsign != -1)
 						return false;
-					if (s[0] == '+')
+					if (s [valuePos] == '+')
 						tzsign = 0;
-					else if (s[0] == '-')
+					else if (s [valuePos] == '-')
 						tzsign = 1;
 					else
 						return false;
-					s = s.Substring (1);
+					valuePos++;
 					if (num == 0)
-						tzoffset = _ParseNumber (s, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+						tzoffset = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
 					else if (num == 1)
-						tzoffset = _ParseNumber (s, 2, true, sloppy_parsing, false, out num_parsed);
+						tzoffset = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, false, out num_parsed);
 					else
 					{
-						tzoffset = _ParseNumber (s, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+						tzoffset = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
 						if (num_parsed < 0)
 							return false;
-						s = s.Substring (num_parsed);
-						if (Char.IsDigit (s [0]))
+						valuePos += num_parsed;
+						if (Char.IsDigit (s [valuePos]))
 							num_parsed = 0;
-						else if (!_ParseString (s, 0, dfi.TimeSeparator, out num_parsed))
+						else if (!_ParseString (s, valuePos, 0, dfi.TimeSeparator, out num_parsed))
 							return false;
-						s = s.Substring (num_parsed);
-						tzoffmin = _ParseNumber (s, 2, true, sloppy_parsing, false, out num_parsed);
+						valuePos += num_parsed;
+						tzoffmin = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, false, out num_parsed);
 						if (num_parsed < 0)
 							return false;
 						num = 2;
@@ -1147,7 +1149,7 @@ namespace System
 				// verification. Also, "Z" != "'Z'" under MS.NET
 				// ("'Z'" is just literal; handled above)
 				case 'Z':
-					if (s [0] != 'Z')
+					if (s [valuePos] != 'Z')
 						return false;
 					num = 0;
 					num_parsed = 1;
@@ -1155,7 +1157,7 @@ namespace System
 					break;
 
 				case ':':
-					if (!_ParseString (s, 0, dfi.TimeSeparator, out num_parsed))
+					if (!_ParseString (s, valuePos, 0, dfi.TimeSeparator, out num_parsed))
 						return false;
 					break;
 				case '/':
@@ -1167,14 +1169,14 @@ namespace System
 					 * behaviour here.  See bug
 					 * 54047.
 					 */
-					if (exact && s [0] != '/')
+					if (exact && s [valuePos] != '/')
 						return false;
 
-					if (_ParseString (s, 0,
+					if (_ParseString (s, valuePos, 0,
 							  dfi.TimeSeparator,
 							  out num_parsed) ||
-					    Char.IsDigit (s[0]) ||
-					    Char.IsLetter (s[0])) {
+					    Char.IsDigit (s [valuePos]) ||
+					    Char.IsLetter (s [valuePos])) {
 						return(false);
 					}
 
@@ -1185,7 +1187,7 @@ namespace System
 					
 					break;
 				default:
-					if (s[0] != chars[pos]) {
+					if (s [valuePos] != chars[pos]) {
 						// FIXME: It is not sure, but
 						// IsLetter() is introduced 
 						// because we have to reject 
@@ -1193,8 +1195,8 @@ namespace System
 						// allow "2002$02$25". The same
 						// thing applies to '/' case.
 						if (exact ||
-							Char.IsDigit (s [0]) ||
-							Char.IsLetter (s [0]))
+							Char.IsDigit (s [valuePos]) ||
+							Char.IsLetter (s [valuePos]))
 							return false;
 					}
 					num = 0;
@@ -1205,7 +1207,7 @@ namespace System
 				if (num_parsed < 0)
 					return false;
 
-				s = s.Substring (num_parsed);
+				valuePos += num_parsed;
 
 				if (!exact) {
 					switch (chars [pos]) {
@@ -1213,11 +1215,11 @@ namespace System
 					case 's':
 					case 'f':
 					case 'z':
-						if (s.Length > 0 && s [0] == 'Z'
+						if (s.Length > valuePos && s [valuePos] == 'Z'
 						    && (pos + 1 == chars.Length
 						    || chars [pos + 1] != 'Z')) {
 							useutc = true;
-							s = s.Substring (1);
+							valuePos++;
 						}
 						break;
 					}
@@ -1230,7 +1232,7 @@ namespace System
 			if (exact && pos < len)
 				return false;
 
-			if (s.Length != 0) // extraneous tail.
+			if (s.Length != valuePos) // extraneous tail.
 				return false;
 
 			if (hour == -1)