summaryrefslogtreecommitdiff
path: root/app/wlib/mswlib/getline/getline.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/wlib/mswlib/getline/getline.c')
-rw-r--r--app/wlib/mswlib/getline/getline.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/app/wlib/mswlib/getline/getline.c b/app/wlib/mswlib/getline/getline.c
new file mode 100644
index 0000000..202c7e2
--- /dev/null
+++ b/app/wlib/mswlib/getline/getline.c
@@ -0,0 +1,73 @@
+#include "getline.h"
+
+#include <stdlib.h>
+#include <errno.h>
+
+// MSVC specific implementation
+static void fseterr(FILE *fp)
+{
+ struct file { // Undocumented implementation detail
+ unsigned char *_ptr;
+ unsigned char *_base;
+ int _cnt;
+ int _flag;
+ int _file;
+ int _charbuf;
+ int _bufsiz;
+ };
+ #define _IOERR 0x10
+
+ ((struct file *)fp)->_flag |= _IOERR;
+}
+
+ssize_t getdelim(char **restrict lineptr, size_t *restrict n, int delim, FILE *restrict stream)
+{
+ if (lineptr == NULL || n == NULL || stream == NULL || (*lineptr == NULL && *n != 0)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (feof(stream) || ferror(stream)) {
+ return -1;
+ }
+
+ if (*lineptr == NULL) {
+ *n = 256;
+ *lineptr = malloc(*n);
+ if (*lineptr == NULL) {
+ fseterr(stream);
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ ssize_t nread = 0;
+ int c = EOF;
+ while (c != delim) {
+ c = fgetc(stream);
+ if (c == EOF) {
+ break;
+ }
+ if (nread >= (ssize_t)(*n - 1)) {
+ size_t newn = *n * 2;
+ char *newptr = realloc(*lineptr, newn);
+ if (newptr == NULL) {
+ fseterr(stream);
+ errno = ENOMEM;
+ return -1;
+ }
+ *lineptr = newptr;
+ *n = newn;
+ }
+ (*lineptr)[nread++] = c;
+ }
+ if (c == EOF && nread == 0) {
+ return -1;
+ }
+ (*lineptr)[nread] = 0;
+ return nread;
+}
+
+ssize_t getline(char **restrict lineptr, size_t *restrict n, FILE *restrict stream)
+{
+ return getdelim(lineptr, n, '\n', stream);
+}
+