util: Add xa{v}sprintf_append functions

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@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
main
Rob Herring 2018-11-24 14:47:54 -06:00 committed by David Gibson
parent 82a52ce457
commit a1eff70c02
2 changed files with 41 additions and 21 deletions

60
util.c
View File

@ -46,36 +46,54 @@ char *xstrdup(const char *s)
return d; return d;
} }


/* based in part from (3) vsnprintf */ int xavsprintf_append(char **strp, const char *fmt, va_list ap)
int xasprintf(char **strp, const char *fmt, ...)
{ {
int n, size = 128; /* start with 128 bytes */ int n, size = 0; /* start with 128 bytes */
char *p; char *p;
va_list ap; va_list ap_copy;


/* initial pointer is NULL making the fist realloc to be malloc */ p = *strp;
p = NULL; if (p)
while (1) { size = strlen(p);
p = xrealloc(p, size);


/* Try to print in the allocated space. */ va_copy(ap_copy, ap);
va_start(ap, fmt); n = vsnprintf(NULL, 0, fmt, ap_copy) + 1;
n = vsnprintf(p, size, fmt, ap); va_end(ap_copy);
va_end(ap);
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; *strp = p;
return strlen(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) char *join_path(const char *path, const char *name)
{ {
int lenp = strlen(path); int lenp = strlen(path);

2
util.h
View File

@ -72,6 +72,8 @@ static inline void *xrealloc(void *p, size_t len)
extern char *xstrdup(const char *s); extern char *xstrdup(const char *s);


extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); 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); extern char *join_path(const char *path, const char *name);


/** /**