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.Diagnostics;
using Microsoft.AspNet.Http;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNet.Routing.Internal
{
public struct PathTokenizer : IReadOnlyList<PathSegment>
public struct PathTokenizer : IReadOnlyList<StringSegment>
{
private readonly string _path;
private int _count;
@ -63,7 +64,7 @@ namespace Microsoft.AspNet.Routing.Internal
}
}
public PathSegment this[int index]
public StringSegment this[int index]
{
get
{
@ -82,7 +83,7 @@ namespace Microsoft.AspNet.Routing.Internal
{
if (currentSegmentIndex++ == index)
{
return new PathSegment(_path, currentSegmentStart, delimiterIndex - currentSegmentStart);
return new StringSegment(_path, currentSegmentStart, delimiterIndex - currentSegmentStart);
}
else
{
@ -96,7 +97,7 @@ namespace Microsoft.AspNet.Routing.Internal
Debug.Assert(_path[_path.Length - 1] != '/');
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);
}
IEnumerator<PathSegment> IEnumerable<PathSegment>.GetEnumerator()
IEnumerator<StringSegment> IEnumerable<StringSegment>.GetEnumerator()
{
return GetEnumerator();
}
@ -115,7 +116,7 @@ namespace Microsoft.AspNet.Routing.Internal
return GetEnumerator();
}
public struct Enumerator : IEnumerator<PathSegment>
public struct Enumerator : IEnumerator<StringSegment>
{
private readonly string _path;
@ -130,11 +131,11 @@ namespace Microsoft.AspNet.Routing.Internal
_length = -1;
}
public PathSegment Current
public StringSegment Current
{
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.
var part = routeSegment.Parts[0];
if (!requestSegment.Equals(part.Text))
if (!requestSegment.Equals(part.Text, StringComparison.OrdinalIgnoreCase))
{
return null;
}
@ -149,7 +149,7 @@ namespace Microsoft.AspNet.Routing.Template
{
// A catch-all captures til the end of the string.
var part = routeSegment.Parts[0];
var captured = requestSegment.GetRemainingPath();
var captured = requestSegment.Buffer.Substring(requestSegment.Offset);
if (captured.Length > 0)
{
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.
using Microsoft.AspNet.Http;
using Microsoft.Extensions.Primitives;
using Xunit;
namespace Microsoft.AspNet.Routing.Internal
{
public class PathTokenizerTest
{
public static TheoryData<string, PathSegment[]> TokenizationData
public static TheoryData<string, StringSegment[]> TokenizationData
{
get
{
return new TheoryData<string, PathSegment[]>
return new TheoryData<string, StringSegment[]>
{
{ string.Empty, new PathSegment[] { } },
{ "/", new PathSegment[] { } },
{ "//", new PathSegment[] { new PathSegment("//", 1, 0) } },
{ string.Empty, new StringSegment[] { } },
{ "/", new StringSegment[] { } },
{ "//", new StringSegment[] { new StringSegment("//", 1, 0) } },
{
"///",
new PathSegment[]
new StringSegment[]
{
new PathSegment("///", 1, 0),
new PathSegment("///", 2, 0),
new StringSegment("///", 1, 0),
new StringSegment("///", 2, 0),
}
},
{
"////",
new PathSegment[]
new StringSegment[]
{
new PathSegment("////", 1, 0),
new PathSegment("////", 2, 0),
new PathSegment("////", 3, 0),
new StringSegment("////", 1, 0),
new StringSegment("////", 2, 0),
new StringSegment("////", 3, 0),
}
},
{ "/zero", new PathSegment[] { new PathSegment("/zero", 1, 4) } },
{ "/zero/", new PathSegment[] { new PathSegment("/zero/", 1, 4) } },
{ "/zero", new StringSegment[] { new StringSegment("/zero", 1, 4) } },
{ "/zero/", new StringSegment[] { new StringSegment("/zero/", 1, 4) } },
{
"/zero/one",
new PathSegment[]
new StringSegment[]
{
new PathSegment("/zero/one", 1, 4),
new PathSegment("/zero/one", 6, 3),
new StringSegment("/zero/one", 1, 4),
new StringSegment("/zero/one", 6, 3),
}
},
{
"/zero/one/",
new PathSegment[]
new StringSegment[]
{
new PathSegment("/zero/one/", 1, 4),
new PathSegment("/zero/one/", 6, 3),
new StringSegment("/zero/one/", 1, 4),
new StringSegment("/zero/one/", 6, 3),
}
},
{
"/zero/one/two",
new PathSegment[]
new StringSegment[]
{
new PathSegment("/zero/one/two", 1, 4),
new PathSegment("/zero/one/two", 6, 3),
new PathSegment("/zero/one/two", 10, 3),
new StringSegment("/zero/one/two", 1, 4),
new StringSegment("/zero/one/two", 6, 3),
new StringSegment("/zero/one/two", 10, 3),
}
},
{
"/zero/one/two/",
new PathSegment[]
new StringSegment[]
{
new PathSegment("/zero/one/two/", 1, 4),
new PathSegment("/zero/one/two/", 6, 3),
new PathSegment("/zero/one/two/", 10, 3),
new StringSegment("/zero/one/two/", 1, 4),
new StringSegment("/zero/one/two/", 6, 3),
new StringSegment("/zero/one/two/", 10, 3),
}
},
};
@ -76,7 +77,7 @@ namespace Microsoft.AspNet.Routing.Internal
[Theory]
[MemberData(nameof(TokenizationData))]
public void PathTokenizer_Count(string path, PathSegment[] expectedSegments)
public void PathTokenizer_Count(string path, StringSegment[] expectedSegments)
{
// Arrange
var tokenizer = new PathTokenizer(new PathString(path));
@ -90,7 +91,7 @@ namespace Microsoft.AspNet.Routing.Internal
[Theory]
[MemberData(nameof(TokenizationData))]
public void PathTokenizer_Indexer(string path, PathSegment[] expectedSegments)
public void PathTokenizer_Indexer(string path, StringSegment[] expectedSegments)
{
// Arrange
var tokenizer = new PathTokenizer(new PathString(path));
@ -104,13 +105,13 @@ namespace Microsoft.AspNet.Routing.Internal
[Theory]
[MemberData(nameof(TokenizationData))]
public void PathTokenizer_Enumerator(string path, PathSegment[] expectedSegments)
public void PathTokenizer_Enumerator(string path, StringSegment[] expectedSegments)
{
// Arrange
var tokenizer = new PathTokenizer(new PathString(path));
// Act & Assert
Assert.Equal<PathSegment>(expectedSegments, tokenizer);
Assert.Equal<StringSegment>(expectedSegments, tokenizer);
}
}
}