Implement general purpose CLI tool

This commit is contained in:
Aaron Cook 2025-09-21 20:01:38 -05:00
commit aef38e01f3
2 changed files with 109 additions and 4 deletions

View file

@ -6,6 +6,8 @@
#include "empack.h"
#define USAGE \
"empack_cli [OPTIONS] <file | msgpack hex>\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);
}