private void ConstructFastPathTable() { this.noTemplateHasQueryPart = true; foreach (KeyValuePair <UriTemplate, object> pair in this.templates) { UriTemplate key = pair.Key; if (!UriTemplateHelpers.CanMatchQueryTrivially(key)) { this.noTemplateHasQueryPart = false; } if (key.HasNoVariables && !key.HasWildcard) { if (this.fastPathTable == null) { this.fastPathTable = new Dictionary <string, FastPathInfo>(); } Uri uri = key.BindByPosition(this.originalUncanonicalizedBaseAddress, new string[0]); string uriPath = UriTemplateHelpers.GetUriPath(uri); if (!this.fastPathTable.ContainsKey(uriPath)) { FastPathInfo info = new FastPathInfo(); if (this.ComputeRelativeSegmentsAndLookup(uri, info.RelativePathSegments, info.Candidates)) { info.Freeze(); this.fastPathTable.Add(uriPath, info); } } } } }
static bool AtLeastOneCandidateHasQueryPart(IList <UriTemplateTableMatchCandidate> candidates) { for (int i = 0; i < candidates.Count; i++) { if (!UriTemplateHelpers.CanMatchQueryTrivially(candidates[i].Template)) { return(true); } } return(false); }
void ConstructFastPathTable() { this.noTemplateHasQueryPart = true; foreach (KeyValuePair <UriTemplate, object> kvp in this.templates) { UriTemplate ut = kvp.Key; if (!UriTemplateHelpers.CanMatchQueryTrivially(ut)) { this.noTemplateHasQueryPart = false; } if (ut.HasNoVariables && !ut.HasWildcard) { // eligible for fast path if (this.fastPathTable == null) { this.fastPathTable = new Dictionary <string, FastPathInfo>(); } Uri uri = ut.BindByPosition(this.originalUncanonicalizedBaseAddress); string uriPath = UriTemplateHelpers.GetUriPath(uri); if (this.fastPathTable.ContainsKey(uriPath)) { // nothing to do, we've already seen it } else { FastPathInfo fpInfo = new FastPathInfo(); if (ComputeRelativeSegmentsAndLookup(uri, fpInfo.RelativePathSegments, fpInfo.Candidates)) { fpInfo.Freeze(); this.fastPathTable.Add(uriPath, fpInfo); } } } } }
public Collection <UriTemplateMatch> Match(Uri uri) { if (uri == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("uri"); } if (!uri.IsAbsoluteUri) { return(None()); } this.MakeReadOnly(true); // Matching path : Collection <String> relativeSegments; IList <UriTemplateTableMatchCandidate> candidates; if (!FastComputeRelativeSegmentsAndLookup(uri, out relativeSegments, out candidates)) { return(None()); } // Matching query : NameValueCollection queryParameters = null; if (!this.noTemplateHasQueryPart && AtLeastOneCandidateHasQueryPart(candidates)) { Collection <UriTemplateTableMatchCandidate> nextCandidates = new Collection <UriTemplateTableMatchCandidate>(); Fx.Assert(nextCandidates.Count == 0, "nextCandidates should be empty"); // then deal with query queryParameters = UriTemplateHelpers.ParseQueryString(uri.Query); bool mustBeEspeciallyInteresting = NoCandidateHasQueryLiteralRequirementsAndThereIsAnEmptyFallback(candidates); for (int i = 0; i < candidates.Count; i++) { if (UriTemplateHelpers.CanMatchQueryInterestingly(candidates[i].Template, queryParameters, mustBeEspeciallyInteresting)) { nextCandidates.Add(candidates[i]); } } if (nextCandidates.Count > 1) { Fx.Assert(AllEquivalent(nextCandidates, 0, nextCandidates.Count), "demux algorithm problem, multiple non-equivalent matches"); } if (nextCandidates.Count == 0) { for (int i = 0; i < candidates.Count; i++) { if (UriTemplateHelpers.CanMatchQueryTrivially(candidates[i].Template)) { nextCandidates.Add(candidates[i]); } } } if (nextCandidates.Count == 0) { return(None()); } if (nextCandidates.Count > 1) { Fx.Assert(AllEquivalent(nextCandidates, 0, nextCandidates.Count), "demux algorithm problem, multiple non-equivalent matches"); } candidates = nextCandidates; } // Verifying that we have not broken the allowDuplicates settings because of terminal defaults // This situation can be caused when we are hosting ".../" and ".../{foo=xyz}" in the same // table. They are not equivalent; yet they reside together in the same path partially-equivalent // set. If we hit a uri that ends up in that particular end-of-path set, we want to provide the // user only the 'best' match and not both; thus preventing inconsistancy between the MakeReadonly // settings and the matching results. We will assume that the 'best' matches will be the ones with // the smallest number of segments - this will prefer ".../" over ".../{x=1}[/...]". if (NotAllCandidatesArePathFullyEquivalent(candidates)) { Collection <UriTemplateTableMatchCandidate> nextCandidates = new Collection <UriTemplateTableMatchCandidate>(); int minSegmentsCount = -1; for (int i = 0; i < candidates.Count; i++) { UriTemplateTableMatchCandidate candidate = candidates[i]; if (minSegmentsCount == -1) { minSegmentsCount = candidate.Template.segments.Count; nextCandidates.Add(candidate); } else if (candidate.Template.segments.Count < minSegmentsCount) { minSegmentsCount = candidate.Template.segments.Count; nextCandidates.Clear(); nextCandidates.Add(candidate); } else if (candidate.Template.segments.Count == minSegmentsCount) { nextCandidates.Add(candidate); } } Fx.Assert(minSegmentsCount != -1, "At least the first entry in the list should be kept"); Fx.Assert(nextCandidates.Count >= 1, "At least the first entry in the list should be kept"); Fx.Assert(nextCandidates[0].Template.segments.Count == minSegmentsCount, "Trivial"); candidates = nextCandidates; } // Building the actual result Collection <UriTemplateMatch> actualResults = new Collection <UriTemplateMatch>(); for (int i = 0; i < candidates.Count; i++) { UriTemplateTableMatchCandidate candidate = candidates[i]; UriTemplateMatch match = candidate.Template.CreateUriTemplateMatch(this.originalUncanonicalizedBaseAddress, uri, candidate.Data, candidate.SegmentsCount, relativeSegments, queryParameters); actualResults.Add(match); } return(actualResults); }
public Collection <UriTemplateMatch> Match(Uri uri) { Collection <string> collection; IList <UriTemplateTableMatchCandidate> list; if (uri == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("uri"); } if (!uri.IsAbsoluteUri) { return(None()); } this.MakeReadOnly(true); if (!this.FastComputeRelativeSegmentsAndLookup(uri, out collection, out list)) { return(None()); } NameValueCollection query = null; if (!this.noTemplateHasQueryPart && AtLeastOneCandidateHasQueryPart(list)) { Collection <UriTemplateTableMatchCandidate> collection2 = new Collection <UriTemplateTableMatchCandidate>(); query = UriTemplateHelpers.ParseQueryString(uri.Query); bool mustBeEspeciallyInteresting = NoCandidateHasQueryLiteralRequirementsAndThereIsAnEmptyFallback(list); for (int j = 0; j < list.Count; j++) { UriTemplateTableMatchCandidate candidate3 = list[j]; if (UriTemplateHelpers.CanMatchQueryInterestingly(candidate3.Template, query, mustBeEspeciallyInteresting)) { collection2.Add(list[j]); } } int count = collection2.Count; if (collection2.Count == 0) { for (int k = 0; k < list.Count; k++) { UriTemplateTableMatchCandidate candidate4 = list[k]; if (UriTemplateHelpers.CanMatchQueryTrivially(candidate4.Template)) { collection2.Add(list[k]); } } } if (collection2.Count == 0) { return(None()); } int num6 = collection2.Count; list = collection2; } if (NotAllCandidatesArePathFullyEquivalent(list)) { Collection <UriTemplateTableMatchCandidate> collection3 = new Collection <UriTemplateTableMatchCandidate>(); int num3 = -1; for (int m = 0; m < list.Count; m++) { UriTemplateTableMatchCandidate item = list[m]; if (num3 == -1) { num3 = item.Template.segments.Count; collection3.Add(item); } else if (item.Template.segments.Count < num3) { num3 = item.Template.segments.Count; collection3.Clear(); collection3.Add(item); } else if (item.Template.segments.Count == num3) { collection3.Add(item); } } list = collection3; } Collection <UriTemplateMatch> collection4 = new Collection <UriTemplateMatch>(); for (int i = 0; i < list.Count; i++) { UriTemplateTableMatchCandidate candidate2 = list[i]; UriTemplateMatch match = candidate2.Template.CreateUriTemplateMatch(this.originalUncanonicalizedBaseAddress, uri, candidate2.Data, candidate2.SegmentsCount, collection, query); collection4.Add(match); } return(collection4); }