Use vsnprintf() instead of vasprintf()

Windows doesn't reliably offer *asprintf() (sprintf functions that
automatically malloc as much memory as they need) so hand-roll the
equivalent on all platforms.
This commit is contained in:
Lassi Kortela 2019-08-21 22:10:13 +03:00
parent c76379e6f5
commit 439eeb2b06
1 changed files with 21 additions and 18 deletions

39
c/ios.c
View File

@ -992,43 +992,46 @@ char *ios_readline(struct ios *s)
return ios_takebuf(&dest, &n); return ios_takebuf(&dest, &n);
} }
int vasprintf(char **strp, const char *fmt, va_list ap);
int ios_vprintf(struct ios *s, const char *format, va_list args) int ios_vprintf(struct ios *s, const char *format, va_list args)
{ {
char *str; char *str;
int c;
va_list al; va_list al;
size_t avail; size_t avail;
int len;
char *start; char *start;
str = NULL;
va_copy(al, args); va_copy(al, args);
if (s->state == bst_wr && s->bpos < s->maxsize && s->bm != bm_none) { if (s->state == bst_wr && s->bpos < s->maxsize && s->bm != bm_none) {
avail = s->maxsize - s->bpos; avail = s->maxsize - s->bpos;
start = s->buf + s->bpos; start = s->buf + s->bpos;
c = vsnprintf(start, avail, format, args); len = vsnprintf(start, avail, format, args);
if (c < 0) { if (len < 0) {
va_end(al); goto done;
return c;
} }
if (avail > (size_t)c) { if (avail > (size_t)len) {
s->bpos += (size_t)c; s->bpos += (size_t)len;
_write_update_pos(s); _write_update_pos(s);
// TODO: only works right if newline is at end // TODO: only works right if newline is at end
if (s->bm == bm_line && our_memrchr(start, '\n', (size_t)c)) if (s->bm == bm_line && our_memrchr(start, '\n', (size_t)len)) {
ios_flush(s); ios_flush(s);
va_end(al); }
return c; goto done;
} }
} }
c = vasprintf(&str, format, al); len = vsnprintf(NULL, 0, format, al);
if (c >= 0) { if (len <= 0) {
ios_write(s, str, c); len = 0;
goto done;
}
if (!(str = calloc(1, len + 1))) {
goto done;
}
len = vsnprintf(str, len, format, al);
ios_write(s, str, len);
LLT_FREE(str); LLT_FREE(str);
} done:
va_end(al); va_end(al);
return c; return len;
} }
int ios_printf(struct ios *s, const char *format, ...) int ios_printf(struct ios *s, const char *format, ...)