Compress-LZ4Frame

 view release on metacpan or  search on metacpan

CompressLZ4Frame.xs  view on Meta::CPAN

            bytes_read = src_len;

            if (!dest) {
                warn("Could not allocate enough memory (%zu Bytes)", dest_len);
                LZ4F_freeDecompressionContext(ctx);
                return NULL;
            }

            result = LZ4F_decompress(ctx, dest + dest_offset, &current_chunk, src + src_offset, &bytes_read, NULL);
            if (LZ4F_isError(result) || !current_chunk) {
                if (LZ4F_isError(result))
                    warn("Error during decompression: %s", LZ4F_getErrorName(result));
                Safefree(dest);
                LZ4F_freeDecompressionContext(ctx);
                return NULL;
            }

            // bytes_processed is relevant for concatenated frames
            *bytes_processed += bytes_read;

            // current_chunk contains how much was read
            // dest_offset is where the current chunk started
            // result contains the number of bytes that LZ4F is still expecting
            // in combination this should be the full new size of the destination buffer
            dest_len = dest_offset + current_chunk + result;

            if (!result) // 0 means no more data in this frame
                break;

            // where the next chunk will be read to
            dest_offset += current_chunk;
            // the size of the next chunk
            current_chunk = result;
            // how much is left to read from the source buffer
            src_len -= bytes_read;
            // where to read from
            src_offset += bytes_read;

            Renew(dest, dest_len, char);
        }

        // done uncompressing, now put the stuff into a scalar
        decompressed = newSV(0);
        sv_usepvn_flags(decompressed, dest, dest_len, SV_SMAGIC);
        LZ4F_freeDecompressionContext(ctx);
    }

    return decompressed;
}

MODULE = Compress::LZ4Frame PACKAGE = Compress::LZ4Frame
PROTOTYPES: ENABLE

SV *
compress(sv, level = 0)
    SV * sv
    int level
    ALIAS:
        compress_checksum = 1
    PREINIT:
        LZ4F_preferences_t prefs = { 0 };
        char * src, * dest;
        size_t src_len, dest_len;
    CODE:
        SvGETMAGIC(sv);
        if (SvROK(sv) && !SvAMAGIC(sv)) {
            sv = SvRV(sv);
            SvGETMAGIC(sv);
        }
        if (!SvOK(sv))
            XSRETURN_NO;

        src = SvPVbyte(sv, src_len);
        if (!src_len)
            XSRETURN_NO;

        prefs.frameInfo.contentChecksumFlag = (ix == 1 ? LZ4F_contentChecksumEnabled : LZ4F_noContentChecksum);
        prefs.frameInfo.contentSize = (unsigned long long)src_len;
        prefs.compressionLevel = level;
        prefs.autoFlush = 1u;

        dest_len = LZ4F_compressFrameBound(src_len, &prefs);
        RETVAL = newSV(dest_len);
        dest = SvPVX(RETVAL);
        if (!dest) {
            warn("Could not allocate enough memory (%zu Bytes)", dest_len);
            SvREFCNT_dec(RETVAL);
            XSRETURN_UNDEF;
        }

        dest_len = LZ4F_compressFrame(dest, dest_len, src, src_len, &prefs);
        if (LZ4F_isError(dest_len)) {
            warn("Error during compression: %s", LZ4F_getErrorName(dest_len));
            SvREFCNT_dec(RETVAL);
            XSRETURN_UNDEF;
        }

        SvCUR_set(RETVAL, dest_len);
        SvPOK_on(RETVAL);
    OUTPUT:
        RETVAL

SV *
decompress(sv)
    SV * sv
    PREINIT:
        char * src;
        size_t src_len, bytes_read;
        SV * current = (SV*)1; /* simply not NULL */
    CODE:
        SvGETMAGIC(sv);
        if (SvROK(sv) && !SvAMAGIC(sv)) {
            sv = SvRV(sv);
            SvGETMAGIC(sv);
        }
        if (!SvOK(sv))
            XSRETURN_NO;

        src = SvPVbyte(sv, src_len);
        if (!src_len)
            XSRETURN_NO;

        RETVAL = decompress_single_frame(aTHX_ src, src_len, &bytes_read);
        if (RETVAL == NULL)
            XSRETURN_UNDEF;
        src += bytes_read;
        src_len = src_len >= bytes_read ? src_len - bytes_read : 0u;
        while (src_len && (current = decompress_single_frame(aTHX_ src, src_len, &bytes_read)) && (bytes_read > 0))
        {
            sv_catsv(RETVAL, current);
            SvREFCNT_dec(current);
            src += bytes_read;
            src_len = src_len >= bytes_read ? src_len - bytes_read : 0u;
        }
        if (current == NULL)
        {
            SvREFCNT_dec(RETVAL);
            XSRETURN_UNDEF;
        }

    OUTPUT:
        RETVAL

int
looks_like_lz4frame(sv)
    SV * sv
    PREINIT:
        LZ4F_decompressionContext_t ctx;
        LZ4F_frameInfo_t info;
        char * src;
        size_t src_len;



( run in 1.496 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )