0
0

[PHP] 可読性0の短めなbase64エンコード・デコード関数

Last updated at Posted at 2024-07-24

いろいろ改善した結果、ほぼ全部関数の中身が変わってしまったので、新しい記事に記入しました。
入力形式は同じになります。

また、この記事に乗っているコードは使わないでください。2024/09/07以降に発生した問題については、責任を負いません。

この記事は横幅が960px以上(PCなど)のデバイスで見ることをお勧めします。
(表を見る際にスマホだと見づらいです)

修正内容について、改訂版が上記にありますので省略します。

重要な修正をしました。
$b64Arrの宣言時、演算子"+"を使っていましたが、マージするときに数値添字配列であっても上書きされてしまうことがわかりました。
array_merge()を使用してください。
(参考: https://blog.umigame.tech/post/53/)

あいさつ

こんにちは、 codebydeer.com の UziDeer です。
今回はphpを2進にしたり+/=を取り除いたりの関数を、できるだけ短い(?)コードで書きました。
作った理由は、phpのbase64関連の関数があんまり充実していなく、軽く調べてみても冗長なものしか無かったということに加え、自分のコードの内容理解を深めようと思ったからです。
短く書こうと頑張ったら可読性が死にました(笑)

では見ていきましょう。


フォローしてくれたらうれしいな

書いたコード

phpのbase64関連関数たち => 改訂版に移動しました。
//修正しました
- $b64Arr = range("A", "Z") + range("a", "z") + range("0", "9") + ["+", "/"];
+ $b64Arr = array_merge(range("A", "Z"), range("a", "z"), range("0", "9"), ["+", "/"]);
//base64の64進の数字になる[A-Za-z0-9+/]の文字の配列を用意

function b64safe(string $b64, bool $dec = false, array $rep = [["+", "/", "="], [".", "_", "-"]]):string {
    return str_replace($rep[(int) $dec], $rep[(int) !$dec], $b64);
}


function padLen(int $abs, int $len):int {
    return ($len - ($abs + $len - 1) % $len) - 1;
}

function bin2b64(string $bin):string {
    global $b64Arr;
    $bin .= str_pad("", padLen(strlen($bin), 6), "0");
    return implode("", array_map(fn($v) => $b64Arr[base_convert($v, 2, 10)], str_split($bin, 6))).str_repeat("=", padLen(strlen($bin) / 6, 4));
}

function b642bin(string $b64):string {
    global $b64Arr;
    $b64 = str_replace("=", "", $b64);
    return implode("", array_map(fn($v) => str_pad(base_convert(array_search($v, $b64Arr, true), 10, 2), 6, "0", 0), str_split($b64)));
}

関数 引数 引数の説明 返り値
b64safe() $b64 入力するbase64 $repのルールによって
エンコード/デコードされたbase64
$dec false エンコード
true デコード
$rep 変換ルールの指定
padLen() $abs pad前の文字列の長さ 必要なpadの長さ
$len pad後の文字列の長さを
何の倍数にするか
bin2b64() $bin 入力するbinary_string $binからbase64へ変換した文字列
bin2b64() $b64 入力するbase64 $b64からbinaryへ変換した文字列

こだわりポイント

b64safe()で、配列のアクセスにboolを転用する

記述量・計算量節約のために、boolをそのままintにして、うまく一行程度で表せられるようにした。

padLen()の剰余計算(%)を1回で済ませたところ

本来は($len - $abs % $len) % $lenとしたかったところを計算量節約で($len - ($abs - 1) % $len) - 1に。
そして、phpでは負の数 % 数の結果が負になることがあるため、せめて0の時だけでもカバーしようとなり、($len - ($abs + $len - 1) % $len) - 1に。

bin2b64()b642bin()を、配列操作で記述量を減らす

phpの標準関数であるarray_split()array_map()などをうまく使い、なるべく一行にたくさんの処理ができるように詰めた。

さいごに

いやはや、phpは変な癖が多すぎて困っちゃいますね(;^_^
まぁ標準の関数はとっても使いやすいので、書きなれてくると「意外と便利だな」という感じもします。

余談ですが、これらの関数を書くよりこの記事を書く方がかなり時間かかっちゃいました笑笑
記事を書く練習もしていきたいものですねー

それでは!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0