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.
103 lines
2.6 KiB
C
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;
|
|
}
|