@@ -82,6 +82,8 @@ instance Monoid Builder where
8282 {-# INLINE mempty #-}
8383 mappend = append
8484 {-# INLINE mappend #-}
85+ mconcat = foldr mappend mempty
86+ {-# INLINE mconcat #-}
8587
8688instance String.IsString Builder where
8789 fromString = fromString
@@ -97,7 +99,7 @@ instance Show Builder where
9799-- * @'toLazyText' 'empty' = 'L.empty'@
98100--
99101empty :: Builder
100−empty = Builder id
102+empty = Builder (\ k buf -> k buf)
101103{-# INLINE empty #-}
102104
103105-- | /O(1)./ A @Builder@ taking a single character, satisfying
@@ -105,7 +107,17 @@ empty = Builder id
105107-- * @'toLazyText' ('singleton' c) = 'L.singleton' c@
106108--
107109singleton :: Char -> Builder
108−singleton c = putChar c
110+singleton c = writeAtMost 2 $ \ marr o ->
111+ if n < 0x10000
112+ then A.unsafeWrite marr o (fromIntegral n) >> return 1
113+ else do
114+ A.unsafeWrite marr o lo
115+ A.unsafeWrite marr (o+1) hi
116+ return 2
117+ where n = ord c
118+ m = n - 0x10000
119+ lo = fromIntegral $ (m `shiftR` 10) + 0xD800
120+ hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
109121{-# INLINE singleton #-}
110122
111123------------------------------------------------------------------------
@@ -229,20 +241,6 @@ mapBuilder f = Builder (fmap f .)
229241
230242------------------------------------------------------------------------
231243
232−putChar :: Char -> Builder
233−putChar c
234− | n < 0x10000 = writeN 1 $ \marr o -> A.unsafeWrite marr o (fromIntegral n)
235− | otherwise = writeN 2 $ \marr o -> do
236− A.unsafeWrite marr o lo
237− A.unsafeWrite marr (o+1) hi
238− where n = ord c
239− m = n - 0x10000
240− lo = fromIntegral $ (m `shiftR` 10) + 0xD800
241− hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
242−{-# INLINE putChar #-}
243−
244−------------------------------------------------------------------------
245−
246244-- | Ensure that there are at least @n@ many elements available.
247245ensureFree :: Int -> Builder
248246ensureFree !n = withSize $ \ l ->
@@ -251,18 +249,21 @@ ensureFree !n = withSize $ \ l ->
251249 else flush `append'` withBuffer (const (newBuffer (max n smallChunkSize)))
252250{-# INLINE [0] ensureFree #-}
253251
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 #-}
255+
254256-- | Ensure that @n@ many elements are available, and then use @f@ to
255257-- write some elements into the memory.
256258writeN :: Int -> (forall s. A.MArray s -> Int -> ST s ()) -> Builder
257−writeN n f = ensureFree n `append'` withBuffer (writeNBuffer n f)
258−{-# INLINE [0] writeN #-}
259+writeN n f = writeAtMost n (\ p o -> f p o >> return n)
260+{-# INLINE writeN #-}
259261
260−writeNBuffer :: Int -> (A.MArray s -> Int -> ST s ()) -> (Buffer s)
261− -> ST s (Buffer s)
262−writeNBuffer n f (Buffer p o u l) = do
263− f p (o+u)
262+writeBuffer :: (A.MArray s -> Int -> ST s Int) -> Buffer s -> ST s (Buffer s)
263+writeBuffer f (Buffer p o u l) = do
264+ n <- f p (o+u)
264265 return $! Buffer p o (u+n) (l-n)
265−{-# INLINE writeNBuffer #-}
266+{-# INLINE writeBuffer #-}
266267
267268newBuffer :: Int -> ST s (Buffer s)
268269newBuffer size = do
@@ -275,27 +276,31 @@ newBuffer size = do
275276
276277-- This function makes GHC understand that 'writeN' and 'ensureFree'
277278-- are *not* recursive in the precense of the rewrite rules below.
278−-- This is not needed with GHC 6.14+.
279+-- This is not needed with GHC 7+.
279280append' :: Builder -> Builder -> Builder
280281append' (Builder f) (Builder g) = Builder (f . g)
281282{-# INLINE append' #-}
282283
283284{-# RULES
284285
285−"append/writeN" forall a b (f::forall s. A.MArray s -> Int -> ST s ())
286− (g::forall s. A.MArray s -> Int -> ST s ()) ws.
287− append (writeN a f) (append (writeN b g) ws) =
288− append (writeN (a+b) (\marr o -> f marr o >> g marr (o+a))) ws
286+"append/writeAtMost" forall a b (f::forall s. A.MArray s -> Int -> ST s Int)
287+ (g::forall s. A.MArray s -> Int -> ST s Int) ws.
288+ append (writeAtMost a f) (append (writeAtMost b g) 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
289292
290−"writeN/writeN" forall a b (f::forall s. A.MArray s -> Int -> ST s ())
291− (g::forall s. A.MArray s -> Int -> ST s ()).
292− append (writeN a f) (writeN b g) =
293− writeN (a+b) (\marr o -> f marr o >> g marr (o+a))
293+"writeAtMost/writeAtMost" forall a b (f::forall s. A.MArray s -> Int -> ST s Int)
294+ (g::forall s. A.MArray s -> Int -> ST s Int).
295+ append (writeAtMost a f) (writeAtMost b g) =
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)
294299
295300"ensureFree/ensureFree" forall a b .
296− append (ensureFree a) (ensureFree b) = ensureFree (max a b)
301+ append (ensureFree a) (ensureFree b) = ensureFree (max a b)
297302
298303"flush/flush"
299− append flush flush = flush
304+ append flush flush = flush
300305
301306 #-}