diff options
-rw-r--r-- | sort.c | 90 |
1 files changed, 86 insertions, 4 deletions
@@ -28,6 +28,7 @@ #include <locale.h> #include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> @@ -35,10 +36,16 @@ #define LINE_MAX _POSIX_LINE_MAX #endif +struct line { + FILE *file; + fpos_t pos; +}; + static int sort_check(const char *input, char sep, const char *key, unsigned int flags) { (void)sep; (void)key; + (void)flags; char prev[LINE_MAX] = ""; char cur[LINE_MAX] = ""; @@ -68,6 +75,78 @@ static int sort_check(const char *input, char sep, const char *key, unsigned int return 0; } +static void sort_add_pos(struct line **lines, size_t *nlines, FILE *f) +{ + struct line *tmp = realloc(*lines, (*nlines + 1) * sizeof(**lines)); + if (tmp == NULL) { + perror("sort"); + exit(1); + } + *lines = tmp; + (*lines)[*nlines].file = f; + fgetpos(f, &((*lines)[*nlines].pos)); +} + +static int sort_read(const char *path, struct line **lines, size_t *nlines) +{ + FILE *f = stdin; + if (strcmp(path, "-")) { + f = fopen(path, "r"); + } + if (f == NULL) { + fprintf(stderr, "sort: %s: %s\n", path, strerror(errno)); + return 1; + } + + char cur[LINE_MAX] = ""; + + sort_add_pos(lines, nlines, f); + while (fgets(cur, sizeof(cur), f) != NULL) { + } + + /* ignore EOF position */ + (*nlines)--; + + /* do *NOT* close f */ + return 0; +} + +static int sort_compar(const void *a, const void *b) +{ + const struct line *l1 = a; + const struct line *l2 = b; + char line1[LINE_MAX] = ""; + char line2[LINE_MAX] = ""; + + fsetpos(l1->file, &l1->pos); + fgets(line1, sizeof(line1), l1->file); + + fsetpos(l2->file, &l2->pos); + fgets(line2, sizeof(line2), l2->file); + + return strcoll(line1, line2); +} + +static int sort_sort(char *files[], int nfiles, char sep, const char *key, unsigned int flags) +{ + (void)sep; + (void)key; + (void)flags; + + struct line *lines = NULL; + size_t nlines = 0; + + for (int i = 0; i < nfiles; i++) { + if (sort_read(files[i], &lines, &nlines) != 0) { + return 1; + } + } + + qsort(lines, nlines, sizeof(*lines), sort_compar); + + return 0; +} + int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); @@ -124,9 +203,12 @@ int main(int argc, char *argv[]) return sort_check(argv[optind], separator, key, flags); } - /* add lines from all inputs */ - /* sort */ - /* print */ + #if 0 + if (mode == MERGE) { + /* optimize to assume sorted input */ + return sort_merge(argv + optind, argc - optind, separator, key, flags); + } + #endif - return 0; + return sort_sort(argv + optind, argc - optind, separator, key, flags); } |