bstr: add bstr_xappend function

Apparently this can be really useful when being paranoid and trying to
avoid too much malloc/realloc, since it can be used to appending into a
buffer (with transparent realloc only if the buffer is too small).
This commit is contained in:
wm4 2013-12-30 20:20:28 +01:00
parent 56ce2a39be
commit 097fe8ea6f
2 changed files with 59 additions and 0 deletions

View File

@ -356,6 +356,57 @@ struct bstr bstr_sanitize_utf8_latin1(void *talloc_ctx, struct bstr s)
return new;
}
static void resize_append(void *talloc_ctx, bstr *s, size_t append_min)
{
size_t size = talloc_get_size(s->start);
assert(s->len <= size);
if (append_min > size - s->len) {
if (append_min < size)
append_min = size; // preallocate in power of 2s
s->start = talloc_realloc_size(talloc_ctx, s->start, size + append_min);
}
}
// Append the string, so that *s = *s + append. s->start is expected to be
// a talloc allocation (which can be realloced) or NULL.
// This function will always implicitly append a \0 after the new string for
// convenience.
// talloc_ctx will be used as parent context, if s->start is NULL.
void bstr_xappend(void *talloc_ctx, bstr *s, bstr append)
{
resize_append(talloc_ctx, s, append.len + 1);
memcpy(s->start + s->len, append.start, append.len);
s->len += append.len;
s->start[s->len] = '\0';
}
void bstr_xappend_asprintf(void *talloc_ctx, bstr *s, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
bstr_xappend_vasprintf(talloc_ctx, s, fmt, ap);
va_end(ap);
}
// Exactly as bstr_xappend(), but with a formatted string.
void bstr_xappend_vasprintf(void *talloc_ctx, bstr *s, const char *fmt,
va_list ap)
{
int size;
va_list copy;
va_copy(copy, ap);
char c;
size = vsnprintf(&c, 1, fmt, copy);
va_end(copy);
if (size < 0)
abort();
resize_append(talloc_ctx, s, size + 1);
vsnprintf(s->start + s->len, size + 1, fmt, ap);
s->len += size;
}
bool bstr_case_startswith(struct bstr s, struct bstr prefix)
{
struct bstr start = bstr_splice(s, 0, prefix.len);

View File

@ -23,8 +23,10 @@
#include <stddef.h>
#include <string.h>
#include <stdbool.h>
#include <stdarg.h>
#include "talloc.h"
#include "compat/compiler.h"
/* NOTE: 'len' is size_t, but most string-handling functions below assume
* that input size has been sanity checked and len fits in an int.
@ -118,6 +120,12 @@ struct bstr bstr_getline(struct bstr str, struct bstr *rest);
// and will remove the trailing \n or \r\n sequence.
struct bstr bstr_strip_linebreaks(struct bstr str);
void bstr_xappend(void *talloc_ctx, bstr *s, bstr append);
void bstr_xappend_asprintf(void *talloc_ctx, bstr *s, const char *fmt, ...)
PRINTF_ATTRIBUTE(3, 4);
void bstr_xappend_vasprintf(void *talloc_ctx, bstr *s, const char *fmt, va_list va)
PRINTF_ATTRIBUTE(3, 0);
// If s starts with prefix, return true and return the rest of the string in s.
bool bstr_eatstart(struct bstr *s, struct bstr prefix);