Beispiel #1
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);
}
Beispiel #2
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");
    }
}
Beispiel #3
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);
}
Beispiel #4
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);
}
Beispiel #5
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);
}
Beispiel #6
0
srl_iterator_stack_ptr
srl_iterator_stack(pTHX_ srl_iterator_t *iter)
{
    return srl_stack_empty(iter->pstack) ? NULL : iter->stack.ptr;
}
Beispiel #7
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);
}
Beispiel #8
0
SRL_STATIC_INLINE void
srl_merge_single_value(pTHX_ srl_merger_t *mrg)
{
    U8 tag;
    UV length, offset;
    ptable_entry_ptr ptable_entry;


read_again:
    assert(mrg->recursion_depth >= 0);
    DEBUG_ASSERT_RDR_SANE(mrg->pibuf);
    DEBUG_ASSERT_BUF_SANE(&mrg->obuf);

    if (expect_false(++mrg->recursion_depth > mrg->max_recursion_depth))
        SRL_RDR_ERRORf1(mrg->pibuf, "Reached recursion limit (%lu) during merging", mrg->max_recursion_depth);

    ptable_entry = NULL;
    if (expect_false(SRL_RDR_DONE(mrg->pibuf)))
        SRL_RDR_ERROR(mrg->pibuf, "Unexpected termination of input buffer");

    tag = *mrg->ibuf.pos & ~SRL_HDR_TRACK_FLAG;
    SRL_REPORT_CURRENT_TAG(mrg, tag);

    if (mrg->tracked_offsets && !srl_stack_empty(mrg->tracked_offsets)) {
        UV itag_offset = SRL_RDR_BODY_POS_OFS(mrg->pibuf);
        if (expect_false(itag_offset == srl_stack_peek_nocheck(aTHX_ mrg->tracked_offsets))) {
            // trackme case
            srl_stack_pop_nocheck(mrg->tracked_offsets);
            ptable_entry = srl_store_tracked_offset(aTHX_ mrg, itag_offset, BODY_POS_OFS(&mrg->obuf));
        }
    }

    if (tag <= SRL_HDR_NEG_HIGH) {
        srl_buf_cat_tag_nocheck(mrg, tag);
    } else if (tag >= SRL_HDR_ARRAYREF_LOW && tag <= SRL_HDR_ARRAYREF_HIGH) {
        srl_merge_array(aTHX_ mrg, tag, SRL_HDR_ARRAYREF_LEN_FROM_TAG(tag));
    } else if (tag >= SRL_HDR_HASHREF_LOW && tag <= SRL_HDR_HASHREF_HIGH) {
        srl_merge_hash(aTHX_ mrg, tag, SRL_HDR_HASHREF_LEN_FROM_TAG(tag));
    } else if (tag >= SRL_HDR_SHORT_BINARY_LOW) {
        srl_merge_short_binary(aTHX_ mrg, tag, ptable_entry);
    } else {
        switch (tag) {
            case SRL_HDR_VARINT:
            case SRL_HDR_ZIGZAG:
                srl_buf_cat_tag_nocheck(mrg, tag);
                srl_copy_varint(aTHX_ mrg);
                break;

            case SRL_HDR_FLOAT:         srl_buf_copy_content_nocheck(aTHX_ mrg, 5);  break;
            case SRL_HDR_DOUBLE:        srl_buf_copy_content_nocheck(aTHX_ mrg, 9);  break;
            case SRL_HDR_LONG_DOUBLE:   srl_buf_copy_content_nocheck(aTHX_ mrg, 17); break;

            case SRL_HDR_TRUE:
            case SRL_HDR_FALSE:
            case SRL_HDR_UNDEF:
            case SRL_HDR_CANONICAL_UNDEF:
                srl_buf_cat_tag_nocheck(mrg, tag);
                break;

            case SRL_HDR_BINARY:
            case SRL_HDR_STR_UTF8:
                srl_merge_binary_utf8(aTHX_ mrg, ptable_entry);
                break;

            case SRL_HDR_HASH:
                mrg->ibuf.pos++; // skip tag in input buffer
                length = srl_read_varint_uv_count(aTHX_ mrg->pibuf, " while reading ARRAY or HASH");
                srl_merge_hash(aTHX_ mrg, tag, length);
                break;

            case SRL_HDR_ARRAY:
                mrg->ibuf.pos++; // skip tag in input buffer
                length = srl_read_varint_uv_count(aTHX_ mrg->pibuf, " while reading ARRAY or HASH");
                srl_merge_array(aTHX_ mrg, tag, length);
                break;

            default:
                switch (tag) {
                    case SRL_HDR_COPY:
                    case SRL_HDR_REFP:
                    case SRL_HDR_ALIAS:
                        mrg->ibuf.pos++; // skip tag in input buffer
                        offset = srl_read_varint_uv_offset(aTHX_ mrg->pibuf, " while reading COPY/ALIAS/REFP");
                        offset = srl_lookup_tracked_offset(aTHX_ mrg, offset); // convert ibuf offset to obuf offset
                        srl_buf_cat_varint(aTHX_ &mrg->obuf, tag, offset);

                        if (tag == SRL_HDR_REFP || tag == SRL_HDR_ALIAS) {
                            SRL_SET_TRACK_FLAG(*(mrg->obuf.body_pos + offset));
                        }

                        break;

                    case SRL_HDR_REFN:
                    case SRL_HDR_WEAKEN:
                    case SRL_HDR_EXTEND:
                        srl_buf_cat_tag_nocheck(mrg, tag);
                        goto read_again;

                    case SRL_HDR_OBJECT:
                    case SRL_HDR_OBJECT_FREEZE:
                        srl_merge_object(aTHX_ mrg, tag);
                        break;

                    case SRL_HDR_REGEXP:
                        srl_buf_cat_tag_nocheck(mrg, tag);
                        srl_merge_stringish(aTHX_ mrg);

                        tag = *mrg->ibuf.pos;
                        if (expect_false(tag < SRL_HDR_SHORT_BINARY_LOW))
                            SRL_RDR_ERROR_UNEXPECTED(mrg->pibuf, tag, "SRL_HDR_SHORT_BINARY");

                        srl_buf_copy_content_nocheck(aTHX_ mrg, SRL_HDR_SHORT_BINARY_LEN_FROM_TAG(tag) + 1);
                        break;

                    case SRL_HDR_OBJECTV:
                    case SRL_HDR_OBJECTV_FREEZE:
                        mrg->ibuf.pos++; // skip tag in input buffer
                        offset = srl_read_varint_uv_offset(aTHX_ mrg->pibuf, " while reading OBJECTV/OBJECTV_FREEZE");
                        offset = srl_lookup_tracked_offset(aTHX_ mrg, offset); // convert ibuf offset to obuf offset
                        srl_buf_cat_varint(aTHX_ &mrg->obuf, tag, offset);
                        goto read_again;

                    case SRL_HDR_PAD:
                        while (SRL_RDR_NOT_DONE(mrg->pibuf) && *mrg->ibuf.pos == SRL_HDR_PAD) {
                            srl_buf_cat_tag_nocheck(mrg, SRL_HDR_PAD);
                        }

                        goto read_again;

                     default:
                        SRL_RDR_ERROR_UNIMPLEMENTED(mrg->pibuf, tag, "");
                        break;
                }
        }
    }

    --mrg->recursion_depth;
    DEBUG_ASSERT_RDR_SANE(mrg->pibuf);
    DEBUG_ASSERT_BUF_SANE(&mrg->obuf);
}
Beispiel #9
0
SRL_STATIC_INLINE void
srl_build_track_table(pTHX_ srl_merger_t *mrg)
{
    U8 tag;
    UV offset, length;

    DEBUG_ASSERT_RDR_SANE(mrg->pibuf);

    if (mrg->tracked_offsets)
        srl_stack_clear(mrg->tracked_offsets);

    while (expect_true(BUF_NOT_DONE(mrg->pibuf))) {
        /* since we're doing full pass, it's not necessary to
         * add items into tracked_offsets here. They will be added
         * by corresponding REFP/ALIAS/COPY and other tags */

        tag = *mrg->ibuf.pos & ~SRL_HDR_TRACK_FLAG;
        SRL_REPORT_CURRENT_TAG(mrg, tag);
        mrg->ibuf.pos++;

        if (tag >= SRL_HDR_SHORT_BINARY_LOW) {
            mrg->ibuf.pos += SRL_HDR_SHORT_BINARY_LEN_FROM_TAG(tag);
        } else if (tag > SRL_HDR_NEG_HIGH && tag < SRL_HDR_ARRAYREF_LOW) {
            switch (tag) {
                case SRL_HDR_VARINT:
                case SRL_HDR_ZIGZAG:
                    srl_read_varint_uv(aTHX_ mrg->pibuf); // TODO test/implement srl_skip_varint()
                    break;

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

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

                case SRL_HDR_HASH:
                case SRL_HDR_ARRAY:
                    srl_read_varint_uv_count(aTHX_ mrg->pibuf, " while reading ARRAY or HASH");
                    break;

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

                default:
                    switch (tag) {
                        case SRL_HDR_COPY:
                        case SRL_HDR_REFP:
                        case SRL_HDR_ALIAS:
                        case SRL_HDR_OBJECTV:
                        case SRL_HDR_OBJECTV_FREEZE:
                            offset = srl_read_varint_uv_offset(aTHX_ mrg->pibuf, " while reading COPY, OBJECTV or OBJECTV_FREEZE");
                            srl_stack_push_val(SRL_GET_TRACKED_OFFSETS(mrg), offset);
                            break;

                        case SRL_HDR_PAD:
                        case SRL_HDR_REFN:
                        case SRL_HDR_WEAKEN:
                        case SRL_HDR_EXTEND:
                        case SRL_HDR_REGEXP:
                        case SRL_HDR_OBJECT:
                        case SRL_HDR_OBJECT_FREEZE:
                            // noop
                            break;

                        default:
                            SRL_RDR_ERROR_UNIMPLEMENTED(mrg->pibuf, tag, "");
                            break;
                    }
            }
        }
    }

    if (mrg->tracked_offsets && !srl_stack_empty(mrg->tracked_offsets)) {
        srl_stack_rsort(aTHX_ mrg->tracked_offsets);
        srl_stack_dedupe(aTHX_ mrg->tracked_offsets);

        //int i = 0;
        //SRL_STACK_TYPE *ptr = mrg->tracked_offsets->begin;
        //while (ptr <= mrg->tracked_offsets->ptr) {
        //    warn("tracked_offsets: offset dedups idx %d offset %d\n", i, (int) *ptr);
        //    i++; ptr++;
        //}
    }

    DEBUG_ASSERT_RDR_SANE(mrg->pibuf);
}