Пример #1
0
IV
srl_iterator_array_exists(pTHX_ srl_iterator_t *iter, I32 idx)
{
    I32 s_idx;
    srl_iterator_stack_ptr stack_ptr = iter->stack.ptr;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_ASSERT_EOF(iter, "array element");
    SRL_ITER_ASSERT_STACK(iter);
    SRL_ITER_ASSERT_ARRAY_ON_STACK(iter);

    SRL_ITER_TRACE("idx=%d", idx);
    SRL_ITER_REPORT_STACK_STATE(iter);

    if (idx >= 0) {
        s_idx = stack_ptr->count - idx;
        if (idx >= (I32) stack_ptr->count) {
            SRL_ITER_TRACE("Index is out of range, idx=%d count=%u", idx, stack_ptr->count);
            return SRL_ITER_NOT_FOUND;
        }
    } else {
        s_idx = -idx;
        if (s_idx > (I32) stack_ptr->count) {
            SRL_ITER_TRACE("Index is out of range, idx=%d count=%u", idx, stack_ptr->count);
            return SRL_ITER_NOT_FOUND;
        }
    }

    return s_idx;
}
Пример #2
0
void
srl_iterator_unite(pTHX_ srl_iterator_t *iter)
{
    UV offset;
    srl_stack_t *stack = iter->pstack;
    SRL_ITER_TRACE("--------------------------");

    if (expect_false(SRL_STACK_DEPTH(stack) <= 0))
        SRL_ITER_ERROR("There is nothing to unite. Please call disjoin first.");

    while (!SRL_ITER_STACK_ON_ROOT(stack)) {
        srl_stack_pop(stack);
    }

    offset = stack->ptr->offset;
    srl_stack_pop(stack); // remove SRL_ITER_STACK_ROOT_TAG

    SRL_ITER_ASSERT_STACK(iter);
    iter->buf.pos = iter->buf.body_pos + offset;

    SRL_ITER_REPORT_STACK_STATE(iter);
    SRL_ITER_TRACE("ofs %"UVuf" body_ofs %"UVuf,
                   (UV) SRL_RDR_POS_OFS((iter)->pbuf),
                   (UV) SRL_RDR_BODY_POS_OFS((iter)->pbuf));

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}
Пример #3
0
void
srl_iterator_next_until_depth_and_idx(pTHX_ srl_iterator_t *iter, UV expected_depth, U32 expected_idx) {
    U32 current_idx;
    srl_stack_t *stack = iter->stack;
    IV current_depth = SRL_STACK_DEPTH(stack);

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_TRACE("expected_depth=%"UVuf" expected_idx=%u",
                   expected_depth, expected_idx);

    SRL_ITER_ASSERT_STACK(iter);
    if (expect_false((IV) expected_depth > current_depth)) {
        SRL_ITER_ERRORf2("srl_iterator_next_until_depth() can only go forward, "
                         "so expected_depth=%"UVuf" should not be greater then current_depth=%"IVdf,
                         expected_depth, current_depth);
    }

    current_idx = stack->ptr->idx;
    if (expect_false((IV) expected_depth == current_depth && expected_idx == current_idx))
        return;

    while (expect_true(!srl_stack_empty(stack))) {
        srl_iterator_wrap_stack(aTHX_ iter, expected_depth);

        current_depth = SRL_STACK_DEPTH(stack);
        if (expect_false(srl_stack_empty(stack)))
            break;

        current_idx  = stack->ptr->idx;
        if (current_depth == (IV) expected_depth && current_idx == expected_idx)
            break;

        if (expect_false(current_depth == (IV) expected_depth && expected_idx > current_idx)) {
            SRL_ITER_ERRORf2("srl_iterator_next_until_depth() can only go forward, "
                             "so expected_idx=%d should not be greater then current_idx=%d",
                             expected_idx, current_idx);
        }

        srl_iterator_step_internal(aTHX_ iter);
    }

    if (expect_false(current_depth != (IV) expected_depth)) {
        SRL_ITER_ERRORf2("func led to wrong stack depth, expected=%"IVdf", actual=%"IVdf,
                          expected_depth, current_depth);
    }

    if (expect_false(current_idx != expected_idx)) {
        SRL_ITER_ERRORf2("func led to wrong stack index, expected=%u, actual=%u",
                          expected_idx, current_idx);
    }

    SRL_ITER_TRACE("Reached expected stack depth: %"UVuf " and idx: %u",
                   expected_depth, expected_idx);
    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}
