blob: 7ad49d24162d7fcdc94e1cb1b36baa0215d4a534 [file] [log] [blame]
/*
* fwrite.c
*/
#include <string.h>
#include "stdioint.h"
static size_t fwrite_noflush(const void *buf, size_t count, FILE *f)
{
size_t bytes = 0;
size_t nb;
const char *p = buf;
/* Note: one could avoid double-buffering large writes. */
for (;;) {
nb = f->bufsiz - f->bytes;
nb = (count < nb) ? count : nb;
if (nb) {
memcpy(f->buf+f->bytes, p, nb);
p += nb;
f->bytes += nb;
count -= nb;
bytes += nb;
f->filepos += nb;
f->flags |= _IO_FILE_FLAG_WRITE;
}
if (!count)
break; /* Done... */
/* If we get here, the buffer must be full */
if (fflush(f))
break;
}
return bytes;
}
size_t _fwrite(const void *buf, size_t count, FILE *f)
{
size_t bytes = 0;
size_t pf_len, pu_len;
const char *p = buf;
/* We divide the data into two chunks, flushed (pf)
and unflushed (pu) depending on buffering mode
and contents. */
if (f->flags & _IO_FILE_FLAG_UNBUF) {
pf_len = 0;
pu_len = count;
} else if (f->flags & _IO_FILE_FLAG_LINE_BUF) {
pf_len = count;
pu_len = 0;
while (pf_len && p[pf_len-1] != '\n') {
pf_len--;
pu_len++;
}
} else {
pf_len = 0;
pu_len = count;
}
if (pf_len) {
bytes = fwrite_noflush(p, pf_len, f);
p += bytes;
if (fflush(f) || bytes != pf_len)
return bytes;
}
if (pu_len)
bytes += fwrite_noflush(p, pu_len, f);
return bytes;
}