parent
ed3ea33918
commit
7a24045953
|
|
@ -0,0 +1,62 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Http.Internal
|
||||||
|
{
|
||||||
|
internal struct HeaderSegment : IEquatable<HeaderSegment>
|
||||||
|
{
|
||||||
|
private readonly StringSegment _formatting;
|
||||||
|
private readonly StringSegment _data;
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
// Initializes a new instance of the <see cref="T:System.Object"/> class.
|
||||||
|
// </summary>
|
||||||
|
public HeaderSegment(StringSegment formatting, StringSegment data)
|
||||||
|
{
|
||||||
|
_formatting = formatting;
|
||||||
|
_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringSegment Formatting
|
||||||
|
{
|
||||||
|
get { return _formatting; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringSegment Data
|
||||||
|
{
|
||||||
|
get { return _data; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(HeaderSegment other)
|
||||||
|
{
|
||||||
|
return _formatting.Equals(other._formatting) && _data.Equals(other._data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj is HeaderSegment && Equals((HeaderSegment)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
return (_formatting.GetHashCode() * 397) ^ _data.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(HeaderSegment left, HeaderSegment right)
|
||||||
|
{
|
||||||
|
return left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(HeaderSegment left, HeaderSegment right)
|
||||||
|
{
|
||||||
|
return !left.Equals(right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,78 +1,10 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
using System;
|
||||||
// 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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.Framework.Internal;
|
|
||||||
using Microsoft.Framework.Primitives;
|
using Microsoft.Framework.Primitives;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Internal
|
namespace Microsoft.AspNet.Http.Internal
|
||||||
{
|
{
|
||||||
internal struct HeaderSegment : IEquatable<HeaderSegment>
|
|
||||||
{
|
|
||||||
private readonly StringSegment _formatting;
|
|
||||||
private readonly StringSegment _data;
|
|
||||||
|
|
||||||
// <summary>
|
|
||||||
// Initializes a new instance of the <see cref="T:System.Object"/> class.
|
|
||||||
// </summary>
|
|
||||||
public HeaderSegment(StringSegment formatting, StringSegment data)
|
|
||||||
{
|
|
||||||
_formatting = formatting;
|
|
||||||
_data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringSegment Formatting
|
|
||||||
{
|
|
||||||
get { return _formatting; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringSegment Data
|
|
||||||
{
|
|
||||||
get { return _data; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Equality members
|
|
||||||
|
|
||||||
public bool Equals(HeaderSegment other)
|
|
||||||
{
|
|
||||||
return _formatting.Equals(other._formatting) && _data.Equals(other._data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(null, obj))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj is HeaderSegment && Equals((HeaderSegment)obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
unchecked
|
|
||||||
{
|
|
||||||
return (_formatting.GetHashCode() * 397) ^ _data.GetHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(HeaderSegment left, HeaderSegment right)
|
|
||||||
{
|
|
||||||
return left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(HeaderSegment left, HeaderSegment right)
|
|
||||||
{
|
|
||||||
return !left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
[System.CodeDom.Compiler.GeneratedCode("App_Packages", "")]
|
|
||||||
internal struct HeaderSegmentCollection : IEnumerable<HeaderSegment>, IEquatable<HeaderSegmentCollection>
|
internal struct HeaderSegmentCollection : IEnumerable<HeaderSegment>, IEquatable<HeaderSegmentCollection>
|
||||||
{
|
{
|
||||||
private readonly StringValues _headers;
|
private readonly StringValues _headers;
|
||||||
|
|
@ -82,8 +14,6 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
_headers = headers;
|
_headers = headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Equality members
|
|
||||||
|
|
||||||
public bool Equals(HeaderSegmentCollection other)
|
public bool Equals(HeaderSegmentCollection other)
|
||||||
{
|
{
|
||||||
return Equals(_headers, other._headers);
|
return Equals(_headers, other._headers);
|
||||||
|
|
@ -114,8 +44,6 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
return !left.Equals(right);
|
return !left.Equals(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public Enumerator GetEnumerator()
|
public Enumerator GetEnumerator()
|
||||||
{
|
{
|
||||||
return new Enumerator(_headers);
|
return new Enumerator(_headers);
|
||||||
|
|
@ -360,259 +288,4 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.CodeDom.Compiler.GeneratedCode("App_Packages", "")]
|
|
||||||
internal struct StringSegment : IEquatable<StringSegment>
|
|
||||||
{
|
|
||||||
private readonly string _buffer;
|
|
||||||
private readonly int _offset;
|
|
||||||
private readonly int _count;
|
|
||||||
|
|
||||||
// <summary>
|
|
||||||
// Initializes a new instance of the <see cref="T:System.Object"/> class.
|
|
||||||
// </summary>
|
|
||||||
public StringSegment(string buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
_buffer = buffer;
|
|
||||||
_offset = offset;
|
|
||||||
_count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Buffer
|
|
||||||
{
|
|
||||||
get { return _buffer; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Offset
|
|
||||||
{
|
|
||||||
get { return _offset; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Count
|
|
||||||
{
|
|
||||||
get { return _count; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Value
|
|
||||||
{
|
|
||||||
get { return _offset == -1 ? null : _buffer.Substring(_offset, _count); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasValue
|
|
||||||
{
|
|
||||||
get { return _offset != -1 && _count != 0 && _buffer != null; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Equality members
|
|
||||||
|
|
||||||
public bool Equals(StringSegment other)
|
|
||||||
{
|
|
||||||
return string.Equals(_buffer, other._buffer) && _offset == other._offset && _count == other._count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(null, obj))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj is StringSegment && Equals((StringSegment)obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
unchecked
|
|
||||||
{
|
|
||||||
int hashCode = (_buffer != null ? _buffer.GetHashCode() : 0);
|
|
||||||
hashCode = (hashCode * 397) ^ _offset;
|
|
||||||
hashCode = (hashCode * 397) ^ _count;
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(StringSegment left, StringSegment right)
|
|
||||||
{
|
|
||||||
return left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(StringSegment left, StringSegment right)
|
|
||||||
{
|
|
||||||
return !left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public bool StartsWith([NotNull] string text, StringComparison comparisonType)
|
|
||||||
{
|
|
||||||
int textLength = text.Length;
|
|
||||||
if (!HasValue || _count < textLength)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool EndsWith([NotNull] string text, StringComparison comparisonType)
|
|
||||||
{
|
|
||||||
int textLength = text.Length;
|
|
||||||
if (!HasValue || _count < textLength)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Compare(_buffer, _offset + _count - textLength, text, 0, textLength, comparisonType) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals([NotNull] string text, StringComparison comparisonType)
|
|
||||||
{
|
|
||||||
int textLength = text.Length;
|
|
||||||
if (!HasValue || _count != textLength)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Substring(int offset, int length)
|
|
||||||
{
|
|
||||||
return _buffer.Substring(_offset + offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringSegment Subsegment(int offset, int length)
|
|
||||||
{
|
|
||||||
return new StringSegment(_buffer, _offset + offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Value ?? string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class ParsingHelpers
|
|
||||||
{
|
|
||||||
public static StringValues GetHeader(IDictionary<string, StringValues> headers, string key)
|
|
||||||
{
|
|
||||||
StringValues value;
|
|
||||||
return headers.TryGetValue(key, out value) ? value : StringValues.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static StringValues GetHeaderSplit(IDictionary<string, StringValues> headers, string key)
|
|
||||||
{
|
|
||||||
var values = GetHeaderUnmodified(headers, key);
|
|
||||||
return new StringValues(GetHeaderSplitImplementation(values).ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<string> GetHeaderSplitImplementation(StringValues values)
|
|
||||||
{
|
|
||||||
foreach (var segment in new HeaderSegmentCollection(values))
|
|
||||||
{
|
|
||||||
if (segment.Data.HasValue)
|
|
||||||
{
|
|
||||||
yield return DeQuote(segment.Data.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static StringValues GetHeaderUnmodified([NotNull] IDictionary<string, StringValues> headers, string key)
|
|
||||||
{
|
|
||||||
StringValues values;
|
|
||||||
return headers.TryGetValue(key, out values) ? values : StringValues.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetHeaderJoined([NotNull] IDictionary<string, StringValues> headers, [NotNull] string key, StringValues value)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(key))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(key));
|
|
||||||
}
|
|
||||||
if (StringValues.IsNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
headers.Remove(key);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
headers[key] = string.Join(",", value.Select(QuoteIfNeeded));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quote items that contain comas and are not already quoted.
|
|
||||||
private static string QuoteIfNeeded(string value)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(value))
|
|
||||||
{
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
else if (value.Contains(','))
|
|
||||||
{
|
|
||||||
if (value[0] != '"' || value[value.Length - 1] != '"')
|
|
||||||
{
|
|
||||||
value = '"' + value + '"';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string DeQuote(string value)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(value))
|
|
||||||
{
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
else if (value.Length > 1 && value[0] == '"' && value[value.Length - 1] == '"')
|
|
||||||
{
|
|
||||||
value = value.Substring(1, value.Length - 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetHeaderUnmodified([NotNull] IDictionary<string, StringValues> headers, [NotNull] string key, StringValues? values)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(key))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(key));
|
|
||||||
}
|
|
||||||
if (!values.HasValue || StringValues.IsNullOrEmpty(values.Value))
|
|
||||||
{
|
|
||||||
headers.Remove(key);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
headers[key] = values.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AppendHeaderJoined([NotNull] IDictionary<string, StringValues> headers, [NotNull] string key, params string[] values)
|
|
||||||
{
|
|
||||||
if (values == null || values.Length == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string existing = GetHeader(headers, key);
|
|
||||||
if (existing == null)
|
|
||||||
{
|
|
||||||
SetHeaderJoined(headers, key, values);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
headers[key] = existing + "," + string.Join(",", values.Select(value => QuoteIfNeeded(value)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AppendHeaderUnmodified([NotNull] IDictionary<string, StringValues> headers, [NotNull] string key, StringValues values)
|
|
||||||
{
|
|
||||||
if (values.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var existing = GetHeaderUnmodified(headers, key);
|
|
||||||
SetHeaderUnmodified(headers, key, StringValues.Concat(existing, values));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
// 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;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Framework.Internal;
|
||||||
|
using Microsoft.Framework.Primitives;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Http.Internal
|
||||||
|
{
|
||||||
|
internal static class ParsingHelpers
|
||||||
|
{
|
||||||
|
public static StringValues GetHeader(IDictionary<string, StringValues> headers, string key)
|
||||||
|
{
|
||||||
|
StringValues value;
|
||||||
|
return headers.TryGetValue(key, out value) ? value : StringValues.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StringValues GetHeaderSplit(IDictionary<string, StringValues> headers, string key)
|
||||||
|
{
|
||||||
|
var values = GetHeaderUnmodified(headers, key);
|
||||||
|
return new StringValues(GetHeaderSplitImplementation(values).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> GetHeaderSplitImplementation(StringValues values)
|
||||||
|
{
|
||||||
|
foreach (var segment in new HeaderSegmentCollection(values))
|
||||||
|
{
|
||||||
|
if (segment.Data.HasValue)
|
||||||
|
{
|
||||||
|
yield return DeQuote(segment.Data.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StringValues GetHeaderUnmodified([NotNull] IDictionary<string, StringValues> headers, string key)
|
||||||
|
{
|
||||||
|
StringValues values;
|
||||||
|
return headers.TryGetValue(key, out values) ? values : StringValues.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetHeaderJoined([NotNull] IDictionary<string, StringValues> headers, [NotNull] string key, StringValues value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(key))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(key));
|
||||||
|
}
|
||||||
|
if (StringValues.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
headers.Remove(key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
headers[key] = string.Join(",", value.Select(QuoteIfNeeded));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quote items that contain comas and are not already quoted.
|
||||||
|
private static string QuoteIfNeeded(string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
else if (value.Contains(','))
|
||||||
|
{
|
||||||
|
if (value[0] != '"' || value[value.Length - 1] != '"')
|
||||||
|
{
|
||||||
|
value = '"' + value + '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string DeQuote(string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
else if (value.Length > 1 && value[0] == '"' && value[value.Length - 1] == '"')
|
||||||
|
{
|
||||||
|
value = value.Substring(1, value.Length - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetHeaderUnmodified([NotNull] IDictionary<string, StringValues> headers, [NotNull] string key, StringValues? values)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(key))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(key));
|
||||||
|
}
|
||||||
|
if (!values.HasValue || StringValues.IsNullOrEmpty(values.Value))
|
||||||
|
{
|
||||||
|
headers.Remove(key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
headers[key] = values.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AppendHeaderJoined([NotNull] IDictionary<string, StringValues> headers, [NotNull] string key, params string[] values)
|
||||||
|
{
|
||||||
|
if (values == null || values.Length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string existing = GetHeader(headers, key);
|
||||||
|
if (existing == null)
|
||||||
|
{
|
||||||
|
SetHeaderJoined(headers, key, values);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
headers[key] = existing + "," + string.Join(",", values.Select(value => QuoteIfNeeded(value)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AppendHeaderUnmodified([NotNull] IDictionary<string, StringValues> headers, [NotNull] string key, StringValues values)
|
||||||
|
{
|
||||||
|
if (values.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = GetHeaderUnmodified(headers, key);
|
||||||
|
SetHeaderUnmodified(headers, key, StringValues.Concat(existing, values));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.Framework.Internal;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Http.Internal
|
||||||
|
{
|
||||||
|
internal struct StringSegment : IEquatable<StringSegment>
|
||||||
|
{
|
||||||
|
private readonly string _buffer;
|
||||||
|
private readonly int _offset;
|
||||||
|
private readonly int _count;
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
// Initializes a new instance of the <see cref="T:System.Object"/> class.
|
||||||
|
// </summary>
|
||||||
|
public StringSegment(string buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
_buffer = buffer;
|
||||||
|
_offset = offset;
|
||||||
|
_count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Buffer
|
||||||
|
{
|
||||||
|
get { return _buffer; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Offset
|
||||||
|
{
|
||||||
|
get { return _offset; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return _count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Value
|
||||||
|
{
|
||||||
|
get { return _offset == -1 ? null : _buffer.Substring(_offset, _count); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasValue
|
||||||
|
{
|
||||||
|
get { return _offset != -1 && _count != 0 && _buffer != null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(StringSegment other)
|
||||||
|
{
|
||||||
|
return string.Equals(_buffer, other._buffer) && _offset == other._offset && _count == other._count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj is StringSegment && Equals((StringSegment)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hashCode = (_buffer != null ? _buffer.GetHashCode() : 0);
|
||||||
|
hashCode = (hashCode * 397) ^ _offset;
|
||||||
|
hashCode = (hashCode * 397) ^ _count;
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(StringSegment left, StringSegment right)
|
||||||
|
{
|
||||||
|
return left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(StringSegment left, StringSegment right)
|
||||||
|
{
|
||||||
|
return !left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StartsWith([NotNull] string text, StringComparison comparisonType)
|
||||||
|
{
|
||||||
|
int textLength = text.Length;
|
||||||
|
if (!HasValue || _count < textLength)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool EndsWith([NotNull] string text, StringComparison comparisonType)
|
||||||
|
{
|
||||||
|
int textLength = text.Length;
|
||||||
|
if (!HasValue || _count < textLength)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Compare(_buffer, _offset + _count - textLength, text, 0, textLength, comparisonType) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals([NotNull] string text, StringComparison comparisonType)
|
||||||
|
{
|
||||||
|
int textLength = text.Length;
|
||||||
|
if (!HasValue || _count != textLength)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Substring(int offset, int length)
|
||||||
|
{
|
||||||
|
return _buffer.Substring(_offset + offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringSegment Subsegment(int offset, int length)
|
||||||
|
{
|
||||||
|
return new StringSegment(_buffer, _offset + offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Value ?? string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue