BLI_dynstr: add memarena-based version, and helper to clear without freeing.
authorBastien Montagne <montagne29@wanadoo.fr>
Mon, 24 Apr 2017 08:42:10 +0000 (10:42 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Mon, 24 Apr 2017 08:42:10 +0000 (10:42 +0200)
source/blender/blenlib/BLI_dynstr.h
source/blender/blenlib/intern/BLI_dynstr.c

index 7aa1c30e44923bbb8a910eb9fbe6e91f96c918d8..b26accc7f780c7250287a67373afae8cb92aba81 100644 (file)
 #include "BLI_compiler_attrs.h"
 
 struct DynStr;
+struct MemArena;
 
 /** The abstract DynStr type */
 typedef struct DynStr DynStr;
 
 DynStr *BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+DynStr *BLI_dynstr_new_memarena(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+
 void    BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL();
 void    BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) ATTR_NONNULL();
 
@@ -56,8 +59,9 @@ void    BLI_dynstr_vappendf(DynStr *__restrict ds, const char *__restrict format
 
 int     BLI_dynstr_get_len(DynStr *ds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 char   *BLI_dynstr_get_cstring(DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
 void    BLI_dynstr_get_cstring_ex(DynStr *__restrict ds, char *__restrict str) ATTR_NONNULL();
+
+void    BLI_dynstr_clear(DynStr *ds) ATTR_NONNULL();
 void    BLI_dynstr_free(DynStr *ds) ATTR_NONNULL();
 
 #endif  /* __BLI_DYNSTR_H__ */
index ecd4a6e6b093c63f321f1143bb60abfeb2e1493c..bce6614beb5fa8b846df7cf7869c55e3817d9305 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "MEM_guardedalloc.h"
 #include "BLI_utildefines.h"
+#include "BLI_memarena.h"
 #include "BLI_string.h"
 #include "BLI_dynstr.h"
 
@@ -64,6 +65,7 @@ struct DynStrElem {
 struct DynStr {
        DynStrElem *elems, *last;
        int curlen;
+       MemArena *memarena;
 };
 
 /***/
@@ -78,10 +80,31 @@ DynStr *BLI_dynstr_new(void)
        DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr");
        ds->elems = ds->last = NULL;
        ds->curlen = 0;
+       ds->memarena = NULL;
        
        return ds;
 }
 
+/**
+ * Create a new DynStr.
+ *
+ * \return Pointer to a new DynStr.
+ */
+DynStr *BLI_dynstr_new_memarena(void)
+{
+       DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr");
+       ds->elems = ds->last = NULL;
+       ds->curlen = 0;
+       ds->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+       return ds;
+}
+
+BLI_INLINE void *dynstr_alloc(DynStr *__restrict ds, size_t size)
+{
+       return ds->memarena ? BLI_memarena_alloc(ds->memarena, size) : malloc(size);
+}
+
 /**
  * Append a c-string to a DynStr.
  *
@@ -90,10 +113,10 @@ DynStr *BLI_dynstr_new(void)
  */
 void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr)
 {
-       DynStrElem *dse = malloc(sizeof(*dse));
+       DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse));
        int cstrlen = strlen(cstr);
        
-       dse->str = malloc(cstrlen + 1);
+       dse->str = dynstr_alloc(ds, cstrlen + 1);
        memcpy(dse->str, cstr, cstrlen + 1);
        dse->next = NULL;
        
@@ -114,10 +137,10 @@ void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr)
  */
 void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len)
 {
-       DynStrElem *dse = malloc(sizeof(*dse));
+       DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse));
        int cstrlen = BLI_strnlen(cstr, len);
 
-       dse->str = malloc(cstrlen + 1);
+       dse->str = dynstr_alloc(ds, cstrlen + 1);
        memcpy(dse->str, cstr, cstrlen);
        dse->str[cstrlen] = '\0';
        dse->next = NULL;
@@ -295,6 +318,29 @@ char *BLI_dynstr_get_cstring(DynStr *ds)
        return rets;
 }
 
+/**
+ * Clear the DynStr
+ *
+ * \param ds The DynStr to clear.
+ */
+void BLI_dynstr_clear(DynStr *ds)
+{
+       if (ds->memarena) {
+               BLI_memarena_clear(ds->memarena);
+       }
+       else {
+               for (DynStrElem *dse_next, *dse = ds->elems; dse; dse = dse_next) {
+                       dse_next = dse->next;
+
+                       free(dse->str);
+                       free(dse);
+               }
+       }
+
+       ds->elems = ds->last = NULL;
+       ds->curlen = 0;
+}
+
 /**
  * Free the DynStr
  *
@@ -302,16 +348,12 @@ char *BLI_dynstr_get_cstring(DynStr *ds)
  */
 void BLI_dynstr_free(DynStr *ds)
 {
-       DynStrElem *dse;
-       
-       for (dse = ds->elems; dse; ) {
-               DynStrElem *n = dse->next;
-               
-               free(dse->str);
-               free(dse);
-               
-               dse = n;
+       if (ds->memarena) {
+               BLI_memarena_free(ds->memarena);
        }
-       
+       else {
+               BLI_dynstr_clear(ds);
+       }
+
        MEM_freeN(ds);
 }