All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.luben.zstd.ZstdCompressCtx Maven / Gradle / Ivy

The newest version!
package com.github.luben.zstd;

import com.github.luben.zstd.util.Native;
import com.github.luben.zstd.ZstdDictCompress;

import java.nio.ByteBuffer;
import java.util.Arrays;

public class ZstdCompressCtx extends AutoCloseBase {

    static {
        Native.load();
    }

    private long nativePtr = 0;

    private ZstdDictCompress compression_dict = null;

    private native void init();

    private native void free();

    /**
     * Create a context for faster compress operations
     * One such context is required for each thread - put this in a ThreadLocal.
     */
    public ZstdCompressCtx() {
        init();
        if (0 == nativePtr) {
            throw new IllegalStateException("ZSTD_createCompressCtx failed");
        }
        storeFence();
    }

    void  doClose() {
        if (nativePtr != 0) {
            free();
            nativePtr = 0;
        }
    }

    /**
     * Set compression level
     * @param level compression level, default: {@link Zstd#defaultCompressionLevel()}
     */
    public ZstdCompressCtx setLevel(int level) {
        if (nativePtr == 0) {
            throw new IllegalStateException("Compression context is closed");
        }
        acquireSharedLock();
        setLevel0(level);
        releaseSharedLock();
        return this;
    }

    private native void setLevel0(int level);

    /**
     * Enable or disable compression checksums
     * @param checksumFlag A 32-bits checksum of content is written at end of frame, default: false
     */
    public ZstdCompressCtx setChecksum(boolean checksumFlag) {
        if (nativePtr == 0) {
            throw new IllegalStateException("Compression context is closed");
        }
        acquireSharedLock();
        setChecksum0(checksumFlag);
        releaseSharedLock();
        return this;
    }
    private native void setChecksum0(boolean checksumFlag);


    public ZstdCompressCtx setWorkers(int workers) {
        acquireSharedLock();
        Zstd.setCompressionWorkers(nativePtr, workers);
        releaseSharedLock();
        return this;
    }

    /**
     * Enable or disable content size
     * @param contentSizeFlag Content size will be written into frame header _whenever known_, default: true
     */
    public ZstdCompressCtx setContentSize(boolean contentSizeFlag) {
        if (nativePtr == 0) {
            throw new IllegalStateException("Compression context is closed");
        }
        acquireSharedLock();
        setContentSize0(contentSizeFlag);
        releaseSharedLock();
        return this;
    }
    private native void setContentSize0(boolean contentSizeFlag);

    /**
     * Enable or disable dictID
     * @param dictIDFlag When applicable, dictionary's ID is written into frame header, default: true
     */
    public ZstdCompressCtx setDictID(boolean dictIDFlag) {
        if (nativePtr == 0) {
            throw new IllegalStateException("Compression context is closed");
        }
        acquireSharedLock();
        setDictID0(dictIDFlag);
        releaseSharedLock();
        return this;
    }
    private native void setDictID0(boolean dictIDFlag);

    /**
     * Enable or disable LongDistanceMatching and set the window size
     * @param windowLog Maximum allowed back-reference distance, expressed as power of 2.
     *                  This will set a memory budget for streaming decompression,
     *                  with larger values requiring more memory and typically compressing more.
     *                  Must be clamped between 10 and 32/64 but values greater then 27 may not
     *                  be decompressable in all context as they require more memory.
     *                  0 disables LDM.
     */
    public ZstdCompressCtx setLong(int windowLog) {
        if (nativePtr == 0) {
            throw new IllegalStateException("Compression context is closed");
        }
        acquireSharedLock();
        Zstd.setCompressionLong(nativePtr, windowLog);
        releaseSharedLock();
        return this;
    }

