# Case Folding and Normalization

> StringZilla for Swift

`utf8UncasedFind(substring:)` performs a case-insensitive search using full Unicode folding and returns a byte-accurate `Range<Index>?`.
The matched length can differ from the needle length, since folding can change byte counts.

```swift
if let range = "Grüße".utf8UncasedFind(substring: "GRÜSSE") {
    print("matched", "Grüße"[range])
}
```

For repeated case-insensitive searches with the same needle, build a `Utf8UncasedNeedle` once and reuse it.
The needle is prepared once and never changes, so one needle can search from many threads at once.
An empty needle matches at the start of any haystack with an empty range.

```swift
let needle = Utf8UncasedNeedle("hello")
let r = needle.findFirst(in: "Say HELLO to the world")
assert(r != nil)
```

`utf8UncasedFoldedBytes()` returns the fully case-folded UTF-8 bytes, which may be longer than the input since `"ß"` folds to `"ss"`.

```swift
let folded = "Straße".utf8UncasedFoldedBytes()  // [UInt8] of "strasse"
assert(folded == Array("strasse".utf8))
```

Normalization is driven by `StringZillaNormalizationForm`, one of `.nfc`, `.nfd`, `.nfkc`, or `.nfkd`.
`utf8Normalized(_:)` returns the normalized UTF-8 bytes and defaults to `.nfc`, `utf8NormalizationViolation(_:)` returns the `Index?` of the first non-conforming byte, and `isUtf8Normalized(_:)` is a convenience `Bool`.

```swift
let nfc = "e\u{0301}".utf8Normalized(.nfc)  // composed "é" bytes
assert("café".isUtf8Normalized(.nfc))       // already composed
let fi = "\u{FB01}".utf8Normalized(.nfkc)   // ligature "ﬁ" → "fi" bytes
assert(fi == Array("fi".utf8))
let bad = "e\u{0301}".utf8NormalizationViolation(.nfc) // Index of the violation
assert(bad != nil)
```

`import StringZilla`

## StringZillaNormalizationForm

Unicode normalization form selector.

```swift
enum StringZillaNormalizationForm
```

- `nfd`
- `nfc`
- `nfkd`
- `nfkc`

Conforms to: `Equatable`, `Hashable`, `RawRepresentable`, `Sendable`

## RawValue

```swift
typealias RawValue = sz_normal_form_t
```

## rawValue

```swift
var rawValue: sz_normal_form_t { get }
```

## init

```swift
init?(rawValue: sz_normal_form_t)
```

## Utf8UncasedNeedle

Uncased search pattern for UTF-8 strings, prepared once for many searches.

```swift
final class Utf8UncasedNeedle
```

It is immutable once built, so one needle can search from many threads at once.

Conforms to: `Sendable`

## init

```swift
init<S>(_ needle: S) where S : StringZillaViewable
```

## findFirst

Finds the first uncased match of the needle, whose byte length folding may change.

```swift
func findFirst<S>(in haystack: S) -> Range<S.Index>? where S : StringZillaViewable
```

