diff options
Diffstat (limited to 'libmu_sieve/mem.c')
-rw-r--r-- | libmu_sieve/mem.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/libmu_sieve/mem.c b/libmu_sieve/mem.c new file mode 100644 index 000000000..f03b06dd5 --- /dev/null +++ b/libmu_sieve/mem.c @@ -0,0 +1,206 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 1999-2002, 2005-2008, 2010-2012, 2014-2016 Free + Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <sieve-priv.h> + +struct memory_cell +{ + void *ptr; + void (*reclaim) (void *); +}; + +static void +memory_cell_destroy (void *item) +{ + struct memory_cell *mcp = item; + if (!mcp->reclaim) + abort (); + else + mcp->reclaim (mcp->ptr); + free (mcp); +} + +static int +memory_cell_cmp (const void *a, const void *b) +{ + struct memory_cell const *ma = a; + struct memory_cell const *mb = b; + return ma->ptr != mb->ptr; +} + +void +mu_sieve_register_memory (mu_sieve_machine_t mach, void *ptr, + mu_sieve_reclaim_t reclaim) +{ + struct memory_cell *mcp; + + if (!reclaim) + reclaim = mu_sieve_reclaim_default; + + if (!mach->memory_pool) + { + if (mu_list_create (&mach->memory_pool)) + mu_sieve_abort (mach); + mu_list_set_destroy_item (mach->memory_pool, memory_cell_destroy); + mu_list_set_comparator (mach->memory_pool, memory_cell_cmp); + } + mcp = malloc (sizeof (*mcp)); + if (!mcp) + mu_sieve_abort (mach); + mcp->ptr = ptr; + mcp->reclaim = reclaim; + if (mu_list_append (mach->memory_pool, mcp)) + { + memory_cell_destroy (mcp); + mu_sieve_abort (mach); + } +} + +void +mu_sieve_free (mu_sieve_machine_t mach, void *ptr) +{ + int rc; + struct memory_cell mcell; + + mcell.ptr = ptr; + rc = mu_list_remove (mach->memory_pool, &mcell); + if (rc) + { + mu_sieve_error (mach, _("INTERNAL ERROR: trying to free unregistered memory pointer")); + abort (); + } +} + +void * +mu_sieve_alloc_memory (mu_sieve_machine_t mach, size_t size, + mu_sieve_reclaim_t recfun) +{ + char *p = malloc (size); + if (!p) + { + mu_sieve_error (mach, "%s", mu_strerror (errno)); + mu_sieve_abort (mach); + } + mu_sieve_register_memory (mach, p, recfun); + return p; +} + +void * +mu_sieve_malloc (mu_sieve_machine_t mach, size_t size) +{ + return mu_sieve_alloc_memory (mach, size, mu_sieve_reclaim_default); +} + +void * +mu_sieve_calloc (mu_sieve_machine_t mach, size_t nmemb, size_t size) +{ + char *p = calloc (nmemb, size); + if (!p) + { + mu_sieve_error (mach, "%s", mu_strerror (errno)); + mu_sieve_abort (mach); + } + mu_sieve_register_memory (mach, p, mu_sieve_reclaim_default); + return p; +} + +char * +mu_sieve_strdup (mu_sieve_machine_t mach, char const *str) +{ + size_t len; + char *p; + + if (!str) + return NULL; + len = strlen (str); + p = mu_sieve_malloc (mach, len + 1); + memcpy (p, str, len); + p[len] = 0; + return p; +} + +void * +mu_sieve_realloc (mu_sieve_machine_t mach, void *ptr, size_t size) +{ + int rc; + struct memory_cell mcell, *mcp; + + if (!ptr) + return mu_sieve_malloc (mach, size); + + mcell.ptr = ptr; + rc = mu_list_locate (mach->memory_pool, &mcell, (void **)&mcp); + if (rc == MU_ERR_NOENT) + { + mu_sieve_error (mach, _("INTERNAL ERROR: trying to reallocate unregistered memory pointer")); + abort (); + } + else if (rc) + { + mu_sieve_error (mach, _("error reallocating memory: %s"), + mu_strerror (rc)); + mu_sieve_abort (mach); + } + + ptr = realloc (mcp->ptr, size); + if (!ptr) + { + mu_sieve_error (mach, _("error reallocating memory: %s"), + mu_strerror (errno)); + mu_sieve_abort (mach); + } + mcp->ptr = ptr; + + return ptr; +} + +void +mu_sieve_reclaim_default (void *p) +{ + free (p); +} + +void +mu_sieve_reclaim_list (void *p) +{ + mu_list_t list = p; + mu_list_destroy (&list); +} + +void +mu_sieve_reclaim_value (void *p) +{ + if (!p) + return; + /* For now, the same as _default. Will change in the future */ + free (p); +} + +void +mu_sieve_reclaim_tag (void *p) +{ + mu_sieve_runtime_tag_t *tag = p; + mu_sieve_reclaim_value (tag->arg); +} + |