File: Unsafe.hs

package info (click to toggle)
ghc 9.10.3-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 169,076 kB
  • sloc: haskell: 713,554; ansic: 84,184; cpp: 30,255; javascript: 9,003; sh: 7,870; fortran: 3,527; python: 3,228; asm: 2,523; makefile: 2,324; yacc: 1,570; lisp: 532; xml: 196; perl: 111; csh: 2
file content (284 lines) | stat: -rw-r--r-- 11,670 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
{-# LANGUAGE Unsafe #-}

-- |
-- Module      : Data.ByteString.Unsafe
-- Copyright   : (c) Don Stewart 2006-2008
--               (c) Duncan Coutts 2006-2011
-- License     : BSD-style
-- Maintainer  : dons00@gmail.com, duncan@community.haskell.org
-- Stability   : provisional
-- Portability : non-portable
--
-- A module containing unsafe 'ByteString' operations.
--
-- While these functions have a stable API and you may use these functions in
-- applications, do carefully consider the documented pre-conditions;
-- incorrect use can break referential transparency or worse.
--
module Data.ByteString.Unsafe (

        -- * Unchecked access
        unsafeHead,
        unsafeTail,
        unsafeInit,
        unsafeLast,
        unsafeIndex,
        unsafeTake,
        unsafeDrop,

        -- * Low level interaction with CStrings
        -- ** Using ByteStrings with functions for CStrings
        unsafeUseAsCString,
        unsafeUseAsCStringLen,

        -- ** Converting CStrings to ByteStrings
        unsafePackCString,
        unsafePackCStringLen,
        unsafePackMallocCString,
        unsafePackMallocCStringLen,

        unsafePackAddress,
        unsafePackAddressLen,
        unsafePackCStringFinalizer,
        unsafeFinalize,

  ) where

import Data.ByteString.Internal

import Foreign.ForeignPtr       (newForeignPtr_, newForeignPtr, withForeignPtr)

import Foreign.Storable         (Storable(..))
import Foreign.C.String         (CString, CStringLen)

import Control.Exception        (assert)

import Data.Word                (Word8)

import qualified Foreign.ForeignPtr as FC (finalizeForeignPtr)
import qualified Foreign.Concurrent as FC (newForeignPtr)

import GHC.Exts                 (Addr#)
import GHC.Ptr                  (Ptr(..), castPtr)

-- ---------------------------------------------------------------------
--
-- Extensions to the basic interface
--

-- | A variety of 'head' for non-empty ByteStrings. 'unsafeHead' omits the
-- check for the empty case, so there is an obligation on the programmer
-- to provide a proof that the ByteString is non-empty.
unsafeHead :: ByteString -> Word8
unsafeHead (BS x l) = assert (l > 0) $
    accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> peek p
{-# INLINE unsafeHead #-}

-- | A variety of 'tail' for non-empty ByteStrings. 'unsafeTail' omits the
-- check for the empty case. As with 'unsafeHead', the programmer must
-- provide a separate proof that the ByteString is non-empty.
unsafeTail :: ByteString -> ByteString
unsafeTail (BS ps l) = assert (l > 0) $ BS (plusForeignPtr ps 1) (l-1)
{-# INLINE unsafeTail #-}

-- | A variety of 'init' for non-empty ByteStrings. 'unsafeInit' omits the
-- check for the empty case. As with 'unsafeHead', the programmer must
-- provide a separate proof that the ByteString is non-empty.
unsafeInit :: ByteString -> ByteString
unsafeInit (BS ps l) = assert (l > 0) $ BS ps (l-1)
{-# INLINE unsafeInit #-}

-- | A variety of 'last' for non-empty ByteStrings. 'unsafeLast' omits the
-- check for the empty case. As with 'unsafeHead', the programmer must
-- provide a separate proof that the ByteString is non-empty.
unsafeLast :: ByteString -> Word8
unsafeLast (BS x l) = assert (l > 0) $
    accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> peekByteOff p (l-1)
{-# INLINE unsafeLast #-}

-- | Unsafe 'ByteString' index (subscript) operator, starting from 0, returning a 'Word8'
-- This omits the bounds check, which means there is an accompanying
-- obligation on the programmer to ensure the bounds are checked in some
-- other way.
unsafeIndex :: ByteString -> Int -> Word8
unsafeIndex (BS x l) i = assert (i >= 0 && i < l) $
    accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> peekByteOff p i
{-# INLINE unsafeIndex #-}

-- | A variety of 'take' which omits the checks on @n@ so there is an
-- obligation on the programmer to provide a proof that @0 <= n <= 'length' xs@.
unsafeTake :: Int -> ByteString -> ByteString
unsafeTake n (BS x l) = assert (0 <= n && n <= l) $ BS x n
{-# INLINE unsafeTake #-}

-- | A variety of 'drop' which omits the checks on @n@ so there is an
-- obligation on the programmer to provide a proof that @0 <= n <= 'length' xs@.
unsafeDrop  :: Int -> ByteString -> ByteString
unsafeDrop n (BS x l) = assert (0 <= n && n <= l) $ BS (plusForeignPtr x n) (l-n)
{-# INLINE unsafeDrop #-}


-- | /O(1)/ 'unsafePackAddressLen' provides constant-time construction of
-- 'ByteString's, which is ideal for string literals. It packs a sequence
-- of bytes into a 'ByteString', given a raw 'Addr#' to the string, and
-- the length of the string.
--
-- This function is /unsafe/ in two ways:
--
-- * the length argument is assumed to be correct. If the length
-- argument is incorrect, it is possible to overstep the end of the
-- byte array.
--
-- * if the underlying 'Addr#' is later modified, this change will be
-- reflected in the resulting 'ByteString', breaking referential
-- transparency.
--
-- If in doubt, don't use this function.
--
unsafePackAddressLen :: Int -> Addr# -> IO ByteString
unsafePackAddressLen len addr# = do
    p <- newForeignPtr_ (Ptr addr#)
    return $ BS p len
{-# INLINE unsafePackAddressLen #-}

-- | /O(1)/ Construct a 'ByteString' given a Ptr Word8 to a buffer, a
-- length, and an IO action representing a finalizer. This function is
-- not available on Hugs.
--
-- This function is /unsafe/, it is possible to break referential
-- transparency by modifying the underlying buffer pointed to by the
-- first argument. Any changes to the original buffer will be reflected
-- in the resulting 'ByteString'.
--
unsafePackCStringFinalizer :: Ptr Word8 -> Int -> IO () -> IO ByteString
unsafePackCStringFinalizer p l f = do
    fp <- FC.newForeignPtr p f
    return $ BS fp l

-- | Explicitly run the finaliser associated with a 'ByteString'.
-- References to this value after finalisation may generate invalid memory
-- references.
--
-- This function is /unsafe/, as there may be other
-- 'ByteString's referring to the same underlying pages. If you use
-- this, you need to have a proof of some kind that all 'ByteString's
-- ever generated from the underlying byte array are no longer live.
--
unsafeFinalize :: ByteString -> IO ()
unsafeFinalize (BS p _) = FC.finalizeForeignPtr p

------------------------------------------------------------------------
-- Packing CStrings into ByteStrings

-- | /O(n)/ Build a 'ByteString' from a 'CString'. This value will have /no/
-- finalizer associated to it, and will not be garbage collected by
-- Haskell. The ByteString length is calculated using /strlen(3)/,
-- and thus the complexity is a /O(n)/.
--
-- This function is /unsafe/. If the 'CString' is later modified, this
-- change will be reflected in the resulting 'ByteString', breaking
-- referential transparency.
--
unsafePackCString :: CString -> IO ByteString
unsafePackCString cstr = do
    fp <- newForeignPtr_ (castPtr cstr)
    l <- c_strlen cstr
    return $! BS fp (fromIntegral l)

-- | /O(1)/ Build a 'ByteString' from a 'CStringLen'. This value will
-- have /no/ finalizer associated with it, and will not be garbage
-- collected by Haskell. This operation has /O(1)/ complexity as we
-- already know the final size, so no /strlen(3)/ is required.
--
-- This function is /unsafe/. If the original 'CStringLen' is later
-- modified, this change will be reflected in the resulting 'ByteString',
-- breaking referential transparency.
--
unsafePackCStringLen :: CStringLen -> IO ByteString
unsafePackCStringLen (ptr,len) = do
    fp <- newForeignPtr_ (castPtr ptr)
    return $! BS fp (fromIntegral len)

-- | /O(n)/ Build a 'ByteString' from a malloced 'CString'. This value will
-- have a @free(3)@ finalizer associated to it.
--
-- This function is /unsafe/. If the original 'CString' is later
-- modified, this change will be reflected in the resulting 'ByteString',
-- breaking referential transparency.
--
-- This function is also unsafe if you call its finalizer twice,
-- which will result in a /double free/ error, or if you pass it
-- a 'CString' not allocated with 'Foreign.Marshal.Alloc.malloc'.
--
unsafePackMallocCString :: CString -> IO ByteString
unsafePackMallocCString cstr = do
    fp <- newForeignPtr c_free_finalizer (castPtr cstr)
    len <- c_strlen cstr
    return $! BS fp (fromIntegral len)

-- | /O(1)/ Build a 'ByteString' from a malloced 'CStringLen'. This
-- value will have a @free(3)@ finalizer associated to it.
--
-- This function is /unsafe/. If the original 'CString' is later
-- modified, this change will be reflected in the resulting 'ByteString',
-- breaking referential transparency.
--
-- This function is also unsafe if you call its finalizer twice,
-- which will result in a /double free/ error, or if you pass it
-- a 'CString' not allocated with 'Foreign.Marshal.Alloc.malloc'.
--
unsafePackMallocCStringLen :: CStringLen -> IO ByteString
unsafePackMallocCStringLen (cstr, len) = do
    fp <- newForeignPtr c_free_finalizer (castPtr cstr)
    return $! BS fp len

-- ---------------------------------------------------------------------

-- | /O(1) construction/ Use a 'ByteString' with a function requiring a
-- 'CString'.
--
-- This function does zero copying, and merely unwraps a 'ByteString' to
-- appear as a 'CString'. It is /unsafe/ in two ways:
--
-- * After calling this function the 'CString' shares the underlying
-- byte buffer with the original 'ByteString'. Thus modifying the
-- 'CString', either in C, or using poke, will cause the contents of the
-- 'ByteString' to change, breaking referential transparency. Other
-- 'ByteString's created by sharing (such as those produced via 'take'
-- or 'drop') will also reflect these changes. Modifying the 'CString'
-- will break referential transparency. To avoid this, use
-- 'Data.ByteString.useAsCString', which makes a copy of the original 'ByteString'.
--
-- * 'CString's are often passed to functions that require them to be
-- null-terminated. If the original 'ByteString' wasn't null terminated,
-- neither will the 'CString' be. It is the programmers responsibility
-- to guarantee that the 'ByteString' is indeed null terminated. If in
-- doubt, use 'Data.ByteString.useAsCString'.
--
-- * The memory may freed at any point after the subcomputation
-- terminates, so the pointer to the storage must *not* be used
-- after this.
--
unsafeUseAsCString :: ByteString -> (CString -> IO a) -> IO a
unsafeUseAsCString (BS ps _) action = withForeignPtr ps $ \p -> action (castPtr p)
-- Cannot use unsafeWithForeignPtr, because action can diverge

-- | /O(1) construction/ Use a 'ByteString' with a function requiring a
-- 'CStringLen'.
--
-- This function does zero copying, and merely unwraps a 'ByteString' to
-- appear as a 'CStringLen'. It is /unsafe/:
--
-- * After calling this function the 'CStringLen' shares the underlying
-- byte buffer with the original 'ByteString'. Thus modifying the
-- 'CStringLen', either in C, or using poke, will cause the contents of the
-- 'ByteString' to change, breaking referential transparency. Other
-- 'ByteString's created by sharing (such as those produced via 'take'
-- or 'drop') will also reflect these changes. Modifying the 'CStringLen'
-- will break referential transparency. To avoid this, use
-- 'Data.ByteString.useAsCStringLen', which makes a copy of the original 'ByteString'.
--
-- If 'Data.ByteString.empty' is given, it will pass @('Foreign.Ptr.nullPtr', 0)@.
unsafeUseAsCStringLen :: ByteString -> (CStringLen -> IO a) -> IO a
unsafeUseAsCStringLen (BS ps l) action = withForeignPtr ps $ \p -> action (castPtr p, l)
-- Cannot use unsafeWithForeignPtr, because action can diverge