diff options
Diffstat (limited to 'fuzz/text-fuzzer.c')
| -rw-r--r-- | fuzz/text-fuzzer.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/fuzz/text-fuzzer.c b/fuzz/text-fuzzer.c new file mode 100644 index 0000000..449e0dd --- /dev/null +++ b/fuzz/text-fuzzer.c @@ -0,0 +1,149 @@ +#include <stddef.h> +#include <stdbool.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include "fuzzer.h" +#include "text.h" +#include "text-util.h" +#include "util.h" + +#ifndef BUFSIZ +#define BUFSIZ 1024 +#endif + +typedef enum CmdStatus (*Cmd)(Text *txt, const char *cmd); + +static Mark mark = EMARK; + +static enum CmdStatus cmd_insert(Text *txt, const char *cmd) { + char data[BUFSIZ]; + size_t pos; + if (sscanf(cmd, "%zu %s\n", &pos, data) != 2) + return CMD_ERR; + size_t len = strlen(data); + return text_insert(txt, pos, data, len); +} + +static enum CmdStatus cmd_delete(Text *txt, const char *cmd) { + size_t pos, len; + if (sscanf(cmd, "%zu %zu", &pos, &len) != 2) + return CMD_ERR; + return text_delete(txt, pos, len); +} + +static enum CmdStatus cmd_size(Text *txt, const char *cmd) { + printf("%zu bytes\n", text_size(txt)); + return CMD_OK; +} + +static enum CmdStatus cmd_snapshot(Text *txt, const char *cmd) { + text_snapshot(txt); + return CMD_OK; +} + +static enum CmdStatus cmd_undo(Text *txt, const char *cmd) { + return text_undo(txt) != EPOS; +} + +static enum CmdStatus cmd_redo(Text *txt, const char *cmd) { + return text_redo(txt) != EPOS; +} + +static enum CmdStatus cmd_earlier(Text *txt, const char *cmd) { + return text_earlier(txt, 1) != EPOS; +} + +static enum CmdStatus cmd_later(Text *txt, const char *cmd) { + return text_later(txt, 1) != EPOS; +} + +static enum CmdStatus cmd_mark_set(Text *txt, const char *cmd) { + size_t pos; + if (sscanf(cmd, "%zu\n", &pos) != 1) + return CMD_ERR; + Mark m = text_mark_set(txt, pos); + if (m != EMARK) + mark = m; + return m != EMARK; +} + +static enum CmdStatus cmd_mark_get(Text *txt, const char *cmd) { + size_t pos = text_mark_get(txt, mark); + if (pos != EPOS) + printf("%zu\n", pos); + return pos != EPOS; +} + +static enum CmdStatus cmd_print(Text *txt, const char *cmd) { + size_t start = 0, size = text_size(txt), rem = size; + for (Iterator it = text_iterator_get(txt, start); + rem > 0 && text_iterator_valid(&it); + text_iterator_next(&it)) { + size_t prem = it.end - it.text; + if (prem > rem) + prem = rem; + if (fwrite(it.text, prem, 1, stdout) != 1) + return CMD_ERR; + rem -= prem; + } + if (rem != size) + puts(""); + return rem == 0; +} + +static enum CmdStatus cmd_quit(Text *txt, const char *cmd) { + return CMD_QUIT; +} + +static Cmd commands[] = { + ['-'] = cmd_earlier, + ['+'] = cmd_later, + ['?'] = cmd_mark_get, + ['='] = cmd_mark_set, + ['#'] = cmd_size, + ['d'] = cmd_delete, + ['i'] = cmd_insert, + ['p'] = cmd_print, + ['q'] = cmd_quit, + ['r'] = cmd_redo, + ['s'] = cmd_snapshot, + ['u'] = cmd_undo, +}; + +int main(int argc, char *argv[]) { + char line[BUFSIZ], *name = (argc == 1) ? NULL : argv[1]; + Text *txt = text_load(name); + if (!name) + name = "-"; + if (!txt) { + fprintf(stderr, "Failed to load text from `%s'\n", name); + return 1; + } + + printf("Loaded %zu bytes from `%s'\n", text_size(txt), name); + + for (;;) { + printf("> "); + if (!fgets(line, sizeof(line), stdin)) + break; + if (!isatty(0)) + printf("%s", line); + if (line[0] == '\n') + continue; + size_t idx = line[0]; + if (idx < LENGTH(commands) && commands[idx]) { + enum CmdStatus ret = commands[idx](txt, line+1); + printf("%s", cmd_status_msg[ret]); + if (ret == CMD_QUIT) + break; + } else { + puts("Invalid command"); + } + } + + text_free(txt); + + return 0; +} |
