forked from lda/telodendria
Fix broken IoVprintf().
You can't call vsnprintf() on the same va_list more than once! I learned this the hard way with StreamVprintf().
This commit is contained in:
parent
5289c16e2b
commit
6c9e939b9f
2 changed files with 14 additions and 33 deletions
4
TODO.txt
4
TODO.txt
|
@ -12,8 +12,8 @@ Milestone: v0.3.0
|
|||
-----------------
|
||||
|
||||
[~] Stream API
|
||||
[~] Implementation
|
||||
[ ] Convert all code that deals with I/O
|
||||
[x] Implementation
|
||||
[x] Convert all code that deals with I/O
|
||||
[!] Multi-output (proof of concept)
|
||||
[!] Memory streams (proof of concept)
|
||||
[ ] TLS
|
||||
|
|
43
src/Io.c
43
src/Io.c
|
@ -25,8 +25,9 @@
|
|||
|
||||
#include <Memory.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
struct Io
|
||||
|
@ -133,8 +134,9 @@ IoClose(Io * io)
|
|||
int
|
||||
IoVprintf(Io * io, const char *fmt, va_list ap)
|
||||
{
|
||||
char *buf;
|
||||
int write;
|
||||
char *buf = NULL;
|
||||
size_t bufSize = 0;
|
||||
FILE *fp;
|
||||
|
||||
int ret;
|
||||
|
||||
|
@ -143,42 +145,21 @@ IoVprintf(Io * io, const char *fmt, va_list ap)
|
|||
return -1;
|
||||
}
|
||||
|
||||
buf = Malloc(IO_BUFFER);
|
||||
if (!buf)
|
||||
fp = open_memstream(&buf, &bufSize);
|
||||
if (!fp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
write = vsnprintf(buf, IO_BUFFER, fmt, ap);
|
||||
ret = vfprintf(fp, fmt, ap);
|
||||
fclose(fp);
|
||||
|
||||
if (write < 0)
|
||||
if (ret >= 0)
|
||||
{
|
||||
Free(buf);
|
||||
return write;
|
||||
ret = IoWrite(io, buf, bufSize);
|
||||
}
|
||||
|
||||
/* Number of bytes to write exceeded buffer size; this should be
|
||||
* rare, but may occasionally happen. If it does, realloc to the
|
||||
* correct size and try again. */
|
||||
if (write >= IO_BUFFER)
|
||||
{
|
||||
char *new = Realloc(buf, write + 1);
|
||||
|
||||
if (!new)
|
||||
{
|
||||
Free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = new;
|
||||
|
||||
/* This time we don't care about the return value */
|
||||
vsnprintf(buf, write, fmt, ap);
|
||||
}
|
||||
|
||||
ret = IoWrite(io, buf, write);
|
||||
|
||||
Free(buf);
|
||||
free(buf); /* Allocated by stdlib, not Memory API */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue