Ejemplo n.º 1
0
SRL_STATIC_INLINE void
srl_fill_header(pTHX_ srl_merger_t *mrg, const char *user_header, STRLEN user_header_len)
{
    /* 4 byte magic string + proto version
     * + potentially uncompressed size varint
     * +  1 byte varint that indicates zero-length header */
    GROW_BUF(&mrg->obuf, 128);

    if (expect_true(mrg->protocol_version > 2)) {
        srl_buf_cat_str_s_nocheck(&mrg->obuf, SRL_MAGIC_STRING_HIGHBIT);
    } else {
        srl_buf_cat_str_s_nocheck(&mrg->obuf, SRL_MAGIC_STRING);
    }

    srl_buf_cat_char_nocheck(&mrg->obuf, (U8) mrg->protocol_version);

    if (user_header == NULL) {
        srl_buf_cat_char_nocheck(&mrg->obuf, '\0');
    } else {
        if (expect_false(mrg->protocol_version < 2))
            croak("Cannot serialize user header data in Sereal protocol V1 mode!"); // TODO

        srl_buf_cat_varint_nocheck(aTHX_ &mrg->obuf, 0, (UV) (user_header_len + 1)); /* Encode header length, +1 for bit field */
        srl_buf_cat_char_nocheck(&mrg->obuf, '\1');                                  /* Encode bitfield */
        Copy(user_header, mrg->obuf.pos, user_header_len, char);                     /* Copy user header data */
        mrg->obuf.pos += user_header_len;
    }

    SRL_UPDATE_BODY_POS(&mrg->obuf, mrg->protocol_version);
}
Ejemplo n.º 2
0
void
srl_write_header(pTHX_ srl_encoder_t *enc)
{
    /* 4th to 8th bit are flags. Using 4th for snappy flag. FIXME needs to go in spec. */
    const U8 version_and_flags = SRL_PROTOCOL_VERSION
                                 | (
                                    SRL_ENC_HAVE_OPTION(enc, SRL_F_COMPRESS_SNAPPY)
                                    ? SRL_PROTOCOL_ENCODING_SNAPPY
                                    : SRL_PROTOCOL_ENCODING_RAW
                                 );

    /* 4 byte magic string + proto version
     * + potentially uncompressed size varint
     * +  1 byte varint that indicates zero-length header */
    BUF_SIZE_ASSERT(enc, sizeof(SRL_MAGIC_STRING) + 1 + 1);
    srl_buf_cat_str_s_nocheck(enc, SRL_MAGIC_STRING);
    srl_buf_cat_char_nocheck(enc, version_and_flags);
    srl_buf_cat_char_nocheck(enc, '\0'); /* variable header length (0 right now) */
}
Ejemplo n.º 3
0
/* Code for serializing floats */
static SRL_INLINE void
srl_dump_nv(pTHX_ srl_encoder_t *enc, SV *src)
{
    NV nv= SvNV(src);
    float f= nv;
    double d= nv;
    if ( f == nv || nv != nv ) {
        BUF_SIZE_ASSERT(enc, 1 + sizeof(f)); /* heuristic: header + string + simple value */
        srl_buf_cat_char_nocheck(enc,SRL_HDR_FLOAT);
        Copy((char *)&f, enc->pos, sizeof(f), char);
        enc->pos += sizeof(f);
    } else if (d == nv) {
Ejemplo n.º 4
0
/* Code for serializing floats */
SRL_STATIC_INLINE void
srl_dump_nv(pTHX_ srl_encoder_t *enc, SV *src)
{
    NV nv= SvNV(src);
    MS_VC6_WORKAROUND_VOLATILE float f= (float)nv;
    MS_VC6_WORKAROUND_VOLATILE double d= (double)nv;
    /* TODO: this logic could be reworked to not duplicate so much code, which will help on win32 */
    if ( f == nv || nv != nv ) {
        BUF_SIZE_ASSERT(enc, 1 + sizeof(f)); /* heuristic: header + string + simple value */
        srl_buf_cat_char_nocheck(enc,SRL_HDR_FLOAT);
        Copy((char *)&f, enc->pos, sizeof(f), char);
        enc->pos += sizeof(f);
    } else if (d == nv) {
Ejemplo n.º 5
0
srl_merger_t *
srl_build_merger_struct(pTHX_ HV *opt)
{
    srl_merger_t *mrg;
    SV **svp;
    int i;

    mrg = srl_empty_merger_struct(aTHX);

    /* load options */
    if (opt != NULL) {
        /* Needs to be before the snappy options */
        /* mrg->protocol_version defaults to SRL_PROTOCOL_VERSION. */
        svp = hv_fetchs(opt, "protocol_version", 0);
        if (svp && SvOK(*svp)) {
            mrg->protocol_version = SvUV(*svp);
            if (mrg->protocol_version < 1 || mrg->protocol_version > SRL_PROTOCOL_VERSION) {
                croak("Specified Sereal protocol version ('%lu') is invalid",
                      (unsigned long) mrg->protocol_version);
            }
        }

        svp = hv_fetchs(opt, "top_level_element", 0);
        if (svp && SvOK(*svp)) {
            switch (SvUV(*svp)) {
                case 0: /* SCALAR */
                    SRL_MRG_SET_OPTION(mrg, SRL_F_TOPLEVEL_KEY_SCALAR);
                    break;

                case 1: /* ARRAYREF */
                    SRL_MRG_SET_OPTION(mrg, SRL_F_TOPLEVEL_KEY_ARRAY);
                    break;

                case 2: /* HASHREF */
                    SRL_MRG_SET_OPTION(mrg, SRL_F_TOPLEVEL_KEY_HASH);
                    break;

                default:
                    croak("Invalid Sereal::Merger top level element");
            }
        }

        svp = hv_fetchs(opt, "dedupe_strings", 0);
        if (svp && SvTRUE(*svp))
            SRL_MRG_SET_OPTION(mrg, SRL_F_DEDUPE_STRINGS);

        svp = hv_fetchs(opt, "compress", 0);
        if (svp && SvOK(*svp)) {
            switch (SvIV(*svp)) {
                case 0: /* uncompressed */
                    break;

                case 1: /* snappy incremental */
                    SRL_MRG_SET_OPTION(mrg, SRL_F_COMPRESS_SNAPPY_INCREMENTAL);
                    break;

                default:
                    croak("Invalid Sereal compression format");
            }
        }

        svp = hv_fetchs(opt, "max_recursion_depth", 0);
        if (svp && SvOK(*svp))
            mrg->max_recursion_depth = SvUV(*svp);
    }

    if (mrg->protocol_version == 1) {
        srl_fill_header(aTHX_ mrg, NULL, 0);
    } else {
        /* Preallocate memory for buffer.
         * SRL_PREALLOCATE_FOR_USER_HEADER for potential user header + 100 bytes for body */
        GROW_BUF(&mrg->obuf, SRL_PREALLOCATE_FOR_USER_HEADER + 100);
        mrg->obuf.pos = mrg->obuf.start + SRL_PREALLOCATE_FOR_USER_HEADER;
        SRL_UPDATE_BODY_POS(&mrg->obuf, mrg->protocol_version);
    }

    if (!SRL_MRG_HAVE_OPTION(mrg, SRL_F_TOPLEVEL_KEY_SCALAR)) {
        srl_buf_cat_char_nocheck(&mrg->obuf, SRL_HDR_REFN);
        srl_buf_cat_char_nocheck(&mrg->obuf, SRL_MRG_HAVE_OPTION(mrg, SRL_F_TOPLEVEL_KEY_HASH) ? SRL_HDR_HASH : SRL_HDR_ARRAY);

        mrg->obuf_padding_bytes_offset = BUF_POS_OFS(&mrg->obuf);
        for (i = 0; i < SRL_MAX_VARINT_LENGTH_U32; ++i) {
            srl_buf_cat_char_nocheck(&mrg->obuf, SRL_HDR_PAD);
        }
    }

    return mrg;
}