{-# LANGUAGE BangPatterns, CPP, MagicHash, RankNTypes, RecordWildCards, UnboxedTuples, UnliftedFFITypes #-}{-# OPTIONS_GHC -fno-warn-unused-matches #-}-- |-- Module : Data.Text.Array-- Copyright : (c) 2009, 2010, 2011 Bryan O'Sullivan---- License : BSD-style-- Maintainer : bos@serpentine.com-- Portability : portable---- Packed, unboxed, heap-resident arrays. Suitable for performance-- critical use, both in terms of large data quantities and high-- speed.---- This module is intended to be imported @qualified@, to avoid name-- clashes with "Prelude" functions, e.g.---- > import qualified Data.Text.Array as A---- The names in this module resemble those in the 'Data.Array' family-- of modules, but are shorter due to the assumption of qualified-- naming.moduleData.Text.Array(-- * TypesArray (..),MArray (..)-- * Functions,resizeM ,shrinkM ,copyM ,copyI ,copyFromPointer ,copyToPointer ,empty ,equal ,compare ,run ,run2 ,toList ,unsafeFreeze ,unsafeIndex ,new ,newPinned ,newFilled ,unsafeWrite ,tile ,getSizeofMArray )where #if defined(ASSERTS) importGHC.Stack(HasCallStack) #endif #if !MIN_VERSION_base(4,11,0) importForeign.C.Types(CInt(..)) #endif importGHC.Extshiding(toList)importGHC.ST(ST(..),runST)importGHC.Word(Word8(..))importqualifiedPreludeimportPreludehiding(length,read,compare)-- | Immutable array type.dataArray =ByteArray ByteArray#-- | Mutable array type, for use in the ST monad.dataMArray s =MutableByteArray (MutableByteArray#s )-- | Create an uninitialized mutable array.new ::foralls .Int->STs (MArray s )new :: forall s. Int -> ST s (MArray s) new (I#Int# len# ) #if defined(ASSERTS) |I#len#<0=error"Data.Text.Array.new: size overflow" #endif |Bool otherwise=forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. Int# -> State# d -> (# State# d, MutableByteArray# d #) newByteArray#Int# len# State# s s1# of(#State# s s2# ,MutableByteArray# s marr# #)->(#State# s s2# ,forall s. MutableByteArray# s -> MArray s MutableByteArray MutableByteArray# s marr# #){-# INLINEnew #-}-- | Create an uninitialized mutable pinned array.---- @since 2.0newPinned ::foralls .Int->STs (MArray s )newPinned :: forall s. Int -> ST s (MArray s) newPinned (I#Int# len# ) #if defined(ASSERTS) |I#len#<0=error"Data.Text.Array.newPinned: size overflow" #endif |Bool otherwise=forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. Int# -> State# d -> (# State# d, MutableByteArray# d #) newPinnedByteArray#Int# len# State# s s1# of(#State# s s2# ,MutableByteArray# s marr# #)->(#State# s s2# ,forall s. MutableByteArray# s -> MArray s MutableByteArray MutableByteArray# s marr# #){-# INLINEnewPinned #-}-- | @since 2.0newFilled ::Int->Int->STs (MArray s )newFilled :: forall s. Int -> Int -> ST s (MArray s) newFilled (I#Int# len# )(I#Int# c# )=forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. Int# -> State# d -> (# State# d, MutableByteArray# d #) newByteArray#Int# len# State# s s1# of(#State# s s2# ,MutableByteArray# s marr# #)->caseforall d. MutableByteArray# d -> Int# -> Int# -> Int# -> State# d -> State# d setByteArray#MutableByteArray# s marr# Int# 0#Int# len# Int# c# State# s s2# ofState# s s3# ->(#State# s s3# ,forall s. MutableByteArray# s -> MArray s MutableByteArray MutableByteArray# s marr# #){-# INLINEnewFilled #-}-- | @since 2.0tile ::MArray s ->Int->STs ()tile :: forall s. MArray s -> Int -> ST s () tile MArray s marr Int tileLen =doInt totalLen <-forall s. MArray s -> ST s Int getSizeofMArray MArray s marr letgo :: Int -> ST s () go Int l |Int 2forall a. Num a => a -> a -> a *Int l forall a. Ord a => a -> a -> Bool >Int totalLen =forall s. MArray s -> Int -> MArray s -> Int -> Int -> ST s () copyM MArray s marr Int l MArray s marr Int 0(Int totalLen forall a. Num a => a -> a -> a -Int l )|Bool otherwise=forall s. MArray s -> Int -> MArray s -> Int -> Int -> ST s () copyM MArray s marr Int l MArray s marr Int 0Int l forall (m :: * -> *) a b. Monad m => m a -> m b -> m b >>Int -> ST s () go (Int 2forall a. Num a => a -> a -> a *Int l )Int -> ST s () go Int tileLen {-# INLINEtile #-}-- | Freeze a mutable array. Do not mutate the 'MArray' afterwards!unsafeFreeze ::MArray s ->STs Array unsafeFreeze :: forall s. MArray s -> ST s Array unsafeFreeze (MutableByteArray MutableByteArray# s marr )=forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. MutableByteArray# d -> State# d -> (# State# d, ByteArray# #) unsafeFreezeByteArray#MutableByteArray# s marr State# s s1# of(#State# s s2# ,ByteArray# ba# #)->(#State# s s2# ,ByteArray# -> Array ByteArray ByteArray# ba# #){-# INLINEunsafeFreeze #-}-- | Unchecked read of an immutable array. May return garbage or-- crash on an out-of-bounds access.unsafeIndex :: #if defined(ASSERTS) HasCallStack=> #endif Array ->Int->Word8unsafeIndex :: Array -> Int -> Word8 unsafeIndex (ByteArray ByteArray# arr )i :: Int i @(I#Int# i# )= #if defined(ASSERTS) letword8len=I#(sizeofByteArray#arr)inifi<0||i>=word8lenthenerror("Data.Text.Array.unsafeIndex: bounds error, offset "++showi++", length "++showword8len)else #endif caseByteArray# -> Int# -> Word8# indexWord8Array#ByteArray# arr Int# i# ofWord8# r# ->(Word8# -> Word8 W8#Word8# r# ){-# INLINEunsafeIndex #-}-- | @since 2.0getSizeofMArray ::MArray s ->STs IntgetSizeofMArray :: forall s. MArray s -> ST s Int getSizeofMArray (MutableByteArray MutableByteArray# s marr )=forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s0# ->-- Cannot simply use (deprecated) 'sizeofMutableByteArray#', because it is-- unsafe in the presence of 'shrinkMutableByteArray#' and 'resizeMutableByteArray#'.caseforall d. MutableByteArray# d -> State# d -> (# State# d, Int# #) getSizeofMutableByteArray#MutableByteArray# s marr State# s s0# of(#State# s s1# ,Int# word8len# #)->(#State# s s1# ,Int# -> Int I#Int# word8len# #) #if defined(ASSERTS) checkBoundsM::HasCallStack=>MArrays->Int->Int->STs()checkBoundsMmaielSize=dolen<-getSizeofMArraymaifi<0||i+elSize>lenthenerror("bounds error, offset "++showi++", length "++showlen)elsereturn() #endif -- | Unchecked write of a mutable array. May return garbage or crash-- on an out-of-bounds access.unsafeWrite :: #if defined(ASSERTS) HasCallStack=> #endif MArray s ->Int->Word8->STs ()unsafeWrite :: forall s. MArray s -> Int -> Word8 -> ST s () unsafeWrite ma :: MArray s ma @(MutableByteArray MutableByteArray# s marr )i :: Int i @(I#Int# i# )(W8#Word8# e# )= #if defined(ASSERTS) checkBoundsMmai1>> #endif (forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. MutableByteArray# d -> Int# -> Word8# -> State# d -> State# d writeWord8Array#MutableByteArray# s marr Int# i# Word8# e# State# s s1# ofState# s s2# ->(#State# s s2# ,()#)){-# INLINEunsafeWrite #-}-- | Convert an immutable array to a list.toList ::Array ->Int->Int->[Word8]toList :: Array -> Int -> Int -> [Word8] toList Array ary Int off Int len =Int -> [Word8] loop Int 0whereloop :: Int -> [Word8] loop Int i |Int i forall a. Ord a => a -> a -> Bool <Int len =Array -> Int -> Word8 unsafeIndex Array ary (Int off forall a. Num a => a -> a -> a +Int i )forall a. a -> [a] -> [a] :Int -> [Word8] loop (Int i forall a. Num a => a -> a -> a +Int 1)|Bool otherwise=[]-- | An empty immutable array.empty ::Array empty :: Array empty =forall a. (forall s. ST s a) -> a runST(forall s. Int -> ST s (MArray s) new Int 0forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>=forall s. MArray s -> ST s Array unsafeFreeze )-- | Run an action in the ST monad and return an immutable array of-- its result.run ::(foralls .STs (MArray s ))->Array run :: (forall s. ST s (MArray s)) -> Array run forall s. ST s (MArray s) k =forall a. (forall s. ST s a) -> a runST(forall s. ST s (MArray s) k forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>=forall s. MArray s -> ST s Array unsafeFreeze )-- | Run an action in the ST monad and return an immutable array of-- its result paired with whatever else the action returns.run2 ::(foralls .STs (MArray s ,a ))->(Array ,a )run2 :: forall a. (forall s. ST s (MArray s, a)) -> (Array, a) run2 forall s. ST s (MArray s, a) k =forall a. (forall s. ST s a) -> a runST(do(MArray s marr ,a b )<-forall s. ST s (MArray s, a) k Array arr <-forall s. MArray s -> ST s Array unsafeFreeze MArray s marr forall (m :: * -> *) a. Monad m => a -> m a return(Array arr ,a b )){-# INLINErun2 #-}-- | @since 2.0resizeM ::MArray s ->Int->STs (MArray s )resizeM :: forall s. MArray s -> Int -> ST s (MArray s) resizeM (MutableByteArray MutableByteArray# s ma )i :: Int i @(I#Int# i# )=forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. MutableByteArray# d -> Int# -> State# d -> (# State# d, MutableByteArray# d #) resizeMutableByteArray#MutableByteArray# s ma Int# i# State# s s1# of(#State# s s2# ,MutableByteArray# s newArr #)->(#State# s s2# ,forall s. MutableByteArray# s -> MArray s MutableByteArray MutableByteArray# s newArr #){-# INLINEresizeM #-}-- | @since 2.0shrinkM :: #if defined(ASSERTS) HasCallStack=> #endif MArray s ->Int->STs ()shrinkM :: forall s. MArray s -> Int -> ST s () shrinkM (MutableByteArray MutableByteArray# s marr )i :: Int i @(I#Int# newSize )=do #if defined(ASSERTS) oldSize<-getSizeofMArray(MutableByteArraymarr)ifI#newSize>oldSizethenerror$"shrinkM: shrink cannot grow "++showoldSize++" to "++show(I#newSize)elsereturn() #endif forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. MutableByteArray# d -> Int# -> State# d -> State# d shrinkMutableByteArray#MutableByteArray# s marr Int# newSize State# s s1# ofState# s s2# ->(#State# s s2# ,()#){-# INLINEshrinkM #-}-- | Copy some elements of a mutable array.copyM ::MArray s -- ^ Destination->Int-- ^ Destination offset->MArray s -- ^ Source->Int-- ^ Source offset->Int-- ^ Count->STs ()copyM :: forall s. MArray s -> Int -> MArray s -> Int -> Int -> ST s () copyM dst :: MArray s dst @(MutableByteArray MutableByteArray# s dst# )dstOff :: Int dstOff @(I#Int# dstOff# )src :: MArray s src @(MutableByteArray MutableByteArray# s src# )srcOff :: Int srcOff @(I#Int# srcOff# )count :: Int count @(I#Int# count# ) #if defined(ASSERTS) |count<0=error$"copyM: count must be >= 0, but got "++showcount #endif |Bool otherwise=do #if defined(ASSERTS) srcLen<-getSizeofMArraysrcdstLen<-getSizeofMArraydstifsrcOff+count>srcLenthenerror"copyM: source is too short"elsereturn()ifdstOff+count>dstLenthenerror"copyM: destination is too short"elsereturn() #endif forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. MutableByteArray# d -> Int# -> MutableByteArray# d -> Int# -> Int# -> State# d -> State# d copyMutableByteArray#MutableByteArray# s src# Int# srcOff# MutableByteArray# s dst# Int# dstOff# Int# count# State# s s1# ofState# s s2# ->(#State# s s2# ,()#){-# INLINEcopyM #-}-- | Copy some elements of an immutable array.copyI ::Int-- ^ Count->MArray s -- ^ Destination->Int-- ^ Destination offset->Array -- ^ Source->Int-- ^ Source offset->STs ()copyI :: forall s. Int -> MArray s -> Int -> Array -> Int -> ST s () copyI count :: Int count @(I#Int# count# )(MutableByteArray MutableByteArray# s dst# )dstOff :: Int dstOff @(I#Int# dstOff# )(ByteArray ByteArray# src# )(I#Int# srcOff# ) #if defined(ASSERTS) |count<0=error$"copyI: count must be >= 0, but got "++showcount #endif |Bool otherwise=forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. ByteArray# -> Int# -> MutableByteArray# d -> Int# -> Int# -> State# d -> State# d copyByteArray#ByteArray# src# Int# srcOff# MutableByteArray# s dst# Int# dstOff# Int# count# State# s s1# ofState# s s2# ->(#State# s s2# ,()#){-# INLINEcopyI #-}-- | Copy from pointer.---- @since 2.0copyFromPointer ::MArray s -- ^ Destination->Int-- ^ Destination offset->PtrWord8-- ^ Source->Int-- ^ Count->STs ()copyFromPointer :: forall s. MArray s -> Int -> Ptr Word8 -> Int -> ST s () copyFromPointer (MutableByteArray MutableByteArray# s dst# )dstOff :: Int dstOff @(I#Int# dstOff# )(PtrAddr# src# )count :: Int count @(I#Int# count# ) #if defined(ASSERTS) |count<0=error$"copyFromPointer: count must be >= 0, but got "++showcount #endif |Bool otherwise=forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. Addr# -> MutableByteArray# d -> Int# -> Int# -> State# d -> State# d copyAddrToByteArray#Addr# src# MutableByteArray# s dst# Int# dstOff# Int# count# State# s s1# ofState# s s2# ->(#State# s s2# ,()#){-# INLINEcopyFromPointer #-}-- | Copy to pointer.---- @since 2.0copyToPointer ::Array -- ^ Source->Int-- ^ Source offset->PtrWord8-- ^ Destination->Int-- ^ Count->STs ()copyToPointer :: forall s. Array -> Int -> Ptr Word8 -> Int -> ST s () copyToPointer (ByteArray ByteArray# src# )srcOff :: Int srcOff @(I#Int# srcOff# )(PtrAddr# dst# )count :: Int count @(I#Int# count# ) #if defined(ASSERTS) |count<0=error$"copyToPointer: count must be >= 0, but got "++showcount #endif |Bool otherwise=forall s a. STRep s a -> ST s a STforall a b. (a -> b) -> a -> b $\State# s s1# ->caseforall d. ByteArray# -> Int# -> Addr# -> Int# -> State# d -> State# d copyByteArrayToAddr#ByteArray# src# Int# srcOff# Addr# dst# Int# count# State# s s1# ofState# s s2# ->(#State# s s2# ,()#){-# INLINEcopyToPointer #-}-- | Compare portions of two arrays for equality. No bounds checking-- is performed.equal ::Array ->Int->Array ->Int->Int->Boolequal :: Array -> Int -> Array -> Int -> Int -> Bool equal Array src1 Int off1 Array src2 Int off2 Int count =Array -> Int -> Array -> Int -> Int -> Int compareInternal Array src1 Int off1 Array src2 Int off2 Int count forall a. Eq a => a -> a -> Bool ==Int 0{-# INLINEequal #-}-- | Compare portions of two arrays. No bounds checking is performed.---- @since 2.0compare ::Array ->Int->Array ->Int->Int->Orderingcompare :: Array -> Int -> Array -> Int -> Int -> Ordering compare Array src1 Int off1 Array src2 Int off2 Int count =Array -> Int -> Array -> Int -> Int -> Int compareInternal Array src1 Int off1 Array src2 Int off2 Int count forall a. Ord a => a -> a -> Ordering `Prelude.compare`Int 0{-# INLINEcompare #-}compareInternal ::Array -- ^ First->Int-- ^ Offset into first->Array -- ^ Second->Int-- ^ Offset into second->Int-- ^ Count->IntcompareInternal :: Array -> Int -> Array -> Int -> Int -> Int compareInternal (ByteArray ByteArray# src1# )(I#Int# off1# )(ByteArray ByteArray# src2# )(I#Int# off2# )(I#Int# count# )=Int i where #if MIN_VERSION_base(4,11,0) i :: Int i =Int# -> Int I#(ByteArray# -> Int# -> ByteArray# -> Int# -> Int# -> Int# compareByteArrays#ByteArray# src1# Int# off1# ByteArray# src2# Int# off2# Int# count# ) #else i=fromIntegral(memcmpsrc1#off1#src2#off2#count#)foreignimportccallunsafe"_hs_text_memcmp2"memcmp::ByteArray#->Int#->ByteArray#->Int#->Int#->CInt #endif {-# INLINEcompareInternal #-}