on master help sign in
Expose and fix some subtle bugs.
d387502Bryan O'Sullivan
Data/Text/Fusion.hs+5−6
@@ -54,7 +54,7 @@ import Data.Bits ((.&.))
54import Data.Char (ord)
54import Data.Char (ord)
55import Data.Text.Internal (Text(..))
55import Data.Text.Internal (Text(..))
56import Data.Text.UnsafeChar (unsafeChr, unsafeWrite)
56import Data.Text.UnsafeChar (unsafeChr, unsafeWrite)
57−import Data.Text.UnsafeShift (shiftR)
57+import Data.Text.UnsafeShift (shiftL, shiftR)
58import qualified Data.Text.Array as A
58import qualified Data.Text.Array as A
59import qualified Data.Text.Fusion.Common as S
59import qualified Data.Text.Fusion.Common as S
60import Data.Text.Fusion.Internal
60import Data.Text.Fusion.Internal
@@ -97,9 +97,7 @@ reverseStream (Text arr off len) = Stream next (off+len-1) (maxSize len)
97
97
98-- | /O(n)/ Convert a 'Stream Char' into a 'Text'.
98-- | /O(n)/ Convert a 'Stream Char' into a 'Text'.
99unstream :: Stream Char -> Text
99unstream :: Stream Char -> Text
100−unstream (Stream next0 s0 len)
100+unstream (Stream next0 s0 len) = I.textP (P.fst a) 0 (P.snd a)
101− | isEmpty len = I.empty
102− | otherwise = I.textP (P.fst a) 0 (P.snd a)
103 where
101 where
104 mlen = upperBound 4 len
102 mlen = upperBound 4 len
105 a = A.run2 (A.unsafeNew mlen >>= (\arr -> loop arr mlen s0 0))
103 a = A.run2 (A.unsafeNew mlen >>= (\arr -> loop arr mlen s0 0))
@@ -107,8 +105,9 @@ unstream (Stream next0 s0 len)
107 | i + 1 >= top = case next0 s of
105 | i + 1 >= top = case next0 s of
108 Done -> return (arr, i)
106 Done -> return (arr, i)
109 _ -> do
107 _ -> do
108+ let top' = (top `shiftL` 1) + 1
110− arr' <- A.unsafeNew (top*2)
109+ arr' <- A.unsafeNew top'
111− A.copy arr arr' >> loop arr' (top*2) s i
110+ A.copy arr arr' >> loop arr' top' s i
112 | otherwise = case next0 s of
111 | otherwise = case next0 s of
113 Done -> return (arr, i)
112 Done -> return (arr, i)
114 Skip s' -> loop arr top s' i
113 Skip s' -> loop arr top s' i
Data/Text/Fusion/Common.hs+4−5
@@ -118,7 +118,6 @@ singleton c = Stream next False 1
118
118
119streamList :: [a] -> Stream a
119streamList :: [a] -> Stream a
120{-# INLINE [0] streamList #-}
120{-# INLINE [0] streamList #-}
121−streamList [] = empty
122streamList s = Stream next s unknownSize
121streamList s = Stream next s unknownSize
123 where next [] = Done
122 where next [] = Done
124 next (x:xs) = Yield x xs
123 next (x:xs) = Yield x xs
@@ -220,12 +219,12 @@ tail (Stream next0 s0 len) = Stream next (False :!: s0) (len-1)
220 where
219 where
221 {-# INLINE next #-}
220 {-# INLINE next #-}
222 next (False :!: s) = case next0 s of
221 next (False :!: s) = case next0 s of
223− Done -> emptyError "tail"
222+ Done -> emptyError "tail"
224− Skip s' -> Skip (False :!: s')
223+ Skip s' -> Skip (False :!: s')
225 Yield _ s' -> Skip (True :!: s')
224 Yield _ s' -> Skip (True :!: s')
226 next (True :!: s) = case next0 s of
225 next (True :!: s) = case next0 s of
227− Done -> Done
226+ Done -> Done
228− Skip s' -> Skip (True :!: s')
227+ Skip s' -> Skip (True :!: s')
229 Yield x s' -> Yield x (True :!: s')
228 Yield x s' -> Yield x (True :!: s')
230{-# INLINE [0] tail #-}
229{-# INLINE [0] tail #-}
231
230
Data/Text/Fusion/Internal.hs+1−3
@@ -48,12 +48,10 @@ data Step s a = Done
48 | Skip !s
48 | Skip !s
49 | Yield !a !s
49 | Yield !a !s
50
50
51−{-
52−instance Show a => Show (Step s a)
51+instance (Show a) => Show (Step s a)
53 where show Done = "Done"
52 where show Done = "Done"
54 show (Skip _) = "Skip"
53 show (Skip _) = "Skip"
55 show (Yield x _) = "Yield " ++ show x
54 show (Yield x _) = "Yield " ++ show x
56−-}
57
55
58instance (Eq a) => Eq (Stream a) where
56instance (Eq a) => Eq (Stream a) where
59 (==) = eq
57 (==) = eq
tests/Properties.hs+4
@@ -156,6 +156,7 @@ s_snoc x = (++ [x]) `eqP` (unpackS . (flip S.snoc) x)
156t_snoc x = (++ [x]) `eqP` (unpackS . (flip T.snoc) x)
156t_snoc x = (++ [x]) `eqP` (unpackS . (flip T.snoc) x)
157tl_snoc x = (++ [x]) `eqP` (unpackS . (flip TL.snoc) x)
157tl_snoc x = (++ [x]) `eqP` (unpackS . (flip TL.snoc) x)
158s_append s = (s++) `eqP` (unpackS . S.append (S.streamList s))
158s_append s = (s++) `eqP` (unpackS . S.append (S.streamList s))
159+s_append_s s = (s++) `eqP` (unpackS . S.unstream . S.append (S.streamList s))
159sf_append p s = (L.filter p s++) `eqP` (unpackS . S.append (S.filter p $ S.streamList s))
160sf_append p s = (L.filter p s++) `eqP` (unpackS . S.append (S.filter p $ S.streamList s))
160t_append s = (s++) `eqP` (unpackS . T.append (packS s))
161t_append s = (s++) `eqP` (unpackS . T.append (packS s))
161
162
@@ -175,6 +176,7 @@ sf_last p = (last . L.filter p) `eqP` (S.last . S.filter p)
175t_last = last `eqP` T.last
176t_last = last `eqP` T.last
176tl_last = last `eqP` TL.last
177tl_last = last `eqP` TL.last
177s_tail = tail `eqP` (unpackS . S.tail)
178s_tail = tail `eqP` (unpackS . S.tail)
179+s_tail_s = tail `eqP` (unpackS . S.unstream . S.tail)
178sf_tail p = (tail . L.filter p) `eqP` (unpackS . S.tail . S.filter p)
180sf_tail p = (tail . L.filter p) `eqP` (unpackS . S.tail . S.filter p)
179t_tail = tail `eqP` (unpackS . T.tail)
181t_tail = tail `eqP` (unpackS . T.tail)
180tl_tail = tail `eqP` (unpackS . TL.tail)
182tl_tail = tail `eqP` (unpackS . TL.tail)
@@ -585,6 +587,7 @@ tests = [
585 testProperty "t_snoc" t_snoc,
587 testProperty "t_snoc" t_snoc,
586 testProperty "tl_snoc" tl_snoc,
588 testProperty "tl_snoc" tl_snoc,
587 testProperty "s_append" s_append,
589 testProperty "s_append" s_append,
590+ testProperty "s_append_s" s_append_s,
588 testProperty "sf_append" sf_append,
591 testProperty "sf_append" sf_append,
589 testProperty "t_append" t_append,
592 testProperty "t_append" t_append,
590 testProperty "s_uncons" s_uncons,
593 testProperty "s_uncons" s_uncons,
@@ -600,6 +603,7 @@ tests = [
600 testProperty "t_last" t_last,
603 testProperty "t_last" t_last,
601 testProperty "tl_last" tl_last,
604 testProperty "tl_last" tl_last,
602 testProperty "s_tail" s_tail,
605 testProperty "s_tail" s_tail,
606+ testProperty "s_tail_s" s_tail_s,
603 testProperty "sf_tail" sf_tail,
607 testProperty "sf_tail" sf_tail,
604 testProperty "t_tail" t_tail,
608 testProperty "t_tail" t_tail,
605 testProperty "tl_tail" tl_tail,
609 testProperty "tl_tail" tl_tail,