本記事はクソアプリ2 Advent Calendar 2020の24日目の記事です。
Hannya64
https://inabajunmr.github.io/Hannya64/
デモ
Base64の実装
注意
- 筆者は普段こういうコードを全く書かないので、なんか間違ってたら教えて下さい
- 効率とかは全然意識してないです
- パディングとかURLエンコードの話とかはないです
基本的な方針
バイト列を先頭から3バイト取り出し、6ビット4つに変換する。6ビット(0〜63)を、文字列にマッピングしていく。
こちらを参考にさせてもらいました。
Algorithm Implementation/Miscellaneous/Base64 - Wikibooks, open books for an open world
実装
エンコード前のバイト配列を以下とする。
10000000 11000000 11100000 11110000 11111000 11111100
3バイトずつ処理する。最初は先頭の3バイトを処理する。
10000000 11000000 11100000
3バイトをくっつけて24ビットにする。 まず1バイト目を16ビット左シフトする。
10000000 << 16
結果右に0が16個くっついて以下になる。
<--------------- 100000000000000000000000
2バイト目を8ビット左シフトする。
<------- 000000001100000000000000
3バイト目はそのまま。
000000000000000011100000
1つ目と2つ目をORでつなぐ。
100000000000000000000000 | 000000001100000000000000
ビット演算子のORは、いずれかが1だったら1になるので、以下のようになる。
100000001100000000000000
つないだ結果と3つ目もORでつなぐ。
100000001100000000000000 | 000000000000000011100000
結果、24ビットの列ができる。
100000001100000011100000
24ビットの列を18ビット右シフトして6ビット取り出す。
100000001100000011100000 >> 18
右シフトすると、左から0が詰められて右側のビットはあふれて消えるので、以下のようになる。
-----------------> 000000000000000000100000
24ビットの列を12ビット右シフトして次の6ビットを取り出す。
-----------> 000000000000100000001100
001100
だけを取り出したいので、111111
とANDで右から6桁だけ取り出す。
000000000000100000001100 & 000000000000000000111111
ANDは両方とも1だった時だけ1になるので以下になる。
000000000000000000001100
同じようにして次の6ビットも取り出す。
100000001100000011100000 >> 6 & 000000000000000000111111
最後の6ビットも同様に取り出す。最初の24ビットのうち、最後の6ビットを取り出せばよいので右シフトは不要となる。
100000001100000011100000 & 000000000000000000111111
この結果、この3バイトが
10000000 11000000 11100000
6ビット4つに変換できる。
100000 001100 000011 100000
6ビットなので、ここで得たそれぞれの値は000000(0)から111111(63)の64パターンになる。 10進数に変換すると以下になる。
32 12 3 32
以下のような文字列を用意する。
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
A
が0で、/
が63として文字列のインデックスと数値の対応を変換すると以下になる。
gMDg
残った3バイトも同じ方法で変換していくと以下になる。
gMDg8Pj8