|
|
//+--------------------------------------------------------------------------
//
// Copyright (c) 1997-1999 Microsoft Corporation
//
// File:
//
// Contents:
//
// History:
//
//---------------------------------------------------------------------------
#include <windows.h>
#include <assert.h>
#include <math.h>
class CDataCoding { private: DWORD m_dwBaseDigits;
DWORD m_dwEncodedLength; DWORD m_dwInputDataBits; DWORD m_dwInputDataBytes;
DWORD m_dwDecodedLength; DWORD m_dwInputEncDataBytes; DWORD m_dwDecodedBits;
TCHAR * m_tpBaseDigits; public: CDataCoding(TCHAR * tpBaseDigits = NULL);
void SetInputDataBitLen(DWORD dwBits); void SetInputEncDataLen(DWORD dwChars); DWORD SetBaseDigits(TCHAR * tpBaseDigits); DWORD EncodeData(LPBYTE pbSource, //[IN] Stream of Bytes to be encoded
TCHAR **pbEncodedData); //[OUT] Pointer to a string containing the encoded data
DWORD DecodeData(TCHAR * pbEncodedData, LPBYTE * pbDecodedData);
~CDataCoding(); };
class CBase24Coding : public CDataCoding { public: CBase24Coding(void) : CDataCoding(L"BCDFGHJKMPQRTVWXY2346789") { return; } };
static CBase24Coding b24Global;
// **************************************************************
DWORD B24EncodeMSID(LPBYTE pbSource, TCHAR **pbEncodedData) { b24Global.SetInputDataBitLen(160);
return b24Global.EncodeData(pbSource, pbEncodedData); }
// ***************************************************************
DWORD B24DecodeMSID(TCHAR * pbEncodedData, LPBYTE * pbDecodedData) { b24Global.SetInputEncDataLen(35);
return b24Global.DecodeData(pbEncodedData, pbDecodedData); }
// ***********************************************************
DWORD B24EncodeCNumber(LPBYTE pbSource, TCHAR **pbEncodedData) { b24Global.SetInputDataBitLen(32);
return b24Global.EncodeData(pbSource, pbEncodedData); }
// ******************************************************************
DWORD B24DecodeCNumber(TCHAR * pbEncodedData, LPBYTE * pbDecodedData) { b24Global.SetInputEncDataLen(7);
return b24Global.DecodeData(pbEncodedData, pbDecodedData); }
// *******************************************************
DWORD B24EncodeSPK(LPBYTE pbSource, TCHAR **pbEncodedData) { b24Global.SetInputDataBitLen(114);
return b24Global.EncodeData(pbSource, pbEncodedData); }
// ******************************************************************
DWORD B24DecodeSPK(TCHAR * pbEncodedData, LPBYTE * pbDecodedData) { b24Global.SetInputEncDataLen(25);
return b24Global.DecodeData(pbEncodedData, pbDecodedData); }
// *****************************************
CDataCoding::CDataCoding(TCHAR * tpBaseDigits) { m_tpBaseDigits = NULL; m_dwBaseDigits = 0; m_dwEncodedLength = 0; m_dwInputDataBits = 0; m_dwInputDataBytes = 0; SetBaseDigits(tpBaseDigits); }
// ********************************************
void CDataCoding::SetInputDataBitLen(DWORD dwBits) { assert(dwBits > 0); assert(log(m_dwBaseDigits) > 0);
// Determine How many Characters would be required to encode the data
// What we have is a dwDataLength of Binary Data stream.
// So, we can represent 2^(dwDataLength*8) amount of information using these bits
// Assuming that our set of digits (which form the base for encoding) is X,
// the above number should then equal X^(NumberofEncoded Digits)
// So,
double dLength = ((double) dwBits*log10(2)) / ((double) log10(m_dwBaseDigits));
// Now round - up
m_dwEncodedLength = (DWORD) dLength;
if ((double) m_dwEncodedLength < dLength) { // There was a decimal part
m_dwEncodedLength++; } m_dwInputDataBits = dwBits; m_dwInputDataBytes = (dwBits / 8) + (dwBits % 8 ? 1 : 0);
return; }
// ***********************************************
void CDataCoding::SetInputEncDataLen(DWORD dwBytes) { assert(dwBytes > 0); assert(log(m_dwBaseDigits) > 0);
m_dwInputEncDataBytes = dwBytes; // Determine How many bits would be required to decode this data
// So,
double dLength = ((double) dwBytes*log10(m_dwBaseDigits))/ ((double) log10(2));
// Now round - up
m_dwDecodedBits = (DWORD) dLength;
if ((double) m_dwDecodedBits < dLength) { // There was a decimal part
m_dwDecodedBits++; }
m_dwDecodedLength = (m_dwDecodedBits / 8) + (m_dwDecodedBits % 8 ? 1 : 0);
return; }
// **************************************************
DWORD CDataCoding::SetBaseDigits(TCHAR * tpBaseDigits) { DWORD dwReturn = ERROR_SUCCESS;
if (tpBaseDigits != NULL) { DWORD dwLen = wcslen(tpBaseDigits); assert(dwLen > 0); m_tpBaseDigits = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (dwLen+1)*sizeof(TCHAR)); if (m_tpBaseDigits == NULL) { dwReturn = ERROR_NOT_ENOUGH_MEMORY; } else { memcpy(m_tpBaseDigits, tpBaseDigits, (dwLen+1)*sizeof(TCHAR)); m_dwBaseDigits = dwLen; } } else { if (m_tpBaseDigits != NULL) { HeapFree(GetProcessHeap(), 0, m_tpBaseDigits); m_tpBaseDigits = NULL; m_dwBaseDigits = 0; } assert(m_tpBaseDigits == NULL && m_dwBaseDigits == 0); }
return dwReturn; }
// ************************************************
DWORD CDataCoding::EncodeData(LPBYTE pbSource, //[IN] Stream of Bytes to be encoded
TCHAR **pbEncodedData) //[OUT] Pointer to a string containing the encoded data
// I allocate the Buffer, you should free it
{ assert(m_dwInputDataBits > 0); assert(m_dwInputDataBytes > 0); assert(m_dwEncodedLength > 0); assert(m_tpBaseDigits != NULL);
DWORD dwReturn = ERROR_SUCCESS; int nStartIndex = m_dwEncodedLength; *pbEncodedData = NULL; BYTE * pbDataToEncode = NULL; TCHAR * pbEncodeBuffer = NULL;
if (NULL == pbEncodedData) { dwReturn = ERROR_INVALID_PARAMETER; goto done; }
*pbEncodedData = NULL;
pbEncodeBuffer = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (m_dwEncodedLength+1)*sizeof(TCHAR)); if (pbEncodeBuffer == NULL) { dwReturn = ERROR_NOT_ENOUGH_MEMORY; goto done; }
// Now need to make a copy of the incoming data, so we can run the algorithm below
pbDataToEncode = (BYTE *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_dwInputDataBytes); if (pbDataToEncode == NULL) { dwReturn = ERROR_NOT_ENOUGH_MEMORY; goto done; } memcpy(pbDataToEncode, pbSource, m_dwInputDataBytes);
// Let us get rid of the simple stuff
pbEncodeBuffer[ nStartIndex--] = 0;
for (; nStartIndex >= 0; --nStartIndex) { unsigned int i = 0;
for (int nIndex = m_dwInputDataBytes-1; 0 <= nIndex; --nIndex) { i = (i * 256) + pbDataToEncode[nIndex]; pbDataToEncode[ nIndex] = (BYTE)(i / m_dwBaseDigits); i %= m_dwBaseDigits; } // i now contains the remainder, which is the current digit
pbEncodeBuffer[ nStartIndex] = m_tpBaseDigits[ i]; } assert(dwReturn == ERROR_SUCCESS); *pbEncodedData = pbEncodeBuffer;
done: if (pbDataToEncode != NULL) { HeapFree(GetProcessHeap(), 0, pbDataToEncode); }
if (dwReturn != ERROR_SUCCESS) { // There was an error, so free the memory that you allocated
if (pbEncodeBuffer != NULL) { HeapFree(GetProcessHeap(), 0, pbEncodeBuffer); } } return dwReturn; }
// *************************************************
DWORD CDataCoding::DecodeData(TCHAR * pbEncodedData, LPBYTE * pbDecodedData) // Again, I allocate the Buffer, you release it
{ assert(m_dwDecodedBits > 0); assert(m_dwDecodedLength > 0); assert(m_tpBaseDigits != NULL); assert((DWORD) lstrlen(pbEncodedData) == m_dwInputEncDataBytes);
DWORD dwReturn = ERROR_SUCCESS; TCHAR * tpTemp; DWORD dwDigit; unsigned int i; unsigned int nDecodedBytes, nDecodedBytesMax = 0; BYTE * pbDecodeBuffer = NULL;
if (NULL == pbDecodedData) { dwReturn = ERROR_INVALID_PARAMETER; goto done; }
*pbDecodedData = NULL;
pbDecodeBuffer = (BYTE *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_dwDecodedLength); if ( pbDecodeBuffer == NULL) { dwReturn = ERROR_NOT_ENOUGH_MEMORY; goto done; } memset(pbDecodeBuffer, 0, m_dwDecodedLength);
while (*pbEncodedData) { // First Find the position of this character in the Base Encoding Character Set
tpTemp = wcschr(m_tpBaseDigits, *pbEncodedData); if (tpTemp == NULL) { // Found a character which is not in base character set
// ERROR ERROR
dwReturn = ERROR_INVALID_DATA; goto done; } dwDigit = (DWORD)(tpTemp - m_tpBaseDigits);
nDecodedBytes = 0; i = (unsigned int) dwDigit;
while (nDecodedBytes <= nDecodedBytesMax) { i += m_dwBaseDigits * pbDecodeBuffer[ nDecodedBytes]; pbDecodeBuffer[ nDecodedBytes] = (unsigned char)i; i /= 256; ++nDecodedBytes; }
if (i != 0) { assert(nDecodedBytes < m_dwDecodedLength);
pbDecodeBuffer[ nDecodedBytes] = (unsigned char)i; nDecodedBytesMax = nDecodedBytes; }
pbEncodedData++; }
assert(dwReturn == ERROR_SUCCESS); *pbDecodedData = pbDecodeBuffer; done: if (dwReturn != ERROR_SUCCESS) { // There was an error, so free the memory that you allocated
if (pbDecodeBuffer != NULL) { HeapFree(GetProcessHeap(), 0, pbDecodeBuffer); } }
return dwReturn; }
// **********************
CDataCoding::~CDataCoding() { if (m_tpBaseDigits != NULL) { HeapFree(GetProcessHeap(), 0, m_tpBaseDigits); m_tpBaseDigits = NULL; m_dwBaseDigits = 0; } }
|