Add API to let caller handle memory management

This is inspired by [skeeto]'s recent post on [minimalist C libraries]
and allows the caller to decide how to allocate or free memory needed by
libx52. A future addition could let the caller allocate a big enough
buffer up front, and let libx52 manage it.

[skeeto]: https://github.com/skeeto
[minimalist C libraries]: http://nullprogram.com/blog/2018/06/10/

[skip-ci]
feature/test-new-mem-api
nirenjan 2018-06-11 15:25:35 -07:00
parent 7dcd3049ec
commit a733d4420c
3 changed files with 60 additions and 2 deletions

View File

@ -187,6 +187,24 @@ typedef enum {
} libx52_error_code; } libx52_error_code;
/**
* @brief Memory allocation callback type
*
* This function has the same signature as realloc(3), but is passed
* to allow the calling application to manage memory instead of relying
* on the standard library.
*/
typedef void * (*libx52_memalloc)(void *ptr, size_t size);
/**
* @brief Memory free callback type
*
* This function has the same signature as free(3), but is passed
* to allow the calling application to manage memory instead of relying
* on the standard library.
*/
typedef void (*libx52_memfree)(void *ptr);
/** /**
* @brief Initialize the X52 library * @brief Initialize the X52 library
* *
@ -206,6 +224,27 @@ typedef enum {
*/ */
int libx52_init(libx52_device ** dev); int libx52_init(libx52_device ** dev);
/**
* @brief Initialize the X52 library
*
* This function does the exact same functionality as \ref libx52_init,
* except that it requires the user to provide function callbacks for
* allocating and releasing memory.
*
* @param[out] dev Pointer to a \ref libx52_device *
* @param[in] memalloc Pointer to a function that returns an allocated
* block of memory. Function should have the same
* signature as realloc(3)
* @param[in] memfree Pointer to a function that frees an allocated
* block of memory. Function should have the same
* signature as free(3)
*
* @returns \ref libx52_error_code indicating status
*/
int libx52_init_mem(libx52_device ** dev,
libx52_memalloc memalloc,
libx52_memfree memfree);
/** /**
* @brief Exit the library and free up any resources used * @brief Exit the library and free up any resources used
* *

View File

@ -34,6 +34,9 @@ struct libx52_device {
libusb_context *ctx; libusb_context *ctx;
libusb_device_handle *hdl; libusb_device_handle *hdl;
libx52_memalloc memalloc;
libx52_memfree memfree;
uint32_t update_mask; uint32_t update_mask;
uint32_t flags; uint32_t flags;

View File

@ -43,6 +43,14 @@ static int libx52_device_is_x52pro(uint16_t idProduct)
} }
int libx52_init(libx52_device **dev) int libx52_init(libx52_device **dev)
{
/* Call libx52_init_mem with realloc and free */
return libx52_init_mem(dev, realloc, free);
}
int libx52_init_mem(libx52_device **dev,
libx52_memalloc memalloc,
libx52_memfree memfree)
{ {
int rc; int rc;
ssize_t count; ssize_t count;
@ -58,12 +66,20 @@ int libx52_init(libx52_device **dev)
return LIBX52_ERROR_INVALID_PARAM; return LIBX52_ERROR_INVALID_PARAM;
} }
/* Make sure that our alloc and free functions are valid */
if (memalloc == NULL || memfree == NULL) {
return LIBX52_ERROR_INVALID_PARAM;
}
/* Allocate memory for the library's data structures */ /* Allocate memory for the library's data structures */
x52_dev = calloc(1, sizeof(libx52_device)); x52_dev = (*memalloc)(NULL, sizeof(libx52_device));
if (!x52_dev) { if (!x52_dev) {
return LIBX52_ERROR_OUT_OF_MEMORY; return LIBX52_ERROR_OUT_OF_MEMORY;
} }
x52_dev->memalloc = memalloc;
x52_dev->memfree = memfree;
rc = libusb_init(&(x52_dev->ctx)); rc = libusb_init(&(x52_dev->ctx));
if (rc) { if (rc) {
rc = LIBX52_ERROR_INIT_FAILURE; rc = LIBX52_ERROR_INIT_FAILURE;
@ -109,6 +125,6 @@ void libx52_exit(libx52_device *dev)
{ {
libusb_close(dev->hdl); libusb_close(dev->hdl);
libusb_exit(dev->ctx); libusb_exit(dev->ctx);
free(dev); (*(dev->memfree))(dev);
} }