Skip to content

Commit c98b879

Browse files
bgamariBodigrim
authored andcommitted
Use unsafeWithForeignPtr when available
It turns out that all uses of withForeignPtr can safely use unsafeWithForeignPtr.
1 parent ca73ae3 commit c98b879

File tree

6 files changed

+46
-23
lines changed

6 files changed

+46
-23
lines changed

src/Data/Text/Encoding.hs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ import Control.Exception (evaluate, try, throwIO, ErrorCall(ErrorCall))
6969
import Control.Monad.ST (runST)
7070
import Data.Bits ((.&.))
7171
import Data.ByteString as B
72-
import Data.ByteString.Internal as B hiding (c2w)
72+
import qualified Data.ByteString.Internal as B
7373
import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
7474
import Data.Text.Internal (Text(..), safe, text)
75+
import Data.Text.Internal.Functions
7576
import Data.Text.Internal.Private (runText)
7677
import Data.Text.Internal.Unsafe.Char (ord, unsafeWrite)
7778
import Data.Text.Internal.Unsafe.Shift (shiftR)
@@ -83,7 +84,6 @@ import Foreign.C.Types (CSize(CSize))
8384
#else
8485
import Foreign.C.Types (CSize)
8586
#endif
86-
import Foreign.ForeignPtr (withForeignPtr)
8787
import Foreign.Marshal.Utils (with)
8888
import Foreign.Ptr (Ptr, minusPtr, nullPtr, plusPtr)
8989
import Foreign.Storable (Storable, peek, poke)
@@ -128,7 +128,7 @@ decodeLatin1 bs = withBS bs aux where
128128
aux fp len = text a 0 len
129129
where
130130
a = A.run (A.new len >>= unsafeIOToST . go)
131-
go dest = withForeignPtr fp $ \ptr -> do
131+
go dest = unsafeWithForeignPtr fp $ \ptr -> do
132132
c_decode_latin1 (A.maBA dest) ptr (ptr `plusPtr` len)
133133
return dest
134134

@@ -144,7 +144,7 @@ decodeUtf8With :: OnDecodeError -> ByteString -> Text
144144
decodeUtf8With onErr bs = withBS bs aux
145145
where
146146
aux fp len = runText $ \done -> do
147-
let go dest = withForeignPtr fp $ \ptr ->
147+
let go dest = unsafeWithForeignPtr fp $ \ptr ->
148148
with (0::CSize) $ \destOffPtr -> do
149149
let end = ptr `plusPtr` len
150150
loop curPtr = do
@@ -300,7 +300,7 @@ streamDecodeUtf8With onErr = decodeChunk B.empty 0 0
300300
aux fp len = runST $ (unsafeIOToST . decodeChunkToBuffer) =<< A.new (len+1)
301301
where
302302
decodeChunkToBuffer :: A.MArray s -> IO Decoding
303-
decodeChunkToBuffer dest = withForeignPtr fp $ \ptr ->
303+
decodeChunkToBuffer dest = unsafeWithForeignPtr fp $ \ptr ->
304304
with (0::CSize) $ \destOffPtr ->
305305
with codepoint0 $ \codepointPtr ->
306306
with state0 $ \statePtr ->
@@ -433,18 +433,18 @@ encodeUtf8 :: Text -> ByteString
433433
encodeUtf8 (Text arr off len)
434434
| len == 0 = B.empty
435435
| otherwise = unsafeDupablePerformIO $ do
436-
fp <- mallocByteString (len*3) -- see https://github.com/haskell/text/issues/194 for why len*3 is enough
437-
withForeignPtr fp $ \ptr ->
436+
fp <- B.mallocByteString (len*3) -- see https://github.com/haskell/text/issues/194 for why len*3 is enough
437+
unsafeWithForeignPtr fp $ \ptr ->
438438
with ptr $ \destPtr -> do
439439
c_encode_utf8 destPtr (A.aBA arr) (fromIntegral off) (fromIntegral len)
440440
newDest <- peek destPtr
441441
let utf8len = newDest `minusPtr` ptr
442442
if utf8len >= len `shiftR` 1
443443
then return (mkBS fp utf8len)
444444
else do
445-
fp' <- mallocByteString utf8len
446-
withForeignPtr fp' $ \ptr' -> do
447-
memcpy ptr' ptr (fromIntegral utf8len)
445+
fp' <- B.mallocByteString utf8len
446+
unsafeWithForeignPtr fp' $ \ptr' -> do
447+
B.memcpy ptr' ptr (fromIntegral utf8len)
448448
return (mkBS fp' utf8len)
449449

450450
-- | Decode text from little endian UTF-16 encoding.

src/Data/Text/Foreign.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ import Control.Monad.ST (unsafeIOToST)
4242
import Data.ByteString.Unsafe (unsafePackCStringLen, unsafeUseAsCStringLen)
4343
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
4444
import Data.Text.Internal (Text(..), empty)
45+
import Data.Text.Internal.Functions (unsafeWithForeignPtr)
4546
import Data.Text.Unsafe (lengthWord16)
4647
import Data.Word (Word16)
4748
import Foreign.C.String (CStringLen)
48-
import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrArray, withForeignPtr)
49+
import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrArray)
4950
import Foreign.Marshal.Alloc (allocaBytes)
5051
import Foreign.Ptr (Ptr, castPtr, plusPtr)
5152
import Foreign.Storable (peek, poke)
@@ -150,7 +151,7 @@ useAsPtr t@(Text _arr _off len) action =
150151
asForeignPtr :: Text -> IO (ForeignPtr Word16, I16)
151152
asForeignPtr t@(Text _arr _off len) = do
152153
fp <- mallocForeignPtrArray len
153-
withForeignPtr fp $ unsafeCopyToPtr t
154+
unsafeWithForeignPtr fp $ unsafeCopyToPtr t
154155
return (fp, I16 len)
155156

