public RouteValueDictionary Match (string path, RouteValueDictionary defaults)
{
var ret = new RouteValueDictionary ();
string url = Url;
string [] argSegs;
int argsCount;
if (String.IsNullOrEmpty (path)) {
argSegs = null;
argsCount = 0;
} else {
// quick check
if (String.Compare (url, path, StringComparison.Ordinal) == 0 && url.IndexOf ('{') < 0)
return AddDefaults (ret, defaults);
argSegs = path.Split ('/');
argsCount = argSegs.Length;
if (String.IsNullOrEmpty (argSegs [argsCount - 1]))
argsCount--; // path ends with a trailinig '/'
}
bool haveDefaults = defaults != null && defaults.Count > 0;
if (argsCount == 1 && String.IsNullOrEmpty (argSegs [0]))
argsCount = 0;
if (!haveDefaults && ((haveSegmentWithCatchAll && argsCount < segmentCount) || (!haveSegmentWithCatchAll && argsCount != segmentCount)))
return null;
int i = 0;
foreach (PatternSegment segment in segments) {
if (i >= argsCount)
break;
if (segment.AllLiteral) {
if (String.Compare (argSegs [i], segment.Tokens [0].Name, StringComparison.OrdinalIgnoreCase) != 0)
return null;
i++;
continue;
}
if (!MatchSegment (i, argsCount, argSegs, segment.Tokens, ret))
return null;
i++;
}
// Check the remaining segments, if any, and see if they are required
//
// If a segment has more than one section (i.e. there's at least one
// literal, then it cannot match defaults
//
// All of the remaining segments must have all defaults provided and they
// must not be literals or the match will fail.
if (i < segmentCount) {
if (!haveDefaults)
return null;
for (;i < segmentCount; i++) {
var segment = segments [i];
if (segment.AllLiteral)
return null;
var tokens = segment.Tokens;
if (tokens.Count != 1)
return null;
if (!defaults.ContainsKey (tokens [0].Name))
return null;
}
} else if (!haveSegmentWithCatchAll && argsCount > segmentCount)
return null;
return AddDefaults (ret, defaults);
}