diff options
Diffstat (limited to 'lib/fs.c')
-rw-r--r-- | lib/fs.c | 98 |
1 files changed, 98 insertions, 0 deletions
@@ -641,3 +641,101 @@ char *spm_mkdtemp(const char *base, const char *name, const char *extended_path) return 0; } + +char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn *readerFn) { + FILE *fp = NULL; + char **result = NULL; + char *buffer = NULL; + size_t lines = 0; + int use_stdin = 0; + + if (strcmp(filename, "-") == 0) { + use_stdin = 1; + } + + if (use_stdin) { + fp = stdin; + } else { + fp = fopen(filename, "r"); + } + + if (fp == NULL) { + perror(filename); + fprintf(SYSERROR); + return NULL; + } + + // Allocate buffer + if ((buffer = calloc(BUFSIZ, sizeof(char))) == NULL) { + perror("line buffer"); + fprintf(SYSERROR); + if (!use_stdin) { + fclose(fp); + } + return NULL; + } + + // count number the of lines in the file + while ((fgets(buffer, BUFSIZ - 1, fp)) != NULL) { + lines++; + } + + if (!lines) { + free(buffer); + if (!use_stdin) { + fclose(fp); + } + return NULL; + } + + rewind(fp); + + // Handle invalid start offset + if (start > lines) { + start = 0; + } + + // Adjust line count when start offset is non-zero + if (start != 0 && start < lines) { + lines -= start; + } + + + // Handle minimum and maximum limits + if (limit == 0 || limit > lines) { + limit = lines; + } + + // Populate results array + result = calloc(limit + 1, sizeof(char *)); + for (size_t i = start; i < limit; i++) { + if (i < start) { + continue; + } + + if (fgets(buffer, BUFSIZ - 1, fp) == NULL) { + break; + } + + if (readerFn != NULL) { + int status = readerFn(i - start, &buffer); + // A status greater than zero indicates we should ignore this line entirely and "continue" + // A status less than zero indicates we should "break" + // A zero status proceeds normally + if (status > 0) { + i--; + continue; + } else if (status < 0) { + break; + } + } + result[i] = strdup(buffer); + memset(buffer, '\0', BUFSIZ); + } + + free(buffer); + if (!use_stdin) { + fclose(fp); + } + return result; +}
\ No newline at end of file |