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
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release # LTO on by default
cmake --build build
ctest --test-dir build --output-on-failurescripts/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 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)cc my.c $(pkg-config --cflags --libs teptris)find_package(teptris REQUIRED CONFIG)
target_link_libraries(my_app PRIVATE teptris::teptris)The API shape
#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:
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
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 versionWhere to go next
- leptris/teptris — the canonical repository:
benchmarks/LEDGER.mdcarries the measured story,DESCRIPTOR_ABI.mdthe schema-descriptor ABI. - The teptris gem for Ruby
- The teptris package for Python
- The TOML benchmark campaigns
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.