mirror of
https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc.git
synced 2025-04-20 01:47:12 +02:00
stdio: fgetc(), fgets(), tests for fputc() and fputs() (DONE)
This commit is contained in:
parent
294fda9731
commit
ed873a652e
7 changed files with 108 additions and 19 deletions
|
@ -126,7 +126,9 @@ set(SOURCES
|
|||
src/libc/stdio/ferror.c
|
||||
src/libc/stdio/feof.c
|
||||
src/libc/stdio/fflush.c
|
||||
src/libc/stdio/fgetc.c
|
||||
src/libc/stdio/fgetpos.c
|
||||
src/libc/stdio/fgets.c
|
||||
src/libc/stdio/fileutil.c
|
||||
src/libc/stdio/fopen.c
|
||||
src/libc/stdio/fprintf.c
|
||||
|
|
20
STATUS
20
STATUS
|
@ -119,16 +119,16 @@ TEST: Function/symbol/macro needs to be tested
|
|||
(EXT) dprintf TEST
|
||||
(EXT) vdprintf TEST
|
||||
|
||||
7.19.7.1 fgetc TODO
|
||||
7.19.7.2 fgets TODO
|
||||
7.19.7.3 fputc TEST
|
||||
7.19.7.4 fputs TEST
|
||||
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 TEST
|
||||
7.19.7.9 putchar TEST
|
||||
7.19.7.10 puts TEST
|
||||
7.19.7.1 fgetc -
|
||||
7.19.7.2 fgets -
|
||||
7.19.7.3 fputc -
|
||||
7.19.7.4 fputs -
|
||||
7.19.7.5 getc -
|
||||
7.19.7.6 getchar LDEPS(stdin)
|
||||
7.19.7.7 gets LDEPS(stdin)
|
||||
7.19.7.8 putc -
|
||||
7.19.7.9 putchar LDEPS(stdout)
|
||||
7.19.7.10 puts LDEPS(stdout)
|
||||
7.19.7.11 ungetc -
|
||||
|
||||
7.19.8.1 fread -
|
||||
|
|
43
src/libc/stdio/fgetc.c
Normal file
43
src/libc/stdio/fgetc.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include <stdio.h>
|
||||
#include "fileutil.h"
|
||||
|
||||
int fgetc(FILE *fp)
|
||||
{
|
||||
if(!fp->readable) {
|
||||
fp->error = 1;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* For this function we inline __fp_fread2() and__fp_buffered_read() in
|
||||
order to maintain decent performance */
|
||||
unsigned char c;
|
||||
__fp_buffer_mode_read(fp);
|
||||
|
||||
/* No buffered data available, non-buffered mode */
|
||||
if(!fp->buf) {
|
||||
ssize_t rc = __fp_read(fp, &c, 1);
|
||||
return (rc == 1) ? c : EOF;
|
||||
}
|
||||
|
||||
/* If there is no data, get some */
|
||||
if(fp->bufpos >= fp->bufread) {
|
||||
ssize_t rc = __fp_read(fp, fp->buf, fp->bufsize);
|
||||
if(rc <= 0)
|
||||
return EOF;
|
||||
fp->bufread = rc;
|
||||
}
|
||||
|
||||
/* Get a byte from the buffer */
|
||||
c = fp->buf[fp->bufpos++];
|
||||
fp->bufungetc -= (fp->bufungetc > 0);
|
||||
|
||||
/* Rewind the buffer if at end, and clear _IONBF ungetc() buffers */
|
||||
if(fp->bufpos >= fp->bufread) {
|
||||
fp->bufread = 0;
|
||||
fp->bufpos = 0;
|
||||
if(fp->bufmode == _IONBF)
|
||||
__fp_remove_buffer(fp);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
11
src/libc/stdio/fgets.c
Normal file
11
src/libc/stdio/fgets.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <stdio.h>
|
||||
#include "fileutil.h"
|
||||
|
||||
char *fgets(char * restrict s, int n, FILE * restrict fp)
|
||||
{
|
||||
ssize_t read_size = __fp_fread2(fp, s, n - 1, '\n');
|
||||
if(read_size <= 0)
|
||||
return NULL;
|
||||
s[read_size] = 0;
|
||||
return s;
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
#include "fileutil.h"
|
||||
#include <gint/defs/util.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -98,10 +97,26 @@ ssize_t __fp_fread2(FILE *fp, void *data, size_t request_size, int stop_char)
|
|||
|
||||
while(read_size < request_size) {
|
||||
int remaining = request_size - read_size;
|
||||
int chunk = __fp_buffered_read(fp, data+read_size, remaining);
|
||||
int chunk = __fp_buffered_read(fp, data+read_size, remaining,
|
||||
stop_char);
|
||||
|
||||
/* Stream is not/no longer buffered, finish unbuffered */
|
||||
if(chunk < 0) {
|
||||
if(chunk < 0 && stop_char >= 0) {
|
||||
unsigned char c;
|
||||
|
||||
/* When there is a stop char, we can only read one
|
||||
byte at a time, which is reaaaally slow */
|
||||
for(int i = 0; i < remaining; i++) {
|
||||
ssize_t rc = __fp_read(fp, &c, 1);
|
||||
if(rc != 1)
|
||||
break;
|
||||
((char *)data)[read_size++] = c;
|
||||
if(c == stop_char)
|
||||
break;
|
||||
}
|
||||
return read_size;
|
||||
}
|
||||
else if(chunk < 0) {
|
||||
ssize_t rc = __fp_read(fp, data+read_size, remaining);
|
||||
return read_size + (rc == EOF ? 0 : rc);
|
||||
}
|
||||
|
@ -110,6 +125,11 @@ ssize_t __fp_fread2(FILE *fp, void *data, size_t request_size, int stop_char)
|
|||
if(read_size >= request_size)
|
||||
break;
|
||||
|
||||
/* If a stop char has been read, stop */
|
||||
if(stop_char >= 0 && read_size > 0 &&
|
||||
((char *)data)[read_size-1] == stop_char)
|
||||
break;
|
||||
|
||||
/* Get more data from the file descriptor into the buffer */
|
||||
if(fp->buf) {
|
||||
ssize_t rc = __fp_read(fp, fp->buf, fp->bufsize);
|
||||
|
@ -122,18 +142,29 @@ ssize_t __fp_fread2(FILE *fp, void *data, size_t request_size, int stop_char)
|
|||
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,
|
||||
int stop_char)
|
||||
{
|
||||
if(!fp->buf || __fp_hasbuf_write(fp))
|
||||
return -1;
|
||||
|
||||
int read_size = min((int)request_size, fp->bufread - fp->bufpos);
|
||||
int read_size = request_size;
|
||||
if(read_size > (int)(fp->bufread - fp->bufpos))
|
||||
read_size = fp->bufread - fp->bufpos;
|
||||
if(read_size <= 0)
|
||||
return 0;
|
||||
|
||||
if(stop_char >= 0) {
|
||||
char *end = memchr(fp->buf+fp->bufpos, stop_char, read_size);
|
||||
if(end != NULL)
|
||||
read_size = end - (fp->buf + fp->bufpos) + 1;
|
||||
}
|
||||
|
||||
memcpy(data, fp->buf + fp->bufpos, read_size);
|
||||
fp->bufpos += read_size;
|
||||
fp->bufungetc = max(fp->bufungetc - read_size, 0);
|
||||
fp->bufungetc = fp->bufungetc - read_size;
|
||||
if(fp->bufungetc < 0)
|
||||
fp->bufungetc = 0;
|
||||
|
||||
/* Rewind the buffer if we read it fully */
|
||||
if(fp->bufpos >= fp->bufread) {
|
||||
|
|
|
@ -43,7 +43,7 @@ ssize_t __fp_fread2(FILE *fp, void *data, size_t request_size, int stop_char);
|
|||
Returns amount of data read; if >= 0 but < size, the buffer should be
|
||||
refilled. Returns -1 to indicate that unbuffered access should be used.
|
||||
Allows reading from temporary ungetc() buffers and cleans them. */
|
||||
ssize_t __fp_buffered_read(FILE *fp, void *data, size_t size);
|
||||
ssize_t __fp_buffered_read(FILE *fp, void *data, size_t size, int stop_char);
|
||||
|
||||
/* Reads data from a file descriptor; updates the fdpos and sets the error
|
||||
indicator. Returns 0 on success, EOF on error. */
|
||||
|
|
|
@ -15,8 +15,10 @@ int fputc(int c_int, FILE *fp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if(!fp->buf)
|
||||
return __fp_write(fp, &c, 1);
|
||||
if(!fp->buf) {
|
||||
ssize_t rc = __fp_write(fp, &c, 1);
|
||||
return (rc == 1) ? c : EOF;
|
||||
}
|
||||
|
||||
__fp_buffer_mode_write(fp);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue