Implemented fgets() and enhanced IO buffering

This commit is contained in:
2022-05-11 22:06:28 +01:00
parent c21902d3e0
commit f3e2312d35
7 changed files with 162 additions and 21 deletions

View File

@@ -11,6 +11,8 @@
#define FILENAME_MAX 1024 #define FILENAME_MAX 1024
#endif #endif
#define BUFSIZ __FIO_BUFSZ
#define SEEK_SET __SEEK_SET #define SEEK_SET __SEEK_SET
#define SEEK_CUR __SEEK_CUR #define SEEK_CUR __SEEK_CUR
#define SEEK_END __SEEK_END #define SEEK_END __SEEK_END
@@ -41,6 +43,7 @@ extern int fileno(FILE *fp);
extern int fputs(const char *str, FILE *fp); extern int fputs(const char *str, FILE *fp);
extern int fputc(int c, FILE *fp); extern int fputc(int c, FILE *fp);
extern int fgetc(FILE *fp); extern int fgetc(FILE *fp);
extern char *fgets(char *restrict str, int count, FILE *restrict fp);
extern int putchar(int c); extern int putchar(int c);
extern int ungetc(int c, FILE *fp); extern int ungetc(int c, FILE *fp);

View File

@@ -4,8 +4,8 @@
int fgetc(FILE *fp) int fgetc(FILE *fp)
{ {
char ch = 0; char ch = 0;
__fio_read(fp, &ch, 1); unsigned int r = __fio_read(fp, &ch, 1);
if (__fio_error(fp)) { if (r == 0 || __fio_error(fp) || __fio_eof(fp)) {
return EOF; return EOF;
} }

32
photon/libc/stdio/fgets.c Normal file
View File

@@ -0,0 +1,32 @@
#include <stdio.h>
char *fgets(char *restrict str, int count, FILE *restrict fp)
{
if (count < 1) {
return NULL;
}
if (count == 1) {
str[0] = '\0';
return str;
}
int r = 0;
while (1) {
int c = fgetc(fp);
if (c == EOF) {
str[r] = '\0';
break;
}
str[r++] = c;
if (r == count - 1 || c == '\n') {
str[r] = '\0';
break;
}
}
return r > 0 ? str : NULL;
}

View File

@@ -3,6 +3,10 @@
int ungetc(int c, FILE *fp) int ungetc(int c, FILE *fp)
{ {
if (c == EOF) {
return EOF;
}
int res = __fio_ungetc(fp, c); int res = __fio_ungetc(fp, c);
return res == -1 ? EOF : c; return res == -1 ? EOF : c;
} }

View File

@@ -8,11 +8,12 @@ extern "C" {
#endif #endif
struct __io_file { struct __io_file {
char buf[__FIO_BUFSZ]; char in_buf[__FIO_BUFSZ];
unsigned long buf_idx; char out_buf[__FIO_BUFSZ];
int fd; unsigned long in_buf_ptr, in_buf_len;
char err; unsigned long out_buf_len;
char unget; int fd, unget;
char err, eof;
}; };
extern int __fileno(struct __io_file *f); extern int __fileno(struct __io_file *f);
@@ -21,6 +22,7 @@ extern unsigned int __fio_read(struct __io_file *f, char *buf, unsigned int sz);
extern unsigned int __fio_write(struct __io_file *f, const char *buf, unsigned int sz); extern unsigned int __fio_write(struct __io_file *f, const char *buf, unsigned int sz);
extern unsigned int __fio_flush(struct __io_file *f); extern unsigned int __fio_flush(struct __io_file *f);
extern int __fio_error(struct __io_file *f); extern int __fio_error(struct __io_file *f);
extern int __fio_eof(struct __io_file *f);
extern int __fio_ungetc(struct __io_file *f, char c); extern int __fio_ungetc(struct __io_file *f, char c);
extern int __fio_fopen(const char *path, const char *mode, struct __io_file *out); extern int __fio_fopen(const char *path, const char *mode, struct __io_file *out);

View File

@@ -1,5 +1,5 @@
#include <magenta/misc.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include "sys/types.h" #include "sys/types.h"
#include "__fio.h" #include "__fio.h"
@@ -13,6 +13,20 @@ static int flags_from_mode(const char *r)
return 0; return 0;
} }
static int refill(struct __io_file *fp)
{
ssize_t err = read(fp->fd, fp->in_buf, sizeof fp->in_buf);
if (err < 0) {
fp->err = 1;
return 0;
}
fp->in_buf_ptr = 0;
fp->in_buf_len = err;
return err;
}
FILE *__get_stdio_file(int i) FILE *__get_stdio_file(int i)
{ {
switch (i) { switch (i) {
@@ -36,17 +50,37 @@ void __fio_init(int in, int out, int err)
int __fio_fopen(const char *path, const char *mode, struct __io_file *fp) int __fio_fopen(const char *path, const char *mode, struct __io_file *fp)
{ {
/* TODO */
int fd = open(path, 0);
if (fd == -1) {
return -1; return -1;
}
fp->fd = fd;
return 0;
} }
int __fio_fclose(struct __io_file *fp) int __fio_fclose(struct __io_file *fp)
{ {
if (fp->fd == -1) {
return -1; return -1;
}
close(fp->fd);
fp->fd = -1;
return 0;
} }
int __fio_fdopen(int fd, const char *mode, struct __io_file *fp) int __fio_fdopen(int fd, const char *mode, struct __io_file *fp)
{ {
if (fd == -1) {
return -1; return -1;
}
fp->fd = fd;
return 0;
} }
int __fileno(struct __io_file *f) int __fileno(struct __io_file *f)
@@ -56,23 +90,77 @@ int __fileno(struct __io_file *f)
unsigned int __fio_read(struct __io_file *f, char *buf, unsigned int sz) unsigned int __fio_read(struct __io_file *f, char *buf, unsigned int sz)
{ {
ssize_t err = read(f->fd, buf, sz); if (sz == 0) {
if (err < 0) {
f->err = 1;
return 0; return 0;
} }
return err; size_t r = 0;
char *out = buf;
if (f->unget) {
*out++ = f->unget;
f->unget = 0;
r++;
sz--;
}
size_t available = f->in_buf_len - f->in_buf_ptr;
size_t bufread = sz;
if (bufread > available) {
bufread = available;
}
memcpy(out, f->in_buf + f->in_buf_ptr, bufread);
f->in_buf_ptr += bufread;
out += bufread;
sz -= bufread;
r += bufread;
if (sz == 0) {
return r;
}
while (1) {
refill(f);
available = f->in_buf_len - f->in_buf_ptr;
if (available == 0) {
f->eof = 1;
break;
}
bufread = sz;
if (bufread > available) {
bufread = available;
}
memcpy(out, f->in_buf + f->in_buf_ptr, bufread);
f->in_buf_ptr += bufread;
out += bufread;
sz -= bufread;
r += bufread;
if (sz == 0 || f->err || f->eof) {
break;
}
}
if (sz > 0) {
f->eof = 1;
}
return r;
} }
unsigned int __fio_write(struct __io_file *f, const char *buf, unsigned int sz) unsigned int __fio_write(struct __io_file *f, const char *buf, unsigned int sz)
{ {
for (unsigned int i = 0; i < sz; i++) { for (unsigned int i = 0; i < sz; i++) {
if (f->buf_idx >= __FIO_BUFSZ) { if (f->out_buf_len >= __FIO_BUFSZ) {
__fio_flush(f); __fio_flush(f);
} }
f->buf[f->buf_idx++] = buf[i]; f->out_buf[f->out_buf_len++] = buf[i];
if (buf[i] == '\n') { if (buf[i] == '\n') {
__fio_flush(f); __fio_flush(f);
} }
@@ -83,18 +171,23 @@ unsigned int __fio_write(struct __io_file *f, const char *buf, unsigned int sz)
int __fio_ungetc(struct __io_file *f, char c) int __fio_ungetc(struct __io_file *f, char c)
{ {
if (f->unget) {
return -1;
}
f->unget = c;
return 0; return 0;
} }
unsigned int __fio_flush(struct __io_file *f) unsigned int __fio_flush(struct __io_file *f)
{ {
ssize_t res = write(f->fd, f->buf, f->buf_idx); ssize_t res = write(f->fd, f->out_buf, f->out_buf_len);
if (res != f->buf_idx) { if (res != f->out_buf_len) {
f->err = 1; f->err = 1;
} }
size_t flushed = f->buf_idx; size_t flushed = f->out_buf_len;
f->buf_idx = 0; f->out_buf_len = 0;
return flushed; return flushed;
} }
@@ -102,3 +195,8 @@ int __fio_error(struct __io_file *f)
{ {
return f->err != 0; return f->err != 0;
} }
int __fio_eof(struct __io_file *f)
{
return f->eof != 0;
}

View File

@@ -240,6 +240,8 @@ int __crt_init(mx_handle_t bootstrap)
dbg_log("calling main\n"); dbg_log("calling main\n");
int ret = main(msg->args_num, argv); int ret = main(msg->args_num, argv);
fflush(stdout);
fflush(stderr);
__crt_run_atexit(); __crt_run_atexit();
mio_fd_cleanup(); mio_fd_cleanup();
mio_fs_cleanup(); mio_fs_cleanup();