# DBF

Read DBASE files in Elixir.

At the moment it only supports read.

## Usage

For callback-scoped reads, use `DBF.with_open/2,3`. It closes the DBF and any
memo resource after the callback returns or raises:

```elixir
records =
  DBF.with_open("test/dbf_files/bayarea_zipcodes.dbf", fn db ->
    Enum.to_list(db)
  end)
```

An open database implements `Enumerable`. Each element is a `{status, values}`
tuple whose status is `:record` or `:deleted_record`.

Use `DBF.get/2` for a specific zero-based record index:

```elixir
DBF.with_open("test/dbf_files/bayarea_zipcodes.dbf", fn db ->
  case DBF.get(db, 2) do
    {:record, row} -> IO.inspect(row)
    {:deleted_record, row} -> IO.inspect(row)
    {:error, error} -> IO.warn(Exception.message(error))
  end
end)
```

For streaming, suspended enumeration, or longer-lived access, use
`DBF.open/1,2` and pair every successful open with `DBF.close/1`.

### Exact numeric values

Numeric fields remain floats by default for compatibility. Opt into exact values
to receive integers for scale-zero fields and `Decimal` values for positive
scales:

```elixir
DBF.with_open("table.dbf", [numeric: :exact], fn db ->
  DBF.get(db, 0)
end)
```

Malformed and blank numeric fields remain `nil` under this value policy.

### Text encoding

Known language drivers for Windows-1251 and Windows-1252 are decoded to UTF-8.
Missing or unknown drivers preserve raw bytes by default instead of guessing:

```elixir
DBF.with_open(
  "table.dbf",
  [encoding: :windows_1251, encoding_errors: :strict],
  fn db -> Enum.to_list(db) end
)
```

`encoding` accepts `:auto`, `:raw`, `:windows_1251`, or `:windows_1252`.
`encoding_errors` accepts `:strict`, `:replace`, or `:raw`. The defaults are
`:auto` and `:raw`. The selected policy applies consistently to field names,
character values, and textual DBT memos; binary values are not decoded as text.

## Format compatibility

Support is evidence-based and applies only to the capabilities exercised by the
checked-in fixtures. A recognized version byte alone does not imply support.

- **Verified** — representative headers, records, and applicable memo values are
  covered by local expected values.
- **Partial** — some real files work, but known format features or value semantics
  remain incomplete.
- **Planned** — fixtures and primary references are recorded, but the format is
  not accepted yet.
- **Not planned** — outside the scope of the read-only table reader.

| Format/profile                      | Version bytes                  | Level       | Notes                                                                                                                                                           |
| ----------------------------------- | ------------------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| FoxBase                             | `0x02`                         | Verified    | All fixture records and `C`/unscaled `N` values are checked, including blanks, exact numerics, and deleted-record behavior.                                     |
| dBASE III without memo              | `0x03`                         | Verified    | All zipcode oracle rows, the full schema, legacy value states, exact numerics, Windows-1252 policies, and ambiguous-schema rejection are covered.               |
| dBASE III with DBT memo             | `0x83`                         | Verified    | Representative complete records, schema, exact numerics, logical states, multi-block memos, pointers, encoding overrides, and companion validation are covered. |
| dBASE IV with DBT memo              | `0x8B`                         | Verified    | Representative schema and values, text policies, declared block sizing, multi-block memos, and companion validation are covered.                                |
| FoxPro and Visual FoxPro tables/FPT | `0x30`, `0x31`, `0x32`, `0xF5` | Planned     | Fixtures cover FPT, autoincrement, variable-width fields, null flags, and CP1251 text.                                                                          |
| dBASE Level 7-style tables          | `0x8C` fixture                 | Planned     | Extended header/descriptor and memo support are not implemented.                                                                                                |
| DBF writing                         | —                              | Not planned | Read-only scope.                                                                                                                                                |
| NDX/MDX/CDX/DCX index reading       | —                              | Not planned | Tracked separately from table reading.                                                                                                                          |

See `test/support/fixture_manifest.ex` for per-fixture provenance, encoding,
redistribution status, expected-value source, and normative references.
