ソフトウェア開発 Win32プログラミング

Base64デコード

戻る


与えられたBase64文字列を元のデータにデコードするコードは以下の通り。

#include <windows.h>
#if !defined(NDEBUG) && !defined(DEBUG)
#define NDEBUG
#endif
#include <assert.h>

static const BYTE base64_table[0x100] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF,   62, 0xFF, 0xFF, 0xFF,   63,
  52,   53,   54,   55,   56,   57,   58,   59,
  60,   61, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF,    0,    1,    2,    3,    4,    5,    6,
   7,    8,    9,   10,   11,   12,   13,   14,
  15,   16,   17,   18,   19,   20,   21,   22,
  23,   24,   25, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   0,   26,   27,   28,   29,   30,   31,   32,
  33,   34,   35,   36,   37,   38,   39,   40,
  41,   42,   43,   44,   45,   46,   47,   48,
  49,   50,   51, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

INT Base64DecodeSize(LPCSTR pszSrc, INT cchSrc)
{
    INT cchDest, cch = 0;
    while(cchSrc--)
    {
        if (*pszSrc == '=')
            break;
        if (base64_table[(BYTE)*pszSrc++] != (BYTE)0xFF)
            cch++;
    }
    cchDest = cch / 4 * 3;
    switch(cch % 4)
    {
    case 1: case 2:
        cchDest++;
        break;

    case 3:
        cchDest += 2;
        break;
    }
    return cchDest;
}

INT Base64Decode(LPBYTE pbDest, LPCSTR pszSrc, INT cchSrc)
{
    INT i, j, n, cchDest, cch;
    BYTE b;

    cch = 0;
    for(i = 0; i < cchSrc; i++)
    {
        if (pszSrc[i] == '=')
            break;
        if (base64_table[(BYTE)pszSrc[i]] != (BYTE)0xFF)
            cch++;
    }

    cchDest = cch / 4 * 3;
    switch(cch % 4)
    {
    case 1: case 2:
        cchDest++;
        break;

    case 3:
        cchDest += 2;
        break;
    }

#ifdef DEBUG
    LPBYTE pbSave = pbDest;
#endif
    for(i = 0; i < cch / 4 * 4; i += 4)
    {
        for(j = n = 0; j < 4; )
        {
            b = base64_table[(BYTE)*pszSrc++];
            if (b != (BYTE) 0xFF)
            {
                n |= (((INT)b) << ((3 - j) * 6));
                j++;
            }
        }
        for(j = 0; j < 3; j++)
            *pbDest++ = (BYTE) ((n >> (8 * (2 - j))) & 0xFF);
    }
    for(j = n = 0; j < cch % 4; )
    {
        b = base64_table[(BYTE)*pszSrc++];
        if (b != (BYTE) 0xFF)
        {
            n |= (((INT)b) << ((3 - j) * 6));
            j++;
        }
    }
    for(j = 0; j < ((cch % 4) * 6 / 8); j++)
        *pbDest++ = (BYTE) ((n >> (8 * (2 - j))) & 0xFF);

    assert(pbDest - pbSave == cchDest);
    return cchDest;
}

#ifdef UNITTEST
#include <cstdio>
#include <new>  // for bad_alloc
using namespace std;

#define BUFSIZE 0x10000

class DataStream
{
    LPSTR m_p;
    INT m_size;
public:
    DataStream()
    {
        m_p = (LPSTR)malloc(1);
        if (m_p == NULL) throw bad_alloc();
        m_size = 0;
        m_p[m_size] = '\0';
    }
    ~DataStream() { if (m_p != NULL) free(m_p); }
    LPSTR Ptr() { return m_p; }
    INT Size() const { return m_size; }
    VOID Append(LPCVOID p, INT size)
    {
        m_p = (LPSTR)realloc(m_p, m_size + size + 1);
        if (m_p == NULL) throw bad_alloc();
        CopyMemory(m_p + m_size, p, size);
        m_size += size;
        m_p[m_size] = '\0';
    }
};

int main(int argc, char **argv)
{
    CHAR buf[BUFSIZE];
    INT n;
    FILE *fin, *fout;
    DataStream ds;

    if (argc <= 2)
    {
        fprintf(stderr,
            "base64de ver. 0.0 (base64 decoder)\n"
            "by Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>\n"
            "usage: base64de input_file output_file\n");
        return 0;
    }

    fin = fopen(argv[1], "rb");
    if (fin == NULL)
    {
        fprintf(stderr, "base64de: cannot open input file: %s\n", argv[1]);
        return 2;
    }
    try
    {
        while((n = fread(buf, 1, BUFSIZE, fin)) != 0)
        {
            ds.Append(buf, n);
        }
    }
    catch(bad_alloc ba)
    {
        fclose(fin);
        fprintf(stderr, "base64de: out of memory\n");
        return 1;
    }
    fclose(fin);

    INT size = Base64DecodeSize(ds.Ptr(), ds.Size());
    LPBYTE pb = new BYTE[size];
    Base64Decode(pb, ds.Ptr(), ds.Size());

    fout = fopen(argv[2], "wb");
    if (fout == NULL)
    {
        fprintf(stderr, "base64de: cannot open output file: %s\n", argv[2]);
        return 3;
    }

    fwrite(pb, size, 1, fout);
    delete[] pb;
    fclose(fout);

    return 0;
}
#endif  // def UNITTEST

ソース: base64de.zip


戻る

©片山博文MZ
katayama.hirofumi.mz@gmail.com

inserted by FC2 system