LEPTRIS

libteptris v0.1.27 — TOML from C

A TOML 1.0/1.1 parser and writer in pure C99 — zero required runtime dependencies, a stable ABI, opaque handles. The grammar is the TOML 1.1 draft as a strict superset of 1.0; the emitter is canonical: parse(emit(d)) == d, and emit is idempotent.

Build and test

from a checkout
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release   # LTO on by default
cmake --build build
ctest --test-dir build --output-on-failure

scripts/validate.sh is the project’s pre-completion gate: a clean warnings-as-errors build, the full test suite, a CLI smoke, and a leak check. Sanitizer presets exist alongside the default build dir — build-asan, build-ubsan,build-tsan — and the nightly CI lane runs libFuzzer (parse → emit → re-parse) under ASan/UBSan.

Install and link

The install rule ships the public headers, the compiled library, a pkg-config manifest, and a CMake package with ateptris:: namespace:

cmake --install
cmake --install build --prefix /usr/local
# headers:   /usr/local/include/teptris/*.h
# library:   /usr/local/lib/libteptris.*
# pkg-config: /usr/local/lib/pkgconfig/teptris.pc
# cmake:     /usr/local/lib/cmake/teptris/  (teptris::teptris)
pkg-config consumers
cc my.c $(pkg-config --cflags --libs teptris)
CMake consumers
find_package(teptris REQUIRED CONFIG)
target_link_libraries(my_app PRIVATE teptris::teptris)

The API shape

parse, walk, emit
#include <teptris/teptris.h>

teptris_document *doc = NULL;
if (teptris_parse(data, len, NULL, &doc) != TEPTRIS_OK) {
    const teptris_error *e = teptris_document_error(doc);
    fprintf(stderr, "%s at %zu:%zu\n", e->message, e->line, e->column);
    teptris_document_free(doc);
    return 1;
}
const teptris_node *root = teptris_document_root(doc);
const teptris_node *v = teptris_node_table_get(root, "key", 3);

char *out = NULL; size_t out_len = 0;
if (teptris_document_emit(doc, &out, &out_len) == TEPTRIS_OK) {
    /* out is canonical TOML — free(out) when done */
}
teptris_document_free(doc);

Many documents, one call

teptris_parse_batch parses N documents in a single C crossing and reports per-document status — the surface the Rubyload_batch and Python loads_batch bindings ride:

teptris_parse_batch
const char *docs[] = { doc_a, doc_b, doc_c };
const size_t lens[] = { len_a, len_b, len_c };
teptris_document *out[3] = {0};
teptris_status st[3];
teptris_parse_batch(docs, lens, 3, NULL, out, st);
/* st[i] == TEPTRIS_OK, out[i] owned — free each */

The CLI

bash
teptris parse config.toml     # typed-JSON tree (the toml-test wire shape)
teptris to-json config.toml   # same tree, explicit
teptris format config.toml    # canonical TOML
teptris validate broken.toml  # exit 1, line:col on stderr
teptris version

This is the curated guide. The repositories are canonical: when this page and the repo disagree, the repo wins. Full documentation lives with the source.