Incorporate StringSegment from primitives

This commit is contained in:
Ryan Nowak 2015-10-08 12:44:59 -07:00
parent e5f4aa03d2
commit a5727dc932
4 changed files with 44 additions and 178 deletions

View File

@ -1,136 +0,0 @@
// 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;
namespace Microsoft.AspNet.Routing.Internal
{
public struct PathSegment : IEquatable<PathSegment>, IEquatable<string>
{
private readonly string _path;
private readonly int _start;
private readonly int _length;
private string _segment;
public PathSegment(string path, int start, int length)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
if (start < 1 || start >= path.Length)
{
throw new ArgumentOutOfRangeException(nameof(start));
}
if (length < 0 || start + length > path.Length)
{
throw new ArgumentOutOfRangeException(nameof(length));
}
_path = path;
_start = start;
_length = length;
_segment = null;
}
public int Length => _length;
public string GetRemainingPath()
{
if (_path == null)
{
return string.Empty;
}
return _path.Substring(_start);
}
public override bool Equals(object obj)
{
var other = obj as PathSegment?;
if (other == null)
{
return false;
}
else
{
return Equals(other.Value);
}
}
public override int GetHashCode()
{
if (_path == null)
{
return 0;
}
return StringComparer.OrdinalIgnoreCase.GetHashCode(ToString());
}
public override string ToString()
{
if (_path == null)
{
return string.Empty;
}
if (_segment == null)
{
_segment = _path.Substring(_start, _length);
}
return _segment;
}
public bool Equals(PathSegment other)
{
if (_path == null)
{
return other._path == null;
}
if (other._length != _length)
{
return false;
}
return string.Compare(
_path,
_start,
other._path,
other._start,
_length,
StringComparison.OrdinalIgnoreCase) == 0;
}
public bool Equals(string other)
{
if (_path == null)
{
return other == null;
}
if (other.Length != _length)
{
return false;
}
return string.Compare(_path, _start, other, 0, _length, StringComparison.OrdinalIgnoreCase) == 0;
}
public static bool operator ==(PathSegment x, PathSegment y)
{
return x.Equals(y);
}
public static bool operator !=(PathSegment x, PathSegment y)
{
return !x.Equals(y);
}
}
}

View File

@ -6,10 +6,11 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNet.Routing.Internal namespace Microsoft.AspNet.Routing.Internal
{ {
public struct PathTokenizer : IReadOnlyList<PathSegment> public struct PathTokenizer : IReadOnlyList<StringSegment>
{ {
private readonly string _path; private readonly string _path;
private int _count; private int _count;
@ -63,7 +64,7 @@ namespace Microsoft.AspNet.Routing.Internal
} }
} }
public PathSegment this[int index] public StringSegment this[int index]
{ {
get get
{ {
@ -82,7 +83,7 @@ namespace Microsoft.AspNet.Routing.Internal
{ {
if (currentSegmentIndex++ == index) if (currentSegmentIndex++ == index)
{ {
return new PathSegment(_path, currentSegmentStart, delimiterIndex - currentSegmentStart); return new StringSegment(_path, currentSegmentStart, delimiterIndex - currentSegmentStart);
} }
else else
{ {
@ -96,7 +97,7 @@ namespace Microsoft.AspNet.Routing.Internal
Debug.Assert(_path[_path.Length - 1] != '/'); Debug.Assert(_path[_path.Length - 1] != '/');
Debug.Assert(currentSegmentIndex == index); Debug.Assert(currentSegmentIndex == index);
return new PathSegment(_path, currentSegmentStart, _path.Length - currentSegmentStart); return new StringSegment(_path, currentSegmentStart, _path.Length - currentSegmentStart);
} }
} }
@ -105,7 +106,7 @@ namespace Microsoft.AspNet.Routing.Internal
return new Enumerator(this); return new Enumerator(this);
} }
IEnumerator<PathSegment> IEnumerable<PathSegment>.GetEnumerator() IEnumerator<StringSegment> IEnumerable<StringSegment>.GetEnumerator()
{ {
return GetEnumerator(); return GetEnumerator();
} }
@ -115,7 +116,7 @@ namespace Microsoft.AspNet.Routing.Internal
return GetEnumerator(); return GetEnumerator();
} }
public struct Enumerator : IEnumerator<PathSegment> public struct Enumerator : IEnumerator<StringSegment>
{ {
private readonly string _path; private readonly string _path;
@ -130,11 +131,11 @@ namespace Microsoft.AspNet.Routing.Internal
_length = -1; _length = -1;
} }
public PathSegment Current public StringSegment Current
{ {
get get
{ {
return new PathSegment(_path, _index, _length); return new StringSegment(_path, _index, _length);
} }
} }

View File