Пример #4
0
void
srl_iterator_next_until_depth_and_idx(pTHX_ srl_iterator_t *iter, UV expected_depth, U32 expected_idx) {
    IV current_depth = iter->stack.depth;
    srl_iterator_stack_ptr stack_ptr = iter->stack.ptr;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_ASSERT_STACK(iter);

    SRL_ITER_TRACE("expected_depth=%"UVuf" expected_idx=%u", expected_depth, expected_idx);
    SRL_ITER_REPORT_STACK_STATE(iter);

    if (expect_false((IV) expected_depth == current_depth && (IV) expected_idx == stack_ptr->idx))
        return;

    if (expect_false((IV) expected_depth > current_depth)) {
        SRL_ITER_ERRORf2("srl_iterator_next_until_depth() can only go forward, "
                         "so expected_depth=%"UVuf" should not be greater then current_depth=%"IVdf,
                         expected_depth, current_depth);
    }

    stack_ptr = iter->stack.begin + expected_depth;
    if (expect_false((IV) expected_idx > stack_ptr->idx)) {
        SRL_ITER_ERRORf3("srl_iterator_next_until_depth() can only go forward, "
                         "so expected_idx=%u should not be greater then current "
                         "index (%u) at expected_depth=%"IVdf,
                         expected_idx, stack_ptr->idx, expected_depth);
    }

    stack_ptr = iter->stack.ptr;

    while (1) {
        srl_iterator_wrap_stack(iter, expected_depth, stack_ptr);

        if (iter->stack.depth == (IV) expected_depth) {
            if (stack_ptr->idx == (IV) expected_idx)  break;
            assert(((IV) expected_idx > stack_ptr->idx) == 0);
        }

        srl_iterator_step_internal(iter, stack_ptr);
    }

    assert(stack_ptr->idx == (IV) expected_idx);
    assert(iter->stack.depth == (IV) expected_depth);
    SRL_ITER_TRACE("Reached expected stack depth: %"UVuf " and idx: %u",
                   expected_depth, expected_idx);

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}
Пример #5
0
void
srl_iterator_step_out(pTHX_ srl_iterator_t *iter, UV n)
{
    UV offset;
    srl_stack_t *stack = iter->stack;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_TRACE("n=%"UVuf, n);

    SRL_ITER_ASSERT_STACK(iter);
    // SRL_ITER_ASSERT_EOF(iter, "serialized object"); XXX need ability to go back on last element
    // if (expect_false(n == 0)) return; XXX keep it as a feature?

    while (n--) {
        srl_stack_pop_nocheck(stack);
        if (expect_false(srl_stack_empty(stack))) {
            SRL_ITER_ERROR("It was last object on stack, no more parents");
        }
    }

    offset = stack->ptr->offset; 
    iter->buf.pos = iter->buf.body_pos + offset;
    stack->ptr->idx = stack->ptr->count;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}
Пример #6
0
void
srl_iterator_reset(pTHX_ srl_iterator_t *iter)
{
    U8 tag = '\0';
    SRL_ITER_TRACE();
    srl_stack_clear(iter->stack);
    srl_stack_push_and_set(iter, tag, 1);
    iter->buf.pos = iter->buf.body_pos + iter->first_tag_offset;
    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}
Пример #7
0
void
srl_iterator_step_in(pTHX_ srl_iterator_t *iter, UV n)
{
    srl_iterator_stack_ptr stack_ptr = iter->stack.ptr;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_ASSERT_STACK(iter);

    SRL_ITER_TRACE("n=%"UVuf, n);
    SRL_ITER_REPORT_STACK_STATE(iter);

    while (n--) {
        srl_iterator_wrap_stack(iter, -1, stack_ptr);
        srl_iterator_step_internal(iter, stack_ptr);
    }

    SRL_ITER_TRACE("Completed expected number of steps");
    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}
