libfyaml is a high-performance YAML 1.2 and JSON parser/emitter with zero-copy operation, full document and event APIs, and the two major 1.0 features:
- generics: a schema-light, sum-type value model for YAML/JSON data in C
- reflection/meta-type: typed YAML <-> C serdes driven by C type metadata
The 1.0 series adds a clear progression:
- use the core API when you need parser, emitter, event, or document-tree control
- use generics when your problem is "work with values"
- use reflection when your problem is "populate native C data structures"
1.0.0-beta2 is a correctness and portability release. It adds no new API.
- fixes for the fuzzing reports gh#317 to gh#409: memory leaks, double frees, use after free, unbounded recursion and size hint errors in the scanner, parser, document builder, YPath and reflection code
- allocation failure injection in the tests, and fixes for the error paths it found
- ASAN builds stop on undefined behaviour and check float casts
- support for FreeBSD, NetBSD, OpenBSD, illumos, MinGW-w64, 32-bit x86 and arm, riscv64 and big-endian ppc64, with fixes for the problems found there
- a weekly CI run of all supported platforms, and pinned runner images in the daily run
- a CMake based Nix derivation
The linker interface version moves to 8:1:6: the interfaces are unchanged.
The center of the generic API is fy_generic.
fy_generic is the sum-type value used to represent YAML and JSON data in C.
It carries one runtime value of one type: null, bool, int, float, string,
sequence, mapping, or YAML-specific wrappers.
It is a single pointer-sized word with inline storage for common small values, including 61-bit signed integers on 64-bit builds, short strings, and inline 32-bit floats.
The rest of the generic API is about working with fy_generic values:
- creating
fy_genericvalues from C literals or parsed input - reading typed values back out
- transforming one
fy_genericinto another - controlling lifetime through stack-local values and builders
That gives C a Python-like data model:
- scalars, sequences, and mappings as immutable tagged
fy_genericvalues - construction via
fy_value(),fy_sequence(), andfy_mapping() - parse/emit helpers for YAML and JSON
- functional collection operations such as map, filter, and reduce
If you know Python dict / list workflows, serde_json::Value,
tagged unions, or other sum-type/value-tree APIs, generics are the direct fit.
The reflection subsystem provides schema-driven typed serdes:
- extract type metadata from annotated C headers
- deserialize YAML directly into native C structs
- emit native C structs back to YAML
- inspect type and field metadata through the public reflection API
- choose between direct libclang authoring or packed metadata blobs
Reflection is the typed layer for stable C data models.
The Python binding in python-libfyaml/ is built on the
generic runtime. It is a direct bridge into the C generics API:
- Python
FyGenericlazy wrappers mirror Cfy_genericvalues - the binding demonstrates dict/list/scalar usage over the same data model
- users can move from Python prototypes to C without changing how they think about the data
See the binding reference at
python-libfyaml/docs/API.md.
Choose the core library when you need:
- event-streaming parsing
- YAML document tree access and mutation
- path queries and document-building helpers
- full control over emission details and original YAML structure
Choose generics when you need:
- Python-like data handling in C
- a schema-less or schema-light value layer
- transformations over YAML/JSON values
- a common model shared with the Python binding
Choose reflection when you need:
- direct YAML <-> C struct serdes
- stable typed configuration objects
- metadata-aware array/mapping handling
- deployable packed schemas without runtime libclang dependency
#include <libfyaml/libfyaml-generic.h>
fy_generic config = fy_mapping(
"server", fy_mapping(
"host", "localhost",
"port", 8080,
"tls", true),
"features", fy_sequence("http", "metrics", "admin"));fy_generic doc = fy_parse(
"values: [1, 2, 3, 4]",
FYOPPF_DISABLE_DIRECTORY | FYOPPF_INPUT_TYPE_STRING,
NULL);
fy_generic values = fy_get(doc, "values", fy_invalid);
fy_generic first = fy_first(values);#include <libfyaml/libfyaml-reflection.h>
struct fy_reflection *rfl = fy_reflection_from_c_file_with_cflags(
"schema.h", "", false, true, NULL);
struct fy_type_context_cfg cfg = {
.rfl = rfl,
.entry_type = "struct app_config",
};
struct fy_type_context *ctx = fy_type_context_create(&cfg);Start with these pages:
doc/generics-guide.rst: value model, schemas, lifetimesdoc/reflection-guide.rst: typed serdes, libclang, packed blobs
Reference pages:
The refreshed examples directory now covers the new alpha workflows:
- generic literals and Python-like object construction
- generic parse/transform/reduce flows
- generic lambda examples with captured local variables
- generic serial and parallel lambda-based filter/map/reduce flows with an explicit thread pool and configurable workload size
- schema-sensitive generic round-trips
- a Python-binding-to-C adoption bridge
- reflection from libclang-processed headers
- reflection export to packed blobs and runtime load from packed metadata
See examples/README.md for the full list.
libfyaml also remains:
- a full YAML 1.2 and JSON parser/emitter
- zero-copy in core parsing paths
- free of artificial key/document size limits
- strong on diagnostics and document manipulation
- fully MIT licensed
libfyaml is built and tested on these platforms:
| Platform | Versions | Architectures | Compilers |
|---|---|---|---|
| Linux (Ubuntu) | 22.04, 24.04, 26.04 | x86-64, arm64 | gcc, clang |
| Linux (other distributions) | Debian stable and testing, Fedora, Arch, Rocky Linux 9, Alpine (musl), Nix | x86-64 | gcc |
| Linux (other architectures) | Ubuntu / Debian | i386, armv7, riscv64, ppc64 (big-endian) | gcc |
| macOS | 15, 26 | arm64 | Apple clang, gcc |
| Windows | Server 2022, Server 2025, 11 | x64, arm64, x86 (Win32) | MSVC, clang, MinGW-w64 gcc |
| FreeBSD | 15.1 | x86-64 | clang |
| NetBSD | 11.0 | x86-64 | gcc |
| OpenBSD | 7.9 | x86-64 | clang |
| illumos (OmniOS) | r151058 | x86-64 | gcc |
Pushes and pull requests build a subset of these. The full CMake matrix, including ASAN builds on Linux and macOS, runs daily, and every platform above runs weekly.
Some features depend on the platform:
- The generic subsystem (and so the Python bindings) needs GCC or Clang statement expressions and a little-endian target: it is not available with MSVC or on big-endian targets.
- Durable arena garbage collection needs an atomic directory exchange, which
only Linux and macOS provide;
fy_durable_arena_gc()fails withENOSYSelsewhere. - Durable arenas have a default fixed base address on Linux and macOS
(x86-64 and arm64) and on the BSDs and illumos (x86-64); on other targets
pass an explicit
region_base.
find_package(libfyaml 1.0 REQUIRED)
target_link_libraries(your_app PRIVATE libfyaml::libfyaml)If the installed package was built with libclang support, the CMake package also
exports libfyaml_HAS_LIBCLANG.
pkg-config --cflags libfyaml
pkg-config --libs libfyamlUsing CMake:
mkdir build && cd build
cmake ..
cmake --build .
ctest --progress -j"$(nproc)"Using Autotools:
./bootstrap.sh
./configure
make
make checkllvm-dev libclang-dev: author reflection metadata directly from C headers- no runtime libclang is required when using packed reflection blobs
Sphinx documentation targets require the Python documentation toolchain:
sphinxsphinx_rtd_themesphinx-markdown-builderlinuxdoc
PDF documentation also requires a LaTeX toolchain with:
latexmkpdflatexxcolor.stywrapfig.sty
On Debian/Ubuntu, the practical package set is:
python3 -m pip install sphinx sphinx_rtd_theme sphinx-markdown-builder linuxdoc
sudo apt-get install latexmk tex-gyre texlive-fonts-recommended texlive-latex-base texlive-latex-recommended texlive-latex-extraThen build the docs with:
cmake --build build --target doc-html
cmake --build build --target doc-latexpdfThe binding lives in python-libfyaml/. Run its tests with:
cd python-libfyaml
python3 -m pytest tests/The binding is part of the 1.0 release story and shows the generic runtime's
data model in regular use. v1.0.0-alpha3 improved the Windows story for the
binding, v1.0.0-alpha4 repaired the wheel and sdist packaging flow,
v1.0.0-alpha5 broadened build and CI coverage, and v1.0.0-alpha6 expands
generic formatting/document handling. v1.0.0-alpha7 adds transparent parse
caching, optimized generic emission, and Stable ABI Python wheels.
v1.0.0-alpha8 adds durable storage, auto-anchor emission, stronger comment
round-tripping, and more complete generic helper APIs. v1.0.0-beta1 starts
the beta cycle with additional conversion, predicate, iteration, formatting,
and correctness fixes on top of that alpha surface. v1.0.0-beta2 fixes the
fuzzing reports and extends the supported platforms.
libfyaml is fully MIT licensed.