From b76c50a91b29048d9c27711898f5cc4acf4e61c2 Mon Sep 17 00:00:00 2001
From: Eric <eric@wolf42.net>
Date: Tue, 27 May 2025 15:14:55 +0200
Subject: [PATCH 1/9] change header macro names to be more idiomatic

---
 encode.h | 4 ++--
 input.h  | 4 ++--
 output.h | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/encode.h b/encode.h
index 2ea285a..425038c 100644
--- a/encode.h
+++ b/encode.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_ENCODE
-#define HEADER_ENCODE
+#ifndef ENCODE_H
+#define ENCODE_H
 
 int
 encode(unsigned char *op, int olen, unsigned char *sp, int url);
diff --git a/input.h b/input.h
index 42bd4a6..d859cbd 100644
--- a/input.h
+++ b/input.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_INPUT
-#define HEADER_INPUT
+#ifndef INPUT_H
+#define INPUT_H
 
 #include <stdio.h>
 
diff --git a/output.h b/output.h
index 8135e20..85736f2 100644
--- a/output.h
+++ b/output.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_OUTPUT
-#define HEADER_OUTPUT
+#ifndef OUTPUT_H
+#define OUTPUT_H
 
 #include <stdio.h>
 

From fa5095133ab4187c7846c9c1115dfab43d6b36de Mon Sep 17 00:00:00 2001
From: Eric <eric@wolf42.net>
Date: Tue, 27 May 2025 18:37:48 +0200
Subject: [PATCH 2/9] remove buffer size dependency from input functions

This should've been part of 848c37, when buffers were unwired from input
functions. Now buffer size is also no longer supplied in function calls
but assumed. It is up to the caller to provide appropriately sized
buffers.
---
 input.c | 14 ++++++++------
 input.h |  4 ++--
 main.c  | 12 ++++++------
 3 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/input.c b/input.c
index cfe80b1..517522b 100644
--- a/input.c
+++ b/input.c
@@ -1,29 +1,31 @@
 #include "input.h"
 
-#define PADDING '='
+#define PADDING  '='
+#define OCTETBUF  3
+#define SXTETBUF  4
 
 int
-getocts(FILE *fp, unsigned char *o, int olen)
+getocts(FILE *fp, unsigned char *o)
 {
     int c, n;
 
     n = 0;
-    while (n < olen-1 && (c = fgetc(fp)) != EOF)
+    while (n < OCTETBUF && (c = fgetc(fp)) != EOF)
         o[n++] = c;
 
     return n;
 }
 
 int
