BLI_dynstr: add memarena-based version, and helper to clear without freeing.

This commit is contained in:
Bastien Montagne 2017-04-24 10:42:10 +02:00
parent 5a232039d5
commit 6d9a223c90
2 changed files with 61 additions and 15 deletions

View File

@ -43,11 +43,14 @@
#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__ */

View 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);
}