86typedef enum : uint8_t {
189 if ((cur->
len + 1U) >= cur->
cap) {
220 uint16_t remaining = count;
224 for (uint16_t i = 0U; i < remaining; i++) {
234 if (buf ==
nullptr) {
244 uint64_t remaining = value;
248 buf[count] = glyphs[remaining % (uint64_t)base];
250 remaining /= (uint64_t)base;
251 if (remaining == 0U) {
257 for (uint8_t i = 0U; i < (uint8_t)(count / 2U); i++) {
258 const char swap = buf[i];
259 buf[i] = buf[(uint8_t)(count - 1U - i)];
260 buf[(uint8_t)(count - 1U - i)] = swap;
341 *out_width = (uint16_t)width;
410 return (conv ==
'd') || (conv ==
'i') || (conv ==
'u') || (conv ==
'x') || (conv ==
'X') ||
411 (conv ==
'c') || (conv ==
's') || (conv ==
'p') ||
421 if ((after_percent ==
nullptr) || (out ==
nullptr)) {
431 const char conv = after_percent[used];
437 out->
consumed = (uint8_t)(used + 1U);
478 return (uint64_t)va_arg(args->
ap,
unsigned long long);
482 return (uint64_t)va_arg(args->
ap,
unsigned long);
485 return (uint64_t)va_arg(args->
ap,
size_t);
487 return (uint64_t)va_arg(args->
ap,
unsigned int);
517 return (int64_t)va_arg(args->
ap,
long long);
521 return (int64_t)va_arg(args->
ap,
long);
524 return (int64_t)va_arg(args->
ap, ptrdiff_t);
526 return (int64_t)va_arg(args->
ap,
int);
561 const uint16_t pad_count = (spec->
width > token_len) ? (uint16_t)(spec->
width - token_len) : 0U;
568 for (uint16_t i = 0U; i < token_len; i++) {
645 if (spec->
conv ==
'c') {
647 digits[0] = (char)va_arg(args->
ap,
int);
651 if (spec->
conv ==
's') {
653 const char* text = va_arg(args->
ap,
const char*);
654 const char* safe = (text ==
nullptr) ?
"(null)" : text;
658 if ((spec->
conv ==
'd') || (spec->
conv ==
'i')) {
660 const bool negative = (value < 0);
661 const uint64_t magnitude = negative ? (uint64_t)(-(value + 1)) + 1U : (uint64_t)value;
675 const bool is_pointer = (spec->
conv ==
'p');
676 const bool upper = (spec->
conv ==
'X');
680 const uint64_t value = is_pointer ? (uint64_t)(uintptr_t)va_arg(args->
ap,
void*)
691 if ((out ==
nullptr) || (cap == 0U) || (fmt ==
nullptr)) {
692 if ((out !=
nullptr) && (cap != 0U)) {
702 va_copy(args.
ap, ap);
704 for (uint32_t guard = 0U; guard < cap; guard++) {
705 const char ch = fmt[pos];
Annotation-attribute framework macros for ra8-firmware.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
static void internal_emit_conv(ra8_esp_hosted_fmt_cursor_t *cur, const ra8_esp_hosted_fmt_spec_t *spec, ra8_esp_hosted_fmt_args_t *args)
Expand one parsed conversion into the cursor.
static uint8_t internal_parse_flags(const char *text, ra8_esp_hosted_fmt_spec_t *out)
Recognise and record the flag characters of a specification.
ra8_esp_hosted_fmt_char_t
Characters the parser and emitter test for by name.
@ k_ra8_esp_hosted_fmt_ch_space
Pad character when not zero-padding.
@ k_ra8_esp_hosted_fmt_ch_nul
String terminator.
@ k_ra8_esp_hosted_fmt_ch_zed
Size-type length modifier.
@ k_ra8_esp_hosted_fmt_ch_ell
Long length modifier.
@ k_ra8_esp_hosted_fmt_ch_minus
Left-justify flag and sign.
@ k_ra8_esp_hosted_fmt_ch_percent
Starts a conversion.
@ k_ra8_esp_hosted_fmt_ch_zero
Zero-pad flag and first digit.
@ k_ra8_esp_hosted_fmt_ch_nine
Last decimal digit.
struct ra8_esp_hosted_fmt_args ra8_esp_hosted_fmt_args_t
static int64_t internal_next_signed(ra8_esp_hosted_fmt_args_t *args, ra8_esp_hosted_fmt_len_t len)
Pull the next signed argument at the width the modifier names.
static void internal_pad(ra8_esp_hosted_fmt_cursor_t *cur, char pad, uint16_t count)
Append the pad character a bounded number of times.
static const char s_ra8_esp_hosted_fmt_digits_lower[]
Digit glyphs for lower-case hexadecimal and every smaller base.
static void internal_put(ra8_esp_hosted_fmt_cursor_t *cur, char ch)
Append one character if the buffer still has room for it.
static uint8_t internal_parse_len(const char *text, ra8_esp_hosted_fmt_len_t *out_len)
Read the optional length modifier of a specification.
static uint16_t internal_bounded_len(const char *text)
Measure a NUL-terminated string, bounded by the width cap.
static void internal_emit_token(ra8_esp_hosted_fmt_cursor_t *cur, const ra8_esp_hosted_fmt_spec_t *spec, const char *token, uint16_t token_len)
Emit an already-rendered token honouring width and justification.
static bool internal_is_supported(char conv)
Whether a character is a conversion this formatter emits.
static uint64_t internal_next_unsigned(ra8_esp_hosted_fmt_args_t *args, ra8_esp_hosted_fmt_len_t len)
Pull the next unsigned argument at the width the modifier names.
ra8_esp_hosted_fmt_radix_t
Radices the formatter renders.
@ k_ra8_esp_hosted_fmt_radix_dec
Decimal, for the integer conversions.
@ k_ra8_esp_hosted_fmt_radix_min
Smallest base the digit table serves.
@ k_ra8_esp_hosted_fmt_radix_hex
Hexadecimal, for x, X and p.
bool priv_ra8_esp_hosted_fmt_parse(const char *after_percent, ra8_esp_hosted_fmt_spec_t *out)
Implementation of priv_ra8_esp_hosted_fmt_parse() – flags, width, length modifier and conversion,...
static uint8_t internal_parse_width(const char *text, uint16_t *out_width)
Read the optional decimal field width of a specification.
uint8_t priv_ra8_esp_hosted_fmt_utoa(char *buf, uint64_t value, uint8_t base, bool upper)
Implementation of priv_ra8_esp_hosted_fmt_utoa() – divides down and reverses in place,...
struct ra8_esp_hosted_fmt_cursor ra8_esp_hosted_fmt_cursor_t
uint32_t priv_ra8_esp_hosted_fmt_vformat(char *out, uint32_t cap, const char *fmt, va_list ap)
Implementation of priv_ra8_esp_hosted_fmt_vformat() – single pass, every loop bounded,...
static const char s_ra8_esp_hosted_fmt_digits_upper[]
Digit glyphs for upper-case hexadecimal.
Bounded, heap-free printf-subset formatter for the esp-hosted port.
struct ra8_esp_hosted_fmt_spec ra8_esp_hosted_fmt_spec_t
ra8_esp_hosted_fmt_len_t
Argument width selected by a conversion's length modifier.
@ k_ra8_esp_hosted_fmt_len_size
z; argument is size_t.
@ k_ra8_esp_hosted_fmt_len_long
l; argument is long.
@ k_ra8_esp_hosted_fmt_len_int
No modifier; argument is int.
@ k_ra8_esp_hosted_fmt_len_llong
ll; argument is long long.
@ k_ra8_esp_hosted_fmt_spec_max
Longest run of specification characters accepted after a per-cent sign, which bounds the parser's loo...
@ k_ra8_esp_hosted_fmt_width_max
Largest field width honoured; anything wider is clamped.
@ k_ra8_esp_hosted_fmt_digits_max
Widest digit run the supported bases produce, from UINT64_MAX in base ten.
Single-member holder that names this unit's argument list once.
va_list ap
The held variable-argument list.
Write cursor over the caller's output buffer.
uint32_t len
Characters written so far.
char * out
Destination buffer.
uint32_t cap
Capacity including the terminator.
bool left_justify
The - flag was present.
bool zero_pad
The 0 flag was present.
uint16_t width
Minimum field width; zero if absent.
char conv
Conversion character, zero on failure.
ra8_esp_hosted_fmt_len_t len
Argument width from the length modifier.
uint8_t consumed
Characters consumed after the per-cent.