Commits

Bryan O'Sullivan committed 18eead3

Use a specialised tuple for iter

Comments (0)

Files changed (3)

 import Data.Text.Fusion (stream, reverseStream, unstream)
 import Data.Text.Internal (Text(..), empty, text, textP)
 import qualified Prelude as P
-import Data.Text.Unsafe (iter, iter_, reverseIter, unsafeHead, unsafeTail)
+import Data.Text.Unsafe (Iter(..), iter, iter_, reverseIter, unsafeHead, unsafeTail)
 import Data.Text.UnsafeChar (unsafeChr)
 import qualified Data.Text.Encoding.Utf16 as U16
 import Data.Text.Search (indices)
 uncons t@(Text arr off len)
     | len <= 0  = Nothing
     | otherwise = Just (c, textP arr (off+d) (len-d))
-    where (c,d) = iter t 0
+    where Iter c d = iter t 0
 {-# INLINE [1] uncons #-}
 
 -- | Lifted from Control.Arrow and specialized.
   where loop !i | i >= len    = t
                 | p c         = loop (i+d)
                 | otherwise   = textP arr off i
-            where (c,d)       = iter t i
+            where Iter c d    = iter t i
 {-# INLINE [1] takeWhile #-}
 
 {-# RULES
   where loop !i !l | l >= len  = empty
                    | p c       = loop (i+d) (l+d)
                    | otherwise = Text arr (off+i) (len-l)
-            where (c,d)        = iter t i
+            where Iter c d     = iter t i
 {-# INLINE [1] dropWhile #-}
 
 {-# RULES
   where k = loop 0
         loop !i | i >= len || not (p c) = i
                 | otherwise             = loop (i+d)
-            where (c,d)                 = iter t i
+            where Iter c d              = iter t i
 {-# INLINE spanBy #-}
 
 -- | /O(n)/ 'breakBy' is like 'spanBy', but the prefix returned is
     loop t@(Text arr off len)
         | null t    = []
         | otherwise = text arr off n : loop (text arr (off+n) (len-n))
-        where (c,d) = iter t 0
+        where Iter c d = iter t 0
               n     = d + findAIndexOrEnd (not . p c) (Text arr (off+d) (len-d))
 
 -- | Returns the /array/ index (in units of 'Word16') at which a
 findAIndexOrEnd q t@(Text _arr _off len) = go 0
     where go !i | i >= len || q c       = i
                 | otherwise             = go (i+d)
-                where (c,d)             = iter t i
+                where Iter c d          = iter t i
     
 -- | /O(n)/ Group characters in a string by equality.
 group :: Text -> [Text]
             then loop (start+1) (start+1)
             else Text arr (start+off) (n-start) : loop (n+d) (n+d)
         | otherwise = loop start (n+d)
-        where (c,d) = iter t n
+        where Iter c d = iter t n
 {-# INLINE words #-}
 
 -- | /O(n)/ Breaks a 'Text' up into a list of 'Text's at

Data/Text/Lazy/Fusion.hs

 import qualified Data.Text.Array as A
 import Data.Text.UnsafeChar (unsafeWrite)
 import Data.Text.UnsafeShift (shiftL)
-import Data.Text.Unsafe (iter)
+import Data.Text.Unsafe (Iter(..), iter)
 import Data.Int (Int64)
 
 default(Int64)
     next (txt@(Chunk t@(I.Text _ _ len) ts) :*: i)
         | i >= len  = next (ts :*: 0)
         | otherwise = Yield c (txt :*: i+d)
-        where (c,d) = iter t i
+        where Iter c d = iter t i
 {-# INLINE [0] stream #-}
 
 -- | /O(n)/ Convert a 'Stream Char' into a 'Text', using the given

Data/Text/Unsafe.hs

     (
       inlineInterleaveST
     , inlinePerformIO
+    , Iter(..)
     , iter
     , iter_
     , reverseIter
   where d = iter_ t 0
 {-# INLINE unsafeTail #-}
 
+data Iter = Iter {-# UNPACK #-} !Char {-# UNPACK #-} !Int
+
 -- | /O(1)/ Iterate (unsafely) one step forwards through a UTF-16
 -- array, returning the current character and the delta to add to give
 -- the next offset to iterate at.
-iter :: Text -> Int -> (Char,Int)
+iter :: Text -> Int -> Iter
 iter (Text arr off _len) i
-    | m < 0xD800 || m > 0xDBFF = (unsafeChr m, 1)
-    | otherwise                = (chr2 m n,    2)
+    | m < 0xD800 || m > 0xDBFF = Iter (unsafeChr m) 1
+    | otherwise                = Iter (chr2 m n) 2
   where m = A.unsafeIndex arr j
         n = A.unsafeIndex arr k
         j = off + i