C言語にてバイナリデータを Base64 文字列に変換する

Base64 は電子メールに画像を添付する際に用いられる変換形式です。
RFC 4648で標準化されている。

wikipedia: Base64

RFC 4648 - The Base16, Base32, and Base64 Data Encodings

仕様はシンプルなので仕様とおりに作ればよいが。 6ビット毎に変換するので、C言語で実装するのは、面倒です。

ここは先人の知恵に頼ることにする。
下記にあるコードをそのまま借用する。

qiita: CでBASE64のエンコード/デコードを行う関数

char *base64Encode(const char *data, const size_t size, const BASE64_TYPE type)  
{  
    BASE64_SPEC spec;  
    size_t length;  
    char *base64;  
    char *cursor;  
    int lineLength;  
    int i;  
    int j;  
    if (data == NULL) {  
        return NULL;  
    }  
    spec = BASE64_SPECS[0];  
    for (i = 0; i < (int)BASE64_SPECS_LENGTH; i++) {  
        if (BASE64_SPECS[i].type == type) {  
            spec = BASE64_SPECS[i];  
            break;  
        }  
    }  
    length = size * 4 / 3 + 3 + 1;  
    if (spec.maxLineLength > 0) {  
        length += size / spec.maxLineLength * spec.lineSepLength;  
    }  
    base64 = malloc(length);  
    if (base64 == NULL) {  
        return NULL;  
    }  
    cursor = base64;  
    lineLength = 0;  
    for (i = 0, j = size; j > 0; i += 3, j -= 3) {  
        if (spec.maxLineLength > 0) {  
            if (lineLength >= spec.maxLineLength) {  
                char *sep;  
                for (sep = spec.lineSep; *sep != 0; sep++) {  
                    *(cursor++) = *sep;  
                }  
                lineLength = 0;  
            }  
            lineLength += 4;  
        }  
        if (j == 1) {  
            *(cursor++) = spec.table[(data[i + 0] >> 2 & 0x3f)];  
            *(cursor++) = spec.table[(data[i + 0] << 4 & 0x30)];  
            *(cursor++) = spec.pad;  
            *(cursor++) = spec.pad;  
        }  
        else if (j == 2) {  
            *(cursor++) = spec.table[(data[i + 0] >> 2 & 0x3f)];  
            *(cursor++) = spec.table[(data[i + 0] << 4 & 0x30) | (data[i + 1] >> 4 & 0x0f)];  
            *(cursor++) = spec.table[(data[i + 1] << 2 & 0x3c)];  
            *(cursor++) = spec.pad;  
        }  
        else {  
            *(cursor++) = spec.table[(data[i + 0] >> 2 & 0x3f)];  
            *(cursor++) = spec.table[(data[i + 0] << 4 & 0x30) | (data[i + 1] >> 4 & 0x0f)];  
            *(cursor++) = spec.table[(data[i + 1] << 2 & 0x3c) | (data[i + 2] >> 6 & 0x03)];  
            *(cursor++) = spec.table[(data[i + 2] << 0 & 0x3f)];  
        }  
    }  
    *cursor = 0;  
    return base64;  
}  

やはり難しいので、コード解説はしない。

サンプルコードを Guthub に公開した。
https://github.com/ohwada/MAC_cpp_Samples/tree/master/binary/base64