summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Minichmayr <markus@tapkey.com>2018-03-02 17:40:36 +0100
committerMarkus Minichmayr <markus@tapkey.com>2022-02-15 08:54:22 +0100
commit6634726906548b00cb14cada82b3aa6fd445c8d4 (patch)
tree20a13274042e391aed4bffd15acbb4237bc77b1b
parentf109855e238f7857d4683be838e8acd5fcafd0a2 (diff)
downloadlibical-git-6634726906548b00cb14cada82b3aa6fd445c8d4.tar.gz
icalmemory: Making memory management functions configurable.
-rw-r--r--config.h.cmake4
-rw-r--r--src/libical/icalmemory.c63
-rw-r--r--src/libical/icalmemory.h57
3 files changed, 115 insertions, 9 deletions
diff --git a/config.h.cmake b/config.h.cmake
index 93f7c6e7..834dd7b1 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -551,3 +551,7 @@ typedef ssize_t IO_SSIZE_T;
#define icalassert(...) assert(__VA_ARGS__)
#define icalerrprintf(...) fprintf(stderr, __VA_ARGS__)
+
+#define ICALMEMORY_DEFAULT_MALLOC malloc
+#define ICALMEMORY_DEFAULT_REALLOC realloc
+#define ICALMEMORY_DEFAULT_FREE free \ No newline at end of file
diff --git a/src/libical/icalmemory.c b/src/libical/icalmemory.c
index 3650cfe3..de52c94a 100644
--- a/src/libical/icalmemory.c
+++ b/src/libical/icalmemory.c
@@ -281,6 +281,44 @@ char *icalmemory_strdup(const char *s)
return res;
}
+#if defined(ICALMEMORY_DEFAULT_MALLOC)
+static icalmemory_malloc_f global_icalmem_malloc = &ICALMEMORY_DEFAULT_MALLOC;
+#else
+static icalmemory_malloc_f global_icalmem_malloc = NULL;
+#endif
+
+#if defined(ICALMEMORY_DEFAULT_REALLOC)
+static icalmemory_realloc_f global_icalmem_realloc = &ICALMEMORY_DEFAULT_REALLOC;
+#else
+static icalmemory_realloc_f global_icalmem_realloc = NULL;
+#endif
+
+#if defined(ICALMEMORY_DEFAULT_FREE)
+static icalmemory_free_f global_icalmem_free = &ICALMEMORY_DEFAULT_FREE;
+#else
+static icalmemory_free_f global_icalmem_free = NULL;
+#endif
+
+
+void icalmemory_set_mem_alloc_funcs(icalmemory_malloc_f f_malloc, icalmemory_realloc_f f_realloc, icalmemory_free_f f_free)
+{
+ global_icalmem_malloc = f_malloc;
+ global_icalmem_realloc = f_realloc;
+ global_icalmem_free = f_free;
+}
+
+void icalmemory_get_mem_alloc_funcs(icalmemory_malloc_f* f_malloc, icalmemory_realloc_f* f_realloc, icalmemory_free_f* f_free) {
+ if (f_malloc) {
+ *f_malloc = global_icalmem_malloc;
+ }
+ if (f_realloc) {
+ *f_realloc = global_icalmem_realloc;
+ }
+ if (f_free) {
+ *f_free = global_icalmem_free;
+ }
+}
+
/*
* These buffer routines create memory the old fashioned way -- so the
* caller will have to deallocate the new memory
@@ -288,7 +326,14 @@ char *icalmemory_strdup(const char *s)
void *icalmemory_new_buffer(size_t size)
{
- void *b = malloc(size);
+ void *b;
+
+ if (global_icalmem_malloc == NULL) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ b = global_icalmem_malloc(size);
if (b == 0) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
@@ -302,7 +347,14 @@ void *icalmemory_new_buffer(size_t size)
void *icalmemory_resize_buffer(void *buf, size_t size)
{
- void *b = realloc(buf, size);
+ void *b;
+
+ if (global_icalmem_realloc == NULL) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ b = global_icalmem_realloc(buf, size);
if (b == 0) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
@@ -314,7 +366,12 @@ void *icalmemory_resize_buffer(void *buf, size_t size)
void icalmemory_free_buffer(void *buf)
{
- free(buf);
+ if (global_icalmem_free == NULL) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return;
+ }
+
+ global_icalmem_free(buf);
}
void icalmemory_append_string(char **buf, char **pos, size_t *buf_size, const char *string)
diff --git a/src/libical/icalmemory.h b/src/libical/icalmemory.h
index 81d39909..e0e036e0 100644
--- a/src/libical/icalmemory.h
+++ b/src/libical/icalmemory.h
@@ -103,7 +103,11 @@ LIBICAL_ICAL_EXPORT char *icalmemory_tmp_copy(const char *str);
* Adds an externally allocated buffer to the ring. This ensures that libical
* will `free()` the buffer automatically, either after ::BUFFER_RING_SIZE other
* buffers have been created or added, or after ::icalmemory_free_ring() has
- * been called.
+ * been called. Note that freeing the buffers is done using the
+ * icalmemory_free_buffer() function, which by default is a wrapper around stdlib's
+ * free() function. However, if the memory management functions are
+ * customized by the user, the user must make sure to only pass in buffers
+ * that have been allocated in a compatible manner.
*
* @par Error handling
* No error is raised if @a buf is `NULL`.
@@ -141,10 +145,42 @@ LIBICAL_ICAL_EXPORT void icalmemory_add_tmp_buffer(void *buf);
*/
LIBICAL_ICAL_EXPORT void icalmemory_free_ring(void);
-/* Non-tmp buffers must be freed. These are mostly wrappers around
- * icalmemory_new_buffer, etc, but are used so the caller can change the memory
- * allocators in a future version of the library */
+typedef void* (*icalmemory_malloc_f)(size_t);
+typedef void* (*icalmemory_realloc_f)(void*, size_t);
+typedef void (*icalmemory_free_f)(void*);
+
+/**
+ * @brief Configures the functions to use for memory management.
+ *
+ * @param f_malloc The function to use for memory allocation.
+ * @param f_realloc The function to use for memory reallocation.
+ * @param f_free The function to use for memory deallocation.
+ *
+ * This function configures the library to use the specified functions for
+ * memory management. By default the standard system memory management
+ * functions malloc(), realloc() and free() are used.
+ *
+ * Note: The memory management functions configured via this
+ * functions are used throughout the core libical component but not within
+ * other components like libicalvcal.
+ * @since 3.1.0
+ */
+LIBICAL_ICAL_EXPORT void icalmemory_set_mem_alloc_funcs(icalmemory_malloc_f f_malloc, icalmemory_realloc_f f_realloc, icalmemory_free_f f_free);
+
+/**
+ * @brief Returns the functions used for memory management.
+ *
+ * @param f_malloc A pointer to the function to use for memory allocation.
+ * @param f_realloc A pointer to the function to use for memory reallocation.
+ * @param f_free A pointer to the function to use for memory deallocation.
+ *
+ * Retrieves the functions used by the library for memory management.
+ * @since 3.1.0
+ */
+LIBICAL_ICAL_EXPORT void icalmemory_get_mem_alloc_funcs(icalmemory_malloc_f* f_malloc, icalmemory_realloc_f* f_realloc, icalmemory_free_f* f_free);
+
+
/**
* @brief Creates new buffer with the specified size.
* @param size The size of the buffer that is to be created.
@@ -156,12 +192,15 @@ LIBICAL_ICAL_EXPORT void icalmemory_free_ring(void);
* ::ICAL_NEWFAILED_ERROR and returns `NULL`.
*
* @par Ownership
- * Buffers created with this method are owned by the caller. The must be
- * released with the appropriate icalmemory_free_buffer() method.
+ * Buffers created with this method are owned by the caller. They must be
+ * released with the icalmemory_free_buffer() method.
*
* This creates a new (non-temporary) buffer of the specified @a size. All
* buffers returned by this method are zeroed-out.
*
+ * By default this function delegates to stdlib's malloc() but
+ * the used function can be changed via icalmemory_set_mem_alloc_funcs().
+ *
* ### Usage
* ```c
* // create buffer
@@ -194,6 +233,9 @@ LIBICAL_ICAL_EXPORT void *icalmemory_new_buffer(size_t size);
* appropriate icalmemory_free_buffer() method. The old buffer, @a buf, can not
* be used anymore after calling this method.
*
+ * By default this function delegates to stdlib's realloc() but
+ * the used function can be configured via icalmemory_set_mem_alloc_funcs().
+ *
* ### Usage
* ```c
* // create new buffer
@@ -220,6 +262,9 @@ LIBICAL_ICAL_EXPORT void *icalmemory_resize_buffer(void *buf, size_t size);
* @sa icalmemory_new_buffer()
*
* Releases the memory of the buffer.
+ *
+ * By default this function delegates to stdlib's free() but
+ * the used function can be configured via icalmemory_set_mem_alloc_funcs().
*/
LIBICAL_ICAL_EXPORT void icalmemory_free_buffer(void *buf);