// // ProcessTerminal_HM // // Actions: Validate the 2-number "Hours:Minutes" terminal case // private static Boolean ProcessTerminal_HM(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result) { if (raw.SepCount != 3 || raw.NumCount != 2 || (style & TimeSpanStandardStyles.RequireFull) != 0) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0); bool loc = ((style & TimeSpanStandardStyles.Localized) != 0); bool positive = false; bool match = false; if (inv) { if (raw.FullHMMatch(raw.PositiveInvariant)) { match = true; positive = true; } if (!match && raw.FullHMMatch(raw.NegativeInvariant)) { match = true; positive = false; } } if (loc) { if (!match && raw.FullHMMatch(raw.PositiveLocalized)) { match = true; positive = true; } if (!match && raw.FullHMMatch(raw.NegativeLocalized)) { match = true; positive = false; } } long ticks = 0; if (match) { if (!TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], zero, zero, out ticks)) { result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge"); return false; } if (!positive) { ticks = -ticks; if (ticks > 0) { result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge"); return false; } } result.parsedTimeSpan._ticks = ticks; return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; }
// // ProcessTerminal_HM_S_D // // Actions: Validate the ambiguous 3-number "Hours:Minutes:Seconds", "Days.Hours:Minutes", or "Hours:Minutes:.Fraction" terminal case // private static Boolean ProcessTerminal_HM_S_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result) { if (raw.SepCount != 4 || raw.NumCount != 3 || (style & TimeSpanStandardStyles.RequireFull) != 0) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0); bool loc = ((style & TimeSpanStandardStyles.Localized) != 0); bool positive = false; bool match = false; bool overflow = false; long ticks = 0; if (inv) { if (raw.FullHMSMatch(raw.PositiveInvariant)) { positive = true; match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, out ticks); overflow = overflow || !match; } if (!match && raw.FullDHMMatch(raw.PositiveInvariant)) { positive = true; match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, zero, out ticks); overflow = overflow || !match; } if (!match && raw.PartialAppCompatMatch(raw.PositiveInvariant)) { positive = true; match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], zero, raw.numbers[2], out ticks); overflow = overflow || !match; } if (!match && raw.FullHMSMatch(raw.NegativeInvariant)) { positive = false; match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, out ticks); overflow = overflow || !match; } if (!match && raw.FullDHMMatch(raw.NegativeInvariant)) { positive = false; match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, zero, out ticks); overflow = overflow || !match; } if (!match && raw.PartialAppCompatMatch(raw.NegativeInvariant)) { positive = false; match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], zero, raw.numbers[2], out ticks); overflow = overflow || !match; } } if (loc) { if (!match && raw.FullHMSMatch(raw.PositiveLocalized)) { positive = true; match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, out ticks); overflow = overflow || !match; } if (!match && raw.FullDHMMatch(raw.PositiveLocalized)) { positive = true; match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, zero, out ticks); overflow = overflow || !match; } if (!match && raw.PartialAppCompatMatch(raw.PositiveLocalized)) { positive = true; match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], zero, raw.numbers[2], out ticks); overflow = overflow || !match; } if (!match && raw.FullHMSMatch(raw.NegativeLocalized)) { positive = false; match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, out ticks); overflow = overflow || !match; } if (!match && raw.FullDHMMatch(raw.NegativeLocalized)) { positive = false; match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, zero, out ticks); overflow = overflow || !match; } if (!match && raw.PartialAppCompatMatch(raw.NegativeLocalized)) { positive = false; match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], zero, raw.numbers[2], out ticks); overflow = overflow || !match; } } if (match) { if (!positive) { ticks = -ticks; if (ticks > 0) { result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge"); return false; } } result.parsedTimeSpan._ticks = ticks; return true; } if (overflow) { // we found at least one literal pattern match but the numbers just didn't fit result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge"); return false; } else { // we couldn't find a thing result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } }
// // ProcessTerminalState // // Actions: Validate the terminal state of a standard format parse. // Sets result.parsedTimeSpan on success. // // Calculates the resultant TimeSpan from the TimeSpanRawInfo // // try => +InvariantPattern, -InvariantPattern, +LocalizedPattern, -LocalizedPattern // 1) Verify Start matches // 2) Verify End matches // 3) 1 number => d // 2 numbers => h:m // 3 numbers => h:m:s | d.h:m | h:m:.f // 4 numbers => h:m:s.f | d.h:m:s | d.h:m:.f // 5 numbers => d.h:m:s.f private static Boolean ProcessTerminalState(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result) { if (raw.lastSeenTTT == TTT.Num) { TimeSpanToken tok = new TimeSpanToken(); tok.ttt = TTT.Sep; tok.sep = String.Empty; if (!raw.ProcessToken(ref tok, ref result)) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } } switch (raw.NumCount) { case 1: return ProcessTerminal_D(ref raw, style, ref result); case 2: return ProcessTerminal_HM(ref raw, style, ref result); case 3: return ProcessTerminal_HM_S_D(ref raw, style, ref result); case 4: return ProcessTerminal_HMS_F_D(ref raw, style, ref result); case 5: return ProcessTerminal_DHMSF(ref raw, style, ref result); default: result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } }
// ---- 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 ProcessTerminal_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result) { if (((raw.SepCount != 2) || (raw.NumCount != 1)) || ((style & TimeSpanStandardStyles.RequireFull) != TimeSpanStandardStyles.None)) { result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; } bool flag = (style & TimeSpanStandardStyles.Invariant) != TimeSpanStandardStyles.None; bool flag2 = (style & TimeSpanStandardStyles.Localized) != TimeSpanStandardStyles.None; bool positive = false; bool flag4 = false; if (flag) { if (raw.FullDMatch(raw.PositiveInvariant)) { flag4 = true; positive = true; } if (!flag4 && raw.FullDMatch(raw.NegativeInvariant)) { flag4 = true; positive = false; } } if (flag2) { if (!flag4 && raw.FullDMatch(raw.PositiveLocalized)) { flag4 = true; positive = true; } if (!flag4 && raw.FullDMatch(raw.NegativeLocalized)) { flag4 = true; positive = false; } } long num = 0L; if (flag4) { if (!TryTimeToTicks(positive, raw.numbers[0], zero, zero, zero, zero, out num)) { result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge"); return false; } if (!positive) { num = -num; if (num > 0L) { result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge"); return false; } } result.parsedTimeSpan._ticks = num; return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan"); return false; }
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; }