Changeset: 1a666a65fa35 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/1a666a65fa35
Modified Files:
        clients/mapilib/msettings.c
        clients/mapilib/msettings.h
        clients/mapilib/msettings_internal.h
Branch: odbc_loader
Log Message:

Allow custom allocator for msettings


diffs (truncated from 341 to 300 lines):

diff --git a/clients/mapilib/msettings.c b/clients/mapilib/msettings.c
--- a/clients/mapilib/msettings.c
+++ b/clients/mapilib/msettings.c
@@ -54,29 +54,6 @@ int msetting_parse_bool(const char *text
        return -1;
 }
 
-char* allocprintf(const char *fmt, ...)
-       __attribute__((__format__(__printf__, 1, 2)));
-
-char *
-allocprintf(const char *fmt, ...)
-{
-       va_list ap;
-       char *buf = NULL;
-       size_t pos = 0, cap = 0;
-       int n;
-
-       va_start(ap, fmt);
-       n = vreallocprintf(&buf, &pos, &cap, fmt, ap);
-       va_end(ap);
-
-       if (n >= 0)
-               return buf;
-       free(buf);
-       return NULL;
-}
-
-
-
 
 static const struct { const char *name;  mparm parm; }
 by_name[] = {
@@ -208,53 +185,92 @@ const msettings msettings_default_values
 
 const msettings *msettings_default = &msettings_default_values;
 
+static void*
+default_alloc(void *state, void *old, size_t size)
+{
+       (void)state;
+       return realloc(old, size);
+}
+
+msettings *msettings_create_with(msettings_allocator alloc, void 
*allocator_state)
+{
+       if (alloc == NULL) {
+               alloc = default_alloc;
+               allocator_state = NULL;
+       }
+
+       msettings *mp = alloc(allocator_state, NULL, sizeof(*mp));
+       if (!mp)
+               return NULL;
+
+       *mp = msettings_default_values;
+       mp->alloc = alloc;
+       mp->alloc_state = allocator_state;
+
+       return mp;
+}
+
 msettings *msettings_create(void)
 {
-       msettings *mp = malloc(sizeof(*mp));
-       if (!mp) {
+       return msettings_create_with(NULL, NULL);
+}
+
+msettings *msettings_clone_with(msettings_allocator alloc, void *alloc_state, 
const msettings *orig)
+{
+       bool free_unix_sock_name_buffer = false;
+       struct string *copy_start = NULL;
+       struct string *copy_pos = NULL;
+
+       msettings *mp = msettings_create_with(alloc, alloc_state);
+       if (!mp)
                return NULL;
+
+       // Before we copy orig over mp, remember mp's allocator as decided by 
msettings_create_with.
+       alloc = mp->alloc;
+       alloc_state = mp->alloc_state;
+
+       // Copy the whole struct, including the pointers to data owned by orig.
+       // This means we must be really careful when we abort halfway and need 
to free 'mp'.
+       // We will use 'start' and 'pos' to keep track of which strings must be 
free'd BY US
+       *mp = *orig;
+       mp->alloc = alloc;
+       mp->alloc_state = alloc_state;
+       copy_start = &mp->dummy_start_string;
+       copy_pos = copy_start;
+
+       if (orig->unix_sock_name_buffer) {
+               mp->unix_sock_name_buffer = msettings_strdup(mp, 
orig->unix_sock_name_buffer);
+               if (mp->unix_sock_name_buffer == NULL)
+                       goto bailout;
+               free_unix_sock_name_buffer = true;
        }
-       *mp = msettings_default_values;
+
+       // Duplicate the strings that need to be duplicated
+       for (; copy_pos < &mp->dummy_end_string; copy_pos++) {
+               if (copy_pos->must_free) {
+                       copy_pos->str = msettings_strdup(mp, copy_pos->str);
+                       if (copy_pos->str == NULL)
+                               goto bailout;
+               }
+       }
+
+       // Now all references to data allocated by 'orig' has been copied.
        return mp;
+
+bailout:
+       if (free_unix_sock_name_buffer)
+               msettings_dealloc(mp, mp->unix_sock_name_buffer);
+       while (copy_start != copy_pos) {
+               msettings_dealloc(mp, copy_start->str);
+               copy_start++;
+       }
+       msettings_dealloc(mp, mp);
+       return NULL;
 }
 
 msettings *msettings_clone(const msettings *orig)
 {
-       msettings *mp = malloc(sizeof(*mp));
-       const char *namebuf = orig->unix_sock_name_buffer;
-       char *cloned_name_buffer = namebuf ? strdup(namebuf) : NULL;
-       if (!mp || (namebuf && !cloned_name_buffer)) {
-               free(mp);
-               free(cloned_name_buffer);
-               return NULL;
-       }
-       *mp = *orig;
-       mp->unix_sock_name_buffer = cloned_name_buffer;
-
-       // now we have to very carefully duplicate the strings.
-       // taking care to only free our own ones if that fails
-
-       struct string *start = &mp->dummy_start_string;
-       struct string *end = &mp->dummy_end_string;
-       struct string *p = start;
-       while (p < end) {
-               if (p->must_free) {
-                       p->str = strdup(p->str);
-                       if (p->str == NULL)
-                               goto bailout;
-               }
-               p++;
-       }
-
-       return mp;
-
-bailout:
-       for (struct string *q = start; q < p; q++)
-               if (q->must_free)
-                       free(q->str);
-       free(mp->unix_sock_name_buffer);
-       free(mp);
-       return NULL;
+       return msettings_clone_with(NULL, NULL, orig);
 }
 
 void
@@ -265,20 +281,24 @@ msettings_reset(msettings *mp)
        struct string *end = &mp->dummy_end_string;
        for (struct string *p = start; p < end; p++) {
                if (p->must_free)
-                       free(p->str);
+                       msettings_dealloc(mp, p->str);
        }
 
        // free the buffer
-       free(mp->unix_sock_name_buffer);
+       msettings_dealloc(mp, mp->unix_sock_name_buffer);
 
-       // keep the localizer
+       // keep the localizer and the allocator
        void *localizer = mp->localizer;
        void *localizer_data = mp->localizer_data;
+       msettings_allocator alloc = mp->alloc;
+       void *alloc_state = mp->alloc_state;
 
        // now overwrite the whole thing
        *mp = *msettings_default;
        mp->localizer = localizer;
        mp->localizer_data = localizer_data;
+       mp->alloc = alloc;
+       mp->alloc_state = alloc_state;
 }
 
 msettings *
@@ -289,10 +309,10 @@ msettings_destroy(msettings *mp)
 
        for (struct string *p = &mp->dummy_start_string + 1; p < 
&mp->dummy_end_string; p++) {
                if (p->must_free)
-                       free(p->str);
+                       msettings_dealloc(mp, p->str);
        }
-       free(mp->unix_sock_name_buffer);
-       free(mp);
+       msettings_dealloc(mp, mp->unix_sock_name_buffer);
+       msettings_dealloc(mp, mp);
 
        return NULL;
 }
