Skip to content
TypeSpecificIO

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)
    }
    
    bool str_append_fmt(Str *o, Zstr fmt, TypeSpecificIO *args, u64 argc) {
        if (!o || !fmt) {
            LOG_FATAL("Invalid arguments");
                }
    
                TypeSpecificIO *arg = &args[arg_idx++];
                if (!arg->writer || !arg->data) {
    #if defined(_MSC_VER) || defined(__MSC_VER)
    }
    
    bool str_write_fmt(Str *o, Zstr fmt, TypeSpecificIO *args, u64 argc) {
        if (!o || !fmt) {
            LOG_FATAL("Invalid arguments");
    }
    
    bool str_patch_fmt(Str *o, size offset, Zstr fmt, TypeSpecificIO *args, u64 argc) {
        if (!o || !fmt) {
            LOG_FATAL("Invalid arguments");
    }
    
    bool f_write_fmt(File *stream, Zstr fmtstr, TypeSpecificIO *argv, u64 argc, bool append_newline) {
        Str  out;
        bool ok = true;
    }
    
    Zstr str_read_fmt(Zstr input, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
        if (!input || !fmtstr) {
            LOG_FATAL("Invalid arguments");
                rem_p--;
    
                TypeSpecificIO *io = &argv[arg_index++];
                if (!io->reader) {
                    LOG_ERROR("Missing reader function");
    // ---------------------------------------------------------------------------
    
    bool buf_read_fmt(BufIter *iter, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
        if (!iter || !fmtstr) {
            LOG_FATAL("buf_read_fmt: NULL iter or fmtstr");
                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);
    // 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);
    // 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);
                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;
    }
    
    bool buf_append_fmt(Buf *out, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
        if (!out || !fmtstr) {
            LOG_FATAL("buf_append_fmt: NULL out or fmtstr");
    }
    
    bool buf_write_fmt(Buf *out, Zstr fmtstr, TypeSpecificIO *argv, u64 argc) {
        if (!out || !fmtstr) {
            LOG_FATAL("buf_write_fmt: NULL out or fmtstr");
    }
    
    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");
    }
    
    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.
        TypeSpecificReader reader;
        void              *data;
    } TypeSpecificIO;
    
    ///
    
    #ifdef __cplusplus
    #    define EMPTY_TYPE_SPECIFIC_IO() (TypeSpecificIO {NULL, NULL, NULL})
    #else
    #    define EMPTY_TYPE_SPECIFIC_IO() ((TypeSpecificIO) {NULL, NULL, NULL})
    #    define EMPTY_TYPE_SPECIFIC_IO() (TypeSpecificIO {NULL, NULL, NULL})
    #else
    #    define EMPTY_TYPE_SPECIFIC_IO() ((TypeSpecificIO) {NULL, NULL, NULL})
    #endif
    #endif
    
    static inline TypeSpecificIO TO_TYPE_SPECIFIC_IO_IMPL(TypeSpecificWriter w, TypeSpecificReader r, void *d) {
        return (TypeSpecificIO) {.writer = w, .reader = r, .data = d};
    }
    
    static inline TypeSpecificIO TO_TYPE_SPECIFIC_IO_IMPL(TypeSpecificWriter w, TypeSpecificReader r, void *d) {
        return (TypeSpecificIO) {.writer = w, .reader = r, .data = d};
    }
    #else
    #    define ZstrIO(zstr, alloc_ptr)                                                                                    \
            ((TypeSpecificIO) {                                                                                            \
                .writer = (TypeSpecificWriter)_write_ZstrAlloc,                                                            \
                .reader = (TypeSpecificReader)_read_ZstrAlloc,                                                             \
            _Generic(                                                                                                      \
                (x),                                                                                                       \
                TypeSpecificIO: (x),                                                                                       \
                Str: TO_TYPE_SPECIFIC_IO(Str, &(x)),                                                                       \
                IOFMT_FLOAT_CASE_(x, &(x)) IOFMT_INT_CASE_(x, &(x)) IOFMT_BITVEC_CASE_(x, &(x)) IOFMT_USER_CASE_(x, &(x))  \
            _Generic(                                                                                                      \
                (x),                                                                                                       \
                TypeSpecificIO: (x),                                                                                       \
                Str: TO_TYPE_SPECIFIC_IO(Str, (void *)&(x)),                                                               \
                IOFMT_FLOAT_CASE_(x, (void *)&(x)) IOFMT_INT_CASE_(x, (void *)&(x)) IOFMT_BITVEC_CASE_(x, (void *)&(x))    \
            input,                                                                                                         \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                               \
        })                                                                                                             \
        )
    #define StrAppendFmt_IMPL2(input, fmtstr, varr)                                                                        \
        str_append_fmt((input), (fmtstr), &(varr)[0], (sizeof(varr) / sizeof(TypeSpecificIO)) - 1)
    
    ///
            input,                                                                                                         \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                               \
        })                                                                                                             \
        )
    #define StrWriteFmt_IMPL2(input, fmtstr, varr)                                                                         \
        str_write_fmt((input), (fmtstr), &(varr)[0], (sizeof(varr) / sizeof(TypeSpecificIO)) - 1)
    
    ///
            offset,                                                                                                        \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                               \
        })                                                                                                             \
        )
    #define StrPatchFmt_IMPL2(input, offset, fmtstr, varr)                                                                 \
        str_patch_fmt((input), (offset), (fmtstr), &(varr)[0], (sizeof(varr) / sizeof(TypeSpecificIO)) - 1)
    
    ///
            input,                                                                                                         \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                                    \
        })                                                                                                             \
    #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);                      \
        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))                                                                                                 \
            file,                                                                                                          \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                                    \
        })                                                                                                             \
    #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));                                                          \
        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)
            stream,                                                                                                        \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                               \
        })                                                                                                             \
        )
    #define FWriteFmt_IMPL2(stream, fmtstr, varr)                                                                          \
        f_write_fmt((stream), (fmtstr), &(varr)[0], (sizeof(varr) / sizeof(TypeSpecificIO)) - 1, false)
    
    ///
            stream,                                                                                                        \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                               \
        })                                                                                                             \
        )
    #define FWriteFmtLn_IMPL2(stream, fmtstr, varr)                                                                        \
        f_write_fmt((stream), (fmtstr), &(varr)[0], (sizeof(varr) / sizeof(TypeSpecificIO)) - 1, true)
    
    ///
    /// TAGS: Buf, Read, Format, I/O
    ///
    bool buf_read_fmt(BufIter *iter, Zstr fmtstr, TypeSpecificIO *argv, u64 argc);
    
    ///
    /// TAGS: Buf, Append, Format, I/O
    ///
    bool buf_append_fmt(Buf *out, Zstr fmtstr, TypeSpecificIO *argv, u64 argc);
    
    ///
    /// TAGS: Buf, Write, Format, I/O
    ///
    bool buf_write_fmt(Buf *out, Zstr fmtstr, TypeSpecificIO *argv, u64 argc);
    
    ///
    /// TAGS: Buf, Patch, Format, I/O
    ///
    bool buf_patch_fmt(Buf *out, size offset, Zstr fmtstr, TypeSpecificIO *argv, u64 argc);
    
    ///
            (iter),                                                                                                        \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                                    \
        })                                                                                                             \
        )
    #define BufReadFmt_IMPL2(iter, fmtstr, varr)                                                                           \
        buf_read_fmt((iter), (fmtstr), &(varr)[0], sizeof(varr) / sizeof(TypeSpecificIO) - 1)
    
    ///
            (buf),                                                                                                         \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                               \
        })                                                                                                             \
        )
    #define BufAppendFmt_IMPL2(buf, fmtstr, varr)                                                                          \
        buf_append_fmt((buf), (fmtstr), &(varr)[0], sizeof(varr) / sizeof(TypeSpecificIO) - 1)
    
    ///
            (buf),                                                                                                         \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                               \
        })                                                                                                             \
        )
    #define BufWriteFmt_IMPL2(buf, fmtstr, varr)                                                                           \
        buf_write_fmt((buf), (fmtstr), &(varr)[0], sizeof(varr) / sizeof(TypeSpecificIO) - 1)
    
    ///
            (offset),                                                                                                      \
            fmtstr,                                                                                                        \
            ((TypeSpecificIO[]) {                                                                                          \
                APPLY_MACRO_FOREACH(IOFMT_LVAL_APPEND_COMMA, __VA_ARGS__) {NULL, NULL, NULL}                               \
        })                                                                                                             \
        )
    #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
Last updated on