# Case Folding and Normalization

> StringZilla for JavaScript

These functions operate on UTF-8 encoded buffers and apply full Unicode case folding.
Each accepts an optional trailing `validate` boolean; when `true`, the input is checked for valid UTF-8 and an error is thrown otherwise.

`utf8UncasedFold` returns a new `Buffer` with the input case-folded.
The result may be longer than the input because some code points expand when folded.

```javascript
assert.strictEqual(sz.utf8UncasedFold(Buffer.from("Straße")).toString(), "strasse");
```

`utf8UncasedFind` performs a case-insensitive substring search.
It returns an object `{ index, length }`, both `BigInt`, where `index` is the matched byte offset, or `-1n` if not found, and `length` is the matched byte length, which can differ from the needle's length under folding.

```javascript
const { index, length } = sz.utf8UncasedFind(Buffer.from("Hello WÖRLD"), Buffer.from("wörld"));
```

The `Utf8UncasedNeedle` class prepares a needle once for repeated searches, amortizing the folding setup.
It keeps its own copy of the needle bytes, so later writes to the source buffer do not affect it.
An empty needle matches at index `0n` with length `0n`, in both forms.
Construct it with the needle buffer and an optional `validate` flag, then call `findIn(haystack, validate?)`, which returns the same `{ index, length }` object.

```javascript
const needle = new sz.Utf8UncasedNeedle(Buffer.from("wörld"));
needle.findIn(Buffer.from("Hello WÖRLD")); // => { index, length }
```

### Unicode Normalization

`utf8Norm` converts a UTF-8 buffer into one of the four Unicode normal forms, passed as a `Utf8NormalForm` constant: `NFD`, `NFC`, `NFKD`, or `NFKC`.
It returns a new `Buffer` and accepts the same optional trailing `validate` boolean as the case-folding functions.

```javascript
const decomposed = Buffer.from("café"); // "e" followed by a combining acute
assert.strictEqual(sz.utf8Norm(decomposed, sz.Utf8NormalForm.NFC).toString(), "café");
```

`utf8FindDenormalized` checks a buffer against a normal form without rewriting it.
It returns the byte offset of the first violation as a `BigInt`, or `-1n` when the input is already normalized.

```javascript
assert.strictEqual(sz.utf8FindDenormalized(Buffer.from("café"), sz.Utf8NormalForm.NFC), -1n);
assert.strictEqual(sz.utf8FindDenormalized(decomposed, sz.Utf8NormalForm.NFC), 3n);
```

`import * as stringzilla from 'stringzilla';`

`import { Utf8UncasedNeedle } from 'stringzilla';`

`import { Utf8UncasedNeedleConstructor } from 'stringzilla';`

## Utf8NormalFormValue

One of the [`Utf8NormalForm`](https://www.unum.cloud/docs/stringzilla/javascript/types.md#Utf8NormalForm) constants: NFD, NFC, NFKD or NFKC.

```typescript
type Utf8NormalFormValue = 0 | 1 | 2 | 3
```

## Utf8UncasedNeedle

Uncased UTF-8 needle prepared once, over its own copy of the bytes, for repeated searches.

```typescript
interface Utf8UncasedNeedle
```

## findIn

Finds the first occurrence of the needle in `haystack` under full Unicode case folding.

```typescript
findIn(haystack: Buffer, validate?: boolean): FindResult
```

- `haystack`: UTF-8 encoded haystack
- `validate`: If true, validates UTF-8 and throws on invalid input

## Utf8UncasedNeedleConstructor

Constructs a [`Utf8UncasedNeedle`](#Utf8UncasedNeedle).

```typescript
interface Utf8UncasedNeedleConstructor
```

## Utf8UncasedNeedleConstructor

```typescript
new Utf8UncasedNeedleConstructor(
    needle: Buffer,
    validate?: boolean,
): Utf8UncasedNeedle
```

- `needle`: UTF-8 encoded needle
- `validate`: If true, validates UTF-8 and throws on invalid input

