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); }
void srl_iterator_set(pTHX_ srl_iterator_t *iter, SV *src) { SV *sv; STRLEN len; UV header_len; U8 encoding_flags; U8 protocol_version; srl_reader_char_ptr tmp; IV proto_version_and_encoding_flags_int; srl_iterator_stack_ptr stack_ptr = NULL; if (iter->document) { SvREFCNT_dec(iter->document); iter->document = NULL; } iter->document = src; SvREFCNT_inc(iter->document); tmp = (srl_reader_char_ptr) SvPV(src, len); iter->buf.start = iter->buf.pos = tmp; iter->buf.end = iter->buf.start + len; proto_version_and_encoding_flags_int = srl_validate_header_version(aTHX_ iter->buf.start, len); if (proto_version_and_encoding_flags_int < 1) { if (proto_version_and_encoding_flags_int == 0) SRL_RDR_ERROR(iter->pbuf, "Bad Sereal header: It seems your document was accidentally UTF-8 encoded"); else SRL_RDR_ERROR(iter->pbuf, "Bad Sereal header: Not a valid Sereal document."); } iter->buf.pos += 5; encoding_flags = (U8) (proto_version_and_encoding_flags_int & SRL_PROTOCOL_ENCODING_MASK); protocol_version = (U8) (proto_version_and_encoding_flags_int & SRL_PROTOCOL_VERSION_MASK); if (expect_false(protocol_version > 3 || protocol_version < 1)) { SRL_RDR_ERRORf1(iter->pbuf, "Unsupported Sereal protocol version %u", (unsigned int) protocol_version); } // skip header in any case header_len = srl_read_varint_uv_length(aTHX_ iter->pbuf, " while reading header"); iter->buf.pos += header_len; if (encoding_flags == SRL_PROTOCOL_ENCODING_RAW) { /* no op */ } else if ( encoding_flags == SRL_PROTOCOL_ENCODING_SNAPPY || encoding_flags == SRL_PROTOCOL_ENCODING_SNAPPY_INCREMENTAL) { srl_decompress_body_snappy(aTHX_ iter->pbuf, encoding_flags, &sv); SvREFCNT_dec(iter->document); SvREFCNT_inc(sv); iter->document = sv; } else if (encoding_flags == SRL_PROTOCOL_ENCODING_ZLIB) { srl_decompress_body_zlib(aTHX_ iter->pbuf, &sv); SvREFCNT_dec(iter->document); SvREFCNT_inc(sv); iter->document = sv; } else { SRL_RDR_ERROR(iter->pbuf, "Sereal document encoded in an unknown format"); } /* this function *MUST* be called after calling srl_decompress_body* */ SRL_RDR_UPDATE_BODY_POS(iter->pbuf, protocol_version); DEBUG_ASSERT_RDR_SANE(iter->pbuf); srl_stack_push_and_set(iter, SRL_ITER_STACK_ROOT_TAG, 1, stack_ptr); srl_iterator_reset(aTHX_ iter); }
/* 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); }