BASE64の変換をする関数を書いてみました。
同じような感じでBASE32とかBASE16とかも作れると思います。RFCを読んでて思ったのですが、BASE64はURLとかファイル名に使っても問題ない文字だけを使うバージョンもあったのですか… 知らなかったです。
module Main (main) where import Data.Array (Array, (!), listArray) import Data.Bits ((.&.), (.|.), shiftR, shiftL) import Data.Char (ord) base64Table :: Array Int Char base64Table = listArray (0, 63) $ ['A' .. 'Z'] ++ ['a' .. 'z'] ++ ['0' .. '9'] ++ "+/" base64Convert :: Int -> Int -> Int -> String base64Convert c1 c2 c3 = let i1 = (c1 .&. 0xfc) `shiftR` 2 i2 = ((c1 .&. 0x03) `shiftL` 4) .|. ((c2 .&. 0xf0) `shiftR` 4) i3 = ((c2 .&. 0x0f) `shiftL` 2) .|. ((c3 .&. 0xc0) `shiftR` 6) i4 = c3 .&. 0x3f in [base64Table ! i1, base64Table ! i2, base64Table ! i3, base64Table ! i4] base64 :: String -> String base64 [] = "" base64 (x1 : []) = (take 2 $ base64Convert (ord x1) 0 0) ++ "==" base64 (x1 : x2 : []) = (take 3 $ base64Convert (ord x1) (ord x2) 0) ++ "=" base64 (x1 : x2 : x3 : xs) = base64Convert (ord x1) (ord x2) (ord x3) ++ base64 xs base64SepLn :: Int -> String -> String base64SepLn n = f n n where f _ _ [] = "" f n 1 (x : xs) = x : '\n' : f n n xs f n i (x : xs) = x : f n (i - 1) xs main :: IO () main = putStrLn $ base64SepLn 76 $ base64 "Haskell" -- => "SGFza2VsbA=="
参照: RFC3548