Skip to content

Commit 7532a9f

Browse files
committed
Avoid reconstructing chars in commonPrefixes
1 parent b15a8fe commit 7532a9f

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

src/Data/Text.hs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ import Control.Monad.ST.Unsafe (unsafeIOToST)
222222
import qualified Data.Text.Array as A
223223
import qualified Data.List as L
224224
import Data.Binary (Binary(get, put))
225+
import Data.Int (Int8)
225226
import Data.Monoid (Monoid(..))
226227
import Data.Semigroup (Semigroup(..))
227228
import Data.String (IsString(..))
@@ -1922,16 +1923,26 @@ stripPrefix p@(Text _arr _off plen) t@(Text arr off len)
19221923
--
19231924
-- >>> commonPrefixes "" "baz"
19241925
-- Nothing
1925-
commonPrefixes :: Text -> Text -> Maybe (Text,Text,Text)
1926-
commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
1926+
commonPrefixes :: Text -> Text -> Maybe (Text, Text, Text)
1927+
commonPrefixes !t0@(Text arr0 off0 len0) !t1@(Text arr1 off1 len1)
1928+
| len0 == 0 = Nothing
1929+
| len1 == 0 = Nothing
1930+
| otherwise = go 0 0
19271931
where
1928-
go !i !j | i < len0 && j < len1 && a == b = go (i+d0) (j+d1)
1929-
| i > 0 = Just (Text arr0 off0 i,
1930-
text arr0 (off0+i) (len0-i),
1931-
text arr1 (off1+j) (len1-j))
1932-
| otherwise = Nothing
1933-
where Iter a d0 = iter t0 i
1934-
Iter b d1 = iter t1 j
1932+
go !i !j
1933+
| i == len0 = Just (t0, empty, text arr1 (off1 + i) (len1 - i))
1934+
| i == len1 = Just (t1, text arr0 (off0 + i) (len0 - i), empty)
1935+
| a == b = go (i + 1) k
1936+
| k > 0 = Just (Text arr0 off0 k,
1937+
Text arr0 (off0 + k) (len0 - k),
1938+
Text arr1 (off1 + k) (len1 - k))
1939+
| otherwise = Nothing
1940+
where
1941+
a = A.unsafeIndex arr0 (off0 + i)
1942+
b = A.unsafeIndex arr1 (off1 + i)
1943+
isLeader = word8ToInt8 a >= -64
1944+
k = if isLeader then i else j
1945+
{-# INLINE commonPrefixes #-}
19351946

19361947
-- | /O(n)/ Return the prefix of the second string if its suffix
19371948
-- matches the entire first string.
@@ -2002,6 +2013,9 @@ intToCSize = P.fromIntegral
20022013
cSsizeToInt :: CSsize -> Int
20032014
cSsizeToInt = P.fromIntegral
20042015

2016+
word8ToInt8 :: Word8 -> Int8
2017+
word8ToInt8 = P.fromIntegral
2018+
20052019
-------------------------------------------------
20062020
-- NOTE: the named chunk below used by doctest;
20072021
-- verify the doctests via `doctest -fobject-code Data/Text.hs`

0 commit comments

Comments
 (0)