Skip to content

BufData

Description

Pointer to the contiguous byte storage backing b. Read-only at the macro level; the bytes themselves are mutable through this pointer. Invalidated by any growth (BufReserve, BufResize, BufWriteU8, BufPushBytes).

Usage example (Cross-references)

Usage examples (Cross-references)
    /// TAGS: Buf, Iter, Construct
    ///
    #define BufIterFromBuf(b_) BufIterFromMemory(BufData(b_), BufLength(b_))
    
    // ---------------------------------------------------------------------------
            File *: proc_maps_load_from_file((out), (File *)(src), MisraScope),                                            \
            Str *: proc_maps_load_from_bytes((out), (const u8 *)StrBegin((Str *)(src)), StrLen((Str *)(src)), MisraScope), \
            Buf *: proc_maps_load_from_bytes((out), BufData((Buf *)(src)), BufLength((Buf *)(src)), MisraScope)            \
        )
    #define ProcMapsLoadFrom_3(out, src, alloc)                                                                            \
                     ALLOCATOR_OF(alloc)                                                                                   \
                 ),                                                                                                        \
            Buf *: proc_maps_load_from_bytes((out), BufData((Buf *)(src)), BufLength((Buf *)(src)), ALLOCATOR_OF(alloc))   \
        )
    #define ProcMapsLoadFrom_4(out, bytes, len, alloc)                                                                     \
                ok = false;
            } else if (StrLen(&tmp)) {
                MemCopy(BufData(out) + offset, StrBegin(&tmp), StrLen(&tmp));
            }
        }
        const MachoSection *str_sec    = MachoFindSection(&e->dsym, "__DWARF", "__debug_str");
    
        const u8 *info_b   = info_sec ? BufData(MachoBuf(&e->dsym)) + info_sec->offset : NULL;
        u64       info_n   = info_sec ? info_sec->size : 0;
        const u8 *abbrev_b = abbrev_sec ? BufData(MachoBuf(&e->dsym)) + abbrev_sec->offset : NULL;
        const u8 *info_b   = info_sec ? BufData(MachoBuf(&e->dsym)) + info_sec->offset : NULL;
        u64       info_n   = info_sec ? info_sec->size : 0;
        const u8 *abbrev_b = abbrev_sec ? BufData(MachoBuf(&e->dsym)) + abbrev_sec->offset : NULL;
        u64       abbrev_n = abbrev_sec ? abbrev_sec->size : 0;
        const u8 *str_b    = str_sec ? BufData(MachoBuf(&e->dsym)) + str_sec->offset : NULL;
        const u8 *abbrev_b = abbrev_sec ? BufData(MachoBuf(&e->dsym)) + abbrev_sec->offset : NULL;
        u64       abbrev_n = abbrev_sec ? abbrev_sec->size : 0;
        const u8 *str_b    = str_sec ? BufData(MachoBuf(&e->dsym)) + str_sec->offset : NULL;
        u64       str_n    = str_sec ? str_sec->size : 0;
            return false;
        }
        BufIter mz_iter = BufIterFromMemory(BufData(&ctx->out->data), 2);
        u16     mz;
        if (!BufReadU16LE(&mz_iter, &mz)) {
        u32     e_lfanew;
        BufIter c = BufIterFromMemory(
            BufData(&ctx->out->data) + DOS_E_LFANEW_OFFSET,
            BufLength(&ctx->out->data) - DOS_E_LFANEW_OFFSET
        );
    static bool pe_decode_nt(PeContext *ctx, u64 *out_opt_offset) {
        BufIter c =
            BufIterFromMemory(BufData(&ctx->out->data) + ctx->nt_offset, BufLength(&ctx->out->data) - ctx->nt_offset);
        u32 sig;
        if (!BufReadU32LE(&c, &sig) || sig != NT_SIGNATURE) {
        ctx->num_sections = num_sec;
        ctx->opt_hdr_size = size_opt;
        *out_opt_offset   = (u64)(IterDataAt(&c, IterIndex(&c)) - BufData(&ctx->out->data));
        return true;
    }
            return false;
        }
        BufIter c = BufIterFromMemory(BufData(&ctx->out->data) + opt_offset, ctx->opt_hdr_size);
    
        u16 magic;
    static bool pe_decode_sections(PeContext *ctx, u64 opt_offset) {
        u64     sec_offset = opt_offset + ctx->opt_hdr_size;
        BufIter c = BufIterFromMemory(BufData(&ctx->out->data) + sec_offset, BufLength(&ctx->out->data) - sec_offset);
    
        for (u32 i = 0; i < ctx->num_sections; ++i) {
        for (u32 i = 0; i < num_entries; ++i) {
            u64     entry_off = dir_offset + (u64)i * DEBUG_ENTRY_SIZE;
            BufIter c = BufIterFromMemory(BufData(&ctx->out->data) + entry_off, BufLength(&ctx->out->data) - entry_off);
            u32     charac, ts, type, sz, raddr, rptr;
            u16     ver_maj, ver_min;
            if (sz < 4 + 16 + 4 + 1)
                continue;
            BufIter cv_cur = BufIterFromMemory(BufData(&ctx->out->data) + rptr, sz);
            u32     cv_sig;
            if (!BufReadU32LE(&cv_cur, &cv_sig))
    // cleans up via PeDeinit -- the buffer never leaks.
    bool PeOpenFromMemory(Pe *out, Buf *in) {
        if (!out || !in || !BufData(in) || !BufAllocator(in)) {
            LOG_FATAL("PeOpenFromMemory: NULL argument (contract violation)");
        }
            return false;
        }
        MemCopy(BufData(&copy), data, data_size);
        BufResize(&copy, (size)data_size);
        return PeOpenFromMemory(out, &copy);
        const ElfSection *str_sec    = ElfFindSection(elf, ".debug_str");
    
        const u8 *info_b   = info_sec ? BufData(ElfBuf(elf)) + info_sec->offset : NULL;
        u64       info_n   = info_sec ? info_sec->size : 0;
        const u8 *abbrev_b = abbrev_sec ? BufData(ElfBuf(elf)) + abbrev_sec->offset : NULL;
        const u8 *info_b   = info_sec ? BufData(ElfBuf(elf)) + info_sec->offset : NULL;
        u64       info_n   = info_sec ? info_sec->size : 0;
        const u8 *abbrev_b = abbrev_sec ? BufData(ElfBuf(elf)) + abbrev_sec->offset : NULL;
        u64       abbrev_n = abbrev_sec ? abbrev_sec->size : 0;
        const u8 *str_b    = str_sec ? BufData(ElfBuf(elf)) + str_sec->offset : NULL;
        const u8 *abbrev_b = abbrev_sec ? BufData(ElfBuf(elf)) + abbrev_sec->offset : NULL;
        u64       abbrev_n = abbrev_sec ? abbrev_sec->size : 0;
        const u8 *str_b    = str_sec ? BufData(ElfBuf(elf)) + str_sec->offset : NULL;
        u64       str_n    = str_sec ? str_sec->size : 0;
        return DwarfFunctionsBuildFromSlices(out, info_b, info_n, abbrev_b, abbrev_n, str_b, str_n, alloc);
        if (off + self->block_size > BufLength(&self->data))
            return NULL;
        return BufData(&self->data) + off;
    }
            return false;
        }
        if (MemCompare(BufData(&self->data), MSF_MAGIC_7, sizeof(MSF_MAGIC_7)) != 0) {
            LOG_ERROR("PDB: bad MSF magic (not 7.00)");
            return false;
            return false;
        }
        BufIter sb = BufIterFromMemory(BufData(&self->data) + 32, BufLength(&self->data) - 32);
        u32     free_blk, num_blocks, unknown;
        if (!BufReadFmt(
    // or failure); allocator and bytes are carried by `taken`.
    bool PdbOpenFromMemory(Pdb *out, Buf *in) {
        if (!out || !in || !BufData(in) || !BufAllocator(in)) {
            LOG_FATAL("PdbOpenFromMemory: NULL argument (contract violation)");
        }
            return false;
        }
        MemCopy(BufData(&copy), data, data_size);
        BufResize(&copy, (size)data_size);
        return PdbOpenFromMemory(out, &copy);
            return false;
        }
        bool ok = TzifOffsetFromBuf(BufData(&data), BufLength(&data), unix_seconds, out_offset_seconds);
        BufDeinit(&data);
        return ok;
        if (eh && eh->size > 0) {
            out->eh_frame_addr = eh->addr;
            ok                 = cfi_parse_section(out, BufData(ElfBuf(elf)) + eh->offset, eh->addr, eh->size, false);
        } else {
            const ElfSection *df = ElfFindSection(elf, ".debug_frame");
            }
            out->eh_frame_addr = df->addr;
            ok                 = cfi_parse_section(out, BufData(ElfBuf(elf)) + df->offset, df->addr, df->size, true);
        }
        if (!ok) {
            return false;
        }
        const u8 *str_base = BufData(&ctx->out->data) + ctx->stroff;
        BufIter   tab      = BufIterFromBuf(&ctx->out->data);
        // Must-precondition: `tab_end > BufLength` was checked above, so
    // snapshot cleans up via MachoDeinit -- the buffer never leaks.
    bool MachoOpenFromMemory(Macho *out, Buf *in) {
        if (!out || !in || !BufData(in) || !BufAllocator(in)) {
            LOG_FATAL("MachoOpenFromMemory: NULL argument (contract violation)");
        }
            return false;
        }
        MemCopy(BufData(&copy), data, data_size);
        BufResize(&copy, (size)data_size);
        return MachoOpenFromMemory(out, &copy);
        // read past the strtab. Scan forward; if no NUL is found inside
        // [idx, strtab_size), return an empty string.
        Zstr base = (Zstr)(BufData(&self->data) + strtab_offset);
        for (u64 p = idx; p < strtab_size; ++p) {
            if (base[p] == '\0') {
        }
    
        const u8 *id = BufData(&self->data);
        if (id[EI_MAG0] != ELF_MAG0 || id[EI_MAG1] != ELF_MAG1 || id[EI_MAG2] != ELF_MAG2 || id[EI_MAG3] != ELF_MAG3) {
            LOG_ERROR("Elf: bad magic");
        }
    
        BufIter it = BufIterFromMemory(BufData(&self->data) + note->offset, note->size);
    
        u32 namesz = 0, descsz = 0, type = 0;
            return;
        }
        Zstr base = (Zstr)(BufData(&self->data) + dl->offset);
        // filename runs up to (and including) the NUL; CRC follows in the
        // last 4 bytes of the section, after alignment padding.
        }
        // CRC is in the last 4 bytes.
        const u8 *crc_bytes = BufData(&self->data) + dl->offset + dl->size - 4;
        BufIter   crc_iter  = BufIterFromMemory(crc_bytes, 4);
        u32       crc;
    // so the buffer never leaks.
    bool ElfOpenFromMemory(Elf *out, Buf *in) {
        if (!out || !in || !BufData(in) || !BufAllocator(in)) {
            LOG_FATAL("ElfOpenFromMemory: NULL argument (contract violation)");
        }
            return false;
        }
        MemCopy(BufData(&copy), data, data_size);
        BufResize(&copy, (size)data_size);
        // Hand `&copy` to the L-form -- it consumes the local and zeros
        U64Vec pending_dir_offsets  = VecInitT(pending_dir_offsets, alloc);
    
        BufIter section_cur = BufIterFromMemory(BufData(ElfBuf(elf)) + line_section->offset, line_section->size);
    
        bool ok = true;
        bool ok  = BufResize(&src, N);
        for (i32 i = 0; i < N; ++i) {
            BufData(&src)[i] = (u8)('A' + (i % 26));
        }
        ok = ok && (FileWrite(&f, BufData(&src), (u64)N) == (i64)N);
            BufData(&src)[i] = (u8)('A' + (i % 26));
        }
        ok = ok && (FileWrite(&f, BufData(&src), (u64)N) == (i64)N);
        FileClose(&f);
        FileClose(&r);
    
        ok = ok && (got == (i64)N) && (BufLength(&dst) == (size)N) && (MemCompare(BufData(&dst), BufData(&src), N) == 0);
    
        BufDeinit(&src);
        Buf  in = BufInit(alloc_base);
        bool ok = BufResize(&in, 5);
        MemCopy(BufData(&in), "12345", 5);
    
        i64 wrote = FileWriteAndClose(&path, &in);
        BufWriteU8(&b, 0x42);
        BufWriteU8(&b, 0x43);
        ok = ok && BufLength(&b) == 2 && BufData(&b)[0] == 0x42 && BufData(&b)[1] == 0x43;
        BufClear(&b);
        ok = ok && BufLength(&b) == 0;
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // u64 BE
        };
        bool ok = BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        BufWriteULeb128(&b, 16384);
        const u8 expect_uleb[] = {0x00, 0x7F, 0x80, 0x01, 0x80, 0x80, 0x01};
        if (BufLength(&b) != sizeof(expect_uleb) || MemCompare(BufData(&b), expect_uleb, sizeof(expect_uleb)) != 0) {
            BufDeinit(&b);
            DefaultAllocatorDeinit(&alloc);
        BufWriteSLeb128(&b, -64);
        const u8 expect_sleb[] = {0x00, 0x7F, 0xC0, 0x00, 0x40};
        bool ok = BufLength(&b) == sizeof(expect_sleb) && MemCompare(BufData(&b), expect_sleb, sizeof(expect_sleb)) == 0;
    
        BufDeinit(&b);
        BufWriteZstr(&b, "hi");
        const u8 expect[] = {'h', 'i', 0};
        bool     ok       = BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        bool     ok       = BufAppendFmt(&b, "{<2r}{>4r}", (u16)0xCAFE, (u32)0xDEADBEEF);
        const u8 expect[] = {0x99, 0xFE, 0xCA, 0xDE, 0xAD, 0xBE, 0xEF};
        ok                = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        bool     ok       = BufWriteFmt(&b, "{<2r}", (u16)0x1234);
        const u8 expect[] = {0x34, 0x12};
        ok                = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
            0x11
        };
        ok = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
    
        // Out-of-range patch must fail and leave the buf unchanged.
        // Out-of-range patch must fail and leave the buf unchanged.
        Buf snapshot = BufInit(&alloc);
        BufPushBytes(&snapshot, BufData(&b), BufLength(&b));
        ok = ok && !BufPatchFmt(&b, BufLength(&b), "{<2r}", (u16)0);
        ok = ok && BufLength(&b) == BufLength(&snapshot);
        ok = ok && !BufPatchFmt(&b, BufLength(&b), "{<2r}", (u16)0);
        ok = ok && BufLength(&b) == BufLength(&snapshot);
        ok = ok && MemCompare(BufData(&b), BufData(&snapshot), BufLength(&b)) == 0;
        BufDeinit(&snapshot);
        ok = ok && (BufLength(&b) == 4);
        {
            const u8 *d = BufData(&b);
            ok          = ok && d[0] == 0xEF && d[1] == 0xBE && d[2] == 0xAD && d[3] == 0xDE;
        }
        ok = ok && BufWriteFmt(&b, "{>4r}", (u32)0xDEADBEEF);
        {
            const u8 *d = BufData(&b);
            ok          = ok && d[0] == 0xDE && d[1] == 0xAD && d[2] == 0xBE && d[3] == 0xEF;
        }
        ok = ok && (BufLength(&b) == 5);
        {
            const u8 *d = BufData(&b);
            ok          = ok && d[0] == 'T' && d[1] == 'Z' && d[2] == 'i' && d[3] == 'f' && d[4] == '2';
        }
    
        ok = ok && BufWriteFmt(&b, "{​{{>1r}", (u8)0x41); // literal '{' then 'A'
        ok = ok && (BufLength(&b) == 2) && (BufData(&b)[0] == '{') && (BufData(&b)[1] == 0x41);
    
        BufIter it = BufIterFromBuf(&b);
        ok = ok && (BufLength(&b) == 8);
        {
            const u8 *d = BufData(&b);
            ok          = ok && d[4] == 0x44 && d[5] == 0x33 && d[6] == 0x22 && d[7] == 0x11;
            // Bytes before the patch are untouched.
        ok = ok && (BufLength(&b) == 8);
        {
            const u8 *d = BufData(&b);
            ok          = ok && d[0] == 1 && d[7] == 8; // untouched
        }
        ok      = ok && (BufLength(&b) == 8);
        {
            const u8 *d = BufData(&b);
            // On overflow the buffer is documented to be left unchanged.
            ok = ok && d[4] == 0xAA && d[5] == 0xAA && d[6] == 0xAA && d[7] == 0xAA;
        bool             ok       = BufAppendFmt(&b, "{<1r}", (u8)0x7E);
        const u8         expect[] = {0x7E};
        ok = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        bool             ok       = BufAppendFmt(&b, "{<8r}", (i64)0x0102030405060708ll);
        const u8         expect[] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
        ok = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        bool     ok       = BufAppendFmt(&b, "{<8r}", in.f);
        const u8 expect[] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
        ok                = ok && BufLength(&b) == sizeof(expect) && MemCompare(BufData(&b), expect, sizeof(expect)) == 0;
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        Buf              b     = BufInit(&alloc);
        bool             ok    = BufWriteFmt(&b, "{<1r}", (u8)0xAB);
        ok                     = ok && (BufLength(&b) == 1) && (BufData(&b)[0] == 0xAB);
        BufDeinit(&b);
        DefaultAllocatorDeinit(&alloc);
        bool r = BufAppendFmt(&b, "{>4r}", (u32)0xAABBCCDD);
    
        const u8 *d  = BufData(&b);
        bool      ok = r && (BufLength(&b) == 4) && d[0] == 0xAA && d[1] == 0xBB && d[2] == 0xCC && d[3] == 0xDD;
    
        bool      ok = BufWriteFmt(&b, "{>2r}", (u16)0x1234);
        const u8 *d  = BufData(&b);
        ok           = ok && (BufLength(&b) == 2) && d[0] == 0x12 && d[1] == 0x34;
    
        bool      ok = BufWriteFmt(&b, "{^2r}", (u16)0x1234);
        const u8 *d  = BufData(&b);
        // Host is little-endian: low byte first.
        ok = ok && (BufLength(&b) == 2) && d[0] == 0x34 && d[1] == 0x12;
    
        bool      ok = BufWriteFmt(&b, "{^4r}", (u32)0x11223344);
        const u8 *d  = BufData(&b);
        ok           = ok && (BufLength(&b) == 4) && d[0] == 0x44 && d[1] == 0x33 && d[2] == 0x22 && d[3] == 0x11;
    
        bool      ok = BufWriteFmt(&b, "{^8r}", (u64)0x0102030405060708ULL);
        const u8 *d  = BufData(&b);
        ok = ok && (BufLength(&b) == 8) && d[0] == 0x08 && d[1] == 0x07 && d[2] == 0x06 && d[3] == 0x05 && d[4] == 0x04 &&
             d[5] == 0x03 && d[6] == 0x02 && d[7] == 0x01;
        bool opened = PeOpenFromMemoryCopy(&pe, blob, sizeof(blob), ALLOCATOR_OF(&alloc));
        // Real code: rejected AND `out` zeroed by PeDeinit on the fail path.
        bool ok = !opened && BufData(&pe.data) == NULL && BufLength(&pe.data) == 0 && VecLen(&pe.sections) == 0;
        if (opened)
            PeDeinit(&pe);
        bool            match      = ok && BufLength(&buf) == sizeof(expected);
        for (u64 i = 0; match && i < sizeof(expected); ++i) {
            if (BufData(&buf)[i] != expected[i]) {
                match = false;
            }
        bool match = ok && BufLength(&no_dot) == BufLength(&w_dot);
        for (u64 i = 0; match && i < BufLength(&no_dot); ++i) {
            if (BufData(&no_dot)[i] != BufData(&w_dot)[i]) {
                match = false;
            }
        bool            match      = ok && BufLength(&buf) == sizeof(expected);
        for (u64 i = 0; match && i < sizeof(expected); ++i) {
            if (BufData(&buf)[i] != expected[i]) {
                match = false;
            }
    
        // header(12) + qname(just 0x00) + qtype(2) + qclass(2) = 17 bytes.
        bool match = ok && BufLength(&buf) == 17 && BufData(&buf)[12] == 0x00 && BufData(&buf)[13] == 0x00 &&
                     BufData(&buf)[14] == 0x01 && BufData(&buf)[15] == 0x00 && BufData(&buf)[16] == 0x01;
        // header(12) + qname(just 0x00) + qtype(2) + qclass(2) = 17 bytes.
        bool match = ok && BufLength(&buf) == 17 && BufData(&buf)[12] == 0x00 && BufData(&buf)[13] == 0x00 &&
                     BufData(&buf)[14] == 0x01 && BufData(&buf)[15] == 0x00 && BufData(&buf)[16] == 0x01;
    
        VecDeinit(&buf);
        // header(12) + [63]+63 label bytes + 0 term + 4 = 12+64+1+4 = 81; first
        // qname byte (offset 12) must be the length 63.
        bool match = ok && BufLength(&buf) == 81 && BufData(&buf)[12] == 63;
    
        VecDeinit(&buf);
        bool match = ok && BufLength(&no_dot) == BufLength(&w_dot) && BufLength(&no_dot) > 0;
        for (u64 i = 0; match && i < BufLength(&no_dot); ++i) {
            if (BufData(&no_dot)[i] != BufData(&w_dot)[i]) {
                match = false;
            }
        bool            match      = ok && BufLength(&buf) == sizeof(expected);
        for (u64 i = 0; match && i < sizeof(expected); ++i) {
            if (BufData(&buf)[i] != expected[i]) {
                match = false;
            }
                    ZstrCompare(StrBegin(&r->name), "a") == 0;
            // rdata raw stash must equal the 4 IP bytes.
            match = match && BufLength(&r->rdata) == 4 && BufData(&r->rdata)[0] == 8 && BufData(&r->rdata)[1] == 8 &&
                    BufData(&r->rdata)[2] == 4 && BufData(&r->rdata)[3] == 4;
        }
            // rdata raw stash must equal the 4 IP bytes.
            match = match && BufLength(&r->rdata) == 4 && BufData(&r->rdata)[0] == 8 && BufData(&r->rdata)[1] == 8 &&
                    BufData(&r->rdata)[2] == 4 && BufData(&r->rdata)[3] == 4;
        }
            match = match && BufLength(&r->rdata) == 16;
            for (u64 i = 0; match && i < 16; ++i) {
                if (BufData(&r->rdata)[i] != ip6[i]) {
                    match = false;
                }
            return false;
        }
        MemCopy(BufData(&in), sblob, sizeof(sblob));
        BufResize(&in, (size)sizeof(sblob));
    
    static bool resolve(Buf *b, i64 t, i32 *off) {
        return TzifOffsetFromBuf(BufData(b), BufLength(b), t, off);
    }
        BufAppendFmt(&b, "{>4r}{>1r}{>1r}", (i32)-18000, (u8)0, (u8)0); // ttinfo[1] STD
        i32  off = 0;
        bool ok  = TzifOffsetFromBuf(BufData(&b), BufLength(&b), 0, &off);
        BufDeinit(&b);
        DefaultAllocatorDeinit(&a);
        BufAppendFmt(&b, "{>4r}{>1r}{>1r}", (i32)-14400, (u8)1, (u8)0); // sole ttinfo: DST, no STD
        i32  off = 7;
        bool ok  = TzifOffsetFromBuf(BufData(&b), BufLength(&b), 0, &off);
        BufDeinit(&b);
        DefaultAllocatorDeinit(&a);
        BufAppendFmt(&b, "{>4r}{>1r}{>1r}", (i32)-14400, (u8)1, (u8)0); // v2 sole ttinfo: DST, no STD
        i32  off = 7;
        bool ok  = TzifOffsetFromBuf(BufData(&b), BufLength(&b), 0, &off);
        BufDeinit(&b);
        DefaultAllocatorDeinit(&a);
Last updated on