Source

text / Text / Utf32 / Fusion.hs

The default branch has multiple heads

{-# OPTIONS_GHC -fbang-patterns #-}

module Text.Utf32.Fusion where
    
import Text.Fusion hiding (stream, unstream)
import Text.Utf32.Internal
import Text.UnsafeChar
import Data.Array.Base
import Data.Word
import Data.Array.ST
import Control.Monad.ST
import Char
import Control.Monad

stream :: Text -> Stream Char
stream (Text arr off len) = Stream next off len
    where    
      end = off+len
      {-# INLINE next #-}
      next !i
          | i >= end  = Done
          | otherwise = Yield (unsafeChr32 (arr `unsafeAt` i)) (i+1)
{-# INLINE [0] stream #-}

unstream :: Stream Char -> Text
unstream (Stream next0 s0 len) = x `seq` Text (fst x) 0 (snd x)
    where
      x :: ((UArray Int Word32),Int)
      x = runST ((unsafeNewArray_ (0,len) :: ST s (STUArray s Int Word32)) 
                 >>= (\arr -> loop arr 0 (len) s0))
      loop arr !i !max !s
          | i > max = do arr' <-unsafeNewArray_ (0,max*2)
                         copy arr arr'
                         loop arr' i (max*2) s
          | otherwise = case next0 s of
               Done       -> liftM2 (,) (unsafeFreezeSTUArray arr) (return i)
               Skip s'    -> loop arr i max s'
               Yield x s' -> do
                 unsafeWrite arr i n
                 loop arr (i+1) max s'
                   where
                     n :: Word32
                     n = fromIntegral $ ord x
{-# INLINE [0] unstream #-}

{-# RULES 
"STREAM stream/unstream fusion" forall s. 
   stream (unstream s) = s 
 #-}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.