Пример #8
0
void
srl_iterator_reset(pTHX_ srl_iterator_t *iter)
{
    srl_stack_t *stack = iter->pstack;
    SRL_ITER_TRACE("--------------------------");

    while (!SRL_ITER_STACK_ON_ROOT(stack)) {
        srl_stack_pop(stack); // does empty check internally
    }

    srl_iterator_restore_stack_position(aTHX_ iter);
}
Пример #9
0
IV
srl_iterator_array_goto(pTHX_ srl_iterator_t *iter, I32 idx)
{
    I32 s_idx;
    srl_iterator_stack_ptr stack_ptr = iter->stack.ptr;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_ASSERT_EOF(iter, "array element");
    SRL_ITER_ASSERT_STACK(iter);
    SRL_ITER_ASSERT_ARRAY_ON_STACK(iter);

    SRL_ITER_TRACE("idx=%d", idx);
    SRL_ITER_REPORT_STACK_STATE(iter);

    if (idx >= 0) {
        s_idx = stack_ptr->count - idx;
        if (idx >= (I32) stack_ptr->count) {
            SRL_ITER_TRACE("Index is out of range, idx=%d count=%u", idx, stack_ptr->count);
            return SRL_ITER_NOT_FOUND;
        }
    } else {
        s_idx = -idx;
        if (s_idx > (I32) stack_ptr->count) {
            SRL_ITER_TRACE("Index is out of range, idx=%d count=%u", idx, stack_ptr->count);
            return SRL_ITER_NOT_FOUND;
        }
    }

    if (s_idx == stack_ptr->idx) {
        return SRL_RDR_BODY_POS_OFS(iter->pbuf); // already at expected position
    } else if (s_idx > stack_ptr->idx) {
        SRL_ITER_ERRORf2("Can't go backwards, idx=%d, count=%u",
                         idx, stack_ptr->count);
    }

    // srl_iterator_next garantee that we remans on current stack
    srl_iterator_next(aTHX_ iter, stack_ptr->idx - s_idx);
    assert(stack_ptr->idx == s_idx);
    return SRL_RDR_BODY_POS_OFS(iter->pbuf);
}
Пример #10
0
void
srl_iterator_next(pTHX_ srl_iterator_t *iter, UV n)
{
    IV expected_depth = iter->stack.depth;
    srl_iterator_stack_ptr stack_ptr = iter->stack.ptr;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_ASSERT_STACK(iter);

    SRL_ITER_TRACE("n=%"UVuf, n);
    SRL_ITER_REPORT_STACK_STATE(iter);

    if (expect_false(n == 0)) return;

    while (1) {
        srl_iterator_wrap_stack(iter, expected_depth, stack_ptr);

        if (iter->stack.depth == expected_depth) {
            if (n == 0) break;
            else n--;
        }

        srl_iterator_step_internal(iter, stack_ptr);
    }

    if (expect_false(n != 0)) {
        SRL_ITER_ERRORf1("Failed to do %"UVuf" next steps. Likely EOF was reached", n);
    }

    if (expect_false(iter->stack.depth != expected_depth)) {
        SRL_ITER_ERRORf2("next() led to wrong stack depth, expected=%"IVdf", actual=%"IVdf,
                          expected_depth, iter->stack.depth);
    }

    SRL_ITER_TRACE("Did expected number of steps at depth %"IVdf, expected_depth);
    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}
Пример #11
0
void
srl_iterator_step_in(pTHX_ srl_iterator_t *iter, UV n)
{
    srl_stack_t *stack = iter->stack;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_TRACE("n=%"UVuf, n);

    SRL_ITER_ASSERT_STACK(iter);
    if (expect_false(n == 0)) return;

    while (expect_true(!srl_stack_empty(stack))) {
        if (n == 0) break;
        srl_iterator_step_internal(aTHX_ iter);
        n--;
    }

    if (expect_false(n != 0)) {
        SRL_ITER_ERRORf1("Failed to do %"UVuf" steps. Likely EOF was reached", n);
    }

    SRL_ITER_TRACE("Did expected number of steps");
    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}