    /**
     * Load compression dictionary to be used for subsequently compressed frames.
     *
     * @param dict the dictionary or `null` to remove loaded dictionary
     */
    public ZstdCompressCtx loadDict(ZstdDictCompress dict) {
        if (nativePtr == 0) {
            throw new IllegalStateException("Compression context is closed");
        }

        acquireSharedLock();
        dict.acquireSharedLock();
        try {
            long result = loadCDictFast0(dict);
            if (Zstd.isError(result)) {
                throw new ZstdException(result);
            }
            // keep a reference to the dictionary so it's not garbage collected
            compression_dict = dict;
        } finally {
            dict.releaseSharedLock();
            releaseSharedLock();
        }
        return this;
    }
    private native long loadCDictFast0(ZstdDictCompress dict);

    /**
     * Load compression dictionary to be used for subsequently compressed frames.
     *
     * @param dict the dictionary or `null` to remove loaded dictionary
     */
    public ZstdCompressCtx loadDict(byte[] dict) {
        if (nativePtr == 0) {
            throw new IllegalStateException("Compression context is closed");
        }
        acquireSharedLock();
        try {
            long result = loadCDict0(dict);
            if (Zstd.isError(result)) {
                throw new ZstdException(result);
            }
            compression_dict = null;
        } finally {
            releaseSharedLock();
        }
        return this;
    }
    private native long loadCDict0(byte[] dict);

    /**
     * Compresses buffer 'srcBuff' into buffer 'dstBuff' reusing this ZstdCompressCtx.
     *
     * Destination buffer should be sized to handle worst cases situations (input
     * data not compressible). Worst case size evaluation is provided by function
     * ZSTD_compressBound(). This is a low-level function that does not take into
     * account or affect the `limit` or `position` of source or destination buffers.
     *
     * @param dstBuff the destination buffer - must be direct
     * @param dstOffset the start offset of 'dstBuff'
     * @param dstSize the size of 'dstBuff' (after 'dstOffset')
     * @param srcBuff the source buffer - must be direct
     * @param srcOffset the start offset of 'srcBuff'
     * @param srcSize the length of 'srcBuff' (after 'srcOffset')
     * @return  the number of bytes written into buffer 'dstBuff'.
     */
    public int compressDirectByteBuffer(ByteBuffer dstBuff, int dstOffset, int dstSize, ByteBuffer srcBuff, int srcOffset, int srcSize) {
        if (nativePtr == 0) {
            throw new IllegalStateException("Compression context is closed");
        }
        if (!srcBuff.isDirect()) {
            throw new IllegalArgumentException("srcBuff must be a direct buffer");
        }
        if (!dstBuff.isDirect()) {
            throw new IllegalArgumentException("dstBuff must be a direct buffer");
        }

        acquireSharedLock();

        try {
            long size = compressDirectByteBuffer0(dstBuff, dstOffset, dstSize, srcBuff, srcOffset, srcSize);
            if (Zstd.isError(size)) {
                throw new ZstdException(size);
            }
            if (size > Integer.MAX_VALUE) {
                throw new ZstdException(Zstd.errGeneric(), "Output size is greater than MAX_INT");
            }
            return (int) size;
        } finally {
            releaseSharedLock();
        }
    }

    private native long compressDirectByteBuffer0(ByteBuffer dst, int dstOffset, int dstSize, ByteBuffer src, int srcOffset, int srcSize);

    /**
     * Compresses byte array 'srcBuff' into byte array 'dstBuff' reusing this ZstdCompressCtx.
     *
     * Destination buffer should be sized to handle worst cases situations (input
     * data not compressible). Worst case size evaluation is provided by function
     * ZSTD_compressBound().
     *
     * @param dstBuff the destination buffer (byte array)
     * @param dstOffset the start offset of 'dstBuff'
     * @param dstSize the size of 'dstBuff' (after 'dstOffset')
     * @param srcBuff the source buffer (byte array)
     * @param srcOffset the start offset of 'srcBuff'
     * @param srcSize the length of 'srcBuff' (after 'srcOffset')
     * @return  the number of bytes written into buffer 'dstBuff'.
     */
    public int compressByteArray(byte[] dstBuff, int dstOffset, int dstSize, byte[] srcBuff, int srcOffset, int srcSize) {
        if (nativePtr == 0) {
            throw new IllegalStateException("Compression context is closed");
        }

        acquireSharedLock();

        try {
            long size = compressByteArray0(dstBuff, dstOffset, dstSize, srcBuff, srcOffset, srcSize);
            if (Zstd.isError(size)) {
                throw new ZstdException(size);
            }
            if (size > Integer.MAX_VALUE) {
                throw new ZstdException(Zstd.errGeneric(), "Output size is greater than MAX_INT");
            }
            return (int) size;
        } finally {
            releaseSharedLock();
        }
    }

