|
ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
|
Bounded no-heap string builder that fails closed on overflow (one shared copy). More...
#include <stddef.h>#include <stdint.h>#include <string.h>Go to the source code of this file.
Classes | |
| struct | pc_sb |
Bump-append target; ok latches false once an append would overflow cap. More... | |
Functions | |
| 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_put (pc_sb *b, const char *s) |
Append NUL-terminated s; leaves the buffer untouched and clears ok if it would not fit. | |
| template<size_t N> | |
| void | pc_sb_lit (pc_sb *b, const char(&s)[N]) |
Append a string literal. The array parameter deduces N, so the length is a constant. | |
| void | pc_sb_put_clip (pc_sb *b, const char *s) |
Append as much of s as fits and stop, WITHOUT latching ok. | |
| void | pc_sb_u64_clip (pc_sb *b, uint64_t v, uint8_t columns) |
Append v as decimal, right-aligned in at least columns with leading spaces, if the whole field fits - else append nothing, without latching ok. | |
| void | pc_sb_xml (pc_sb *b, const char *s) |
Append s XML-escaped (& < > "); a NULL s appends nothing. | |
| void | pc_sb_ch (pc_sb *b, char c) |
| Append a single character. | |
| 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_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_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_u32 (pc_sb *b, uint32_t v) |
Append v as decimal (no leading zeros; "0" for zero). | |
| void | pc_sb_u64 (pc_sb *b, uint64_t v) |
Append v as decimal (64-bit). | |
| void | pc_sb_i64 (pc_sb *b, int64_t v) |
Append v as signed decimal (64-bit), with a leading '-' when negative. | |
| bool | pc_signbit (double v) |
True if v carries the IEEE-754 sign bit, including for -0.0 (a mask, not a divide). | |
| bool | pc_isinf (double v) |
True if v is an infinity: all exponent bits set, zero significand. | |
| double | pc_pow10i (int p) |
| 10^p for p >= 0, by binary composition. | |
| int | pc_dec_exp (double v) |
Decimal exponent of v (the X such that 10^X <= |v| < 10^(X+1)), for v > 0. | |
| void | pc_sb_digits (pc_sb *b, uint64_t mant, unsigned digits, unsigned point_after) |
Emit digits decimal digits of mant, with a '.' after the first point_after. | |
| void | pc_sb_g (pc_sb *b, double v, unsigned sig) |
Append v with sig significant digits, choosing fixed or scientific form - the printf "%.<sig>g" rendering, including trailing-zero removal. | |
| void | pc_sb_fixed (pc_sb *b, double v, unsigned decimals) |
Append v with exactly decimals digits after the point (printf "%.<decimals>f"). | |
| 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. A NULL
@p s emits <tt>"". (Control chars are passed through, matching the emitters this replaced.) | |
| size_t | pc_sb_finish (pc_sb *b) |
| NUL-terminate and return the built length, or 0 if the build overflowed. | |
Bounded no-heap string builder that fails closed on overflow (one shared copy).
The same little Buf appender was open-coded inside the anonymous namespace of ~5 codecs (utmc, sep2, openadr, atc, exc_decoder). It bump-appends into a caller-owned char[] and latches ok to false the first time something would not fit, so every later append is a no-op and callers test one flag at the end. These header-only inline helpers are the single home for it, mirroring hex.h / numparse.h - no <stdlib.h>, no heap, and zero link cost when unused. The verbatim pieces (struct + raw append + XML escape + decimal + JSON-string + terminate) live here; the JSON emitters (hw_health, http_delivery, ble_gatt, ...) shared them byte-for-byte, so they are no longer per-codec.
Definition in file strbuf.h.
|
inline |
Append sl bytes of s - the primitive the others build on.
Takes the length rather than finding it. Every frame here is mostly literal text whose length the compiler already knows; scanning for a NUL to rediscover it is the same waste as re-parsing a format string. Appending a literal goes through pc_sb_lit, which deduces the length.
Definition at line 44 of file strbuf.h.
References pc_sb::cap, pc_sb::len, pc_sb::ok, and pc_sb::p.
Referenced by pc_frame_vbuild(), pc_sb_lit(), and pc_sb_put().
|
inline |
Append NUL-terminated s; leaves the buffer untouched and clears ok if it would not fit.
Definition at line 60 of file strbuf.h.
References pc_sb::cap, pc_sb::ok, and pc_sb_put_n().
Referenced by PC::add_response_header(), fs_path_join(), pc_frame_vbuild(), pc_sb_fixed(), pc_sb_g(), pc_sb_json(), pc_sb_xml(), PC::redirect(), PC::send(), PC::send_chunked(), PC::send_empty(), PC::send_template(), PC::set_cache_control(), PC::set_cookie(), and PC::set_cors().
|
inline |
Append a string literal. The array parameter deduces N, so the length is a constant.
pc_sb_put(b, "HTTP/1.1 ") scans nine bytes at runtime to learn what the type already states. Binding to const char (&)[N] takes the length from the type instead, and a pointer will not bind here, so a runtime string cannot reach this overload by mistake.
Definition at line 76 of file strbuf.h.
References pc_sb_put_n().
Referenced by PC::send_template().
|
inline |
Append as much of s as fits and stop, WITHOUT latching ok.
For display text only - an ls -l line, a log message - where a short rendering is better than none and nothing downstream parses the result. Never use it for a protocol field: a clipped header or frame has no terminator and desynchronizes the peer, which is exactly what the latching pc_sb_put exists to prevent. The two are deliberately different functions so the choice is visible at the call site rather than being a flag someone sets once and forgets.
Definition at line 90 of file strbuf.h.
References pc_sb::cap, pc_sb::len, pc_sb::ok, and pc_sb::p.
|
inline |
Append v as decimal, right-aligned in at least columns with leading spaces, if the whole field fits - else append nothing, without latching ok.
The display-text counterpart to pc_sb_u64. A half-written number reads as a different number, so this one is all-or-nothing where pc_sb_put_clip is byte-wise. columns is what aligns a fixed-width column (an ls -l date is %2d day and %5d year); 0 asks for the natural width. Space padding, not the zero padding pc_sb_uint does: a column pads to align, a field pads to a fixed digit count, and the two are not interchangeable on the wire.
Definition at line 112 of file strbuf.h.
References pc_sb::cap, pc_sb::len, pc_sb::ok, and pc_sb::p.
|
inline |
Append s XML-escaped (& < > "); a NULL s appends nothing.
Definition at line 143 of file strbuf.h.
References pc_sb::cap, pc_sb::len, pc_sb::ok, pc_sb::p, and pc_sb_put().
Referenced by pc_frame_vbuild().
|
inline |
Append a single character.
Definition at line 186 of file strbuf.h.
References pc_sb::cap, pc_sb::len, pc_sb::ok, and pc_sb::p.
Referenced by pc_frame_vbuild(), pc_sb_digits(), pc_sb_fixed(), pc_sb_g(), and pc_sb_i64().
|
inline |
Append v in base (10 or 16), left-padded with '0' to at least min_digits.
The one shared engine behind the decimal and hex appenders: measure the field, bounds-check once, then fill it back-to-front in place. Same shape as pc_sb_u32 so neither needs a scratch array. min_digits is what carries a printf width like %08lx or %02d.
Definition at line 207 of file strbuf.h.
References pc_sb::cap, pc_sb::len, pc_sb::ok, and pc_sb::p.
Referenced by pc_frame_vbuild(), pc_sb_hex(), pc_sb_i64(), pc_sb_u32(), pc_sb_u32w(), and pc_sb_u64().
|
inline |
Append v as decimal, zero-padded to at least min_digits (printf "%0Nu").
Definition at line 291 of file strbuf.h.
References pc_sb_uint().
Referenced by pc_frame_vbuild(), pc_sb_fixed(), and pc_sb_g().
|
inline |
Append v as lowercase hex, zero-padded to at least min_digits (printf "%0Nx").
Definition at line 297 of file strbuf.h.
References pc_sb_uint().
Referenced by pc_frame_vbuild().
|
inline |
Append v as decimal (no leading zeros; "0" for zero).
Definition at line 303 of file strbuf.h.
References pc_sb_uint().
Referenced by pc_frame_vbuild(), PC::send_chunked(), PC::send_template(), and JsonWriter::uinteger().
|
inline |
Append v as decimal (64-bit).
Definition at line 309 of file strbuf.h.
References pc_sb_uint().
Referenced by pc_frame_vbuild(), and pc_sb_fixed().
|
inline |
Append v as signed decimal (64-bit), with a leading '-' when negative.
Definition at line 315 of file strbuf.h.
References pc_sb_ch(), and pc_sb_uint().
Referenced by JsonWriter::integer(), pc_frame_vbuild(), PC::redirect(), PC::send(), and PC::send_empty().
|
inline |
True if v carries the IEEE-754 sign bit, including for -0.0 (a mask, not a divide).
Definition at line 332 of file strbuf.h.
Referenced by pc_sb_fixed(), and pc_sb_g().
|
inline |
True if v is an infinity: all exponent bits set, zero significand.
Definition at line 340 of file strbuf.h.
Referenced by pc_sb_fixed(), and pc_sb_g().
|
inline |
10^p for p >= 0, by binary composition.
Definition at line 348 of file strbuf.h.
Referenced by pc_dec_exp(), and pc_sb_g().
|
inline |
Decimal exponent of v (the X such that 10^X <= |v| < 10^(X+1)), for v > 0.
The binary exponent is a field of the IEEE-754 encoding, so it is a mask and a shift rather than something to converge on: multiplying it by log10(2) in fixed point (78913/2^18) gives the decimal exponent to within one, which a single comparison settles. The loop this replaces stepped one decade per iteration - about 320 of them for a denormal - to recover a number the representation was already carrying.
Definition at line 370 of file strbuf.h.
References pc_pow10i().
Referenced by pc_sb_g().
|
inline |
Emit digits decimal digits of mant, with a '.' after the first point_after.
Peels digits by division so no scratch array is needed. point_after == 0 or == digits emits no point.
Definition at line 406 of file strbuf.h.
References pc_sb_ch().
Referenced by pc_sb_g().
|
inline |
Append v with sig significant digits, choosing fixed or scientific form - the printf "%.<sig>g" rendering, including trailing-zero removal.
Needed because g is a wire format here, not a debug convenience: SCPI's NR2/NR3 numeric forms and SenML/JSON numbers are both defined by what this produces, so the shape has to match what the format string produced rather than being approximated with fixed decimals.
Byte-identical to printf %.<sig>g for sig <= 10, which covers every call site in this library (SCPI uses 10, JSON/SenML use the default 6); verified against libc over 450k values including ties, denormals, +/-0, inf and NaN. Above that the scaling is done in double, which runs out of precision around 16 significant digits, so sig >= 15 can differ from libc in the last digit.
Definition at line 437 of file strbuf.h.
References pc_sb::ok, pc_dec_exp(), pc_isinf(), pc_pow10i(), pc_sb_ch(), pc_sb_digits(), pc_sb_put(), pc_sb_u32w(), and pc_signbit().
Referenced by pc_frame_vbuild(), and pc_sb_fixed().
|
inline |
Append v with exactly decimals digits after the point (printf "%.<decimals>f").
Byte-identical to printf for |v| < 2^64, which is the range a fixed-decimal reading occupies. A larger magnitude falls back to the significant-digit form (see pc_sb_g) rather than being rendered wrong: its exact f expansion needs big-integer arithmetic.
Definition at line 565 of file strbuf.h.
References pc_sb::ok, pc_isinf(), pc_sb_ch(), pc_sb_g(), pc_sb_put(), pc_sb_u32w(), pc_sb_u64(), and pc_signbit().
Referenced by pc_frame_vbuild().
|
inline |
Append s as a JSON string literal: double-quoted, with "</tt> and <tt>\\</tt> backslash-escaped. A NULL
@p s emits <tt>"". (Control chars are passed through, matching the emitters this replaced.)
Definition at line 620 of file strbuf.h.
References pc_sb::cap, pc_sb::len, pc_sb::ok, pc_sb::p, and pc_sb_put().
Referenced by pc_frame_vbuild().
|
inline |
NUL-terminate and return the built length, or 0 if the build overflowed.
Definition at line 648 of file strbuf.h.
References pc_sb::cap, pc_sb::len, pc_sb::ok, and pc_sb::p.
Referenced by PC::add_response_header(), fs_path_join(), JsonWriter::integer(), pc_frame_vbuild(), PC::redirect(), PC::send(), PC::send_chunked(), PC::send_empty(), PC::send_template(), PC::set_cache_control(), PC::set_cookie(), PC::set_cors(), and JsonWriter::uinteger().