mirror of https://github.com/mpv-player/mpv
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:
parent
56ce2a39be
commit
097fe8ea6f
51
bstr/bstr.c
51
bstr/bstr.c
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue