C

거믄마루 2013. 1. 9. 14:48

직접 작성한 BASE64 를 엔코딩하는 코드

다음과 같은 정의가 필요하다.

decode 는 난이도가 높지도 않고 필요하지 않아서 작성하지 않았다.

코드를 사용할때는 출처를 반드시 밝히기 바란다.


#define FAIL -1

#define SUCCESS 0

#define IN

#define OUT



 int
base64_encode(IN char *buf, IN int bufsz, OUT char *obuf, OUT int obufsz, IN int width)
{
    int i;
    int compsz = 0;
    int encoded = 0;
    int crlfs = 0;
    int remain;
    static const char *base64 =
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "abcdefghijklmnopqrstuvwxyz"
            "0123456789"
            "+/"
            ;
    int idx;

    if (buf == NULL)
    {
        return FAIL;
    }

    if (bufsz < 0)
    {
        return FAIL;
    }

    if (obuf == NULL)
    {
        return FAIL;
    }

    if (obufsz < 1)
    {
        return FAIL;
    }

    compsz = ((bufsz / 3) + ((bufsz % 3) ? 1 : 0)) * 4;

    if (width > 0)
    {
        if (width % 4)
        {
            return FAIL;
        }

        crlfs = ((compsz / width) + ((compsz % width) ? 1 : 0)) * 2;

        if (obufsz <= (compsz + crlfs))
        {
            return FAIL;
        }
    }
    else if (width == 0)
    {
        if (obufsz <= compsz)
        {
            return FAIL;
        }
    }
    else
    {
        return FAIL;
    }

    encoded = 0;

    for (i = 0; i < bufsz; i += 3)
    {
        encoded += 4;
        remain = bufsz - i;

        idx = ((buf[0] & 0xFC) >> 2);
        obuf[0] = base64[idx];

        idx = ((buf[0] & 0x03) << 4);
        if (remain > 1)
        {
            idx |= ((buf[1] & 0xF0) >> 4);
        }
        obuf[1] = base64[idx];

        obuf[2] = '=';
        if (remain > 1)
        {
            idx = ((buf[1] & 0x0F) << 2);
            obuf[2] = base64[idx];
        }
        if (remain > 2)
        {
            idx |= ((buf[2] & 0xC0) >> 6);
            obuf[2] = base64[idx];
        }

        obuf[3] = '=';
        if (remain > 2)
        {
            idx = (buf[2] & 0x3F);
            obuf[3] = base64[idx];
        }

        obuf += 4;
        buf += 3;

        if (width > 0 && ((encoded % width) == 0 || remain <= 3))
        {
            obuf[0] = '\r';
            obuf[1] = '\n';
            obuf += 2;
        }
    }

    *obuf = 0;

    return SUCCESS;
}


사용법을 간단히 설명하면


입력값 설명:

    buf: 입력버퍼

    bufsz: 엔코딩할 데이터의 크기, 즉, 바이너리를 처리할 수 있도록 설계됨 

    obuf: 출력버퍼

    obufsz: 출력버퍼의 크기, 함수에서 필요한 크기보다 출력버퍼의 크기가 작다면 에러가 발생할 것이다.

    width: 라인크기, 0보다 큰 4의 배수를 입력해야 한다, 0을 입력하면 라인크기는 무한대가 된다. 

        -- 4의 배수를 입력하지 않으면 에러가 발생할 것이다. 4의 배수가 아니면 자동으로 4의 배수로 보정하는 개선을 생각해 볼 수는 있겠다.  그런건 각자 알아서...


반환값 설명:

    0 이면 성공으로 입력버퍼 buf 의 내용은 완전하게 변환되어 출력버퍼 obuf 로 보내진 상태이다, 그 이외의 경우에는 모두 에러 -1를 반환한다.


입력값들이 정상이면 위 함수는 입력버퍼의 내용을 BASE64 방식으로 엔코딩하여 출력버퍼로 보낸다. 그리고 출력버퍼의 마지막은 NULL 바이트로 끝낸다.


질문 환영~