diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5e4e31a --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +.PHONY: examples + +examples: examples/example_cli.c + +examples/example_cli.c: + clang -Wall -g -Isrc -o examples/empack_cli src/empack.c examples/empack_cli.c diff --git a/examples/empack_cli.c b/examples/empack_cli.c index eef3c67..c78f8a9 100644 --- a/examples/empack_cli.c +++ b/examples/empack_cli.c @@ -6,6 +6,8 @@ #include "empack.h" + + #define USAGE \ "empack_cli [OPTIONS] \r\n" \ " file: File to read binary Msgpack data from, \"-\" for stdin\r\n" \ @@ -14,25 +16,121 @@ "OPTIONS\r\n" \ " -h/--help: Print this message\r\n" + + +static int +char_to_nibble(char c, uint8_t *nibble) +{ + if ((c >= '0') && (c <= '9')) { + (*nibble) = c - '0'; + } else if ((c >= 'a') && (c <= 'f')) { + (*nibble) = c - 'a' + 0x0a; + } else if ((c >= 'A') && (c <= 'F')) { + (*nibble) = c - 'A' + 0x0a; + } else { + return (-1); + } + + return (0); +} + static void print_func(const char *buf, uint32_t buflen, void *arg) { printf("%.*s", buflen, buf); } + + int main(int argc, char **argv) { - const uint8_t input[] = { 0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00 }; - size_t input_len = sizeof(input); empack_t empack; - uint8_t arena[256]; - uint32_t chars_printed; + uint8_t arena[0x4000]; + struct stat file_stat; + uint8_t *input = NULL; + size_t input_len = 0; + size_t input_bufsz = 0; + uint32_t chars_printed = 0; + + if (argc != 2) { + fprintf(stderr, USAGE); + return (-1); + } + + if ((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) { + printf(USAGE); + return (0); + } + + if (!strcmp(argv[1], "-")) { + /* read bytes from stdin */ + while (1) { + size_t read; + + input_bufsz += 1024; + input = realloc(input, input_bufsz); + + read = fread(&input[input_len], 1, input_bufsz, stdin); + if (read == 0) { + break; + } + + input_len += read; + } + } else if (stat(argv[1], &file_stat) == 0) { + /* read bytes from a file */ + FILE *fd = fopen(argv[1], "r"); + if (fd == NULL) { + fprintf(stderr, "Failed to open file \"%s\"\r\n", argv[1]); + return (-1); + } + + input_bufsz = file_stat.st_size; + input = malloc(input_bufsz); + input_len = fread(input, 1, input_bufsz, fd); + fclose(fd); + + if (input_len != input_bufsz) { + fprintf(stderr, "Failed to read file \"%s\"\r\n", argv[1]); + return (-1); + } + } else { + /* interpret argument as hex data */ + size_t arg_sz = strlen(argv[1]); + if ((arg_sz % 2) != 0) { + fprintf(stderr, "Invalid hex data - odd number of characters\r\n"); + return (-1); + } + + input_bufsz = arg_sz / 2; + input = malloc(input_bufsz); + if (input == NULL) { + fprintf(stderr, "Failed to allocate appropriate resources\r\n"); + return (-1); + } + + for (size_t i = 0; i < arg_sz; i += 2) { + uint8_t hi; + uint8_t lo; + + if (char_to_nibble(argv[1][i], &hi) || + char_to_nibble(argv[1][i+1], &lo)) { + fprintf(stderr, "Invalid hex byte at offset %u\r\n", (uint32_t)(i / 2)); + free(input); + return (-1); + } + + input[input_len] = (hi << 4) | lo; + input_len++; + } + } empack_init(&empack, arena, sizeof(arena)); if (empack_parse(&empack, input, input_len)) { fprintf(stderr, "Parsing error\r\n"); + free(input); return (-1); } @@ -46,5 +144,6 @@ main(int argc, char **argv) empack.arena_sz, (empack.arena_used * 100) / empack.arena_sz); + free(input); return (0); }