@@ -107,7 +107,17 @@ empty = Builder (\ k buf -> k buf)
107107-- * @'toLazyText' ('singleton' c) = 'L.singleton' c@
108108--
109109singleton :: Char -> Builder
110−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
111121{-# INLINE singleton #-}
112122
113123------------------------------------------------------------------------
@@ -231,20 +241,6 @@ mapBuilder f = Builder (fmap f .)
231241
232242------------------------------------------------------------------------
233243
234−putChar :: Char -> Builder
235−putChar c
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
240− where n = ord c
241− m = n - 0x10000
242− lo = fromIntegral $ (m `shiftR` 10) + 0xD800
243− hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
244−{-# INLINE putChar #-}
245−
246−------------------------------------------------------------------------
247−
248244-- | Ensure that there are at least @n@ many elements available.
249245ensureFree :: Int -> Builder
250246ensureFree !n = withSize $ \ l ->
@@ -253,18 +249,21 @@ ensureFree !n = withSize $ \ l ->
253249 else flush `append'` withBuffer (const (newBuffer (max n smallChunkSize)))
254250{-# INLINE [0] ensureFree #-}
255251
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+
256256-- | Ensure that @n@ many elements are available, and then use @f@ to
257257-- write some elements into the memory.
258258writeN :: Int -> (forall s. A.MArray s -> Int -> ST s ()) -> Builder
259−writeN n f = ensureFree n `append'` withBuffer (writeNBuffer n f)
260−{-# INLINE [0] writeN #-}
259+writeN n f = writeAtMost n (\ p o -> f p o >> return n)
260+{-# INLINE writeN #-}
261261
262−writeNBuffer :: Int -> (A.MArray s -> Int -> ST s ()) -> (Buffer s)
263− -> ST s (Buffer s)
264−writeNBuffer n f (Buffer p o u l) = do
265− 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)
266265 return $! Buffer p o (u+n) (l-n)
267−{-# INLINE writeNBuffer #-}
266+{-# INLINE writeBuffer #-}
268267
269268newBuffer :: Int -> ST s (Buffer s)
270269newBuffer size = do
@@ -277,27 +276,31 @@ newBuffer size = do
277276
278277-- This function makes GHC understand that 'writeN' and 'ensureFree'
279278-- 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+.
281280append' :: Builder -> Builder -> Builder
282281append' (Builder f) (Builder g) = Builder (f . g)
283282{-# INLINE append' #-}
284283
285284{-# RULES
286285
287−"append/writeN" forall a b (f::forall s. A.MArray s -> Int -> ST s ())
288− (g::forall s. A.MArray s -> Int -> ST s ()) ws.
289− append (writeN a f) (append (writeN b g) ws) =
290− 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
291292
292−"writeN/writeN" forall a b (f::forall s. A.MArray s -> Int -> ST s ())
293− (g::forall s. A.MArray s -> Int -> ST s ()).
294− append (writeN a f) (writeN b g) =
295− 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)
296299
297300"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)
299302
300303"flush/flush"
301− append flush flush = flush
304+ append flush flush = flush
302305
303306 #-}