-getsxts(FILE *fp, unsigned char *s, int slen)
+getsxts(FILE *fp, unsigned char *s)
 {
     int c, n, pad;
 
     n = pad = 0;
-    while (n < slen-1 && (c = fgetc(fp)) != EOF && c != PADDING)
+    while (n < SXTETBUF && (c = fgetc(fp)) != EOF && c != PADDING)
         if (c != '\n')
             s[n++] = c;
-    while (n+pad < slen-1)
+    while (n+pad < SXTETBUF)
         s[n+pad++] = PADDING;
 
     return n;
diff --git a/input.h b/input.h
index d859cbd..2238695 100644
--- a/input.h
+++ b/input.h
@@ -4,9 +4,9 @@
 #include <stdio.h>
 
 int
-getocts(FILE *fp, unsigned char *o, int olen);
+getocts(FILE *fp, unsigned char *o);
 
 int
-getsxts(FILE *fp, unsigned char *s, int slen);
+getsxts(FILE *fp, unsigned char *s);
 
 #endif
diff --git a/main.c b/main.c
index 0cf51bc..c2017bf 100644
--- a/main.c
+++ b/main.c
@@ -4,11 +4,11 @@
 #include "output.h"
 #include "encode.h"
 
-#define OBUFSIZE 4
-#define SBUFSIZE 5
+#define OCTETBUF 4
+#define SXTETBUF 5
 
-unsigned char obuf[OBUFSIZE];
-unsigned char sbuf[SBUFSIZE];
+unsigned char obuf[OCTETBUF];
+unsigned char sbuf[SXTETBUF];
 
 int
 main(int argc, char *argv[])
@@ -51,12 +51,12 @@ main(int argc, char *argv[])
             exit(EXIT_FAILURE);
         }
         if (dec) {
-            while ((n = getsxts((argc >= 1) ? in : stdin, sbuf, SBUFSIZE))) {
+            while ((n = getsxts((argc >= 1) ? in : stdin, sbuf))) {
                 n = decode(sbuf, n, obuf, url);
                 fwrite(obuf, sizeof(*obuf), n, (argc == 2) ? out : stdout);
             }
         } else {
-            while ((n = getocts((argc >= 1) ? in : stdin, obuf, OBUFSIZE))) {
+            while ((n = getocts((argc >= 1) ? in : stdin, obuf))) {
                 if (wrp) {
                     n = encode(obuf, n, sbuf, url);
                     l = printw((argc == 2) ? out : stdout, sbuf, n);

From 733a013ee75f43c4fe4a317a7806981f4e6dd8a1 Mon Sep 17 00:00:00 2001
From: Eric <eric@wolf42.net>
Date: Wed, 28 May 2025 17:31:07 +0200
Subject: [PATCH 3/9] remove bugs related to uninitialized variables

These bugs became visible when using optimization options. They were
either not present unoptimized or very unlikely to occur. However, given
the options, the resulting program would behave incorrectly and reliably
break under all circumstances.

The makefile will see the intended changes accordingly in the following
commit to ensure compatibility.
---
 main.c   | 31 +++++++++++++++++--------------
 output.c |  1 +
 2 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/main.c b/main.c
index c2017bf..44b9a71 100644
--- a/main.c
+++ b/main.c
@@ -13,11 +13,12 @@ unsigned char sbuf[SXTETBUF];
 int
 main(int argc, char *argv[])
 {
-    int c, n, l;
+    int c, n, last;
     int dec, url, hlp, wrp;
-    char *prog = *argv;
     FILE *in, *out;
+    char *prog;
 
+    prog = *argv;
     dec = url = hlp = wrp = 0;
     while (--argc > 0 && (*++argv)[0] == '-')
         while ((c = *++argv[0]))
@@ -42,6 +43,7 @@ main(int argc, char *argv[])
     if (hlp) {
         fprintf(stdout, "Usage: %s -duhw infile outfile\n", prog);
     } else {
+        in = out = NULL;
         if (argc >= 1 && (in = fopen(*argv, "r")) == NULL) {
             fprintf(stderr, "%s: can't open %s\n", prog, *argv);
             exit(EXIT_FAILURE);
@@ -51,22 +53,23 @@ main(int argc, char *argv[])
             exit(EXIT_FAILURE);
         }
         if (dec) {
-            while ((n = getsxts((argc >= 1) ? in : stdin, sbuf))) {
+            while ((n = getsxts((in) ? in : stdin, sbuf))) {
                 n = decode(sbuf, n, obuf, url);
-                fwrite(obuf, sizeof(*obuf), n, (argc == 2) ? out : stdout);
+                fwrite(obuf, sizeof(*obuf), n, (out) ? out : stdout);
             }
+        } else if (wrp) {
+            last = 0;
+            while ((n = getocts((in) ? in : stdin, obuf))) {
+                n = encode(obuf, n, sbuf, url);
+                last = printw((out) ? out : stdout, sbuf, n);
+            }
+            if (last != '\n')
+                fprintf((out) ? out : stdout, "\n");
         } else {
-            while ((n = getocts((argc >= 1) ? in : stdin, obuf))) {
-                if (wrp) {
-                    n = encode(obuf, n, sbuf, url);
-                    l = printw((argc == 2) ? out : stdout, sbuf, n);
-                } else {
-                    encode(obuf, n, sbuf, url);
-                    fprintf((argc == 2) ? out : stdout, "%s", sbuf);
-                }
+            while ((n = getocts((in) ? in : stdin, obuf))) {
+                encode(obuf, n, sbuf, url);
+                fprintf((out) ? out : stdout, "%s", sbuf);
             }
-            if (wrp && l != '\n')
-                fprintf((argc == 2) ? out : stdout, "\n");
         }
         if (in)
             fclose(in);
diff --git a/output.c b/output.c
index d5c1a3a..b48713e 100644
--- a/output.c
+++ b/output.c
@@ -8,6 +8,7 @@ printw(FILE *fp, unsigned char *s, int slen)
     static int col;
     int c;
 
+    c = '\n';
     while (slen--) {
         fputc((c = *s++), fp);
         ++col;

From 4e8bb86ddd7c38b8248c1b19e66d058405cfc974 Mon Sep 17 00:00:00 2001
From: Eric <eric@wolf42.net>
Date: Wed, 28 May 2025 17:55:13 +0200
Subject: [PATCH 4/9] change Makefile to be stricter

-Og enables better detection of bugs that would only occur in optimized
compilations and allows for slightly lesser than -O1 optimization that
does not interfere with debugging.
---
 Makefile | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index ff2a3f4..b66cfcc 100644
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,14 @@
-CFLAGS = -g -Wall -Wextra -Werror
+CC = gcc
+CFLAGS = -Og -Wall -Wextra -Werror
 
 objects = main.o input.o output.o encode.o
 
 b64 : $(objects)
-	cc -o b64 $(objects)
+	$(CC) -o b64 $(objects)
 
 main.o input.o : input.h
-main.o output.o : output.h
 main.o encode.o : encode.h
+main.o output.o : output.h
 
 .PHONY : clean
 clean :

From 3194981825cce26cdc54207ec4948087397cdeb0 Mon Sep 17 00:00:00 2001
From: Eric <eric@wolf42.net>
Date: Wed, 28 May 2025 20:33:16 +0200
Subject: [PATCH 5/9] repair Makefile to include -g in CFLAGS again

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index b66cfcc..e6f82d7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 CC = gcc
-CFLAGS = -Og -Wall -Wextra -Werror
+CFLAGS = -Og -g -Wall -Wextra -Werror
 
 objects = main.o input.o output.o encode.o
 

From f0577d8ea0d2735195471a446fc8e08bd00ac9b2 Mon Sep 17 00:00:00 2001
From: Eric <eric@wolf42.net>
Date: Wed, 28 May 2025 23:24:05 +0200
Subject: [PATCH 6/9] decrease encode time

The functions encode and decode are now capable of processing larger
buffers with less conditional logic. Input and output functions need to
follow suit to make better use of this next. Encode without line
wrapping already makes use of these improvements, because input and
output are now entirely handled by <stdio.h> functions.
---
 encode.c | 101 ++++++++++++++++++++++++++++---------------------------
 input.c  |  13 -------
 input.h  |   3 --
 main.c   |  12 +++----
 4 files changed, 58 insertions(+), 71 deletions(-)

diff --git a/encode.c b/encode.c
index cee611f..861bae9 100644
--- a/encode.c
+++ b/encode.c
@@ -7,80 +7,83 @@ unsigned char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
                       "0123456789" \
                       "+/";
 
-unsigned char b64u[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
-                       "abcdefghijklmnopqrstuvwxyz" \
-                       "0123456789" \
-                       "-_";
+unsigned char b64url[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+                         "abcdefghijklmnopqrstuvwxyz" \
+                         "0123456789" \
+                         "-_";
 
 int
 encode(unsigned char *op, int olen, unsigned char *sp, int url)
 {
-    int n;
-    unsigned char *sb, *enc;
+    int tmp;
+    unsigned char *table;
+    unsigned char *sbeg;
+    unsigned char *tend;
 
-    sb = sp;
-    enc = (!url) ? b64 : b64u;
-    switch (olen) {
-        case 3:
-            *sp++ = enc[(*op & ~3) >> 2];
-            n = (*op++ & 3) << 4;
-            *sp++ = enc[n + ((*op & ~15) >> 4)];
-            n = (*op++ & 15) << 2;
-            *sp++ = enc[n + ((*op & 192) >> 6)];
-            *sp = enc[*op & ~192];
-            break;
+    table = (!url) ? b64 : b64url;
+
+    sbeg = sp;
+    tend = op + olen - (olen % 3);
+    while (op < tend) {
+        *sp++ = table[(*op & ~3) >> 2];
+        tmp = (*op++ & 3) << 4;
+        *sp++ = table[tmp + ((*op & ~15) >> 4)];
+        tmp = (*op++ & 15) << 2;
+        *sp++ = table[tmp + ((*op & 192) >> 6)];
+        *sp++ = table[*op++ & ~192];
+    }
+    switch (olen % 3) {
         case 2:
-            *sp++ = enc[(*op & ~3) >> 2];
-            n = (*op++ & 3) << 4;
-            *sp++ = enc[n + ((*op & ~15) >> 4)];
-            *sp++ = enc[(*op & 15) << 2];
-            *sp = PADDING;
+            *sp++ = table[(*op & ~3) >> 2];
+            tmp = (*op++ & 3) << 4;
+            *sp++ = table[tmp + ((*op & ~15) >> 4)];
+            *sp++ = table[(*op & 15) << 2];
+            *sp++ = PADDING;
             break;
         case 1:
-            *sp++ = enc[(*op & ~3) >> 2];
-            *sp++ = enc[(*op & 3) << 4];
+            *sp++ = table[(*op & ~3) >> 2];
+            *sp++ = table[(*op & 3) << 4];
+            *sp++ = PADDING;
             *sp++ = PADDING;
-            *sp = PADDING;
             break;
     }
 
-    return sp-sb+1;
+    return sp-sbeg;
 }
 
 int
 decode(unsigned char *sp, int slen, unsigned char *op, int url)
 {
-    int n, b, atob(int c, int url);
-    unsigned char *ob;
+    int tmp, b, atob(int c, int url);
+    unsigned char *obeg;
+    unsigned char *qend;
 
-    ob = op;
-    switch (slen) {
-        case 4:
-            n = atob(*sp++, url) << 2;
-            b = atob(*sp++, url);
-            *op++ = n + ((b & ~15) >> 4);
-
-            n = (b & 15) << 4;
-            b = atob(*sp++, url);
-            *op++ = n + ((b & ~3) >> 2);
-
-            *op = ((b & 3) << 6) + atob(*sp, url);
-            break;
+    obeg = op;
+    qend = sp + slen - (slen % 4);
+    while (sp < qend) {
+        tmp = atob(*sp++, url) << 2;
+        b = atob(*sp++, url);
+        *op++ = tmp + ((b & ~15) >> 4);
+        tmp = (b & 15) << 4;
+        b = atob(*sp++, url);
+        *op++ = tmp + ((b & ~3) >> 2);
+        *op++ = ((b & 3) << 6) + atob(*sp++, url);
+    }
+    switch (slen % 4) {
         case 3:
-            n = atob(*sp++, url) << 2;
+            tmp = atob(*sp++, url) << 2;
             b = atob(*sp++, url);
-            *op++ = n + ((b & ~15) >> 4);
-
-            n = (b & 15) << 4;
-            *op = n + ((atob(*sp, url) & ~3) >> 2);
+            *op++ = tmp + ((b & ~15) >> 4);
+            tmp = (b & 15) << 4;
+            *op++ = tmp + ((atob(*sp++, url) & ~3) >> 2);
             break;
         case 2:
-            n = atob(*sp++, url) << 2;
-            *op = n + ((atob(*sp, url) & ~15) >> 4);
+            tmp = atob(*sp++, url) << 2;
+            *op++ = tmp + ((atob(*sp++, url) & ~15) >> 4);
             break;
     }
 
-    return op-ob+1;
+    return op-obeg;
 }
 
 int atob(int c, int url)
diff --git a/input.c b/input.c
index 517522b..aef154f 100644
--- a/input.c
+++ b/input.c
@@ -1,21 +1,8 @@
 #include "input.h"
 
 #define PADDING  '='
-#define OCTETBUF  3
 #define SXTETBUF  4
 
-int
-getocts(FILE *fp, unsigned char *o)
-{
-    int c, n;
-
-    n = 0;
-    while (n < OCTETBUF && (c = fgetc(fp)) != EOF)
-        o[n++] = c;
-
-    return n;
-}
-
 int
 getsxts(FILE *fp, unsigned char *s)
 {
diff --git a/input.h b/input.h
index 2238695..ca98ef2 100644
--- a/input.h
+++ b/input.h
@@ -3,9 +3,6 @@
 
 #include <stdio.h>
 
-int
-getocts(FILE *fp, unsigned char *o);
-
 int
 getsxts(FILE *fp, unsigned char *s);
 
diff --git a/main.c b/main.c
index 44b9a71..66232cd 100644
--- a/main.c
+++ b/main.c
@@ -4,8 +4,8 @@
 #include "output.h"
 #include "encode.h"
 
-#define OCTETBUF 4
-#define SXTETBUF 5
+#define OCTETBUF  300
+#define SXTETBUF  400
 
 unsigned char obuf[OCTETBUF];
 unsigned char sbuf[SXTETBUF];
@@ -59,16 +59,16 @@ main(int argc, char *argv[])
             }
         } else if (wrp) {
             last = 0;
-            while ((n = getocts((in) ? in : stdin, obuf))) {
+            while ((n = fread(obuf, sizeof(*obuf), OCTETBUF, (in) ? in : stdin))) {
                 n = encode(obuf, n, sbuf, url);
                 last = printw((out) ? out : stdout, sbuf, n);
             }
             if (last != '\n')
                 fprintf((out) ? out : stdout, "\n");
         } else {
-            while ((n = getocts((in) ? in : stdin, obuf))) {
-                encode(obuf, n, sbuf, url);
-                fprintf((out) ? out : stdout, "%s", sbuf);
+            while ((n = fread(obuf, sizeof(*obuf), OCTETBUF, (in) ? in : stdin))) {
+                n = encode(obuf, n, sbuf, url);
+                fwrite(sbuf, sizeof(*sbuf), n, (out) ? out : stdout);
             }
         }
         if (in)

From 0a4a98390d5f3b361fe2e9e63f018a3979c1498e Mon Sep 17 00:00:00 2001
From: Eric <eric@wolf42.net>
Date: Thu, 29 May 2025 00:51:00 +0200
Subject: [PATCH 7/9] improve printw to write faster

Now all encoding options are faster.
---
 output.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/output.c b/output.c
index b48713e..171c083 100644
--- a/output.c
+++ b/output.c
@@ -9,11 +9,29 @@ printw(FILE *fp, unsigned char *s, int slen)
     int c;
 
     c = '\n';
-    while (slen--) {
-        fputc((c = *s++), fp);
-        ++col;
-        if (!(col %= WRAPCOL))
-            fputc((c = '\n'), fp);
+    if (col) {
+        if (slen >= WRAPCOL-col) {
+            fwrite(s, sizeof(*s), WRAPCOL-col, fp);
+            s += WRAPCOL-col;
+            slen -= WRAPCOL-col;
+            col = 0;
+            fputc('\n', fp);
+        } else {
+            fwrite(s, sizeof(*s), slen, fp);
+            s += slen;
+            col += slen;
+            slen -= slen;
+            c = *(s+slen-1);
+        }
+    }
+    for (; slen >= WRAPCOL; slen -= WRAPCOL, s += WRAPCOL) {
+        fwrite(s, sizeof(*s), WRAPCOL, fp);
+        fputc('\n', fp);
+    }
+    if (slen > 0) {
+        fwrite(s, sizeof(*s), slen, fp);
+        col += slen;
+        c = *(s+slen-1);
     }
 
     return c;

From debab62506c3952509dfb9a3a0e8ff562b3761ca Mon Sep 17 00:00:00 2001
From: Eric <eric@wolf42.net>
Date: Thu, 29 May 2025 01:24:37 +0200
Subject: [PATCH 8/9] remove getsxts for better function readb

Decoding input is read faster now.
With this, all options have been tuned to a reasonable degree.
---
 input.c | 32 +++++++++++++++++++++-----------
 input.h |  2 +-
 main.c  |  2 +-
 3 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/input.c b/input.c
index aef154f..8e500b3 100644
--- a/input.c
+++ b/input.c
@@ -1,19 +1,29 @@
 #include "input.h"
 
 #define PADDING  '='
-#define SXTETBUF  4
 
 int
-getsxts(FILE *fp, unsigned char *s)
+readb(FILE *fp, unsigned char *s, int slen)
 {
-    int c, n, pad;
+    int read, tread;
+    unsigned char *send, *sbeg;
+    unsigned char *l, *r;
+    
+    read = tread = 0;
+    sbeg = l = r = s;
+    while (tread < slen && (read = fread(l, sizeof(*l), slen-tread, fp))) {
+        tread += read;
+        send = s + tread;
+        for (r = l; r < send; ++r)
+            if (*r != '\n')
+                *l++ = *r;
+        tread -= r - l;
+        if (l > sbeg) {
+            for (--l; *l == PADDING; --l)
+                ;
+            ++l;
+        }
+    }
 
-    n = pad = 0;
-    while (n < SXTETBUF && (c = fgetc(fp)) != EOF && c != PADDING)
-        if (c != '\n')
-            s[n++] = c;
-    while (n+pad < SXTETBUF)
-        s[n+pad++] = PADDING;
-
-    return n;
+    return l-sbeg;
 }
diff --git a/input.h b/input.h
index ca98ef2..901b2c4 100644
--- a/input.h
+++ b/input.h
@@ -4,6 +4,6 @@
 #include <stdio.h>
 
 int
-getsxts(FILE *fp, unsigned char *s);
+readb(FILE *fp, unsigned char *s, int slen);
 
 #endif
diff --git a/main.c b/main.c
index 66232cd..d7d8530 100644
--- a/main.c
+++ b/main.c
@@ -53,7 +53,7 @@ main(int argc, char *argv[])
             exit(EXIT_FAILURE);
         }
         if (dec) {
-            while ((n = getsxts((in) ? in : stdin, sbuf))) {
+            while ((n = readb((in) ? in : stdin, sbuf, SXTETBUF))) {
                 n = decode(sbuf, n, obuf, url);
                 fwrite(obuf, sizeof(*obuf), n, (out) ? out : stdout);
             }

From aacf2324c7ba1893fb2eccd63c16208706910994 Mon Sep 17 00:00:00 2001
From: Eric <eric@wolf42.net>
Date: Thu, 29 May 2025 16:02:45 +0200
Subject: [PATCH 9/9] improve decode time

atob() has been replaced with a lookup table, removing previous
conditionals and function calls necessary to decode.
---
 encode.c | 76 +++++++++++++++++++++++++++++---------------------------
 encode.h |  2 +-
 main.c   |  6 ++---
 3 files changed, 44 insertions(+), 40 deletions(-)

diff --git a/encode.c b/encode.c
index 861bae9..08d50f8 100644
--- a/encode.c
+++ b/encode.c
@@ -2,15 +2,35 @@
 
 #define PADDING '='
 
-unsigned char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
-                      "abcdefghijklmnopqrstuvwxyz" \
-                      "0123456789" \
-                      "+/";
+static
+unsigned char b64toascii[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+                             "abcdefghijklmnopqrstuvwxyz" \
+                             "0123456789" \
+                             "+/";
+
+static
+unsigned char b64urltoascii[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+                                "abcdefghijklmnopqrstuvwxyz" \
+                                "0123456789" \
+                                "-_";
+
+static
+unsigned char asciitob64[] = {
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0, 62,  0, 62,  0, 63, 52, 53,
+    54, 55, 56, 57, 58, 59, 60, 61,  0,  0,
+     0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
+     5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+    25,  0,  0,  0,  0, 63,  0, 26, 27, 28,
+    29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+    39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+    49, 50, 51
+};
 
-unsigned char b64url[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
-                         "abcdefghijklmnopqrstuvwxyz" \
-                         "0123456789" \
-                         "-_";
 
 int
 encode(unsigned char *op, int olen, unsigned char *sp, int url)
@@ -20,7 +40,7 @@ encode(unsigned char *op, int olen, unsigned char *sp, int url)
     unsigned char *sbeg;
     unsigned char *tend;
 
-    table = (!url) ? b64 : b64url;
+    table = (!url) ? b64toascii : b64urltoascii;
 
     sbeg = sp;
     tend = op + olen - (olen % 3);
@@ -52,52 +72,36 @@ encode(unsigned char *op, int olen, unsigned char *sp, int url)
 }
 
 int
-decode(unsigned char *sp, int slen, unsigned char *op, int url)
+decode(unsigned char *sp, int slen, unsigned char *op)
 {
-    int tmp, b, atob(int c, int url);
+    int tmp, b;
     unsigned char *obeg;
     unsigned char *qend;
 
     obeg = op;
     qend = sp + slen - (slen % 4);
     while (sp < qend) {
-        tmp = atob(*sp++, url) << 2;
-        b = atob(*sp++, url);
+        tmp = asciitob64[*sp++] << 2;
+        b = asciitob64[*sp++];
         *op++ = tmp + ((b & ~15) >> 4);
         tmp = (b & 15) << 4;
-        b = atob(*sp++, url);
+        b = asciitob64[*sp++];
         *op++ = tmp + ((b & ~3) >> 2);
-        *op++ = ((b & 3) << 6) + atob(*sp++, url);
+        *op++ = ((b & 3) << 6) + asciitob64[*sp++];
     }
     switch (slen % 4) {
         case 3:
-            tmp = atob(*sp++, url) << 2;
-            b = atob(*sp++, url);
+            tmp = asciitob64[*sp++] << 2;
+            b = asciitob64[*sp++];
             *op++ = tmp + ((b & ~15) >> 4);
             tmp = (b & 15) << 4;
-            *op++ = tmp + ((atob(*sp++, url) & ~3) >> 2);
+            *op++ = tmp + ((asciitob64[*sp++] & ~3) >> 2);
             break;
         case 2:
-            tmp = atob(*sp++, url) << 2;
-            *op++ = tmp + ((atob(*sp++, url) & ~15) >> 4);
+            tmp = asciitob64[*sp++] << 2;
+            *op++ = tmp + ((asciitob64[*sp++] & ~15) >> 4);
             break;
     }
 
     return op-obeg;
 }
-
-int atob(int c, int url)
-{
-    if (c >= 'A' && c <= 'Z')
-        c -= 'A';
-    else if (c >= 'a' && c <= 'z')
-        c = c - 'a' + 26;
-    else if (c >= '0' && c <= '9')
-        c = c - '0' + 26 * 2;
-    else if (c == ((!url) ? '+' : '-'))
-        c = 62;
-    else
-        c = 63;
-
-    return c;
-}
diff --git a/encode.h b/encode.h
index 425038c..7e6f217 100644
--- a/encode.h
+++ b/encode.h
@@ -5,6 +5,6 @@ int
 encode(unsigned char *op, int olen, unsigned char *sp, int url);
 
 int
-decode(unsigned char *sp, int slen, unsigned char *op, int url);
+decode(unsigned char *sp, int slen, unsigned char *op);
 
 #endif
diff --git a/main.c b/main.c
index d7d8530..bc612d5 100644
--- a/main.c
+++ b/main.c
@@ -4,8 +4,8 @@
 #include "output.h"
 #include "encode.h"
 
-#define OCTETBUF  300
-#define SXTETBUF  400
+#define OCTETBUF  1500
+#define SXTETBUF  2000
 
 unsigned char obuf[OCTETBUF];
 unsigned char sbuf[SXTETBUF];
@@ -54,7 +54,7 @@ main(int argc, char *argv[])
         }
         if (dec) {
             while ((n = readb((in) ? in : stdin, sbuf, SXTETBUF))) {
-                n = decode(sbuf, n, obuf, url);
+                n = decode(sbuf, n, obuf);
                 fwrite(obuf, sizeof(*obuf), n, (out) ? out : stdout);
             }
         } else if (wrp) {