Files
LuaCsForBarotraumaEP/Libraries/BarotraumaLibs/BarotraumaCore/Utils/Identifier.cs
2024-03-28 18:34:33 +02:00

166 lines
5.7 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace Barotrauma
{
// Identifier struct to eliminate case-sensitive comparisons
public readonly struct Identifier : IComparable, IEquatable<Identifier>
{
public readonly static Identifier Empty = default;
private readonly static int emptyHash = "".GetHashCode(StringComparison.OrdinalIgnoreCase);
private readonly string? value;
private readonly Lazy<int>? hashCode;
public string Value => value ?? "";
public int HashCode => hashCode?.Value ?? emptyHash;
public Identifier(string? str)
{
value = str;
hashCode = new Lazy<int>(() => (str ?? "").GetHashCode(StringComparison.OrdinalIgnoreCase));
}
public bool IsEmpty => Value.IsNullOrEmpty();
public Identifier IfEmpty(in Identifier id)
=> IsEmpty ? id : this;
public Identifier Replace(in Identifier subStr, in Identifier newStr)
=> Replace(subStr.Value, newStr.Value);
public Identifier Replace(string subStr, string newStr)
=> Value.Replace(subStr, newStr, StringComparison.OrdinalIgnoreCase).ToIdentifier();
public Identifier Remove(Identifier subStr)
=> Remove(subStr.Value);
public Identifier Remove(string subStr)
=> Value.Remove(subStr, StringComparison.OrdinalIgnoreCase).ToIdentifier();
public override bool Equals(object? obj) =>
obj switch
{
Identifier i => this == i,
string s => this == s,
_ => base.Equals(obj)
};
public bool StartsWith(string str) => Value.StartsWith(str, StringComparison.OrdinalIgnoreCase);
public bool StartsWith(Identifier id) => StartsWith(id.Value);
public bool EndsWith(string str) => Value.EndsWith(str, StringComparison.OrdinalIgnoreCase);
public bool EndsWith(Identifier id) => EndsWith(id.Value);
public Identifier AppendIfMissing(string suffix)
=> EndsWith(suffix) ? this : $"{this}{suffix}".ToIdentifier();
public Identifier RemoveFromEnd(string suffix)
=> Value.RemoveFromEnd(suffix, StringComparison.OrdinalIgnoreCase).ToIdentifier();
public bool Contains(string str) => Value.Contains(str, StringComparison.OrdinalIgnoreCase);
public bool Contains(in Identifier id) => Contains(id.Value);
public override string ToString() => Value;
public override int GetHashCode() => HashCode;
public int CompareTo(object? obj)
{
return string.Compare(Value, obj?.ToString() ?? "", StringComparison.InvariantCultureIgnoreCase);
}
public bool Equals([AllowNull] Identifier other)
{
return this == other;
}
private static bool StringEquality(string? a, string? b)
=> (a.IsNullOrEmpty() && b.IsNullOrEmpty()) || string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
public static bool operator ==(in Identifier a, in Identifier b) =>
StringEquality(a.Value, b.Value);
public static bool operator !=(in Identifier a, in Identifier b) =>
!(a == b);
public static bool operator ==(in Identifier identifier, string? str) =>
StringEquality(identifier.Value, str);
public static bool operator !=(in Identifier identifier, string? str) =>
!(identifier == str);
public static bool operator ==(string? str, in Identifier identifier) =>
identifier == str;
public static bool operator !=(string? str, in Identifier identifier) =>
!(identifier == str);
public static bool operator ==(in Identifier? a, in Identifier? b) =>
StringEquality(a?.Value, b?.Value);
public static bool operator !=(in Identifier? a, in Identifier? b) =>
!(a == b);
public static bool operator ==(in Identifier? a, string? b) =>
StringEquality(a?.Value, b);
public static bool operator !=(in Identifier? a, string? b) =>
!(a == b);
public static bool operator ==(string str, in Identifier? identifier) =>
identifier == str;
public static bool operator !=(string str, in Identifier? identifier) =>
!(identifier == str);
public int IndexOf(char c) => Value.IndexOf(c);
public Identifier this[Range range] => Value[range].ToIdentifier();
public Char this[int i] => Value[i];
}
public static class IdentifierExtensions
{
public static IEnumerable<Identifier> ToIdentifiers(this IEnumerable<string> strings)
{
foreach (string s in strings)
{
if (string.IsNullOrEmpty(s)) { continue; }
yield return new Identifier(s);
}
}
public static Identifier[] ToIdentifiers(this string[] strings)
=> ((IEnumerable<string>)strings).ToIdentifiers().ToArray();
public static Identifier ToIdentifier(this string? s)
{
return new Identifier(s);
}
public static Identifier ToIdentifier<T>(this T t) where T: notnull
{
return t.ToString().ToIdentifier();
}
public static bool Contains(this ISet<Identifier> set, string identifier)
{
return set.Contains(identifier.ToIdentifier());
}
public static bool ContainsKey<T>(this IReadOnlyDictionary<Identifier, T> dictionary, string key)
{
return dictionary.ContainsKey(key.ToIdentifier());
}
}
}