@@ -21,7 +21,9 @@ module Data.Text.Unsafe
21 , unsafeTail
21 , unsafeTail
24import Control.Exception (assert)
25import Control.Exception (assert)
25import Data.Text.Encoding.Utf16 (chr2)
27import Data.Text.Encoding.Utf16 (chr2)
26import Data.Text.Internal (Text(..))
28import Data.Text.Internal (Text(..))
27import Data.Text.UnsafeChar (unsafeChr)
29import Data.Text.UnsafeChar (unsafeChr)
@@ -40,11 +42,11 @@ import GHC.Base (realWorld#)
40-- omits the check for the empty case, so there is an obligation on
42-- omits the check for the empty case, so there is an obligation on
41-- the programmer to provide a proof that the 'Text' is non-empty.
43-- the programmer to provide a proof that the 'Text' is non-empty.
42unsafeHead :: Text -> Char
44unsafeHead :: Text -> Char
43−unsafeHead (Text arr off len)
45+unsafeHead (Text arr off _len)
44 | m < 0xD800 || m > 0xDBFF = unsafeChr m
46 | m < 0xD800 || m > 0xDBFF = unsafeChr m
45 | otherwise = chr2 m n
47 | otherwise = chr2 m n
46− where m = assert (len > 0) $ A.unsafeIndex arr off
48+ where m = A.unsafeIndex arr off
47− n = assert (len > 1) $ A.unsafeIndex arr (off+1)
49+ n = A.unsafeIndex arr (off+1)
48{-# INLINE unsafeHead #-}
50{-# INLINE unsafeHead #-}
50-- | /O(1)/ A variant of 'tail' for non-empty 'Text'. 'unsafeHead'
52-- | /O(1)/ A variant of 'tail' for non-empty 'Text'. 'unsafeHead'
@@ -52,42 +54,45 @@ unsafeHead (Text arr off len)
52-- the programmer to provide a proof that the 'Text' is non-empty.
54-- the programmer to provide a proof that the 'Text' is non-empty.
53unsafeTail :: Text -> Text
55unsafeTail :: Text -> Text
54unsafeTail t@(Text arr off len) =
56unsafeTail t@(Text arr off len) =
55− assert (d <= len) $ Text arr (off+d) (len-d)
60+ Text arr (off+d) (len-d)
56 where d = iter_ t 0
61 where d = iter_ t 0
57{-# INLINE unsafeTail #-}
62{-# INLINE unsafeTail #-}
59−-- | /O(1)/ Iterate one step forwards through a UTF-16 array,
64+-- | /O(1)/ Iterate (unsafely) one step forwards through a UTF-16
60−-- returning the current character and the delta to add to give the
65+-- array, returning the current character and the delta to add to give
61−-- next offset to iterate at.
66+-- the next offset to iterate at.
62iter :: Text -> Int -> (Char,Int)
67iter :: Text -> Int -> (Char,Int)
63−iter (Text arr off len) i
68+iter (Text arr off _len) i
64 | m < 0xD800 || m > 0xDBFF = (unsafeChr m, 1)
69 | m < 0xD800 || m > 0xDBFF = (unsafeChr m, 1)
65 | otherwise = (chr2 m n, 2)
70 | otherwise = (chr2 m n, 2)
66− where m = assert (i < len) $ A.unsafeIndex arr j
71+ where m = A.unsafeIndex arr j
67− n = assert (i + 1 < len) $ A.unsafeIndex arr k
72+ n = A.unsafeIndex arr k
68− j = assert (i >= 0) $ off + i
73+ j = off + i
69− k = j + 1
74+ k = j + 1
70{-# INLINE iter #-}
75{-# INLINE iter #-}
72-- | /O(1)/ Iterate one step through a UTF-16 array, returning the
77-- | /O(1)/ Iterate one step through a UTF-16 array, returning the
73-- delta to add to give the next offset to iterate at.
78-- delta to add to give the next offset to iterate at.
74iter_ :: Text -> Int -> Int
79iter_ :: Text -> Int -> Int
75−iter_ (Text arr off len) i | m < 0xD800 || m > 0xDBFF = 1
80+iter_ (Text arr off _len) i | m < 0xD800 || m > 0xDBFF = 1
76− | otherwise = 2
81+ | otherwise = 2
77− where m = assert (i >= 0 && i < len) $ A.unsafeIndex arr (off+i)
82+ where m = A.unsafeIndex arr (off+i)
78{-# INLINE iter_ #-}
83{-# INLINE iter_ #-}
80-- | /O(1)/ Iterate one step backwards through a UTF-16 array,
85-- | /O(1)/ Iterate one step backwards through a UTF-16 array,
81-- returning the current character and the delta to add (i.e. a
86-- returning the current character and the delta to add (i.e. a
82-- negative number) to give the next offset to iterate at.
87-- negative number) to give the next offset to iterate at.
83reverseIter :: Text -> Int -> (Char,Int)
88reverseIter :: Text -> Int -> (Char,Int)
84−reverseIter (Text arr off len) i
89+reverseIter (Text arr off _len) i
85 | m < 0xDC00 || m > 0xDFFF = (unsafeChr m, -1)
90 | m < 0xDC00 || m > 0xDFFF = (unsafeChr m, -1)
86 | otherwise = (chr2 n m, -2)
91 | otherwise = (chr2 n m, -2)
87− where m = assert (i < len) $ A.unsafeIndex arr j
92+ where m = A.unsafeIndex arr j
88− n = assert (i - 1 >= 0) $ A.unsafeIndex arr k
93+ n = A.unsafeIndex arr k
89− j = assert (i >= 0) $ off + i
94+ j = off + i
90− k = j - 1
95+ k = j - 1
91{-# INLINE reverseIter #-}
96{-# INLINE reverseIter #-}
93-- | Just like unsafePerformIO, but we inline it. Big performance gains as
98-- | Just like unsafePerformIO, but we inline it. Big performance gains as