📄 cyodecode.cpp
字号:
//////////////////////////////////////////////////////////////////////
//
// CyoDecode.cpp
//
// Developed by Graham Bull for Cyotec Systems Limited.
// http://www.cyotec.com
//
// Copyright (c) 2004 by Cyotec Systems Limited. All Rights Reserved.
//
// This source code may be used, modified, compiled, duplicated, and/or
// distributed without restriction provided this copyright notice remains intact.
// Cyotec Systems Limited and/or its employees cannot be held responsible for any
// direct or indirect damage or loss of any kind that may result from using this
// code, and provides no warranty, guarantee, or support.
//
// Associated Files
// - CyoDecode.h
// - CyoEncode.h
// - CyoEncode.cpp
//
// History
// - September 22, 2004 - Created
// - November 04, 2004 - Not strictly ANSI compatible!
//
//////////////////////////////////////////////////////////////////////
#include "CyoDecode.h"
#include <stdexcept> //for std::runtime_error
#include <assert.h> //for assert()
typedef unsigned char BYTE, *LPBYTE;
typedef unsigned long DWORD;
typedef const char* LPCSTR;
////////////////////////////////////////
// Constants
namespace CyoDecode
{
DWORD BASE16_INPUT = 2;
DWORD BASE16_OUTPUT = 1;
BYTE 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
};
DWORD BASE32_INPUT = 8;
DWORD BASE32_OUTPUT = 5;
BYTE 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')
};
DWORD BASE64_INPUT = 4;
DWORD BASE64_OUTPUT = 3;
BYTE 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'
};
const char* c_pszErrorInvalidParameter = "Invalid parameter";
const char* c_pszErrorNotMultipleOf2 = "Invalid source, size is not a multiple of 2";
const char* c_pszErrorNotMultipleOf4 = "Invalid source, size is not a multiple of 4";
const char* c_pszErrorNotMultipleOf8 = "Invalid source, size is not a multiple of 8";
}
////////////////////////////////////////
// Base16 Decoding
unsigned long CyoDecode::Base16DecodeGetLength( unsigned long size )
{
// output 1 byte for every 2 input:
// 1
// 1 = ----1111 = 1111----
// 2 = ----1111 = ----1111
if (size % BASE16_INPUT != 0)
throw std::runtime_error( c_pszErrorNotMultipleOf2 );
return (((size + BASE16_INPUT - 1) / BASE16_INPUT) * BASE16_OUTPUT);
}
unsigned long CyoDecode::Base16Decode( void* dest, const void* src, unsigned long size )
{
if ((dest == NULL) || (src == NULL))
throw std::runtime_error( c_pszErrorInvalidParameter );
if (size % BASE16_INPUT != 0)
throw std::runtime_error( c_pszErrorNotMultipleOf2 );
///
LPBYTE pSrc = (LPBYTE)src;
LPBYTE pDest = (LPBYTE)dest;
DWORD dwSrcSize = size;
DWORD dwDestSize = 0;
while (dwSrcSize >= 1)
{
// 2 inputs...
BYTE in1 = *pSrc++;
BYTE in2 = *pSrc++;
dwSrcSize -= BASE16_INPUT; //2
// Validate ascii...
assert( 0 <= in1 && in1 <= 0x7f );
assert( 0 <= in2 && in2 <= 0x7f );
// Convert ascii to base16...
in1 = BASE16_TABLE[ in1 ];
in2 = BASE16_TABLE[ in2 ];
// Validate base16...
assert( in1 != 0xff );
assert( 0 <= in1 && in1 <= 15 );
assert( 0 <= in2 && in2 <= 15 );
// 1 output...
*pDest++ = ((in1 << 4) | in2);
dwDestSize += BASE16_OUTPUT; //1
}
return dwDestSize;
}
////////////////////////////////////////
// Base32 Decoding
unsigned long CyoDecode::Base32DecodeGetLength( unsigned long size )
{
// output 5 bytes for every 8 input:
// 1 2 3 4 5
// 1 = ---11111 = 11111---
// 2 = ---111XX = -----111 XX------
// 3 = ---11111 = --11111-
// 4 = ---1XXXX = -------1 XXXX----
// 5 = ---1111X = ----1111 X-------
// 6 = ---11111 = -11111--
// 7 = ---11XXX = ------11 XXX-----
// 8 = ---11111 = ---11111
if (size % BASE32_INPUT != 0)
throw std::runtime_error( c_pszErrorNotMultipleOf8 );
return (((size + BASE32_INPUT - 1) / BASE32_INPUT) * BASE32_OUTPUT);
}
unsigned long CyoDecode::Base32Decode( void* dest, const void* src, unsigned long size )
{
if ((dest == NULL) || (src == NULL))
throw std::runtime_error( c_pszErrorInvalidParameter );
if (size % BASE32_INPUT != 0)
throw std::runtime_error( c_pszErrorNotMultipleOf8 );
///
LPBYTE pSrc = (LPBYTE)src;
LPBYTE pDest = (LPBYTE)dest;
DWORD dwSrcSize = size;
DWORD dwDestSize = 0;
while (dwSrcSize >= 1)
{
// 8 inputs...
BYTE in1 = *pSrc++;
BYTE in2 = *pSrc++;
BYTE in3 = *pSrc++;
BYTE in4 = *pSrc++;
BYTE in5 = *pSrc++;
BYTE in6 = *pSrc++;
BYTE in7 = *pSrc++;
BYTE in8 = *pSrc++;
dwSrcSize -= BASE32_INPUT; //8
// Validate ascii...
assert( 0 <= in1 && in1 <= 0x7f );
assert( 0 <= in2 && in2 <= 0x7f );
assert( 0 <= in3 && in3 <= 0x7f );
assert( 0 <= in4 && in4 <= 0x7f );
assert( 0 <= in5 && in5 <= 0x7f );
assert( 0 <= in6 && in6 <= 0x7f );
assert( 0 <= in7 && in7 <= 0x7f );
assert( 0 <= in8 && in8 <= 0x7f );
// 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...
assert( in1 != 0xff );
assert( in2 != 0xff );
assert( in3 != 0xff );
assert( in4 != 0xff );
assert( in5 != 0xff );
assert( in6 != 0xff );
assert( in7 != 0xff );
assert( in8 != 0xff );
assert( 0 <= in1 && in1 <= 31 );
assert( 0 <= in2 && in2 <= 31 );
assert( 0 <= in3 && in3 <= 32 ); //possible padding
assert( 0 <= in4 && in4 <= 32 ); //possible padding
assert( 0 <= in5 && in5 <= 32 ); //possible padding
assert( 0 <= in6 && in6 <= 32 ); //possible padding
assert( 0 <= in7 && in7 <= 32 ); //possible padding
assert( 0 <= in8 && in8 <= 32 ); //possible padding
// 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; //5
//6 4 3 1
// Padding...
if (in8 == 32)
{
--dwDestSize;
assert( (in7 == 32 && in6 == 32) || (in7 != 32) );
if (in6 == 32)
{
--dwDestSize;
if (in5 == 32)
{
--dwDestSize;
assert( (in4 == 32 && in3 == 32) || (in4 != 32) );
if (in3 == 32)
{
--dwDestSize;
}
}
}
}
}
return dwDestSize;
}
////////////////////////////////////////
// Base64 Decoding
unsigned long CyoDecode::Base64DecodeGetLength( unsigned long size )
{
// output 3 bytes for every 4 input:
// 1 2 3
// 1 = --111111 = 111111--
// 2 = --11XXXX = ------11 XXXX----
// 3 = --1111XX = ----1111 XX------
// 4 = --111111 = --111111
if (size % BASE64_INPUT != 0)
throw std::runtime_error( c_pszErrorNotMultipleOf4 );
return (((size + BASE64_INPUT - 1) / BASE64_INPUT) * BASE64_OUTPUT);
}
unsigned long CyoDecode::Base64Decode( void* dest, const void* src, unsigned long size )
{
if ((dest == NULL) || (src == NULL))
throw std::runtime_error( c_pszErrorInvalidParameter );
if (size % BASE64_INPUT != 0)
throw std::runtime_error( c_pszErrorNotMultipleOf4 );
///
LPBYTE pSrc = (LPBYTE)src;
LPBYTE pDest = (LPBYTE)dest;
DWORD dwSrcSize = size;
DWORD dwDestSize = 0;
while (dwSrcSize >= 1)
{
// 4 inputs...
BYTE in1 = *pSrc++;
BYTE in2 = *pSrc++;
BYTE in3 = *pSrc++;
BYTE in4 = *pSrc++;
dwSrcSize -= BASE64_INPUT; //4
// Validate ascii...
assert( 0 <= in1 && in1 <= 0x7f );
assert( 0 <= in2 && in2 <= 0x7f );
assert( 0 <= in1 && in3 <= 0x7f );
assert( 0 <= in2 && in4 <= 0x7f );
// Convert ascii to base16...
in1 = BASE64_TABLE[ in1 ];
in2 = BASE64_TABLE[ in2 ];
in3 = BASE64_TABLE[ in3 ];
in4 = BASE64_TABLE[ in4 ];
// Validate base16...
assert( in1 != 0xff );
assert( in2 != 0xff );
assert( in3 != 0xff );
assert( in4 != 0xff );
assert( 0 <= in1 && in1 <= 63 );
assert( 0 <= in2 && in2 <= 63 );
assert( 0 <= in3 && in3 <= 64 ); //possible padding
assert( 0 <= in4 && in4 <= 64 ); //possible padding
// 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; //3
// Padding...
if (in4 == 64)
{
--dwDestSize;
if (in3 == 64)
{
--dwDestSize;
}
}
}
return dwDestSize;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -