on master help sign in
Write straight into the dest buffer
46ddff9Bryan O'Sullivan
Data/Text/Lazy/Builder/Int.hs+35−11
@@ -1,4 +1,4 @@
1−{-# LANGUAGE BangPatterns, CPP, MagicHash, UnboxedTuples #-}
1+{-# LANGUAGE BangPatterns, CPP, MagicHash, RankNTypes, UnboxedTuples #-}
2
2
3-- Module: Data.Text.Lazy.Builder.Int
3-- Module: Data.Text.Lazy.Builder.Int
4-- Copyright: (c) 2011 MailRank, Inc.
4-- Copyright: (c) 2011 MailRank, Inc.
@@ -19,10 +19,12 @@ import Data.Int (Int8, Int16, Int32, Int64)
19import Data.Monoid (mempty)
19import Data.Monoid (mempty)
20import Data.Text.Lazy.Builder.Functions ((<>), i2d)
20import Data.Text.Lazy.Builder.Functions ((<>), i2d)
21import Data.Text.Lazy.Builder.Internal
21import Data.Text.Lazy.Builder.Internal
22+import Data.Text.Array
22import Data.Word (Word, Word8, Word16, Word32, Word64)
23import Data.Word (Word, Word8, Word16, Word32, Word64)
23import GHC.Base (quotInt, remInt)
24import GHC.Base (quotInt, remInt)
24import GHC.Num (quotRemInteger)
25import GHC.Num (quotRemInteger)
25import GHC.Types (Int(..))
26import GHC.Types (Int(..))
27+import Control.Monad.ST
26
28
27#ifdef __GLASGOW_HASKELL__
29#ifdef __GLASGOW_HASKELL__
28# if __GLASGOW_HASKELL__ < 611
30# if __GLASGOW_HASKELL__ < 611
@@ -69,14 +71,16 @@ decimal' :: (Integral a) => (a -> Bool) -> a -> Builder
69decimal' p i
71decimal' p i
70 | i < 0 = if p i
72 | i < 0 = if p i
71 then let j = -(i `quot` 10)
73 then let j = -(i `quot` 10)
72− n = countDigits j + 2
74+ !n = countDigits j
73− in go n $ singleton '-' <>
75+ in writeN (n + 2) $ \marr off -> do
74− positive j <> digit (-(i `rem` 10))
76+ unsafeWrite marr off minus
77+ posDecimal marr (off+1) n j
78+ unsafeWrite marr (off+n+1) (i2w (-(i `rem` 10)))
75 else let j = -i
79 else let j = -i
76− n = countDigits j + 1
80+ !n = countDigits j
77− in go n $ singleton '-' <> positive j
81+ in writeN (n + 1) $ \marr off ->
82+ unsafeWrite marr off minus >> posDecimal marr (off+1) n j
78− | otherwise = go (countDigits i) $ positive i
83+ | otherwise = positive i
79− where go k b = ensureFree k `append'` b
80
84
81positive :: (Integral a) => a -> Builder
85positive :: (Integral a) => a -> Builder
82{-# SPECIALIZE positive :: Int -> Builder #-}
86{-# SPECIALIZE positive :: Int -> Builder #-}
@@ -89,9 +93,29 @@ positive :: (Integral a) => a -> Builder
89{-# SPECIALIZE positive :: Word16 -> Builder #-}
93{-# SPECIALIZE positive :: Word16 -> Builder #-}
90{-# SPECIALIZE positive :: Word32 -> Builder #-}
94{-# SPECIALIZE positive :: Word32 -> Builder #-}
91{-# SPECIALIZE positive :: Word64 -> Builder #-}
95{-# SPECIALIZE positive :: Word64 -> Builder #-}
92−positive = go
96+positive i
97+ | i < 10 = writeN 1 $ \marr off -> unsafeWrite marr off (i2w i)
98+ | otherwise = let !n = countDigits i
99+ in writeN n $ \marr off -> posDecimal marr off n i
100+
101+posDecimal :: Integral a => forall s. MArray s -> Int -> Int -> a -> ST s ()
102+{-# INLINE posDecimal #-}
103+posDecimal marr off0 ds v0 = go (off0 + ds - 1) v0
93− where go n | n < 10 = digit n
104+ where go off v
105+ | v < 10 = unsafeWrite marr off (i2w v)
94− | otherwise = go (n `quot` 10) <> digit (n `rem` 10)
106+ | otherwise = do
107+ unsafeWrite marr off (i2w (v `rem` 10))
108+ go (off-1) (v `div` 10)
109+
110+minus, zero :: Word16
111+{-# INLINE minus #-}
112+{-# INLINE zero #-}
113+minus = 45
114+zero = 48
115+
116+i2w :: (Integral a) => a -> Word16
117+{-# INLINE i2w #-}
118+i2w v = zero + fromIntegral v
95
119
96countDigits :: (Integral a) => a -> Int
120countDigits :: (Integral a) => a -> Int
97{-# INLINE countDigits #-}
121{-# INLINE countDigits #-}
Data/Text/Lazy/Builder/Internal.hs+1
@@ -46,6 +46,7 @@ module Data.Text.Lazy.Builder.Internal
46 -- * Internal functions
46 -- * Internal functions
47 , append'
47 , append'
48 , ensureFree
48 , ensureFree
49+ , writeN
49 ) where
50 ) where
50
51
51import Control.Monad.ST (ST, runST)
52import Control.Monad.ST (ST, runST)