@@ -107,7 +107,17 @@ empty = Builder (\ k buf -> k buf)
107-- * @'toLazyText' ('singleton' c) = 'L.singleton' c@
107-- * @'toLazyText' ('singleton' c) = 'L.singleton' c@
109singleton :: Char -> Builder
109singleton :: Char -> Builder
110−singleton c = putChar c
110+singleton c = writeAtMost 2 $ \ marr o ->
112+ then A.unsafeWrite marr o (fromIntegral n) >> return 1
114+ A.unsafeWrite marr o lo
115+ A.unsafeWrite marr (o+1) hi
119+ lo = fromIntegral $ (m `shiftR` 10) + 0xD800
120+ hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
111{-# INLINE singleton #-}
121{-# INLINE singleton #-}
113------------------------------------------------------------------------
123------------------------------------------------------------------------
@@ -231,20 +241,6 @@ mapBuilder f = Builder (fmap f .)
232------------------------------------------------------------------------
242------------------------------------------------------------------------
234−putChar :: Char -> Builder
236− | n < 0x10000 = writeN 1 $ \marr o -> A.unsafeWrite marr o (fromIntegral n)
237− | otherwise = writeN 2 $ \marr o -> do
238− A.unsafeWrite marr o lo
239− A.unsafeWrite marr (o+1) hi
242− lo = fromIntegral $ (m `shiftR` 10) + 0xD800
243− hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
244−{-# INLINE putChar #-}
246−------------------------------------------------------------------------
248-- | Ensure that there are at least @n@ many elements available.
244-- | Ensure that there are at least @n@ many elements available.
249ensureFree :: Int -> Builder
245ensureFree :: Int -> Builder
250ensureFree !n = withSize $ \ l ->
246ensureFree !n = withSize $ \ l ->
@@ -253,18 +249,21 @@ ensureFree !n = withSize $ \ l ->
253 else flush `append'` withBuffer (const (newBuffer (max n smallChunkSize)))
249 else flush `append'` withBuffer (const (newBuffer (max n smallChunkSize)))
254{-# INLINE [0] ensureFree #-}
250{-# INLINE [0] ensureFree #-}
252+writeAtMost :: Int -> (forall s. A.MArray s -> Int -> ST s Int) -> Builder
253+writeAtMost n f = ensureFree n `append'` withBuffer (writeBuffer f)
254+{-# INLINE [0] writeAtMost #-}
256-- | Ensure that @n@ many elements are available, and then use @f@ to
256-- | Ensure that @n@ many elements are available, and then use @f@ to
257-- write some elements into the memory.
257-- write some elements into the memory.
258writeN :: Int -> (forall s. A.MArray s -> Int -> ST s ()) -> Builder
258writeN :: Int -> (forall s. A.MArray s -> Int -> ST s ()) -> Builder
259−writeN n f = ensureFree n `append'` withBuffer (writeNBuffer n f)
259+writeN n f = writeAtMost n (\ p o -> f p o >> return n)
260−{-# INLINE [0] writeN #-}
260+{-# INLINE writeN #-}
262−writeNBuffer :: Int -> (A.MArray s -> Int -> ST s ()) -> (Buffer s)
262+writeBuffer :: (A.MArray s -> Int -> ST s Int) -> Buffer s -> ST s (Buffer s)
264−writeNBuffer n f (Buffer p o u l) = do
263+writeBuffer f (Buffer p o u l) = do
265− f p (o+u)
264+ n <- f p (o+u)
266 return $! Buffer p o (u+n) (l-n)
265 return $! Buffer p o (u+n) (l-n)
267−{-# INLINE writeNBuffer #-}
266+{-# INLINE writeBuffer #-}
269newBuffer :: Int -> ST s (Buffer s)
268newBuffer :: Int -> ST s (Buffer s)
270newBuffer size = do
269newBuffer size = do
@@ -277,27 +276,31 @@ newBuffer size = do
278-- This function makes GHC understand that 'writeN' and 'ensureFree'
277-- This function makes GHC understand that 'writeN' and 'ensureFree'
279-- are *not* recursive in the precense of the rewrite rules below.
278-- are *not* recursive in the precense of the rewrite rules below.
280−-- This is not needed with GHC 6.14+.
279+-- This is not needed with GHC 7+.
281append' :: Builder -> Builder -> Builder
280append' :: Builder -> Builder -> Builder
282append' (Builder f) (Builder g) = Builder (f . g)
281append' (Builder f) (Builder g) = Builder (f . g)
283{-# INLINE append' #-}
282{-# INLINE append' #-}
287−"append/writeN" forall a b (f::forall s. A.MArray s -> Int -> ST s ())
286+"append/writeAtMost" forall a b (f::forall s. A.MArray s -> Int -> ST s Int)
288− (g::forall s. A.MArray s -> Int -> ST s ()) ws.
287+ (g::forall s. A.MArray s -> Int -> ST s Int) ws.
289− append (writeN a f) (append (writeN b g) ws) =
288+ append (writeAtMost a f) (append (writeAtMost b g) ws) =
290− append (writeN (a+b) (\marr o -> f marr o >> g marr (o+a))) ws
289+ append (writeAtMost (a+b) (\marr o -> f marr o >>= \ n ->
290+ g marr (o+n) >>= \ m ->
291+ let s = n+m in s `seq` return s)) ws
292−"writeN/writeN" forall a b (f::forall s. A.MArray s -> Int -> ST s ())
293+"writeAtMost/writeAtMost" forall a b (f::forall s. A.MArray s -> Int -> ST s Int)
293− (g::forall s. A.MArray s -> Int -> ST s ()).
294+ (g::forall s. A.MArray s -> Int -> ST s Int).
294− append (writeN a f) (writeN b g) =
295+ append (writeAtMost a f) (writeAtMost b g) =
295− writeN (a+b) (\marr o -> f marr o >> g marr (o+a))
296+ writeAtMost (a+b) (\marr o -> f marr o >>= \ n ->
297+ g marr (o+n) >>= \ m ->
298+ let s = n+m in s `seq` return s)
297"ensureFree/ensureFree" forall a b .
300"ensureFree/ensureFree" forall a b .
298− append (ensureFree a) (ensureFree b) = ensureFree (max a b)
301+ append (ensureFree a) (ensureFree b) = ensureFree (max a b)
300"flush/flush"
303"flush/flush"
301− append flush flush = flush
304+ append flush flush = flush