Skip to content

Commit 5945caf

Browse files
committed
Implement copy from/to pointer via primops
1 parent 04ff3b7 commit 5945caf

File tree

2 files changed

+44
-24
lines changed

2 files changed

+44
-24
lines changed

src/Data/Text/Array.hs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ module Data.Text.Array
3131
, shrinkM
3232
, copyM
3333
, copyI
34+
, copyFromPointer
35+
, copyToPointer
3436
, empty
3537
, equal
3638
, compare
@@ -250,6 +252,40 @@ copyI count@(I# count#) (MutableByteArray dst#) dstOff@(I# dstOff#) (ByteArray s
250252
s2# -> (# s2#, () #)
251253
{-# INLINE copyI #-}
252254

255+
-- | Copy from pointer.
256+
copyFromPointer
257+
:: MArray s -- ^ Destination
258+
-> Int -- ^ Destination offset
259+
-> Ptr Word8 -- ^ Source
260+
-> Int -- ^ Count
261+
-> ST s ()
262+
copyFromPointer (MutableByteArray dst#) dstOff@(I# dstOff#) (Ptr src#) count@(I# count#)
263+
#if defined(ASSERTS)
264+
| count < 0 = error $
265+
"copyFromPointer: count must be >= 0, but got " ++ show count
266+
#endif
267+
| otherwise = ST $ \s1# ->
268+
case copyAddrToByteArray# src# dst# dstOff# count# s1# of
269+
s2# -> (# s2#, () #)
270+
{-# INLINE copyFromPointer #-}
271+
272+
-- | Copy to pointer.
273+
copyToPointer
274+
:: Array -- ^ Source
275+
-> Int -- ^ Source offset
276+
-> Ptr Word8 -- ^ Destination
277+
-> Int -- ^ Count
278+
-> ST s ()
279+
copyToPointer (ByteArray src#) srcOff@(I# srcOff#) (Ptr dst#) count@(I# count#)
280+
#if defined(ASSERTS)
281+
| count < 0 = error $
282+
"copyToPointer: count must be >= 0, but got " ++ show count
283+
#endif
284+
| otherwise = ST $ \s1# ->
285+
case copyByteArrayToAddr# src# srcOff# dst# count# s1# of
286+
s2# -> (# s2#, () #)
287+
{-# INLINE copyToPointer #-}
288+
253289
-- | Compare portions of two arrays for equality. No bounds checking
254290
-- is performed.
255291
equal :: Array -> Int -> Array -> Int -> Int -> Bool

src/Data/Text/Foreign.hs

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ module Data.Text.Foreign
3434
#if defined(ASSERTS)
3535
import Control.Exception (assert)
3636
#endif
37-
import Control.Monad.ST.Unsafe (unsafeIOToST)
37+
import Control.Monad.ST.Unsafe (unsafeSTToIO)
3838
import Data.ByteString.Unsafe (unsafePackCStringLen, unsafeUseAsCStringLen)
3939
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
4040
import Data.Text.Internal (Text(..), empty)
@@ -44,8 +44,7 @@ import Data.Word (Word8)
4444
import Foreign.C.String (CStringLen)
4545
import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrArray)
4646
import Foreign.Marshal.Alloc (allocaBytes)
47-
import Foreign.Ptr (Ptr, castPtr, plusPtr)
48-
import Foreign.Storable (peek, poke)
47+
import Foreign.Ptr (Ptr, castPtr)
4948
import qualified Data.Text.Array as A
5049

5150
-- $interop
@@ -68,20 +67,11 @@ newtype I8 = I8 Int
6867
fromPtr :: Ptr Word8 -- ^ source array
6968
-> I8 -- ^ length of source array (in 'Word8' units)
7069
-> IO Text
71-
fromPtr _ (I8 0) = return empty
72-
fromPtr ptr (I8 len) =
73-
#if defined(ASSERTS)
74-
assert (len > 0) $
75-
#endif
76-
return $! Text arr 0 len
77-
where
78-
arr = A.run (A.new len >>= copy)
79-
copy marr = loop ptr 0
80-
where
81-
loop !p !i | i == len = return marr
82-
| otherwise = do
83-
A.unsafeWrite marr i =<< unsafeIOToST (peek p)
84-
loop (p `plusPtr` 1) (i + 1)
70+
fromPtr ptr (I8 len) = unsafeSTToIO $ do
71+
dst <- A.new len
72+
A.copyFromPointer dst 0 ptr len
73+
arr <- A.unsafeFreeze dst
74+
return $! Text arr 0 len
8575

8676
-- $lowlevel
8777
--
@@ -130,13 +120,7 @@ splitAtWord8 (I8 n) t@(Text arr off len)
130120
-- | /O(n)/ Copy a 'Text' to an array. The array is assumed to be big
131121
-- enough to hold the contents of the entire 'Text'.
132122
unsafeCopyToPtr :: Text -> Ptr Word8 -> IO ()
133-
unsafeCopyToPtr (Text arr off len) ptr = loop ptr off
134-
where
135-
end = off + len
136-
loop !p !i | i == end = return ()
137-
| otherwise = do
138-
poke p (A.unsafeIndex arr i)
139-
loop (p `plusPtr` 1) (i + 1)
123+
unsafeCopyToPtr (Text arr off len) ptr = unsafeSTToIO $ A.copyToPointer arr off ptr len
140124

141125
-- | /O(n)/ Perform an action on a temporary, mutable copy of a
142126
-- 'Text'. The copy is freed as soon as the action returns.

0 commit comments

Comments
 (0)