Пример #12
0
SRL_STATIC_INLINE void
srl_iterator_restore_stack_position(pTHX_ srl_iterator_t *iter)
{
    SRL_ITER_ASSERT_STACK(iter);

    iter->stack.ptr->idx = iter->stack.ptr->count;
    iter->buf.pos = iter->buf.body_pos + iter->stack.ptr->offset;

    SRL_ITER_REPORT_STACK_STATE(iter);
    SRL_ITER_TRACE("ofs %"UVuf" body_ofs %"UVuf,
                   (UV) SRL_RDR_POS_OFS((iter)->pbuf),
                   (UV) SRL_RDR_BODY_POS_OFS((iter)->pbuf));

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}
Пример #13
0
SRL_STATIC_INLINE void
srl_iterator_wrap_stack(pTHX_ srl_iterator_t *iter, IV expected_depth)
{
    srl_stack_t *stack = iter->stack;
    if (expect_false(SRL_STACK_DEPTH(stack) < expected_depth))
        SRL_ITER_ERRORf2("expected depth %"IVdf" is higher than current depth %"IVdf,
                         expected_depth, SRL_STACK_DEPTH(stack));

    while (!srl_stack_empty(stack) && stack->ptr->idx == 0) {
        if (SRL_STACK_DEPTH(stack) == expected_depth) break;
        srl_stack_pop_nocheck(stack);
        if (srl_stack_empty(stack))
            SRL_ITER_TRACE("end of stack reached");
    }
}
Пример #14
0
void
srl_iterator_next(pTHX_ srl_iterator_t *iter, UV n)
{
    srl_stack_t *stack = iter->stack;
    IV expected_depth = SRL_STACK_DEPTH(stack);

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_TRACE("n=%"UVuf, n);

    SRL_ITER_ASSERT_STACK(iter);
    if (expect_false(n == 0)) return;
    if (expect_false(stack->ptr->idx == 0))
        SRL_ITER_ERROR("Nothing to parse at this depth");

    while (expect_true(!srl_stack_empty(stack))) {
        if (SRL_STACK_DEPTH(stack) == expected_depth) {
            if (n == 0) break;
            else n--;
        }

        srl_iterator_step_internal(aTHX_ iter);
        srl_iterator_wrap_stack(aTHX_ iter, expected_depth);
    }

    if (expect_false(n != 0)) {
        SRL_ITER_ERRORf1("Failed to do %"UVuf" next steps. Likely EOF was reached", n);
    }

    if (expect_false(SRL_STACK_DEPTH(stack) != expected_depth)) {
        SRL_ITER_ERRORf2("next() led to wrong stack depth, expected=%"IVdf", actual=%"IVdf,
                          expected_depth, SRL_STACK_DEPTH(stack));
    }

    SRL_ITER_TRACE("Did expected number of steps at depth %"IVdf, expected_depth);
    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}
