Make major improvements to stdio
Buffering now has optimal performance, bugs have been fixed, and some missing apis have been introduced. This implementation is also now more production worthy since it's less brittle now in terms of system errors. That's going to help redbean since lua i/o is all based on stdio. See #97
This commit is contained in:
@ -16,10 +16,17 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
/**
|
||||
* Writes data to stream.
|
||||
@ -29,10 +36,54 @@
|
||||
* @return count on success, [0,count) on EOF, 0 on error or count==0
|
||||
*/
|
||||
size_t fwrite(const void *data, size_t stride, size_t count, FILE *f) {
|
||||
size_t i, n;
|
||||
const unsigned char *p;
|
||||
for (n = stride * count, p = data, i = 0; i < n; ++i) {
|
||||
if (fputc(p[i], f) == -1) return -1;
|
||||
ldiv_t d;
|
||||
ssize_t rc;
|
||||
size_t n, m;
|
||||
const char *p;
|
||||
struct iovec iov[2];
|
||||
if ((f->iomode & O_ACCMODE) == O_RDONLY) {
|
||||
f->state = errno = EBADF;
|
||||
return 0;
|
||||
}
|
||||
n = stride * count;
|
||||
m = f->size - f->beg;
|
||||
if (n <= m && f->bufmode != _IONBF) {
|
||||
memcpy(f->buf + f->beg, data, n);
|
||||
f->beg += n;
|
||||
if (f->fd != -1 && f->bufmode == _IOLBF &&
|
||||
(p = memrchr(f->buf, '\n', f->beg))) {
|
||||
n = p + 1 - f->buf;
|
||||
if ((rc = write(f->fd, f->buf, n)) == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) return count;
|
||||
f->state = errno;
|
||||
return 0;
|
||||
}
|
||||
n = rc;
|
||||
memmove(f->buf, f->buf + n, f->beg - n);
|
||||
f->beg -= n;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
if (f->fd == -1) {
|
||||
n = MIN(n, m);
|
||||
d = ldiv(n, stride);
|
||||
n -= d.rem;
|
||||
memcpy(f->buf + f->beg, data, n);
|
||||
f->beg += n;
|
||||
f->state = -1;
|
||||
return d.quot;
|
||||
}
|
||||
iov[0].iov_base = f->buf;
|
||||
iov[0].iov_len = f->beg;
|
||||
iov[1].iov_base = data;
|
||||
iov[1].iov_len = n;
|
||||
n += f->beg;
|
||||
if ((rc = writev(f->fd, iov, 2)) == -1) {
|
||||
f->state = errno;
|
||||
return 0;
|
||||
}
|
||||
m = rc;
|
||||
if (n != m) abort();
|
||||
f->beg = 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user