Ejemplo n.º 1
0
        static UriTemplate FindAnyUriTemplate(UriTemplateTrieNode node)
        {
            while (node != null)
            {
                if (node.endOfPath.Items.Count > 0)
                {
                    return(node.endOfPath.Items[0].Key);
                }
                if (node.finalVariableSegment.Items.Count > 0)
                {
                    return(node.finalVariableSegment.Items[0].Key);
                }
                if (node.star.Items.Count > 0)
                {
                    return(node.star.Items[0].Key);
                }
                if (node.finalLiteralSegment != null)
                {
                    UriTemplatePathPartiallyEquivalentSet pes =
                        GetAnyDictionaryValue <UriTemplatePathPartiallyEquivalentSet>(node.finalLiteralSegment);
                    Fx.Assert(pes.Items.Count > 0, "Otherwise, why creating the dictionary?");
                    return(pes.Items[0].Key);
                }
                if (node.finalCompoundSegment != null)
                {
                    UriTemplatePathPartiallyEquivalentSet pes = node.finalCompoundSegment.GetAnyValue();
                    Fx.Assert(pes.Items.Count > 0, "Otherwise, why creating the collection?");
                    return(pes.Items[0].Key);
                }

                if (node.nextLiteralSegment != null)
                {
                    UriTemplateTrieLocation location =
                        GetAnyDictionaryValue <UriTemplateTrieLocation>(node.nextLiteralSegment);
                    node = location.node;
                }
                else if (node.nextCompoundSegment != null)
                {
                    UriTemplateTrieLocation location = node.nextCompoundSegment.GetAnyValue();
                    node = location.node;
                }
                else if (node.nextVariableSegment != null)
                {
                    node = node.nextVariableSegment.node;
                }
                else
                {
                    node = null;
                }
            }
            Fx.Assert("How did we got here without finding a UriTemplate earlier?");
            return(null);
        }
Ejemplo n.º 2
0
 UriTemplateTrieNode AddNextVariableSegment()
 {
     if (this.nextVariableSegment != null)
     {
         return(this.nextVariableSegment.node);
     }
     else
     {
         UriTemplateTrieNode newNode = new UriTemplateTrieNode(this.depth + 1);
         newNode.onFailure        = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterVariable);
         this.nextVariableSegment = new UriTemplateTrieLocation(newNode, UriTemplateTrieIntraNodeLocation.BeforeLiteral);
         return(newNode);
     }
 }
        private UriTemplateTrieNode AddNextVariableSegment()
        {
            if (this.nextVariableSegment != null)
            {
                return(this.nextVariableSegment.node);
            }
            UriTemplateTrieNode n = new UriTemplateTrieNode(this.depth + 1)
            {
                onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterVariable)
            };

            this.nextVariableSegment = new UriTemplateTrieLocation(n, UriTemplateTrieIntraNodeLocation.BeforeLiteral);
            return(n);
        }
Ejemplo n.º 4
0
        UriTemplateTrieNode AddNextCompoundSegment(UriTemplateCompoundPathSegment cps)
        {
            Fx.Assert(cps != null, "must be - based on the segment nature");
            if (this.nextCompoundSegment == null)
            {
                this.nextCompoundSegment = new AscendingSortedCompoundSegmentsCollection <UriTemplateTrieLocation>();
            }
            UriTemplateTrieLocation nextLocation = this.nextCompoundSegment.Find(cps);

            if (nextLocation == null)
            {
                UriTemplateTrieNode nextNode = new UriTemplateTrieNode(this.depth + 1);
                nextNode.onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterCompound);
                nextLocation       = new UriTemplateTrieLocation(nextNode, UriTemplateTrieIntraNodeLocation.BeforeLiteral);
                this.nextCompoundSegment.Add(cps, nextLocation);
            }
            return(nextLocation.node);
        }
        private UriTemplateTrieNode AddNextCompoundSegment(UriTemplateCompoundPathSegment cps)
        {
            if (this.nextCompoundSegment == null)
            {
                this.nextCompoundSegment = new AscendingSortedCompoundSegmentsCollection <UriTemplateTrieLocation>();
            }
            UriTemplateTrieLocation location = this.nextCompoundSegment.Find(cps);

            if (location == null)
            {
                UriTemplateTrieNode n = new UriTemplateTrieNode(this.depth + 1)
                {
                    onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterCompound)
                };
                location = new UriTemplateTrieLocation(n, UriTemplateTrieIntraNodeLocation.BeforeLiteral);
                this.nextCompoundSegment.Add(cps, location);
            }
            return(location.node);
        }
