/// <summary> /// Gets the value range for <paramref name="parameter"/> /// </summary> public static Range GetParameterBounds(ZstdCompressionParameter parameter) { ZstdBounds bounds = Native.ZSTD_cParam_getBounds(parameter); Zstd.ThrowOnError(bounds.ErrorCode); return(bounds.GetRange()); }
/// <summary> /// Gets the value of a parameter /// </summary> public int GetParameter(ZstdCompressionParameter parameter) { int value = 0; unsafe { Zstd.ThrowOnError(Native.ZSTD_CCtx_getParameter(this._context, parameter, (IntPtr)(&value))); } return(value); }
/// <summary> /// Compresses data in <paramref name="buffer"/> starting at <paramref name="offset"/> with <paramref name="size"/> /// using the specified <paramref name="compressionLevel"/> and parameters set on this <see cref="ZstdCompressionContext"/> /// </summary> /// <param name="buffer">The buffer to compress</param> /// <param name="offset">The offset at which the data to compress starts</param> /// <param name="size">The size of the data to compress</param> /// <param name="compressionLevel">The compression level to use</param> /// <returns>The compressed buffer</returns> /// <remarks> /// This method will usually cause a double heap allocation of the compressed buffer, /// it is recommended to use <see cref="Compress(ReadOnlyMemory{byte}, int, int, int)"/> if you want to avoid this /// </remarks> public byte[] Compress(byte[] buffer, int offset, int size, int compressionLevel = Native.ZSTD_CLEVEL_DEFAULT) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer), $"{nameof(buffer)} cannot be null"); } Zstd.ValidateCompressionArguments(buffer.Length, offset, size, compressionLevel); // Allocate compressed buffer Size compressionBound = Native.ZSTD_compressBound(new Size((uint)size)); byte[] compressedBuffer = new byte[compressionBound.ToUInt32()]; Size compressedBufferSize = Size.Zero; unsafe { fixed(byte *compressedBufferPointer = compressedBuffer) fixed(byte *uncompressedBufferPointer = buffer) { if (this.Dictionary == null) { compressedBufferSize = Native.ZSTD_compress2( this._context, (IntPtr)compressedBufferPointer, compressionBound, (IntPtr)(uncompressedBufferPointer + offset), (Size)size); } else { compressedBufferSize = Native.ZSTD_compress_usingCDict( this._context, (IntPtr)compressedBufferPointer, compressionBound, (IntPtr)(uncompressedBufferPointer + offset), (Size)size, this.Dictionary.GetCompressionDictionary(compressionLevel)); } } } // Check for errors Zstd.ThrowOnError(compressedBufferSize); // If compressionBound is same as the amount of compressed bytes then we can return the same array // otherwise we need to allocate a new one :/ if (compressionBound != compressedBufferSize) { Array.Resize(ref compressedBuffer, (int)compressedBufferSize); } return(compressedBuffer); }
/// <summary> /// Compresses data in <paramref name="memory"/> starting at <paramref name="offset"/> with <paramref name="size"/> /// using the specified <paramref name="compressionLevel"/> and parameters set on this <see cref="ZstdCompressionContext"/> /// </summary> /// <param name="memory">The buffer to compress</param> /// <param name="offset">The offset at which the data to compress starts</param> /// <param name="size">The size of the data to compress</param> /// <param name="compressionLevel">The compression level to use</param> /// <returns>The compressed buffer wrapped in <see cref="Memory{Byte}"/></returns> public Memory <byte> Compress(ReadOnlyMemory <byte> memory, int offset, int size, int compressionLevel = Native.ZSTD_CLEVEL_DEFAULT) { Zstd.ValidateCompressionArguments(memory.Length, offset, size, compressionLevel); // Allocate compressed buffer Size compressionBound = Native.ZSTD_compressBound(new Size((uint)size)); byte[] compressedBuffer = new byte[compressionBound.ToUInt32()]; // Get handles to buffers using MemoryHandle compressedBufferHandle = compressedBuffer.AsMemory().Pin(); using MemoryHandle uncompressedBufferHandle = memory.Pin(); unsafe { // Get raw pointers from handles IntPtr compressedBufferPointer = new IntPtr(compressedBufferHandle.Pointer); IntPtr uncompressedBufferPointer = new IntPtr(uncompressedBufferHandle.Pointer); Size compressedBufferSize; if (this.Dictionary == null) { compressedBufferSize = Native.ZSTD_compressCCtx( this._context, compressedBufferPointer, compressionBound, uncompressedBufferPointer + offset, (Size)size, compressionLevel); } else { compressedBufferSize = Native.ZSTD_compress_usingCDict( this._context, compressedBufferPointer, compressionBound, uncompressedBufferPointer + offset, (Size)size, this.Dictionary.GetCompressionDictionary(compressionLevel)); } // Check for errors Zstd.ThrowOnError(compressedBufferSize); return(compressedBuffer.AsMemory(0, (int)compressedBufferSize.ToUInt32())); } }
/// <summary> /// Decompresses data with <paramref name="size"/> at <paramref name="offset"/> in <paramref name="buffer"/> using this <see cref="ZstdDecompressionContext"/> /// </summary> /// <param name="buffer">The compressed data buffer</param> /// <param name="offset">The offset of the compressed data</param> /// <param name="size">The size of the compressed data</param> /// <param name="uncompressedSize">Uncompressed size of <paramref name="buffer"/></param> /// <returns>The uncompressed buffer</returns> /// <remarks>If you do not know the uncompressed size then it is recommended to use <see cref="ZstdStream"/></remarks> public byte[] Decompress(byte[] buffer, int offset, int size, int uncompressedSize) { Zstd.ValidateDecompressionArguments(buffer.Length, offset, size, uncompressedSize); // Allocate uncompressed buffer byte[] uncompressedBuffer = new byte[uncompressedSize]; Size uncompressedBufferSize = Size.Zero; unsafe { fixed(byte *uncompressedBufferPtr = uncompressedBuffer) fixed(byte *compressedBufferPtr = buffer) { if (this.Dictionary == null) { uncompressedBufferSize = Native.ZSTD_decompressDCtx( this._context, (IntPtr)uncompressedBufferPtr, (Size)uncompressedSize, (IntPtr)(compressedBufferPtr + offset), (Size)size); } else { uncompressedBufferSize = Native.ZSTD_decompress_usingDDict( this._context, (IntPtr)uncompressedBufferPtr, (Size)uncompressedSize, (IntPtr)(compressedBufferPtr + offset), (Size)size, this.Dictionary.GetDecompressionDictionary()); } } } // Check for errors Zstd.ThrowOnError(uncompressedBufferSize); // Check for possiblity that user passed in higher than required uncompressed size if (uncompressedSize != uncompressedBufferSize.ToUInt32()) { Array.Resize(ref uncompressedBuffer, (int)uncompressedBufferSize); } return(uncompressedBuffer); }
/// <summary> /// Decompresses data with <paramref name="size"/> at <paramref name="offset"/> in <paramref name="memory"/> using this <see cref="ZstdDecompressionContext"/> /// </summary> /// <param name="memory">The compressed data buffer</param> /// <param name="offset">The offset of the compressed data</param> /// <param name="size">The size of the compressed data</param> /// <param name="uncompressedSize">Uncompressed size of <paramref name="buffer"/></param> /// <returns>The uncompressed buffer</returns> /// <remarks>If you do not know the uncompressed size then it is recommended to use <see cref="ZstdStream"/></remarks> public Memory <byte> Decompress(ReadOnlyMemory <byte> memory, int offset, int size, int uncompressedSize) { Zstd.ValidateDecompressionArguments(memory.Length, offset, size, uncompressedSize); // Allocate uncompressed buffer byte[] uncompressedBuffer = new byte[uncompressedSize]; // Get handles to buffers using MemoryHandle compressedBufferHandle = memory.Pin(); using MemoryHandle uncompressedBufferHandle = uncompressedBuffer.AsMemory().Pin(); unsafe { // Get pointers from handles IntPtr compressedBufferPointer = (IntPtr)compressedBufferHandle.Pointer; IntPtr uncompressedBufferPointer = (IntPtr)uncompressedBufferHandle.Pointer; Size uncompressedBufferSize; if (this.Dictionary == null) { uncompressedBufferSize = Native.ZSTD_decompressDCtx( this._context, uncompressedBufferPointer, (Size)uncompressedSize, compressedBufferPointer + offset, (Size)size); } else { uncompressedBufferSize = Native.ZSTD_decompress_usingDDict( this._context, uncompressedBufferPointer, (Size)uncompressedSize, compressedBufferPointer + offset, (Size)size, this.Dictionary.GetDecompressionDictionary()); } // Check for errors Zstd.ThrowOnError(uncompressedBufferSize); return(uncompressedBuffer.AsMemory(0, (int)uncompressedBufferSize)); } }
/// <summary> /// Resets this <see cref="ZstdCompressionContext"/> /// </summary> public void Reset(ZstdResetDirective resetDirective) { Zstd.ThrowOnError(Native.ZSTD_CCtx_reset(this._context, resetDirective)); }
// ------------ PARAMETERS ------------ \\ /// <summary> /// Sets a parameter value inside of this <see cref="ZstdCompressionContext"/> /// </summary> /// <param name="parameter">The parameter to set</param> /// <param name="value">The value of the parameter</param> /// <remarks> /// <paramref name="value"/> need to be in a valid range or else it will get clamped, /// use <see cref="GetParameterBounds(ZstdCompressionParameter)"/> to get a valid range for a parameter /// </remarks> public void SetParameter(ZstdCompressionParameter parameter, int value) { Zstd.ThrowOnError(Native.ZSTD_CCtx_setParameter(this._context, parameter, value)); }