stdio: basic fread/fwrite (WIP)

This commit is contained in:
Lephenixnoir 2022-01-05 21:25:41 +01:00
parent b6dbdf321d
commit 4461bdb96a
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
14 changed files with 222 additions and 33 deletions

View file

@ -130,10 +130,15 @@ set(SOURCES
src/libc/stdio/fileutil.c
src/libc/stdio/fopen.c
src/libc/stdio/fprintf.c
src/libc/stdio/fread.c
src/libc/stdio/freopen.c
src/libc/stdio/fseek.c
src/libc/stdio/fsetpos.c
src/libc/stdio/ftell.c
src/libc/stdio/fwrite.c
src/libc/stdio/getc.c
src/libc/stdio/getchar.c
src/libc/stdio/gets.c
src/libc/stdio/printf.c
src/libc/stdio/printf/format_fixed.c
src/libc/stdio/printf/format_fp.c
@ -141,6 +146,7 @@ set(SOURCES
src/libc/stdio/printf/print.c
src/libc/stdio/printf/util.c
src/libc/stdio/putc.c
src/libc/stdio/putchar.c
src/libc/stdio/puts.c
src/libc/stdio/remove.c
src/libc/stdio/rewind.c

16
STATUS
View file

@ -122,16 +122,16 @@ TEST: Function/symbol/macro needs to be tested
7.19.7.2 fgets TODO
7.19.7.3 fputc TODO
7.19.7.4 fputs TODO
7.19.7.5 getc TODO
7.19.7.6 getchar TODO
7.19.7.7 gets TODO
7.19.7.8 putc TODO
7.19.7.9 putchar TODO
7.19.7.10 puts TODO
7.19.7.5 getc LDEPS(fgetc)
7.19.7.6 getchar LDEPS(fgetc)
7.19.7.7 gets LDEPS(fgets)
7.19.7.8 putc LDPES(fputc)
7.19.7.9 putchar LDEPS(fputc)
7.19.7.10 puts LDEPS(fputs)
7.19.7.11 ungetc TODO
7.19.8.1 fread TODO
7.19.8.2 fwrite TODO
7.19.8.1 fread TEST
7.19.8.2 fwrite TEST
7.19.9.1 fgetpos TEST
7.19.9.2 fseek TEST

View file

@ -175,7 +175,60 @@ extern int vasprintf(char ** __restrict__ __str,
char const * __restrict__ __format, va_list __args);
/*
** File positioning functions;
** Character input/output functions.
*/
/* Read a character from a stream. */
extern int fgetc(FILE *__fp);
/* Read at most n characters from a stream, stopping after a newline. */
extern char *fgets(char * __restrict__ __s, int __n,
FILE * __restrict__ __fp);
/* Write a character to a stream. */
extern int fputc(int __c, FILE *__fp);
/* Write a string to a stream (excluding the NUL nyte). */
extern int fputs(char const * __restrict__ s, FILE * __restrict__ fp);
extern int getc(FILE *__fp);
#define getc fgetc
/* Get a character from stdin */
extern int getchar(void);
#define getchar() fgetc(stdin)
/* (DEPRECATED; use fgets() instead) Read a string from stdin. */
extern char *gets(char *__s);
extern int putc(int __c, FILE *__fp);
#define putc fputc
/* Write a character to stdout */
extern int putchar(int __c);
#define putchar(__c) fputc(__c, stdout)
/* Write a string to stdout, followed by a newline */
extern int puts(char const *__s);
/* Un-read a character back to the stream; only one ungetc() is guaranteed, and
the character is lost after reading, writing or flushing. */
extern int ungetc(int __c, FILE *__fp);
/*
** Direct input/output functions.
*/
/* Read an array of items from a stream. */
extern size_t fread(void * __restrict__ __ptr, size_t __size, size_t __nmemb,
FILE * __restrict__ __fp);
/* Write an array of items to a stream. */
extern size_t fwrite(void const * __restrict__ __ptr, size_t __size,
size_t __nmemb, FILE * __restrict__ __fp);
/*
** File positioning functions.
*/
/* Get current position (same as ftell() unless wide-oriented). */

View file

@ -14,7 +14,7 @@ int fflush(FILE *fp)
return 0;
/* In reading mode, reset the file offset */
if(fp->bufmode == __FILE_BUF_READ && fp->bufpos < fp->bufread) {
if(fp->bufdir == __FILE_BUF_READ && fp->bufpos < fp->bufread) {
fp->fdpos = fp->fdpos - fp->bufread + fp->bufpos;
lseek(fp->fd, fp->fdpos, SEEK_SET);
fp->bufpos = 0;
@ -23,7 +23,7 @@ int fflush(FILE *fp)
}
/* In writing mode, write pending data */
if(fp->bufmode == __FILE_BUF_WRITE && fp->bufpos > 0) {
if(fp->bufdir == __FILE_BUF_WRITE && fp->bufpos > 0) {
ssize_t written = __fp_write(fp, fp->buf, fp->bufpos);
fp->bufpos = 0;
return (written == (ssize_t)fp->bufpos ? 0 : EOF);

View file

@ -1,6 +1,7 @@
#include "fileutil.h"
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int __fp_open(FILE *fp, int fd, bool use_buffering)
@ -28,6 +29,23 @@ void __fp_close(FILE *fp, bool free_fp)
free(fp);
}
void __fp_buffer_mode_read(FILE *fp)
{
if(fp->buf && fp->bufdir == __FILE_BUF_WRITE && fp->bufpos > 0) {
fflush(fp);
fp->bufdir = __FILE_BUF_READ;
}
}
void __fp_buffer_mode_write(FILE *fp)
{
if(fp->buf && fp->bufdir == __FILE_BUF_READ
&& fp->bufpos < fp->bufread) {
fflush(fp);
fp->bufdir = __FILE_BUF_WRITE;
}
}
ssize_t __fp_read(FILE *fp, void *data, size_t size)
{
size_t read_ = 0;
@ -39,8 +57,10 @@ ssize_t __fp_read(FILE *fp, void *data, size_t size)
fp->error = 1;
return EOF;
}
if(rc == 0)
if(rc == 0) {
fp->eof = 1;
break;
}
fp->fdpos += rc;
}

View file

@ -15,6 +15,12 @@ int __fp_open(FILE *fp, int fd, bool use_buffering);
/* Close fp and free all of its resources. */
void __fp_close(FILE *fp, bool free_fp);
/* Set reading mode on the buffer. */
void __fp_buffer_mode_read(FILE *fp);
/* Set writing mode on the buffer. */
void __fp_buffer_mode_write(FILE *fp);
/* Reads data from a file descriptor; updates the fdpos and sets the error
indicator. Returns 0 on success, EOF on error. */
ssize_t __fp_read(FILE *fp, void *data, size_t size);

45
src/libc/stdio/fread.c Normal file
View file

@ -0,0 +1,45 @@
#include <stdio.h>
#include <string.h>
#include "fileutil.h"
size_t fread(void *data, size_t membsize, size_t nmemb, FILE *fp)
{
size_t size;
if(__builtin_umul_overflow(membsize, nmemb, &size)) {
fp->error = 1;
return 0;
}
if(!fp->buf) {
ssize_t rc = __fp_read(fp, data, size);
return (rc == EOF) ? 0 : rc;
}
__fp_buffer_mode_read(fp);
size_t size_read = 0;
while(size_read < size) {
/* Take what's available in the buffer (may be 0) */
size_t size_frag = fp->bufread - fp->bufpos;
if(size_frag > size - size_read)
size_frag = size - size_read;
memcpy(data + size_read, fp->buf + fp->bufpos, size_frag);
size_read += size_frag;
fp->bufpos += size_frag;
if(fp->bufpos >= fp->bufread) {
fp->bufread = 0;
fp->bufpos = 0;
}
if(size_read >= size)
break;
/* Get more data */
ssize_t rc = __fp_read(fp, fp->buf, fp->bufsize);
if(rc <= 0) /* EOF or error */
break;
fp->bufread = rc;
}
return size_read;
}

42
src/libc/stdio/fwrite.c Normal file
View file

@ -0,0 +1,42 @@
#include <stdio.h>
#include <string.h>
#include "fileutil.h"
size_t fwrite(void const *data, size_t membsize, size_t nmemb, FILE *fp)
{
size_t size;
if(__builtin_umul_overflow(membsize, nmemb, &size)) {
fp->error = 1;
return 0;
}
if(!fp->buf) {
ssize_t rc = __fp_write(fp, data, size);
return (rc == EOF) ? 0 : rc;
}
__fp_buffer_mode_write(fp);
// TODO: fwrite: line buffering
size_t size_written = 0;
while(size_written < size) {
/* Fill the buffer */
size_t size_frag = fp->bufsize - fp->bufpos;
if(size_frag > size - size_written)
size_frag = size - size_written;
memcpy(fp->buf + fp->bufpos, data + size_written, size_frag);
size_written += size_frag;
fp->bufpos += size_frag;
if(fp->bufpos >= fp->bufsize) {
ssize_t rc = __fp_write(fp, fp->buf, fp->bufpos);
if(rc <= 0) /* error */
break;
fp->bufpos = 0;
}
}
return size_written;
}

7
src/libc/stdio/getc.c Normal file
View file

@ -0,0 +1,7 @@
#include <stdio.h>
#undef getc
int getc(FILE *fp)
{
return fgetc(fp);
}

7
src/libc/stdio/getchar.c Normal file
View file

@ -0,0 +1,7 @@
#include <stdio.h>
#undef getchar
int getchar(void)
{
return fgetc(stdin);
}

7
src/libc/stdio/gets.c Normal file
View file

@ -0,0 +1,7 @@
#include <stdio.h>
#include <limits.h>
extern char *gets(char *s)
{
return fgets(s, INT_MAX, stdin);
}

View file

@ -1,11 +1,7 @@
#include <stdio.h>
#include <unistd.h>
#undef putc
int putchar(int c)
int putc(int c, FILE *fp)
{
char n;
n = (char)c;
write(STDOUT_FILENO, &n, 1);
return (n);
return fputc(c, fp);
}

7
src/libc/stdio/putchar.c Normal file
View file

@ -0,0 +1,7 @@
#include <stdio.h>
#undef putchar
int putchar(int c)
{
return fputc(c, stdout);
}

View file

@ -1,18 +1,11 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/*
** puts() writes the string s and a trailing newline to stdout.
** FIXME: check last write error !
*/
int puts(const char *s)
int puts(char const *s)
{
size_t size;
size_t n;
size = strlen(s);
n = write(STDOUT_FILENO, s, size);
write(STDOUT_FILENO, "\n", 1);
return (-(n == size));
int rc = 0;
if(fputs(s, stdout) != 0)
rc = -1;
if(fputc('\n', stdout) == EOF)
rc = -1;
return rc;
}