Пример #15
0
void
srl_iterator_disjoin(pTHX_ srl_iterator_t *iter)
{
    srl_iterator_stack_ptr stack_ptr;

    SRL_ITER_REPORT_STACK_STATE(iter);
    SRL_ITER_TRACE("ofs %"UVuf" body_ofs %"UVuf,
                   (UV) SRL_RDR_POS_OFS((iter)->pbuf),
                   (UV) SRL_RDR_BODY_POS_OFS((iter)->pbuf));

    // This record apart of being a boundary stores offset to idx's tag (i.e
    // current tag). By default stack keeps offset to tag's starting point
    // (i.e. continer located in the buf).

    srl_stack_push_ptr(iter->pstack, stack_ptr);
    stack_ptr->offset = SRL_RDR_BODY_POS_OFS(iter->pbuf); // disjoint point
    stack_ptr->tag = SRL_ITER_STACK_ROOT_TAG;
    stack_ptr->count = 1;
    stack_ptr->idx = 1;
}
Пример #16
0
void
srl_copy_iterator(pTHX_ srl_iterator_t *from, srl_iterator_t *to)
{
    assert(from != NULL);
    assert(to != NULL);
    SRL_ITER_TRACE("from=%p to=%p", from, to);

    if (srl_stack_copy(aTHX_ &from->stack, &to->stack) != 0)
        croak("Out of memory");

    /* it's assumed that buf holds buffer owned by sv */
    to->document = from->document;
    if (to->document) SvREFCNT_inc(to->document);
    Copy(&from->buf, &to->buf, 1, srl_reader_buffer_t);

    to->pstack = &to->stack;
    to->pbuf = &to->buf;
    to->dec = NULL;

    assert(to->buf.pos == from->buf.pos);
}
Пример #17
0
void
srl_iterator_step_out(pTHX_ srl_iterator_t *iter, UV n)
{
    srl_stack_t *stack = iter->pstack;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_ASSERT_STACK(iter);

    SRL_ITER_TRACE("n=%"UVuf, n);
    SRL_ITER_REPORT_STACK_STATE(iter);

    // SRL_ITER_ASSERT_EOF(iter, "serialized object"); XXX need ability to go back on last element
    // if (expect_false(n == 0)) return; XXX keep it as a feature?

    while (n--) {
        if (expect_false(SRL_ITER_STACK_ON_ROOT(stack))) {
            SRL_ITER_ERROR("It was last object on stack, no more parents");
        }

        srl_stack_pop_nocheck(stack);
    }

    srl_iterator_restore_stack_position(aTHX_ iter);
}
Пример #18
0
IV
srl_iterator_hash_exists(pTHX_ srl_iterator_t *iter, const char *name, STRLEN name_len)
{
    U8 tag;
    UV length, offset;
    const char *key_ptr;

    IV stack_depth = iter->stack.depth;
    srl_iterator_stack_ptr stack_ptr = iter->stack.ptr;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
    SRL_ITER_ASSERT_EOF(iter, "stringish");
    SRL_ITER_ASSERT_STACK(iter);
    SRL_ITER_ASSERT_HASH_ON_STACK(iter);

    SRL_ITER_TRACE("name=%.*s", (int) name_len, name);
    SRL_ITER_REPORT_STACK_STATE(iter);

    while (stack_ptr->idx) {
        stack_ptr->idx--; // do not make it be part of while clause
        SRL_ITER_ASSERT_STACK(iter);
        assert(stack_ptr->idx % 2 == 1);
        assert(iter->stack.depth == stack_depth);
        DEBUG_ASSERT_RDR_SANE(iter->pbuf);

        tag = *iter->buf.pos & ~SRL_HDR_TRACK_FLAG;
        SRL_ITER_REPORT_TAG(iter, tag);
        iter->buf.pos++;

        switch (tag) {
            CASE_SRL_HDR_SHORT_BINARY:
                length = SRL_HDR_SHORT_BINARY_LEN_FROM_TAG(tag);
                key_ptr = (const char *) iter->buf.pos;
                iter->buf.pos += length;
                break;

            case SRL_HDR_BINARY:
                length = srl_read_varint_uv_length(aTHX_ iter->pbuf, " while reading BINARY");
                key_ptr = (const char *) iter->buf.pos;
                iter->buf.pos += length;
                break;

            case SRL_HDR_STR_UTF8:      
                // TODO deal with UTF8
                length = srl_read_varint_uv_length(aTHX_ iter->pbuf, " while reading STR_UTF8");
                key_ptr = (const char *) iter->buf.pos;
                iter->buf.pos += length;
                break;

            case SRL_HDR_COPY:
                offset = srl_read_varint_uv_offset(aTHX_ iter->pbuf, " while reading COPY tag");
                key_ptr = (const char *) iter->buf.body_pos + offset;
                tag = *key_ptr & ~SRL_HDR_TRACK_FLAG;
                key_ptr++;

                /* Note we do NOT validate these items, as we have already read them
                 * and if they were a problem we would not be here to process them! */

                switch (tag) {
                    CASE_SRL_HDR_SHORT_BINARY:
                        length = SRL_HDR_SHORT_BINARY_LEN_FROM_TAG(tag);
                        break;

                    case SRL_HDR_BINARY:
                        SET_UV_FROM_VARINT(iter->pbuf, length, key_ptr);
                        break;

                    case SRL_HDR_STR_UTF8:
                        // TODO deal with UTF8
                        SET_UV_FROM_VARINT(iter->pbuf, length, key_ptr);
                        break;

                    default:
                        SRL_RDR_ERROR_BAD_COPY(iter->pbuf, SRL_HDR_HASH);
                }

                break;

            default:
                SRL_RDR_ERROR_UNEXPECTED(iter->pbuf, tag, "stringish");
        }

        if (expect_false((srl_reader_char_ptr) key_ptr >= iter->buf.end)) {
            SRL_RDR_ERROR_EOF(iter->pbuf, "string content");
        }

        if (   length == name_len
            && memcmp(name, key_ptr, name_len) == 0)
        {
            SRL_ITER_TRACE("found key '%.*s' at offset %"UVuf,
                         (int) name_len, name, SRL_RDR_BODY_POS_OFS(iter->pbuf));
            return SRL_RDR_BODY_POS_OFS(iter->pbuf);
        }

        // srl_iterator_next garantee that we remans on current stack
        srl_iterator_next(aTHX_ iter, 1);
        stack_ptr = iter->stack.ptr;
    }

    SRL_ITER_TRACE("didn't found key '%.*s'", (int) name_len, name);
    return SRL_ITER_NOT_FOUND;
}
Пример #19
0
/* Main routine. Caller must ensure that EOF is NOT reached */
SRL_STATIC_INLINE void
srl_iterator_step_internal(pTHX_ srl_iterator_t *iter)
{
    U8 tag;
    UV length;
    srl_stack_t *stack = iter->stack;

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);

    srl_iterator_wrap_stack(aTHX_ iter, -1);
    if (srl_stack_empty(stack)) return;

    SRL_ITER_ASSERT_STACK(iter);

    stack->ptr->idx--;
    SRL_ITER_TRACE("stack->ptr: idx=%d depth=%d",
                   stack->ptr->idx, (int) SRL_STACK_DEPTH(stack));

    SRL_ITER_ASSERT_STACK(iter);

