Skip to content

Commit

Permalink
Fix bugs in matching engine
Browse files Browse the repository at this point in the history
  • Loading branch information
lilith committed Feb 4, 2024
1 parent f308a5a commit 4977962
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 17 deletions.
9 changes: 5 additions & 4 deletions src/Imazen.Routing/Matching/ExpressionParsingHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ public static bool TryParseCondition(ReadOnlyMemory<char> text,
}

// now parse using unescaped commas
var argListSpan = text[(functionNameEnds + 1)..];
var argListMemory = text[(functionNameEnds + 1)..^1];
var argListSpan = argListMemory.Span;
if (argListSpan.Length == 0)
{
error = null;
Expand All @@ -212,14 +213,14 @@ public static bool TryParseCondition(ReadOnlyMemory<char> text,
var start = 0;
while (start < argListSpan.Length)
{
var subSpan = textSpan[start..];
var subSpan = argListSpan[start..];
var commaIndex = FindCharNotEscaped(subSpan, ',', '\\');
if (commaIndex == -1)
{
args.Add(argListSpan[start..^1]); // no need to include the last character, it's a )
args.Add(argListMemory[start..]);
break;
}
args.Add(argListSpan.Slice(start, commaIndex));
args.Add(argListMemory[start..(start + commaIndex)]);
start += commaIndex + 1;
}
error = null;
Expand Down
23 changes: 11 additions & 12 deletions src/Imazen.Routing/Matching/MatchExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -531,15 +531,16 @@ private static bool TryParseConditionOrSegment(MatchingContext context,
error = null;
var conditionSpan = conditionMemory.Span;
var globChars = ExpressionParsingHelpers.GetGlobChars(conditionSpan);
var makeOptional = (globChars | ExpressionParsingHelpers.GlobChars.Optional) == ExpressionParsingHelpers.GlobChars.Optional
var makeOptional = (globChars & ExpressionParsingHelpers.GlobChars.Optional) == ExpressionParsingHelpers.GlobChars.Optional
|| conditionSpan.Is("optional");
if (makeOptional)
{
segmentStartLogic ??= SegmentBoundary.DefaultStart;
segmentStartLogic = segmentStartLogic.Value.MakeOptional(true);
}
// We ignore the glob chars, they don't constrain behavior any.
if (globChars != ExpressionParsingHelpers.GlobChars.None)
if (globChars != ExpressionParsingHelpers.GlobChars.None
|| conditionSpan.Is("optional"))
{
return true;
}
Expand Down Expand Up @@ -608,18 +609,16 @@ private static bool TryParseConditionOrSegment(MatchingContext context,

}
}
// TODO: skip adding if if (!conditionConsumed)
if (conditionConsumed)
if (!conditionConsumed)
{

}
conditions ??= new List<StringCondition>();
if (!TryParseCondition(context, conditions, functionName, args, out var condition, out error))
{
//TODO: add more context to error
return false;
conditions ??= new List<StringCondition>();
if (!TryParseCondition(context, conditions, functionName, args, out var condition, out error))
{
//TODO: add more context to error
return false;
}
conditions.Add(condition.Value);
}
conditions.Add(condition.Value);
return true;
}

Expand Down
8 changes: 8 additions & 0 deletions src/Imazen.Routing/Matching/StringCondition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,8 @@ private StringCondition(StringConditionKind stringConditionKind, char? c, string
StringConditionKind.CharLength => text.LengthWithinInclusive(int1, int2),
StringConditionKind.EqualsOrdinal => text.EqualsOrdinal(str!),
StringConditionKind.EqualsOrdinalIgnoreCase => text.EqualsOrdinalIgnoreCase(str!),
StringConditionKind.EqualsAnyOrdinal => text.EqualsAnyOrdinal(strArray!),
StringConditionKind.EqualsAnyOrdinalIgnoreCase => text.EqualsAnyOrdinalIgnoreCase(strArray!),
StringConditionKind.StartsWithChar => text.StartsWithChar(c!.Value),
StringConditionKind.StartsWithOrdinal => text.StartsWithOrdinal(str!),
StringConditionKind.StartsWithOrdinalIgnoreCase => text.StartsWithOrdinalIgnoreCase(str!),
Expand Down Expand Up @@ -458,6 +460,8 @@ private static ExpectedArgs ForKind(StringConditionKind stringConditionKind) =>
StringConditionKind.EndsWithChar => ExpectedArgs.Char,
StringConditionKind.EqualsOrdinal => ExpectedArgs.String,
StringConditionKind.EqualsOrdinalIgnoreCase => ExpectedArgs.String,
StringConditionKind.EqualsAnyOrdinal => ExpectedArgs.StringArray,
StringConditionKind.EqualsAnyOrdinalIgnoreCase => ExpectedArgs.StringArray,
StringConditionKind.StartsWithOrdinal => ExpectedArgs.String,
StringConditionKind.StartsWithOrdinalIgnoreCase => ExpectedArgs.String,
StringConditionKind.EndsWithOrdinal => ExpectedArgs.String,
Expand Down Expand Up @@ -580,6 +584,10 @@ public enum StringConditionKind: byte
EqualsOrdinal,
[Display(Name = "equals-i")]
EqualsOrdinalIgnoreCase,
[Display(Name = "equals")]
EqualsAnyOrdinal,
[Display(Name = "equals-i")]
EqualsAnyOrdinalIgnoreCase,
[Display(Name = "starts-with")]
StartsWithOrdinal,
[Display(Name = "starts-with")]
Expand Down
20 changes: 20 additions & 0 deletions src/Imazen.Routing/Matching/StringConditionMatchingHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ internal static bool LengthWithinInclusive(this ReadOnlySpan<char> chars, int? m
}
internal static bool EqualsOrdinal(this ReadOnlySpan<char> chars, string value) => chars.Equals(value.AsSpan(), StringComparison.Ordinal);
internal static bool EqualsOrdinalIgnoreCase(this ReadOnlySpan<char> chars, string value) => chars.Equals(value.AsSpan(), StringComparison.OrdinalIgnoreCase);


internal static bool StartsWithChar(this ReadOnlySpan<char> chars, char c) => chars.Length > 0 && chars[0] == c;
internal static bool StartsWithOrdinal(this ReadOnlySpan<char> chars, string value) => chars.StartsWith(value.AsSpan(), StringComparison.Ordinal);
internal static bool StartsWithOrdinalIgnoreCase(this ReadOnlySpan<char> chars, string value) => chars.StartsWith(value.AsSpan(), StringComparison.OrdinalIgnoreCase);
Expand All @@ -150,6 +152,24 @@ internal static bool StartsWithAnyOrdinalIgnoreCase(this ReadOnlySpan<char> char
}
return false;
}

internal static bool EqualsAnyOrdinal(this ReadOnlySpan<char> chars, string[] values)
{
foreach (var value in values)
{
if (chars.Equals(value.AsSpan(), StringComparison.Ordinal)) return true;
}
return false;
}
internal static bool EqualsAnyOrdinalIgnoreCase(this ReadOnlySpan<char> chars, string[] values)
{
foreach (var value in values)
{
if (chars.Equals(value.AsSpan(), StringComparison.OrdinalIgnoreCase)) return true;
}
return false;
}

internal static bool EndsWithChar(this ReadOnlySpan<char> chars, char c) => chars.Length > 0 && chars[^1] == c;
internal static bool EndsWithOrdinal(this ReadOnlySpan<char> chars, string value) => chars.EndsWith(value.AsSpan(), StringComparison.Ordinal);
internal static bool EndsWithOrdinalIgnoreCase(this ReadOnlySpan<char> chars, string value) => chars.EndsWith(value.AsSpan(), StringComparison.OrdinalIgnoreCase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ public void TestCaseSensitivity(bool isMatch, bool caseSensitive, string path)
[InlineData(true, "/{name}/{country:length(3)}", "/hi/usa")]
[InlineData(false, "/{name}/{country:length(3)}", "/hi/usa2")]
[InlineData(false, "/{name}/{country:length(3)}", "/hi/usa/")]
[InlineData(true, "/{name}/{country:length(3)}", "/hi/usa/")]
[InlineData(true, "/images/{seo_string_ignored}/{sku:guid}/{image_id:integer-range(0,1111111)}{width:integer:after(_):optional}.{format:equals(jpg|png|gif)}"
, "/images/seo-string/12345678-1234-1234-1234-123456789012/12678_300.jpg", "/images/seo-string/12345678-1234-1234-1234-123456789012/12678.png")]

public void TestAll(bool s, string expr, params string[] inputs)
{
var caseSensitive = expr.Contains("(i)");
Expand Down

0 comments on commit 4977962

Please sign in to comment.