Skip to content

Commit da36e7e

Browse files
committed
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
1 parent 09bcfa2 commit da36e7e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1585
-725
lines changed
File renamed without changes.

libc/dns/parsehoststxt.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "libc/alg/arraylist.internal.h"
2020
#include "libc/dns/dns.h"
2121
#include "libc/dns/hoststxt.h"
22+
#include "libc/errno.h"
2223
#include "libc/runtime/runtime.h"
2324
#include "libc/sock/sock.h"
2425
#include "libc/stdio/stdio.h"
@@ -43,28 +44,28 @@
4344
* @see hoststxtsort() which is the logical next step
4445
*/
4546
int parsehoststxt(struct HostsTxt *ht, FILE *f) {
46-
int rc;
4747
char *line;
4848
size_t linesize;
49-
rc = 0;
49+
struct HostsTxtEntry entry;
50+
char *addr, *name, *tok, *comment;
5051
line = NULL;
5152
linesize = 0;
5253
while ((getline(&line, &linesize, f)) != -1) {
53-
struct HostsTxtEntry entry;
54-
char *addr, *name, *tok, *comment;
5554
if ((comment = strchr(line, '#'))) *comment = '\0';
5655
if ((addr = strtok_r(line, " \t\r\n\v", &tok)) &&
5756
inet_pton(AF_INET, addr, entry.ip) == 1) {
5857
entry.canon = ht->strings.i;
5958
while ((name = strtok_r(NULL, " \t\r\n\v", &tok))) {
6059
entry.name = ht->strings.i;
61-
if (concat(&ht->strings, name, strnlen(name, DNS_NAME_MAX) + 1) == -1 ||
62-
append(&ht->entries, &entry) == -1) {
63-
rc = -1;
64-
}
60+
concat(&ht->strings, name, strnlen(name, DNS_NAME_MAX) + 1);
61+
append(&ht->entries, &entry);
6562
}
6663
}
6764
}
6865
free(line);
69-
return rc | ferror(f);
66+
if (ferror(f)) {
67+
errno = ferror(f);
68+
return -1;
69+
}
70+
return 0;
7071
}

