cembed

convert files to C char arrays
git clone git://git.rr3.xyz/cembed
Log | Files | Refs | README | LICENSE

commit 5556aa64bbea0da9e3b46ec492a90c8f2225b446
parent b1fcd99ec975069313fc7bbee2fe56c0298e2586
Author: Robert Russell <robert@rr3.xyz>
Date:   Sat, 28 Dec 2024 13:54:32 -0800

Fix handling of binary data

Diffstat:
Mcembed.c | 43+++++++++++++++++++++++++++++--------------
1 file changed, 29 insertions(+), 14 deletions(-)

diff --git a/cembed.c b/cembed.c @@ -6,10 +6,9 @@ #define USAGE "usage: %s [-h|--help] NAME PATH\n" usize -format_char(char *buf, char c) { - // Escape specials - switch (c) { - case '\0': strcpy(buf, "\\0"); return 2; +format_char(char *buf, uchar curr, uchar next) { + // Escape specials. + switch (curr) { case '\a': strcpy(buf, "\\a"); return 2; case '\b': strcpy(buf, "\\b"); return 2; case '\t': strcpy(buf, "\\t"); return 2; @@ -22,20 +21,34 @@ format_char(char *buf, char c) { case '\\': strcpy(buf, "\\\\"); return 2; } - // Keep non-special printable ASCII as-is - if (' ' <= c && c <= '~') { - buf[0] = c; + // Keep non-special printable ASCII as-is. + if (' ' <= curr && curr <= '~') { + buf[0] = curr; buf[1] = '\0'; return 1; } - // Hex-encode rest + // Octal-encode rest. We can't hex-encode, because C hex encoding is + // variable length. + char octal[4] = { + "01234567"[(curr >> 6) & 0x3], + "01234567"[(curr >> 3) & 0x7], + "01234567"[(curr >> 0) & 0x7], + '\0', + }; buf[0] = '\\'; - buf[1] = 'x'; - buf[2] = "0123456789abcdef"[((uchar)c >> 0) & 0xf]; - buf[3] = "0123456789abcdef"[((uchar)c >> 4) & 0xf]; - buf[4] = '\0'; - return 4; + // We want the encoding to be as small as possible, but if the next + // character is an octal digit, than we must pad to 3 digits. + if (('0' <= next && next <= '7') || curr >= 64) { + strcpy(&buf[1], &octal[0]); + return 4; + } else if (curr >= 8) { + strcpy(&buf[1], &octal[1]); + return 3; + } else { + strcpy(&buf[1], &octal[2]); + return 2; + } } int @@ -73,7 +86,9 @@ main(int argc, char **argv) { } char buf[5]; - line_len += format_char(buf, data[i]); + uchar curr = data[i]; + uchar next = i + 1 < size ? data[i + 1] : '\0'; + line_len += format_char(buf, curr, next); fputs(buf, stdout); }