diff --git a/CMakeLists.txt b/CMakeLists.txt index ec2f1b2..7340d1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,6 +138,8 @@ set(SOURCES src/libc/stdio/getc.c src/libc/stdio/getchar.c src/libc/stdio/gets.c + src/libc/stdio/getline.c + src/libc/stdio/getdelim.c src/libc/stdio/perror.c src/libc/stdio/printf.c src/libc/stdio/printf/format_fixed.c diff --git a/include/stdio.h b/include/stdio.h index 7d56567..2a090bd 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -289,6 +289,12 @@ extern int getchar(void); /* (DEPRECATED; use fgets() instead) Read a string from stdin. */ extern char *gets(char *__s); +/*get a line from stream*/ +extern ssize_t getline(char **restrict __lineptr, size_t *restrict __n, FILE *restrict __fp); + +/*like getline but with 'delim' instead of \n*/ +extern ssize_t getdelim(char **restrict __lineptr, size_t *restrict __n, int __delim, FILE *restrict __fp); + extern int putc(int __c, FILE *__fp); #define putc fputc diff --git a/src/libc/stdio/getdelim.c b/src/libc/stdio/getdelim.c new file mode 100644 index 0000000..d2b5014 --- /dev/null +++ b/src/libc/stdio/getdelim.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include "fileutil.h" + +ssize_t getdelim(char **restrict lineptr, size_t *restrict n, int delim, FILE *restrict fp) +{ + ssize_t cur = 0; + char *new_lineptr = NULL; + size_t new_n; + + if(lineptr == NULL || n == NULL || fp == NULL) + { + errno=EINVAL; + return -1; + } + + if(*lineptr == NULL) + { + *n = 80; + *lineptr = (char *) malloc(*n); + if(*lineptr==NULL) return -1; + } + + do + { + ssize_t read_size = __fp_fread2(fp, *lineptr + cur, *n - cur - 1, delim); + if(read_size <= 0) return -1; + cur += read_size; + if((*lineptr)[cur - 1] != delim && !feof(fp)) + { + new_n = *n * 2; + new_lineptr = (char *) realloc(*lineptr, new_n); + if(new_lineptr == NULL) return -1; + *lineptr = new_lineptr; + *n = new_n; + } + }while((*lineptr)[cur-1] != delim && !feof(fp)); + + (*lineptr)[cur] = '\0'; + + if(feof(fp) && (*lineptr)[cur-1] != delim) + { + return -1; + }else{ + return cur; + } +} diff --git a/src/libc/stdio/getline.c b/src/libc/stdio/getline.c new file mode 100644 index 0000000..0862bf3 --- /dev/null +++ b/src/libc/stdio/getline.c @@ -0,0 +1,6 @@ +#include + +ssize_t getline(char **restrict lineptr, size_t *restrict n, FILE *restrict fp) +{ + return getdelim(lineptr, n, '\n', fp); +}