// ---- SECTION: private static methods that do the actual work ---------* #region TryParseTimeSpan // // TryParseTimeSpan // // Actions: Common private Parse method called by both Parse and TryParse // private static Boolean TryParseTimeSpan(String input, TimeSpanStandardStyles style, IFormatProvider formatProvider, ref TimeSpanResult result) { if (input == null) { result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, nameof(input)); return false; } input = input.Trim(); if (input == String.Empty) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } TimeSpanTokenizer tokenizer = new TimeSpanTokenizer(); tokenizer.Init(input); TimeSpanRawInfo raw = new TimeSpanRawInfo(); raw.Init(DateTimeFormatInfo.GetInstance(formatProvider)); TimeSpanToken tok = tokenizer.GetNextToken(); /* The following loop will break out when we reach the end of the str or * when we can determine that the input is invalid. */ while (tok.ttt != TTT.End) { if (!raw.ProcessToken(ref tok, ref result)) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } tok = tokenizer.GetNextToken(); } if (!tokenizer.EOL) { // embedded nulls in the input string result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } if (!ProcessTerminalState(ref raw, style, ref result)) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } return true; }
private static bool TryParseTimeSpan(string input, TimeSpanStandardStyles style, IFormatProvider formatProvider, ref TimeSpanResult result) { if (input == null) { result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "input"); return false; } input = input.Trim(); if (input == string.Empty) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } TimeSpanTokenizer tokenizer = new TimeSpanTokenizer(); tokenizer.Init(input); TimeSpanRawInfo raw = new TimeSpanRawInfo(); raw.Init(DateTimeFormatInfo.GetInstance(formatProvider)); for (TimeSpanToken token = tokenizer.GetNextToken(); token.ttt != TTT.End; token = tokenizer.GetNextToken()) { if (!raw.ProcessToken(ref token, ref result)) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } } if (!tokenizer.EOL) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } if (!ProcessTerminalState(ref raw, style, ref result)) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } return true; }
// // TryParseByFormat // // Actions: Parse the TimeSpan instance using the specified format. Used by TryParseExactTimeSpan. // private static Boolean TryParseByFormat(String input, String format, TimeSpanStyles styles, ref TimeSpanResult result) { Debug.Assert(input != null, "input != null"); Debug.Assert(format != null, "format != null"); bool seenDD = false; // already processed days? bool seenHH = false; // already processed hours? bool seenMM = false; // already processed minutes? bool seenSS = false; // already processed seconds? bool seenFF = false; // already processed fraction? int dd = 0; // parsed days int hh = 0; // parsed hours int mm = 0; // parsed minutes int ss = 0; // parsed seconds int leadingZeroes = 0; // number of leading zeroes in the parsed fraction int ff = 0; // parsed fraction int i = 0; // format string position int tokenLen = 0; // length of current format token, used to update index 'i' TimeSpanTokenizer tokenizer = new TimeSpanTokenizer(); tokenizer.Init(input, -1); while (i < format.Length) { char ch = format[i]; int nextFormatChar; switch (ch) { case 'h': tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch); if (tokenLen > 2 || seenHH || !ParseExactDigits(ref tokenizer, tokenLen, out hh)) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } seenHH = true; break; case 'm': tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch); if (tokenLen > 2 || seenMM || !ParseExactDigits(ref tokenizer, tokenLen, out mm)) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } seenMM = true; break; case 's': tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch); if (tokenLen > 2 || seenSS || !ParseExactDigits(ref tokenizer, tokenLen, out ss)) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } seenSS = true; break; case 'f': tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch); if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF || !ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff)) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } seenFF = true; break; case 'F': tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch); if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff); seenFF = true; break; case 'd': tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch); int tmp = 0; if (tokenLen > 8 || seenDD || !ParseExactDigits(ref tokenizer, (tokenLen<2) ? 1 : tokenLen, (tokenLen<2) ? 8 : tokenLen, out tmp, out dd)) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } seenDD = true; break; case '\'': case '\"': StringBuilder enquotedString = new StringBuilder(); if (!DateTimeParse.TryParseQuoteString(format, i, enquotedString, out tokenLen)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadQuote", ch); return false; } if (!ParseExactLiteral(ref tokenizer, enquotedString)) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } break; case '%': // Optional format character. // For example, format string "%d" will print day // Most of the cases, "%" can be ignored. nextFormatChar = DateTimeFormat.ParseNextChar(format, i); // nextFormatChar will be -1 if we already reach the end of the format string. // Besides, we will not allow "%%" appear in the pattern. if (nextFormatChar >= 0 && nextFormatChar != (int)'%') { tokenLen = 1; // skip the '%' and process the format character break; } else { // This means that '%' is at the end of the format string or // "%%" appears in the format string. result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } case '\\': // Escaped character. Can be used to insert character into the format string. // For example, "\d" will insert the character 'd' into the string. // nextFormatChar = DateTimeFormat.ParseNextChar(format, i); if (nextFormatChar >= 0 && tokenizer.NextChar == (char)nextFormatChar) { tokenLen = 2; } else { // This means that '\' is at the end of the format string or the literal match failed. result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } break; default: result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } i += tokenLen; } if (!tokenizer.EOL) { // the custom format didn't consume the entire input result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } long ticks = 0; bool positive = (styles & TimeSpanStyles.AssumeNegative) == 0; if (TryTimeToTicks(positive, new TimeSpanToken(dd), new TimeSpanToken(hh), new TimeSpanToken(mm), new TimeSpanToken(ss), new TimeSpanToken(leadingZeroes, ff), out ticks)) { if (!positive) ticks = -ticks; result.parsedTimeSpan._ticks = ticks; return true; } else { result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge"); return false; } }
private static bool TryParseByFormat(string input, string format, TimeSpanStyles styles, ref TimeSpanResult result) { bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; bool flag5 = false; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int zeroes = 0; int num6 = 0; int pos = 0; int returnValue = 0; TimeSpanTokenizer tokenizer = new TimeSpanTokenizer(); tokenizer.Init(input, -1); while (pos < format.Length) { int num9; char failureMessageFormatArgument = format[pos]; switch (failureMessageFormatArgument) { case '%': num9 = DateTimeFormat.ParseNextChar(format, pos); if ((num9 < 0) || (num9 == 0x25)) { goto Label_0280; } returnValue = 1; goto Label_02CA; case '\'': case '"': { StringBuilder builder = new StringBuilder(); if (!DateTimeParse.TryParseQuoteString(format, pos, builder, out returnValue)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadQuote", failureMessageFormatArgument); return false; } if (ParseExactLiteral(ref tokenizer, builder)) { goto Label_02CA; } result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } case 'F': returnValue = DateTimeFormat.ParseRepeatPattern(format, pos, failureMessageFormatArgument); if ((returnValue > 7) || flag5) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } ParseExactDigits(ref tokenizer, returnValue, returnValue, out zeroes, out num6); flag5 = true; goto Label_02CA; case 'm': returnValue = DateTimeFormat.ParseRepeatPattern(format, pos, failureMessageFormatArgument); if (((returnValue > 2) || flag3) || !ParseExactDigits(ref tokenizer, returnValue, out num3)) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } flag3 = true; goto Label_02CA; case 's': returnValue = DateTimeFormat.ParseRepeatPattern(format, pos, failureMessageFormatArgument); if (((returnValue > 2) || flag4) || !ParseExactDigits(ref tokenizer, returnValue, out num4)) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } flag4 = true; goto Label_02CA; case 'd': { returnValue = DateTimeFormat.ParseRepeatPattern(format, pos, failureMessageFormatArgument); int num10 = 0; if (((returnValue > 8) || flag) || !ParseExactDigits(ref tokenizer, (returnValue < 2) ? 1 : returnValue, (returnValue < 2) ? 8 : returnValue, out num10, out num)) { result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } flag = true; goto Label_02CA; } case 'f': returnValue = DateTimeFormat.ParseRepeatPattern(format, pos, failureMessageFormatArgument); if (((returnValue <= 7) && !flag5) && ParseExactDigits(ref tokenizer, returnValue, returnValue, out zeroes, out num6)) { goto Label_0193; } result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; case 'h': returnValue = DateTimeFormat.ParseRepeatPattern(format, pos, failureMessageFormatArgument); if (((returnValue <= 2) && !flag2) && ParseExactDigits(ref tokenizer, returnValue, out num2)) { break; } result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; case '\\': num9 = DateTimeFormat.ParseNextChar(format, pos); if ((num9 >= 0) && (tokenizer.NextChar == ((char) num9))) { returnValue = 2; goto Label_02CA; } result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; default: result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; } flag2 = true; goto Label_02CA; Label_0193: flag5 = true; goto Label_02CA; Label_0280: result.SetFailure(ParseFailureKind.Format, "Format_InvalidString"); return false; Label_02CA: pos += returnValue; } if (!tokenizer.EOL) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } long num11 = 0L; bool positive = (styles & TimeSpanStyles.AssumeNegative) == TimeSpanStyles.None; if (TryTimeToTicks(positive, new TimeSpanToken(num), new TimeSpanToken(num2), new TimeSpanToken(num3), new TimeSpanToken(num4), new TimeSpanToken(zeroes, num6), out num11)) { if (!positive) { num11 = -num11; } result.parsedTimeSpan._ticks = num11; return true; } result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge"); return false; }