4 using System.Collections.Generic;
5 using System.Diagnostics.CodeAnalysis;
11 public readonly
struct Identifier : IComparable, IEquatable<Identifier>
15 private readonly
static int emptyHash =
"".
GetHashCode(StringComparison.OrdinalIgnoreCase);
17 private readonly
string? value;
18 private readonly Lazy<int>? hashCode;
20 public string Value => value ??
"";
21 public int HashCode => hashCode?.Value ?? emptyHash;
26 hashCode =
new Lazy<int>(() => (str ??
"").
GetHashCode(StringComparison.OrdinalIgnoreCase));
35 =>
Replace(subStr.Value ??
"", newStr.Value ??
"");
38 => (
Value?.Replace(subStr, newStr, StringComparison.OrdinalIgnoreCase)).ToIdentifier();
41 =>
Remove(subStr.Value ??
"");
44 => (
Value?.Remove(subStr, StringComparison.OrdinalIgnoreCase)).ToIdentifier();
46 public override bool Equals(
object? obj) =>
50 string s =>
this == s,
54 public bool StartsWith(
string str) =>
Value?.StartsWith(str, StringComparison.OrdinalIgnoreCase) ?? str.IsNullOrEmpty();
58 public bool EndsWith(
string str) =>
Value?.EndsWith(str, StringComparison.OrdinalIgnoreCase) ?? str.IsNullOrEmpty();
63 =>
EndsWith(suffix) ? this : $
"{this}{suffix}".ToIdentifier();
66 => (
Value?.RemoveFromEnd(suffix, StringComparison.OrdinalIgnoreCase)).ToIdentifier();
68 public bool Contains(
string str) =>
Value?.Contains(str, StringComparison.OrdinalIgnoreCase) ?? str.IsNullOrEmpty();
78 return string.Compare(
Value, obj?.
ToString() ??
"", StringComparison.InvariantCultureIgnoreCase);
86 private static bool StringEquality(
string? a,
string? b)
87 => (a.IsNullOrEmpty() && b.IsNullOrEmpty()) ||
string.
Equals(a, b, StringComparison.OrdinalIgnoreCase);
90 StringEquality(a.Value, b.Value);
96 StringEquality(identifier.Value, str);
105 !(identifier == str);
114 StringEquality(a?.
Value, b);
123 !(identifier == str);
129 internal int IndexOf(
char c) =>
Value.IndexOf(c);
132 internal Char
this[
int i] =>
Value[i];
135 public static class IdentifierExtensions
137 public static IEnumerable<Identifier> ToIdentifiers(
this IEnumerable<string> strings)
139 foreach (
string s
in strings)
141 if (
string.IsNullOrEmpty(s)) {
continue; }
142 yield
return new Identifier(s);
146 public static Identifier[] ToIdentifiers(
this string[] strings)
147 => ((IEnumerable<string>)strings).ToIdentifiers().ToArray();
149 public static Identifier ToIdentifier(
this string? s)
151 return new Identifier(s);
154 public static Identifier ToIdentifier<T>(
this T t) where T: notnull
156 return t.ToString().ToIdentifier();
159 public static bool Contains(
this ISet<Identifier>
set,
string identifier)
161 return set.Contains(identifier.ToIdentifier());
164 public static bool ContainsKey<T>(
this IReadOnlyDictionary<Identifier, T> dictionary,
string key)
166 return dictionary.ContainsKey(key.ToIdentifier());
bool StartsWith(string str)
bool Contains(in Identifier id)
bool EndsWith(Identifier id)
bool Equals([AllowNull] Identifier other)
override bool Equals(object? obj)
Identifier IfEmpty(in Identifier id)
Identifier RemoveFromEnd(string suffix)
Identifier AppendIfMissing(string suffix)
bool Contains(string str)
static bool operator!=(in Identifier a, in Identifier b)
Identifier Replace(in Identifier subStr, in Identifier newStr)
override string ToString()
bool StartsWith(Identifier id)
override int GetHashCode()
Identifier Replace(string subStr, string newStr)
static bool operator==(in Identifier a, in Identifier b)
int CompareTo(object? obj)
static readonly Identifier Empty
Identifier Remove(string subStr)
bool EndsWith(string str)
Identifier Remove(Identifier subStr)
An inclusive range, i.e. [Start, End] where Start <= End