peerplays-fc/vendor/cyoencode-1.0.2/src/CyoDecode.c
Daniel Larimer b59fe17562 Merge branch 'phoenix' of github.com:bytemaster/fc into phoenix
Remove fc::vector and fc::string
2013-06-27 14:45:11 -04:00

398 lines
15 KiB
C

/*
* CyoDecode.c - part of the CyoEncode library
*
* Copyright (c) 2009-2012, Graham Bull.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "CyoDecode.h"
#include <assert.h>
#include <stdio.h> //TEMP
/********************************** Shared ***********************************/
static int cyoBaseXXValidate( const char* src, size_t size, size_t inputBytes, size_t maxPadding,
unsigned char maxValue, const unsigned char table[] )
{
/*
* returns 0 if the source is a valid baseXX encoding
*/
if (!src)
return -1; /*ERROR - NULL pointer*/
if (size % inputBytes != 0)
return -1; /*ERROR - extra characters*/
/* check the bytes */
for (; size >= 1; --size, ++src)
{
unsigned char ch = *src;
if ((ch >= 0x80) || (table[ ch ] > maxValue))
break;
}
/* check any padding */
for (; 1 <= size && size <= maxPadding; --size, ++src)
{
unsigned char ch = *src;
if ((ch >= 0x80) || (table[ ch ] != maxValue + 1))
break;
}
/* if size isn't zero then the encoded string isn't valid */
if (size != 0)
return -2; /*ERROR - invalid baseXX character*/
/* OK */
return 0;
}
static size_t cyoBaseXXDecodeGetLength( size_t size, size_t inputBytes, size_t outputBytes )
{
if (size % inputBytes != 0)
return 0; /*ERROR - extra characters*/
/* OK */
return (((size + inputBytes - 1) / inputBytes) * outputBytes) + 1; /*plus terminator*/
}
/****************************** Base16 Decoding ******************************/
static const size_t BASE16_INPUT = 2;
static const size_t BASE16_OUTPUT = 1;
static const size_t BASE16_MAX_PADDING = 0;
static const unsigned char BASE16_MAX_VALUE = 15;
static const unsigned char BASE16_TABLE[ 0x80 ] = {
/*00-07*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*08-0f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*10-17*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*18-1f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*20-27*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*28-2f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*30-37*/ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /*8 = '0'-'7'*/
/*38-3f*/ 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*2 = '8'-'9'*/
/*40-47*/ 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF, /*6 = 'A'-'F'*/
/*48-4f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*50-57*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*58-5f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*60-67*/ 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF, /*6 = 'a'-'f' (same as 'A'-'F')*/
/*68-6f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*70-77*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*78-7f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
int cyoBase16Validate( const char* src, size_t size )
{
return cyoBaseXXValidate( src, size, BASE16_INPUT, BASE16_MAX_PADDING, BASE16_MAX_VALUE, BASE16_TABLE );
}
size_t cyoBase16DecodeGetLength( size_t size )
{
return cyoBaseXXDecodeGetLength( size, BASE16_INPUT, BASE16_OUTPUT );
}
size_t cyoBase16Decode( void* dest, const char* src, size_t size )
{
/*
* output 1 byte for every 2 input:
*
* outputs: 1
* inputs: 1 = ----1111 = 1111----
* 2 = ----2222 = ----2222
*/
if (dest && src && (size % BASE16_INPUT == 0))
{
unsigned char* pDest = (unsigned char*)dest;
size_t dwSrcSize = size;
size_t dwDestSize = 0;
unsigned char in1, in2;
while (dwSrcSize >= 1)
{
/* 2 inputs */
in1 = *src++;
in2 = *src++;
dwSrcSize -= BASE16_INPUT;
/* Validate ascii */
if (in1 >= 0x80 || in2 >= 0x80)
return 0; /*ERROR - invalid base16 character*/
/* Convert ascii to base16 */
in1 = BASE16_TABLE[ in1 ];
in2 = BASE16_TABLE[ in2 ];
/* Validate base16 */
if (in1 > BASE16_MAX_VALUE || in2 > BASE16_MAX_VALUE)
return 0; /*ERROR - invalid base16 character*/
/* 1 output */
*pDest++ = ((in1 << 4) | in2);
dwDestSize += BASE16_OUTPUT;
}
*pDest++ = '\x0'; /*append terminator*/
return dwDestSize;
}
else
return 0; /*ERROR - null pointer, or size isn't a multiple of 2*/
}
/****************************** Base32 Decoding ******************************/
static const size_t BASE32_INPUT = 8;
static const size_t BASE32_OUTPUT = 5;
static const size_t BASE32_MAX_PADDING = 6;
static const unsigned char BASE32_MAX_VALUE = 31;
static const unsigned char BASE32_TABLE[ 0x80 ] = {
/*00-07*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*08-0f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*10-17*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*18-1f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*20-27*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*28-2f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*30-37*/ 0xFF, 0xFF, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /*6 = '2'-'7'*/
/*38-3f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, /*1 = '='*/
/*40-47*/ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /*7 = 'A'-'G'*/
/*48-4f*/ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /*8 = 'H'-'O'*/
/*50-57*/ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /*8 = 'P'-'W'*/
/*58-5f*/ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*3 = 'X'-'Z'*/
/*60-67*/ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /*7 = 'a'-'g' (same as 'A'-'G')*/
/*68-6f*/ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /*8 = 'h'-'o' (same as 'H'-'O')*/
/*70-77*/ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /*8 = 'p'-'w' (same as 'P'-'W')*/
/*78-7f*/ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /*3 = 'x'-'z' (same as 'X'-'Z')*/
};
int cyoBase32Validate( const char* src, size_t size )
{
return cyoBaseXXValidate( src, size, BASE32_INPUT, BASE32_MAX_PADDING, BASE32_MAX_VALUE, BASE32_TABLE );
}
size_t cyoBase32DecodeGetLength( size_t size )
{
return cyoBaseXXDecodeGetLength( size, BASE32_INPUT, BASE32_OUTPUT );
}
size_t cyoBase32Decode( void* dest, const char* src, size_t size )
{
/*
* output 5 bytes for every 8 input:
*
* outputs: 1 2 3 4 5
* inputs: 1 = ---11111 = 11111---
* 2 = ---222XX = -----222 XX------
* 3 = ---33333 = --33333-
* 4 = ---4XXXX = -------4 XXXX----
* 5 = ---5555X = ----5555 X-------
* 6 = ---66666 = -66666--
* 7 = ---77XXX = ------77 XXX-----
* 8 = ---88888 = ---88888
*/
if (dest && src && (size % BASE32_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)
{
/* 8 inputs */
in1 = *src++;
in2 = *src++;
in3 = *src++;
in4 = *src++;
in5 = *src++;
in6 = *src++;
in7 = *src++;
in8 = *src++;
dwSrcSize -= BASE32_INPUT;
/* Validate ascii */
if ( in1 >= 0x80 || in2 >= 0x80 || in3 >= 0x80 || in4 >= 0x80
|| in5 >= 0x80 || in6 >= 0x80 || in7 >= 0x80 || in8 >= 0x80)
return 0; /*ERROR - invalid base32 character*/
/* Convert ascii to base16 */
in1 = BASE32_TABLE[ in1 ];
in2 = BASE32_TABLE[ in2 ];
in3 = BASE32_TABLE[ in3 ];
in4 = BASE32_TABLE[ in4 ];
in5 = BASE32_TABLE[ in5 ];
in6 = BASE32_TABLE[ in6 ];
in7 = BASE32_TABLE[ in7 ];
in8 = BASE32_TABLE[ in8 ];
/* Validate base32 */
if (in1 > BASE32_MAX_VALUE || in2 > BASE32_MAX_VALUE)
return 0; /*ERROR - invalid base32 character*/
/*the following can be padding*/
if ( in3 > BASE32_MAX_VALUE + 1 || in4 > BASE32_MAX_VALUE + 1 || in5 > BASE32_MAX_VALUE + 1
|| in6 > BASE32_MAX_VALUE + 1 || in7 > BASE32_MAX_VALUE + 1 || in8 > BASE32_MAX_VALUE + 1)
return 0; /*ERROR - invalid base32 character*/
/* 5 outputs */
*pDest++ = ((in1 & 0x1f) << 3) | ((in2 & 0x1c) >> 2);
*pDest++ = ((in2 & 0x03) << 6) | ((in3 & 0x1f) << 1) | ((in4 & 0x10) >> 4);
*pDest++ = ((in4 & 0x0f) << 4) | ((in5 & 0x1e) >> 1);
*pDest++ = ((in5 & 0x01) << 7) | ((in6 & 0x1f) << 2) | ((in7 & 0x18) >> 3);
*pDest++ = ((in7 & 0x07) << 5) | (in8 & 0x1f);
dwDestSize += BASE32_OUTPUT;
/* Padding */
if (in8 == BASE32_MAX_VALUE + 1)
{
--dwDestSize;
assert( (in7 == BASE32_MAX_VALUE + 1 && in6 == BASE32_MAX_VALUE + 1) || (in7 != BASE32_MAX_VALUE + 1) );
if (in6 == BASE32_MAX_VALUE + 1)
{
--dwDestSize;
if (in5 == BASE32_MAX_VALUE + 1)
{
--dwDestSize;
assert( (in4 == BASE32_MAX_VALUE + 1 && in3 == BASE32_MAX_VALUE + 1) || (in4 != BASE32_MAX_VALUE + 1) );
if (in3 == BASE32_MAX_VALUE + 1)
{
--dwDestSize;
}
}
}
}
}
*pDest++ = '\x0'; /*append terminator*/
return dwDestSize;
}
else
return 0; /*ERROR - null pointer, or size isn't a multiple of 8*/
}
/****************************** Base64 Decoding ******************************/
static const size_t BASE64_INPUT = 4;
static const size_t BASE64_OUTPUT = 3;
static const size_t BASE64_MAX_PADDING = 2;
static const unsigned char BASE64_MAX_VALUE = 63;
static const unsigned char BASE64_TABLE[ 0x80 ] = {
/*00-07*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*08-0f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*10-17*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*18-1f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*20-27*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/*28-2f*/ 0xFF, 0xFF, 0xFF, 0x3e, 0xFF, 0xFF, 0xFF, 0x3f, /*2 = '+' and '/'*/
/*30-37*/ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, /*8 = '0'-'7'*/
/*38-3f*/ 0x3c, 0x3d, 0xFF, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, /*2 = '8'-'9' and '='*/
/*40-47*/ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /*7 = 'A'-'G'*/
/*48-4f*/ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /*8 = 'H'-'O'*/
/*50-57*/ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /*8 = 'P'-'W'*/
/*58-5f*/ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*3 = 'X'-'Z'*/
/*60-67*/ 0xFF, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, /*7 = 'a'-'g'*/
/*68-6f*/ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, /*8 = 'h'-'o'*/
/*70-77*/ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, /*8 = 'p'-'w'*/
/*78-7f*/ 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /*3 = 'x'-'z'*/
};
int cyoBase64Validate( const char* src, size_t size )
{
return cyoBaseXXValidate( src, size, BASE64_INPUT, BASE64_MAX_PADDING, BASE64_MAX_VALUE, BASE64_TABLE );
}
size_t cyoBase64DecodeGetLength( size_t size )
{
return cyoBaseXXDecodeGetLength( size, BASE64_INPUT, BASE64_OUTPUT );
}
size_t cyoBase64Decode( void* dest, const char* src, size_t size )
{
/*
* output 3 bytes for every 4 input:
*
* outputs: 1 2 3
* inputs: 1 = --111111 = 111111--
* 2 = --22XXXX = ------22 XXXX----
* 3 = --3333XX = ----3333 XX------
* 4 = --444444 = --444444
*/
if (dest && src && (size % BASE64_INPUT == 0))
{
unsigned char* pDest = (unsigned char*)dest;
size_t dwSrcSize = size;
size_t dwDestSize = 0;
unsigned char in1, in2, in3, in4;
while (dwSrcSize >= 1)
{
/* 4 inputs */
in1 = *src++;
in2 = *src++;
in3 = *src++;
in4 = *src++;
dwSrcSize -= BASE64_INPUT;
/* Validate ascii */
if (in1 >= 0x80 || in2 >= 0x80 || in3 >= 0x80 || in4 >= 0x80)
return 0; /*ERROR - invalid base64 character*/
/* Convert ascii to base64 */
in1 = BASE64_TABLE[ in1 ];
in2 = BASE64_TABLE[ in2 ];
in3 = BASE64_TABLE[ in3 ];
in4 = BASE64_TABLE[ in4 ];
/* Validate base64 */
if (in1 > BASE64_MAX_VALUE || in2 > BASE64_MAX_VALUE)
return 0; /*ERROR - invalid base64 character*/
/*the following can be padding*/
if (in3 > BASE64_MAX_VALUE + 1 || in4 > BASE64_MAX_VALUE + 1)
return 0; /*ERROR - invalid base64 character*/
/* 3 outputs */
*pDest++ = ((in1 & 0x3f) << 2) | ((in2 & 0x30) >> 4);
*pDest++ = ((in2 & 0x0f) << 4) | ((in3 & 0x3c) >> 2);
*pDest++ = ((in3 & 0x03) << 6) | (in4 & 0x3f);
dwDestSize += BASE64_OUTPUT;
/* Padding */
if (in4 == BASE64_MAX_VALUE + 1)
{
--dwDestSize;
if (in3 == BASE64_MAX_VALUE + 1)
{
--dwDestSize;
}
}
}
*pDest++ = '\x0'; /*append terminator*/
return dwDestSize;
}
else
return 0; /*ERROR - null pointer, or size isn't a multiple of 4*/
}