Visual C++ in Short: Encoding and decoding with Base64

Base64 is a popular encoding to convert arbitrary data into a format that can be transmitted as an ASCII string. ATL provides a few functions that implement the Base64 specification.

To encode with Base64, start by allocating a buffer large enough to hold the Base64 string. The Base64EncodeGetRequiredLength function calculates how much space is required. The result of this function may be slightly larger than the actual Base64 string as it favors performance over accuracy.

The Base64Encode function performs the actual encoding. Its first two parameters specify the data to encode as well as the length in bytes. The third parameter identifies the destination buffer for the character string. The fourth parameter is an in/out parameter that on input specifies the size of the destination buffer and on output specifies the actual length of the Base64 string.

The following helper function wraps this logic and uses ATL’s string class to properly allocate and truncate the Base64 string buffer:

CStringA ToBase64(const void* bytes, int byteLength)
{
    ASSERT(0 != bytes);

    CStringA base64;
    int base64Length = Base64EncodeGetRequiredLength(byteLength);

    VERIFY(Base64Encode(static_cast<const BYTE*>(bytes),
                        byteLength,
                        base64.GetBufferSetLength(base64Length),
                        &base64Length));

    base64.ReleaseBufferSetLength(base64Length);
    return base64;
}

To decode with Base64, start by allocating a buffer large enough to hold the decoded data. If the data can have a variable length you can just allocate a byte array that is the same length as the Base64 string since the decoded data will always be somewhat smaller. ATL provides the Base64DecodeGetRequiredLength function but it simply returns its argument.

The Base64Decode function performs the actual decoding. Its first two parameters specify the Base64 string and its length. The third parameter identifies the destination buffer for the decoded data. The fourth parameter is an in/out parameter that on input specifies the size of the destination buffer and on output specifies the actual length of the decoded data.

The following example shows how to encode and decode the SYSTEM_INFO data structure:

#include <atlenc.h>
#include <atlstr.h>

#define ASSERT ATLASSERT
#define VERIFY ATLVERIFY

CStringA ToBase64(const void* bytes, int byteLength);

int main()
{
    SYSTEM_INFO info1 = { 0 };
    ::GetNativeSystemInfo(&info1);

    const CStringA base64 = ToBase64(&info1, sizeof(SYSTEM_INFO));

    SYSTEM_INFO info2 = { 0 };
    int byteLength = Base64DecodeGetRequiredLength(sizeof(SYSTEM_INFO));

    if (!Base64Decode(base64, base64.GetLength(), reinterpret_cast<BYTE*>(&info2), &byteLength))
    {
        // The string could not be decoded.
    }

    ASSERT(sizeof(SYSTEM_INFO) == byteLength);
    ASSERT(0 == memcmp(&info1, &info2, sizeof(SYSTEM_INFO)));
}

If you’re looking for one of my previous articles here is a complete list of them for you to browse through.

Produce the highest quality screenshots with the least amount of effort! Use Window Clippings.

No Comments