283 lines
8.8 KiB
C
283 lines
8.8 KiB
C
/*
|
|
* CyoEncode.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 "CyoEncode.h"
|
|
|
|
#include <assert.h>
|
|
|
|
/********************************** Shared ***********************************/
|
|
|
|
static size_t cyoBaseXXEncodeGetLength( size_t size, size_t inputBytes, size_t outputBytes )
|
|
{
|
|
return (((size + inputBytes - 1) / inputBytes) * outputBytes) + 1; /*plus terminator*/
|
|
}
|
|
|
|
/****************************** Base16 Encoding ******************************/
|
|
|
|
static const size_t BASE16_INPUT = 1;
|
|
static const size_t BASE16_OUTPUT = 2;
|
|
static const char* const BASE16_TABLE = "0123456789ABCDEF";
|
|
|
|
size_t cyoBase16EncodeGetLength( size_t size )
|
|
{
|
|
return cyoBaseXXEncodeGetLength( size, BASE16_INPUT, BASE16_OUTPUT );
|
|
}
|
|
|
|
size_t cyoBase16Encode( char* dest, const void* src, size_t size )
|
|
{
|
|
/*
|
|
* output 2 bytes for every 1 input:
|
|
*
|
|
* inputs: 1
|
|
* outputs: 1 = ----1111 = 1111----
|
|
* 2 = ----2222 = ----2222
|
|
*/
|
|
|
|
if (dest && src)
|
|
{
|
|
unsigned char* pSrc = (unsigned char*)src;
|
|
size_t dwSrcSize = size;
|
|
size_t dwDestSize = 0;
|
|
unsigned char ch;
|
|
|
|
while (dwSrcSize >= 1)
|
|
{
|
|
/* 1 input */
|
|
ch = *pSrc++;
|
|
dwSrcSize -= BASE16_INPUT;
|
|
|
|
/* 2 outputs */
|
|
*dest++ = BASE16_TABLE[ (ch & 0xf0) >> 4 ];
|
|
*dest++ = BASE16_TABLE[ (ch & 0x0f) ];
|
|
dwDestSize += BASE16_OUTPUT;
|
|
}
|
|
*dest++ = '\x0'; /*append terminator*/
|
|
|
|
return dwDestSize;
|
|
}
|
|
else
|
|
return 0; /*ERROR - null pointer*/
|
|
}
|
|
|
|
/****************************** Base32 Encoding ******************************/
|
|
|
|
static const size_t BASE32_INPUT = 5;
|
|
static const size_t BASE32_OUTPUT = 8;
|
|
static const char* const BASE32_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=";
|
|
|
|
size_t cyoBase32EncodeGetLength( size_t size )
|
|
{
|
|
return cyoBaseXXEncodeGetLength( size, BASE32_INPUT, BASE32_OUTPUT );
|
|
}
|
|
|
|
size_t cyoBase32Encode( char* dest, const void* src, size_t size )
|
|
{
|
|
/*
|
|
* output 8 bytes for every 5 input:
|
|
*
|
|
* inputs: 1 2 3 4 5
|
|
* outputs: 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)
|
|
{
|
|
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)
|
|
{
|
|
/* Encode inputs */
|
|
dwBlockSize = (dwSrcSize < BASE32_INPUT ? dwSrcSize : BASE32_INPUT);
|
|
n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = 0;
|
|
switch (dwBlockSize)
|
|
{
|
|
case 5:
|
|
n8 = (pSrc[ 4 ] & 0x1f);
|
|
n7 = ((pSrc[ 4 ] & 0xe0) >> 5);
|
|
case 4:
|
|
n7 |= ((pSrc[ 3 ] & 0x03) << 3);
|
|
n6 = ((pSrc[ 3 ] & 0x7c) >> 2);
|
|
n5 = ((pSrc[ 3 ] & 0x80) >> 7);
|
|
case 3:
|
|
n5 |= ((pSrc[ 2 ] & 0x0f) << 1);
|
|
n4 = ((pSrc[ 2 ] & 0xf0) >> 4);
|
|
case 2:
|
|
n4 |= ((pSrc[ 1 ] & 0x01) << 4);
|
|
n3 = ((pSrc[ 1 ] & 0x3e) >> 1);
|
|
n2 = ((pSrc[ 1 ] & 0xc0) >> 6);
|
|
case 1:
|
|
n2 |= ((pSrc[ 0 ] & 0x07) << 2);
|
|
n1 = ((pSrc[ 0 ] & 0xf8) >> 3);
|
|
break;
|
|
|
|
default:
|
|
assert( 0 );
|
|
}
|
|
pSrc += dwBlockSize;
|
|
dwSrcSize -= dwBlockSize;
|
|
|
|
/* Validate */
|
|
assert( n1 <= 31 );
|
|
assert( n2 <= 31 );
|
|
assert( n3 <= 31 );
|
|
assert( n4 <= 31 );
|
|
assert( n5 <= 31 );
|
|
assert( n6 <= 31 );
|
|
assert( n7 <= 31 );
|
|
assert( n8 <= 31 );
|
|
|
|
/* Padding */
|
|
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 );
|
|
}
|
|
|
|
/* 8 outputs */
|
|
*dest++ = BASE32_TABLE[ n1 ];
|
|
*dest++ = BASE32_TABLE[ n2 ];
|
|
*dest++ = BASE32_TABLE[ n3 ];
|
|
*dest++ = BASE32_TABLE[ n4 ];
|
|
*dest++ = BASE32_TABLE[ n5 ];
|
|
*dest++ = BASE32_TABLE[ n6 ];
|
|
*dest++ = BASE32_TABLE[ n7 ];
|
|
*dest++ = BASE32_TABLE[ n8 ];
|
|
dwDestSize += BASE32_OUTPUT;
|
|
}
|
|
*dest++ = '\x0'; /*append terminator*/
|
|
|
|
return dwDestSize;
|
|
}
|
|
else
|
|
return 0; /*ERROR - null pointer*/
|
|
}
|
|
|
|
/****************************** Base64 Encoding ******************************/
|
|
|
|
static const size_t BASE64_INPUT = 3;
|
|
static const size_t BASE64_OUTPUT = 4;
|
|
static const char* const BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
|
|
|
size_t cyoBase64EncodeGetLength( size_t size )
|
|
{
|
|
return cyoBaseXXEncodeGetLength( size, BASE64_INPUT, BASE64_OUTPUT );
|
|
}
|
|
|
|
size_t cyoBase64Encode( char* dest, const void* src, size_t size )
|
|
{
|
|
/*
|
|
* output 4 bytes for every 3 input:
|
|
*
|
|
* inputs: 1 2 3
|
|
* outputs: 1 = --111111 = 111111--
|
|
* 2 = --22XXXX = ------22 XXXX----
|
|
* 3 = --3333XX = ----3333 XX------
|
|
* 4 = --444444 = --444444
|
|
*/
|
|
|
|
if (dest && src)
|
|
{
|
|
unsigned char* pSrc = (unsigned char*)src;
|
|
size_t dwSrcSize = size;
|
|
size_t dwDestSize = 0;
|
|
size_t dwBlockSize = 0;
|
|
unsigned char n1, n2, n3, n4;
|
|
|
|
while (dwSrcSize >= 1)
|
|
{
|
|
/* Encode inputs */
|
|
dwBlockSize = (dwSrcSize < BASE64_INPUT ? dwSrcSize : BASE64_INPUT);
|
|
n1 = n2 = n3 = n4 = 0;
|
|
switch (dwBlockSize)
|
|
{
|
|
case 3:
|
|
n4 = (pSrc[ 2 ] & 0x3f);
|
|
n3 = ((pSrc[ 2 ] & 0xc0) >> 6);
|
|
case 2:
|
|
n3 |= ((pSrc[ 1 ] & 0x0f) << 2);
|
|
n2 = ((pSrc[ 1 ] & 0xf0) >> 4);
|
|
case 1:
|
|
n2 |= ((pSrc[ 0 ] & 0x03) << 4);
|
|
n1 = ((pSrc[ 0 ] & 0xfc) >> 2);
|
|
break;
|
|
|
|
default:
|
|
assert( 0 );
|
|
}
|
|
pSrc += dwBlockSize;
|
|
dwSrcSize -= dwBlockSize;
|
|
|
|
/* Validate */
|
|
assert( n1 <= 63 );
|
|
assert( n2 <= 63 );
|
|
assert( n3 <= 63 );
|
|
assert( n4 <= 63 );
|
|
|
|
/* Padding */
|
|
switch (dwBlockSize)
|
|
{
|
|
case 1: n3 = 64;
|
|
case 2: n4 = 64;
|
|
case 3:
|
|
break;
|
|
|
|
default:
|
|
assert( 0 );
|
|
}
|
|
|
|
/* 4 outputs */
|
|
*dest++ = BASE64_TABLE[ n1 ];
|
|
*dest++ = BASE64_TABLE[ n2 ];
|
|
*dest++ = BASE64_TABLE[ n3 ];
|
|
*dest++ = BASE64_TABLE[ n4 ];
|
|
dwDestSize += BASE64_OUTPUT;
|
|
}
|
|
*dest++ = '\x0'; /*append terminator*/
|
|
|
|
return dwDestSize;
|
|
}
|
|
else
|
|
return 0; /*ERROR - null pointer*/
|
|
}
|