static STRING_HANDLE Base64_Encode_Internal()

in src/azure_base64.c [238:314]


static STRING_HANDLE Base64_Encode_Internal(const unsigned char* source, size_t size)
{
    STRING_HANDLE result;
    char* encoded;
    size_t currentPosition = 0;
    /*Codes_SRS_BASE64_06_006: [If when allocating memory to produce the encoding a failure occurs then Azure_Base64_Encode shall return NULL.]*/
    encoded = malloc_flex(1, (size == 0) ? 0 : (((size - 1) / 3) + 1), 4); /*base==1 because there's a '\0' added at the end of the string, nmemb = (((size - 1) / 3) + 1), each of them having 4 characters*/
    if (encoded == NULL)
    {
        /* Codes_SRS_BASE64_02_004: [ In case of any errors, Azure_Base64_Encode_Bytes shall return NULL. ]*/
        result = NULL;
        LogError("failure in malloc_flex(1, (size == 0) ? 0 : (((size=%zu - 1) / 3) + 1), 4).", size);
    }
    else
    {
        /*b0            b1(+1)          b2(+2)
        7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
        |----c1---| |----c2---| |----c3---| |----c4---|
        */

        size_t destinationPosition = 0;
        while (size - currentPosition >= 3)
        {
            char c1 = base64char(source[currentPosition] >> 2);
            char c2 = base64char(
                ((source[currentPosition] & 3) << 4) |
                    (source[currentPosition + 1] >> 4)
            );
            char c3 = base64char(
                ((source[currentPosition + 1] & 0x0F) << 2) |
                    ((source[currentPosition + 2] >> 6) & 3)
            );
            char c4 = base64char(
                source[currentPosition + 2] & 0x3F
            );
            currentPosition += 3;
            encoded[destinationPosition++] = c1;
            encoded[destinationPosition++] = c2;
            encoded[destinationPosition++] = c3;
            encoded[destinationPosition++] = c4;

        }
        if (size - currentPosition == 2)
        {
            char c1 = base64char(source[currentPosition] >> 2);
            char c2 = base64char(
                ((source[currentPosition] & 0x03) << 4) |
                    (source[currentPosition + 1] >> 4)
            );
            char c3 = base64b16(source[currentPosition + 1] & 0x0F);
            encoded[destinationPosition++] = c1;
            encoded[destinationPosition++] = c2;
            encoded[destinationPosition++] = c3;
            encoded[destinationPosition++] = '=';
        }
        else if (size - currentPosition == 1)
        {
            char c1 = base64char(source[currentPosition] >> 2);
            char c2 = base64b8(source[currentPosition] & 0x03);
            encoded[destinationPosition++] = c1;
            encoded[destinationPosition++] = c2;
            encoded[destinationPosition++] = '=';
            encoded[destinationPosition++] = '=';
        }

        /*null terminating the string*/
        encoded[destinationPosition] = '\0';
        /*Codes_SRS_BASE64_06_007: [Otherwise Azure_Base64_Encode shall return a pointer to STRING, that string contains the base 64 encoding of input.]*/
        result = STRING_new_with_memory(encoded);
        if (result == NULL)
        {
            free(encoded);
            LogError("Azure_Base64_Encode:: Allocation failed for return value.");
        }
    }
    return result;
}