On Sat, Nov 24, 2018 at 02:47:54PM -0600, Rob Herring wrote: > Add variadic and va_list functions, xa{v}sprintf, which appends a > formatted string to an existing string and re-allocate the string buffer > if necessary. xasprintf becomes just a special case of xasprintf_append > with a NULL starting string. > > Rather than looping to get a big enough buffer, simply the implementation > by assuming we have a C99 compliant vsnprintf implementation to return the > necessary size. A side effect is glibc 2.0 support is dropped which seems > unnecessary. > > Signed-off-by: Rob Herring <robh@xxxxxxxxxx> Series applied, thanks. > --- > util.c | 60 ++++++++++++++++++++++++++++++++++++++-------------------- > util.h | 2 ++ > 2 files changed, 41 insertions(+), 21 deletions(-) > > diff --git a/util.c b/util.c > index a69b7a13463d..9c6fb5f286ae 100644 > --- a/util.c > +++ b/util.c > @@ -46,36 +46,54 @@ char *xstrdup(const char *s) > return d; > } > > -/* based in part from (3) vsnprintf */ > -int xasprintf(char **strp, const char *fmt, ...) > +int xavsprintf_append(char **strp, const char *fmt, va_list ap) > { > - int n, size = 128; /* start with 128 bytes */ > + int n, size = 0; /* start with 128 bytes */ > char *p; > - va_list ap; > + va_list ap_copy; > > - /* initial pointer is NULL making the fist realloc to be malloc */ > - p = NULL; > - while (1) { > - p = xrealloc(p, size); > + p = *strp; > + if (p) > + size = strlen(p); > > - /* Try to print in the allocated space. */ > - va_start(ap, fmt); > - n = vsnprintf(p, size, fmt, ap); > - va_end(ap); > + va_copy(ap_copy, ap); > + n = vsnprintf(NULL, 0, fmt, ap_copy) + 1; > + va_end(ap_copy); > + > + p = xrealloc(p, size + n); > + > + n = vsnprintf(p + size, n, fmt, ap); > > - /* If that worked, return the string. */ > - if (n > -1 && n < size) > - break; > - /* Else try again with more space. */ > - if (n > -1) /* glibc 2.1 */ > - size = n + 1; /* precisely what is needed */ > - else /* glibc 2.0 */ > - size *= 2; /* twice the old size */ > - } > *strp = p; > return strlen(p); > } > > +int xasprintf_append(char **strp, const char *fmt, ...) > +{ > + int n; > + va_list ap; > + > + va_start(ap, fmt); > + n = xavsprintf_append(strp, fmt, ap); > + va_end(ap); > + > + return n; > +} > + > +int xasprintf(char **strp, const char *fmt, ...) > +{ > + int n; > + va_list ap; > + > + *strp = NULL; > + > + va_start(ap, fmt); > + n = xavsprintf_append(strp, fmt, ap); > + va_end(ap); > + > + return n; > +} > + > char *join_path(const char *path, const char *name) > { > int lenp = strlen(path); > diff --git a/util.h b/util.h > index f6cea8274174..7658781a6200 100644 > --- a/util.h > +++ b/util.h > @@ -72,6 +72,8 @@ static inline void *xrealloc(void *p, size_t len) > extern char *xstrdup(const char *s); > > extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); > +extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...); > +extern int xavsprintf_append(char **strp, const char *fmt, va_list ap); > extern char *join_path(const char *path, const char *name); > > /** -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Attachment:
signature.asc
Description: PGP signature