@@ -362,11 +382,11 @@ msetting_set_string(msettings *mp, mparm
        if (p >=  &mp->dummy_end_string)
                FATAL();
 
-       char *v = strdup(value);
+       char *v = msettings_strdup(mp, value);
        if (!v)
                return MALLOC_FAILED;
        if (p->must_free)
-               free(p->str);
+               msettings_dealloc(mp, p->str);
        p->str = v;
        p->must_free = true;
 
@@ -665,8 +685,8 @@ msettings_validate(msettings *mp)
        // compute this here so the getter function can take const msettings*
        const char *sockdir = msetting_string(mp, MP_SOCKDIR);
        long effective_port = msettings_connect_port(mp);
-       free(mp->unix_sock_name_buffer);
-       mp->unix_sock_name_buffer = allocprintf("%s/.s.monetdb.%ld", sockdir, 
effective_port);
+       msettings_dealloc(mp, mp->unix_sock_name_buffer);
+       mp->unix_sock_name_buffer = msettings_allocprintf(mp, 
"%s/.s.monetdb.%ld", sockdir, effective_port);
        if (mp->unix_sock_name_buffer == NULL)
                return false;
 
diff --git a/clients/mapilib/msettings.h b/clients/mapilib/msettings.h
--- a/clients/mapilib/msettings.h
+++ b/clients/mapilib/msettings.h
@@ -126,12 +126,12 @@ typedef struct msettings msettings;
 typedef const char *msettings_error;
 mapi_export bool msettings_malloc_failed(msettings_error err);
 
-/* returns NULL if could not allocate */
+/* these return NULL if they cannot not allocate */
+typedef void *(*msettings_allocator)(void *state, void *old, size_t size);
 mapi_export msettings *msettings_create(void);
-
-mapi_export msettings *msettings_create_with();
-
+mapi_export msettings *msettings_create_with(msettings_allocator alloc, void 
*alloc_state);
 mapi_export msettings *msettings_clone(const msettings *mp);
+mapi_export msettings *msettings_clone_with(msettings_allocator alloc, void 
*alloc_state, const msettings *mp);
 mapi_export void msettings_reset(msettings *mp);
 mapi_export const msettings *msettings_default;
 
diff --git a/clients/mapilib/msettings_internal.h 
b/clients/mapilib/msettings_internal.h
--- a/clients/mapilib/msettings_internal.h
+++ b/clients/mapilib/msettings_internal.h
@@ -72,6 +72,8 @@ struct msettings {
        bool validated;
        const char* (*localizer)(const void *data, mparm parm);
        void *localizer_data;
+       void *(*alloc)(void *state, void *old, size_t size);
+       void *alloc_state;
        char error_message[256];
 };
 
@@ -79,5 +81,77 @@ struct msettings {
 const char *format_error(msettings *mp, const char *fmt, ...)
        __attribute__((__format__(__printf__, 2, 3)));
 
+// wrappers around mp->allocator
+
+static inline void*
+msettings_realloc(const msettings *mp, void *old, size_t size)
+{
+       return mp->alloc(mp->alloc_state, old, size);
+}
+
+static inline void*
+msettings_alloc(const msettings *mp, size_t size)
+{
+       return msettings_realloc(mp, NULL, size);
+}
+
+static inline void*
+msettings_alloc_zeroed(const msettings *mp, size_t size)
+{
+       char *data = msettings_realloc(mp, NULL, size);
+       memset(data, 0, size);
+       return data;
+}
+
+static inline void*
+msettings_dealloc(const msettings *mp, void *data)
+{
+       if (data != NULL)
+               msettings_realloc(mp, data, 0);
+       return NULL;
+}
+
+static inline void*
+msettings_strdup(const msettings *mp, const char *string)
+{
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to