7 -- 本當にこんなものを自分で書く必要があったのだらうか。Printf は重いの
8 -- で駄目だが、それ以外のモジュールを探しても見付からなかった。
9 module Network.HTTP.Lucu.Format
16 import Data.Ascii (AsciiBuilder)
17 import qualified Data.ByteString.Char8 as BS
18 import qualified Data.Ascii as A
20 import Data.Monoid.Unicode
21 import Prelude.Unicode
23 fmtInt ∷ ∀n. Integral n ⇒ n → Int → n → AsciiBuilder
24 {-# INLINEABLE fmtInt #-}
25 fmtInt base minWidth n
26 = let (# raw, len #) = fmt' (abs n) (∅) 0
29 ( A.toAsciiBuilder "-" ⊕
30 mkPad (minWidth - 1) len ⊕
34 mkPad minWidth len ⊕ raw
36 fmt' ∷ n → AsciiBuilder → Int → (# AsciiBuilder, Int #)
37 {-# INLINEABLE fmt' #-}
40 = let b' = b ⊕ fromDigit x
44 = let x' = x `div` base
50 mkPad ∷ Int → Int → AsciiBuilder
51 {-# INLINEABLE mkPad #-}
54 A.unsafeFromByteString $
55 BS.replicate (minWidth - len) '0'
57 fmtDec ∷ Integral n ⇒ Int → n → AsciiBuilder
60 | minWidth == 2 = fmtDec2 n -- optimization
61 | minWidth == 3 = fmtDec3 n -- optimization
62 | minWidth == 4 = fmtDec4 n -- optimization
63 | otherwise = fmtInt 10 minWidth n
65 fmtDec2 ∷ Integral n ⇒ n → AsciiBuilder
66 {-# INLINEABLE fmtDec2 #-}
68 | n < 0 ∨ n ≥ 100 = fmtInt 10 2 n -- fallback
69 | n < 10 = A.toAsciiBuilder "0" ⊕
71 | otherwise = fromDigit (n `div` 10) ⊕
72 fromDigit (n `mod` 10)
74 fmtDec3 ∷ Integral n ⇒ n → AsciiBuilder
75 {-# INLINEABLE fmtDec3 #-}
77 | n < 0 ∨ n ≥ 1000 = fmtInt 10 3 n -- fallback
78 | n < 10 = A.toAsciiBuilder "00" ⊕
80 | n < 100 = A.toAsciiBuilder "0" ⊕
81 fromDigit ((n `div` 10) `mod` 10) ⊕
82 fromDigit ( n `mod` 10)
83 | otherwise = fromDigit (n `div` 100) ⊕
84 fromDigit ((n `div` 10) `mod` 10) ⊕
85 fromDigit ( n `mod` 10)
87 fmtDec4 ∷ Integral n ⇒ n → AsciiBuilder
88 {-# INLINEABLE fmtDec4 #-}
90 | n < 0 ∨ n ≥ 10000 = fmtInt 10 4 n -- fallback
91 | n < 10 = A.toAsciiBuilder "000" ⊕
93 | n < 100 = A.toAsciiBuilder "00" ⊕
94 fromDigit ((n `div` 10) `mod` 10) ⊕
95 fromDigit ( n `mod` 10)
96 | n < 1000 = A.toAsciiBuilder "0" ⊕
97 fromDigit ((n `div` 100) `mod` 10) ⊕
98 fromDigit ((n `div` 10) `mod` 10) ⊕
99 fromDigit ( n `mod` 10)
100 | otherwise = fromDigit (n `div` 1000) ⊕
101 fromDigit ((n `div` 100) `mod` 10) ⊕
102 fromDigit ((n `div` 10) `mod` 10) ⊕
103 fromDigit ( n `mod` 10)
105 fmtHex ∷ Integral n ⇒ Int → n → AsciiBuilder
106 {-# INLINE fmtHex #-}
109 digitToChar ∷ Integral n ⇒ n → Char
110 {-# INLINE digitToChar #-}
113 | n < 10 = chr (ord '0' + fromIntegral n )
114 | n < 16 = chr (ord 'A' + fromIntegral (n-10))
117 fromDigit ∷ Integral n ⇒ n → AsciiBuilder
118 {-# INLINE fromDigit #-}
119 fromDigit = A.toAsciiBuilder ∘
120 A.unsafeFromByteString ∘