base64_decode

#include <stdlib.h>
#include <string.h>

#define between(x, min, max) ((x) >= (min) && (x) <= (max))

static inline unsigned int get_value(unsigned int src)
{
	unsigned int ret;

	if (between(src, 'A', 'Z'))
	{
		ret = src - 'A';
	}
	else if (between(src, 'a', 'z'))
	{
		ret = src - 'a' + 26;
	}
	else if (between(src, '0', '9'))
	{
		ret = src - '0' + 52;
	}
	else if (src == '+')
	{
		ret = 62;
	}
	else if (src == '/')
	{
		ret = 63;
	}
	else
	{
		ret = 0;
	}

	return ret;
}

unsigned int base64_decode(unsigned char **dest, const unsigned char *src)
{
	unsigned char *p_dest;
	const unsigned char *p_last;
	unsigned int src_leng, dest_leng, counter;

	src_leng = strlen((const char *) src);
	counter = src_leng >> 2;
	dest_leng = counter + (counter << 1);
	p_last = src + src_leng;

	if ('=' == *p_last)
	{
		--dest_leng;
	}

	if ('=' == *(p_last - 1))
	{
		--dest_leng;
	}

	p_dest = malloc(dest_leng);
	*dest = p_dest;

	while (counter--)
	{
		unsigned int t0, t1, t2, t3;

		t0 = get_value(*src++);
		t1 = get_value(*src++);
		t2 = get_value(*src++);
		t3 = get_value(*src++);

		*p_dest++ = (t0 << 2 | t1 >> 4);
		*p_dest++ = (t1 << 4 | t2 >> 2);
		*p_dest++ = (t2 << 6 | t3);
	}

	return dest_leng;
}