read_again:
    tag = *iter->buf.pos & ~SRL_HDR_TRACK_FLAG;
    SRL_ITER_REPORT_TAG(iter, tag);
    iter->buf.pos++;

    /* No code which decrease step, next or stack's counters should be added here.
     * Otherwise the counters will be decreased twicer for tags like REFN, ALIAS, etc. */

    switch (tag) {
        CASE_SRL_HDR_SHORT_BINARY:
            iter->buf.pos += SRL_HDR_SHORT_BINARY_LEN_FROM_TAG(tag);
            break;

        case SRL_HDR_HASH:
            length = srl_read_varint_uv_count(aTHX_ iter->pbuf, " while reading HASH");
            if (length > 0) srl_stack_push_and_set(iter, tag, length * 2);
            break;

        case SRL_HDR_ARRAY:
            length = srl_read_varint_uv_count(aTHX_ iter->pbuf, " while reading ARRAY");
            if (length > 0) srl_stack_push_and_set(iter, tag, length);
            break;

        CASE_SRL_HDR_HASHREF:
            length = SRL_HDR_HASHREF_LEN_FROM_TAG(tag);
            if (length > 0) srl_stack_push_and_set(iter, tag, length * 2);
            break;

        CASE_SRL_HDR_ARRAYREF:
            length = SRL_HDR_ARRAYREF_LEN_FROM_TAG(tag);
            if (length > 0) srl_stack_push_and_set(iter, tag, length);
            break;

        CASE_SRL_HDR_POS:
        CASE_SRL_HDR_NEG:
            break;

        case SRL_HDR_VARINT:
        case SRL_HDR_ZIGZAG:
            srl_skip_varint(aTHX_ iter->pbuf);
            break;

        case SRL_HDR_FLOAT:         iter->buf.pos += 4;      break;
        case SRL_HDR_DOUBLE:        iter->buf.pos += 8;      break;
        case SRL_HDR_LONG_DOUBLE:   iter->buf.pos += 16;     break;

        case SRL_HDR_TRUE:
        case SRL_HDR_FALSE:
        case SRL_HDR_UNDEF:
        case SRL_HDR_CANONICAL_UNDEF:
            break;

        case SRL_HDR_REFN:
        case SRL_HDR_ALIAS:
        case SRL_HDR_WEAKEN:
            goto read_again;

        case SRL_HDR_PAD:
            while (SRL_RDR_NOT_DONE(iter->pbuf) && *iter->buf.pos++ == SRL_HDR_PAD) {};
            goto read_again;

        case SRL_HDR_BINARY:
        case SRL_HDR_STR_UTF8:
            length = srl_read_varint_uv_length(aTHX_ iter->pbuf, " while reading BINARY or STR_UTF8");
            iter->buf.pos += length;
            break;

        case SRL_HDR_COPY:
        case SRL_HDR_REFP:
            srl_skip_varint(aTHX_ iter->pbuf);
            break;

        /* case SRL_HDR_OBJECTV: */
        /* case SRL_HDR_OBJECTV_FREEZE: */
        /* case SRL_HDR_REGEXP: */
        /* case SRL_HDR_OBJECT: */
        /* case SRL_HDR_OBJECT_FREEZE: */

        default:
            SRL_RDR_ERROR_UNIMPLEMENTED(iter->pbuf, tag, "");
            break;
    }

    DEBUG_ASSERT_RDR_SANE(iter->pbuf);
}