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
| minWidth == 3 = fmtDec3 n
| minWidth == 4 = fmtDec4 n
| otherwise = fmtInt 10 undefined minWidth '0' False n
fmtDec2 :: Int -> String
fmtDec2 n
| n < 0 || n >= 100 = fmtInt 10 undefined 2 '0' False n
| 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
| 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
| 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