Skip to main content

emitting-output

Writing or converting formatted output in ripwire's C++ source — std::print/std::format via rw::emitTo, emitRaw and formatTo, which printf specifier maps to which format spec, and how to prove a conversion moved zero bytes. Use when adding any output call site, converting a printf-family one, or touching a help/legend string.

Ir a la instalación

Datos de origen

Repositorio
redhat-et/ripwire
Última actividad en el origen
10 de septiembre de 2026 a las 02:00
Idioma detectado de SKILL.md
inglés
Estrellas
2234
Forks
141

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
emitting-output
description
Writing or converting formatted output in ripwire's C++ source — std::print/std::format via rw::emitTo, emitRaw and formatTo, which printf specifier maps to which format spec, and how to prove a conversion moved zero bytes. Use when adding any output call site, converting a printf-family one, or touching a help/legend string.
# Emitting output in ripwire Every byte this tool prints feeds G4 (minified XML), the determinism contract, `docs/EVALS.md`'s recorded numbers, and the stored captures. Output code is therefore held to byte-exactness, not taste. ## The three primitives (`src/infra/emit.h`) | You have | Use | Why | | --- | --- | --- | | A format string **with arguments**, going to a stream | `rw::emitTo( stream, "…{}…", args )` | The choke point: `std::print` where the library has it, `std::format`+`fputs` where it does not | | **Literal text, no arguments** | `rw::emitRaw( stream, "…" )` | `std::format_string` is *consteval*; there is nothing to format, and huge literals do not compile | | A **caller-owned char buffer** | `rw::formatTo( buf, cap, "…{}…", args )` | Keeps the stack buffer — `std::format` into a `std::string` puts an allocation on hot paths (G2) | Never add a printf-family call site (`CONTRIBUTING.md` §3). Do not vendor `fmt` — the standard library has the feature, so a vendored copy is a G3 regression. ## The specifier mapping — measured, not remembered Proven byte-identical on this toolchain (218 checks; see the lane's `fmtparity.cpp`): ``` %s %u %d %zu %zd %lu %ld %llu %lld %i -> {} %.*s (precision, pointer) -> {} with std::string_view( ptr, len ) %10s -> {:>10} %-11s -> {:<11} %.9s -> {:.9} %016llx -> {:016x} %llx -> {:x} %llX -> {:X} %o -> {:o} %.3f -> {:.3f} %6.1f -> {:6.1f} %.0f -> {:.0f} %.6g -> {:.6g} %.3g -> {:.3g} (explicit precision only) ``` **The one unsafe mapping.** A `%g` or `%f` with *no* precision is NOT `{}`. printf's `%g` prints six significant digits; `{}` prints the shortest round-trip. `0.1+0.2` is `0.3` under `%g` and `0.30000000000000004` under `{}`. Give the format spec an explicit precision or leave the site alone. ## Three traps that are invisible at the call site 1. **`%%` inverts.** In a printf format a literal percent is `%%`. Text handed to `emitRaw` is no longer a format, so `%%` there prints *two* characters — collapse it to one `%`. This is how garbage reached a generated `docs/COMMANDS.md`. 2. **Braces invert the other way.** `emitTo` needs `{{` and `}}` for literal braces; `emitRaw` needs bare `{` and `}`. JSON emitters are where this bites. 3. **`format_to_n` is not `snprintf`.** `snprintf( p, S, … )` writes at most `S-1` chars *plus a NUL*; `format_to_n( p, S, … )` writes up to `S` and terminates nothing. Swapping one for the other widens the buffer by a byte and drops the terminator. Use `rw::formatTo`, whose contract is snprintf's exactly — including its return value, the would-have-written length. ## Proving a conversion moved zero bytes 1. `bash test/printffmtparitycheck.sh` — per-verb SHA-256 of stdout and stderr. **If it does not have a label for the verb you touched, it proves nothing about your change: add the label and pin it first.** `UPDATE_GOLDEN=1` re-pins; the diff must be additions only. Pinning refuses any verb whose output embeds the git stamp (`at="<sha>"`), because such a verb cannot hold a pin at all. 2. **A green fence is not coverage.** Measure it: a coverage build showed only 25% of one batch's call sites were ever executed by the corpus. Widen at the gaps — `--json` is a whole second output path. 3. **Differential-test against the pre-conversion binary on a REAL tree.** Build the base commit into a scratch worktree and diff both binaries' bytes over `src/`, `test/`, `docs/` and the repo root, normalising only the git stamp. A toy fixture cannot reach a truncation branch; a real tree does it by accident. This is what caught the `format_to_n` byte, with all 40 labels green.
Ver en GitHub