-- 本當にこんなものを自分で書く必要があったのだらうか。Printf は重いの -- で駄目だが、それ以外のモジュールを探しても見付からなかった。 module Network.HTTP.Lucu.Format ( fmtInt , fmtDec , fmtHex ) where fmtInt :: Int -> Bool -> Int -> Char -> Bool -> Int -> String fmtInt base upperCase minWidth pad forceSign n = base `seq` minWidth `seq` pad `seq` forceSign `seq` n `seq` let raw = reverse $! fmt' (abs n) sign = if forceSign || n < 0 then if n < 0 then "-" else "+" else "" padded = padStr (minWidth - length sign) pad raw in sign ++ padded where fmt' :: Int -> String fmt' m | m < base = [intToChar upperCase m] | otherwise = (intToChar upperCase $! m `mod` base) : fmt' (m `div` base) fmtDec :: Int -> Int -> String fmtDec minWidth n | minWidth == 2 = fmtDec2 n -- optimization | minWidth == 3 = fmtDec3 n -- optimization | minWidth == 4 = fmtDec4 n -- optimization | otherwise = fmtInt 10 undefined minWidth '0' False n {-# INLINE fmtDec #-} fmtDec2 :: Int -> String fmtDec2 n | n < 0 || n >= 100 = fmtInt 10 undefined 2 '0' False n -- fallback | n < 10 = [ '0' , intToChar undefined n ] | otherwise = [ intToChar undefined (n `div` 10) , intToChar undefined (n `mod` 10) ] fmtDec3 :: Int -> String fmtDec3 n | n < 0 || n >= 1000 = fmtInt 10 undefined 3 '0' False n -- fallback | n < 10 = [ '0' , '0' , intToChar undefined n ] | n < 100 = [ '0' , intToChar undefined ((n `div` 10) `mod` 10) , intToChar undefined ( n `mod` 10) ] | otherwise = [ intToChar undefined ((n `div` 100) `mod` 10) , intToChar undefined ((n `div` 10) `mod` 10) , intToChar undefined ( n `mod` 10) ] fmtDec4 :: Int -> String fmtDec4 n | n < 0 || n >= 10000 = fmtInt 10 undefined 4 '0' False n -- fallback | n < 10 = [ '0' , '0' , '0' , intToChar undefined n ] | n < 100 = [ '0' , '0' , intToChar undefined ((n `div` 10) `mod` 10) , intToChar undefined ( n `mod` 10) ] | n < 1000 = [ '0' , intToChar undefined ((n `div` 100) `mod` 10) , intToChar undefined ((n `div` 10) `mod` 10) , intToChar undefined ( n `mod` 10) ] | otherwise = [ intToChar undefined ((n `div` 1000) `mod` 10) , intToChar undefined ((n `div` 100) `mod` 10) , intToChar undefined ((n `div` 10) `mod` 10) , intToChar undefined ( n `mod` 10) ] fmtHex :: Bool -> Int -> Int -> String fmtHex upperCase minWidth = fmtInt 16 upperCase minWidth '0' False padStr :: Int -> Char -> String -> String padStr minWidth pad str = let delta = minWidth - length str in if delta > 0 then replicate delta pad ++ str else str intToChar :: Bool -> Int -> Char intToChar _ 0 = '0' intToChar _ 1 = '1' intToChar _ 2 = '2' intToChar _ 3 = '3' intToChar _ 4 = '4' intToChar _ 5 = '5' intToChar _ 6 = '6' intToChar _ 7 = '7' intToChar _ 8 = '8' intToChar _ 9 = '9' intToChar False 10 = 'a' intToChar True 10 = 'A' intToChar False 11 = 'b' intToChar True 11 = 'B' intToChar False 12 = 'c' intToChar True 12 = 'C' intToChar False 13 = 'd' intToChar True 13 = 'D' intToChar False 14 = 'e' intToChar True 14 = 'E' intToChar False 15 = 'f' intToChar True 15 = 'F' intToChar _ _ = undefined