@ -65,7 +65,7 @@ namespace Microsoft.AspNet.Routing.Template
{ {
// This is a literal segment, so we need to match the text, or the route isn't a match. // This is a literal segment, so we need to match the text, or the route isn't a match.
var part = routeSegment.Parts[0]; var part = routeSegment.Parts[0];
if (!requestSegment.Equals(part.Text)) if (!requestSegment.Equals(part.Text, StringComparison.OrdinalIgnoreCase))
{ {
return null; return null;
} }
@ -149,7 +149,7 @@ namespace Microsoft.AspNet.Routing.Template
{ {
// A catch-all captures til the end of the string. // A catch-all captures til the end of the string.
var part = routeSegment.Parts[0]; var part = routeSegment.Parts[0];
var captured = requestSegment.GetRemainingPath(); var captured = requestSegment.Buffer.Substring(requestSegment.Offset);
if (captured.Length > 0) if (captured.Length > 0)
{ {
values.Add(part.Name, captured); values.Add(part.Name, captured);

View File

@ -2,72 +2,73 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.Extensions.Primitives;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Routing.Internal namespace Microsoft.AspNet.Routing.Internal
{ {
public class PathTokenizerTest public class PathTokenizerTest
{ {
public static TheoryData<string, PathSegment[]> TokenizationData public static TheoryData<string, StringSegment[]> TokenizationData
{ {
get get
{ {
return new TheoryData<string, PathSegment[]> return new TheoryData<string, StringSegment[]>
{ {
{ string.Empty, new PathSegment[] { } }, { string.Empty, new StringSegment[] { } },
{ "/", new PathSegment[] { } }, { "/", new StringSegment[] { } },
{ "//", new PathSegment[] { new PathSegment("//", 1, 0) } }, { "//", new StringSegment[] { new StringSegment("//", 1, 0) } },
{ {
"///", "///",
new PathSegment[] new StringSegment[]
{ {
new PathSegment("///", 1, 0), new StringSegment("///", 1, 0),
new PathSegment("///", 2, 0), new StringSegment("///", 2, 0),
} }
}, },
{ {
"////", "////",
new PathSegment[] new StringSegment[]
{ {
new PathSegment("////", 1, 0), new StringSegment("////", 1, 0),
new PathSegment("////", 2, 0), new StringSegment("////", 2, 0),
new PathSegment("////", 3, 0), new StringSegment("////", 3, 0),
} }
}, },
{ "/zero", new PathSegment[] { new PathSegment("/zero", 1, 4) } }, { "/zero", new StringSegment[] { new StringSegment("/zero", 1, 4) } },
{ "/zero/", new PathSegment[] { new PathSegment("/zero/", 1, 4) } }, { "/zero/", new StringSegment[] { new StringSegment("/zero/", 1, 4) } },
{ {
"/zero/one", "/zero/one",
new PathSegment[] new StringSegment[]
{ {
new PathSegment("/zero/one", 1, 4), new StringSegment("/zero/one", 1, 4),
new PathSegment("/zero/one", 6, 3), new StringSegment("/zero/one", 6, 3),
} }
}, },
{ {
"/zero/one/", "/zero/one/",
new PathSegment[] new StringSegment[]
{ {
new PathSegment("/zero/one/", 1, 4), new StringSegment("/zero/one/", 1, 4),
new PathSegment("/zero/one/", 6, 3), new StringSegment("/zero/one/", 6, 3),
} }
}, },
{ {
"/zero/one/two", "/zero/one/two",
new PathSegment[] new StringSegment[]
{ {
new PathSegment("/zero/one/two", 1, 4), new StringSegment("/zero/one/two", 1, 4),
new PathSegment("/zero/one/two", 6, 3), new StringSegment("/zero/one/two", 6, 3),
new PathSegment("/zero/one/two", 10, 3), new StringSegment("/zero/one/two", 10, 3),
} }
}, },
{ {
"/zero/one/two/", "/zero/one/two/",
new PathSegment[] new StringSegment[]
{ {
new PathSegment("/zero/one/two/", 1, 4), new StringSegment("/zero/one/two/", 1, 4),
new PathSegment("/zero/one/two/", 6, 3), new StringSegment("/zero/one/two/", 6, 3),
new PathSegment("/zero/one/two/", 10, 3), new StringSegment("/zero/one/two/", 10, 3),
} }
}, },
}; };
@ -76,7 +77,7 @@ namespace Microsoft.AspNet.Routing.Internal
[Theory] [Theory]
[MemberData(nameof(TokenizationData))] [MemberData(nameof(TokenizationData))]
public void PathTokenizer_Count(string path, PathSegment[] expectedSegments) public void PathTokenizer_Count(string path, StringSegment[] expectedSegments)
{ {
// Arrange // Arrange
var tokenizer = new PathTokenizer(new PathString(path)); var tokenizer = new PathTokenizer(new PathString(path));
@ -90,7 +91,7 @@ namespace Microsoft.AspNet.Routing.Internal
[Theory] [Theory]
[MemberData(nameof(TokenizationData))] [MemberData(nameof(TokenizationData))]
public void PathTokenizer_Indexer(string path, PathSegment[] expectedSegments) public void PathTokenizer_Indexer(string path, StringSegment[] expectedSegments)
{ {
// Arrange // Arrange
var tokenizer = new PathTokenizer(new PathString(path)); var tokenizer = new PathTokenizer(new PathString(path));
@ -104,13 +105,13 @@ namespace Microsoft.AspNet.Routing.Internal
[Theory] [Theory]
[MemberData(nameof(TokenizationData))] [MemberData(nameof(TokenizationData))]
public void PathTokenizer_Enumerator(string path, PathSegment[] expectedSegments) public void PathTokenizer_Enumerator(string path, StringSegment[] expectedSegments)
{ {
// Arrange // Arrange
var tokenizer = new PathTokenizer(new PathString(path)); var tokenizer = new PathTokenizer(new PathString(path));
// Act & Assert // Act & Assert
Assert.Equal<PathSegment>(expectedSegments, tokenizer); Assert.Equal<StringSegment>(expectedSegments, tokenizer);
} }
} }
} }