on master help sign in
Lazy Text Funsion stream/unstream.
commitc79eced7a21ced2c7c89d77a61e419aeb4994395 authorLuigy Leon <luigy@outlook.com> dateWed 28 Sep 2016, 11:32 (10 years ago) parentd1c5d18
1 file changed+99−41
Data/Text/Internal/Lazy/Fusion.hs+99−41
Data/Text/Internal/Lazy/Fusion.hs+99−41
@@ -1,4 +1,10 @@
11{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE CPP #-}
3+#ifdef __GHCJS__
4+{-# LANGUAGE ForeignFunctionInterface #-}
5+{-# LANGUAGE MagicHash #-}
6+{-# LANGUAGE UnliftedFFITypes #-}
7+#endif
28-- |
39-- Module : Data.Text.Lazy.Fusion
410-- Copyright : (c) 2009, 2010 Bryan O'Sullivan
@@ -29,65 +35,110 @@ import Prelude hiding (length)
2935import qualified Data.Text.Internal.Fusion.Common as S
3036import Control.Monad.ST (runST)
3137import Data.Text.Internal.Fusion.Types
38+#ifndef __GHCJS__
3239import Data.Text.Internal.Fusion.Size (isEmpty, unknownSize)
40+#else
41+import Data.JSString (JSString)
42+import qualified Data.JSString as JSS
43+import GHC.Base (Int(..))
44+import GHC.Exts (ByteArray#, Int#)
45+#endif
3346import Data.Text.Internal.Lazy
3447import qualified Data.Text.Internal as I
3548import qualified Data.Text.Array as A
3649import Data.Text.Internal.Unsafe.Char (unsafeWrite)
3750import Data.Text.Internal.Unsafe.Shift (shiftL)
38−-- import Data.Text.Unsafe (Iter(..), iter)
51+import Data.Text.Unsafe (Iter(..), iter)
3952import Data.Int (Int64)
4053
4154default(Int64)
4255
43−-- TODO
4456-- | /O(n)/ Convert a 'Text' into a 'Stream Char'.
4557stream :: Text -> Stream Char
46−stream = undefined
47−-- stream text = Stream next (text :*: 0) unknownSize
48−-- where
49−-- next (Empty :*: _) = Done
50−-- next (txt@(Chunk t@(I.Text _ _ len) ts) :*: i)
51−-- | i >= len = next (ts :*: 0)
52−-- | otherwise = Yield c (txt :*: i+d)
53− -- where Iter c d = iter t i
58+#ifndef __GHCJS__
59+stream text = Stream next (text :*: 0) unknownSize
60+ where
61+ next (Empty :*: _) = Done
62+ next (txt@(Chunk t@(I.Text _ _ len) ts) :*: i)
63+ | i >= len = next (ts :*: 0)
64+ | otherwise = Yield c (txt :*: i+d)
65+ where Iter c d = iter t i
66+#else
67+stream text = Stream next (text :*: 0) -- unknownSize
68+ where
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)
73+ where Iter c d = iter t i
74+#endif
5475{-# INLINE [0] stream #-}
5576
5677-- TODO
5778-- | /O(n)/ Convert a 'Stream Char' into a 'Text', using the given
5879-- chunk size.
5980unstreamChunks :: Int -> Stream Char -> Text
60−unstreamChunks = undefined
61−-- unstreamChunks !chunkSize (Stream next s0 len0)
62−-- | isEmpty len0 = Empty
63−-- | otherwise = outer s0
64−-- where
65−-- outer so = {-# SCC "unstreamChunks/outer" #-}
66−-- case next so of
67−-- Done -> Empty
68−-- Skip s' -> outer s'
69−-- Yield x s' -> runST $ do
70−-- a <- A.new unknownLength
71−-- unsafeWrite a 0 x >>= inner a unknownLength s'
72−-- where unknownLength = 4
73−-- where
74−-- inner marr !len s !i
75−-- | i + 1 >= chunkSize = finish marr i s
76−-- | i + 1 >= len = {-# SCC "unstreamChunks/resize" #-} do
77−-- let newLen = min (len `shiftL` 1) chunkSize
78−-- marr' <- A.new newLen
79−-- A.copyM marr' 0 marr 0 len
80−-- inner marr' newLen s i
81−-- | otherwise =
82−-- {-# SCC "unstreamChunks/inner" #-}
83−-- case next s of
84−-- Done -> finish marr i s
85−-- Skip s' -> inner marr len s' i
86−-- Yield x s' -> do d <- unsafeWrite marr i x
87−-- inner marr len s' (i+d)
88−-- finish marr len s' = do
89−-- arr <- A.unsafeFreeze marr
90−-- return (I.Text arr 0 len `Chunk` outer s')
81+#ifndef __GHCJS__
82+unstreamChunks !chunkSize (Stream next s0 len0)
83+ | isEmpty len0 = Empty
84+ | otherwise = outer s0
85+ where
86+ outer so = {-# SCC "unstreamChunks/outer" #-}
87+ case next so of
88+ Done -> Empty
89+ Skip s' -> outer s'
90+ Yield x s' -> runST $ do
91+ a <- A.new unknownLength
92+ unsafeWrite a 0 x >>= inner a unknownLength s'
93+ where unknownLength = 4
94+ where
95+ inner marr !len s !i
96+ | i + 1 >= chunkSize = finish marr i s
97+ | i + 1 >= len = {-# SCC "unstreamChunks/resize" #-} do
98+ let newLen = min (len `shiftL` 1) chunkSize
99+ marr' <- A.new newLen
100+ A.copyM marr' 0 marr 0 len
101+ inner marr' newLen s i
102+ | otherwise =
103+ {-# SCC "unstreamChunks/inner" #-}
104+ case next s of
105+ Done -> finish marr i s
106+ Skip s' -> inner marr len s' i
107+ Yield x s' -> do d <- unsafeWrite marr i x
108+ inner marr len s' (i+d)
109+ finish marr len s' = do
110+ arr <- A.unsafeFreeze marr
111+ return (I.Text arr 0 len `Chunk` outer s')
112+#else
113+unstreamChunks !chunkSize (Stream next s0) = outer s0
114+ where
115+ outer so = {-# SCC "unstreamChunks/outer" #-}
116+ case next so of
117+ Done -> Empty
118+ Skip s' -> outer s'
119+ Yield x s' -> runST $ do
120+ a <- A.new unknownLength
121+ unsafeWrite a 0 x >>= inner a unknownLength s'
122+ where unknownLength = 4
123+ where
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
131+ | otherwise =
132+ {-# SCC "unstreamChunks/inner" #-}
133+ case next s of
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')
141+#endif
91142{-# INLINE [0] unstreamChunks #-}
92143
93144-- | /O(n)/ Convert a 'Stream Char' into a 'Text', using
@@ -122,3 +173,10 @@ index = S.indexI
122173countChar :: Char -> Stream Char -> Int64
123174countChar = S.countCharI
124175{-# INLINE [0] countChar #-}
176+
177+#ifdef __GHCJS__
178+foreign import javascript unsafe
179+ "h$textToString"
180+ js_toString :: ByteArray# -> Int# -> Int# -> JSString
181+#endif
182+