sandi-0.1: csrc/qp.c
// Copyright: (c) Magnus Therning, 2012
// License: BSD3, found in the LICENSE file
#include <assert.h>
#include "qp.h"
static char const encmap[] = "0123456789ABCDEF";
void qp_enc(uint8_t const *src, size_t srclen,
uint8_t *dst, size_t *dstlen,
uint8_t const **rem, size_t *remlen)
{
assert(src || srclen == 0);
assert(dst);
assert(dstlen);
assert(rem);
assert(remlen);
size_t od = *dstlen, i;
for(i = 0, *dstlen = 0; i < srclen && *dstlen < od; i++, (*dstlen)++) {
if((33 <= src[i] && src[i] <= 60) ||
(62 <= src[i] && src[i] <= 126)) {
dst[*dstlen] = src[i];
} else {
uint8_t o0 = src[i] >> 4, o1 = src[i] & 0x0f;
if(*dstlen + 3 >= od) goto exit;
dst[*dstlen] = '=';
dst[*dstlen + 1] = encmap[o0];
dst[*dstlen + 2] = encmap[o1];
*dstlen += 2;
}
}
exit:
*rem = src + i;
*remlen = srclen -i;
}
static uint8_t const decmap[] = {
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
};
int qp_dec(uint8_t const *src, size_t srclen,
uint8_t *dst, size_t *dstlen,
uint8_t const **rem, size_t *remlen)
{
assert(src || srclen == 0);
assert(dst);
assert(dstlen);
assert(rem);
assert(remlen);
size_t od = *dstlen, i;
int res = 0;
for(i = 0, *dstlen = 0; i < srclen && *dstlen < od; i++, (*dstlen)++) {
if((33 <= src[i] && src[i] <= 60) ||
(62 <= src[i] && src[i] <= 126)) {
dst[*dstlen] = src[i];
} else if('=' == src[i]) {
if(i + 2 >= srclen) { res = 1; goto exit; }
uint8_t o0 = decmap[src[i + 1]], o1 = decmap[src[i + 2]];
if((o0 | o1) & 0xf0) { res = 1; break; }
dst[*dstlen] = o0 << 4 | o1;
i += 2;
} else { res = 1; goto exit; }
}
exit:
*rem = src + i;
*remlen = srclen -i;
return(res);
}