156157
-- | /O(n)/ Decode a C string with explicit length, which is assumed

src/Data/Text/Internal/ByteStringCompat.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@ plusForeignPtr (ForeignPtr addr guts) (I# offset) = ForeignPtr (plusAddr# addr o
5353
#-}
5454
#endif
5555
#endif
56+

src/Data/Text/Internal/Encoding/Fusion.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ import Data.Text.Encoding.Error
4444
import Data.Text.Internal.Encoding.Fusion.Common
4545
import Data.Text.Internal.Unsafe.Char (unsafeChr, unsafeChr8, unsafeChr32)
4646
import Data.Text.Internal.Unsafe.Shift (shiftL, shiftR)
47+
import Data.Text.Internal.Functions (unsafeWithForeignPtr)
4748
import Data.Word (Word8, Word16, Word32)
48-
import Foreign.ForeignPtr (withForeignPtr, ForeignPtr)
49+
import Foreign.ForeignPtr (ForeignPtr)
4950
import Foreign.Storable (pokeByteOff)
5051
import qualified Data.ByteString as B
5152
import qualified Data.ByteString.Unsafe as B
@@ -177,13 +178,13 @@ unstream (Stream next s0 len) = unsafeDupablePerformIO $ do
177178
Yield x s'
178179
| off == n -> realloc fp n off s' x
179180
| otherwise -> do
180-
withForeignPtr fp $ \p -> pokeByteOff p off x
181+
unsafeWithForeignPtr fp $ \p -> pokeByteOff p off x
181182
loop n (off+1) s' fp
182183
{-# NOINLINE realloc #-}
183184
realloc fp n off s x = do
184185
let n' = n+n
185186
fp' <- copy0 fp n n'
186-
withForeignPtr fp' $ \p -> pokeByteOff p off x
187+
unsafeWithForeignPtr fp' $ \p -> pokeByteOff p off x
187188
loop n' (off+1) s fp'
188189
{-# NOINLINE trimUp #-}
189190
trimUp fp _ off = return $! mkBS fp off
@@ -194,8 +195,8 @@ unstream (Stream next s0 len) = unsafeDupablePerformIO $ do
194195
#endif
195196
do
196197
dest <- mallocByteString destLen
197-
withForeignPtr src $ \src' ->
198-
withForeignPtr dest $ \dest' ->
198+
unsafeWithForeignPtr src $ \src' ->
199+
unsafeWithForeignPtr dest $ \dest' ->
199200
memcpy dest' src' (fromIntegral srcLen)
200201
return dest
201202

src/Data/Text/Internal/Functions.hs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# LANGUAGE CPP #-}
2+
13
-- |
24
-- Module : Data.Text.Internal.Functions
35
-- Copyright : 2010 Bryan O'Sullivan
@@ -15,9 +17,18 @@
1517

1618
module Data.Text.Internal.Functions
1719
(
18-
intersperse
20+
intersperse,
21+
unsafeWithForeignPtr
1922
) where
2023

24+
import Foreign.Ptr (Ptr)
25+
import Foreign.ForeignPtr (ForeignPtr)
26+
#if MIN_VERSION_base(4,15,0)
27+
import qualified GHC.ForeignPtr (unsafeWithForeignPtr)
28+
#else
29+
import qualified Foreign.ForeignPtr (withForeignPtr)
30+
#endif
31+
2132
-- | A lazier version of Data.List.intersperse. The other version
2233
-- causes space leaks!
2334
intersperse :: a -> [a] -> [a]
@@ -27,3 +38,10 @@ intersperse sep (x:xs) = x : go xs
2738
go [] = []
2839
go (y:ys) = sep : y: go ys
2940
{-# INLINE intersperse #-}
41+
42+
unsafeWithForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
43+
#if MIN_VERSION_base(4,15,0)
44+
unsafeWithForeignPtr = GHC.ForeignPtr.unsafeWithForeignPtr
45+
#else
46+
unsafeWithForeignPtr = Foreign.ForeignPtr.withForeignPtr
47+
#endif

src/Data/Text/Internal/Lazy/Encoding/Fusion.hs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,20 @@ module Data.Text.Internal.Lazy.Encoding.Fusion
3535
import Data.ByteString.Lazy.Internal (ByteString(..), defaultChunkSize)
3636
import qualified Data.ByteString as B
3737
import qualified Data.ByteString.Unsafe as B
38+
import Data.Text.Internal.ByteStringCompat
3839
import Data.Text.Internal.Encoding.Fusion.Common
3940
import Data.Text.Encoding.Error
4041
import Data.Text.Internal.Fusion (Step(..), Stream(..))
4142
import Data.Text.Internal.Fusion.Size
4243
import Data.Text.Internal.Unsafe.Char (unsafeChr, unsafeChr8, unsafeChr32)
4344
import Data.Text.Internal.Unsafe.Shift (shiftL)
45+
import Data.Text.Internal.Functions (unsafeWithForeignPtr)
4446
import Data.Word (Word8, Word16, Word32)
4547
import qualified Data.Text.Internal.Encoding.Utf8 as U8
4648
import qualified Data.Text.Internal.Encoding.Utf16 as U16
4749
import qualified Data.Text.Internal.Encoding.Utf32 as U32
4850
import Data.Text.Unsafe (unsafeDupablePerformIO)
49-
import Foreign.ForeignPtr (withForeignPtr, ForeignPtr)
51+
import Foreign.ForeignPtr (ForeignPtr)
5052
import Foreign.Storable (pokeByteOff)
5153
import Data.ByteString.Internal (mallocByteString, memcpy)
5254
#if defined(ASSERTS)
@@ -289,13 +291,13 @@ unstreamChunks chunkSize (Stream next s0 len0) = chunk s0 (upperBound 4 len0)
289291
return $! Chunk (trimUp fp off) (chunk s newLen)
290292
| off == n -> realloc fp n off s' x
291293
| otherwise -> do
292-
withForeignPtr fp $ \p -> pokeByteOff p off x
294+
unsafeWithForeignPtr fp $ \p -> pokeByteOff p off x
293295
loop n (off+1) s' fp
294296
{-# NOINLINE realloc #-}
295297
realloc fp n off s x = do
296298
let n' = min (n+n) chunkSize
297299
fp' <- copy0 fp n n'
298-
withForeignPtr fp' $ \p -> pokeByteOff p off x
300+
unsafeWithForeignPtr fp' $ \p -> pokeByteOff p off x
299301
loop n' (off+1) s fp'
300302
trimUp fp off = mkBS fp off
301303
copy0 :: ForeignPtr Word8 -> Int -> Int -> IO (ForeignPtr Word8)
@@ -305,8 +307,8 @@ unstreamChunks chunkSize (Stream next s0 len0) = chunk s0 (upperBound 4 len0)
305307
#endif
306308
do
307309
dest <- mallocByteString destLen
308-
withForeignPtr src $ \src' ->
309-
withForeignPtr dest $ \dest' ->
310+
unsafeWithForeignPtr src $ \src' ->
311+
unsafeWithForeignPtr dest $ \dest' ->
310312
memcpy dest' src' (fromIntegral srcLen)
311313
return dest
312314

0 commit comments

Comments
 (0)