summaryrefslogtreecommitdiff
path: root/libmu_sieve/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmu_sieve/mem.c')
-rw-r--r--libmu_sieve/mem.c206
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);
+}
+

Return to:

Send suggestions and report system problems to the System administrator.