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);
                 }
             }
         }
     }
 }
Example #2
0
 static bool AtLeastOneCandidateHasQueryPart(IList <UriTemplateTableMatchCandidate> candidates)
 {
     for (int i = 0; i < candidates.Count; i++)
     {
         if (!UriTemplateHelpers.CanMatchQueryTrivially(candidates[i].Template))
         {
             return(true);
         }
     }
     return(false);
 }
Example #3
0
 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);
                 }
             }
         }
     }
 }
Example #4
0
        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);
        }