Ejemplo n.º 6
0
        static bool GetMatch(UriTemplateTrieLocation location, UriTemplateLiteralPathSegment[] wireData,
                             ICollection <UriTemplateTableMatchCandidate> candidates)
        {
            int initialDepth = location.node.depth;
            SingleLocationOrLocationsSet          nextStep;
            UriTemplatePathPartiallyEquivalentSet answer;

            do
            {
                if (TryMatch(wireData, location, out answer, out nextStep))
                {
                    if (answer != null)
                    {
                        for (int i = 0; i < answer.Items.Count; i++)
                        {
                            candidates.Add(new UriTemplateTableMatchCandidate(answer.Items[i].Key, answer.SegmentsCount,
                                                                              answer.Items[i].Value));
                        }
                    }
                    return(true);
                }
                if (nextStep.IsSingle)
                {
                    location = nextStep.SingleLocation;
                }
                else
                {
                    Fx.Assert(nextStep.LocationsSet != null, "This should be set to a valid value by TryMatch");
                    if (CheckMultipleMatches(nextStep.LocationsSet, wireData, candidates))
                    {
                        return(true);
                    }
                    location = GetFailureLocationFromLocationsSet(nextStep.LocationsSet);
                }
            } while ((location != null) && (location.node.depth >= initialDepth));

            // we walked the whole trie down and found nothing
            return(false);
        }
        private static bool GetMatch(UriTemplateTrieLocation location, UriTemplateLiteralPathSegment[] wireData, ICollection <UriTemplateTableMatchCandidate> candidates)
        {
            int depth = location.node.depth;

            do
            {
                SingleLocationOrLocationsSet          set;
                UriTemplatePathPartiallyEquivalentSet set2;
                if (TryMatch(wireData, location, out set2, out set))
                {
                    if (set2 != null)
                    {
                        for (int i = 0; i < set2.Items.Count; i++)
                        {
                            KeyValuePair <UriTemplate, object> pair  = set2.Items[i];
                            KeyValuePair <UriTemplate, object> pair2 = set2.Items[i];
                            candidates.Add(new UriTemplateTableMatchCandidate(pair.Key, set2.SegmentsCount, pair2.Value));
                        }
                    }
                    return(true);
                }
                if (set.IsSingle)
                {
                    location = set.SingleLocation;
                }
                else
                {
                    if (CheckMultipleMatches(set.LocationsSet, wireData, candidates))
                    {
                        return(true);
                    }
                    location = GetFailureLocationFromLocationsSet(set.LocationsSet);
                }
            }while ((location != null) && (location.node.depth >= depth));
            return(false);
        }
Ejemplo n.º 8
0
 public SingleLocationOrLocationsSet(IList <IList <UriTemplateTrieLocation> > locationsSet)
 {
     this.isSingle       = false;
     this.singleLocation = null;
     this.locationsSet   = locationsSet;
 }
Ejemplo n.º 9
0
 public SingleLocationOrLocationsSet(UriTemplateTrieLocation singleLocation)
 {
     this.isSingle       = true;
     this.singleLocation = singleLocation;
     this.locationsSet   = null;
 }
Ejemplo n.º 10
0
        public bool Match(UriTemplateLiteralPathSegment[] wireData, ICollection <UriTemplateTableMatchCandidate> candidates)
        {
            UriTemplateTrieLocation currentLocation = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.BeforeLiteral);

            return(GetMatch(currentLocation, wireData, candidates));
        }
