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/ferror.c
|
||||||
src/libc/stdio/feof.c
|
src/libc/stdio/feof.c
|
||||||
src/libc/stdio/fflush.c
|
src/libc/stdio/fflush.c
|
||||||
|
src/libc/stdio/fgetc.c
|
||||||
src/libc/stdio/fgetpos.c
|
src/libc/stdio/fgetpos.c
|
||||||
|
src/libc/stdio/fgets.c
|
||||||
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
|
||||||
|
|
20
STATUS
20
STATUS
|
@ -119,16 +119,16 @@ TEST: Function/symbol/macro needs to be tested
|
||||||
(EXT) dprintf TEST
|
(EXT) dprintf TEST
|
||||||
(EXT) vdprintf TEST
|
(EXT) vdprintf TEST
|
||||||
|
|
||||||
7.19.7.1 fgetc TODO
|
7.19.7.1 fgetc -
|
||||||
7.19.7.2 fgets TODO
|
7.19.7.2 fgets -
|
||||||
7.19.7.3 fputc TEST
|
7.19.7.3 fputc -
|
||||||
7.19.7.4 fputs TEST
|
7.19.7.4 fputs -
|
||||||
7.19.7.5 getc LDEPS(fgetc)
|
7.19.7.5 getc -
|
||||||
7.19.7.6 getchar LDEPS(fgetc)
|
7.19.7.6 getchar LDEPS(stdin)
|
||||||
7.19.7.7 gets LDEPS(fgets)
|
7.19.7.7 gets LDEPS(stdin)
|
||||||
7.19.7.8 putc TEST
|
7.19.7.8 putc -
|
||||||
7.19.7.9 putchar TEST
|
7.19.7.9 putchar LDEPS(stdout)
|
||||||
7.19.7.10 puts TEST
|
7.19.7.10 puts LDEPS(stdout)
|
||||||
7.19.7.11 ungetc -
|
7.19.7.11 ungetc -
|
||||||
|
|
||||||
7.19.8.1 fread -
|
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 "fileutil.h"
|
||||||
#include <gint/defs/util.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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) {
|
while(read_size < request_size) {
|
||||||
int remaining = request_size - read_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 */
|
/* 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);
|
ssize_t rc = __fp_read(fp, data+read_size, remaining);
|
||||||
return read_size + (rc == EOF ? 0 : rc);
|
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)
|
if(read_size >= request_size)
|
||||||
break;
|
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 */
|
/* Get more data from the file descriptor into the buffer */
|
||||||
if(fp->buf) {
|
if(fp->buf) {
|
||||||
ssize_t rc = __fp_read(fp, fp->buf, fp->bufsize);
|
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;
|
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))
|
if(!fp->buf || __fp_hasbuf_write(fp))
|
||||||
return -1;
|
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)
|
if(read_size <= 0)
|
||||||
return 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);
|
memcpy(data, fp->buf + fp->bufpos, read_size);
|
||||||
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 */
|
/* Rewind the buffer if we read it fully */
|
||||||
if(fp->bufpos >= fp->bufread) {
|
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
|
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.
|
||||||
Allows reading from temporary ungetc() buffers and cleans them. */
|
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
|
/* Reads data from a file descriptor; updates the fdpos and sets the error
|
||||||
indicator. Returns 0 on success, EOF on error. */
|
indicator. Returns 0 on success, EOF on error. */
|
||||||
|
|
|
@ -15,8 +15,10 @@ int fputc(int c_int, FILE *fp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!fp->buf)
|
if(!fp->buf) {
|
||||||
return __fp_write(fp, &c, 1);
|
ssize_t rc = __fp_write(fp, &c, 1);
|
||||||
|
return (rc == 1) ? c : EOF;
|
||||||
|
}
|
||||||
|
|
||||||
__fp_buffer_mode_write(fp);
|
__fp_buffer_mode_write(fp);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue