#include <stdlib.h>

#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#include <time.h>
#include "ga.h"
#pragma warning(disable:4996)
// typedef unsigned int     size_t;
// typedef int              ptrdiff_t;
// typedef int              intptr_t;
static co
nst size_t ba
se32_ENCODE_INPUT = 5;
static co
nst size_t ba
se32_ENCODE_OUTPUT = 8;
static co
nst char* co
nst ba
se32_ENCODE_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=";
//返回输出缓冲区需要的大小
size_t ba
se32EncodeGetLength(size_t size)
{
	
	return (((size + ba
se32_ENCODE_INPUT - 1) / ba
se32_ENCODE_INPUT) * ba
se32_ENCODE_OUTPUT) + 1; 
}
//ba
se32编码,size是src字符串的长度不包括结尾的'0'
size_t ba
se32Encode(char* dest, co
nst void* src, size_t size)
{
	if (dest && src)
	{
		unsigned char* pSrc = (unsigned char*)src;
		size_t dwSrcSize = size;
		size_t dwDestSize = 0;
		size_t dwBlockSize;
		unsigned char n1, n2, n3, n4, n5, n6, n7, n8;
		while (dwSrcSize >= 1)
		{
			
			dwBlockSize = (dwSrcSize < ba
se32_ENCODE_INPUT ? dwSrcSize : ba
se32_ENCODE_INPUT);
			n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = 0;
			switch (dwBlockSize)
			{
			case 5:
				n8 = (pSrc[4] & 0
x1f);
				n7 = ((unsigned cha
r)(pSrc[4] & 0
xe0) >> 5);
			case 4:
				n7 |= ((unsigned cha
r)(pSrc[3] & 0
x03) << 3);
				n6 = ((unsigned cha
r)(pSrc[3] & 0
x7c) >> 2);
				n5 = ((unsigned cha
r)(pSrc[3] & 0
x80) >> 7);
			case 3:
				n5 |= ((unsigned cha
r)(pSrc[2] & 0
x0f) << 1);
				n4 = ((unsigned cha
r)(pSrc[2] & 0
xf0) >> 4);
			case 2:
				n4 |= ((unsigned cha
r)(pSrc[1] & 0
x01) << 4);
				n3 = ((unsigned cha
r)(pSrc[1] & 0
x3e) >> 1);
				n2 = ((unsigned cha
r)(pSrc[1] & 0
xc0) >> 6);
			case 1:
				n2 |= ((unsigned cha
r)(pSrc[0] & 0
x07) << 2);
				n1 = ((unsigned cha
r)(pSrc[0] & 0
xf8) >> 3);
				break;
			default:
				assert(0);
			}
			pSrc += dwBlockSize;
			dwSrcSize -= dwBlockSize;
			
			assert(n1 <= 31);
			assert(n2 <= 31);
			assert(n3 <= 31);
			assert(n4 <= 31);
			assert(n5 <= 31);
			assert(n6 <= 31);
			assert(n7 <= 31);
			assert(n8 <= 31);
			
			switch (dwBlockSize)
			{
			case 1: n3 = n4 = 32;
			case 2: n5 = 32;
			case 3: n6 = n7 = 32;
			case 4: n8 = 32;
			case 5:
				break;
			default:
				assert(0);
			}
			
			*dest++ = ba
se32_ENCODE_TABLE[n1];
			*dest++ = ba
se32_ENCODE_TABLE[n2];
			*dest++ = ba
se32_ENCODE_TABLE[n3];
			*dest++ = ba
se32_ENCODE_TABLE[n4];
			*dest++ = ba
se32_ENCODE_TABLE[n5];
			*dest++ = ba
se32_ENCODE_TABLE[n6];
			*dest++ = ba
se32_ENCODE_TABLE[n7];
			*dest++ = ba
se32_ENCODE_TABLE[n8];
			dwDestSize += ba
se32_ENCODE_OUTPUT;
		}
		*dest++ = 'x0'; 
		return dwDestSize;
	}
	else
		return 0; 
}
static co
nst size_t ba
se32_DECODE_INPUT = 8;
static co
nst size_t ba
se32_DECODE_OUTPUT = 5;
static co
nst size_t ba
se32_DECODE_MAX_PADDING = 6;
static co
nst unsigned char ba
se32_DECODE_MAX = 31;
static co
nst unsigned char ba
se32_DECODE_TABLE[0
x80] = {
	 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF,
	 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF,
	 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF,
	 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF,
	 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF,
	 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF,
	 0
xFF, 0
xFF, 0
x1a, 0
x1b, 0
x1c, 0
x1d, 0
x1e, 0
x1f, 
	 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
x20, 0
xFF, 0
xFF, 
	 0
xFF, 0
x00, 0
x01, 0
x02, 0
x03, 0
x04, 0
x05, 0
x06, 
	 0
x07, 0
x08, 0
x09, 0
x0a, 0
x0b, 0
x0c, 0
x0d, 0
x0e, 
	 0
x0f, 0
x10, 0
x11, 0
x12, 0
x13, 0
x14, 0
x15, 0
x16, 
	 0
x17, 0
x18, 0
x19, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 
	 0
xFF, 0
x00, 0
x01, 0
x02, 0
x03, 0
x04, 0
x05, 0
x06, 
	 0
x07, 0
x08, 0
x09, 0
x0a, 0
x0b, 0
x0c, 0
x0d, 0
x0e, 
	 0
x0f, 0
x10, 0
x11, 0
x12, 0
x13, 0
x14, 0
x15, 0
x16, 
	 0
x17, 0
x18, 0
x19, 0
xFF, 0
xFF, 0
xFF, 0
xFF, 0
xFF  
};
int cyoba
se32Validate(co
nst char* src, size_t size)
{
	
	if (size % ba
se32_DECODE_INPUT != 0)
		return -1; 
	for (; size >= 1; --size, ++src)
	{
		unsigned char ch = *src;
		if ((ch >= 0
x80) || (ba
se32_DECODE_TABLE[ch] > ba
se32_DECODE_MAX))
			break;
	}
	for (; 1 <= size && size <= ba
se32_DECODE_MAX_PADDING; --size, ++src)
	{
		unsigned char ch = *src;
		if ((ch >= 0
x80) || (ba
se32_DECODE_TABLE[ch] != ba
se32_DECODE_MAX + 1))
			break;
	}
	if (size != 0)
		return -2; 
	return 0; 
}
size_t ba
se32DecodeGetLength(size_t size)
{
	
	if (size % ba
se32_DECODE_INPUT == 0)
		return (((size + ba
se32_DECODE_INPUT - 1) / ba
se32_DECODE_INPUT) * ba
se32_DECODE_OUTPUT) + 1; 
	else
		return 0; 
}
size_t ba
se32Decode(void* dest, co
nst char* src, size_t size)
{
	if (dest && src && (size % ba
se32_DECODE_INPUT == 0))
	{
		unsigned char* pDest = (unsigned char*)dest;
		size_t dwSrcSize = size;
		size_t dwDestSize = 0;
		unsigned char in1, in2, in3, in4, in5, in6, in7, in8;
		while (dwSrcSize >= 1)
		{
			
			in1 = *src++;
			in2 = *src++;
			in3 = *src++;
			in4 = *src++;
			in5 = *src++;
			in6 = *src++;
			in7 = *src++;
			in8 = *src++;
			dwSrcSize -= ba
se32_DECODE_INPUT;
			
			if (in1 >= 0
x80 || in2 >= 0
x80 || in3 >= 0
x80 || in4 >= 0
x80
				|| in5 >= 0
x80 || in6 >= 0
x80 || in7 >= 0
x80 || in8 >= 0
x80)
				return 0; 
						  
			in1 = ba
se32_DECODE_TABLE[in1];
			in2 = ba
se32_DECODE_TABLE[in2];
			in3 = ba
se32_DECODE_TABLE[in3];
			in4 = ba
se32_DECODE_TABLE[in4];
			in5 = ba
se32_DECODE_TABLE[in5];
			in6 = ba
se32_DECODE_TABLE[in6];
			in7 = ba
se32_DECODE_TABLE[in7];
			in8 = ba
se32_DECODE_TABLE[in8];
			
			if (in1 > ba
se32_DECODE_MAX || in2 > ba
se32_DECODE_MAX)
				return 0; 
						  
			if ((int)in3 > (int)ba
se32_DECODE_MAX + 1 || (int)in4 > (int)ba
se32_DECODE_MAX + 1 || (int)in5 > (int)ba
se32_DECODE_MAX + 1
				|| (int)in6 > (int)ba
se32_DECODE_MAX + 1 || (int)in7 > (int)ba
se32_DECODE_MAX + 1 || (int)in8 > (int)ba
se32_DECODE_MAX + 1)
				return 0; 
						  
			*pDest++ = ((unsigned cha
r)(in1 & 0
x1f) << 3) | ((unsigned cha
r)(in2 & 0
x1c) >> 2);
			*pDest++ = ((unsigned cha
r)(in2 & 0
x03) << 6) | ((unsigned cha
r)(in3 & 0
x1f) << 1) | ((unsigned cha
r)(in4 & 0
x10) >> 4);
			*pDest++ = ((unsigned cha
r)(in4 & 0
x0f) << 4) | ((unsigned cha
r)(in5 & 0
x1e) >> 1);