オモチャBase64

某所にてCでBase64を実装しようとしているのを見て、ふと思ったので書いてみた。これ、Wikipediaの説明を参考に実装すると一旦全部配列に詰め込んで、それを変換してみたいなことしがちなのだけど、配列に入れる必要はなくて、要は入ってきた8bitを6bitで出すだけなんだよな。…とか思いましたとさ。

(バッファ無しだとパフォーマンスは悪いとは思うけども)

/* -*- Mode: c; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- */

// gcc -Wall -std=c99 toybase64.c -o toybase64


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>

const char * const code_table =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/";

int main(void)
{
    int c;
    size_t data_sz = 0;
    uint16_t data = 0;
    size_t outlen = 0;

    while ((c = fgetc(stdin)) != EOF) {
        data_sz += 8;
        data = (data << 8) | c;

        assert(data_sz <= 12);
        do {
            fputc(code_table[(data >> (data_sz - 6)) & 0x3f], stdout);
            outlen += 1;
            data_sz -= 6;
            data &= (1 << data_sz) - 1;
        } while (data_sz >= 6);
        assert(data < 64);
        assert(data_sz < 6);

        if (ferror(stdout) || ferror(stdin)) {
            exit(EXIT_FAILURE);
        }
    }
    if (data_sz != 0) {
        data <<= 6 - data_sz;
        fputc(code_table[data], stdout);
        outlen += 1;
    }
    if (outlen % 4) {
        for (size_t i = 0; i < (4 - (outlen % 4)); i++) {
            fputc('=', stdout);
        }
    }
    fputc('\n', stdout);
    return (ferror(stdout) || ferror(stdin)) ? EXIT_FAILURE : EXIT_SUCCESS;
}

Contents © 2017 sharow - Powered by Nikola