on master help sign in
Reduce the amount of code generated for string literals
2b2cb08Bryan O'Sullivan
Data/Text.hs+17−2
@@ -1,9 +1,9 @@
1−{-# LANGUAGE BangPatterns, CPP, Rank2Types, UnboxedTuples #-}
1+{-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, UnboxedTuples #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
3
3
4-- |
4-- |
5-- Module : Data.Text
5-- Module : Data.Text
6−-- Copyright : (c) 2009, 2010, 2011 Bryan O'Sullivan,
6+-- Copyright : (c) 2009, 2010, 2011, 2012 Bryan O'Sullivan,
7-- (c) 2009 Duncan Coutts,
7-- (c) 2009 Duncan Coutts,
8-- (c) 2008, 2009 Tom Harper
8-- (c) 2008, 2009 Tom Harper
9--
9--
@@ -222,6 +222,8 @@ import Data.ByteString (ByteString)
222import qualified Data.Text.Lazy as L
222import qualified Data.Text.Lazy as L
223import Data.Int (Int64)
223import Data.Int (Int64)
224#endif
224#endif
225+import qualified GHC.CString as GHC
226+import GHC.Prim (Addr#)
225
227
226-- $strict
228-- $strict
227--
229--
@@ -372,6 +374,19 @@ unpack :: Text -> String
372unpack = S.unstreamList . stream
374unpack = S.unstreamList . stream
373{-# INLINE [1] unpack #-}
375{-# INLINE [1] unpack #-}
374
376
377+-- | /O(n)/ Convert a literal string into a Text.
378+unpackCString# :: Addr# -> Text
379+unpackCString# addr# = unstream (S.streamCString# addr#)
380+{-# NOINLINE unpackCString# #-}
381+
382+{-# RULES "TEXT literal" forall a.
383+ unstream (S.streamList (L.map safe (GHC.unpackCString# a)))
384+ = unpackCString# a #-}
385+
386+{-# RULES "TEXT literal UTF8" forall a.
387+ unstream (S.streamList (L.map safe (GHC.unpackCStringUtf8# a)))
388+ = unpackCString# a #-}
389+
375-- | /O(1)/ Convert a character into a Text. Subject to fusion.
390-- | /O(1)/ Convert a character into a Text. Subject to fusion.
376-- Performs replacement on invalid scalar values.
391-- Performs replacement on invalid scalar values.
377singleton :: Char -> Text
392singleton :: Char -> Text
Data/Text/Fusion/Common.hs+35−2
@@ -1,7 +1,7 @@
1−{-# LANGUAGE BangPatterns, Rank2Types #-}
1+{-# LANGUAGE BangPatterns, MagicHash, Rank2Types #-}
2-- |
2-- |
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
5--
5--
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
17 singleton
17 singleton
18 , streamList
18 , streamList
19 , unstreamList
19 , unstreamList
20+ , streamCString#
20
21
21 -- * Basic interface
22 -- * Basic interface
22 , cons
23 , cons
@@ -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(..))
111
115
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
131
135
132{-# RULES "STREAM streamList/unstreamList fusion" forall s. streamList (unstreamList s) = s #-}
136{-# RULES "STREAM streamList/unstreamList fusion" forall s. streamList (unstreamList s) = s #-}
133
137
138+-- | Stream the UTF-8-like packed encoding used by GHC to represent
139+-- constant strings in generated code.
140+--
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
145+ where
146+ step !i
147+ | b == 0 = Done
148+ | b <= 0x7f = Yield (C# b#) (i+1)
149+ | b <= 0xdf = let !c = chr $ ((b-0xc0) `shiftL` 6) + next 1
150+ in Yield c (i+2)
151+ | b <= 0xef = let !c = chr $ ((b-0xe0) `shiftL` 12) +
152+ (next 1 `shiftL` 6) +
153+ next 2
154+ in Yield c (i+3)
155+ | otherwise = let !c = chr $ ((b-0xf0) `shiftL` 18) +
156+ (next 1 `shiftL` 12) +
157+ (next 2 `shiftL` 6) +
158+ next 3
159+ in Yield c (i+4)
160+ where b = I# (ord# b#)
161+ next n = I# (ord# (at# (i+n))) - 0x80
162+ b# = at# i
163+ at# (I# i#) = indexCharOffAddr# addr i#
164+ chr (I# i#) = C# (chr# i#)
165+{-# INLINE [0] streamCString# #-}
166+
134-- ----------------------------------------------------------------------------
167-- ----------------------------------------------------------------------------
135-- * Basic stream functions
168-- * Basic stream functions
136
169
Data/Text/Lazy.hs+17−2
@@ -1,8 +1,8 @@
1{-# OPTIONS_GHC -fno-warn-orphans #-}
1{-# OPTIONS_GHC -fno-warn-orphans #-}
2−{-# LANGUAGE BangPatterns, CPP #-}
2+{-# LANGUAGE BangPatterns, MagicHash, CPP #-}
3-- |
3-- |
4-- Module : Data.Text.Lazy
4-- Module : Data.Text.Lazy
5−-- Copyright : (c) 2009, 2010 Bryan O'Sullivan
5+-- Copyright : (c) 2009, 2010, 2012 Bryan O'Sullivan
6--
6--
7-- License : BSD-style
7-- License : BSD-style
8-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
8-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
@@ -217,6 +217,8 @@ import Data.Text.Lazy.Internal (Text(..), chunk, empty, foldlChunks, foldrChunks
217import Data.Text.Internal (firstf, safe, textP)
217import Data.Text.Internal (firstf, safe, textP)
218import qualified Data.Text.Util as U
218import qualified Data.Text.Util as U
219import Data.Text.Lazy.Search (indices)
219import Data.Text.Lazy.Search (indices)
220+import qualified GHC.CString as GHC
221+import GHC.Prim (Addr#)
220
222
221-- $fusion
223-- $fusion
222--
224--
@@ -351,6 +353,19 @@ unpack :: Text -> String
351unpack t = S.unstreamList (stream t)
353unpack t = S.unstreamList (stream t)
352{-# INLINE [1] unpack #-}
354{-# INLINE [1] unpack #-}
353
355
356+-- | /O(n)/ Convert a literal string into a Text.
357+unpackCString# :: Addr# -> Text
358+unpackCString# addr# = unstream (S.streamCString# addr#)
359+{-# NOINLINE unpackCString# #-}
360+
361+{-# RULES "TEXT literal" forall a.
362+ unstream (S.streamList (L.map safe (GHC.unpackCString# a)))
363+ = unpackCString# a #-}
364+
365+{-# RULES "TEXT literal UTF8" forall a.
366+ unstream (S.streamList (L.map safe (GHC.unpackCStringUtf8# a)))
367+ = unpackCString# a #-}
368+
354-- | /O(1)/ Convert a character into a Text. Subject to fusion.
369-- | /O(1)/ Convert a character into a Text. Subject to fusion.
355-- Performs replacement on invalid scalar values.
370-- Performs replacement on invalid scalar values.
356singleton :: Char -> Text
371singleton :: Char -> Text