]> git.draconx.ca Git - liblbx.git/commitdiff
lbximg: Simplify pnm text output.
authorNick Bowler <nbowler@draconx.ca>
Tue, 21 Sep 2021 03:21:05 +0000 (23:21 -0400)
committerNick Bowler <nbowler@draconx.ca>
Tue, 21 Sep 2021 04:53:46 +0000 (00:53 -0400)
The ASCII output routine here is pointlessly complex, we are only
printing very short lines and a fixed length buffer will do just
fine.

Moreover, let's just optimize it out completely in the case where
the C character set is an ASCII superset and assertions are disabled.

src/pnm.c

index de9d2808c1311c25cd37ebe33c5b92c4bec4dff5..5359ac23518e6be165ea12e47d609eaca76bf69f 100644 (file)
--- a/src/pnm.c
+++ b/src/pnm.c
 #include "tools.h"
 #include "imgoutput.h"
 
+/* PNM formats are ASCII, check if C exec charset is too */
+#if '\a' == 0x07 && '\b' == 0x08 && '\t' == 0x09 && '\n' == 0x0a && \
+    '\v' == 0x0b && '\f' == 0x0c && '\r' == 0x0d && ' ' == 0x20 && \
+    '!' == 0x21 && '"' == 0x22 && '#' == 0x23 && '%' == 0x25 && \
+    '&' == 0x26 && '\'' == 0x27 && '(' == 0x28 && ')' == 0x29 && \
+    '*' == 0x2a && '+' == 0x2b && ',' == 0x2c && '-' == 0x2d && \
+    '.' == 0x2e && '/' == 0x2f && '0' == 0x30 && '1' == 0x31 && \
+    '2' == 0x32 && '3' == 0x33 && '4' == 0x34 && '5' == 0x35 && \
+    '6' == 0x36 && '7' == 0x37 && '8' == 0x38 && '9' == 0x39 && \
+    ':' == 0x3a && ';' == 0x3b && '<' == 0x3c && '=' == 0x3d && \
+    '>' == 0x3e && '?' == 0x3f && 'A' == 0x41 && 'B' == 0x42 && \
+    'C' == 0x43 && 'D' == 0x44 && 'E' == 0x45 && 'F' == 0x46 && \
+    'G' == 0x47 && 'H' == 0x48 && 'I' == 0x49 && 'J' == 0x4a && \
+    'K' == 0x4b && 'L' == 0x4c && 'M' == 0x4d && 'N' == 0x4e && \
+    'O' == 0x4f && 'P' == 0x50 && 'Q' == 0x51 && 'R' == 0x52 && \
+    'S' == 0x53 && 'T' == 0x54 && 'U' == 0x55 && 'V' == 0x56 && \
+    'W' == 0x57 && 'X' == 0x58 && 'Y' == 0x59 && 'Z' == 0x5a && \
+    '[' == 0x5b && '\\' == 0x5c && ']' == 0x5d && '^' == 0x5e && \
+    '_' == 0x5f && 'a' == 0x61 && 'b' == 0x62 && 'c' == 0x63 && \
+    'd' == 0x64 && 'e' == 0x65 && 'f' == 0x66 && 'g' == 0x67 && \
+    'h' == 0x68 && 'i' == 0x69 && 'j' == 0x6a && 'k' == 0x6b && \
+    'l' == 0x6c && 'm' == 0x6d && 'n' == 0x6e && 'o' == 0x6f && \
+    'p' == 0x70 && 'q' == 0x71 && 'r' == 0x72 && 's' == 0x73 && \
+    't' == 0x74 && 'u' == 0x75 && 'v' == 0x76 && 'w' == 0x77 && \
+    'x' == 0x78 && 'y' == 0x79 && 'z' == 0x7a && '{' == 0x7b && \
+    '|' == 0x7c && '}' == 0x7d && '~' == 0x7e
+#  define NATIVE_ASCII 1
+#else
+#  define NATIVE_ASCII 0
+#endif
+
 /* Convert c from the basic execution character set to ASCII. */
 static unsigned char to_ascii(unsigned char c)
 {
@@ -139,42 +170,32 @@ static unsigned char to_ascii(unsigned char c)
        return c;
 }
 
-/* Printf variant which converts all output to ASCII. */
+#if NATIVE_ASCII && defined(NDEBUG)
+/* fprintf can be used directly. */
+#define fprintf_ascii fprintf
+#else
+/* Variant of fprintf which converts all output to ASCII. */
 static int fprintf_ascii(FILE *f, char *fmt, ...)
 {
-       unsigned char *buf;
+       char buf[100];
        va_list ap;
-       int rc, len;
-       size_t ret;
+       int i, len;
 
        va_start(ap, fmt);
-       rc = vsnprintf(NULL, 0, fmt, ap);
+       len = vsnprintf(buf, sizeof buf, fmt, ap);
        va_end(ap);
 
-       if (rc < 0)
-               return -1;
-
-       assert(rc < (size_t)-1);
-       buf = malloc(rc+1u);
-       if (!buf)
+       if (len < 0 || len >= sizeof buf)
                return -1;
 
-       va_start(ap, fmt);
-       len = vsprintf((char *)buf, fmt, ap);
-       va_end(ap);
-
-       assert(rc == len);
-       for (int i = 0; i < len; i++) {
-               buf[i] = to_ascii(buf[i]);
+       for (i = 0; i < len; i++) {
+               if (fputc(to_ascii(buf[i]), f) == EOF)
+                       return -1;
        }
 
-       ret = fwrite(buf, 1, len, f);
-       free(buf);
-
-       if (ret < len)
-               return -(int)ret;
-       return ret;
+       return len;
 }
+#endif
 
 /*
  * Output filter for Netpbm's "plain" PBM format.  This is a bitmap format