C# · Case Folding and Normalization

Case Folding and Normalization

using StringZilla; 6.0.0-rc.1 · 91a27bdd

Case folding fills a gap: .NET has no public Unicode case-folding API.

byte[] folded = Sz.CaseFold("Straße"u8);              // -> "strasse"
long position = Sz.UncasedIndexOf(haystack, "WÖRLD"u8, out long matched); // caseless search

using UncasedNeedle needle = new("fox"u8); // prepared once, reusable across haystacks and threads
needle.IndexIn(document, out long matchedLength);

byte[] composed = Sz.Normalize(text, Sz.NormalForm.Nfc); // cf. string.Normalize
int written = Sz.Normalize(text, Sz.NormalForm.Nfc, destination); // allocation-free variant

Sz.Normalize("é"u8, Sz.NormalForm.Nfc);  // "e" + U+0301 -> precomposed "é"
Sz.Normalize("fi"u8, Sz.NormalForm.Nfkc);       // ligature "fi" -> "fi"
Sz.Normalize("Straße"u8, Sz.NormalForm.NfkcCasefold); // NFKC with case folding -> "strasse", for caseless keys

API

ClassUncasedNeedleA case-folding search needle, prepared once to search many haystacks from any thread.3
StringZilla.cs:1351 ↗
class UncasedNeedle

Fills a gap: no .NET caseless UTF-8 search. Dispose to free the native copy.

UncasedNeedleCopies needle into native memory and prepares it for caseless search.
StringZilla.cs:1356 ↗
UncasedNeedle(ReadOnlySpan<byte> needle);
IndexInFirst byte offset of this needle in haystack (caseless), or -1.
StringZilla.cs:1365 ↗
long IndexIn(ReadOnlySpan<byte> haystack, out long matchedLength);
DisposeFrees the native copy of the needle; calling it again does nothing.
StringZilla.cs:1371 ↗
void Dispose();