Ejemplo n.º 11
0
        static void Validate(UriTemplateTrieNode root, bool allowDuplicateEquivalentUriTemplates)
        {
            // walk the entire tree, and ensure that each PathEquivalentSet is ok (no ambiguous queries),
            // verify thst compound segments didn't add potentialy multiple matchs;
            // also Assert various data-structure invariants
            Queue <UriTemplateTrieNode> nodesQueue = new Queue <UriTemplateTrieNode>();

            UriTemplateTrieNode current = root;

            while (true)
            {
                // validate all the PathEquivalentSets that live in this node
                Validate(current.endOfPath, allowDuplicateEquivalentUriTemplates);
                Validate(current.finalVariableSegment, allowDuplicateEquivalentUriTemplates);
                Validate(current.star, allowDuplicateEquivalentUriTemplates);
                if (current.finalLiteralSegment != null)
                {
                    foreach (KeyValuePair <UriTemplateLiteralPathSegment, UriTemplatePathPartiallyEquivalentSet> kvp in current.finalLiteralSegment)
                    {
                        Validate(kvp.Value, allowDuplicateEquivalentUriTemplates);
                    }
                }
                if (current.finalCompoundSegment != null)
                {
                    IList <IList <UriTemplatePathPartiallyEquivalentSet> > pesLists = current.finalCompoundSegment.Values;
                    for (int i = 0; i < pesLists.Count; i++)
                    {
                        if (!allowDuplicateEquivalentUriTemplates && (pesLists[i].Count > 1))
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
                                                                                                                        SR.UTTDuplicate, pesLists[i][0].Items[0].Key.ToString(), pesLists[i][1].Items[0].Key.ToString())));
                        }
                        for (int j = 0; j < pesLists[i].Count; j++)
                        {
                            Validate(pesLists[i][j], allowDuplicateEquivalentUriTemplates);
                        }
                    }
                }
                // deal with children of this node
                if (current.nextLiteralSegment != null)
                {
                    foreach (KeyValuePair <UriTemplateLiteralPathSegment, UriTemplateTrieLocation> kvp in current.nextLiteralSegment)
                    {
                        Fx.Assert(kvp.Value.locationWithin == UriTemplateTrieIntraNodeLocation.BeforeLiteral, "forward-pointers should always point to a BeforeLiteral location");
                        Fx.Assert(kvp.Value.node.depth == current.depth + 1, "kvp.Value.node.depth == current.depth + 1");
                        Fx.Assert(kvp.Value.node.onFailure.node == current, "back pointer should point back to here");
                        Fx.Assert(kvp.Value.node.onFailure.locationWithin == UriTemplateTrieIntraNodeLocation.AfterLiteral, "back-pointer should be AfterLiteral");
                        nodesQueue.Enqueue(kvp.Value.node);
                    }
                }
                if (current.nextCompoundSegment != null)
                {
                    IList <IList <UriTemplateTrieLocation> > locations = current.nextCompoundSegment.Values;
                    for (int i = 0; i < locations.Count; i++)
                    {
                        if (!allowDuplicateEquivalentUriTemplates && (locations[i].Count > 1))
                        {
                            // In the future we might ease up the restrictions and verify if there is realy
                            // a potential multiple match here; for now we are throwing.
                            UriTemplate firstTemplate  = FindAnyUriTemplate(locations[i][0].node);
                            UriTemplate secondTemplate = FindAnyUriTemplate(locations[i][1].node);
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
                                                                                                                        SR.UTTDuplicate, firstTemplate.ToString(), secondTemplate.ToString())));
                        }
                        for (int j = 0; j < locations[i].Count; j++)
                        {
                            UriTemplateTrieLocation location = locations[i][j];
                            Fx.Assert(location.locationWithin == UriTemplateTrieIntraNodeLocation.BeforeLiteral, "forward-pointers should always point to a BeforeLiteral location");
                            Fx.Assert(location.node.depth == current.depth + 1, "kvp.Value.node.depth == current.depth + 1");
                            Fx.Assert(location.node.onFailure.node == current, "back pointer should point back to here");
                            Fx.Assert(location.node.onFailure.locationWithin == UriTemplateTrieIntraNodeLocation.AfterCompound, "back-pointer should be AfterCompound");
                            nodesQueue.Enqueue(location.node);
                        }
                    }
                }
                if (current.nextVariableSegment != null)
                {
                    Fx.Assert(current.nextVariableSegment.locationWithin == UriTemplateTrieIntraNodeLocation.BeforeLiteral, "forward-pointers should always point to a BeforeLiteral location");
                    Fx.Assert(current.nextVariableSegment.node.depth == current.depth + 1, "current.nextVariableSegment.node.depth == current.depth + 1");
                    Fx.Assert(current.nextVariableSegment.node.onFailure.node == current, "back pointer should point back to here");
                    Fx.Assert(current.nextVariableSegment.node.onFailure.locationWithin == UriTemplateTrieIntraNodeLocation.AfterVariable, "back-pointer should be AfterVariable");
                    nodesQueue.Enqueue(current.nextVariableSegment.node);
                }
                // move on to next bit of work
                if (nodesQueue.Count == 0)
                {
                    break;
                }
                current = nodesQueue.Dequeue();
            }
        }
Ejemplo n.º 12
0
        static bool TryMatch(UriTemplateLiteralPathSegment[] wireUriSegments, UriTemplateTrieLocation currentLocation,
                             out UriTemplatePathPartiallyEquivalentSet success, out SingleLocationOrLocationsSet nextStep)
        {
            // if returns true, success is set to answer
            // if returns false, nextStep is set to next place to look
            success  = null;
            nextStep = new SingleLocationOrLocationsSet();

            if (wireUriSegments.Length <= currentLocation.node.depth)
            {
                Fx.Assert(wireUriSegments.Length == 0 || wireUriSegments[wireUriSegments.Length - 1].EndsWithSlash,
                          "we should not have traversed this deep into the trie unless the wire path ended in a slash");

                if (currentLocation.node.endOfPath.Items.Count != 0)
                {
                    // exact match of e.g. "path1/path2/"
                    success = currentLocation.node.endOfPath;
                    return(true);
                }
                else if (currentLocation.node.star.Items.Count != 0)
                {
                    // inexact match of e.g. WIRE("path1/path2/") against TEMPLATE("path1/path2/*")
                    success = currentLocation.node.star;
                    return(true);
                }
                else
                {
                    nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
                    return(false);
                }
            }
            else
            {
                UriTemplateLiteralPathSegment curWireSeg = wireUriSegments[currentLocation.node.depth];
                bool considerLiteral  = false;
                bool considerCompound = false;
                bool considerVariable = false;
                bool considerStar     = false;
                switch (currentLocation.locationWithin)
                {
                case UriTemplateTrieIntraNodeLocation.BeforeLiteral:
                    considerLiteral  = true;
                    considerCompound = true;
                    considerVariable = true;
                    considerStar     = true;
                    break;

                case UriTemplateTrieIntraNodeLocation.AfterLiteral:
                    considerLiteral  = false;
                    considerCompound = true;
                    considerVariable = true;
                    considerStar     = true;
                    break;

                case UriTemplateTrieIntraNodeLocation.AfterCompound:
                    considerLiteral  = false;
                    considerCompound = false;
                    considerVariable = true;
                    considerStar     = true;
                    break;

                case UriTemplateTrieIntraNodeLocation.AfterVariable:
                    considerLiteral  = false;
                    considerCompound = false;
                    considerVariable = false;
                    considerStar     = true;
                    break;

                default:
                    Fx.Assert("bad kind");
                    break;
                }
                if (curWireSeg.EndsWithSlash)
                {
                    IList <IList <UriTemplateTrieLocation> > compoundLocationsSet;

                    if (considerLiteral && currentLocation.node.nextLiteralSegment != null &&
                        currentLocation.node.nextLiteralSegment.ContainsKey(curWireSeg))
                    {
                        nextStep = new SingleLocationOrLocationsSet(currentLocation.node.nextLiteralSegment[curWireSeg]);
                        return(false);
                    }
                    else if (considerCompound && currentLocation.node.nextCompoundSegment != null &&
                             AscendingSortedCompoundSegmentsCollection <UriTemplateTrieLocation> .Lookup(currentLocation.node.nextCompoundSegment, curWireSeg, out compoundLocationsSet))
                    {
                        nextStep = new SingleLocationOrLocationsSet(compoundLocationsSet);
                        return(false);
                    }
                    else if (considerVariable && currentLocation.node.nextVariableSegment != null &&
                             !curWireSeg.IsNullOrEmpty())
                    {
                        nextStep = new SingleLocationOrLocationsSet(currentLocation.node.nextVariableSegment);
                        return(false);
                    }
                    else if (considerStar && currentLocation.node.star.Items.Count != 0)
                    {
                        // matches e.g. WIRE("path1/path2/path3") and TEMPLATE("path1/*")
                        success = currentLocation.node.star;
                        return(true);
                    }
                    else
                    {
                        nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
                        return(false);
                    }
                }
                else
                {
                    IList <IList <UriTemplatePathPartiallyEquivalentSet> > compoundPathEquivalentSets;

                    Fx.Assert(!curWireSeg.EndsWithSlash, "!curWireSeg.EndsWithSlash");
                    Fx.Assert(!curWireSeg.IsNullOrEmpty(), "!curWireSeg.IsNullOrEmpty()");
                    if (considerLiteral && currentLocation.node.finalLiteralSegment != null &&
                        currentLocation.node.finalLiteralSegment.ContainsKey(curWireSeg))
                    {
                        // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/path2")
                        success = currentLocation.node.finalLiteralSegment[curWireSeg];
                        return(true);
                    }
                    else if (considerCompound && currentLocation.node.finalCompoundSegment != null &&
                             AscendingSortedCompoundSegmentsCollection <UriTemplatePathPartiallyEquivalentSet> .Lookup(currentLocation.node.finalCompoundSegment, curWireSeg, out compoundPathEquivalentSets))
                    {
                        // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/p{var}th2")
                        // we should take only the highest order match!
                        Fx.Assert(compoundPathEquivalentSets.Count >= 1, "Lookup is expected to return false otherwise");
                        Fx.Assert(compoundPathEquivalentSets[0].Count > 0, "Find shouldn't return empty sublists");
                        if (compoundPathEquivalentSets[0].Count == 1)
                        {
                            success = compoundPathEquivalentSets[0][0];
                        }
                        else
                        {
                            success = new UriTemplatePathPartiallyEquivalentSet(currentLocation.node.depth + 1);
                            for (int i = 0; i < compoundPathEquivalentSets[0].Count; i++)
                            {
                                success.Items.AddRange(compoundPathEquivalentSets[0][i].Items);
                            }
                        }
                        return(true);
                    }
                    else if (considerVariable && currentLocation.node.finalVariableSegment.Items.Count != 0)
                    {
                        // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/{var}")
                        success = currentLocation.node.finalVariableSegment;
                        return(true);
                    }
                    else if (considerStar && currentLocation.node.star.Items.Count != 0)
                    {
                        // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/*")
                        success = currentLocation.node.star;
                        return(true);
                    }
                    else
                    {
                        nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
                        return(false);
                    }
                }
            }
        }
        private static void Validate(UriTemplateTrieNode root, bool allowDuplicateEquivalentUriTemplates)
        {
            Queue <UriTemplateTrieNode> queue = new Queue <UriTemplateTrieNode>();
            UriTemplateTrieNode         node  = root;

            while (true)
            {
                Validate(node.endOfPath, allowDuplicateEquivalentUriTemplates);
                Validate(node.finalVariableSegment, allowDuplicateEquivalentUriTemplates);
                Validate(node.star, allowDuplicateEquivalentUriTemplates);
                if (node.finalLiteralSegment != null)
                {
                    foreach (KeyValuePair <UriTemplateLiteralPathSegment, UriTemplatePathPartiallyEquivalentSet> pair in node.finalLiteralSegment)
                    {
                        Validate(pair.Value, allowDuplicateEquivalentUriTemplates);
                    }
                }
                if (node.finalCompoundSegment != null)
                {
                    IList <IList <UriTemplatePathPartiallyEquivalentSet> > values = node.finalCompoundSegment.Values;
                    for (int i = 0; i < values.Count; i++)
                    {
                        if (!allowDuplicateEquivalentUriTemplates && (values[i].Count > 1))
                        {
                            object[] args = new object[2];
                            KeyValuePair <UriTemplate, object> pair3 = values[i][0].Items[0];
                            args[0] = pair3.Key.ToString();
                            KeyValuePair <UriTemplate, object> pair4 = values[i][1].Items[0];
                            args[1] = pair4.Key.ToString();
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("UTTDuplicate", args)));
                        }
                        for (int j = 0; j < values[i].Count; j++)
                        {
                            Validate(values[i][j], allowDuplicateEquivalentUriTemplates);
                        }
                    }
                }
                if (node.nextLiteralSegment != null)
                {
                    foreach (KeyValuePair <UriTemplateLiteralPathSegment, UriTemplateTrieLocation> pair2 in node.nextLiteralSegment)
                    {
                        queue.Enqueue(pair2.Value.node);
                    }
                }
                if (node.nextCompoundSegment != null)
                {
                    IList <IList <UriTemplateTrieLocation> > list2 = node.nextCompoundSegment.Values;
                    for (int k = 0; k < list2.Count; k++)
                    {
                        if (!allowDuplicateEquivalentUriTemplates && (list2[k].Count > 1))
                        {
                            UriTemplate template  = FindAnyUriTemplate(list2[k][0].node);
                            UriTemplate template2 = FindAnyUriTemplate(list2[k][1].node);
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("UTTDuplicate", new object[] { template.ToString(), template2.ToString() })));
                        }
                        for (int m = 0; m < list2[k].Count; m++)
                        {
                            UriTemplateTrieLocation location = list2[k][m];
                            queue.Enqueue(location.node);
                        }
                    }
                }
                if (node.nextVariableSegment != null)
                {
                    queue.Enqueue(node.nextVariableSegment.node);
                }
                if (queue.Count == 0)
                {
                    return;
                }
                node = queue.Dequeue();
            }
        }
        private static bool TryMatch(UriTemplateLiteralPathSegment[] wireUriSegments, UriTemplateTrieLocation currentLocation, out UriTemplatePathPartiallyEquivalentSet success, out SingleLocationOrLocationsSet nextStep)
        {
            IList <IList <UriTemplatePathPartiallyEquivalentSet> > list2;

            success  = null;
            nextStep = new SingleLocationOrLocationsSet();
            if (wireUriSegments.Length <= currentLocation.node.depth)
            {
                if (currentLocation.node.endOfPath.Items.Count != 0)
                {
                    success = currentLocation.node.endOfPath;
                    return(true);
                }
                if (currentLocation.node.star.Items.Count != 0)
                {
                    success = currentLocation.node.star;
                    return(true);
                }
                nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
                return(false);
            }
            UriTemplateLiteralPathSegment key = wireUriSegments[currentLocation.node.depth];
            bool flag  = false;
            bool flag2 = false;
            bool flag3 = false;
            bool flag4 = false;

            switch (currentLocation.locationWithin)
            {
            case UriTemplateTrieIntraNodeLocation.BeforeLiteral:
                flag  = true;
                flag2 = true;
                flag3 = true;
                flag4 = true;
                break;

            case UriTemplateTrieIntraNodeLocation.AfterLiteral:
                flag  = false;
                flag2 = true;
                flag3 = true;
                flag4 = true;
                break;

            case UriTemplateTrieIntraNodeLocation.AfterCompound:
                flag  = false;
                flag2 = false;
                flag3 = true;
                flag4 = true;
                break;

            case UriTemplateTrieIntraNodeLocation.AfterVariable:
                flag  = false;
                flag2 = false;
                flag3 = false;
                flag4 = true;
                break;
            }
            if (key.EndsWithSlash)
            {
                IList <IList <UriTemplateTrieLocation> > list;
                if ((flag && (currentLocation.node.nextLiteralSegment != null)) && currentLocation.node.nextLiteralSegment.ContainsKey(key))
                {
                    nextStep = new SingleLocationOrLocationsSet(currentLocation.node.nextLiteralSegment[key]);
                    return(false);
                }
                if ((flag2 && (currentLocation.node.nextCompoundSegment != null)) && AscendingSortedCompoundSegmentsCollection <UriTemplateTrieLocation> .Lookup(currentLocation.node.nextCompoundSegment, key, out list))
                {
                    nextStep = new SingleLocationOrLocationsSet(list);
                    return(false);
                }
                if ((flag3 && (currentLocation.node.nextVariableSegment != null)) && !key.IsNullOrEmpty())
                {
                    nextStep = new SingleLocationOrLocationsSet(currentLocation.node.nextVariableSegment);
                    return(false);
                }
                if (flag4 && (currentLocation.node.star.Items.Count != 0))
                {
                    success = currentLocation.node.star;
                    return(true);
                }
                nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
                return(false);
            }
            if ((flag && (currentLocation.node.finalLiteralSegment != null)) && currentLocation.node.finalLiteralSegment.ContainsKey(key))
            {
                success = currentLocation.node.finalLiteralSegment[key];
                return(true);
            }
            if ((flag2 && (currentLocation.node.finalCompoundSegment != null)) && AscendingSortedCompoundSegmentsCollection <UriTemplatePathPartiallyEquivalentSet> .Lookup(currentLocation.node.finalCompoundSegment, key, out list2))
            {
                if (list2[0].Count == 1)
                {
                    success = list2[0][0];
                }
                else
                {
                    success = new UriTemplatePathPartiallyEquivalentSet(currentLocation.node.depth + 1);
                    for (int i = 0; i < list2[0].Count; i++)
                    {
                        success.Items.AddRange(list2[0][i].Items);
                    }
                }
                return(true);
            }
            if (flag3 && (currentLocation.node.finalVariableSegment.Items.Count != 0))
            {
                success = currentLocation.node.finalVariableSegment;
                return(true);
            }
            if (flag4 && (currentLocation.node.star.Items.Count != 0))
            {
                success = currentLocation.node.star;
                return(true);
            }
            nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure);
            return(false);
        }