zxdump/src/hexdump.c

110 lines
2.2 KiB
C
Raw Normal View History

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/stat.h>
#include <zx/charset.h>
#include <zx/hexdump.h>
static ssize_t hexdump_line(off_t offset, void *buf, size_t len, int tty, FILE *stream) {
size_t i;
if (printf("%08zx: ", offset) < 0) {
goto error_io;
}
for (i=0; i<len; i++) {
if (i > 0 && (i % ZX81_HEXDUMP_STRIDE_GROUP) == 0) {
if (fputc(' ', stream) < 0) {
goto error_io;
}
}
if (fprintf(stream, "%02x", ((uint8_t *)buf)[offset+i]) < 0) {
goto error_io;
}
}
if (fputs(" ", stream) < 0) {
goto error_io;
}
for (i=0; i<len; i++) {
uint8_t c = ((uint8_t *)buf)[offset+i];
if (c <= 0x3f) {
if (zx81_fputc(c, 0, stream) < 0) {
goto error_io;
}
} else if (c >= 0xa0 && c <= 0xbf) {
if (zx81_fputc(c - 0xa0, tty, stream) < 0) {
goto error_io;
}
} else {
if (fputc('.', stream) < 0) {
goto error_io;
}
}
}
if (fputc('\n', stream) < 0) {
goto error_io;
}
return fflush(stream);
error_io:
return -1;
}
ssize_t zx81_hexdump(int fd, FILE *stream) {
void *buf;
ssize_t total = 0;
int tty = isatty(fileno(stdout));
struct stat st;
if (fstat(fd, &st) < 0) {
goto error_fstat;
}
if ((buf = malloc(st.st_blksize)) == NULL) {
goto error_malloc;
}
while (1) {
ssize_t len, i;
off_t offset = 0;
if ((len = read(fd, buf, st.st_blksize)) < 0) {
goto error_read;
} else if (len == 0) {
break;
}
for (i=0; i<len; i+=ZX81_HEXDUMP_STRIDE_LINE) {
size_t left = len - i,
linesz = left < ZX81_HEXDUMP_STRIDE_LINE? left: ZX81_HEXDUMP_STRIDE_LINE;
if (hexdump_line(offset, buf, linesz, tty, stream) < 0) {
goto error_hexdump_line;
}
offset += linesz;
total += linesz;
}
}
free(buf);
return total;
error_hexdump_line:
error_read:
free(buf);
error_malloc:
error_fstat:
return -1;
}