Skip to content

Commit

Permalink
J2N.Text (CharArrayCharSequence + StringBuilderCharSequence + StringC…
Browse files Browse the repository at this point in the history
…harSequence): Optimized and fixed several bugs in the Equals() and CompareTo() overloads. NOTE: These are superfluous - according to the Javadoc for CharSequence, equality checks are not supposed to be relied upon to put arbitrary CharSequences in a hashtable.
  • Loading branch information
NightOwl888 committed Dec 28, 2023
1 parent 04a4170 commit 70eb575
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 106 deletions.
87 changes: 53 additions & 34 deletions src/J2N/Text/CharArrayCharSequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;


namespace J2N.Text
{
using SR = J2N.Resources.Strings;
Expand Down Expand Up @@ -250,18 +249,12 @@ public override string ToString()
/// <returns><c>true</c> if <paramref name="other"/> is equal to the current <see cref="CharArrayCharSequence"/>; otherwise, <c>false</c>.</returns>
public bool Equals(ICharSequence? other)
{
if (this.Value is null)
if (!HasValue)
return other is null || !other.HasValue;
if (other is null || !other.HasValue)
return false;

int len = other.Length;
if (len != this.Value.Length) return false;
for (int i = 0; i < len; i++)
{
if (!this.Value[i].Equals(other[i])) return false;
}
return true;
return CharSequenceComparer.Ordinal.Equals(this, other);
}

/// <summary>
Expand All @@ -271,12 +264,12 @@ public bool Equals(ICharSequence? other)
/// <returns><c>true</c> if <paramref name="other"/> is equal to the current <see cref="CharArrayCharSequence"/>; otherwise, <c>false</c>.</returns>
public bool Equals(CharArrayCharSequence? other)
{
if (this.Value is null)
if (!HasValue)
return other is null || !other.HasValue;
if (other is null || !other.HasValue)
return false;

return this.Equals(other.Value);
return Equals(other.Value);
}

/// <summary>
Expand All @@ -286,12 +279,12 @@ public bool Equals(CharArrayCharSequence? other)
/// <returns><c>true</c> if <paramref name="other"/> is equal to the current <see cref="CharArrayCharSequence"/>; otherwise, <c>false</c>.</returns>
public bool Equals(StringBuilderCharSequence? other)
{
if (this.Value is null)
if (!HasValue)
return other is null || !other.HasValue;
if (other is null || !other.HasValue)
return false;

return this.Equals(other.Value);
return Equals(other.Value);
}

/// <summary>
Expand All @@ -301,12 +294,12 @@ public bool Equals(StringBuilderCharSequence? other)
/// <returns><c>true</c> if <paramref name="other"/> is equal to the current <see cref="CharArrayCharSequence"/>; otherwise, <c>false</c>.</returns>
public bool Equals(StringCharSequence? other)
{
if (this.Value is null)
if (!HasValue)
return other is null || !other.HasValue;
if (other is null || !other.HasValue)
return false;

return this.Equals(other.Value);
return Equals(other.Value);
}

/// <summary>
Expand All @@ -316,16 +309,17 @@ public bool Equals(StringCharSequence? other)
/// <returns><c>true</c> if <paramref name="other"/> is equal to the current <see cref="CharArrayCharSequence"/>; otherwise, <c>false</c>.</returns>
public bool Equals(string? other)
{
if (this.Value is null)
var value = Value;
if (value is null)
return other is null;
if (other is null)
return false;

int len = other.Length;
if (len != this.Value.Length) return false;
int len = Length;
if (len != other.Length) return false;
for (int i = 0; i < len; i++)
{
if (!this.Value[i].Equals(other[i])) return false;
if (!value[i].Equals(other[i])) return false;
}
return true;
}
Expand All @@ -337,19 +331,24 @@ public bool Equals(string? other)
/// <returns><c>true</c> if <paramref name="other"/> is equal to the current <see cref="CharArrayCharSequence"/>; otherwise, <c>false</c>.</returns>
public bool Equals(StringBuilder? other)
{
if (this.Value is null)
var value = Value;
if (value is null)
return other is null;
if (other is null)
return false;

int len = other.Length;
if (len != this.Value.Length) return false;

// NOTE: This benchmarked to be faster than looping through the StringBuilder
string temp = other.ToString();
int len = Length;
if (len != other.Length) return false;
#if FEATURE_STRINGBUILDER_GETCHUNKS
using var otherIndexer = new ValueStringBuilderChunkIndexer(other);
#elif FEATURE_ARRAYPOOL
using var otherIndexer = new ValueStringBuilderArrayPoolIndexer(other);
#else
var otherIndexer = other.ToString(); // .NET 4.0 - don't care to optimize
#endif
for (int i = 0; i < len; i++)
{
if (!this.Value[i].Equals(temp[i])) return false;
if (!value[i].Equals(otherIndexer[i])) return false;
}
return true;
}
Expand All @@ -361,16 +360,17 @@ public bool Equals(StringBuilder? other)
/// <returns><c>true</c> if <paramref name="other"/> is equal to the current <see cref="CharArrayCharSequence"/>; otherwise, <c>false</c>.</returns>
public bool Equals(char[]? other)
{
if (this.Value is null)
var value = Value;
if (value is null)
return other is null;
if (other is null)
return false;

int len = other.Length;
if (len != this.Value.Length) return false;
int len = Length;
if (len != other.Length) return false;
for (int i = 0; i < len; i++)
{
if (!this.Value[i].Equals(other[i])) return false;
if (!value[i].Equals(other[i])) return false;
}
return true;
}
Expand All @@ -392,15 +392,17 @@ public override bool Equals(object? other)
else if (other is char[] otherCharArray)
return Equals(otherCharArray);
else if (other is StringCharSequence otherStringCharSequence)
return Equals(otherStringCharSequence);
return Equals(otherStringCharSequence.Value);
else if (other is CharArrayCharSequence otherCharArrayCharSequence)
return Equals(otherCharArrayCharSequence);
return Equals(otherCharArrayCharSequence.Value);
else if (other is StringBuilderCharSequence otherStringBuilderCharSequence)
return Equals(otherStringBuilderCharSequence);
return Equals(otherStringBuilderCharSequence.Value);
else if (other is StringBuffer stringBuffer)
return Equals(stringBuffer.builder);
else if (other is ICharSequence otherCharSequence)
return Equals(otherCharSequence);

return false;
return Equals(other.ToString());
}

/// <summary>
Expand Down Expand Up @@ -512,6 +514,23 @@ public int CompareTo(object? other)
if (this.Value is null) return (other is null) ? 0 : -1;
if (other is null) return 1;

if (other is string otherString)
return CompareTo(otherString);
else if (other is StringBuilder otherStringBuilder)
return CompareTo(otherStringBuilder);
else if (other is char[] otherCharArray)
return CompareTo(otherCharArray);
else if (other is StringCharSequence otherStringCharSequence)
return CompareTo(otherStringCharSequence.Value);
else if (other is CharArrayCharSequence otherCharArrayCharSequence)
return CompareTo(otherCharArrayCharSequence.Value);
else if (other is StringBuilderCharSequence otherStringBuilderCharSequence)
return CompareTo(otherStringBuilderCharSequence.Value);
else if (other is StringBuffer stringBuffer)
return CompareTo(stringBuffer.builder);
else if (other is ICharSequence otherCharSequence)
return CompareTo(otherCharSequence);

return this.Value.CompareToOrdinal(other.ToString());
}

Expand Down
Loading

0 comments on commit 70eb575

Please sign in to comment.