Move TreeEnumerator to shared source (#494)
This commit is contained in:
parent
b67c63927c
commit
e2bcefc3d0
|
|
@ -0,0 +1,119 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Dispatcher.Internal;
|
||||
|
||||
#if ROUTING
|
||||
namespace Microsoft.AspNetCore.Routing.Tree
|
||||
#elif DISPATCHER
|
||||
namespace Microsoft.AspNetCore.Dispatcher
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
{
|
||||
internal struct TreeEnumerator : IEnumerator<UrlMatchingNode>
|
||||
{
|
||||
private readonly Stack<UrlMatchingNode> _stack;
|
||||
private readonly PathTokenizer _tokenizer;
|
||||
|
||||
public TreeEnumerator(UrlMatchingNode root, PathTokenizer tokenizer)
|
||||
{
|
||||
_stack = new Stack<UrlMatchingNode>();
|
||||
_tokenizer = tokenizer;
|
||||
Current = null;
|
||||
|
||||
_stack.Push(root);
|
||||
}
|
||||
|
||||
public UrlMatchingNode Current { get; private set; }
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_stack == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (_stack.Count > 0)
|
||||
{
|
||||
var next = _stack.Pop();
|
||||
|
||||
// In case of wild card segment, the request path segment length can be greater
|
||||
// Example:
|
||||
// Template: a/{*path}
|
||||
// Request Url: a/b/c/d
|
||||
if (next.IsCatchAll && next.Matches.Count > 0)
|
||||
{
|
||||
Current = next;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Next template has the same length as the url we are trying to match
|
||||
// The only possible matching segments are either our current matches or
|
||||
// any catch-all segment after this segment in which the catch all is empty.
|
||||
else if (next.Depth >= _tokenizer.Count)
|
||||
{
|
||||
if (next.Matches.Count > 0)
|
||||
{
|
||||
Current = next;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can stop looking as any other child node from this node will be
|
||||
// either a literal, a constrained parameter or a parameter.
|
||||
// (Catch alls and constrained catch alls will show up as candidate matches).
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (next.CatchAlls != null)
|
||||
{
|
||||
_stack.Push(next.CatchAlls);
|
||||
}
|
||||
|
||||
if (next.ConstrainedCatchAlls != null)
|
||||
{
|
||||
_stack.Push(next.ConstrainedCatchAlls);
|
||||
}
|
||||
|
||||
if (next.Parameters != null)
|
||||
{
|
||||
_stack.Push(next.Parameters);
|
||||
}
|
||||
|
||||
if (next.ConstrainedParameters != null)
|
||||
{
|
||||
_stack.Push(next.ConstrainedParameters);
|
||||
}
|
||||
|
||||
if (next.Literals.Count > 0)
|
||||
{
|
||||
Debug.Assert(next.Depth < _tokenizer.Count);
|
||||
if (next.Literals.TryGetValue(_tokenizer[next.Depth].Value, out var node))
|
||||
{
|
||||
_stack.Push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_stack.Clear();
|
||||
Current = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
|
@ -52,7 +51,7 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
var tree = cache.Trees[i];
|
||||
var tokenizer = new PathTokenizer(context.HttpContext.Request.Path);
|
||||
|
||||
var treenumerator = new Treenumerator(tree.Root, tokenizer);
|
||||
var treenumerator = new TreeEnumerator(tree.Root, tokenizer);
|
||||
|
||||
while (treenumerator.MoveNext())
|
||||
{
|
||||
|
|
@ -433,108 +432,6 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
}
|
||||
}
|
||||
|
||||
private struct Treenumerator : IEnumerator<UrlMatchingNode>
|
||||
{
|
||||
private readonly Stack<UrlMatchingNode> _stack;
|
||||
private readonly PathTokenizer _tokenizer;
|
||||
|
||||
public Treenumerator(UrlMatchingNode root, PathTokenizer tokenizer)
|
||||
{
|
||||
_stack = new Stack<UrlMatchingNode>();
|
||||
_tokenizer = tokenizer;
|
||||
Current = null;
|
||||
|
||||
_stack.Push(root);
|
||||
}
|
||||
|
||||
public UrlMatchingNode Current { get; private set; }
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_stack == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (_stack.Count > 0)
|
||||
{
|
||||
var next = _stack.Pop();
|
||||
|
||||
// In case of wild card segment, the request path segment length can be greater
|
||||
// Example:
|
||||
// Template: a/{*path}
|
||||
// Request Url: a/b/c/d
|
||||
if (next.IsCatchAll && next.Matches.Count > 0)
|
||||
{
|
||||
Current = next;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Next template has the same length as the url we are trying to match
|
||||
// The only possible matching segments are either our current matches or
|
||||
// any catch-all segment after this segment in which the catch all is empty.
|
||||
else if (next.Depth >= _tokenizer.Count)
|
||||
{
|
||||
if (next.Matches.Count > 0)
|
||||
{
|
||||
Current = next;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can stop looking as any other child node from this node will be
|
||||
// either a literal, a constrained parameter or a parameter.
|
||||
// (Catch alls and constrained catch alls will show up as candidate matches).
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (next.CatchAlls != null)
|
||||
{
|
||||
_stack.Push(next.CatchAlls);
|
||||
}
|
||||
|
||||
if (next.ConstrainedCatchAlls != null)
|
||||
{
|
||||
_stack.Push(next.ConstrainedCatchAlls);
|
||||
}
|
||||
|
||||
if (next.Parameters != null)
|
||||
{
|
||||
_stack.Push(next.Parameters);
|
||||
}
|
||||
|
||||
if (next.ConstrainedParameters != null)
|
||||
{
|
||||
_stack.Push(next.ConstrainedParameters);
|
||||
}
|
||||
|
||||
if (next.Literals.Count > 0)
|
||||
{
|
||||
Debug.Assert(next.Depth < _tokenizer.Count);
|
||||
if (next.Literals.TryGetValue(_tokenizer[next.Depth].Value, out var node))
|
||||
{
|
||||
_stack.Push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_stack.Clear();
|
||||
Current = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void InitializeServices(IServiceProvider services)
|
||||
{
|
||||
_constraintFactory = services.GetRequiredService<IConstraintFactory>();
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Dispatcher;
|
||||
using Microsoft.AspNetCore.Dispatcher.Internal;
|
||||
|
|
@ -13,7 +10,6 @@ using Microsoft.AspNetCore.Routing.Internal;
|
|||
using Microsoft.AspNetCore.Routing.Logging;
|
||||
using Microsoft.AspNetCore.Routing.Template;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Tree
|
||||
{
|
||||
|
|
@ -217,112 +213,9 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
}
|
||||
}
|
||||
|
||||
private struct TreeEnumerator : IEnumerator<UrlMatchingNode>
|
||||
{
|
||||
private readonly Stack<UrlMatchingNode> _stack;
|
||||
private readonly PathTokenizer _tokenizer;
|
||||
|
||||
public TreeEnumerator(UrlMatchingNode root, PathTokenizer tokenizer)
|
||||
{
|
||||
_stack = new Stack<UrlMatchingNode>();
|
||||
_tokenizer = tokenizer;
|
||||
Current = null;
|
||||
|
||||
_stack.Push(root);
|
||||
}
|
||||
|
||||
public UrlMatchingNode Current { get; private set; }
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_stack == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (_stack.Count > 0)
|
||||
{
|
||||
var next = _stack.Pop();
|
||||
|
||||
// In case of wild card segment, the request path segment length can be greater
|
||||
// Example:
|
||||
// Template: a/{*path}
|
||||
// Request Url: a/b/c/d
|
||||
if (next.IsCatchAll && next.Matches.Count > 0)
|
||||
{
|
||||
Current = next;
|
||||
return true;
|
||||
}
|
||||
// Next template has the same length as the url we are trying to match
|
||||
// The only possible matching segments are either our current matches or
|
||||
// any catch-all segment after this segment in which the catch all is empty.
|
||||
else if (next.Depth == _tokenizer.Count)
|
||||
{
|
||||
if (next.Matches.Count > 0)
|
||||
{
|
||||
Current = next;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can stop looking as any other child node from this node will be
|
||||
// either a literal, a constrained parameter or a parameter.
|
||||
// (Catch alls and constrained catch alls will show up as candidate matches).
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (next.CatchAlls != null)
|
||||
{
|
||||
_stack.Push(next.CatchAlls);
|
||||
}
|
||||
|
||||
if (next.ConstrainedCatchAlls != null)
|
||||
{
|
||||
_stack.Push(next.ConstrainedCatchAlls);
|
||||
}
|
||||
|
||||
if (next.Parameters != null)
|
||||
{
|
||||
_stack.Push(next.Parameters);
|
||||
}
|
||||
|
||||
if (next.ConstrainedParameters != null)
|
||||
{
|
||||
_stack.Push(next.ConstrainedParameters);
|
||||
}
|
||||
|
||||
if (next.Literals.Count > 0)
|
||||
{
|
||||
UrlMatchingNode node;
|
||||
Debug.Assert(next.Depth < _tokenizer.Count);
|
||||
if (next.Literals.TryGetValue(_tokenizer[next.Depth].Value, out node))
|
||||
{
|
||||
_stack.Push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_stack.Clear();
|
||||
Current = null;
|
||||
}
|
||||
}
|
||||
|
||||
private VirtualPathData GetVirtualPathForNamedRoute(VirtualPathContext context)
|
||||
{
|
||||
OutboundMatch match;
|
||||
if (_namedEntries.TryGetValue(context.RouteName, out match))
|
||||
if (_namedEntries.TryGetValue(context.RouteName, out var match))
|
||||
{
|
||||
var path = GenerateVirtualPath(context, match.Entry, match.TemplateBinder);
|
||||
if (path != null)
|
||||
|
|
|
|||
Loading…
Reference in New Issue