libc/log/vflogf.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void vflogf_onfail(FILE *f) {
6464
struct stat st;
6565
if (IsTiny()) return;
6666
err = ferror(f);
67-
if ((err == ENOSPC || err == EDQUOT || err == EFBIG) &&
67+
if (fileno(f) != -1 && (err == ENOSPC || err == EDQUOT || err == EFBIG) &&
6868
(fstat(fileno(f), &st) == -1 || st.st_size > kNontrivialSize)) {
6969
ftruncate(fileno(f), 0);
7070
fseek(f, SEEK_SET, 0);
@@ -91,14 +91,15 @@ void vflogf_onfail(FILE *f) {
9191
*/
9292
void(vflogf)(unsigned level, const char *file, int line, FILE *f,
9393
const char *fmt, va_list va) {
94+
int bufmode;
9495
struct tm tm;
9596
long double t2;
9697
const char *prog;
9798
bool issamesecond;
9899
char buf32[32], *buf32p;
99100
int64_t secs, nsec, dots;
100101
if (!f) f = __log_file;
101-
if (fileno(f) == -1) return;
102+
if (!f) return;
102103
t2 = nowl();
103104
secs = t2;
104105
nsec = (t2 - secs) * 1e9L;
@@ -114,6 +115,8 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f,
114115
buf32p = "--------------------";
115116
}
116117
prog = basename(program_invocation_name);
118+
bufmode = f->bufmode;
119+
if (bufmode == _IOLBF) f->bufmode = _IOFBF;
117120
if ((fprintf)(f, "%c%s%06ld:%s:%d:%.*s:%d] ", vflogf_loglevel2char(level),
118121
buf32p, rem1000000int64(div1000int64(dots)), file, line,
119122
strchrnul(prog, '.') - prog, prog, getpid()) <= 0) {
@@ -122,6 +125,10 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f,
122125
(vfprintf)(f, fmt, va);
123126
va_end(va);
124127
fputs("\n", f);
128+
if (bufmode == _IOLBF) {
129+
f->bufmode = _IOLBF;
130+
fflush(f);
131+
}
125132
if (level == kLogFatal) {
126133
__start_fatal(file, line);
127134
strcpy(buf32, "unknown");

libc/runtime/ftrace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static char g_buf[512];
5353
static const char *g_lastsymbol;
5454
static struct SymbolTable *g_symbols;
5555

56-
forceinline int GetNestingLevel(struct StackFrame *frame) {
56+
static noasan int GetNestingLevel(struct StackFrame *frame) {
5757
int nesting = -2;
5858
while (frame) {
5959
++nesting;
@@ -69,7 +69,7 @@ forceinline int GetNestingLevel(struct StackFrame *frame) {
6969
* prologues of other functions. We assume those functions behave
7070
* according to the System Five NexGen32e ABI.
7171
*/
72-
privileged void ftrace(void) {
72+
privileged noasan void ftrace(void) {
7373
size_t i, j, nesting;
7474
const char *symbol;
7575
struct StackFrame *frame;

libc/stdio/fdopen.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ FILE *fdopen(int fd, const char *mode) {
3535
FILE *f;
3636
if ((f = calloc(1, sizeof(FILE)))) {
3737
f->fd = fd;
38-
f->reader = __freadbuf;
39-
f->writer = __fwritebuf;
4038
f->bufmode = ischardev(fd) ? _IOLBF : _IOFBF;
4139
f->iomode = fopenflags(mode);
4240
f->size = BUFSIZ;

libc/stdio/fflush.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "libc/bits/bits.h"
2121
#include "libc/bits/pushpop.h"
2222
#include "libc/calls/calls.h"
23+
#include "libc/errno.h"
2324
#include "libc/macros.internal.h"
2425
#include "libc/mem/mem.h"
2526
#include "libc/runtime/runtime.h"
@@ -36,28 +37,26 @@
3637
*/
3738
int fflush(FILE *f) {
3839
size_t i;
39-
int rc;
40-
rc = 0;
40+
ssize_t rc;
4141
if (!f) {
4242
for (i = __fflush.handles.i; i; --i) {
4343
if ((f = __fflush.handles.p[i - 1])) {
44-
if (fflush(f) == -1) {
45-
rc = -1;
46-
break;
47-
}
44+
if (fflush(f) == -1) return -1;
4845
}
4946
}
5047
} else if (f->fd != -1) {
51-
while (f->beg && !f->end) {
52-
if (__fwritebuf(f) == -1) {
53-
rc = -1;
54-
break;
48+
while (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
49+
if ((rc = write(f->fd, f->buf, f->beg)) == -1) {
50+
f->state = errno;
51+
return -1;
5552
}
53+
if (rc != f->beg) abort();
54+
f->beg = 0;
5655
}
5756
} else if (f->beg && f->beg < f->size) {
5857
f->buf[f->beg] = 0;
5958
}
60-
return rc;
59+
return 0;
6160
}
6261

6362
textstartup int __fflush_register(FILE *f) {

libc/stdio/fgetc.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,18 @@
1616
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
1717
│ PERFORMANCE OF THIS SOFTWARE. │
1818
╚─────────────────────────────────────────────────────────────────────────────*/
19-
#include "libc/stdio/internal.h"
2019
#include "libc/stdio/stdio.h"
2120

22-
static noinline int __fgetc(FILE *f) {
23-
if (!f->reader) return __fseteof(f);
24-
if (f->reader(f) == -1) return -1;
25-
return f->buf[f->beg++];
26-
}
27-
2821
/**
29-
* Reads uint8_t from stream.
22+
* Reads byte from stream.
23+
* @return byte in range 0..255, or -1 w/ errno
3024
*/
3125
int fgetc(FILE *f) {
26+
unsigned char b;
3227
if (f->beg < f->end) {
33-
return f->buf[f->beg++];
28+
return f->buf[f->beg++] & 0xff;
3429
} else {
35-
return __fgetc(f);
30+
if (!fread(&b, 1, 1, f)) return -1;
31+
return b;
3632
}
3733
}

libc/stdio/fgetwc.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,35 @@
1717
│ PERFORMANCE OF THIS SOFTWARE. │
1818
╚─────────────────────────────────────────────────────────────────────────────*/
1919
#include "libc/stdio/stdio.h"
20+
#include "libc/str/thompike.h"
2021
#include "libc/str/tpdecodecb.internal.h"
2122

2223
/**
2324
* Reads UTF-8 character from stream.
24-
*
2525
* @return wide character or -1 on EOF or error
2626
*/
2727
wint_t fgetwc(FILE *f) {
28-
wint_t res;
29-
res = -1;
30-
tpdecodecb(&res, fgetc(f), (void *)fgetc, f);
31-
return res;
28+
int c, n;
29+
wint_t b, x, y;
30+
if (f->beg < f->end) {
31+
b = f->buf[f->beg++] & 0xff;
32+
} else if ((c = fgetc(f)) != -1) {
33+
b = c;
34+
} else {
35+
return -1;
36+
}
37+
if (b < 0300) return b;
38+
n = ThomPikeLen(b);
39+
x = ThomPikeByte(b);
40+
while (--n) {
41+
if ((c = fgetc(f)) == -1) return -1;
42+
y = c;
43+
if (ThomPikeCont(y)) {
44+
x = ThomPikeMerge(x, y);
45+
} else {
46+
ungetc(y, f);
47+
return b;
48+
}
49+
}
50+
return x;
3251
}

libc/stdio/fgetws.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
* Reads UTF-8 content from stream into UTF-32 buffer.
2525
*/
2626
wchar_t *fgetws(wchar_t *s, int size, FILE *f) {
27+
wint_t c;
2728
wchar_t *p = s;
2829
if (size > 0) {
2930
while (--size > 0) {
30-
wint_t c;
3131
if ((c = fgetwc(f)) == -1) {
3232
if (ferror(f) == EINTR) continue;
3333
break;

libc/stdio/fmemopen.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,39 +32,33 @@ FILE *fmemopen(void *buf, size_t size, const char *mode) {
3232
FILE *f;
3333
char *p;
3434
unsigned flags;
35-
3635
if (size && size > 0x7ffff000) {
3736
einval();
3837
return NULL;
3938
}
40-
4139
if (!(f = calloc(1, sizeof(FILE)))) {
4240
return NULL;
4341
}
44-
45-
if (!buf) {
42+
if (buf) {
43+
f->nofree = true;
44+
} else {
4645
if (!size) size = BUFSIZ;
4746
if (!(buf = calloc(1, size))) {
4847
free(f);
4948
return NULL;
5049
}
51-
} else {
52-
f->nofree = true;
5350
}
54-
5551
f->fd = -1;
5652
f->buf = buf;
57-
f->size = size;
5853
f->end = size;
54+
f->size = size;
5955
f->iomode = fopenflags(mode);
60-
6156
if (f->iomode & O_APPEND) {
6257
if ((p = memchr(buf, '\0', size))) {
6358
f->beg = p - (char *)buf;
6459
} else {
6560
f->beg = f->end;
6661
}
6762
}
68-
6963
return f;
7064
}

0 commit comments

Comments
 (0)