Skip to content

Commit

Permalink
Break out libdeflate_options from CustomMemoryAllocator
Browse files Browse the repository at this point in the history
  • Loading branch information
jzebedee committed Sep 18, 2023
1 parent ff589f6 commit a342a9c
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 80 deletions.
2 changes: 1 addition & 1 deletion src/LibDeflate/Imports/Compression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ internal static class Compression
/// Like <see cref="libdeflate_alloc_compressor"/> but allows specifying advanced options per-compressor.
/// </summary>
[DllImport(Constants.DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern libdeflate_compressor libdeflate_alloc_compressor_ex(int compression_level, in CustomMemoryAllocator.libdeflate_options options);
public static extern libdeflate_compressor libdeflate_alloc_compressor_ex(int compression_level, in libdeflate_options options);

///<summary>
/// libdeflate_deflate_compress() performs raw DEFLATE compression on a buffer of
Expand Down
79 changes: 2 additions & 77 deletions src/LibDeflate/Imports/CustomMemoryAllocator.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace LibDeflate.Imports;

using size_t = UIntPtr;
Expand All @@ -22,79 +22,4 @@ internal static class CustomMemoryAllocator
///</summary>
[DllImport(Constants.DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void libdeflate_set_memory_allocator(malloc_func malloc, free_func free);

/// <summary>
/// Advanced options. This is the options structure that
/// <see cref="Compression.libdeflate_alloc_compressor_ex"/>
/// and <see cref="Decompression.libdeflate_alloc_decompressor_ex"/>
/// require. Most users won't need this and should just use the non-"_ex"
/// functions instead.
/// </summary>
internal readonly struct libdeflate_options
{
private static readonly size_t Size = (nuint)(nint)Unsafe.SizeOf<libdeflate_options>();

public libdeflate_options(malloc_func malloc, free_func free)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(malloc);
ArgumentNullException.ThrowIfNull(free);
#else
//TODO: add throwhelpers
if(malloc is null)
{
throw new ArgumentNullException(nameof(malloc));
}

if(free is null)
{
throw new ArgumentNullException(nameof(free));
}
#endif

this.malloc = malloc;
this.free = free;
}

/// <summary>
/// This field must be set to the struct size. This field exists for
/// extensibility, so that fields can be appended to this struct in
/// future versions of libdeflate while still supporting old binaries.
/// </summary>
public readonly size_t sizeof_options = Size;
/// <summary>
/// An optional custom memory allocator to use for this (de)compressor.
/// 'malloc_func' must be a function that behaves like malloc().
/// </summary>
/// <remarks>
/// This is useful in cases where a process might have multiple users of
/// libdeflate who want to use different memory allocators. For example,
/// a library might want to use libdeflate with a custom memory allocator
/// without interfering with user code that might use libdeflate too.
///
/// This takes priority over the "global" memory allocator (which by
/// default is malloc() and free(), but can be changed by
/// libdeflate_set_memory_allocator()). Moreover, libdeflate will never
/// call the "global" memory allocator if a per-(de)compressor custom
/// allocator is always given.
/// </remarks>
public readonly malloc_func malloc;
/// <summary>
/// An optional custom memory deallocator to use for this (de)compressor.
/// 'free_func' must be a function that behaves like free().
/// </summary>
/// <remarks>
/// This is useful in cases where a process might have multiple users of
/// libdeflate who want to use different memory allocators. For example,
/// a library might want to use libdeflate with a custom memory allocator
/// without interfering with user code that might use libdeflate too.
///
/// This takes priority over the "global" memory allocator (which by
/// default is malloc() and free(), but can be changed by
/// libdeflate_set_memory_allocator()). Moreover, libdeflate will never
/// call the "global" memory allocator if a per-(de)compressor custom
/// allocator is always given.
/// </remarks>
public readonly free_func free;
}
}
}
2 changes: 1 addition & 1 deletion src/LibDeflate/Imports/Decompression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public enum libdeflate_result
/// Like <see cref="libdeflate_alloc_decompressor"/> but allows specifying advanced options per-decompressor.
/// </summary>
[DllImport(Constants.DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern libdeflate_decompressor libdeflate_alloc_decompressor_ex(in CustomMemoryAllocator.libdeflate_options options);
public static extern libdeflate_decompressor libdeflate_alloc_decompressor_ex(in libdeflate_options options);

///<summary>
/// libdeflate_deflate_decompress() decompresses the DEFLATE-compressed stream
Expand Down
83 changes: 83 additions & 0 deletions src/LibDeflate/Imports/libdeflate_options.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System;
using System.Runtime.CompilerServices;
namespace LibDeflate.Imports;

using static LibDeflate.Imports.CustomMemoryAllocator;
using size_t = UIntPtr;

/// <summary>
/// Advanced options. This is the options structure that
/// <see cref="Compression.libdeflate_alloc_compressor_ex"/>
/// and <see cref="Decompression.libdeflate_alloc_decompressor_ex"/>
/// require. Most users won't need this and should just use the non-"_ex"
/// functions instead.
/// </summary>
internal readonly struct libdeflate_options
{
private static readonly size_t Size = (nuint)(nint)Unsafe.SizeOf<libdeflate_options>();

public libdeflate_options(malloc_func malloc, free_func free)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(malloc);
ArgumentNullException.ThrowIfNull(free);
#else
//TODO: add throwhelpers
if (malloc is null)
{
throw new ArgumentNullException(nameof(malloc));
}

if (free is null)
{
throw new ArgumentNullException(nameof(free));
}
#endif
this.sizeof_options = Size;
this.malloc = malloc;
this.free = free;
}

/// <summary>
/// This field must be set to the struct size. This field exists for
/// extensibility, so that fields can be appended to this struct in
/// future versions of libdeflate while still supporting old binaries.
/// </summary>
public readonly size_t sizeof_options;

/// <summary>
/// An optional custom memory allocator to use for this (de)compressor.
/// 'malloc_func' must be a function that behaves like malloc().
/// </summary>
/// <remarks>
/// This is useful in cases where a process might have multiple users of
/// libdeflate who want to use different memory allocators. For example,
/// a library might want to use libdeflate with a custom memory allocator
/// without interfering with user code that might use libdeflate too.
///
/// This takes priority over the "global" memory allocator (which by
/// default is malloc() and free(), but can be changed by
/// libdeflate_set_memory_allocator()). Moreover, libdeflate will never
/// call the "global" memory allocator if a per-(de)compressor custom
/// allocator is always given.
/// </remarks>
public readonly malloc_func malloc;

/// <summary>
/// An optional custom memory deallocator to use for this (de)compressor.
/// 'free_func' must be a function that behaves like free().
/// </summary>
/// <remarks>
/// This is useful in cases where a process might have multiple users of
/// libdeflate who want to use different memory allocators. For example,
/// a library might want to use libdeflate with a custom memory allocator
/// without interfering with user code that might use libdeflate too.
///
/// This takes priority over the "global" memory allocator (which by
/// default is malloc() and free(), but can be changed by
/// libdeflate_set_memory_allocator()). Moreover, libdeflate will never
/// call the "global" memory allocator if a per-(de)compressor custom
/// allocator is always given.
/// </remarks>
public readonly free_func free;
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void UsePerCompressorCustomAllocatorsTest()

int localMallocs = 0;
int localFrees = 0;
var options = new CustomMemoryAllocator.libdeflate_options((nuint len) =>
var options = new libdeflate_options((nuint len) =>
{
localMallocs++;
return Marshal.AllocHGlobal((nint)len);
Expand Down

0 comments on commit a342a9c

Please sign in to comment.