    private native long compressByteArray0(byte[] dst, int dstOffset, int dstSize, byte[] src, int srcOffset, int srcSize);

    /** Convenience methods */

    /**
     * Compresses the data in buffer 'srcBuf'
     *
     * @param dstBuf the destination buffer - must be direct. It is assumed that the `position()` of this buffer marks the offset
     *               at which the compressed data are to be written, and that the `limit()` of this buffer is the maximum
     *               compressed data size to allow.
     *               

* When this method returns successfully, its `position()` will be set to its current `position()` plus the * compressed size of the data. *

* @param srcBuf the source buffer - must be direct. It is assumed that the `position()` of this buffer marks the beginning of the * uncompressed data to be compressed, and that the `limit()` of this buffer marks its end. *

* When this method returns successfully, its `position()` will be set to the initial `limit()`. *

* @return the size of the compressed data */ public int compress(ByteBuffer dstBuf, ByteBuffer srcBuf) { int size = compressDirectByteBuffer(dstBuf, // compress into dstBuf dstBuf.position(), // write compressed data starting at offset position() dstBuf.limit() - dstBuf.position(), // write no more than limit() - position() bytes srcBuf, // read data to compress from srcBuf srcBuf.position(), // start reading at position() srcBuf.limit() - srcBuf.position() // read limit() - position() bytes ); srcBuf.position(srcBuf.limit()); dstBuf.position(dstBuf.position() + size); return size; } /** * Compresses the data in buffer 'srcBuf' * * @param srcBuf the source buffer - must be direct. It is assumed that the `position()` of the * buffer marks the beginning of the uncompressed data to be compressed, and that * the `limit()` of this buffer marks its end. *

* When this method returns successfully, its `position()` will be set to its initial `limit()`. *

* @return A newly allocated direct ByteBuffer containing the compressed data. */ public ByteBuffer compress(ByteBuffer srcBuf) throws ZstdException { long maxDstSize = Zstd.compressBound((long)(srcBuf.limit() - srcBuf.position())); if (maxDstSize > Integer.MAX_VALUE) { throw new ZstdException(Zstd.errGeneric(), "Max output size is greater than MAX_INT"); } ByteBuffer dstBuf = ByteBuffer.allocateDirect((int) maxDstSize); int size = compressDirectByteBuffer(dstBuf, // compress into dstBuf 0, // starting at offset 0 (int) maxDstSize, // writing no more than maxDstSize srcBuf, // read data to be compressed from srcBuf srcBuf.position(), // start reading at offset position() srcBuf.limit() - srcBuf.position() // read limit() - position() bytes ); srcBuf.position(srcBuf.limit()); dstBuf.limit(size); // Since we allocated the buffer ourselves, we know it cannot be used to hold any further compressed data, // so leave the position at zero where the caller surely wants it, ready to read return dstBuf; } public int compress(byte[] dst, byte[] src) { return compressByteArray(dst, 0, dst.length, src, 0, src.length); } public byte[] compress(byte[] src) { long maxDstSize = Zstd.compressBound(src.length); if (maxDstSize > Integer.MAX_VALUE) { throw new ZstdException(Zstd.errGeneric(), "Max output size is greater than MAX_INT"); } byte[] dst = new byte[(int) maxDstSize]; int size = compressByteArray(dst, 0, dst.length, src, 0, src.length); return Arrays.copyOfRange(dst, 0, size); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy