Skip to content

Commit

Permalink
Merge branch 'hotfix/2.1.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
dazinator committed Sep 12, 2018
2 parents 3b862a0 + b124666 commit bbc5a99
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 29 deletions.
9 changes: 6 additions & 3 deletions src/DotNet.Glob.Tests/GlobTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ public void Does_Not_Match(string pattern, params string[] testStrings)
[InlineData("p?th/*a[bcd]b[e-g]a[1-4][!wxyz][!a-c][!1-3].*", "pGth/yGKNY6acbea3rm8.")]
[InlineData("/**/file.*", "/folder/file.csv")]
[InlineData("/**/file.*", "/file.txt")]
[InlineData("/**/file.*", "/file.txt")]
[InlineData("**/file.*", "/file.txt")]
[InlineData("/*file.txt", "/file.txt")]
[InlineData("C:\\THIS_IS_A_DIR\\*", "C:\\THIS_IS_A_DIR\\somefile")] // Regression Test for https://github.com/dazinator/DotNet.Glob/issues/20
Expand Down Expand Up @@ -78,14 +77,18 @@ public void Does_Not_Match(string pattern, params string[] testStrings)
[InlineData(@"C:\myergen[*][]]ator", @"C:\myergen*]ator")]
[InlineData(@"C:\myergen[*]]ator", @"C:\myergen*ator", @"C:\myergen]ator")]
[InlineData(@"C:\myergen[?]ator", @"C:\myergen?ator")]
[InlineData(@"/path[\]hatstand", @"/path\hatstand")]
[InlineData(@"/path[\]hatstand", @"/path\hatstand")]
[InlineData(@"**\[#!]*\**", @"#test3", @"#test3\", @"\#test3\foo", @"\#test3")]
[InlineData(@"**\[#!]*", @"#test3", "#this is a comment", @"\#test3")]
[InlineData(@"[#!]*\**","#this is a comment")]
[InlineData(@"[#!]*", @"#test3", "#this is a comment")]
public void IsMatch(string pattern, params string[] testStrings)
{
var glob = Globbing.Glob.Parse(pattern);
foreach (var testString in testStrings)
{
var match = glob.IsMatch(testString);
Assert.True(match);
Assert.True(match, $"glob {pattern} failed to match test string: {testString}");
}
}

Expand Down
47 changes: 27 additions & 20 deletions src/DotNet.Glob/Evaluation/WildcardDirectoryTokenEvaluator.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Text;
using DotNet.Globbing.Token;
using DotNet.Globbing.Token;

namespace DotNet.Globbing.Evaluation
{
Expand Down Expand Up @@ -31,35 +29,49 @@ public bool IsMatch(string allChars, int currentPosition, out int newPosition)
newPosition = currentPosition;

// 1. Are we already at the end of the test string?
if (currentPosition >= allChars.Length)
if (currentPosition >= allChars.Length - 1)
{
return true;
}

// A) If leading seperator then current character needs to be that seperator.
var currentChar = allChars[currentPosition];
if (this._token.LeadingPathSeperator != null)
char currentChar = allChars[currentPosition];
if (_token.LeadingPathSeperator != null)
{
if (!GlobStringReader.IsPathSeperator(currentChar))
{
// expected seperator.
return false;
}

//else
//{
// advance current position to match the leading seperator.
currentPosition = currentPosition + 1;
//}
}
else
{
// no leading seperator, means ** used at start of pattern not /** used within pattern.
// If **/ is used for start of pattern then input string doesn't need to start with a / or \ and it will be matched.
// i.e **/foo/bar will match foo/bar or /foo/bar.
// where as /**/foo/bar will not match foo/bar it will only match /foo/bar.
if (GlobStringReader.IsPathSeperator(currentChar))
{
// advance current position to match the leading seperator.
currentPosition = currentPosition + 1;
}
}

// 2. if no more tokens require matching (i.e ** is the last token) - we match.
if (this._subEvaluator.EvaluatorCount == 0)
if (_subEvaluator.EvaluatorCount == 0)
{
newPosition = allChars.Length;
return true;
}

// Because we know we have more tokens in the pattern (subevaluators) - those will require a minimum amount of characters to match (could be 0 too).
// We can therefore calculate a "max" character position that we can match to, as if we exceed that position the remaining tokens cant possibly match.
var maxPos = (allChars.Length - _subEvaluator.ConsumesMinLength);
int maxPos = (allChars.Length - _subEvaluator.ConsumesMinLength);

// If all of the remaining tokens have a precise length, we can calculate the exact character that we need to macth to in the string.
// Otherwise we have to test at multiple character positions until we find a match (less efficient)
Expand All @@ -69,12 +81,12 @@ public bool IsMatch(string allChars, int currentPosition, out int newPosition)
// As we can only match full segments, make sure character before chacracter at max pos is a seperator,
if (maxPos > 0)
{
var mustMatchUntilChar = allChars[maxPos - 1];
char mustMatchUntilChar = allChars[maxPos - 1];
if (!GlobStringReader.IsPathSeperator(mustMatchUntilChar))
{
// can only match full segments.
return false;
}
}
}

// Advance position to max pos.
Expand All @@ -90,6 +102,7 @@ public bool IsMatch(string allChars, int currentPosition, out int newPosition)
currentChar = allChars[currentPosition];

// If the ** token was parsed with a trailing slash - i.e "**/" then we need to match past it before we test remainijng tokens.
// special exception if **/ is at start of pattern, as then the input string need not have any path seperators.
if (_token.TrailingPathSeperator != null)
{
if (GlobStringReader.IsPathSeperator(currentChar))
Expand Down Expand Up @@ -125,7 +138,7 @@ public bool IsMatch(string allChars, int currentPosition, out int newPosition)
// match the seperator.
currentPosition = currentPosition + 1;
break;
}
}
}
}
}
Expand All @@ -134,15 +147,9 @@ public bool IsMatch(string allChars, int currentPosition, out int newPosition)

}

public virtual int ConsumesMinLength
{
get { return _subEvaluator.ConsumesMinLength; }
}
public virtual int ConsumesMinLength => _subEvaluator.ConsumesMinLength;

public bool ConsumesVariableLength
{
get { return true; }
}
public bool ConsumesVariableLength => true;

#endregion

Expand Down
18 changes: 12 additions & 6 deletions src/DotNet.Glob/Evaluation/WildcardTokenEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ public class WildcardTokenEvaluator : IGlobTokenEvaluator
private readonly WildcardToken _token;
private readonly CompositeTokenEvaluator _subEvaluator;
private readonly bool _requiresSubEvaluation;


public WildcardTokenEvaluator(WildcardToken token, CompositeTokenEvaluator subEvaluator)
{
_token = token;
_subEvaluator = subEvaluator;
_requiresSubEvaluation = _subEvaluator.EvaluatorCount > 0;
_requiresSubEvaluation = _subEvaluator.EvaluatorCount > 0;
}

#region IGlobTokenEvaluator
Expand Down Expand Up @@ -72,27 +73,32 @@ public bool IsMatch(string allChars, int currentPosition, out int newPosition)
}
var isMatch = _subEvaluator.IsMatch(allChars, requiredMatchPosition, out newPosition);
return isMatch;
}
}

// We can match a variable amount of characters but,
// We can't match more characters than the amount that will take us past the min required length required by the sub evaluator tokens,
// and as we are not a directory wildcard, we can't match past a path seperator.
var maxPos = (allChars.Length - _subEvaluator.ConsumesMinLength);
for (int i = currentPosition; i <= maxPos; i++)
var maxPos = allChars.Length - 1;
if (_subEvaluator.ConsumesMinLength > 0)
{
var currentChar = allChars[i];
maxPos = maxPos - _subEvaluator.ConsumesMinLength + 1;
}
// var maxPos = (allChars.Length - _subEvaluator.ConsumesMinLength);
for (int i = currentPosition; i <= maxPos; i++)
{

var isMatch = _subEvaluator.IsMatch(allChars, i, out newPosition);
if (isMatch)
{
return true;
}

var currentChar = allChars[i];
if (currentChar == '/' || currentChar == '\\')
{
return false;
}
}
}

return false;

Expand Down

0 comments on commit bbc5a99

Please sign in to comment.