diff options
| author | Lieuwe Rooijakkers <lieuwerooijakkers@gmail.com> | 2024-09-08 21:57:14 +0200 | 
|---|---|---|
| committer | Lieuwe Rooijakkers <lieuwerooijakkers@gmail.com> | 2024-09-08 21:57:19 +0200 | 
| commit | f11bd88153ca6ab57d9ebb58807f8771cbd40924 (patch) | |
| tree | a93687462190c7af232b1b49562e6a6d94e5921d | |
| parent | 43d5a40971b825cb78ce9ff56211c0c021109d07 (diff) | |
hus
| -rw-r--r-- | src/hus.c | 160 | 
1 files changed, 160 insertions, 0 deletions
| diff --git a/src/hus.c b/src/hus.c new file mode 100644 index 0000000..9604954 --- /dev/null +++ b/src/hus.c @@ -0,0 +1,160 @@ +#include <assert.h> +#include <errno.h> +#include <getopt.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/random.h> +#include <sys/types.h> +#include <unistd.h> + +#include "util/debug.h" +#include "util/error.h" +#include "util/versie.h" + +static char *shufrange = NULL; + +static char **lines = NULL; +static size_t nlines = 0; + +static void shuf_lines() { +  size_t *js = calloc(nlines, sizeof(size_t)); +  errno = 0; +  if (getrandom(js, nlines*sizeof(size_t), 0) == -1) exit(1); + +  for (ssize_t i = nlines - 1; i > 0; i--) { +    size_t j = js[i] % (nlines-1); + +    char *x = lines[i]; +    lines[i] = lines[j]; +    lines[j] = x; +  } + +  free(js); +} + +static void usage(FILE *f) { +  fprintf(f, +      "Gebruik: hus [-hV] [BESTAND]\n" +      "         hus -i LA-HO [-hV]\n" +      "\n" +      "Hussel de regels van het gegeven bestand.\n" +      "Als er geen bestand gegeven is, of bestand is -, hussel dan de regels op standaard invoer.\n" +      "\n" +      "  -i LA-HO    Genereer regels van laag naar hoog en hussel deze\n" +      "  -h          Toon deze hulptekst\n" +      "  -V          Toon versienummer\n"); +} + +static char** parse_options(int argc, char **argv) { +  int opt; +  while ((opt = getopt(argc, argv, "i:hV")) != -1) { +    switch (opt) { +      case 'i': +        shufrange = optarg; +        break; + +      case 'h': +        usage(stdout); +        exit(0); + +      case 'V': +        drukkedoos_print_versie(stdout); +        exit(0); + +      case '?': +        fprintf(stderr, "hus: Ongeldige optie: -%c\n", optopt); +        usage(stderr); +        exit(1); +    } +  } + +  return argv + optind; +} + +static int exec_shufrange() { +  assert(shufrange != NULL); +  char *seploc = NULL; + +  if ((seploc = strchr(shufrange, '-')) != NULL) { +    *seploc = '\0'; +    const long long start = strtoll(shufrange, NULL, 10); +    const long long end = strtoll(seploc+1, NULL, 10); + +    if (start > end) { +      fprintf(stderr, "hus: HO groter dan LA\n"); +      return 1; +    } + +    nlines = end - start + 1; +    lines = calloc(nlines, sizeof(char*)); +    for (long long i = 0; i <= start+end; i++) { +      long long n = i + start; +      asprintf(lines + i, "%lld", n); +    } +  } else { +    fprintf(stderr, "hus: geen LA en HO waarde opgegeven\n"); +    return 1; +  } + +  return 0; +} + +static int exec_shufstream(FILE *restrict stream) { +  size_t cap = 1 << 8; +  lines = malloc(sizeof(char*)*cap); + +  char *line = NULL; +  size_t linen = 0; + +  ssize_t nread = 0; +  while ((errno = 0, nread = getline(&line, &linen, stream)) != -1) { +    if (nread > 0 && line[nread-1] == '\n') line[--nread] = '\0'; + +    if (nlines == cap) { +      cap *= 2; +      lines = realloc(lines, sizeof(char*)*cap); +    } +    lines[nlines] = strdup(line); +    nlines++; +  } +  free(line); + +  return 0; +} + +int entry_hus(int argc, char **argv) { +  int res; +#define CHECK(f) if ((res = f) != 0) return res; + +  char **args = parse_options(argc, argv); + +  // count the amount of arguments provided +  size_t nargs; +  for (nargs = 0; args[nargs] != NULL; nargs++); + +  if (shufrange) { +    CHECK(exec_shufrange()); +  } else if (nargs == 0 || (nargs == 1 && strcmp(args[0], "-") == 0)) { +    CHECK(exec_shufstream(stdin)); +  } else if (nargs == 1) { +    FILE *stream = fopen(args[0], "r"); +    if (stream == NULL) { +      fprintf(stderr, "hus: %s: kon bestand niet openen\n", args[0]); +      return 1; +    } + +    CHECK(exec_shufstream(stream)); +    fclose(stream); +  } else { +    fprintf(stderr, "hus: teveel argumenten gegeven\n"); +    return 1; +  } + +  shuf_lines(); +  for (size_t i = 0; i < nlines; i++) { +    printf("%s\n", lines[i]); +  } + +  return 0; +} | 
