@@ -1,4 +1,10 @@
1{-# LANGUAGE BangPatterns #-}
1{-# LANGUAGE BangPatterns #-}
4+{-# LANGUAGE ForeignFunctionInterface #-}
5+{-# LANGUAGE MagicHash #-}
6+{-# LANGUAGE UnliftedFFITypes #-}
3-- Module : Data.Text.Lazy.Fusion
9-- Module : Data.Text.Lazy.Fusion
4-- Copyright : (c) 2009, 2010 Bryan O'Sullivan
10-- Copyright : (c) 2009, 2010 Bryan O'Sullivan
@@ -29,65 +35,110 @@ import Prelude hiding (length)
29import qualified Data.Text.Internal.Fusion.Common as S
35import qualified Data.Text.Internal.Fusion.Common as S
30import Control.Monad.ST (runST)
36import Control.Monad.ST (runST)
31import Data.Text.Internal.Fusion.Types
37import Data.Text.Internal.Fusion.Types
32import Data.Text.Internal.Fusion.Size (isEmpty, unknownSize)
39import Data.Text.Internal.Fusion.Size (isEmpty, unknownSize)
41+import Data.JSString (JSString)
42+import qualified Data.JSString as JSS
43+import GHC.Base (Int(..))
44+import GHC.Exts (ByteArray#, Int#)
33import Data.Text.Internal.Lazy
46import Data.Text.Internal.Lazy
34import qualified Data.Text.Internal as I
47import qualified Data.Text.Internal as I
35import qualified Data.Text.Array as A
48import qualified Data.Text.Array as A
36import Data.Text.Internal.Unsafe.Char (unsafeWrite)
49import Data.Text.Internal.Unsafe.Char (unsafeWrite)
37import Data.Text.Internal.Unsafe.Shift (shiftL)
50import Data.Text.Internal.Unsafe.Shift (shiftL)
38−-- import Data.Text.Unsafe (Iter(..), iter)
51+import Data.Text.Unsafe (Iter(..), iter)
39import Data.Int (Int64)
52import Data.Int (Int64)
41default(Int64)
54default(Int64)
44-- | /O(n)/ Convert a 'Text' into a 'Stream Char'.
56-- | /O(n)/ Convert a 'Text' into a 'Stream Char'.
45stream :: Text -> Stream Char
57stream :: Text -> Stream Char
46−stream = undefined
58+#ifndef __GHCJS__
47−-- stream text = Stream next (text :*: 0) unknownSize
59+stream text = Stream next (text :*: 0) unknownSize
49−-- next (Empty :*: _) = Done
61+ next (Empty :*: _) = Done
50−-- next (txt@(Chunk t@(I.Text _ _ len) ts) :*: i)
62+ next (txt@(Chunk t@(I.Text _ _ len) ts) :*: i)
51−-- | i >= len = next (ts :*: 0)
63+ | i >= len = next (ts :*: 0)
52−-- | otherwise = Yield c (txt :*: i+d)
64+ | otherwise = Yield c (txt :*: i+d)
65+ where Iter c d = iter t i
67+stream text = Stream next (text :*: 0) -- unknownSize
69+ next (Empty :*: _) = Done
70+ next (txt@(Chunk t@(I.Text jst) ts) :*: i)
71+ | i >= JSS.length jst = next (ts :*: 0)
72+ | otherwise = Yield c (txt :*: i+d)
53− -- where Iter c d = iter t i
73+ where Iter c d = iter t i
54{-# INLINE [0] stream #-}
75{-# INLINE [0] stream #-}
57-- | /O(n)/ Convert a 'Stream Char' into a 'Text', using the given
78-- | /O(n)/ Convert a 'Stream Char' into a 'Text', using the given
58-- chunk size.
79-- chunk size.
59unstreamChunks :: Int -> Stream Char -> Text
80unstreamChunks :: Int -> Stream Char -> Text
60−unstreamChunks = undefined
81+#ifndef __GHCJS__
61−-- unstreamChunks !chunkSize (Stream next s0 len0)
82+unstreamChunks !chunkSize (Stream next s0 len0)
62−-- | isEmpty len0 = Empty
83+ | isEmpty len0 = Empty
63−-- | otherwise = outer s0
84+ | otherwise = outer s0
65−-- outer so = {-# SCC "unstreamChunks/outer" #-}
86+ outer so = {-# SCC "unstreamChunks/outer" #-}
66−-- case next so of
87+ case next so of
67−-- Done -> Empty
88+ Done -> Empty
68−-- Skip s' -> outer s'
89+ Skip s' -> outer s'
69−-- Yield x s' -> runST $ do
90+ Yield x s' -> runST $ do
70−-- a <- A.new unknownLength
91+ a <- A.new unknownLength
71−-- unsafeWrite a 0 x >>= inner a unknownLength s'
92+ unsafeWrite a 0 x >>= inner a unknownLength s'
72−-- where unknownLength = 4
93+ where unknownLength = 4
74−-- inner marr !len s !i
95+ inner marr !len s !i
75−-- | i + 1 >= chunkSize = finish marr i s
96+ | i + 1 >= chunkSize = finish marr i s
76−-- | i + 1 >= len = {-# SCC "unstreamChunks/resize" #-} do
97+ | i + 1 >= len = {-# SCC "unstreamChunks/resize" #-} do
77−-- let newLen = min (len `shiftL` 1) chunkSize
98+ let newLen = min (len `shiftL` 1) chunkSize
78−-- marr' <- A.new newLen
99+ marr' <- A.new newLen
79−-- A.copyM marr' 0 marr 0 len
100+ A.copyM marr' 0 marr 0 len
80−-- inner marr' newLen s i
101+ inner marr' newLen s i
81−-- | otherwise =
102+ | otherwise =
82−-- {-# SCC "unstreamChunks/inner" #-}
103+ {-# SCC "unstreamChunks/inner" #-}
83−-- case next s of
104+ case next s of
84−-- Done -> finish marr i s
105+ Done -> finish marr i s
85−-- Skip s' -> inner marr len s' i
106+ Skip s' -> inner marr len s' i
86−-- Yield x s' -> do d <- unsafeWrite marr i x
107+ Yield x s' -> do d <- unsafeWrite marr i x
87−-- inner marr len s' (i+d)
108+ inner marr len s' (i+d)
88−-- finish marr len s' = do
109+ finish marr len s' = do
89−-- arr <- A.unsafeFreeze marr
110+ arr <- A.unsafeFreeze marr
90−-- return (I.Text arr 0 len `Chunk` outer s')
111+ return (I.Text arr 0 len `Chunk` outer s')
113+unstreamChunks !chunkSize (Stream next s0) = outer s0
115+ outer so = {-# SCC "unstreamChunks/outer" #-}
119+ Yield x s' -> runST $ do
120+ a <- A.new unknownLength
121+ unsafeWrite a 0 x >>= inner a unknownLength s'
122+ where unknownLength = 4
124+ inner marr !len s !i
125+ | i + 1 >= chunkSize = finish marr i s
126+ | i + 1 >= len = {-# SCC "unstreamChunks/resize" #-} do
127+ let newLen = min (len `shiftL` 1) chunkSize
128+ marr' <- A.new newLen
129+ A.copyM marr' 0 marr 0 len
130+ inner marr' newLen s i
132+ {-# SCC "unstreamChunks/inner" #-}
134+ Done -> finish marr i s
135+ Skip s' -> inner marr len s' i
136+ Yield x s' -> do d <- unsafeWrite marr i x
137+ inner marr len s' (i+d)
138+ finish marr (I# len#) s' = do
139+ arr <- A.unsafeFreeze marr
140+ return (I.Text (js_toString (A.aBA arr) 0# len#) `Chunk` outer s')
91{-# INLINE [0] unstreamChunks #-}
142{-# INLINE [0] unstreamChunks #-}
93-- | /O(n)/ Convert a 'Stream Char' into a 'Text', using
144-- | /O(n)/ Convert a 'Stream Char' into a 'Text', using
@@ -122,3 +173,10 @@ index = S.indexI
122countChar :: Char -> Stream Char -> Int64
173countChar :: Char -> Stream Char -> Int64
123countChar = S.countCharI
174countChar = S.countCharI
124{-# INLINE [0] countChar #-}
175{-# INLINE [0] countChar #-}
178+foreign import javascript unsafe
180+ js_toString :: ByteArray# -> Int# -> Int# -> JSString