Implemented fgets() and enhanced IO buffering
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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
32
photon/libc/stdio/fgets.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
return -1;
|
/* TODO */
|
||||||
|
int fd = open(path, 0);
|
||||||
|
if (fd == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp->fd = fd;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __fio_fclose(struct __io_file *fp)
|
int __fio_fclose(struct __io_file *fp)
|
||||||
{
|
{
|
||||||
return -1;
|
if (fp->fd == -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)
|
||||||
{
|
{
|
||||||
return -1;
|
if (fd == -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user