Skip to content
TO_TYPE_SPECIFIC_IO

TO_TYPE_SPECIFIC_IO

Description

Build a TypeSpecificIO value for type T over data pointer d. Token-pastes _write_T and _read_T to pick the right callback pair from the per-type writer/reader symbols.

Parameters

Name Direction Description
T in Type identifier (must match _write_T / _read_T symbols).
d in Pointer to the value being read/written.

Success

Returns an initialised TypeSpecificIO.

Failure

Compile-time error if _write_T / _read_T are undeclared for the given T.

Usage example (Cross-references)

Usage examples (Cross-references)
    #ifdef __cplusplus
    #    define ZstrIO(zstr, alloc_ptr)                                                                                    \
            TO_TYPE_SPECIFIC_IO(ZstrAlloc, &LVAL(((ZstrIOArg) {.value = (void *)&(zstr), .allocator = (alloc_ptr)})))
    #else
    #    define ZstrIO(zstr, alloc_ptr)                                                                                    \
    #    define IOFMT_BITVEC_CASE_(x, addr)                                                                                \
    BitVec:                                                                                                                \
            TO_TYPE_SPECIFIC_IO(BitVec, addr),
    #else
    #    define IOFMT_BITVEC_CASE_(x, addr)
    #    define IOFMT_INT_CASE_(x, addr)                                                                                   \
    Int:                                                                                                                   \
            TO_TYPE_SPECIFIC_IO(Int, addr),
    #else
    #    define IOFMT_INT_CASE_(x, addr)
    #    define IOFMT_FLOAT_CASE_(x, addr)                                                                                 \
    Float:                                                                                                                 \
            TO_TYPE_SPECIFIC_IO(Float, addr),
    #else
    #    define IOFMT_FLOAT_CASE_(x, addr)
                (x),                                                                                                       \
                TypeSpecificIO: (x),                                                                                       \
                Str: TO_TYPE_SPECIFIC_IO(Str, &(x)),                                                                       \
                Buf: TO_TYPE_SPECIFIC_IO(Buf, &(x)),                                                                       \
                DateTime: TO_TYPE_SPECIFIC_IO(DateTime, &(x)),                                                             \
                TypeSpecificIO: (x),                                                                                       \
                Str: TO_TYPE_SPECIFIC_IO(Str, &(x)),                                                                       \
                Buf: TO_TYPE_SPECIFIC_IO(Buf, &(x)),                                                                       \
                DateTime: TO_TYPE_SPECIFIC_IO(DateTime, &(x)),                                                             \
                IOFMT_FLOAT_CASE_(x, &(x)) IOFMT_INT_CASE_(x, &(x)) IOFMT_BITVEC_CASE_(x, &(x)) IOFMT_USER_CASE_(x, &(x))  \
                Str: TO_TYPE_SPECIFIC_IO(Str, &(x)),                                                                       \
                Buf: TO_TYPE_SPECIFIC_IO(Buf, &(x)),                                                                       \
                DateTime: TO_TYPE_SPECIFIC_IO(DateTime, &(x)),                                                             \
                IOFMT_FLOAT_CASE_(x, &(x)) IOFMT_INT_CASE_(x, &(x)) IOFMT_BITVEC_CASE_(x, &(x)) IOFMT_USER_CASE_(x, &(x))  \
                    Zstr: TO_TYPE_SPECIFIC_IO(Zstr, &(x)),                                                                 \
                DateTime: TO_TYPE_SPECIFIC_IO(DateTime, &(x)),                                                             \
                IOFMT_FLOAT_CASE_(x, &(x)) IOFMT_INT_CASE_(x, &(x)) IOFMT_BITVEC_CASE_(x, &(x)) IOFMT_USER_CASE_(x, &(x))  \
                    Zstr: TO_TYPE_SPECIFIC_IO(Zstr, &(x)),                                                                 \
                char *: TO_TYPE_SPECIFIC_IO(Zstr, &(x)),                                                                   \
                unsigned char: TO_TYPE_SPECIFIC_IO(u8, &(x)),                                                              \
                IOFMT_FLOAT_CASE_(x, &(x)) IOFMT_INT_CASE_(x, &(x)) IOFMT_BITVEC_CASE_(x, &(x)) IOFMT_USER_CASE_(x, &(x))  \
                    Zstr: TO_TYPE_SPECIFIC_IO(Zstr, &(x)),                                                                 \
                char *: TO_TYPE_SPECIFIC_IO(Zstr, &(x)),                                                                   \
                unsigned char: TO_TYPE_SPECIFIC_IO(u8, &(x)),                                                              \
                unsigned short: TO_TYPE_SPECIFIC_IO(u16, &(x)),                                                            \
                    Zstr: TO_TYPE_SPECIFIC_IO(Zstr, &(x)),                                                                 \
                char *: TO_TYPE_SPECIFIC_IO(Zstr, &(x)),                                                                   \
                unsigned char: TO_TYPE_SPECIFIC_IO(u8, &(x)),                                                              \
                unsigned short: TO_TYPE_SPECIFIC_IO(u16, &(x)),                                                            \
                unsigned int: TO_TYPE_SPECIFIC_IO(u32, &(x)),                                                              \
                char *: TO_TYPE_SPECIFIC_IO(Zstr, &(x)),                                                                   \
                unsigned char: TO_TYPE_SPECIFIC_IO(u8, &(x)),                                                              \
                unsigned short: TO_TYPE_SPECIFIC_IO(u16, &(x)),                                                            \
                unsigned int: TO_TYPE_SPECIFIC_IO(u32, &(x)),                                                              \
                unsigned long: sizeof(unsigned long) == 4 ? TO_TYPE_SPECIFIC_IO(u32, &(x)) :                               \
                unsigned char: TO_TYPE_SPECIFIC_IO(u8, &(x)),                                                              \
                unsigned short: TO_TYPE_SPECIFIC_IO(u16, &(x)),                                                            \
                unsigned int: TO_TYPE_SPECIFIC_IO(u32, &(x)),                                                              \
                unsigned long: sizeof(unsigned long) == 4 ? TO_TYPE_SPECIFIC_IO(u32, &(x)) :                               \
                                                            TO_TYPE_SPECIFIC_IO(u64, &(x)),                                \
                unsigned short: TO_TYPE_SPECIFIC_IO(u16, &(x)),                                                            \
                unsigned int: TO_TYPE_SPECIFIC_IO(u32, &(x)),                                                              \
                unsigned long: sizeof(unsigned long) == 4 ? TO_TYPE_SPECIFIC_IO(u32, &(x)) :                               \
                                                            TO_TYPE_SPECIFIC_IO(u64, &(x)),                                \
                unsigned long long: TO_TYPE_SPECIFIC_IO(u64, &(x)),                                                        \
                unsigned int: TO_TYPE_SPECIFIC_IO(u32, &(x)),                                                              \
                unsigned long: sizeof(unsigned long) == 4 ? TO_TYPE_SPECIFIC_IO(u32, &(x)) :                               \
                                                            TO_TYPE_SPECIFIC_IO(u64, &(x)),                                \
                unsigned long long: TO_TYPE_SPECIFIC_IO(u64, &(x)),                                                        \
                signed char: TO_TYPE_SPECIFIC_IO(i8, &(x)),                                                                \
                unsigned long: sizeof(unsigned long) == 4 ? TO_TYPE_SPECIFIC_IO(u32, &(x)) :                               \
                                                            TO_TYPE_SPECIFIC_IO(u64, &(x)),                                \
                unsigned long long: TO_TYPE_SPECIFIC_IO(u64, &(x)),                                                        \
                signed char: TO_TYPE_SPECIFIC_IO(i8, &(x)),                                                                \
                signed short: TO_TYPE_SPECIFIC_IO(i16, &(x)),                                                              \
                                                            TO_TYPE_SPECIFIC_IO(u64, &(x)),                                \
                unsigned long long: TO_TYPE_SPECIFIC_IO(u64, &(x)),                                                        \
                signed char: TO_TYPE_SPECIFIC_IO(i8, &(x)),                                                                \
                signed short: TO_TYPE_SPECIFIC_IO(i16, &(x)),                                                              \
                signed int: TO_TYPE_SPECIFIC_IO(i32, &(x)),                                                                \
                unsigned long long: TO_TYPE_SPECIFIC_IO(u64, &(x)),                                                        \
                signed char: TO_TYPE_SPECIFIC_IO(i8, &(x)),                                                                \
                signed short: TO_TYPE_SPECIFIC_IO(i16, &(x)),                                                              \
                signed int: TO_TYPE_SPECIFIC_IO(i32, &(x)),                                                                \
                signed long: sizeof(signed long) == 4 ? TO_TYPE_SPECIFIC_IO(i32, &(x)) : TO_TYPE_SPECIFIC_IO(i64, &(x)),   \
                signed char: TO_TYPE_SPECIFIC_IO(i8, &(x)),                                                                \
                signed short: TO_TYPE_SPECIFIC_IO(i16, &(x)),                                                              \
                signed int: TO_TYPE_SPECIFIC_IO(i32, &(x)),                                                                \
                signed long: sizeof(signed long) == 4 ? TO_TYPE_SPECIFIC_IO(i32, &(x)) : TO_TYPE_SPECIFIC_IO(i64, &(x)),   \
                signed long long: TO_TYPE_SPECIFIC_IO(i64, &(x)),                                                          \
                signed short: TO_TYPE_SPECIFIC_IO(i16, &(x)),                                                              \
                signed int: TO_TYPE_SPECIFIC_IO(i32, &(x)),                                                                \
                signed long: sizeof(signed long) == 4 ? TO_TYPE_SPECIFIC_IO(i32, &(x)) : TO_TYPE_SPECIFIC_IO(i64, &(x)),   \
                signed long long: TO_TYPE_SPECIFIC_IO(i64, &(x)),                                                          \
                f32: TO_TYPE_SPECIFIC_IO(f32, &(x)),                                                                       \
                signed int: TO_TYPE_SPECIFIC_IO(i32, &(x)),                                                                \
                signed long: sizeof(signed long) == 4 ? TO_TYPE_SPECIFIC_IO(i32, &(x)) : TO_TYPE_SPECIFIC_IO(i64, &(x)),   \
                signed long long: TO_TYPE_SPECIFIC_IO(i64, &(x)),                                                          \
                f32: TO_TYPE_SPECIFIC_IO(f32, &(x)),                                                                       \
                f64: TO_TYPE_SPECIFIC_IO(f64, &(x)),                                                                       \
                signed long: sizeof(signed long) == 4 ? TO_TYPE_SPECIFIC_IO(i32, &(x)) : TO_TYPE_SPECIFIC_IO(i64, &(x)),   \
                signed long long: TO_TYPE_SPECIFIC_IO(i64, &(x)),                                                          \
                f32: TO_TYPE_SPECIFIC_IO(f32, &(x)),                                                                       \
                f64: TO_TYPE_SPECIFIC_IO(f64, &(x)),                                                                       \
                char: TO_TYPE_SPECIFIC_IO(i8, &(x))                                                                        \
                signed long long: TO_TYPE_SPECIFIC_IO(i64, &(x)),                                                          \
                f32: TO_TYPE_SPECIFIC_IO(f32, &(x)),                                                                       \
                f64: TO_TYPE_SPECIFIC_IO(f64, &(x)),                                                                       \
                char: TO_TYPE_SPECIFIC_IO(i8, &(x))                                                                        \
            )
                f32: TO_TYPE_SPECIFIC_IO(f32, &(x)),                                                                       \
                f64: TO_TYPE_SPECIFIC_IO(f64, &(x)),                                                                       \
                char: TO_TYPE_SPECIFIC_IO(i8, &(x))                                                                        \
            )
    #else
                (x),                                                                                                       \
                TypeSpecificIO: (x),                                                                                       \
                Str: TO_TYPE_SPECIFIC_IO(Str, (void *)&(x)),                                                               \
                Buf: TO_TYPE_SPECIFIC_IO(Buf, (void *)&(x)),                                                               \
                DateTime: TO_TYPE_SPECIFIC_IO(DateTime, (void *)&(x)),                                                     \
                TypeSpecificIO: (x),                                                                                       \
                Str: TO_TYPE_SPECIFIC_IO(Str, (void *)&(x)),                                                               \
                Buf: TO_TYPE_SPECIFIC_IO(Buf, (void *)&(x)),                                                               \
                DateTime: TO_TYPE_SPECIFIC_IO(DateTime, (void *)&(x)),                                                     \
                IOFMT_FLOAT_CASE_(x, (void *)&(x)) IOFMT_INT_CASE_(x, (void *)&(x)) IOFMT_BITVEC_CASE_(x, (void *)&(x))    \
                Str: TO_TYPE_SPECIFIC_IO(Str, (void *)&(x)),                                                               \
                Buf: TO_TYPE_SPECIFIC_IO(Buf, (void *)&(x)),                                                               \
                DateTime: TO_TYPE_SPECIFIC_IO(DateTime, (void *)&(x)),                                                     \
                IOFMT_FLOAT_CASE_(x, (void *)&(x)) IOFMT_INT_CASE_(x, (void *)&(x)) IOFMT_BITVEC_CASE_(x, (void *)&(x))    \
                    IOFMT_USER_CASE_(x, (void *)&(x)) Zstr: TO_TYPE_SPECIFIC_IO(Zstr, (void *)&(x)),                       \
                DateTime: TO_TYPE_SPECIFIC_IO(DateTime, (void *)&(x)),                                                     \
                IOFMT_FLOAT_CASE_(x, (void *)&(x)) IOFMT_INT_CASE_(x, (void *)&(x)) IOFMT_BITVEC_CASE_(x, (void *)&(x))    \
                    IOFMT_USER_CASE_(x, (void *)&(x)) Zstr: TO_TYPE_SPECIFIC_IO(Zstr, (void *)&(x)),                       \
                char *: TO_TYPE_SPECIFIC_IO(Zstr, (void *)&(x)),                                                           \
                unsigned char: TO_TYPE_SPECIFIC_IO(u8, (void *)&(x)),                                                      \
                IOFMT_FLOAT_CASE_(x, (void *)&(x)) IOFMT_INT_CASE_(x, (void *)&(x)) IOFMT_BITVEC_CASE_(x, (void *)&(x))    \
                    IOFMT_USER_CASE_(x, (void *)&(x)) Zstr: TO_TYPE_SPECIFIC_IO(Zstr, (void *)&(x)),                       \
                char *: TO_TYPE_SPECIFIC_IO(Zstr, (void *)&(x)),                                                           \
                unsigned char: TO_TYPE_SPECIFIC_IO(u8, (void *)&(x)),                                                      \
                unsigned short: TO_TYPE_SPECIFIC_IO(u16, (void *)&(x)),                                                    \
                    IOFMT_USER_CASE_(x, (void *)&(x)) Zstr: TO_TYPE_SPECIFIC_IO(Zstr, (void *)&(x)),                       \
                char *: TO_TYPE_SPECIFIC_IO(Zstr, (void *)&(x)),                                                           \
                unsigned char: TO_TYPE_SPECIFIC_IO(u8, (void *)&(x)),                                                      \
                unsigned short: TO_TYPE_SPECIFIC_IO(u16, (void *)&(x)),                                                    \
                unsigned int: TO_TYPE_SPECIFIC_IO(u32, (void *)&(x)),                                                      \
                char *: TO_TYPE_SPECIFIC_IO(Zstr, (void *)&(x)),                                                           \
                unsigned char: TO_TYPE_SPECIFIC_IO(u8, (void *)&(x)),                                                      \
                unsigned short: TO_TYPE_SPECIFIC_IO(u16, (void *)&(x)),                                                    \
                unsigned int: TO_TYPE_SPECIFIC_IO(u32, (void *)&(x)),                                                      \
                unsigned long: sizeof(unsigned long) == 4 ? TO_TYPE_SPECIFIC_IO(u32, (void *)&(x)) :                       \
                unsigned char: TO_TYPE_SPECIFIC_IO(u8, (void *)&(x)),                                                      \
                unsigned short: TO_TYPE_SPECIFIC_IO(u16, (void *)&(x)),                                                    \
                unsigned int: TO_TYPE_SPECIFIC_IO(u32, (void *)&(x)),                                                      \
                unsigned long: sizeof(unsigned long) == 4 ? TO_TYPE_SPECIFIC_IO(u32, (void *)&(x)) :                       \
                                                            TO_TYPE_SPECIFIC_IO(u64, (void *)&(x)),                        \
                unsigned short: TO_TYPE_SPECIFIC_IO(u16, (void *)&(x)),                                                    \
                unsigned int: TO_TYPE_SPECIFIC_IO(u32, (void *)&(x)),                                                      \
                unsigned long: sizeof(unsigned long) == 4 ? TO_TYPE_SPECIFIC_IO(u32, (void *)&(x)) :                       \
                                                            TO_TYPE_SPECIFIC_IO(u64, (void *)&(x)),                        \
                unsigned long long: TO_TYPE_SPECIFIC_IO(u64, (void *)&(x)),                                                \
                unsigned int: TO_TYPE_SPECIFIC_IO(u32, (void *)&(x)),                                                      \
                unsigned long: sizeof(unsigned long) == 4 ? TO_TYPE_SPECIFIC_IO(u32, (void *)&(x)) :                       \
                                                            TO_TYPE_SPECIFIC_IO(u64, (void *)&(x)),                        \
                unsigned long long: TO_TYPE_SPECIFIC_IO(u64, (void *)&(x)),                                                \
                signed char: TO_TYPE_SPECIFIC_IO(i8, (void *)&(x)),                                                        \
                unsigned long: sizeof(unsigned long) == 4 ? TO_TYPE_SPECIFIC_IO(u32, (void *)&(x)) :                       \
                                                            TO_TYPE_SPECIFIC_IO(u64, (void *)&(x)),                        \
                unsigned long long: TO_TYPE_SPECIFIC_IO(u64, (void *)&(x)),                                                \
                signed char: TO_TYPE_SPECIFIC_IO(i8, (void *)&(x)),                                                        \
                signed short: TO_TYPE_SPECIFIC_IO(i16, (void *)&(x)),                                                      \
                                                            TO_TYPE_SPECIFIC_IO(u64, (void *)&(x)),                        \
                unsigned long long: TO_TYPE_SPECIFIC_IO(u64, (void *)&(x)),                                                \
                signed char: TO_TYPE_SPECIFIC_IO(i8, (void *)&(x)),                                                        \
                signed short: TO_TYPE_SPECIFIC_IO(i16, (void *)&(x)),                                                      \
                signed int: TO_TYPE_SPECIFIC_IO(i32, (void *)&(x)),                                                        \
                unsigned long long: TO_TYPE_SPECIFIC_IO(u64, (void *)&(x)),                                                \
                signed char: TO_TYPE_SPECIFIC_IO(i8, (void *)&(x)),                                                        \
                signed short: TO_TYPE_SPECIFIC_IO(i16, (void *)&(x)),                                                      \
                signed int: TO_TYPE_SPECIFIC_IO(i32, (void *)&(x)),                                                        \
                signed long: sizeof(signed long) == 4 ? TO_TYPE_SPECIFIC_IO(i32, (void *)&(x)) :                           \
                signed char: TO_TYPE_SPECIFIC_IO(i8, (void *)&(x)),                                                        \
                signed short: TO_TYPE_SPECIFIC_IO(i16, (void *)&(x)),                                                      \
                signed int: TO_TYPE_SPECIFIC_IO(i32, (void *)&(x)),                                                        \
                signed long: sizeof(signed long) == 4 ? TO_TYPE_SPECIFIC_IO(i32, (void *)&(x)) :                           \
                                                        TO_TYPE_SPECIFIC_IO(i64, (void *)&(x)),                            \
                signed short: TO_TYPE_SPECIFIC_IO(i16, (void *)&(x)),                                                      \
                signed int: TO_TYPE_SPECIFIC_IO(i32, (void *)&(x)),                                                        \
                signed long: sizeof(signed long) == 4 ? TO_TYPE_SPECIFIC_IO(i32, (void *)&(x)) :                           \
                                                        TO_TYPE_SPECIFIC_IO(i64, (void *)&(x)),                            \
                signed long long: TO_TYPE_SPECIFIC_IO(i64, (void *)&(x)),                                                  \
                signed int: TO_TYPE_SPECIFIC_IO(i32, (void *)&(x)),                                                        \
                signed long: sizeof(signed long) == 4 ? TO_TYPE_SPECIFIC_IO(i32, (void *)&(x)) :                           \
                                                        TO_TYPE_SPECIFIC_IO(i64, (void *)&(x)),                            \
                signed long long: TO_TYPE_SPECIFIC_IO(i64, (void *)&(x)),                                                  \
                f32: TO_TYPE_SPECIFIC_IO(f32, (void *)&(x)),                                                               \
                signed long: sizeof(signed long) == 4 ? TO_TYPE_SPECIFIC_IO(i32, (void *)&(x)) :                           \
                                                        TO_TYPE_SPECIFIC_IO(i64, (void *)&(x)),                            \
                signed long long: TO_TYPE_SPECIFIC_IO(i64, (void *)&(x)),                                                  \
                f32: TO_TYPE_SPECIFIC_IO(f32, (void *)&(x)),                                                               \
                f64: TO_TYPE_SPECIFIC_IO(f64, (void *)&(x)),                                                               \
                                                        TO_TYPE_SPECIFIC_IO(i64, (void *)&(x)),                            \
                signed long long: TO_TYPE_SPECIFIC_IO(i64, (void *)&(x)),                                                  \
                f32: TO_TYPE_SPECIFIC_IO(f32, (void *)&(x)),                                                               \
                f64: TO_TYPE_SPECIFIC_IO(f64, (void *)&(x)),                                                               \
                char: TO_TYPE_SPECIFIC_IO(i8, (void *)&(x))                                                                \
                signed long long: TO_TYPE_SPECIFIC_IO(i64, (void *)&(x)),                                                  \
                f32: TO_TYPE_SPECIFIC_IO(f32, (void *)&(x)),                                                               \
                f64: TO_TYPE_SPECIFIC_IO(f64, (void *)&(x)),                                                               \
                char: TO_TYPE_SPECIFIC_IO(i8, (void *)&(x))                                                                \
            )
                f32: TO_TYPE_SPECIFIC_IO(f32, (void *)&(x)),                                                               \
                f64: TO_TYPE_SPECIFIC_IO(f64, (void *)&(x)),                                                               \
                char: TO_TYPE_SPECIFIC_IO(i8, (void *)&(x))                                                                \
            )
    #endif
    #define IOFMT_USER_CASE_(x, addr)                                                                                      \
    Point2D:                                                                                                               \
        TO_TYPE_SPECIFIC_IO(Point2D, addr), Bounds : TO_TYPE_SPECIFIC_IO(Bounds, addr),                                    \
                                                     Region : TO_TYPE_SPECIFIC_IO(Region, addr),
    Point2D:                                                                                                               \
        TO_TYPE_SPECIFIC_IO(Point2D, addr), Bounds : TO_TYPE_SPECIFIC_IO(Bounds, addr),                                    \
                                                     Region : TO_TYPE_SPECIFIC_IO(Region, addr),
    
    #include <Misra/Std/Io.h>
    
        TypeSpecificIO argv[2] = {
            TO_TYPE_SPECIFIC_IO(i32, &a),
            TO_TYPE_SPECIFIC_IO(i32, &b),
        };
        TypeSpecificIO argv[2] = {
            TO_TYPE_SPECIFIC_IO(i32, &a),
            TO_TYPE_SPECIFIC_IO(i32, &b),
        };
    static bool test_m1_invalid_spec_leaves_dest(void) {
        i32  val = 77;
        Zstr out = READ1("5", "{q}", TO_TYPE_SPECIFIC_IO(i32, &val));
        // Real: parse fails -> NULL, val unchanged.
        return out == NULL && val == 77;
        u8   ch  = 0;
        Zstr in  = "AZ";
        Zstr out = READ1(in, "{c}Z", TO_TYPE_SPECIFIC_IO(u8, &ch));
        // Real: reads 'A' as the {c} field, matches literal 'Z', consumes all.
        return out == in + 2 && ch == 'A';
    
        Str  s   = StrInit(&alloc);
        Zstr out = READ1(in, "{s}", TO_TYPE_SPECIFIC_IO(Str, &s));
    
        bool ok = (out != NULL) && (StrLen(&s) == 50);
        u8   v   = 0;
        Zstr in  = "\x07";
        Zstr out = READ1(in, "{<1r}", TO_TYPE_SPECIFIC_IO(u8, &v));
        return out == in + 1 && v == 0x07;
    }
        i8   v   = 0;
        Zstr in  = "\x07";
        Zstr out = READ1(in, "{<1r}", TO_TYPE_SPECIFIC_IO(i8, &v));
        return out == in + 1 && v == 0x07;
    }
        u16  v   = 0;
        Zstr in  = "\x34\x12"; // LE -> 0x1234
        Zstr out = READ1(in, "{<2r}", TO_TYPE_SPECIFIC_IO(u16, &v));
        return out == in + 2 && v == 0x1234;
    }
        i16  v   = 0;
        Zstr in  = "\x12\x34"; // BE -> 0x1234
        Zstr out = READ1(in, "{>2r}", TO_TYPE_SPECIFIC_IO(i16, &v));
        return out == in + 2 && v == 0x1234;
    }
        u32  v   = 0;
        Zstr in  = "\xEF\xBE\xAD\xDE"; // LE -> 0xDEADBEEF
        Zstr out = READ1(in, "{<4r}", TO_TYPE_SPECIFIC_IO(u32, &v));
        return out == in + 4 && v == 0xDEADBEEFu;
    }
        i32  v   = 0;
        Zstr in  = "\x12\x34\x56\x78"; // BE -> 0x12345678
        Zstr out = READ1(in, "{>4r}", TO_TYPE_SPECIFIC_IO(i32, &v));
        return out == in + 4 && v == 0x12345678;
    }
        u64  v   = 0;
        Zstr in  = "\x08\x07\x06\x05\x04\x03\x02\x01"; // LE -> 0x0102030405060708
        Zstr out = READ1(in, "{<8r}", TO_TYPE_SPECIFIC_IO(u64, &v));
        return out == in + 8 && v == 0x0102030405060708ull;
    }
        i64  v   = 0;
        Zstr in  = "\x01\x02\x03\x04\x05\x06\x07\x08"; // BE -> 0x0102030405060708
        Zstr out = READ1(in, "{>8r}", TO_TYPE_SPECIFIC_IO(i64, &v));
        return out == in + 8 && v == 0x0102030405060708ll;
    }
    
        Zstr in  = "\xEF\xBE\xAD\xDE"; // LE bytes -> bit pattern 0xDEADBEEF
        Zstr out = READ1(in, "{<4r}", TO_TYPE_SPECIFIC_IO(f32, &got.f));
    
        return out == in + 4 && got.u == 0xDEADBEEFu;
    
        Zstr in  = "\x08\x07\x06\x05\x04\x03\x02\x01"; // LE -> 0x0102030405060708
        Zstr out = READ1(in, "{<8r}", TO_TYPE_SPECIFIC_IO(f64, &got.f));
    
        return out == in + 8 && got.u == 0x0102030405060708ull;
        i32  v   = 0;
        Zstr in  = "42";
        Zstr out = READ1(in, "{}", TO_TYPE_SPECIFIC_IO(i32, &v));
        return out == in + 2 && v == 42;
    }
        i32 v = 7;
        // 32 chars inside braces -> spec_len == 32 -> rejected.
        Zstr out = READ1("x", "{qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq}", TO_TYPE_SPECIFIC_IO(i32, &v));
        return out == NULL && v == 7;
    }
    static bool test_read_invalid_spec_leaves_dest(void) {
        i32  v   = 77;
        Zstr out = READ1("5", "{q}", TO_TYPE_SPECIFIC_IO(i32, &v));
        return out == NULL && v == 77;
    }
        Zstr             in    = "\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\""; // 50 A's quoted
        Str              s     = StrInit(&alloc);
        Zstr             out   = READ1(in, "{s}", TO_TYPE_SPECIFIC_IO(Str, &s));
        bool             ok    = (out != NULL) && (StrLen(&s) == 50);
        StrDeinit(&s);
        u32  v   = 0;
        Zstr in  = "\xEF\xBE\xAD\xDE";
        Zstr out = READ1(in, "{<4r}", TO_TYPE_SPECIFIC_IO(u32, &v));
        return out == in + 4 && v == 0xDEADBEEFu;
    }
        u8   v   = 0;
        Zstr in  = "\x05Z";
        Zstr out = READ1(in, "{<1r}Z", TO_TYPE_SPECIFIC_IO(u8, &v));
        return out == in + 2 && v == 0x05;
    }
        i32  v   = 0;
        Zstr in  = "12-end";
        Zstr out = READ1(in, "{}-end", TO_TYPE_SPECIFIC_IO(i32, &v));
        return out == in + 6 && v == 12;
    }
        i32  v   = 0;
        Zstr in  = "5!{y";
        Zstr out = READ1(in, "{}!{​{y", TO_TYPE_SPECIFIC_IO(i32, &v));
        return out == in + 4 && v == 5;
    }
        f64  v   = 0;
        Zstr in  = "ABCDEFGH";
        Zstr out = READ1(in, "{c}", TO_TYPE_SPECIFIC_IO(f64, &v));
        union {
            f64 f;
        f64  v   = 0;
        Zstr in  = "1e5";
        Zstr out = READ1(in, "{}", TO_TYPE_SPECIFIC_IO(f64, &v));
        return out == in + 3 && f64_is(v, 100000.0);
    }
        f64  v   = 0;
        Zstr in  = "-inf";
        Zstr out = READ1(in, "{}", TO_TYPE_SPECIFIC_IO(f64, &v));
        return out == in + 4 && F64IsInf(v) && v < 0;
    }
        f64  v   = 0;
        Zstr in  = "1.5.6";
        Zstr out = READ1(in, "{}", TO_TYPE_SPECIFIC_IO(f64, &v));
        return out == in + 3 && f64_is(v, 1.5) && (*out == '.');
    }
        u8   v   = 0;
        Zstr in  = "200";
        Zstr out = READ1(in, "{}", TO_TYPE_SPECIFIC_IO(u8, &v));
        return out == in + 3 && v == 200;
    }
        u8   v   = 0;
        Zstr in  = "0xff";
        Zstr out = READ1(in, "{}", TO_TYPE_SPECIFIC_IO(u8, &v));
        return out == in + 4 && v == 255;
    }
        u8   v   = 7;
        Zstr in  = "1f";
        Zstr out = READ1(in, "{}", TO_TYPE_SPECIFIC_IO(u8, &v));
        // _read_u8 returns `start` (no advance) -> str_read_fmt sees next==in ->
        // returns NULL; v untouched.
        u8   v   = 7;
        Zstr in  = "0x";
        Zstr out = READ1(in, "{}", TO_TYPE_SPECIFIC_IO(u8, &v));
        return out == NULL && v == 7;
    }
        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).
        (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);
        f32  v   = 0;
        Zstr in  = "2.5";
        Zstr out = READ1(in, "{}", TO_TYPE_SPECIFIC_IO(f32, &v));
        return out == in + 3 && F64Abs((f64)v - 2.5) < 1e-4;
    }
        f32  v   = 0;
        Zstr in  = "-inf";
        Zstr out = READ1(in, "{}", TO_TYPE_SPECIFIC_IO(f32, &v));
        return out == in + 4 && F64IsInf((f64)v) && v < 0;
    }
Last updated on