Skip to content

IterMove

Description

Propagating move by n positions in the iteration direction. n may be negative to step backward. The new position must land in [0, length] for forward iteration, or in [-1, length) for reverse iteration (where -1 is the past-start sentinel).

Success

Position is updated, returns true.

Failure

The new position would be out of range. Position is unchanged, returns false.

Usage example (Cross-references)

Usage examples (Cross-references)
    /// TAGS: StrIter, Move, Position, Alias
    ///
    #define StrIterMove(si, n) IterMove((si), (n))
    
    ///
    #define IterMustMove(mi, n)                                                                                            \
        do {                                                                                                               \
            if (!IterMove((mi), (n))) {                                                                                    \
                LOG_FATAL("IterMustMove: target position out of range");                                                   \
            }                                                                                                              \
    /// TAGS: Iter, Memory, Position
    ///
    #define IterNext(mi) IterMove((mi), 1)
    
    ///
    /// TAGS: Iter, Memory, Position
    ///
    #define IterPrev(mi) IterMove((mi), -1)
    
    ///
            return true;
        }
        if (!IterMove(&c, (i64)(DIR_INDEX_DEBUG * 8u)))
            return false;
        // Read into a local u32, then widen -- aliasing a u64* through a
                if (!BufReadU8(cur, &n))
                    return false;
                return IterMove(cur, (i64)(n));
            }
            case DW_FORM_block2 : {
                if (!BufReadU16LE(cur, &n))
                    return false;
                return IterMove(cur, (i64)(n));
            }
            case DW_FORM_block4 : {
                if (!BufReadU32LE(cur, &n))
                    return false;
                return IterMove(cur, (i64)(n));
            }
            case DW_FORM_block :
                if (!BufReadULeb128(cur, &n))
                    return false;
                return IterMove(cur, (i64)(n));
            }
            case DW_FORM_indirect : {
        if (!BufReadFmt(it, "TZif{>1r}", ver))
            return false;
        if (!IterMove(it, 15)) // reserved
            return false;
        bool have_chosen = false;
        if (found) {
            if (best > 0 && !IterMove(it, best))
                return false;
            if (!BufReadFmt(it, "{>1r}", chosen))
            have_chosen = true;
            i64 rest    = (i64)timecnt - best - 1;
            if (rest > 0 && !IterMove(it, rest))
                return false;
        } else if (timecnt > 0 && !IterMove(it, (i64)timecnt)) {
            if (rest > 0 && !IterMove(it, rest))
                return false;
        } else if (timecnt > 0 && !IterMove(it, (i64)timecnt)) {
            return false;
        }
            // Skip the v1 data block, then parse the v2+ header and its
            // 8-byte-time data block (the authoritative one).
            if (!IterMove(&it, (i64)tzif_v1_data_size(&h1))) {
                LOG_ERROR("Tzif: truncated v1 data block");
                return false;
    
        u64 name_padded = ((u64)namesz + 3u) & ~(u64)3u;
        if (!IterMove(&it, (i64)name_padded))
            return;
        const u8 buf[2] = {1, 2};
        BufIter  it     = {.data = buf, .length = 2, .pos = 0, .alignment = 1, .dir = 0};
        (void)IterMove(&it, 1);
        return true;
    }
        const u8 buf[4] = {5, 6, 7, 8};
        BufIter  it     = BufIterFromMemory(buf, 4);
        IterMove(&it, 2);
        u8 v;
        if (!IterPeekAt(&it, 0, &v) || v != 7) {
        const u8 buf[5] = {0};
        BufIter  it     = BufIterFromMemory(buf, 5);
        if (!IterMove(&it, 3) || IterIndex(&it) != 3) {
            return false;
        }
            return false;
        }
        if (!IterMove(&it, -2) || IterIndex(&it) != 1) {
            return false;
        }
        const u8 buf[3] = {0};
        BufIter  it     = BufIterFromMemory(buf, 3);
        if (!IterMove(&it, 3) || IterIndex(&it) != 3) {
            return false;
        }
        BufIter  it     = BufIterFromMemory(buf, 3);
        size     before = IterIndex(&it);
        if (IterMove(&it, 4)) {
            return false;
        }
        const u8 buf[3] = {0};
        BufIter  it     = BufIterFromMemory(buf, 3);
        if (IterMove(&it, -1)) {
            return false;
        }
        BufIter  it     = from_rev(buf, 5);
        // start at pos=4
        if (!IterMove(&it, 2) || IterIndex(&it) != 2) {
            return false;
        }
        }
        // step backward in reverse direction (n=-1, effective +1)
        if (!IterMove(&it, -1) || IterIndex(&it) != 3) {
            return false;
        }
        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) {
            return false;
        }
        // pos=2, dir=-1, move by 4 would land at pos=-2 — invalid
        size before = IterIndex(&it);
        if (IterMove(&it, 4)) {
            return false;
        }
        BufIter  it     = from_rev(buf, 3);
        // Step past the start so pos becomes the (size)-1 sentinel.
        IterMove(&it, 3);
        if (IterIndex(&it) != (size)-1) {
            return false;
        const u8 buf[3] = {10, 20, 30};
        BufIter  it     = from_rev(buf, 3);
        IterMove(&it, 3); // -> sentinel
        if (IterIndex(&it) != (size)-1) {
            return false;
        }
        // cur == -1, n == -1 -> new_pos 0.
        if (!IterMove(&it, -1) || IterIndex(&it) != 0) {
            return false;
        }
        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).
        if (!IterMove(&it, -3) || IterIndex(&it) != 2) {
        IterMove(&it, 3); // -> sentinel (cur == -1)
        // cur == -1, n == -3 -> delta +3 -> new_pos 2 == length-1 (top valid pos).
        if (!IterMove(&it, -3) || IterIndex(&it) != 2) {
            return false;
        }
        size     before = IterIndex(&it);
        // cur == 2, n == -1 -> delta +1 -> new_pos 3 == length: out of range.
        if (IterMove(&it, -1)) {
            return false;
        }
        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.
        if (!IterMove(&it, -1) || IterIndex(&it) != 0) {
        IterMove(&it, 3); // -> sentinel
        // cur == -1, n == -1 -> new_pos 0: a real index, not the sentinel.
        if (!IterMove(&it, -1) || IterIndex(&it) != 0) {
            return false;
        }
            return false;
        }
        IterMove(&it, 2); // exhaust
        return IterPos(&it) == NULL_ITER_DATA(&it);
    }
        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) {
            return false;
            return false;
        }
        IterMove(&it, 1);
        // RemainingSize follows the cursor: 2 elements * 8-byte stride.
        return IterRemainingSize(&it) == 16;
        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
        if (IterRemainingLength(&it) != 2) {
        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);
        if (IterRemainingLength(&child) != 2 || IterIndex(&child) != 0) {
Last updated on