7 -- 本當にこんなものを自分で書く必要があったのだらうか。Printf は重いの
8 -- で駄目だが、それ以外のモジュールを探しても見付からなかった。
9 module Network.HTTP.Lucu.Format
16 import qualified Blaze.ByteString.Builder.Char8 as BC
17 import Data.Ascii (AsciiBuilder)
18 import qualified Data.ByteString.Char8 as BS
19 import qualified Data.Ascii as A
21 import Data.Monoid.Unicode
22 import Prelude.Unicode
24 fmtInt ∷ ∀n. Integral n ⇒ n → Int → n → AsciiBuilder
25 {-# INLINEABLE fmtInt #-}
26 fmtInt base minWidth n
27 = let (# raw, len #) = fmt' (abs n) (∅) 0
30 ( A.toAsciiBuilder "-" ⊕
31 mkPad (minWidth - 1) len ⊕
35 mkPad minWidth len ⊕ raw
37 fmt' ∷ n → AsciiBuilder → Int → (# AsciiBuilder, Int #)
38 {-# INLINEABLE fmt' #-}
41 = let b' = b ⊕ fromDigit x
45 = let x' = x `div` base
51 mkPad ∷ Int → Int → AsciiBuilder
52 {-# INLINEABLE mkPad #-}
55 A.unsafeFromByteString $
56 BS.replicate (minWidth - len) '0'
58 fmtDec ∷ Integral n ⇒ Int → n → AsciiBuilder
61 | minWidth == 2 = fmtDec2 n -- optimization
62 | minWidth == 3 = fmtDec3 n -- optimization
63 | minWidth == 4 = fmtDec4 n -- optimization
64 | otherwise = fmtInt 10 minWidth n
66 fmtDec2 ∷ Integral n ⇒ n → AsciiBuilder
67 {-# INLINEABLE fmtDec2 #-}
69 | n < 0 ∨ n ≥ 100 = fmtInt 10 2 n -- fallback
70 | n < 10 = A.toAsciiBuilder "0" ⊕
72 | otherwise = fromDigit (n `div` 10) ⊕
73 fromDigit (n `mod` 10)
75 fmtDec3 ∷ Integral n ⇒ n → AsciiBuilder
76 {-# INLINEABLE fmtDec3 #-}
78 | n < 0 ∨ n ≥ 1000 = fmtInt 10 3 n -- fallback
79 | n < 10 = A.toAsciiBuilder "00" ⊕
81 | n < 100 = A.toAsciiBuilder "0" ⊕
82 fromDigit ((n `div` 10) `mod` 10) ⊕
83 fromDigit ( n `mod` 10)
84 | otherwise = fromDigit (n `div` 100) ⊕
85 fromDigit ((n `div` 10) `mod` 10) ⊕
86 fromDigit ( n `mod` 10)
88 fmtDec4 ∷ Integral n ⇒ n → AsciiBuilder
89 {-# INLINEABLE fmtDec4 #-}
91 | n < 0 ∨ n ≥ 10000 = fmtInt 10 4 n -- fallback
92 | n < 10 = A.toAsciiBuilder "000" ⊕
94 | n < 100 = A.toAsciiBuilder "00" ⊕
95 fromDigit ((n `div` 10) `mod` 10) ⊕
96 fromDigit ( n `mod` 10)
97 | n < 1000 = A.toAsciiBuilder "0" ⊕
98 fromDigit ((n `div` 100) `mod` 10) ⊕
99 fromDigit ((n `div` 10) `mod` 10) ⊕
100 fromDigit ( n `mod` 10)
101 | otherwise = fromDigit (n `div` 1000) ⊕
102 fromDigit ((n `div` 100) `mod` 10) ⊕
103 fromDigit ((n `div` 10) `mod` 10) ⊕
104 fromDigit ( n `mod` 10)
106 fmtHex ∷ Integral n ⇒ Int → n → AsciiBuilder
107 {-# INLINE fmtHex #-}
110 digitToChar ∷ Integral n ⇒ n → Char
111 {-# INLINE digitToChar #-}
114 | n < 10 = chr (ord '0' + fromIntegral n )
115 | n < 16 = chr (ord 'A' + fromIntegral (n-10))
118 fromDigit ∷ Integral n ⇒ n → AsciiBuilder
119 {-# INLINE fromDigit #-}
120 fromDigit = A.unsafeFromBuilder ∘ BC.fromChar ∘ digitToChar