public void MatchCaseInsensitive_MatchAndMove() { var value = new ValueCursor("abcd"); Assert.True(value.MoveNext(), "GetNext() 1"); Assert.True(value.MatchCaseInsensitive("AbC", CultureInfo.InvariantCulture.CompareInfo, true)); ValidateCurrentCharacter(value, 3, 'd'); }
public void MatchCaseInsensitive_StringNotMatched() { var value = new ValueCursor("xabcdef"); Assert.True(value.MoveNext(), "GetNext() 1"); Assert.False(value.MatchCaseInsensitive("abc", CultureInfo.InvariantCulture.CompareInfo, true)); ValidateCurrentCharacter(value, 0, 'x'); }
public void TestMatchCaseInsensitive_string() { var value = new ValueCursor("abc"); Assert.True(value.MoveNext(), "GetNext() 1"); Assert.True(value.MatchCaseInsensitive("AbC", CultureInfo.InvariantCulture.CompareInfo)); Assert.False(value.MoveNext(), "GetNext() end"); }
public void Match_String() { var value = new ValueCursor("abc"); Assert.True(value.MoveNext(), "GetNext() 1"); Assert.True(value.Match("abc")); Assert.False(value.MoveNext(), "GetNext() end"); }
public void Match_StringNotMatched() { var value = new ValueCursor("xabcdef"); Assert.True(value.MoveNext(), "GetNext() 1"); Assert.False(value.Match("abc")); ValidateCurrentCharacter(value, 0, 'x'); }
public void Match_StringOverLongStringToMatch() { var value = new ValueCursor("x"); Assert.True(value.MoveNext()); Assert.False(value.Match("long string")); ValidateCurrentCharacter(value, 0, 'x'); }
public void Parse_Partial_Invalid() { var value = new ValueCursor("x17:y"); value.MoveNext(); value.MoveNext(); var result = SimpleOffsetPattern.ParsePartial(value); Assert.Throws<UnparsableValueException>(() => result.GetValueOrThrow()); }
public void MatchCaseInsensitive_MatchWithoutMoving() { var value = new ValueCursor("abcd"); Assert.True(value.MoveNext(), "GetNext() 1"); Assert.True(value.MatchCaseInsensitive("AbC", CultureInfo.InvariantCulture.CompareInfo, false)); // We're still looking at the start ValidateCurrentCharacter(value, 0, 'a'); }
public void Match_Char() { var value = new ValueCursor("abc"); Assert.True(value.MoveNext(), "GetNext() 1"); Assert.True(value.Match('a'), "First character"); Assert.True(value.Match('b'), "Second character"); Assert.True(value.Match('c'), "Third character"); Assert.False(value.MoveNext(), "GetNext() end"); }
public void ParsePartial_ValidAtEnd() { var value = new ValueCursor("x17:30"); value.MoveNext(); value.MoveNext(); var result = SimpleOffsetPattern.ParsePartial(value); Assert.AreEqual(Offset.FromHoursAndMinutes(17, 30), result.Value); // Finish just after the value, which in this case is at the end. Assert.AreEqual(TextCursor.Nul, value.Current); }
internal ParseResult <ZonedDateTime> ParseZone(ValueCursor value) { DateTimeZone zone = TryParseFixedZone(value) ?? TryParseProviderZone(value); if (zone == null) { return(ParseResult <ZonedDateTime> .NoMatchingZoneId(value)); } Zone = zone; return(null); }
internal static ParseResult <T> ForInvalidValue(ValueCursor cursor, string formatString, params object[] parameters) { return(ForInvalidValue(() => { // Format the message which is specific to the kind of parse error. string detailMessage = string.Format(CultureInfo.CurrentCulture, formatString, parameters); // Format the overall message, containing the parse error and the value itself. string overallMessage = string.Format(CultureInfo.CurrentCulture, Messages.Parse_UnparsableValue, detailMessage, cursor); return new UnparsableValueException(overallMessage); })); }
/// <summary> /// Attempts to parse a fixed time zone from "UTC" with an optional /// offset, expressed as +HH, +HH:mm, +HH:mm:ss or +HH:mm:ss.fff - i.e. the /// general format. If it manages, it will move the cursor and return the /// zone. Otherwise, it will return null and the cursor will remain where /// it was. /// </summary> private DateTimeZone TryParseFixedZone(ValueCursor value) { if (value.CompareOrdinal(DateTimeZone.UtcId) != 0) { return(null); } value.Move(value.Index + 3); var pattern = OffsetPattern.GeneralInvariant.UnderlyingPattern; var parseResult = pattern.ParsePartial(value); return(parseResult.Success ? DateTimeZone.ForOffset(parseResult.Value) : DateTimeZone.Utc); }
public void ParsePartial_ValidInMiddle() { var value = new ValueCursor("x17:30y"); value.MoveNext(); value.MoveNext(); // Start already looking at the value to parse Assert.AreEqual('1', value.Current); var result = SimpleOffsetPattern.ParsePartial(value); Assert.AreEqual(Offset.FromHoursAndMinutes(17, 30), result.Value); // Finish just after the value Assert.AreEqual('y', value.Current); }
public ParseResult <T> ParsePartial(ValueCursor cursor) { int index = cursor.Index; foreach (IPartialPattern <T> pattern in patterns) { cursor.Move(index); ParseResult <T> result = pattern.ParsePartial(cursor); if (result.Success || !result.ContinueAfterErrorWithMultipleFormats) { return(result); } } cursor.Move(index); return(ParseResult <T> .NoMatchingFormat(cursor)); }
/// <summary> /// Tries to parse a time zone ID from the provider. Returns the zone /// on success (after moving the cursor to the end of the ID) or null on failure /// (leaving the cursor where it was). /// </summary> private DateTimeZone TryParseProviderZone(ValueCursor value) { // The IDs from the provider are guaranteed to be in order (using ordinal comparisons). // Use a binary search to find a match, then make sure it's the longest possible match. var ids = zoneProvider.Ids; int lowerBound = 0; // Inclusive int upperBound = ids.Count; // Exclusive while (lowerBound < upperBound) { int guess = (lowerBound + upperBound) / 2; int result = value.CompareOrdinal(ids[guess]); if (result < 0) { // Guess is later than our text: lower the upper bound upperBound = guess; } else if (result > 0) { // Guess is earlier than our text: raise the lower bound lowerBound = guess + 1; } else { // We've found a match! But it may not be as long as it // could be. Keep looking until we find a value which isn't a match... while (guess + 1 < upperBound && value.CompareOrdinal(ids[guess + 1]) == 0) { guess++; } string id = ids[guess]; value.Move(value.Index + id.Length); return(zoneProvider[id]); } } return(null); }
public ParseResult <Offset> ParsePartial(ValueCursor cursor) { // TODO: Do better than this. It's horrible, and may well be invalid // for some cultures. Or just remove the NumberPattern from 2.0... int longestPossible = Math.Min(maxLength, cursor.Length - cursor.Index); for (int length = longestPossible; length >= 0; length--) { string candidate = cursor.Value.Substring(cursor.Index, length); int milliseconds; if (Int32.TryParse(candidate, NumberStyles.Integer | NumberStyles.AllowThousands, formatInfo.NumberFormat, out milliseconds)) { if (milliseconds < -NodaConstants.MillisecondsPerStandardDay || NodaConstants.MillisecondsPerStandardDay < milliseconds) { return(ParseResult <Offset> .ValueOutOfRange(milliseconds)); } cursor.Move(cursor.Index + length); return(ParseResult <Offset> .ForValue(Offset.FromMilliseconds(milliseconds))); } } return(ParseResult <Offset> .CannotParseValue(cursor.Value, "n")); }
public void ParseInt64_Simple() { var value = new ValueCursor("56x"); Assert.True(value.MoveNext()); long result; Assert.IsNull(value.ParseInt64<string>(out result)); Assert.AreEqual(56L, result); // Cursor ends up post-number Assert.AreEqual(2, value.Index); }
internal static ParseResult <T> EscapedCharacterMismatch(ValueCursor cursor, char patternCharacter) => ForInvalidValue(cursor, Messages.Parse_EscapedCharacterMismatch, patternCharacter);
public void ParseInt64Digits_Minimum() { var value = new ValueCursor("1"); value.MoveNext(); long actual; Assert.True(value.ParseInt64Digits(1, 2, out actual)); Assert.AreEqual(1, actual); ValidateEndOfString(value); }
public void ParseInt64Digits_LargeNumber() { var value = new ValueCursor("9999999999999"); Assert.True(value.MoveNext()); long actual; Assert.True(value.ParseInt64Digits(1, 13, out actual)); Assert.AreEqual(actual, 9999999999999L); Assert.Greater(9999999999999L, int.MaxValue); }
internal static ParseResult <T> FieldValueOutOfRange(ValueCursor cursor, long value, char field) => ForInvalidValue(cursor, Messages.Parse_FieldValueOutOfRange, value, field, typeof(T));
public void ParseInt64Digits_Maximum() { var value = new ValueCursor("12"); Assert.True(value.MoveNext()); long actual; Assert.True(value.ParseInt64Digits(1, 2, out actual)); Assert.AreEqual(12, actual); }
internal static ParseResult <T> MissingSign(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_MissingSign);
public void CompareOrdinal_LongMatch_ValueIsEarlier() { var value = new ValueCursor("xabc"); value.Move(1); Assert.Less(value.CompareOrdinal("cccc"), 0); Assert.AreEqual(1, value.Index); // Cursor hasn't moved }
internal static ParseResult <T> NoMatchingCalendarSystem(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_NoMatchingCalendarSystem);
internal static ParseResult <T> MissingAmPmDesignator(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_MissingAmPmDesignator);
internal ParseResult <TResult> ParseEra <TResult>(NodaFormatInfo formatInfo, ValueCursor cursor) { var compareInfo = formatInfo.CompareInfo; foreach (var era in Calendar.Eras) { foreach (string eraName in formatInfo.GetEraNames(era)) { if (cursor.MatchCaseInsensitive(eraName, compareInfo, true)) { Era = era; return(null); } } } return(ParseResult <TResult> .MismatchedText(cursor, 'g')); }
/// <summary> /// Tries to parse a time zone ID from the provider. Returns the zone /// on success (after moving the cursor to the end of the ID) or null on failure /// (leaving the cursor where it was). /// </summary> private DateTimeZone TryParseProviderZone(ValueCursor value) { // The IDs from the provider are guaranteed to be in order (using ordinal comparisons). // Use a binary search to find a match, then make sure it's the longest possible match. var ids = zoneProvider.Ids; int lowerBound = 0; // Inclusive int upperBound = ids.Count; // Exclusive while (lowerBound < upperBound) { int guess = (lowerBound + upperBound) / 2; int result = value.CompareOrdinal(ids[guess]); if (result < 0) { // Guess is later than our text: lower the upper bound upperBound = guess; } else if (result > 0) { // Guess is earlier than our text: raise the lower bound lowerBound = guess + 1; } else { // We've found a match! But it may not be as long as it // could be. Keep track of a "longest match so far" (starting with the match we've found), // and keep looking through the IDs until we find an ID which doesn't start with that "longest // match so far", at which point we know we're done. // // We can't just look through all the IDs from "guess" to "lowerBound" and stop when we hit // a non-match against "value", because of situations like this: // value=Etc/GMT-12 // guess=Etc/GMT-1 // IDs includes { Etc/GMT-1, Etc/GMT-10, Etc/GMT-11, Etc/GMT-12, Etc/GMT-13 } // We can't stop when we hit Etc/GMT-10, because otherwise we won't find Etc/GMT-12. // We *can* stop when we get to Etc/GMT-13, because by then our longest match so far will // be Etc/GMT-12, and we know that anything beyond Etc/GMT-13 won't match that. // We can also stop when we hit upperBound, without any more comparisons. string longestSoFar = ids[guess]; for (int i = guess + 1; i < upperBound; i++) { string candidate = ids[i]; if (candidate.Length < longestSoFar.Length) { break; } if (string.CompareOrdinal(longestSoFar, 0, candidate, 0, longestSoFar.Length) != 0) { break; } if (value.CompareOrdinal(candidate) == 0) { longestSoFar = candidate; } } value.Move(value.Index + longestSoFar.Length); return(zoneProvider[longestSoFar]); } } return(null); }
/// <summary> /// We'd expected to get to the end of the string now, but we haven't. /// </summary> internal static ParseResult <T> ExpectedEndOfString(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_ExpectedEndOfString);
public void ParseInt64_NumberOutOfRange_MinValueLeadingDigits() { var value = new ValueCursor("-9223372036854775809"); Assert.True(value.MoveNext()); long result; Assert.IsNotNull(value.ParseInt64<string>(out result)); // Cursor has not moved Assert.AreEqual(0, value.Index); }
private static ParseResult <ZonedDateTime> ParseZone(ValueCursor value, ZonedDateTimeParseBucket bucket) => bucket.ParseZone(value);
internal static ParseResult <T> QuotedStringMismatch(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_QuotedStringMismatch);
internal static ParseResult <T> ValueOutOfRange(ValueCursor cursor, object value) => ForInvalidValue(cursor, Messages.Parse_ValueOutOfRange, value, typeof(T));
internal static ParseResult <T> ExtraValueCharacters(ValueCursor cursor, string remainder) => ForInvalidValue(cursor, Messages.Parse_ExtraValueCharacters, remainder);
internal static ParseResult <T> MismatchedText(ValueCursor cursor, char field) => ForInvalidValue(cursor, Messages.Parse_MismatchedText, field);
public void ParseInt64Digits_NoNumber() { var value = new ValueCursor("abc"); Assert.True(value.MoveNext()); long actual; Assert.False(value.ParseInt64Digits(1, 2, out actual)); ValidateCurrentCharacter(value, 0, 'a'); }
internal static ParseResult <T> MismatchedCharacter(ValueCursor cursor, char patternCharacter) => ForInvalidValue(cursor, Messages.Parse_MismatchedCharacter, patternCharacter);
public void ParseInt64Digits_MaximumMoreDigits() { var value = new ValueCursor("1234"); Assert.True(value.MoveNext()); long actual; Assert.True(value.ParseInt64Digits(1, 2, out actual)); Assert.AreEqual(12, actual); ValidateCurrentCharacter(value, 2, '3'); }
internal static ParseResult <T> MismatchedNumber(ValueCursor cursor, string pattern) => ForInvalidValue(cursor, Messages.Parse_MismatchedNumber, pattern);
public void ParseInt64Digits_MinimumNonDigits() { var value = new ValueCursor("1abc"); Assert.True(value.MoveNext()); long actual; Assert.True(value.ParseInt64Digits(1, 2, out actual)); Assert.AreEqual(1, actual); ValidateCurrentCharacter(value, 1, 'a'); }
internal static ParseResult <T> UnexpectedNegative(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_UnexpectedNegative);
public void ParseFraction_NonAscii_NeverMatches() { // Arabic-Indic digits 0 and 1. See // http://www.unicode.org/charts/PDF/U0600.pdf var value = new ValueCursor("\u0660\u0661"); Assert.True(value.MoveNext()); int actual; Assert.False(value.ParseFraction(2, 2, out actual, 2)); }
public ParseResult <Period> Parse(string text) { if (text is null) { return(ParseResult <Period> .ArgumentNull("text")); } if (text.Length == 0) { return(ParseResult <Period> .ValueStringEmpty); } ValueCursor valueCursor = new ValueCursor(text); valueCursor.MoveNext(); if (valueCursor.Current != 'P') { return(ParseResult <Period> .MismatchedCharacter(valueCursor, 'P')); } bool inDate = true; PeriodBuilder builder = new PeriodBuilder(); PeriodUnits unitsSoFar = 0; while (valueCursor.MoveNext()) { if (inDate && valueCursor.Current == 'T') { inDate = false; continue; } var failure = valueCursor.ParseInt64 <Period>(out long unitValue); if (failure != null) { return(failure); } if (valueCursor.Length == valueCursor.Index) { return(ParseResult <Period> .EndOfString(valueCursor)); } // Various failure cases: // - Repeated unit (e.g. P1M2M) // - Time unit is in date part (e.g. P5M) // - Date unit is in time part (e.g. PT1D) // - Unit is in incorrect order (e.g. P5D1Y) // - Unit is invalid (e.g. P5J) // - Unit is missing (e.g. P5) PeriodUnits unit; switch (valueCursor.Current) { case 'Y': unit = PeriodUnits.Years; break; case 'M': unit = inDate ? PeriodUnits.Months : PeriodUnits.Minutes; break; case 'W': unit = PeriodUnits.Weeks; break; case 'D': unit = PeriodUnits.Days; break; case 'H': unit = PeriodUnits.Hours; break; case 'S': unit = PeriodUnits.Seconds; break; case 's': unit = PeriodUnits.Milliseconds; break; case 't': unit = PeriodUnits.Ticks; break; case 'n': unit = PeriodUnits.Nanoseconds; break; default: return(InvalidUnit(valueCursor, valueCursor.Current)); } if ((unit & unitsSoFar) != 0) { return(RepeatedUnit(valueCursor, valueCursor.Current)); } // This handles putting months before years, for example. Less significant units // have higher integer representations. if (unit < unitsSoFar) { return(MisplacedUnit(valueCursor, valueCursor.Current)); } // The result of checking "there aren't any time units in this unit" should be // equal to "we're still in the date part". if ((unit & PeriodUnits.AllTimeUnits) == 0 != inDate) { return(MisplacedUnit(valueCursor, valueCursor.Current)); } builder[unit] = unitValue; unitsSoFar |= unit; } return(ParseResult <Period> .ForValue(builder.Build())); }
public void ParseInt64_Negative() { var value = new ValueCursor("-56x"); Assert.True(value.MoveNext()); long result; Assert.IsNull(value.ParseInt64<string>(out result)); Assert.AreEqual(-56L, result); }
// TODO(misc): Tidy this up a *lot*. public ParseResult <Period> Parse(string text) { if (text is null) { return(ParseResult <Period> .ArgumentNull("text")); } if (text.Length == 0) { return(ParseResult <Period> .ValueStringEmpty); } ValueCursor valueCursor = new ValueCursor(text); valueCursor.MoveNext(); if (valueCursor.Current != 'P') { return(ParseResult <Period> .MismatchedCharacter(valueCursor, 'P')); } bool inDate = true; PeriodBuilder builder = new PeriodBuilder(); PeriodUnits unitsSoFar = 0; while (valueCursor.MoveNext()) { if (inDate && valueCursor.Current == 'T') { inDate = false; continue; } bool negative = valueCursor.Current == '-'; var failure = valueCursor.ParseInt64 <Period>(out long unitValue); if (failure != null) { return(failure); } if (valueCursor.Length == valueCursor.Index) { return(ParseResult <Period> .EndOfString(valueCursor)); } // Various failure cases: // - Repeated unit (e.g. P1M2M) // - Time unit is in date part (e.g. P5M) // - Date unit is in time part (e.g. PT1D) // - Unit is in incorrect order (e.g. P5D1Y) // - Unit is invalid (e.g. P5J) // - Unit is missing (e.g. P5) PeriodUnits unit; switch (valueCursor.Current) { case 'Y': unit = PeriodUnits.Years; break; case 'M': unit = inDate ? PeriodUnits.Months : PeriodUnits.Minutes; break; case 'W': unit = PeriodUnits.Weeks; break; case 'D': unit = PeriodUnits.Days; break; case 'H': unit = PeriodUnits.Hours; break; case 'S': unit = PeriodUnits.Seconds; break; case ',': case '.': unit = PeriodUnits.Nanoseconds; break; // Special handling below default: return(InvalidUnit(valueCursor, valueCursor.Current)); } if ((unit & unitsSoFar) != 0) { return(RepeatedUnit(valueCursor, valueCursor.Current)); } // This handles putting months before years, for example. Less significant units // have higher integer representations. if (unit < unitsSoFar) { return(MisplacedUnit(valueCursor, valueCursor.Current)); } // The result of checking "there aren't any time units in this unit" should be // equal to "we're still in the date part". if ((unit & PeriodUnits.AllTimeUnits) == 0 != inDate) { return(MisplacedUnit(valueCursor, valueCursor.Current)); } // Seen a . or , which need special handling. if (unit == PeriodUnits.Nanoseconds) { // Check for already having seen seconds, e.g. PT5S0.5 if ((unitsSoFar & PeriodUnits.Seconds) != 0) { return(MisplacedUnit(valueCursor, valueCursor.Current)); } builder.Seconds = unitValue; if (!valueCursor.MoveNext()) { return(ParseResult <Period> .MissingNumber(valueCursor)); } // Can cope with at most 999999999 nanoseconds if (!valueCursor.ParseFraction(9, 9, out int totalNanoseconds, 1)) { return(ParseResult <Period> .MissingNumber(valueCursor)); } // Use whether or not the seconds value was negative (even if 0) // as the indication of whether this value is negative. if (negative) { totalNanoseconds = -totalNanoseconds; } builder.Milliseconds = (totalNanoseconds / NanosecondsPerMillisecond) % MillisecondsPerSecond; builder.Ticks = (totalNanoseconds / NanosecondsPerTick) % TicksPerMillisecond; builder.Nanoseconds = totalNanoseconds % NanosecondsPerTick; if (valueCursor.Current != 'S') { return(ParseResult <Period> .MismatchedCharacter(valueCursor, 'S')); } if (valueCursor.MoveNext()) { return(ParseResult <Period> .ExpectedEndOfString(valueCursor)); } return(ParseResult <Period> .ForValue(builder.Build())); } builder[unit] = unitValue; unitsSoFar |= unit; } if (unitsSoFar == 0) { return(ParseResult <Period> .ForInvalidValue(valueCursor, TextErrorMessages.EmptyPeriod)); } return(ParseResult <Period> .ForValue(builder.Build())); }
public void ParseInt64_NegativeThenNonDigit() { var value = new ValueCursor("-x"); Assert.True(value.MoveNext()); long result; Assert.IsNotNull(value.ParseInt64<string>(out result)); // Cursor has not moved Assert.AreEqual(0, value.Index); }
private static ParseResult <Period> RepeatedUnit(ValueCursor cursor, char unitCharacter) => ParseResult <Period> .ForInvalidValue(cursor, TextErrorMessages.RepeatedUnitSpecifier, unitCharacter);
public void ParseInt64_MinValue() { var value = new ValueCursor("-9223372036854775808"); Assert.True(value.MoveNext()); long result; Assert.IsNull(value.ParseInt64<string>(out result)); Assert.AreEqual(long.MinValue, result); }
internal ParseResult <TResult> ParseEra <TResult>(NodaFormatInfo formatInfo, ValueCursor cursor) { var compareInfo = formatInfo.CompareInfo; var eras = Calendar.Eras; for (int i = 0; i < eras.Count; i++) { foreach (string eraName in formatInfo.GetEraNames(eras[i])) { if (cursor.MatchCaseInsensitive(eraName, compareInfo, true)) { EraIndex = i; return(null); } } } return(ParseResult <TResult> .MismatchedText('g')); }
public void CompareOrdinal_ExactMatchValueContinues() { var value = new ValueCursor("xabc"); value.Move(1); Assert.AreEqual(0, value.CompareOrdinal("ab")); Assert.AreEqual(1, value.Index); // Cursor hasn't moved }
public void ParseInt64Digits_TooFewDigits() { var value = new ValueCursor("a12b"); Assert.True(value.MoveNext()); ValidateCurrentCharacter(value, 0, 'a'); Assert.True(value.MoveNext()); long actual; Assert.False(value.ParseInt64Digits(3, 3, out actual)); ValidateCurrentCharacter(value, 1, '1'); }
public void CompareOrdinal_LongMatch_ValueIsLater() { var value = new ValueCursor("xabc"); value.Move(1); Assert.Greater(value.CompareOrdinal("aaaa"), 0); Assert.AreEqual(1, value.Index); // Cursor hasn't moved }
internal static ParseResult <T> DateSeparatorMismatch(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_DateSeparatorMismatch);
public void MatchCaseInsensitive_StringOverLongStringToMatch() { var value = new ValueCursor("x"); Assert.True(value.MoveNext()); Assert.False(value.MatchCaseInsensitive("long string", CultureInfo.InvariantCulture.CompareInfo, true)); ValidateCurrentCharacter(value, 0, 'x'); }
internal static ParseResult <T> NoMatchingZoneId(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_NoMatchingZoneId);
private static ParseResult <Period> InvalidUnit(ValueCursor cursor, char unitCharacter) => ParseResult <Period> .ForInvalidValue(cursor, Messages.Parse_InvalidUnitSpecifier, unitCharacter);
private static ParseResult <Period> MisplacedUnit(ValueCursor cursor, char unitCharacter) { return(ParseResult <Period> .ForInvalidValue(cursor, Messages.Parse_MisplacedUnitSpecifier, unitCharacter)); }
public void Match_StringPartial() { var value = new ValueCursor("abcdef"); Assert.True(value.MoveNext(), "GetNext() 1"); Assert.True(value.Match("abc")); ValidateCurrentCharacter(value, 3, 'd'); }
public void TestParseDigit_nonASCII_NeverMatches() { // Arabic-Indic digits 0 and 1. See // http://www.unicode.org/charts/PDF/U0600.pdf var value = new ValueCursor("\u0660\u0661"); Assert.True(value.MoveNext()); int actual; Assert.False(value.ParseDigits(1, 2, out actual)); }