+int b64decode(const char *src, char *dst, int length) {
+ uint32_t triplet = 0;
+ unsigned char *udst = dst;
+
+ for(int i = 0; i < length; i++) {
+ triplet |= charb64decode(src[i]) << (6 * (i & 3));
+ if((i & 3) == 3) {
+ udst[0] = triplet & 0xff; triplet >>= 8;
+ udst[1] = triplet & 0xff; triplet >>= 8;
+ udst[2] = triplet;
+ triplet = 0;
+ udst += 3;
+ }
+ }
+ if((length & 3) == 3) {
+ udst[0] = triplet & 0xff; triplet >>= 8;
+ udst[1] = triplet & 0xff;
+ return length / 4 * 3 + 2;
+ } else if((length & 3) == 2) {
+ udst[0] = triplet & 0xff;
+ return length / 4 * 3 + 1;
+ } else {
+ return length / 4 * 3;
+ }
+}
+
+int b64encode(const char *src, char *dst, int length) {
+ uint32_t triplet;
+ const unsigned char *usrc = src;
+ int origlen = length;
+
+ while(length > 0) {
+ if(length >= 3) {
+ triplet = usrc[0] | usrc[1] << 8 | usrc[2] << 16;
+ dst[0] = base64imals[triplet & 63]; triplet >>= 6;
+ dst[1] = base64imals[triplet & 63]; triplet >>= 6;
+ dst[2] = base64imals[triplet & 63]; triplet >>= 6;
+ dst[3] = base64imals[triplet];
+ dst += 4; usrc += 3; length -= 3;
+ } else if(length >=2) {
+ triplet = usrc[0] | usrc[1] << 8;
+ dst[0] = base64imals[triplet & 63]; triplet >>= 6;
+ dst[1] = base64imals[triplet & 63]; triplet >>= 6;
+ dst[2] = base64imals[triplet];
+ dst[3] = 0;
+ return origlen / 3 * 4 + 3;
+ } else {
+ triplet = usrc[0];
+ dst[0] = base64imals[triplet & 63]; triplet >>= 6;
+ dst[1] = base64imals[triplet];
+ dst[2] = 0;
+ return origlen / 3 * 4 + 2;
+ }
+ }
+
+ *dst = 0;
+ return origlen / 4 * 3;
+}
+