@@ -1,7 +1,7 @@
1−{-# LANGUAGE BangPatterns, Rank2Types #-}
1+{-# LANGUAGE BangPatterns, MagicHash, Rank2Types #-}
3-- Module : Data.Text.Fusion.Common
3-- Module : Data.Text.Fusion.Common
4−-- Copyright : (c) Bryan O'Sullivan 2009
4+-- Copyright : (c) Bryan O'Sullivan 2009, 2012
6-- License : BSD-style
6-- License : BSD-style
7-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
7-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
@@ -17,6 +17,7 @@ module Data.Text.Fusion.Common
18 , streamList
18 , streamList
19 , unstreamList
19 , unstreamList
21 -- * Basic interface
22 -- * Basic interface
@@ -104,10 +105,13 @@ import Prelude (Bool(..), Char, Eq(..), Int, Integral, Maybe(..),
104 (&&), fromIntegral, otherwise)
105 (&&), fromIntegral, otherwise)
105import qualified Data.List as L
106import qualified Data.List as L
106import qualified Prelude as P
107import qualified Prelude as P
108+import Data.Bits (shiftL)
107import Data.Int (Int64)
109import Data.Int (Int64)
108import Data.Text.Fusion.Internal
110import Data.Text.Fusion.Internal
109import Data.Text.Fusion.CaseMapping (foldMapping, lowerMapping, upperMapping)
111import Data.Text.Fusion.CaseMapping (foldMapping, lowerMapping, upperMapping)
110import Data.Text.Fusion.Size
112import Data.Text.Fusion.Size
113+import GHC.Prim (Addr#, chr#, indexCharOffAddr#, ord#)
114+import GHC.Types (Char(..), Int(..))
112singleton :: Char -> Stream Char
116singleton :: Char -> Stream Char
113singleton c = Stream next False 1
117singleton c = Stream next False 1
@@ -131,6 +135,35 @@ unstreamList (Stream next s0 _len) = unfold s0
132{-# RULES "STREAM streamList/unstreamList fusion" forall s. streamList (unstreamList s) = s #-}
136{-# RULES "STREAM streamList/unstreamList fusion" forall s. streamList (unstreamList s) = s #-}
138+-- | Stream the UTF-8-like packed encoding used by GHC to represent
139+-- constant strings in generated code.
141+-- This encoding uses the byte sequence "\xc0\x80" to represent NUL,
142+-- and the string is NUL-terminated.
143+streamCString# :: Addr# -> Stream Char
144+streamCString# addr = Stream step 0 unknownSize
148+ | b <= 0x7f = Yield (C# b#) (i+1)
149+ | b <= 0xdf = let !c = chr $ ((b-0xc0) `shiftL` 6) + next 1
151+ | b <= 0xef = let !c = chr $ ((b-0xe0) `shiftL` 12) +
152+ (next 1 `shiftL` 6) +
155+ | otherwise = let !c = chr $ ((b-0xf0) `shiftL` 18) +
156+ (next 1 `shiftL` 12) +
157+ (next 2 `shiftL` 6) +
160+ where b = I# (ord# b#)
161+ next n = I# (ord# (at# (i+n))) - 0x80
163+ at# (I# i#) = indexCharOffAddr# addr i#
164+ chr (I# i#) = C# (chr# i#)
165+{-# INLINE [0] streamCString# #-}
134-- ----------------------------------------------------------------------------
167-- ----------------------------------------------------------------------------
135-- * Basic stream functions
168-- * Basic stream functions