mirror of
https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc.git
synced 2024-12-29 13:03:38 +01:00
stdio: initial versions of fputc() and fputs() (TEST)
This commit is contained in:
parent
6ec0c24e2d
commit
f1512125d0
7 changed files with 99 additions and 46 deletions
|
@ -130,6 +130,8 @@ set(SOURCES
|
||||||
src/libc/stdio/fileutil.c
|
src/libc/stdio/fileutil.c
|
||||||
src/libc/stdio/fopen.c
|
src/libc/stdio/fopen.c
|
||||||
src/libc/stdio/fprintf.c
|
src/libc/stdio/fprintf.c
|
||||||
|
src/libc/stdio/fputc.c
|
||||||
|
src/libc/stdio/fputs.c
|
||||||
src/libc/stdio/fread.c
|
src/libc/stdio/fread.c
|
||||||
src/libc/stdio/freopen.c
|
src/libc/stdio/freopen.c
|
||||||
src/libc/stdio/fseek.c
|
src/libc/stdio/fseek.c
|
||||||
|
|
14
STATUS
14
STATUS
|
@ -95,8 +95,8 @@ TEST: Function/symbol/macro needs to be tested
|
||||||
7.19.5.1 fclose -
|
7.19.5.1 fclose -
|
||||||
7.19.5.2 fflush -
|
7.19.5.2 fflush -
|
||||||
7.19.5.3 fopen -
|
7.19.5.3 fopen -
|
||||||
(EXT) fdopen TEST
|
(EXT) fdopen -
|
||||||
7.19.5.4 freopen TEST (mode changes untested)
|
7.19.5.4 freopen -
|
||||||
7.19.5.5 setbuf -
|
7.19.5.5 setbuf -
|
||||||
7.19.5.6 setvbuf -
|
7.19.5.6 setvbuf -
|
||||||
|
|
||||||
|
@ -121,14 +121,14 @@ TEST: Function/symbol/macro needs to be tested
|
||||||
|
|
||||||
7.19.7.1 fgetc TODO
|
7.19.7.1 fgetc TODO
|
||||||
7.19.7.2 fgets TODO
|
7.19.7.2 fgets TODO
|
||||||
7.19.7.3 fputc TODO
|
7.19.7.3 fputc TEST
|
||||||
7.19.7.4 fputs TODO
|
7.19.7.4 fputs TEST
|
||||||
7.19.7.5 getc LDEPS(fgetc)
|
7.19.7.5 getc LDEPS(fgetc)
|
||||||
7.19.7.6 getchar LDEPS(fgetc)
|
7.19.7.6 getchar LDEPS(fgetc)
|
||||||
7.19.7.7 gets LDEPS(fgets)
|
7.19.7.7 gets LDEPS(fgets)
|
||||||
7.19.7.8 putc LDPES(fputc)
|
7.19.7.8 putc TEST
|
||||||
7.19.7.9 putchar LDEPS(fputc)
|
7.19.7.9 putchar TEST
|
||||||
7.19.7.10 puts LDEPS(fputs)
|
7.19.7.10 puts TEST
|
||||||
7.19.7.11 ungetc -
|
7.19.7.11 ungetc -
|
||||||
|
|
||||||
7.19.8.1 fread -
|
7.19.8.1 fread -
|
||||||
|
|
|
@ -79,6 +79,49 @@ void __fp_buffer_mode_write(FILE *fp)
|
||||||
fp->bufdir = __FILE_BUF_WRITE;
|
fp->bufdir = __FILE_BUF_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t __fp_fread2(FILE *fp, void *data, size_t request_size, int stop_char)
|
||||||
|
{
|
||||||
|
if(!fp->readable) {
|
||||||
|
fp->error = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the stream if unbuffered, we might have no buffer for the reads.
|
||||||
|
If it's buffered, we always have one. It's also possible that fp is
|
||||||
|
unbuffered (_IONBF) but has a buffer temporarily because ungetc()
|
||||||
|
has been used, in which case we have to transition from buffered
|
||||||
|
reads into direct reads midway. We use __fp_buffered_read() to
|
||||||
|
handle this. */
|
||||||
|
|
||||||
|
size_t read_size = 0;
|
||||||
|
__fp_buffer_mode_read(fp);
|
||||||
|
|
||||||
|
while(read_size < request_size) {
|
||||||
|
int remaining = request_size - read_size;
|
||||||
|
int chunk = __fp_buffered_read(fp, data+read_size, remaining);
|
||||||
|
|
||||||
|
/* Stream is not/no longer buffered, finish unbuffered */
|
||||||
|
if(chunk < 0) {
|
||||||
|
ssize_t rc = __fp_read(fp, data+read_size, remaining);
|
||||||
|
return read_size + (rc == EOF ? 0 : rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
read_size += chunk;
|
||||||
|
if(read_size >= request_size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Get more data from the file descriptor into the buffer */
|
||||||
|
if(fp->buf) {
|
||||||
|
ssize_t rc = __fp_read(fp, fp->buf, fp->bufsize);
|
||||||
|
if(rc <= 0) /* EOF or error */
|
||||||
|
break;
|
||||||
|
fp->bufread = rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return read_size;
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t __fp_buffered_read(FILE *fp, void *data, size_t request_size)
|
ssize_t __fp_buffered_read(FILE *fp, void *data, size_t request_size)
|
||||||
{
|
{
|
||||||
if(!fp->buf || __fp_hasbuf_write(fp))
|
if(!fp->buf || __fp_hasbuf_write(fp))
|
||||||
|
|
|
@ -35,6 +35,10 @@ void __fp_buffer_mode_read(FILE *fp);
|
||||||
/* Set writing mode on the buffer. */
|
/* Set writing mode on the buffer. */
|
||||||
void __fp_buffer_mode_write(FILE *fp);
|
void __fp_buffer_mode_write(FILE *fp);
|
||||||
|
|
||||||
|
/* fread() with an extra option to stop at a certain character (usually '\n');
|
||||||
|
set -1 to disable. */
|
||||||
|
ssize_t __fp_fread2(FILE *fp, void *data, size_t request_size, int stop_char);
|
||||||
|
|
||||||
/* Reads data from the buffer. Always reads as much as possible, up to size.
|
/* Reads data from the buffer. Always reads as much as possible, up to size.
|
||||||
Returns amount of data read; if >= 0 but < size, the buffer should be
|
Returns amount of data read; if >= 0 but < size, the buffer should be
|
||||||
refilled. Returns -1 to indicate that unbuffered access should be used.
|
refilled. Returns -1 to indicate that unbuffered access should be used.
|
||||||
|
|
32
src/libc/stdio/fputc.c
Normal file
32
src/libc/stdio/fputc.c
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "fileutil.h"
|
||||||
|
|
||||||
|
int fputc(int c_int, FILE *fp)
|
||||||
|
{
|
||||||
|
unsigned char c = c_int;
|
||||||
|
|
||||||
|
if(!fp->writable) {
|
||||||
|
fp->error = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(fp->append && fseek(fp, 0, SEEK_END) == EOF) {
|
||||||
|
fp->error = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!fp->buf)
|
||||||
|
return __fp_write(fp, &c, 1);
|
||||||
|
|
||||||
|
__fp_buffer_mode_write(fp);
|
||||||
|
|
||||||
|
if(fp->bufpos >= fp->bufsize)
|
||||||
|
fflush(fp);
|
||||||
|
|
||||||
|
fp->buf[fp->bufpos++] = c;
|
||||||
|
|
||||||
|
if(fp->bufmode == _IOLBF && c == '\n')
|
||||||
|
fflush(fp);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
9
src/libc/stdio/fputs.c
Normal file
9
src/libc/stdio/fputs.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int fputs(char const * restrict s, FILE * restrict fp)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
size_t written = fwrite(s, 1, len, fp);
|
||||||
|
return (written < len) ? EOF : 0;
|
||||||
|
}
|
|
@ -4,49 +4,12 @@
|
||||||
|
|
||||||
size_t fread(void *data, size_t membsize, size_t nmemb, FILE *fp)
|
size_t fread(void *data, size_t membsize, size_t nmemb, FILE *fp)
|
||||||
{
|
{
|
||||||
if(!fp->readable) {
|
|
||||||
fp->error = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t request_size;
|
size_t request_size;
|
||||||
if(__builtin_umul_overflow(membsize, nmemb, &request_size)) {
|
if(__builtin_umul_overflow(membsize, nmemb, &request_size)) {
|
||||||
fp->error = 1;
|
fp->error = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the stream if unbuffered, we might have no buffer for the reads.
|
ssize_t read_size = __fp_fread2(fp, data, request_size, -1);
|
||||||
If it's buffered, we always have one. It's also possible that fp is
|
return (read_size < 0) ? 0 : read_size;
|
||||||
unbuffered (_IONBF) but has a buffer temporarily because ungetc()
|
|
||||||
has been used, in which case we have to transition from buffered
|
|
||||||
reads into direct reads midway. We use __fp_buffered_read() to
|
|
||||||
handle this. */
|
|
||||||
|
|
||||||
size_t read_size = 0;
|
|
||||||
__fp_buffer_mode_read(fp);
|
|
||||||
|
|
||||||
while(read_size < request_size) {
|
|
||||||
int remaining = request_size - read_size;
|
|
||||||
int chunk = __fp_buffered_read(fp, data+read_size, remaining);
|
|
||||||
|
|
||||||
/* Stream is not/no longer buffered, finish unbuffered */
|
|
||||||
if(chunk < 0) {
|
|
||||||
ssize_t rc = __fp_read(fp, data+read_size, remaining);
|
|
||||||
return read_size + (rc == EOF ? 0 : rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
read_size += chunk;
|
|
||||||
if(read_size >= request_size)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Get more data from the file descriptor into the buffer */
|
|
||||||
if(fp->buf) {
|
|
||||||
ssize_t rc = __fp_read(fp, fp->buf, fp->bufsize);
|
|
||||||
if(rc <= 0) /* EOF or error */
|
|
||||||
break;
|
|
||||||
fp->bufread = rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return read_size;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue