Imported Upstream version 3.10.0

Former-commit-id: 172c8e3c300b39d5785c7a3e8dfb08ebdbc1a99b
This commit is contained in:
Jo Shields
2014-10-04 11:27:48 +01:00
parent fe777c5c82
commit 8b9b85e7f5
970 changed files with 20242 additions and 31308 deletions

View File

@ -928,10 +928,10 @@ namespace System
}
// Try as a last resort all the patterns
if (ParseExact (s, dfi.GetAllDateTimePatternsInternal (), dfi, styles, out result, false, ref longYear, setExceptionOnError, ref exception))
if (CoreParseExact (s, dfi.GetAllDateTimePatternsInternal (), dfi, styles, out result, out dto, false, ref longYear, setExceptionOnError, ref exception))
return true;
if (ParseExact (s, ExoticAndNonStandardFormats, dfi, styles, out result, false, ref longYear, setExceptionOnError, ref exception))
if (CoreParseExact (s, ExoticAndNonStandardFormats, dfi, styles, out result, out dto, false, ref longYear, setExceptionOnError, ref exception))
return true;
if (!setExceptionOnError)
@ -1142,7 +1142,8 @@ namespace System
DateTimeStyles style,
bool firstPartIsDate,
ref bool incompleteFormat,
ref bool longYear)
ref bool longYear,
bool dateTimeOffset = false)
{
bool useutc = false;
bool use_invariant = false;
@ -1155,7 +1156,7 @@ namespace System
bool afterTFormat = false;
DateTimeFormatInfo invInfo = DateTimeFormatInfo.InvariantInfo;
if (format.Length == 1)
format = DateTimeUtils.GetStandardPattern (format [0], dfi, out useutc, out use_invariant);
format = DateTimeUtils.GetStandardPattern (format [0], dfi, out useutc, out use_invariant, dateTimeOffset);
result = new DateTime (0);
if (format == null)
@ -1396,13 +1397,8 @@ namespace System
} else if (num < 3) {
year = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
} else {
year = _ParseNumber (s, valuePos, exact ? 4 : 3, 4, false, sloppy_parsing, out num_parsed);
if ((year >= 1000) && (num_parsed == 4) && (!longYear) && (s.Length > 4 + valuePos)) {
int np = 0;
int ly = _ParseNumber (s, valuePos, 5, 5, false, sloppy_parsing, out np);
longYear = (ly > 9999);
}
num = 3;
year = _ParseNumber (s, valuePos, exact ? num + 1 : 3, num + 1, false, sloppy_parsing, out num_parsed);
longYear = (year > 9999);
}
//FIXME: We should do use dfi.Calendat.TwoDigitYearMax
@ -1538,7 +1534,6 @@ namespace System
valuePos += num_parsed;
tzoffmin = _ParseNumber (s, valuePos, 0, 2, true, sloppy_parsing, out num_parsed);
num = 2;
if (num_parsed < 0)
return false;
}
@ -1727,7 +1722,16 @@ namespace System
if (tzsign == -1) {
if (result != DateTime.MinValue) {
try {
dto = new DateTimeOffset (result);
if ((style & DateTimeStyles.AssumeUniversal) != 0) {
dto = new DateTimeOffset (result, TimeSpan.Zero);
} else if ((style & DateTimeStyles.AssumeLocal) != 0) {
var offset = use_invariant ?
TimeSpan.Zero :
TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.Now);
dto = new DateTimeOffset (result, offset);
} else {
dto = new DateTimeOffset (result);
}
} catch { } // We handle this error in DateTimeOffset.Parse
}
} else {
@ -1794,9 +1798,10 @@ namespace System
throw new FormatException ("Format specifier was invalid.");
DateTime result;
DateTimeOffset dto;
bool longYear = false;
Exception e = null;
if (!ParseExact (s, formats, dfi, style, out result, true, ref longYear, true, ref e))
if (!CoreParseExact (s, formats, dfi, style, out result, out dto, true, ref longYear, true, ref e))
throw e;
return result;
}
@ -1860,21 +1865,25 @@ namespace System
{
try {
DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (provider);
DateTimeOffset dto;
bool longYear = false;
Exception e = null;
return ParseExact (s, formats, dfi, style, out result, true, ref longYear, false, ref e);
return CoreParseExact (s, formats, dfi, style, out result, out dto, true, ref longYear, false, ref e);
} catch {
result = MinValue;
return false;
}
}
private static bool ParseExact (string s, string [] formats,
DateTimeFormatInfo dfi, DateTimeStyles style, out DateTime ret,
internal static bool CoreParseExact (string s, string [] formats,
DateTimeFormatInfo dfi, DateTimeStyles style,
out DateTime ret, out DateTimeOffset dto,
bool exact, ref bool longYear,
bool setExceptionOnError, ref Exception exception)
bool setExceptionOnError, ref Exception exception,
bool dateTimeOffset = false)
{
dto = new DateTimeOffset (0, TimeSpan.Zero);
int i;
bool incompleteFormat = false;
for (i = 0; i < formats.Length; i++)
@ -1884,8 +1893,7 @@ namespace System
if (format == null || format == String.Empty)
break;
DateTimeOffset dto;
if (_DoParse (s, formats[i], null, exact, out result, out dto, dfi, style, false, ref incompleteFormat, ref longYear)) {
if (_DoParse (s, formats[i], null, exact, out result, out dto, dfi, style, false, ref incompleteFormat, ref longYear, dateTimeOffset)) {
ret = result;
return true;
}

View File

@ -343,372 +343,21 @@ namespace System
if ((styles & DateTimeStyles.AssumeLocal) != 0 && (styles & DateTimeStyles.AssumeUniversal) != 0)
throw new ArgumentException ("styles parameter contains incompatible flags");
DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (formatProvider);
DateTime d;
DateTimeOffset result;
if (!ParseExact (input, formats, DateTimeFormatInfo.GetInstance (formatProvider), styles, out result))
throw new FormatException ("Invalid format string");
Exception exception = null;
bool longYear = false;
try {
if (!DateTime.CoreParseExact (input, formats, dfi, styles, out d, out result, true, ref longYear, true, ref exception, true))
throw exception;
} catch (ArgumentOutOfRangeException ex) {
throw new FormatException ("The UTC representation falls outside the 1-9999 year range", ex);
}
return result;
}
private static bool ParseExact (string input, string [] formats,
DateTimeFormatInfo dfi, DateTimeStyles styles, out DateTimeOffset ret)
{
foreach (string format in formats)
{
if (format == null || format == String.Empty)
throw new FormatException ("Invalid format string");
DateTimeOffset result;
if (DoParse (input, format, false, out result, dfi, styles)) {
ret = result;
return true;
}
}
ret = DateTimeOffset.MinValue;
return false;
}
private static bool DoParse (string input,
string format,
bool exact,
out DateTimeOffset result,
DateTimeFormatInfo dfi,
DateTimeStyles styles)
{
if ((styles & DateTimeStyles.AllowLeadingWhite) != 0) {
format = format.TrimStart (null);
input = input.TrimStart (null);
}
if ((styles & DateTimeStyles.AllowTrailingWhite) != 0) {
format = format.TrimEnd (null);
input = input.TrimEnd (null);
}
bool allow_white_spaces = false;
if ((styles & DateTimeStyles.AllowInnerWhite) != 0)
allow_white_spaces = true;
result = DateTimeOffset.MinValue;
bool useutc = false, use_invariants = false;
if (format.Length == 1) {
format = DateTimeUtils.GetStandardPattern (format[0], dfi, out useutc, out use_invariants, true);
if (format == null)
return false;
}
int year = -1;
int month = -1;
int day = -1;
int partial_hour = -1; // for 'hh tt' formats
int hour = -1;
int minute = -1;
int second = -1;
double fraction = -1;
int temp_int = -1;
TimeSpan offset = TimeSpan.MinValue;
int fi = 0; //format iterator
int ii = 0; //input iterator
while (fi < format.Length) {
int tokLen;
char ch = format [fi];
switch (ch) {
case 'd':
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
if (day != -1 || tokLen > 4)
return false;
if (tokLen <= 2)
ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out day);
else
ii += ParseEnum (input, ii, tokLen == 3 ? dfi.AbbreviatedDayNames : dfi.DayNames, allow_white_spaces, out temp_int);
break;
case 'f':
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
ii += ParseNumber (input, ii, tokLen, true, allow_white_spaces, out temp_int);
if (fraction >= 0 || tokLen > 7 || temp_int == -1)
return false;
fraction = (double)temp_int / Math.Pow (10, tokLen);
break;
case 'F':
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
int digits;
int read = ParseNumber (input, ii, tokLen, true, allow_white_spaces, out temp_int, out digits);
if (temp_int == -1)
ii += ParseNumber (input, ii, digits, true, allow_white_spaces, out temp_int);
else
ii += read;
if (fraction >= 0 || tokLen > 7 || temp_int == -1)
return false;
fraction = (double)temp_int / Math.Pow (10, digits);
break;
case 'h':
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
if (hour != -1 || tokLen > 2)
return false;
ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out temp_int);
if (temp_int == -1)
return false;
if (partial_hour == -1)
partial_hour = temp_int;
else
hour = partial_hour + temp_int;
break;
case 'H':
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
if (hour != -1 || tokLen > 2)
return false;
ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out hour);
break;
case 'm':
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
if (minute != -1 || tokLen > 2)
return false;
ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out minute);
break;
case 'M':
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
if (month != -1 || tokLen > 4)
return false;
if (tokLen <= 2)
ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out month);
else {
ii += ParseEnum (input, ii, tokLen == 3 ? dfi.AbbreviatedMonthNames : dfi.MonthNames, allow_white_spaces, out month);
month += 1;
}
break;
case 's':
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
if (second != -1 || tokLen > 2)
return false;
ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out second);
break;
case 't':
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
if (hour != -1 || tokLen > 2)
return false;
ii += ParseEnum (input, ii,
tokLen == 1 ? new string[] {new string (dfi.AMDesignator[0], 1), new string (dfi.PMDesignator[0], 0)}
: new string[] {dfi.AMDesignator, dfi.PMDesignator},
allow_white_spaces, out temp_int);
if (temp_int == -1)
return false;
if (partial_hour == -1)
partial_hour = temp_int * 12;
else
hour = partial_hour + temp_int * 12;
break;
case 'y':
if (year != -1)
return false;
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
if (tokLen <= 2) {
ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out year);
if (year != -1)
year = dfi.Calendar.ToFourDigitYear (year);
} else if (tokLen <= 4) { // yyy and yyyy accept up to 5 digits with leading 0
int digit_parsed;
ii += ParseNumber (input, ii, 5, false, allow_white_spaces, out year, out digit_parsed);
if (digit_parsed < tokLen || (digit_parsed > tokLen && (year / Math.Pow (10, digit_parsed - 1) < 1)))
return false;
} else
ii += ParseNumber (input, ii, tokLen, true, allow_white_spaces, out year);
break;
// The documentation is incorrect, they claim that K is the same as 'zz', but
// it actually allows the format to contain 4 digits for the offset
case 'K':
tokLen = 1;
int off_h, off_m = 0, sign;
temp_int = 0;
ii += ParseEnum (input, ii, new string [] {"-", "+"}, allow_white_spaces, out sign);
ii += ParseNumber (input, ii, 4, false, false, out off_h);
if (off_h == -1 || off_m == -1 || sign == -1)
return false;
if (sign == 0)
sign = -1;
offset = new TimeSpan (sign * off_h, sign * off_m, 0);
break;
case 'z':
tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
if (offset != TimeSpan.MinValue || tokLen > 3)
return false;
off_m = 0;
temp_int = 0;
ii += ParseEnum (input, ii, new string [] {"-", "+"}, allow_white_spaces, out sign);
ii += ParseNumber (input, ii, 2, tokLen != 1, false, out off_h);
if (tokLen == 3) {
ii += ParseEnum (input, ii, new string [] {dfi.TimeSeparator}, false, out temp_int);
ii += ParseNumber (input, ii, 2, true, false, out off_m);
}
if (off_h == -1 || off_m == -1 || sign == -1)
return false;
if (sign == 0)
sign = -1;
offset = new TimeSpan (sign * off_h, sign * off_m, 0);
break;
case ':':
tokLen = 1;
ii += ParseEnum (input, ii, new string [] {dfi.TimeSeparator}, false, out temp_int);
if (temp_int == -1)
return false;
break;
case '/':
tokLen = 1;
ii += ParseEnum (input, ii, new string [] {dfi.DateSeparator}, false, out temp_int);
if (temp_int == -1)
return false;
break;
case '%':
tokLen = 1;
if (fi != 0)
return false;
break;
case ' ':
tokLen = 1;
ii += ParseChar (input, ii, ' ', false, out temp_int);
if (temp_int == -1)
return false;
break;
case '\\':
tokLen = 2;
ii += ParseChar (input, ii, format [fi + 1], allow_white_spaces, out temp_int);
if (temp_int == -1)
return false;
break;
case '\'':
case '"':
tokLen = 1;
while (ii < input.Length) {
var ftoken = format [fi + tokLen];
++tokLen;
if (ftoken == format [fi]) {
if (useutc && tokLen == 5 && input [ii - 3] == 'G' && input [ii - 2] == 'M' && input [ii - 1] == 'T') {
offset = TimeSpan.Zero;
}
break;
}
if (ftoken != input [ii++])
return false;
}
break;
default:
//Console.WriteLine ("un-parsed character: {0}", ch);
tokLen = 1;
ii += ParseChar (input, ii, format [fi], allow_white_spaces, out temp_int);
if (temp_int == -1)
return false;
break;
}
fi += tokLen;
}
//Console.WriteLine ("{0}-{1}-{2} {3}:{4} {5}", year, month, day, hour, minute, offset);
if (offset == TimeSpan.MinValue) {
if ((styles & DateTimeStyles.AssumeUniversal) != 0) {
offset = TimeSpan.Zero;
} else if ((styles & DateTimeStyles.AssumeLocal) != 0) {
offset = use_invariants ?
TimeSpan.Zero :
TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.Now);
}
}
if (hour < 0) hour = 0;
if (minute < 0) minute = 0;
if (second < 0) second = 0;
if (fraction < 0) fraction = 0;
if (year > 0 && month > 0 && day > 0) {
result = new DateTimeOffset (year, month, day, hour, minute, second, 0, offset);
result = result.AddSeconds (fraction);
if ((styles & DateTimeStyles.AdjustToUniversal) != 0)
result = result.ToUniversalTime ();
return true;
}
return false;
}
private static int ParseNumber (string input, int pos, int digits, bool leading_zero, bool allow_leading_white, out int result)
{
int digit_parsed;
return ParseNumber (input, pos, digits, leading_zero, allow_leading_white, out result, out digit_parsed);
}
private static int ParseNumber (string input, int pos, int digits, bool leading_zero, bool allow_leading_white, out int result, out int digit_parsed)
{
int char_parsed = 0;
digit_parsed = 0;
result = 0;
for (; allow_leading_white && pos < input.Length && input[pos] == ' '; pos++)
char_parsed++;
for (; pos < input.Length && Char.IsDigit (input[pos]) && digits > 0; pos ++, char_parsed++, digit_parsed++, digits --)
result = 10 * result + (byte) (input[pos] - '0');
if (leading_zero && digits > 0)
result = -1;
if (digit_parsed == 0)
result = -1;
return char_parsed;
}
private static int ParseEnum (string input, int pos, string [] enums, bool allow_leading_white, out int result)
{
int char_parsed = 0;
result = -1;
for (; allow_leading_white && pos < input.Length && input[pos] == ' '; pos++)
char_parsed ++;
for (int i = 0; i < enums.Length; i++)
if (input.Substring(pos).StartsWith (enums [i])) {
result = i;
break;
}
if (result >= 0)
char_parsed += enums[result].Length;
return char_parsed;
}
private static int ParseChar (string input, int pos, char c, bool allow_leading_white, out int result)
{
int char_parsed = 0;
result = -1;
for (; allow_leading_white && pos < input.Length && input[pos] == ' '; pos++, char_parsed++)
;
if (pos < input.Length && input[pos] == c){
result = (int) c;
char_parsed ++;
}
return char_parsed;
}
public TimeSpan Subtract (DateTimeOffset value)
{
return UtcDateTime - value.UtcDateTime;

View File

@ -574,6 +574,14 @@ namespace System
dec_part = Decimal.Floor(dec_part);
dec_part /= (10000000000000000000000000000M / p);
dec_part = Math.Round (dec_part, mode);
// ignore trailing zeros
while (decimals > 0 && (dec_part % 10) == 0) {
decimals--;
dec_part /= 10;
p /= 10;
}
dec_part /= p;
decimal result = int_part + dec_part;

View File

@ -28,12 +28,6 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// NumberFormatter is shared with Grasshopper and hence the #if TARGET_JVM for
// marking the use of unsafe code that is not supported in Grasshopper.
#if !TARGET_JVM
#define UNSAFE_TABLES
#endif
using System.Globalization;
using System.Text;
using System.Threading;
@ -72,7 +66,6 @@ namespace System
const double MinRoundtripVal = -1.79769313486231E+308;
const double MaxRoundtripVal = 1.79769313486231E+308;
#if UNSAFE_TABLES
// The below arrays are taken from mono/metatdata/number-formatter.h
private static readonly unsafe ulong* MantissaBitsTable;
@ -96,9 +89,7 @@ namespace System
out DigitLowerTable, out DigitUpperTable, out TenPowersList, out DecHexDigits);
}
unsafe
#endif
static long GetTenPowerOf(int i)
unsafe static long GetTenPowerOf(int i)
{
return TenPowersList [i];
}
@ -212,10 +203,7 @@ namespace System
// Helper to translate an int in the range 0 .. 9999 to its
// Hexadecimal digits representation.
#if UNSAFE_TABLES
unsafe
#endif
private static uint FastToDecHex (int val)
unsafe private static uint FastToDecHex (int val)
{
if (val < 100)
return (uint)DecHexDigits [val];
@ -440,10 +428,7 @@ namespace System
_decPointPos = _digitsLen = DecHexLen ();
}
#if UNSAFE_TABLES // No unsafe code under TARGET_JVM
unsafe
#endif
private void Init (string format, double value, int defPrecision)
unsafe private void Init (string format, double value, int defPrecision)
{
Init (format);
@ -1236,17 +1221,11 @@ namespace System
return new string (_cbuf, 0, _ind);
}
#if UNSAFE_TABLES // No unsafe code under TARGET_JVM
unsafe
#endif
private string FormatHexadecimal (int precision)
unsafe private string FormatHexadecimal (int precision)
{
int size = Math.Max (precision, _decPointPos);
#if UNSAFE_TABLES
char* digits = _specifierIsUpper ? DigitUpperTable : DigitLowerTable;
#else
char[] digits = _specifierIsUpper ? DigitUpperTable : DigitLowerTable;
#endif
ResetCharBuf (size);
_ind = size;
ulong val = _val1 | ((ulong)_val2 << 32);
@ -1769,10 +1748,7 @@ namespace System
_cbuf [_ind++] = (char)('0' | v & 0xf);
}
#if UNSAFE_TABLES // No unsafe code under TARGET_JVM
unsafe
#endif
private void FastAppendDigits (int val, bool force)
unsafe private void FastAppendDigits (int val, bool force)
{
int i = _ind;
int digits;

View File

@ -2630,9 +2630,22 @@ namespace System
if (ptr < max && str[ptr] == ':') {
int start = ++ ptr;
while (ptr < max && str[ptr] != '}')
++ ptr;
while (ptr < max) {
if (str [ptr] == '}') {
if (ptr + 1 < max && str [ptr + 1] == '}') {
++ptr;
format += str.Substring (start, ptr - start);
++ptr;
start = ptr;
continue;
}
break;
}
++ptr;
}
format += str.Substring (start, ptr - start);
}
else