More string and buffer functions.
[apps/madmutt.git] / lib-lib / mem.h
index c1eb0b1..d981a80 100644 (file)
@@ -1,71 +1,56 @@
 /*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the Free
- *  Software Foundation; either version 2 of the License, or (at your option)
- *  any later version.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
  *
  *  This program 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 General Public License
- *  for more details.
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA 02110-1301, USA.
  *
- * Author: Pierre Habouzit <madcoder@debian.org>
+ *  Copyright © 2006 Pierre Habouzit
  */
 
 #ifndef MUTT_LIB_LIB_MEM_H
 #define MUTT_LIB_LIB_MEM_H
 
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-static inline void *xmalloc(ssize_t size) {
-    void *mem;
-
-    if (size <= 0)
-        return NULL;
-
-    mem = calloc(size, 1);
-    if (!mem)
-        abort();
-    return mem;
-}
-
-static inline void *xrealloc(void *mem, ssize_t newsize) {
-    mem = realloc(mem, newsize);
-    if (!mem)
-        abort();
-    return mem;
-}
-
-static inline void *xmemdup(const void *src, ssize_t size) {
-    return memcpy(xmalloc(size), src, size);
-}
-
-static inline void *xmemdupstr(const void *src, ssize_t len) {
-    char *res = xmalloc(len + 1);
-    memcpy(res, src, len);
-    res[len] = '\0';
-    return res;
-}
+#define ssizeof(foo)            (ssize_t)sizeof(foo)
+#define countof(foo)            (ssizeof(foo) / ssizeof(foo[0]))
 
 #define p_new(type, count)      ((type *)xmalloc(sizeof(type) * (count)))
 #define p_clear(p, count)       ((void)memset((p), 0, sizeof(*(p)) * (count)))
 #define p_dup(p, count)         xmemdup((p), sizeof(*(p)) * (count))
 #define p_dupstr(p, len)        xmemdupstr((p), (len))
+#define p_realloc(pp, count)    xrealloc((void*)(pp), sizeof(**(pp)) * (count))
+
+#define p_alloc_nr(x) (((x) + 16) * 3 / 2)
+
+#define p_allocgrow(pp, goalnb, allocnb)                  \
+  do {                                                    \
+      if ((goalnb) > *(allocnb)) {                        \
+          if (p_alloc_nr(*(allocnb)) < (goalnb)) {        \
+              *(allocnb) = (goalnb);                      \
+          } else {                                        \
+              *(allocnb) = p_alloc_nr(*(allocnb));        \
+          }                                               \
+          p_realloc(pp, *(allocnb));                      \
+      }                                                   \
+  } while (0)
 
 #ifdef __GNUC__
 
 #  define p_delete(mem_pp)                          \
-        ({                                          \
+        do {                                        \
             typeof(**(mem_pp)) **__ptr = (mem_pp);  \
             free(*__ptr);                           \
             *__ptr = NULL;                          \
-        })
+        } while(0)
 
 #else
 
@@ -78,8 +63,83 @@ static inline void *xmemdupstr(const void *src, ssize_t len) {
 
 #endif
 
+static inline void *xmalloc(ssize_t size) {
+    void *mem;
+
+    if (size <= 0)
+        return NULL;
+
+    mem = calloc(size, 1);
+    if (!mem)
+        abort();
+    return mem;
+}
+
 static inline void xmemfree(void **ptr) {
     p_delete(ptr);
 }
 
+static inline void xrealloc(void **ptr, ssize_t newsize) {
+    if (newsize <= 0) {
+        p_delete(ptr);
+    } else {
+        *ptr = realloc(*ptr, newsize);
+        if (!*ptr)
+            abort();
+    }
+}
+
+static inline void *xmemdup(const void *src, ssize_t size) {
+    return memcpy(xmalloc(size), src, size);
+}
+
+static inline void *xmemdupstr(const void *src, ssize_t len) {
+    char *res = memcpy(xmalloc(len + 1), src, len);
+    res[len] = '\0';
+    return res;
+}
+
+
+#define DO_REFCNT(type, prefix)                             \
+    static inline type *prefix##_new(void) {                \
+        type *res = prefix##_init(p_new(type, 1));          \
+        res->refcnt = 1;                                    \
+        return res;                                         \
+    }                                                       \
+    static inline type *prefix##_dup(type *t) {             \
+        t->refcnt++;                                        \
+        return t;                                           \
+    }                                                       \
+    static inline void prefix##_delete(type **tp) {         \
+        if (*tp) {                                          \
+            if (--(*tp)->refcnt > 0) {                      \
+                *tp = NULL;                                 \
+            } else {                                        \
+                prefix##_wipe(*tp);                         \
+                p_delete(tp);                               \
+            }                                               \
+        }                                                   \
+    }
+
+#define DO_INIT(type, prefix) \
+    static inline type * prefix##_init(type *var) {         \
+        p_clear(var, 1);                                    \
+        return var;                                         \
+    }
+#define DO_WIPE(type, prefix) \
+    static inline void prefix##_wipe(type *var __attribute__((unused))) { }
+
+#define DO_NEW(type, prefix) \
+    static inline type * prefix##_new(void) {               \
+        return prefix##_init(p_new(type, 1));               \
+    }
+#define DO_DELETE(type, prefix) \
+    static inline void __attribute__((nonnull))             \
+    prefix##_delete(type **var) {                           \
+        if (*var) {                                         \
+            prefix##_wipe(*var);                            \
+            p_delete(var);                                  \
+        }                                                   \
+    }
+
 #endif /* MUTT_LIB_LIB_MEM_H */