diff options
Diffstat (limited to 'hexdump_pretty.c')
-rw-r--r-- | hexdump_pretty.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/hexdump_pretty.c b/hexdump_pretty.c new file mode 100644 index 0000000..d082c0b --- /dev/null +++ b/hexdump_pretty.c @@ -0,0 +1,125 @@ +#include "hexdump_pretty.h" + +#include <assert.h> +#include <ctype.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define LINELEN 0x8 + +static struct segment line_segments[LINELEN]; +static size_t file_idx = 0; +static size_t line_idx = 0; +static size_t current_segment = 0; + + +enum color next_color(void) { + static uint8_t cc = 0; + cc += 1; + cc %= 6; + return cc + 1; +} + +void color_put(enum color c) { + printf("\x1b[0;3%im", c); +} + +void color_reset(void) { + printf("\x1b[m"); +} + +void cleanup_line(void) { + for (int i = 0; i < current_segment; i++) { + free(line_segments[i].data); + } +} + +void put_byte(uint8_t byte) { + static bool flip = 0; + printf("%02x", byte); + flip = !flip; + if (! flip) { + printf(" "); + } +} + +void flush_line() { + printf("%06lx: ", file_idx); + file_idx += LINELEN; + for (int i = 0; i < current_segment; i++) { + color_put(line_segments[i].c); + for (int b = 0; b < line_segments[i].len; b++) { + put_byte(line_segments[i].data[b]); + } + color_reset(); + } + for (int i = 0; i < current_segment; i++) { + color_put(line_segments[i].c); + for (int b = 0; b < line_segments[i].len; b++) { + uint8_t ch = line_segments[i].data[b]; + if (isprint(ch)) { + printf("%c", ch); + } else { + printf("."); + } + } + color_reset(); + } + printf("\n"); +} + +void add_segment(struct segment segment) { + line_segments[current_segment++] = segment; + line_idx += segment.len; + if (line_idx == LINELEN) { + flush_line(); + cleanup_line(); + current_segment = 0; + line_idx = 0; + } +} + +/* + * Buf MUST be a malloc:ed buffer, which is invalidated on this call. + */ +void write_chunk(uint8_t *buf, size_t len) { + if (line_idx + len >= LINELEN) { + enum color c = next_color(); + size_t len1 = LINELEN - line_idx, + len2 = len - len1; + uint8_t *buf1 = malloc(len1), + *buf2 = malloc(len2); + memcpy(buf1, buf, len1); + memcpy(buf2, buf + len1, len2); + free(buf); + struct segment + seg1 = { + .c = c, + .len = len1, + .data = buf1, + }, + seg2 = { + .c = c, + .len = len2, + .data = buf2, + }; + add_segment(seg1); + add_segment(seg2); + } else { + struct segment seg = { + .c = next_color(), + .len = len, + .data = buf, + }; + add_segment(seg); + } +} + +void write_chunk_s(uint8_t *buf, size_t len) { + assert (len >= 0); + uint8_t *true_buf = malloc(len); + memcpy(true_buf, buf, len); + write_chunk(true_buf, len); +} |