Skip to content

Commit d452d48

Browse files
3.2.2 update
Added StringComparable.
1 parent e593db5 commit d452d48

3 files changed

Lines changed: 107 additions & 1 deletion

File tree

Source/Open.Text.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<RepositoryUrl>https://github.com/Open-NET-Libraries/Open.Text</RepositoryUrl>
1818
<RepositoryType>git</RepositoryType>
1919
<PackageTags>dotnet, dotnetcore, string, span, readonlyspan, text, format, split, trim, equals, trimmed equals, first, last, preceding, following, stringbuilder, extensions</PackageTags>
20-
<Version>3.2.1</Version>
20+
<Version>3.2.2</Version>
2121
<PackageReleaseNotes></PackageReleaseNotes>
2222
<PackageLicenseExpression>MIT</PackageLicenseExpression>
2323
<PublishRepositoryUrl>true</PublishRepositoryUrl>

Source/StringComparable.cs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Open.Text
5+
{
6+
public struct StringComparable : IEquatable<StringComparable>, IEquatable<string>
7+
{
8+
public StringComparable(string source, StringComparison type)
9+
{
10+
Source = source ?? throw new ArgumentNullException(nameof(source));
11+
Type = type;
12+
}
13+
14+
public string Source { get; }
15+
public StringComparison Type { get; }
16+
17+
public int Length => Source.Length;
18+
19+
public bool Equals(string? other)
20+
=> Source.Equals(other, Type);
21+
22+
public bool Equals(ReadOnlySpan<char> other)
23+
=> Source.Equals(other, Type);
24+
25+
public bool Equals(StringComparable other)
26+
=> Source.Equals(other.Source, Type);
27+
28+
public override bool Equals(object obj)
29+
{
30+
return obj switch
31+
{
32+
StringComparable sc => Equals(sc),
33+
string s => Equals(s),
34+
_ => false
35+
};
36+
}
37+
38+
public override int GetHashCode()
39+
{
40+
int hashCode = 141257509;
41+
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Source);
42+
hashCode = hashCode * -1521134295 + Type.GetHashCode();
43+
return hashCode;
44+
}
45+
46+
public static bool operator ==(StringComparable a, StringComparable? b) => a.Equals(b);
47+
public static bool operator !=(StringComparable a, StringComparable? b) => !a.Equals(b);
48+
49+
public static bool operator ==(StringComparable a, string? b) => a.Equals(b);
50+
public static bool operator !=(StringComparable a, string? b) => !a.Equals(b);
51+
52+
public static bool operator ==(StringComparable a, ReadOnlySpan<char> b) => a.Equals(b);
53+
public static bool operator !=(StringComparable a, ReadOnlySpan<char> b) => !a.Equals(b);
54+
55+
}
56+
57+
public static class StringComparableExtensions
58+
{
59+
/// <inheritdoc cref="AsCaseInsensitive(string)"/>
60+
/// <summary>
61+
/// Prepares a string for a specific StringComparison.
62+
/// </summary>
63+
/// <param name="type">The type of StrinComparison to perform.</param>
64+
public static StringComparable AsComparable(this string source, StringComparison type)
65+
=> new(source, type);
66+
67+
/// <summary>
68+
/// Prepares a string to be case insensitive when comparing equality.
69+
/// </summary>
70+
/// <param name="source">The source string.</param>
71+
/// <returns>A StringComparable that can be compared (== or !=) against other StringComparables, strings, and ReadOnlySpan&lt;char&gt;.</returns>
72+
public static StringComparable AsCaseInsensitive(this string source)
73+
=> new(source, StringComparison.OrdinalIgnoreCase);
74+
75+
/// <inheritdoc cref="AsCaseInsensitive(string)"/>
76+
/// <summary>
77+
/// Prepares a string to be invariant culture and case insensitive when comparing equality.
78+
/// </summary>
79+
public static StringComparable AsCaseInsensitiveInvariantCulture(this string source)
80+
=> new(source, StringComparison.InvariantCultureIgnoreCase);
81+
82+
/// <inheritdoc cref="AsCaseInsensitive(string)"/>
83+
/// <summary>
84+
/// Prepares a string to be invariant culture and case insensitive when comparing equality.
85+
/// </summary>
86+
public static StringComparable AsCaseInsensitiveCurrentCulture(this string source)
87+
=> new(source, StringComparison.CurrentCultureIgnoreCase);
88+
89+
/// <inheritdoc cref="AsCaseInsensitive(string)"/>
90+
/// <summary>
91+
/// Prepares a string to be current culture and case sensitive when comparing equality.
92+
/// </summary>
93+
public static StringComparable AsCurrentCulture(this string source)
94+
=> new(source, StringComparison.CurrentCulture);
95+
96+
/// <inheritdoc cref="AsCaseInsensitive(string)"/>
97+
/// <summary>
98+
/// Prepares a string to be invariant culture and case sensitive when comparing equality.
99+
/// </summary>
100+
public static StringComparable AsInvariantCulture(this string source)
101+
=> new(source, StringComparison.InvariantCulture);
102+
103+
}
104+
}

Tests/EqualityTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public void EqualsSpan(string value, StringComparison comparison = StringCompari
3131
{
3232
var roSpan = value.AsSpan();
3333
var span = roSpan.ToArray().AsSpan();
34+
Assert.True(value.AsComparable(comparison) == roSpan);
3435
Assert.True(roSpan.Equals(value, comparison));
3536
Assert.True(value.TrimmedEquals(value, comparison));
3637
Assert.True(value.TrimmedEquals(roSpan, comparison));
@@ -60,6 +61,7 @@ public void NotEqualsSpan(string value, string? other, StringComparison comparis
6061
var roSpan = value.AsSpan();
6162
var span = roSpan.ToArray().AsSpan();
6263
Assert.False(roSpan.Equals(other, comparison));
64+
Assert.True(value.AsComparable(comparison) != other);
6365
if (other is not null)
6466
{
6567
var oRoSpan = other.AsSpan();

0 commit comments

Comments
 (0)