BufIter
Description
Iterator over an immutable byte buffer. Layout matches Iter(const u8) so the generic Iter macros work on it.
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Io.h:826:
/// TAGS: Buf, Read, Format, I/O
///
bool buf_read_fmt(BufIter *iter, Zstr fmtstr, TypeSpecificIO *argv, u64 argc);
///
- In
Buf.h:136:
///
#define BufIterFromMemory(data_, length_) \
((BufIter) {.data = (data_), .length = (length_), .pos = 0, .alignment = 1, .dir = 1})
///
- In
Buf.h:189:
/// TAGS: Buf, Read, U8
///
static inline bool BufReadU8(BufIter *c, u8 *out) {
if (c->pos >= c->length) {
return false;- In
Buf.h:207:
/// TAGS: Buf, Read, U16, LittleEndian
///
static inline bool BufReadU16LE(BufIter *c, u16 *out) {
if (c->pos + 2 > c->length) {
return false;- In
Buf.h:226:
/// TAGS: Buf, Read, U16, BigEndian
///
static inline bool BufReadU16BE(BufIter *c, u16 *out) {
if (c->pos + 2 > c->length) {
return false;- In
Buf.h:245:
/// TAGS: Buf, Read, U32, LittleEndian
///
static inline bool BufReadU32LE(BufIter *c, u32 *out) {
if (c->pos + 4 > c->length) {
return false;- In
Buf.h:265:
/// TAGS: Buf, Read, U32, BigEndian
///
static inline bool BufReadU32BE(BufIter *c, u32 *out) {
if (c->pos + 4 > c->length) {
return false;- In
Buf.h:285:
/// TAGS: Buf, Read, U64, LittleEndian
///
static inline bool BufReadU64LE(BufIter *c, u64 *out) {
if (c->pos + 8 > c->length) {
return false;- In
Buf.h:308:
/// TAGS: Buf, Read, U64, BigEndian
///
static inline bool BufReadU64BE(BufIter *c, u64 *out) {
if (c->pos + 8 > c->length) {
return false;- In
Buf.h:335:
/// TAGS: Buf, Read, LEB128, Unsigned
///
static inline bool BufReadULeb128(BufIter *c, u64 *out) {
u64 result = 0;
u32 shift = 0;- In
Buf.h:367:
/// TAGS: Buf, Read, LEB128, Signed
///
static inline bool BufReadSLeb128(BufIter *c, i64 *out) {
u64 uresult = 0;
u32 shift = 0;- In
Buf.h:405:
/// TAGS: Buf, Read, Zstr, String
///
static inline Zstr BufReadZstr(BufIter *c) {
Zstr s = (Zstr)(c->data + c->pos);
while (c->pos < c->length && c->data[c->pos] != 0) {- 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:817:
}
BufIter start = *iter;
u64 arg_index = 0;
StrIter fsi = StrIterFromZstr(fmtstr);- In
Pe.c:148:
typedef struct PeContext {
Pe *out;
BufIter file; // bounds for the whole image
u32 nt_offset; // offset of NT signature
u16 num_sections;- In
Pe.c:163:
return false;
}
BufIter mz_iter = BufIterFromMemory(BufData(&ctx->out->data), 2);
u16 mz;
if (!BufReadU16LE(&mz_iter, &mz)) {- In
Pe.c:173:
}
u32 e_lfanew;
BufIter c = BufIterFromMemory(
BufData(&ctx->out->data) + DOS_E_LFANEW_OFFSET,
BufLength(&ctx->out->data) - DOS_E_LFANEW_OFFSET- In
Pe.c:189:
// NT signature + File Header. Returns the offset of the Optional Header.
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;- In
Pe.c:220:
return false;
}
BufIter c = BufIterFromMemory(BufData(&ctx->out->data) + opt_offset, ctx->opt_hdr_size);
u16 magic;- In
Pe.c:376:
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) {- In
Pe.c:446:
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;- In
Pe.c:465:
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))- In
DwarfInfo.c:106:
// Parse the abbrev table starting at `start`. The table is terminated
// by an entry with code 0. Returns false on malformed input.
static bool parse_abbrev_table(BufIter cur, AbbrevTable *out, Allocator *alloc) {
*out = VecInitT(*out, alloc);
while (IterRemainingLength(&cur) > 0) {- In
DwarfInfo.c:196:
// Returns false only on truncated / malformed bytes; unknown forms
// fail-closed so the caller can stop cleanly.
static bool read_form(BufIter *cur, u32 form, u8 addr_size, AttrVal *out) {
*out = (AttrVal) {.kind = ATTR_VAL_NONE};
switch (form) {- In
DwarfInfo.c:336:
static bool walk_cu_dies(
BufIter cu_cur, // positioned past CU header
const AbbrevTable *abbrevs,
u8 addr_size,- In
DwarfInfo.c:536:
}
BufIter info_cur = BufIterFromMemory(info_bytes, info_size);
PendingFns pending = VecInitT(pending, alloc);- In
DwarfInfo.c:585:
AbbrevTable abbrevs;
BufIter abbrev_cur = BufIterFromMemory(abbrev_bytes + abbrev_offset, abbrev_size - abbrev_offset);
if (!parse_abbrev_table(abbrev_cur, &abbrevs, alloc)) {
ok = false;- In
DwarfInfo.c:593:
// DIE iter spans the DIE body within this CU (from current
// info_cur position up to unit_end_pos).
BufIter die_cur =
BufIterFromMemory(IterDataAt(&info_cur, IterIndex(&info_cur)), unit_end_pos - IterIndex(&info_cur));
if (!walk_cu_dies(die_cur, &abbrevs, addr_size, str_bytes, str_size, &out->string_pool, &pending)) {- In
Dns.c:102:
//
// Returns false on cycles, oversized names, or out-of-bounds.
static bool decode_name(BufIter *it, Str *out_name) {
const u32 MAX_HOPS = 64;
u32 hops = 0;- In
Dns.c:176:
// Decode one resource record. Advances the iter past the record.
static bool decode_record(BufIter *it, DnsRecord *rec, Allocator *alloc) {
rec->name = StrInit(alloc);
rec->target = StrInit(alloc);- In
Dns.c:229:
// follow compression pointers back into the whole message,
// so we use a sub-iter cloned from the main one.
BufIter sub = *it;
if (!decode_name(&sub, &rec->target)) {
return false;- In
Dns.c:253:
// ---------------------------------------------------------------------------
static bool decode_record_list(BufIter *it, u16 count, DnsRecords *out, Allocator *alloc) {
for (u16 i = 0; i < count; ++i) {
DnsRecord rec = {0};- In
Dns.c:283:
return false;
}
BufIter it = BufIterFromMemory(buf, len);
u16 flags, qd, an, ns, ar;
if (!BufReadFmt(&it, "{>2r}{>2r}{>2r}{>2r}{>2r}{>2r}", out->id, flags, qd, an, ns, ar)) {- In
Pdb.c:151:
return false;
}
BufIter sb = BufIterFromMemory(BufData(&self->data) + 32, BufLength(&self->data) - 32);
u32 free_blk, num_blocks, unknown;
if (!BufReadFmt(- In
Pdb.c:205:
for (u32 i = 0; i < num_dir_blocks; ++i) {
BufIter blk_iter = BufIterFromMemory((const u8 *)&self->dir_stream_blocks[i], sizeof(u32));
u32 block_id;
if (!BufReadU32LE(&blk_iter, &block_id)) {- In
Pdb.c:237:
return false;
}
BufIter dir_iter = BufIterFromMemory(self->stream_dir, self->stream_dir_size);
if (!BufReadU32LE(&dir_iter, &self->num_streams))
return false;- In
Pdb.c:331:
if (!stream_read(self, 1, 0, VecBegin(&buf), VecCapacity(&buf)))
break;
BufIter bi = BufIterFromMemory(VecBegin(&buf), VecCapacity(&buf));
if (!BufReadFmt(&bi, FMT_PDB_INFO_LE, self->info.version, self->info.signature, self->info.age)) {
LOG_ERROR("PDB: info stream prefix truncated");- In
Pdb.c:375:
break;
BufIter bi = BufIterFromMemory(VecBegin(&hdr), VecCapacity(&hdr));
if (!BufReadFmt(
&bi,- In
Pdb.c:490:
for (u32 i = 0; i < n; ++i) {
// IMAGE_SECTION_HEADER: name[8] + VirtualSize(4) + VirtualAddress(4) + ...
BufIter rec = BufIterFromMemory(buf + i * 40 + 8, 40 - 8);
(void)BufReadU32LE(&rec, &out[i].virtual_size);
(void)BufReadU32LE(&rec, &out[i].virtual_address);- In
Pdb.c:563:
u64 cur = 0;
while (cur + 4 <= (u64)sz) {
BufIter rec_iter = BufIterFromMemory(buf + cur, 4);
u16 rec_len, rec_kind;
if (!BufReadU16LE(&rec_iter, &rec_len) || !BufReadU16LE(&rec_iter, &rec_kind))- In
Pdb.c:576:
// Record body starts at cur + 4 (past len + kind). 10-byte
// prefix (Flags/Offset/Segment) then NUL-terminated Name.
BufIter body = BufIterFromMemory(buf + cur + 4, rec_len - 2);
u32 flags, offset;
u16 segment;- In
Tzif.c:49:
} TzifHeader;
static bool tzif_read_header(BufIter *it, TzifHeader *h) {
if ((u64)IterRemainingLength(it) < TZIF_HEADER_SIZE)
return false;- In
Tzif.c:80:
// type's utoff, with the first standard-time (isdst==0) ttinfo as the
// pre-history / past-table fallback.
static bool tzif_resolve(BufIter *it, u32 time_width, u32 timecnt, u32 typecnt, i64 unix_seconds, i32 *out_offset) {
if (typecnt == 0)
return false;- In
Tzif.c:158:
return false;
BufIter it = BufIterFromMemory((u8 *)data, len);
TzifHeader h1;
if (!tzif_read_header(&it, &h1)) {- In
DwarfUnwind.c:60:
// file-relative virtual address of `c->p` (used by PCREL). On success
// `*out` receives the decoded absolute file-relative VA.
static bool decode_eh_ptr(BufIter *c, u8 encoding, u64 here_vaddr, u64 *out) {
if (encoding == DW_EH_PE_OMIT) {
return false; // ---------------------------------------------------------------------------
static bool parse_cie(BufIter *body, u64 cie_offset, DwarfCie *out) {
MemSet(out, 0, sizeof(*out));
out->offset = cie_offset;
static bool parse_fde(
BufIter *body,
const u8 *body_start,
u64 cie_offset, cfi_parse_section(DwarfCfi *out, const u8 *section_data, u64 section_addr, u64 section_size, bool is_debug_frame) {
const u32 cie_id = is_debug_frame ? 0xffffffffu : 0u;
BufIter section_cur = BufIterFromMemory(section_data, section_size);
while (IterRemainingLength(§ion_cur) > 0) {
const u8 *rec_start = IterDataAt(§ion_cur, IterIndex(§ion_cur)); // Body iter starts just after the id field (since parse_cie
// doesn't re-read id) and spans the remainder of the record.
BufIter body = BufIterFromMemory(IterDataAt(§ion_cur, IterIndex(§ion_cur)), length32 - 4);
if (parse_cie(&body, cie_offset, &cie)) {
if (!VecPushBackR(&out->cies, cie)) }
DwarfFde fde;
BufIter body = BufIterFromMemory(IterDataAt(§ion_cur, IterIndex(§ion_cur)), length32 - 4);
if (parse_fde(&body, rec_start, cie_offset, out, section_data, section_addr, &fde)) {
if (!VecPushBackR(&out->fdes, fde)) // One instruction. `stop_at` lets the caller bail mid-stream once an
// advance_loc has covered the requested target PC.
static bool cfi_vm_step(CfiVm *vm, BufIter *cur, u64 stop_at, bool *stop_now) {
u8 op = 0;
if (!BufReadU8(cur, &op))
static bool cfi_vm_run(CfiVm *vm, const u8 *insns, u64 insns_size, u64 stop_at) {
BufIter cur = BufIterFromMemory(insns, insns_size);
bool stop_now = false;
while (IterRemainingLength(&cur) > 0) {- In
MachO.c:124:
return false;
}
BufIter c = BufIterFromBuf(&m->data);
u32 magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags, reserved;
if (!BufReadFmt(- In
MachO.c:173:
// untouched.
static bool decode_segment_64(MachoContext *ctx, BufIter *cmd) {
u64 cmdsize = IterLength(cmd);
if (cmdsize < SEG64_CMD_SIZE_MIN) {- In
MachO.c:219:
// `sec_it` is carved at exactly SECT64_SIZE bytes, so the two
// 16-byte moves below stay inside its window.
BufIter sec_it = IterCarve(cmd, SECT64_SIZE);
MachoSection sec;
MemSet(&sec, 0, sizeof(sec));- In
MachO.c:262:
}
static bool decode_symtab(MachoContext *ctx, BufIter *cmd) {
if (IterLength(cmd) < SYMTAB_CMD_SIZE) {
LOG_ERROR("MachO: LC_SYMTAB truncated");- In
MachO.c:278:
}
static bool decode_uuid(MachoContext *ctx, BufIter *cmd) {
if (IterLength(cmd) < UUID_CMD_SIZE) {
LOG_ERROR("MachO: LC_UUID truncated");- In
MachO.c:296:
return false;
}
BufIter walker = BufIterFromBuf(&ctx->out->data);
// Must-precondition: the check above proves the file is at least
// `MH_HEADER_64_SIZE + sizeofcmds` bytes, so the header skip stays
- In
MachO.c:310:
}
// Peek the prefix (cmd, cmdsize) without advancing the walker.
BufIter prefix = IterCarve(&walker, 8);
u32 cmd, cmdsize;
if (!BufReadFmt(&prefix, FMT_MACHO_LC_PREFIX_LE, cmd, cmdsize)) {- In
MachO.c:322:
// Carve a view of this entire command (including the 8-byte
// prefix) for the sub-decoder. The walker stays put.
BufIter cmd_view = IterCarve(&walker, cmdsize);
u32 type = cmd & ~LC_REQ_DYLD;
switch (type) {- In
MachO.c:371:
}
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
// `symoff <= tab_end <= BufLength` and the move stays in-bounds.
- In
Elf.c:161:
self->header.data = ELF_DATA_LSB;
BufIter iter = BufIterFromBuf(&self->data);
IterMustMove(&iter, EI_NIDENT);- In
Elf.c:221:
u64 shstr_size = 0;
{
BufIter iter = BufIterFromBuf(&self->data);
IterMustMove(&iter, shoff + (u64)self->header.shstrndx * SHDR64_SIZE);
u32 name = 0, type = 0, link = 0, info = 0;- In
Elf.c:234:
}
BufIter iter = BufIterFromBuf(&self->data);
IterMustMove(&iter, shoff);
for (u16 i = 0; i < n; ++i) {- In
Elf.c:273:
}
BufIter iter = BufIterFromBuf(&self->data);
IterMustMove(&iter, phoff);
for (u16 i = 0; i < n; ++i) {- In
Elf.c:340:
}
BufIter iter = BufIterFromBuf(&self->data);
IterMustMove(&iter, symtab->offset);
for (u64 i = 0; i < count; ++i) {- In
Elf.c:410:
}
BufIter it = BufIterFromMemory(BufData(&self->data) + note->offset, note->size);
u32 namesz = 0, descsz = 0, type = 0;- In
Elf.c:448:
// 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;
if (!BufReadU32LE(&crc_iter, &crc)) {- In
Dwarf.c:91:
// cursor sits at the start of the include_directories table; the
// directory / file tables are walked separately by collect_cu_strings.
static bool decode_line_program_header(BufIter *cur, LineProgHeader *out) {
MemSet(out, 0, sizeof(*out));- In
Dwarf.c:170:
// Walk past include_directories + file_names, leaving cur at the
// start of the line number program body.
static bool skip_line_program_tables(BufIter *cur) {
while (IterIndex(cur) < IterLength(cur) && *IterDataAt(cur, IterIndex(cur)) != 0) {
if (!BufReadZstr(cur))- In
Dwarf.c:227:
// to the first byte after the standard_opcode_lengths array; we
// continue from there.
static bool collect_cu_strings(BufIter cur, Str *pool, CuStrings *cs) {
// include_directories
while (IterIndex(&cur) < IterLength(&cur) && *IterDataAt(&cur, IterIndex(&cur)) != 0) {- In
Dwarf.c:333:
static bool run_line_program(
BufIter cur,
const u8 *prog_end,
const LineProgHeader *hdr,- In
Dwarf.c:560:
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;- In
Dwarf.c:566:
const u8 *unit_start = IterDataAt(§ion_cur, IterIndex(§ion_cur));
u32 unit_length = 0;
BufIter peek = section_cur;
if (!BufReadU32LE(&peek, &unit_length)) {
ok = false;- In
Dwarf.c:586:
// tables once to populate the shared string pool, then run
// the program body.
BufIter hdr_cur = section_cur;
LineProgHeader hdr;
if (!decode_line_program_header(&hdr_cur, &hdr)) {- In
Dwarf.c:603:
// up to the end of this CU.
size strings_start_pos = (size)(hdr.strings_start - IterDataAt(§ion_cur, 0));
BufIter str_cur = BufIterFromMemory(IterDataAt(§ion_cur, 0), unit_end_pos);
// strings_start_pos lies within `[0, unit_end_pos]` by construction
// -- `hdr.strings_start` was assigned from inside this section's
- In
Dwarf.c:615:
// Skip past the tables to find the program body start.
BufIter prog_anchor = BufIterFromMemory(IterDataAt(§ion_cur, 0), unit_end_pos);
// Must-precondition: same bounds proof as `str_cur` above --
// `strings_start_pos` is inside `[0, unit_end_pos]` by header
- In
Dwarf.c:626:
}
BufIter prog_cur = prog_anchor;
if (!run_line_program(prog_cur, unit_end, &hdr, &cs, out, &pending_file_offsets, &pending_dir_offsets)) {
cu_strings_deinit(&cs);- In
Buf.c:99:
BufWriteU64LE(&b, 0xFEEDFACECAFEBEEFull);
BufIter it = BufIterFromBuf(&b);
u16 v16;
u32 v32;- In
Buf.c:119:
BufWriteSLeb128(&b, -123456);
BufIter it = BufIterFromBuf(&b);
u64 uv;
i64 sv;- In
Buf.c:137:
BufWriteZstr(&b, "world");
BufIter it = BufIterFromBuf(&b);
Zstr s1 = BufReadZstr(&it);
Zstr s2 = BufReadZstr(&it);- In
Buf.c:220:
BufAppendFmt(&b, "{<2r}{>4r}{<8r}", (u16)0x1234, (u32)0xDEADBEEF, (u64)0x0102030405060708ull);
BufIter it = BufIterFromBuf(&b);
u16 v16;
u32 v32;- In
Buf.c:238:
BufAppendFmt(&b, "{<2r}", (u16)0xABCD); // only 2 bytes; reader wants 6
BufIter it = BufIterFromBuf(&b);
size entry = it.pos;
u16 v16 = 0;- In
Buf.c:253:
bool test_byte_iter_from_memory(void) {
const u8 bytes[] = {0xAA, 0xBB, 0xCC};
BufIter it = BufIterFromMemory(bytes, 3);
u8 v;
bool ok = BufReadU8(&it, &v) && v == 0xAA;- In
Write.c:804:
ok = ok && BufWriteFmt(&b, "{<2r}{>8r}", (u16)0x1234, (u64)0x0102030405060708ULL);
{
BufIter it = BufIterFromBuf(&b);
u16 v16 = 0;
u64 v64 = 0;- In
Write.c:835:
// Read back: the literal matches and the version is extracted.
{
BufIter it = BufIterFromBuf(&b);
u8 ver = 0;
ok = ok && BufReadFmt(&it, "TZif{>1r}", ver) && (ver == '2');- In
Write.c:842:
// Wrong magic -> soft false, no abort, cursor rewound, dest untouched.
{
BufIter it = BufIterFromBuf(&b);
u8 ver = 0xAB;
bool rd = BufReadFmt(&it, "TZig{>1r}", ver);- In
Write.c:863:
ok = ok && (BufLength(&b) == 2) && (BufData(&b)[0] == '{') && (BufData(&b)[1] == 0x41);
BufIter it = BufIterFromBuf(&b);
u8 v = 0;
ok = ok && BufReadFmt(&it, "{{{>1r}", v) && (v == 0x41);- In
Write.c:885:
ok = ok && (BufLength(&b) == 2);
{
BufIter it = BufIterFromBuf(&b);
u8 q = 0;
ok = ok && BufReadFmt(&it, "{>1r}Z", q) && (q == 'Q');- In
Write.c:893:
ok = ok && BufWriteFmt(&b, "{>1r}{{", (u8)'Q');
{
BufIter it = BufIterFromBuf(&b);
u8 q = 0;
ok = ok && BufReadFmt(&it, "{>1r}{{", q) && (q == 'Q');- In
Write.c:1859:
ok = ok && (BufLength(&b) == 1);
BufIter it = BufIterFromBuf(&b);
u8 v8 = 0;
bool rd = BufReadFmt(&it, "{<1r}", v8);- In
Write.c:1885:
ok = ok && (BufLength(&b) == 4);
BufIter it = BufIterFromBuf(&b);
u32 v32 = 0;
bool rd = BufReadFmt(&it, "{<4r}", v32);- In
Write.c:1909:
ok = ok && (BufLength(&b) == 8);
BufIter it = BufIterFromBuf(&b);
u64 v64 = 0;
bool rd = BufReadFmt(&it, "{>8r}", v64);- In
Write.c:1933:
ok = ok && (BufLength(&b) == 8);
BufIter it = BufIterFromBuf(&b);
i64 v64 = 0;
bool rd = BufReadFmt(&it, "{<8r}", v64);- In
Write.c:1963:
BufWriteFmt(&b, "{<2r}", (u16)0x1234);
BufIter it = BufIterFromBuf(&b);
u16 v16 = 0;
BufReadFmt(&it, "{2}", v16); // real: LOG_FATAL (non-raw). mutant: returns.
- In
Write.c:4094:
ok = ok && BufWriteFmt(&b, "{>8r}", (u64)0x0102030405060708ULL);
BufIter it = BufIterFromBuf(&b);
u64 v64 = 0;
ok = ok && BufReadFmt(&it, "{>8r}", v64);- In
Write.c:4629:
ok = ok && (BufLength(&b) == 2);
BufIter it = BufIterFromBuf(&b);
u16 v16 = 0;
bool rd_ok = BufReadFmt(&it, "{^2r}", v16);- In
Write.c:4760:
Buf b = BufInit(&alloc);
BufWriteFmt(&b, "{<1r}{<1r}", (u8)0x11, (u8)0x22); // 2 bytes available
BufIter it = BufIterFromBuf(&b);
u8 v8 = 0;
BufReadFmt(&it, "{<1r}{<1r}", v8); // 2 fields, 1 arg -> abort
- In
Write.c:5052:
bool ok = BufWriteFmt(&b, "{<2r}{>4r}", (u16)0x1234, (u32)0xAABBCCDD);
ok = ok && (BufLength(&b) == 6);
BufIter it = BufIterFromBuf(&b);
u16 a = 0;
u32 c = 0;- In
Read.c:1221:
ok = ok && BufPushBytes(&b, bytes, 4);
BufIter it = BufIterFromBuf(&b);
u32 v32 = 0;
bool rd_ok = BufReadFmt(&it, "{>4r}", v32);- In
Read.c:1254:
ok = ok && BufPushBytes(&b, bytes, 4);
BufIter it = BufIterFromBuf(&b);
u32 v32 = 0;
bool rd_ok = BufReadFmt(&it, "{<4r}", v32);- In
Read.c:1279:
ok = ok && BufPushBytes(&b, bytes, 4);
BufIter it = BufIterFromBuf(&b);
u32 v32 = 0;
bool rd_ok = BufReadFmt(&it, "{<4r}", v32);- In
Read.c:1314:
ok = ok && (BufLength(&b) == 4);
BufIter it = BufIterFromBuf(&b);
u32 v32 = 0;
bool rd_ok = BufReadFmt(&it, "{^4r}", v32);- In
Read.c:1356:
ok = ok && (BufLength(&b) == 8);
BufIter it = BufIterFromBuf(&b);
u64 v64 = 0;
bool rd_ok = BufReadFmt(&it, "{<8r}", v64);- In
Read.c:1383:
ok = ok && (BufLength(&b) == 8);
BufIter it = BufIterFromBuf(&b);
u64 v64 = 0;
bool rd_ok = BufReadFmt(&it, "{<8r}", v64);- In
Read.c:1413:
ok = ok && (BufLength(&b) == 8);
BufIter it = BufIterFromBuf(&b);
u64 v64 = 0;
bool rd_ok = BufReadFmt(&it, "{^8r}", v64);- In
Read.c:1594:
bool ok = BufAppendFmt(&b, "{<1r}", (u8)0xAB);
BufIter it = BufIterFromBuf(&b);
u8 out = 0;
ok = ok && BufReadFmt(&it, "{<1r}", out) && (out == 0xAB);- In
Read.c:2219:
Buf b = BufInit(&alloc);
bool ok = BufWriteFmt(&b, "{<2r}", (u16)0xBEEF);
BufIter it = BufIterFromBuf(&b);
u16 v = 0;
ok = ok && BufReadFmt(&it, "{<2r}", v) && (v == 0xBEEF);- In
Read.c:2237:
} got = {0};
bool ok = BufWriteFmt(&b, "{<8r}", (u64)0x0102030405060708ULL);
BufIter it = BufIterFromBuf(&b);
ok = ok && BufReadFmt(&it, "{<8r}", got.f) && (got.u == 0x0102030405060708ULL);
BufDeinit(&b);- In
Deadend.c:15:
bool deadend_must_read_eof(void) {
const u8 buf[1] = {1};
BufIter it = BufIterFromMemory(buf, 1);
u8 v;
IterRead(&it, &v);- In
Deadend.c:24:
bool deadend_must_peek_out_of_range(void) {
const u8 buf[1] = {1};
BufIter it = BufIterFromMemory(buf, 1);
u8 v;
IterMustPeekAt(&it, 1, &v);- In
Deadend.c:32:
bool deadend_must_move_overflow(void) {
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
IterMustMove(&it, 4);
return true;- In
Deadend.c:39:
bool deadend_must_next_eof(void) {
const u8 buf[1] = {0};
BufIter it = BufIterFromMemory(buf, 1);
u8 v;
IterRead(&it, &v);- In
Deadend.c:48:
bool deadend_must_prev_underflow(void) {
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
IterMustPrev(&it);
return true;- In
Deadend.c:59:
bool deadend_it_validate_bad_dir(void) {
const u8 buf[2] = {1, 2};
BufIter it = {.data = buf, .length = 2, .pos = 0, .alignment = 1, .dir = 0};
ValidateIter(&it);
return true;- In
Deadend.c:67:
bool deadend_it_validate_zero_alignment(void) {
const u8 buf[2] = {1, 2};
BufIter it = {.data = buf, .length = 2, .pos = 0, .alignment = 0, .dir = 1};
ValidateIter(&it);
return true;- In
Deadend.c:78:
bool deadend_it_remaining_bad_dir(void) {
const u8 buf[2] = {1, 2};
BufIter it = {.data = buf, .length = 2, .pos = 0, .alignment = 1, .dir = 0};
(void)IterRemainingLength(&it);
return true;- In
Deadend.c:86:
bool deadend_it_move_bad_dir(void) {
const u8 buf[2] = {1, 2};
BufIter it = {.data = buf, .length = 2, .pos = 0, .alignment = 1, .dir = 0};
(void)IterMove(&it, 1);
return true;- In
Iter.c:10:
// No public reverse-iter constructor yet; open-coded until a
// BufIterFromMemoryRev (or similar) is added.
static BufIter from_rev(const u8 *p, size n) {
BufIter it = {.data = p, .length = n, .pos = n - 1, .alignment = 1, .dir = -1};
return it;- In
Iter.c:11:
// BufIterFromMemoryRev (or similar) is added.
static BufIter from_rev(const u8 *p, size n) {
BufIter it = {.data = p, .length = n, .pos = n - 1, .alignment = 1, .dir = -1};
return it;
}- In
Iter.c:21:
bool test_iter_remaining_forward(void) {
const u8 buf[3] = {1, 2, 3};
BufIter it = BufIterFromMemory(buf, 3);
if (IterRemainingLength(&it) != 3) {
return false;- In
Iter.c:37:
bool test_iter_remaining_reverse(void) {
const u8 buf[3] = {1, 2, 3};
BufIter it = from_rev(buf, 3);
if (IterRemainingLength(&it) != 3) {
return false;- In
Iter.c:53:
bool test_iter_read_forward(void) {
const u8 buf[3] = {10, 20, 30};
BufIter it = BufIterFromMemory(buf, 3);
u8 v = 0;
if (!IterRead(&it, &v) || v != 10) {- In
Iter.c:70:
bool test_iter_read_reverse(void) {
const u8 buf[3] = {10, 20, 30};
BufIter it = from_rev(buf, 3);
u8 v = 0;
if (!IterRead(&it, &v) || v != 30) {- In
Iter.c:87:
bool test_iter_read_eof_leaves_state(void) {
const u8 buf[1] = {7};
BufIter it = BufIterFromMemory(buf, 1);
u8 v = 0;
IterRead(&it, &v);- In
Iter.c:102:
bool test_iter_peek_in_range(void) {
const u8 buf[4] = {5, 6, 7, 8};
BufIter it = BufIterFromMemory(buf, 4);
IterMove(&it, 2);
u8 v;- In
Iter.c:120:
bool test_iter_peek_out_of_range(void) {
const u8 buf[2] = {1, 2};
BufIter it = BufIterFromMemory(buf, 2);
u8 v = 0xAA;
if (IterPeekAt(&it, 2, &v)) {- In
Iter.c:137:
bool test_iter_move_forward_basic(void) {
const u8 buf[5] = {0};
BufIter it = BufIterFromMemory(buf, 5);
if (!IterMove(&it, 3) || IterIndex(&it) != 3) {
return false;- In
Iter.c:149:
bool test_iter_move_forward_to_exhausted(void) {
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
if (!IterMove(&it, 3) || IterIndex(&it) != 3) {
return false;- In
Iter.c:158:
bool test_iter_move_forward_overflow(void) {
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
size before = IterIndex(&it);
if (IterMove(&it, 4)) {- In
Iter.c:168:
bool test_iter_move_forward_underflow(void) {
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
if (IterMove(&it, -1)) {
return false;- In
Iter.c:177:
bool test_iter_move_reverse_basic(void) {
const u8 buf[5] = {0};
BufIter it = from_rev(buf, 5);
// start at pos=4
if (!IterMove(&it, 2) || IterIndex(&it) != 2) {- In
Iter.c:191:
bool test_iter_move_reverse_to_past_start(void) {
const u8 buf[3] = {0};
BufIter it = from_rev(buf, 3);
// pos=2, dir=-1, move by 3 lands on sentinel pos=-1
if (!IterMove(&it, 3) || IterIndex(&it) != (size)-1) {- In
Iter.c:201:
bool test_iter_move_reverse_overflow(void) {
const u8 buf[3] = {0};
BufIter it = from_rev(buf, 3);
// pos=2, dir=-1, move by 4 would land at pos=-2 — invalid
size before = IterIndex(&it);- In
Iter.c:212:
bool test_iter_next_prev(void) {
const u8 buf[3] = {0};
BufIter it = BufIterFromMemory(buf, 3);
if (!IterNext(&it) || IterIndex(&it) != 1) {
return false;- In
Iter.c:236:
bool test_it_peek_from_reverse_sentinel(void) {
const u8 buf[3] = {10, 20, 30};
BufIter it = from_rev(buf, 3);
// Step past the start so pos becomes the (size)-1 sentinel.
IterMove(&it, 3);- In
Iter.c:256:
bool test_it_peek_reverse_nonsentinel_uses_pos(void) {
const u8 buf[3] = {10, 20, 30};
BufIter it = from_rev(buf, 3);
if (IterIndex(&it) != 2) {
return false;- In
Iter.c:275:
bool test_it_move_out_of_reverse_sentinel(void) {
const u8 buf[3] = {10, 20, 30};
BufIter it = from_rev(buf, 3);
IterMove(&it, 3); // -> sentinel
if (IterIndex(&it) != (size)-1) {- In
Iter.c:293:
bool test_it_move_reverse_to_max_position(void) {
const u8 buf[3] = {10, 20, 30};
BufIter it = from_rev(buf, 3);
IterMove(&it, 3); // -> sentinel (cur == -1)
// cur == -1, n == -3 -> delta +3 -> new_pos 2 == length-1 (top valid pos).
- In
Iter.c:308:
bool test_it_move_reverse_rejects_length(void) {
const u8 buf[3] = {10, 20, 30};
BufIter it = from_rev(buf, 3); // pos == 2
size before = IterIndex(&it);
// cur == 2, n == -1 -> delta +1 -> new_pos 3 == length: out of range.
- In
Iter.c:322:
bool test_it_move_reverse_to_index_zero(void) {
const u8 buf[3] = {10, 20, 30};
BufIter it = from_rev(buf, 3);
IterMove(&it, 3); // -> sentinel
// cur == -1, n == -1 -> new_pos 0: a real index, not the sentinel.
- In
Iter.c:337:
bool test_it_validate_accepts_forward(void) {
const u8 buf[2] = {1, 2};
BufIter it = BufIterFromMemory(buf, 2);
ValidateIter(&it);
return true;- In
Iter.c:344:
bool test_it_validate_accepts_reverse(void) {
const u8 buf[2] = {1, 2};
BufIter it = from_rev(buf, 2);
ValidateIter(&it);
return true;- In
Iter.c:357:
bool test_remaining_reverse_pos_eq_length_is_zero(void) {
const u8 buf[3] = {10, 20, 30};
BufIter it = from_rev(buf, 3); // dir == -1, pos == 2, length == 3
// length := pos + 0 == 2, so now pos (2) == length (2).
IterTruncate(&it, 0);- In
Iter.c:376:
bool test_iter_pos_current_and_exhausted(void) {
const u8 buf[2] = {40, 50};
BufIter it = BufIterFromMemory(buf, 2);
if (IterPos(&it) != &buf[0] || *IterPos(&it) != 40) {
return false;- In
Iter.c:389:
bool test_iter_data_at_index_and_end(void) {
const u8 buf[3] = {7, 8, 9};
BufIter it = BufIterFromMemory(buf, 3);
IterMove(&it, 1); // cursor moves; DataAt must ignore it
if (IterDataAt(&it, 0) != &buf[0] || *IterDataAt(&it, 2) != 9) {- In
Iter.c:415:
bool test_iter_truncate_caps_reads(void) {
const u8 buf[5] = {1, 2, 3, 4, 5};
BufIter it = BufIterFromMemory(buf, 5);
IterMove(&it, 1); // cursor at index 1
IterTruncate(&it, 2); // only indices 1,2 remain reachable
- In
Iter.c:437:
bool test_iter_carve_child_range(void) {
const u8 buf[4] = {10, 20, 30, 40};
BufIter parent = BufIterFromMemory(buf, 4);
IterMove(&parent, 1); // parent cursor at index 1
BufIter child = IterCarve(&parent, 2);- In
Iter.c:439:
BufIter parent = BufIterFromMemory(buf, 4);
IterMove(&parent, 1); // parent cursor at index 1
BufIter child = IterCarve(&parent, 2);
if (IterRemainingLength(&child) != 2 || IterIndex(&child) != 0) {
return false;
Last updated on