b64/encode.c
Eric f0577d8ea0 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.
2025-05-28 23:24:05 +02:00

103 lines
2.6 KiB
C

#include "encode.h"
#define PADDING '='
unsigned char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz" \
"0123456789" \
"+/";
unsigned char b64url[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz" \
"0123456789" \
"-_";
int
encode(unsigned char *op, int olen, unsigned char *sp, int url)
{
int tmp;
unsigned char *table;
unsigned char *sbeg;
unsigned char *tend;
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++ = 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++ = table[(*op & ~3) >> 2];
*sp++ = table[(*op & 3) << 4];
*sp++ = PADDING;
*sp++ = PADDING;
break;
}
return sp-sbeg;
}
int
decode(unsigned char *sp, int slen, unsigned char *op, int url)
{
int tmp, b, atob(int c, int url);
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);
*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:
tmp = atob(*sp++, url) << 2;
b = atob(*sp++, url);
*op++ = tmp + ((b & ~15) >> 4);
tmp = (b & 15) << 4;
*op++ = tmp + ((atob(*sp++, url) & ~3) >> 2);
break;
case 2:
tmp = atob(*sp++, url) << 2;
*op++ = tmp + ((atob(*sp++, url) & ~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;
}