TypeSpecificIO
Description
Unified I/O operations container. Bundles a writer + reader pair over a single backing data pointer; one instance per type the I/O machinery dispatches on. Produced via TO_TYPE_SPECIFIC_IO(T, d) and consumed by the per-arg dispatch in the formatted-I/O macros.
Fields
| Name | Description |
|---|---|
writer |
Type-specific write callback, or NULL when not used. |
reader |
Type-specific read callback, or NULL when not used. |
data |
Pointer to the value being read/written. |
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Io.h:134:
TypeSpecificReader reader;
void *data;
} TypeSpecificIO;
///
- In
Io.h:154:
#ifdef __cplusplus
# define EMPTY_TYPE_SPECIFIC_IO() (TypeSpecificIO {NULL, NULL, NULL})
#else
# define EMPTY_TYPE_SPECIFIC_IO() ((TypeSpecificIO) {NULL, NULL, NULL})- In
Io.h:156:
# define EMPTY_TYPE_SPECIFIC_IO() (TypeSpecificIO {NULL, NULL, NULL})
#else
# define EMPTY_TYPE_SPECIFIC_IO() ((TypeSpecificIO) {NULL, NULL, NULL})
#endif- In
Io.h:159:
#endif
static inline TypeSpecificIO TO_TYPE_SPECIFIC_IO_IMPL(TypeSpecificWriter w, TypeSpecificReader r, void *d) {
return (TypeSpecificIO) {.writer = w, .reader = r, .data = d};
}- In
Io.h:160:
static inline TypeSpecificIO TO_TYPE_SPECIFIC_IO_IMPL(TypeSpecificWriter w, TypeSpecificReader r, void *d) {
return (TypeSpecificIO) {.writer = w, .reader = r, .data = d};
}- In
Io.h:207:
#else
# define ZstrIO(zstr, alloc_ptr) \
((TypeSpecificIO) { \
.writer = (TypeSpecificWriter)_write_ZstrAlloc, \
.reader = (TypeSpecificReader)_read_ZstrAlloc, \- In
Io.h:299:
_Generic( \
(x), \
TypeSpecificIO: (x), \
Str: TO_TYPE_SPECIFIC_IO(Str, &(x)), \
Buf: TO_TYPE_SPECIFIC_IO(Buf, &(x)), \
- In
Io.h:325:
_Generic( \
(x), \
TypeSpecificIO: (x), \
Str: TO_TYPE_SPECIFIC_IO(Str, (void *)&(x)), \
Buf: TO_TYPE_SPECIFIC_IO(Buf, (void *)&(x)), \
- In
Io.h:461:
input, \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:466:
)
#define StrAppendFmt_IMPL2(input, fmtstr, varr) \
str_append_fmt((input), (fmtstr), &(varr)[0], (sizeof(varr) / sizeof(TypeSpecificIO)) - 1)
///
- In
Io.h:487:
input, \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:492:
)
#define StrWriteFmt_IMPL2(input, fmtstr, varr) \
str_write_fmt((input), (fmtstr), &(varr)[0], (sizeof(varr) / sizeof(TypeSpecificIO)) - 1)
///
- In
Io.h:513:
offset, \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:518:
)
#define StrPatchFmt_IMPL2(input, offset, fmtstr, varr) \
str_patch_fmt((input), (offset), (fmtstr), &(varr)[0], (sizeof(varr) / sizeof(TypeSpecificIO)) - 1)
///
- In
Io.h:566:
input, \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:572:
#define StrReadFmt_IMPL2(input, fmtstr, varr) \
do { \
TypeSpecificIO *UNPL(argv) = &(varr)[0]; \
u64 UNPL(argc) = sizeof(varr) / sizeof(TypeSpecificIO); \
Zstr UNPL(out) = str_read_fmt((input), (fmtstr), UNPL(argv), UNPL(argc) - 1); \- In
Io.h:573:
do { \
TypeSpecificIO *UNPL(argv) = &(varr)[0]; \
u64 UNPL(argc) = sizeof(varr) / sizeof(TypeSpecificIO); \
Zstr UNPL(out) = str_read_fmt((input), (fmtstr), UNPL(argv), UNPL(argc) - 1); \
if (UNPL(out)) \
- In
Io.h:602:
file, \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:608:
#define FReadFmt_IMPL2(file, fmtstr, varr) \
do { \
TypeSpecificIO *UNPL(argv) = &(varr)[0]; \
u64 UNPL(argc) = sizeof(varr) / sizeof(TypeSpecificIO) - 1; \
f_read_fmt((file), (fmtstr), UNPL(argv), UNPL(argc)); \- In
Io.h:609:
do { \
TypeSpecificIO *UNPL(argv) = &(varr)[0]; \
u64 UNPL(argc) = sizeof(varr) / sizeof(TypeSpecificIO) - 1; \
f_read_fmt((file), (fmtstr), UNPL(argv), UNPL(argc)); \
} while (0)- In
Io.h:635:
stream, \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:640:
)
#define FWriteFmt_IMPL2(stream, fmtstr, varr) \
f_write_fmt((stream), (fmtstr), &(varr)[0], (sizeof(varr) / sizeof(TypeSpecificIO)) - 1, false)
///
- In
Io.h:664:
stream, \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:669:
)
#define FWriteFmtLn_IMPL2(stream, fmtstr, varr) \
f_write_fmt((stream), (fmtstr), &(varr)[0], (sizeof(varr) / sizeof(TypeSpecificIO)) - 1, true)
///
- In
Io.h:826:
/// TAGS: Buf, Read, Format, I/O
///
bool buf_read_fmt(BufIter *iter, Zstr fmtstr, TypeSpecificIO *argv, u64 argc);
///
- In
Io.h:844:
/// TAGS: Buf, Append, Format, I/O
///
bool buf_append_fmt(Buf *out, Zstr fmtstr, TypeSpecificIO *argv, u64 argc);
///
- In
Io.h:860:
/// TAGS: Buf, Write, Format, I/O
///
bool buf_write_fmt(Buf *out, Zstr fmtstr, TypeSpecificIO *argv, u64 argc);
///
- In
Io.h:877:
/// TAGS: Buf, Patch, Format, I/O
///
bool buf_patch_fmt(Buf *out, size offset, Zstr fmtstr, TypeSpecificIO *argv, u64 argc);
///
- In
Io.h:898:
(iter), \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:903:
)
#define BufReadFmt_IMPL2(iter, fmtstr, varr) \
buf_read_fmt((iter), (fmtstr), &(varr)[0], sizeof(varr) / sizeof(TypeSpecificIO) - 1)
///
- In
Io.h:922:
(buf), \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:927:
)
#define BufAppendFmt_IMPL2(buf, fmtstr, varr) \
buf_append_fmt((buf), (fmtstr), &(varr)[0], sizeof(varr) / sizeof(TypeSpecificIO) - 1)
///
- In
Io.h:947:
(buf), \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:952:
)
#define BufWriteFmt_IMPL2(buf, fmtstr, varr) \
buf_write_fmt((buf), (fmtstr), &(varr)[0], sizeof(varr) / sizeof(TypeSpecificIO) - 1)
///
- In
Io.h:974:
(offset), \
fmtstr, \
((TypeSpecificIO[]) { \
APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL} \
}) \
- In
Io.h:979:
)
#define BufPatchFmt_IMPL2(buf, offset, fmtstr, varr) \
buf_patch_fmt((buf), (offset), (fmtstr), &(varr)[0], sizeof(varr) / sizeof(TypeSpecificIO) - 1)
#endif // MISRA_STD_IO_H
- In
Io.c:293:
}
bool str_append_fmt(Str *o, Zstr fmt, TypeSpecificIO *args, u64 argc) {
if (!o || !fmt) {
LOG_FATAL("Invalid arguments");- In
Io.c:341:
}
TypeSpecificIO *arg = &args[arg_idx++];
if (!arg->writer || !arg->data) {
#if defined(_MSC_VER) || defined(__MSC_VER)- In
Io.c:480:
}
bool str_write_fmt(Str *o, Zstr fmt, TypeSpecificIO *args, u64 argc) {
if (!o || !fmt) {
LOG_FATAL("Invalid arguments");- In
Io.c:489:
}
bool str_patch_fmt(Str *o, size offset, Zstr fmt, TypeSpecificIO *args, u64 argc) {
if (!o || !fmt) {
LOG_FATAL("Invalid arguments");- In
Io.c:519:
}
bool f_write_fmt(File *stream, Zstr fmtstr, TypeSpecificIO *argv, u64 argc, bool append_newline) {
Str out;
bool ok = true;- In
Io.c:558:
}
Zstr str_read_fmt(Zstr input, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
if (!input || !fmtstr) {
LOG_FATAL("Invalid arguments");- In
Io.c:637:
rem_p--;
TypeSpecificIO *io = &argv[arg_index++];
if (!io->reader) {
LOG_ERROR("Missing reader function");- In
Io.c:812:
// ---------------------------------------------------------------------------
bool buf_read_fmt(BufIter *iter, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
if (!iter || !fmtstr) {
LOG_FATAL("buf_read_fmt: NULL iter or fmtstr");- In
Io.c:877:
LOG_FATAL("buf_read_fmt: too few arguments for format string");
}
TypeSpecificIO *io = &argv[arg_index++];
if (!io->reader) {
LOG_FATAL("buf_read_fmt: argument {} has no reader", arg_index - 1);- In
Io.c:971:
// raw output. Returns the index of the next byte after the directive,
// or 0 on a failed write (fmt error / OOM).
static bool render_one_raw_field(Str *out, FmtInfo *fmt_info, TypeSpecificIO *io, u64 arg_index) {
if (!io->writer) {
LOG_FATAL("buf_*_fmt: argument {} has no writer", arg_index);- In
Io.c:1021:
// ultimately writes into. Shared between buf_append_fmt and the body
// rendering done by buf_write_fmt / buf_patch_fmt.
static bool render_binary_fmt(Str *out, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
u64 arg_index = 0;
StrIter fsi = StrIterFromZstr(fmtstr);- In
Io.c:1068:
LOG_FATAL("buf_*_fmt: too few arguments for format string");
}
TypeSpecificIO *io = &argv[arg_index++];
if (!render_one_raw_field(out, &fmt_info, io, arg_index - 1)) {
return false;- In
Io.c:1080:
}
bool buf_append_fmt(Buf *out, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
if (!out || !fmtstr) {
LOG_FATAL("buf_append_fmt: NULL out or fmtstr");- In
Io.c:1089:
}
bool buf_write_fmt(Buf *out, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
if (!out || !fmtstr) {
LOG_FATAL("buf_write_fmt: NULL out or fmtstr");- In
Io.c:1097:
}
bool buf_patch_fmt(Buf *out, size offset, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
if (!out || !fmtstr) {
LOG_FATAL("buf_patch_fmt: NULL out or fmtstr");- In
Io.c:1126:
}
void f_read_fmt(File *file, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
// DefaultAllocator: the slurp buffer below sizes itself from file length
// (potentially many MiB on seekable inputs), so no stack-bound applies.
- In
Write.c:944:
#define DOUBLE_EPSILON 1e-9
#define SENTINEL (-987654.0)
#define READ1(in, fmt, IO) str_read_fmt((in), (fmt), (TypeSpecificIO[]) {(IO)}, 1)
static bool f32_close(f32 a, f32 b) {- In
Write.c:1036:
i32 b = 999;
TypeSpecificIO argv[2] = {
TO_TYPE_SPECIFIC_IO(i32, &a),
TO_TYPE_SPECIFIC_IO(i32, &b),- In
Read.c:1015:
in,
"{{",
(TypeSpecificIO[]) {
{NULL, NULL, NULL}
},- In
Read.c:1033:
in,
"{{",
(TypeSpecificIO[]) {
{NULL, NULL, NULL}
},- In
Read.c:1049:
in,
"}}",
(TypeSpecificIO[]) {
{NULL, NULL, NULL}
},- In
Read.c:1062:
in,
"}}",
(TypeSpecificIO[]) {
{NULL, NULL, NULL}
},- In
Read.c:2095:
// --- helpers/macros relocated from Io.Blind.c + Io.Leak.c ---
#define READ1(in, fmt, IO) str_read_fmt((in), (fmt), (TypeSpecificIO[]) {(IO)}, 1)
#define SENTINEL (-987654.0)- In
Read.c:2497:
char *s = NULL;
Zstr in = "hello world";
Zstr out = str_read_fmt(in, "{}", (TypeSpecificIO[]) {ZstrIO(s, &dbg.base)}, 1);
// Unquoted, non-{s} read takes the whole input (whitespace only ends an
// is_string field), so s is the full "hello world".
- In
Read.c:2614:
Int v = IntFrom(777, &alloc.base);
Zstr z = "12_3";
Zstr out = str_read_fmt(z, "{}", (TypeSpecificIO[]) {TO_TYPE_SPECIFIC_IO(Int, &v)}, 1);
// Real: '_' rejected -> returns start (==z) -> str_read_fmt sees next==in ->
// NULL; v unchanged (still 777).
- In
Read.c:2651:
(void)FloatTryFromStr(&f, "42");
Zstr z = "xyz"; // no float token
Zstr out = str_read_fmt(z, "{}", (TypeSpecificIO[]) {TO_TYPE_SPECIFIC_IO(Float, &f)}, 1);
Str t = FloatToStr(&f);
bool ok = (out == NULL) && (ZstrCompare(StrBegin(&t), "42") == 0);
Last updated on