diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/toilet.c | 105 | 
1 files changed, 38 insertions, 67 deletions
diff --git a/src/toilet.c b/src/toilet.c index ff51ba8..de32003 100644 --- a/src/toilet.c +++ b/src/toilet.c @@ -1,11 +1,9 @@  #include <assert.h>  #include <ctype.h> -#include <errno.h>  #include <getopt.h>  #include <limits.h>  #include <pwd.h>  #include <stdbool.h> -#include <stdio.h>  #include <stdlib.h>  #include <string.h>  #include <sys/types.h> @@ -13,7 +11,7 @@  #include "util/debug.h"  #include "util/error.h" -#include "util/loop_args.h" +#include "util/loop_files.h"  #include "util/map.h"  #include "util/versie.h" @@ -21,8 +19,6 @@  static int modeMap; -#define BUF_SIZE 4096 -  static void usage(FILE *f) {    fprintf(f,        "Gebruik: toilet [-nchV] [BESTAND]...\n" @@ -77,91 +73,66 @@ static char** parse_options(int argc, char **argv, int *modeMap) {    return argv + optind;  } -static size_t count_lines(char *fname, FILE *f) { -  size_t nlines = 0; -  bool last_was_nl = false; - -  while (!feof(f)) { -    static char buf[BUF_SIZE]; -    const size_t n = fread(buf, 1, BUF_SIZE, f); - -    for (size_t i = 0; i < n; i++) { -      last_was_nl = false; -      if (buf[i] == '\n') { -        nlines++; -        last_was_nl = true; -      } -    } -  } +static size_t get_count(enum MODE mode, struct filebuf *fb) { +  switch (mode) { +    case M_BYTES: +      return fb->sz; -  if (!last_was_nl) nlines++; +    case M_WORDS: { +#define IN(i) (i < fb->sz) -  if (errno != 0) { -    printf("toilet: fout bij lezen uit bestand '%s'\n", fname); -    exit(1); -  } +      size_t words = 0; -  rewind(f); -  return nlines; -} - -static size_t count_words(FILE *f) { -  size_t nwords = 0; +      // (c) Tom Forging +      for (size_t i = 0; IN(i);) { +        size_t previ = i; +        while (IN(i) && !isspace(fb->buf[i])) i++; +        words += i != previ; +        while (IN(i) && isspace(fb->buf[i])) i++; +      } -  while (!feof(f)) { -    static char buf[BUF_SIZE]; -    const size_t n = fread(buf, 1, BUF_SIZE, f); +      return words; -    // (c) Tom Forging -    for (size_t i = 0; i<n;) { -      size_t previ = i; -      while (i<n && !isspace(buf[i])) i++; -      nwords += i != previ; -      while (i<n && isspace(buf[i])) i++; +#undef IN      } -  } -  rewind(f); -  return nwords; -} +    case M_LINES: { +      size_t lines = 0; +      size_t i = 0; -static size_t get_count(enum MODE mode, char *fname, FILE *f) { -  switch (mode) { -    case M_BYTES: { -      fseek(f, 0, SEEK_END); -      long offset = ftell(f); -      rewind(f); -      return offset; -    } +      while (i != fb->sz) { +        if (fb->buf[i] == '\n') lines++; +        i++; +      } -    case M_WORDS: -      return count_words(f); +      // handle case if file does not have trailing newline +      if (fb->buf[i - 1] != '\n') { +        lines++; +      } -    case M_LINES: -      return count_lines(fname, f); +      return lines; +    }      default:        assert(false);    }  } -static int process(char *fname, bool isstdin) { -  FILE *f = isstdin ? stdin : fopen(fname, "rb"); - +static int process(struct filebuf *fb, char *fname, bool) {    for (enum MODE mode = 1; mode <= M_BYTES; mode <<= 1) {      if (mode & modeMap) { -      const size_t count = get_count(mode, fname, f); +      const size_t count = get_count(mode, fb);        printf("%li ", count);      }    } - -  if (fname != NULL) printf("%s", fname); -  putchar('\n'); - -  if (!isstdin) fclose(f); +  printf("%s\n", fname); +  free_filebuf(fb);    return 0;  } +// TODO: be smarter, toilet doesn't have to read the whole file in memory (for +// unmappable files) +  int entry_toilet(int argc, char **argv) {    modeMap = 0;    char **args = parse_options(argc, argv, &modeMap); @@ -169,5 +140,5 @@ int entry_toilet(int argc, char **argv) {      modeMap = INT_MAX;    } -  return loop_args(args, process); +  return loop_files(args, process);  }  | 
