···11+# kvn
22+33+CCSDS Key-Value Notation parser.
44+55+Typed parser for CCSDS Key-Value Notation (KVN), the text format used by OEM, OCM, TDM, ADM, CDM, and other CCSDS navigation data messages. Provides line classification, epoch parsing, block iteration, and low-level parsing primitives.
66+77+## Installation
88+99+```
1010+opam install kvn
1111+```
1212+1313+## Usage
1414+1515+```ocaml
1616+(* Parse a KVN file line by line *)
1717+let st = Kvn.of_string kvn_data in
1818+while not (Kvn.eof st) do
1919+ match Kvn.next st with
2020+ | Some (_n, line) ->
2121+ (match Kvn.classify line with
2222+ | Keyword (k, v) -> Printf.printf "%s = %s\n" k v
2323+ | Data d -> Printf.printf "data: %s\n" d
2424+ | Comment c -> Printf.printf "# %s\n" c
2525+ | Blank -> ())
2626+ | None -> ()
2727+done
2828+2929+(* Iterate over a metadata block *)
3030+Kvn.iter_block ~start:"META_START" ~stop:"META_STOP" st
3131+ ~on_keyword:(fun k v -> Printf.printf "%s = %s\n" k v)
3232+ ~on_data:(fun _n _d -> ())
3333+```
3434+3535+## API Overview
3636+3737+- **`type line`** -- `Keyword of string * string`, `Data of string`, `Comment of string`, `Blank`
3838+- **`classify`** -- Classify a raw KVN line
3939+- **`parse_epoch`** -- Parse CCSDS epoch string to `Ptime.t`
4040+- **`type state`** -- Mutable line-by-line parser state
4141+- **`of_string`**, **`of_channel`** -- Create parser from string or channel
4242+- **`peek`**, **`next`**, **`advance`**, **`skip_blanks`**, **`eof`** -- Parser navigation
4343+- **`iter_block`** -- Iterate over a delimited block (e.g., `META_START`/`META_STOP`)
4444+- **`expect_keyword`** -- Check and consume a specific keyword
4545+- **`parse_float`**, **`parse_int`**, **`parse_floats`**, **`split_data`** -- Value parsing
4646+4747+## License
4848+4949+ISC