summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-01-29 01:49:01 +0100
committerLouis Burda <quent.burda@gmail.com>2023-01-29 01:49:01 +0100
commit6e3ea85cccec28f645a3678d38d8532e3dedac56 (patch)
tree313382d9f68dcab6daaba22c44047ce7f4cc6675
downloadhexdiff-6e3ea85cccec28f645a3678d38d8532e3dedac56.tar.gz
hexdiff-6e3ea85cccec28f645a3678d38d8532e3dedac56.zip
Initial version
-rw-r--r--.gitignore1
-rw-r--r--Makefile19
-rw-r--r--hexdiff.c113
3 files changed, 133 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ecc2344
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+hexdiff
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1a85bee
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,19 @@
+PREFIX ?= /usr/local
+BINDIR ?= /bin
+
+CFLAGS = -O2 -g
+
+all: hexdiff
+
+clean:
+ rm -f hexdiff
+
+hexdiff: hexdiff.c
+
+install:
+ install -m755 hexdiff -t "$(DESTDIR)$(PREFIX)$(BINDIR)"
+
+uninstall:
+ rm -f "$(DESTDIR)$(PREFIX)$(BINDIR)/hexdiff"
+
+.PHONY: all clean install uninstall
diff --git a/hexdiff.c b/hexdiff.c
new file mode 100644
index 0000000..1f34efc
--- /dev/null
+++ b/hexdiff.c
@@ -0,0 +1,113 @@
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+struct file {
+ const char *fname;
+ FILE *file;
+ uint8_t buf[16];
+ size_t buflen;
+};
+
+const int equal_gradient[256] = {
+ [0] = 241,
+ [1 ... 31] = 242,
+ [32 ... 63] = 244,
+ [64 ... 95] = 246,
+ [96 ... 127] = 247,
+ [128 ... 159] = 248,
+ [160 ... 191] = 250,
+ [192 ... 223] = 252,
+ [224 ... 254] = 254,
+ [255] = 255,
+};
+
+const int diff_gradient[256] = {
+ [0] = 52,
+ [1 ... 95] = 88,
+ [96 ... 159] = 124,
+ [160 ... 223] = 160,
+ [224 ... 255] = 196,
+};
+
+bool use_color;
+bool has_color;
+
+static inline void
+color_byte(uint8_t b1, uint8_t b2)
+{
+ if (b1 != b2)
+ printf("\x1b[38:5:%um", diff_gradient[b1]);
+ else
+ printf("\x1b[38:5:%um", equal_gradient[b1]);
+ has_color = true;
+}
+
+static inline void
+color_clear(void)
+{
+ printf("\x1b[0m");
+}
+
+int
+main(int argc, const char **argv)
+{
+ struct file f1, f2;
+ const char **arg;
+ size_t pos, i;
+
+ memset(&f1, 0, sizeof(f1));
+ memset(&f2, 0, sizeof(f2));
+
+ has_color = false;
+ use_color = true;
+ for (arg = &argv[1]; *arg; arg++) {
+ if (!strcmp(*arg, "-c")) {
+ use_color = true;
+ } else if (!strcmp(*arg, "-C")) {
+ use_color = false;
+ } else if (!f1.fname) {
+ f1.fname = *arg;
+ } else if (!f2.fname) {
+ f2.fname = *arg;
+ } else {
+ fprintf(stderr, "Usage: hexdiff [-c] FILE FILE\n");
+ return 1;
+ }
+ }
+
+ f1.file = fopen(f1.fname, "r");
+ if (!f1.file) err(1, "fopen %s", f1.fname);
+
+ f2.file = fopen(f2.fname, "r");
+ if (!f2.file) err(1, "fopen %s", f2.fname);
+
+ pos = 0;
+ while (!feof(f1.file) && !feof(f2.file)) {
+ f1.buflen = fread(f1.buf, 1, 16, f1.file);
+ f2.buflen = fread(f2.buf, 1, 16, f2.file);
+ if (!f1.buflen && !f2.buflen) break;
+
+ printf("%06lx: ", pos);
+ for (i = 0; i < 16; i++) {
+ if (use_color) color_byte(f1.buf[i], f2.buf[i]);
+ printf("%02x ", f1.buf[i]);
+ if (has_color) color_clear();
+ }
+ printf("| ");
+ for (i = 0; i < 16; i++) {
+ if (use_color) color_byte(f2.buf[i], f1.buf[i]);
+ printf("%02x ", f2.buf[i]);
+ if (has_color) color_clear();
+ }
+ printf("\n");
+
+ pos += 16;
+ }
+
+ fclose(f1.file);
+ fclose(f2.file);
+}