17#ifndef PC_FRAME_SCAN_LITERALS
18#define PC_FRAME_SCAN_LITERALS 0
27 if (!out || cap == 0 || !spec)
31 pc_sb b = {out, cap, 0,
true};
37#if PC_FRAME_SCAN_LITERALS
45 const char *s = va_arg(ap,
const char *);
59 pc_sb_u32w(&b, va_arg(ap, uint32_t), f->width);
62 pc_sb_hex(&b, va_arg(ap, uint64_t), f->width ? f->width : 1);
65 pc_sb_uint(&b, va_arg(ap, uint64_t), 8, f->width ? f->width : 1);
68 pc_sb_g(&b, va_arg(ap,
double), f->width ? f->width : 6);
111 if (!out || cap == 0 || !spec)
115 size_t used = strnlen(out, cap);
size_t pc_frame_build(char *out, size_t cap, const pc_field *spec,...)
Build spec into out (capacity cap), taking one variadic argument per valued field.
size_t pc_frame_append(char *out, size_t cap, const pc_field *spec,...)
Append spec to the NUL-terminated contents already in out.
PC_OPTIMIZE_O2 size_t pc_frame_vbuild(char *out, size_t cap, const pc_field *spec, va_list ap)
va_list form, for a caller that already has one.
Declarative frame builder: a frame is a static table of typed fields, built by one engine.
@ PC_FK_G
double, printf %.<width>g (width 0 means 6)
@ PC_FK_OCT
uint64_t, octal zero-padded to width
@ PC_FK_JSON
const char *, emitted as a quoted JSON string literal
@ PC_FK_LIT
literal text from lit; takes no argument
@ PC_FK_HEX
uint64_t, lowercase hex zero-padded to width
@ PC_FK_FIX
double, printf %.<width>f
@ PC_FK_I64
int64_t, signed decimal
@ PC_FK_DEC
uint32_t, decimal zero-padded to width
@ PC_FK_U32
uint32_t, plain decimal
@ PC_FK_U64
uint64_t, plain decimal
@ PC_FK_END
terminator; takes no argument
@ PC_FK_STR
const char * (NULL renders as empty)
@ PC_FK_XML
const char *, XML-escaped
Build one file at a named optimization level instead of the framework's.
#define PC_OPTIMIZE_O2
Build this file at optimization level 2, overriding the framework's size-optimized level.
void pc_sb_g(pc_sb *b, double v, unsigned sig)
Append v with sig significant digits, choosing fixed or scientific form - the printf "%....
void pc_sb_fixed(pc_sb *b, double v, unsigned decimals)
Append v with exactly decimals digits after the point (printf "%.<decimals>f").
size_t pc_sb_finish(pc_sb *b)
NUL-terminate and return the built length, or 0 if the build overflowed.
void pc_sb_uint(pc_sb *b, uint64_t v, unsigned base, unsigned min_digits)
Append v in base (10 or 16), left-padded with '0' to at least min_digits.
void pc_sb_xml(pc_sb *b, const char *s)
Append s XML-escaped (& < > "); a NULL s appends nothing.
void pc_sb_hex(pc_sb *b, uint64_t v, unsigned min_digits)
Append v as lowercase hex, zero-padded to at least min_digits (printf "%0Nx").
void pc_sb_put_n(pc_sb *b, const char *s, size_t sl)
Append sl bytes of s - the primitive the others build on.
void pc_sb_ch(pc_sb *b, char c)
Append a single character.
void pc_sb_u64(pc_sb *b, uint64_t v)
Append v as decimal (64-bit).
void pc_sb_u32w(pc_sb *b, uint32_t v, unsigned min_digits)
Append v as decimal, zero-padded to at least min_digits (printf "%0Nu").
void pc_sb_i64(pc_sb *b, int64_t v)
Append v as signed decimal (64-bit), with a leading '-' when negative.
void pc_sb_json(pc_sb *b, const char *s)
Append s as a JSON string literal: double-quoted, with "</tt> and <tt>\</tt> backslash-escaped....
void pc_sb_put(pc_sb *b, const char *s)
Append NUL-terminated s; leaves the buffer untouched and clears ok if it would not fit.
void pc_sb_u32(pc_sb *b, uint32_t v)
Append v as decimal (no leading zeros; "0" for zero).
One field of a frame. Frames are static const pc_field[], so they live in rodata.
Bump-append target; ok latches false once an append would overflow cap.