<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <!-- Generated by HsColour, http://www.cs.york.ac.uk/fp/darcs/hscolour/ --> <title>Data/ByteString/Unsafe.hs</title> <link type='text/css' rel='stylesheet' href='hscolour.css' /> </head> <body> <pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE CPP #-}</span> <a name="line-2"></a><span class='hs-comment'>-- We cannot actually specify all the language pragmas, see ghc ticket #</span> <a name="line-3"></a><span class='hs-comment'>-- If we could, these are what they would be:</span> <a name="line-4"></a><span class='hs-comment'>{- LANGUAGE MagicHash -}</span> <a name="line-5"></a> <a name="line-6"></a><span class='hs-comment'>-- |</span> <a name="line-7"></a><span class='hs-comment'>-- Module : Data.ByteString.Unsafe</span> <a name="line-8"></a><span class='hs-comment'>-- License : BSD-style</span> <a name="line-9"></a><span class='hs-comment'>-- Maintainer : dons@cse.unsw.edu.au, duncan@haskell.org</span> <a name="line-10"></a><span class='hs-comment'>-- Stability : experimental</span> <a name="line-11"></a><span class='hs-comment'>-- Portability : portable</span> <a name="line-12"></a><span class='hs-comment'>--</span> <a name="line-13"></a><span class='hs-comment'>-- A module containing unsafe 'ByteString' operations.</span> <a name="line-14"></a><span class='hs-comment'>--</span> <a name="line-15"></a><span class='hs-comment'>-- While these functions have a stable API and you may use these functions in</span> <a name="line-16"></a><span class='hs-comment'>-- applications, do carefully consider the documented pre-conditions;</span> <a name="line-17"></a><span class='hs-comment'>-- incorrect use can break referential transparency or worse.</span> <a name="line-18"></a><span class='hs-comment'>--</span> <a name="line-19"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-varop'>.</span><span class='hs-conid'>Unsafe</span> <span class='hs-layout'>(</span> <a name="line-20"></a> <a name="line-21"></a> <span class='hs-comment'>-- * Unchecked access</span> <a name="line-22"></a> <span class='hs-varid'>unsafeHead</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: ByteString -> Word8</span> <a name="line-23"></a> <span class='hs-varid'>unsafeTail</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: ByteString -> ByteString</span> <a name="line-24"></a> <span class='hs-varid'>unsafeIndex</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: ByteString -> Int -> Word8</span> <a name="line-25"></a> <span class='hs-varid'>unsafeTake</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: Int -> ByteString -> ByteString</span> <a name="line-26"></a> <span class='hs-varid'>unsafeDrop</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: Int -> ByteString -> ByteString</span> <a name="line-27"></a> <a name="line-28"></a> <span class='hs-comment'>-- * Low level interaction with CStrings</span> <a name="line-29"></a> <span class='hs-comment'>-- ** Using ByteStrings with functions for CStrings</span> <a name="line-30"></a> <span class='hs-varid'>unsafeUseAsCString</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: ByteString -> (CString -> IO a) -> IO a</span> <a name="line-31"></a> <span class='hs-varid'>unsafeUseAsCStringLen</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: ByteString -> (CStringLen -> IO a) -> IO a</span> <a name="line-32"></a> <a name="line-33"></a> <span class='hs-comment'>-- ** Converting CStrings to ByteStrings</span> <a name="line-34"></a> <span class='hs-varid'>unsafePackCString</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: CString -> IO ByteString</span> <a name="line-35"></a> <span class='hs-varid'>unsafePackCStringLen</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: CStringLen -> IO ByteString</span> <a name="line-36"></a> <span class='hs-varid'>unsafePackMallocCString</span><span class='hs-layout'>,</span><span class='hs-comment'>-- :: CString -> IO ByteString</span> <a name="line-37"></a> <a name="line-38"></a><span class='hs-cpp'>#if defined(__GLASGOW_HASKELL__)</span> <a name="line-39"></a> <span class='hs-varid'>unsafePackAddress</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: Addr# -> IO ByteString</span> <a name="line-40"></a> <span class='hs-varid'>unsafePackAddressLen</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: Int -> Addr# -> IO ByteString</span> <a name="line-41"></a> <span class='hs-varid'>unsafePackCStringFinalizer</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: Ptr Word8 -> Int -> IO () -> IO ByteString</span> <a name="line-42"></a> <span class='hs-varid'>unsafeFinalize</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- :: ByteString -> IO ()</span> <a name="line-43"></a><span class='hs-cpp'>#endif</span> <a name="line-44"></a> <a name="line-45"></a> <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span> <a name="line-46"></a> <a name="line-47"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-varop'>.</span><span class='hs-conid'>Internal</span> <a name="line-48"></a> <a name="line-49"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-layout'>(</span><span class='hs-varid'>newForeignPtr_</span><span class='hs-layout'>,</span> <span class='hs-varid'>newForeignPtr</span><span class='hs-layout'>,</span> <span class='hs-varid'>withForeignPtr</span><span class='hs-layout'>)</span> <a name="line-50"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>Ptr</span> <span class='hs-layout'>(</span><span class='hs-conid'>Ptr</span><span class='hs-layout'>,</span> <span class='hs-varid'>plusPtr</span><span class='hs-layout'>,</span> <span class='hs-varid'>castPtr</span><span class='hs-layout'>)</span> <a name="line-51"></a> <a name="line-52"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>Storable</span> <span class='hs-layout'>(</span><span class='hs-conid'>Storable</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-53"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>C</span><span class='hs-varop'>.</span><span class='hs-conid'>String</span> <span class='hs-layout'>(</span><span class='hs-conid'>CString</span><span class='hs-layout'>,</span> <span class='hs-conid'>CStringLen</span><span class='hs-layout'>)</span> <a name="line-54"></a> <a name="line-55"></a><span class='hs-cpp'>#ifndef __NHC__</span> <a name="line-56"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Exception</span> <span class='hs-layout'>(</span><span class='hs-varid'>assert</span><span class='hs-layout'>)</span> <a name="line-57"></a><span class='hs-cpp'>#endif</span> <a name="line-58"></a> <a name="line-59"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Word</span> <span class='hs-layout'>(</span><span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-60"></a> <a name="line-61"></a><span class='hs-cpp'>#if defined(__GLASGOW_HASKELL__)</span> <a name="line-62"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>ForeignPtr</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>FC</span> <span class='hs-layout'>(</span><span class='hs-varid'>finalizeForeignPtr</span><span class='hs-layout'>)</span> <a name="line-63"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>FC</span> <span class='hs-layout'>(</span><span class='hs-varid'>newForeignPtr</span><span class='hs-layout'>)</span> <a name="line-64"></a> <a name="line-65"></a><span class='hs-comment'>--import Data.Generics (Data(..), Typeable(..))</span> <a name="line-66"></a> <a name="line-67"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Prim</span> <span class='hs-layout'>(</span><span class='hs-conid'>Addr</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <a name="line-68"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Ptr</span> <span class='hs-layout'>(</span><span class='hs-conid'>Ptr</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <a name="line-69"></a><span class='hs-cpp'>#endif</span> <a name="line-70"></a> <a name="line-71"></a><span class='hs-comment'>-- An alternative to Control.Exception (assert) for nhc98</span> <a name="line-72"></a><span class='hs-cpp'>#ifdef __NHC__</span> <a name="line-73"></a><span class='hs-cpp'>#define assert assertS "__FILE__ : __LINE__"</span> <a name="line-74"></a><a name="assertS"></a><span class='hs-definition'>assertS</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>a</span> <a name="line-75"></a><span class='hs-definition'>assertS</span> <span class='hs-keyword'>_</span> <span class='hs-conid'>True</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>id</span> <a name="line-76"></a><span class='hs-definition'>assertS</span> <span class='hs-varid'>s</span> <span class='hs-conid'>False</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>error</span> <span class='hs-layout'>(</span><span class='hs-str'>"assertion failed at "</span><span class='hs-varop'>++</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <a name="line-77"></a><span class='hs-cpp'>#endif</span> <a name="line-78"></a> <a name="line-79"></a><span class='hs-comment'>-- -----------------------------------------------------------------------------</span> <a name="line-80"></a><span class='hs-comment'>--</span> <a name="line-81"></a><span class='hs-comment'>-- Useful macros, until we have bang patterns</span> <a name="line-82"></a><span class='hs-comment'>--</span> <a name="line-83"></a> <a name="line-84"></a><span class='hs-cpp'>#define STRICT1(f) f a | a `seq` False = undefined</span> <a name="line-85"></a><span class='hs-cpp'>#define STRICT2(f) f a b | a `seq` b `seq` False = undefined</span> <a name="line-86"></a><span class='hs-cpp'>#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined</span> <a name="line-87"></a><span class='hs-cpp'>#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined</span> <a name="line-88"></a><span class='hs-cpp'>#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undefined</span> <a name="line-89"></a> <a name="line-90"></a><span class='hs-comment'>-- ---------------------------------------------------------------------</span> <a name="line-91"></a><span class='hs-comment'>--</span> <a name="line-92"></a><span class='hs-comment'>-- Extensions to the basic interface</span> <a name="line-93"></a><span class='hs-comment'>--</span> <a name="line-94"></a> <a name="line-95"></a><a name="unsafeHead"></a><span class='hs-comment'>-- | A variety of 'head' for non-empty ByteStrings. 'unsafeHead' omits the</span> <a name="line-96"></a><span class='hs-comment'>-- check for the empty case, so there is an obligation on the programmer</span> <a name="line-97"></a><span class='hs-comment'>-- to provide a proof that the ByteString is non-empty.</span> <a name="line-98"></a><span class='hs-definition'>unsafeHead</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Word8</span> <a name="line-99"></a><span class='hs-definition'>unsafeHead</span> <span class='hs-layout'>(</span><span class='hs-conid'>PS</span> <span class='hs-varid'>x</span> <span class='hs-varid'>s</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>assert</span> <span class='hs-layout'>(</span><span class='hs-varid'>l</span> <span class='hs-varop'>></span> <span class='hs-num'>0</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <a name="line-100"></a> <span class='hs-varid'>inlinePerformIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>withForeignPtr</span> <span class='hs-varid'>x</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>p</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>peekByteOff</span> <span class='hs-varid'>p</span> <span class='hs-varid'>s</span> <a name="line-101"></a><span class='hs-comment'>{-# INLINE unsafeHead #-}</span> <a name="line-102"></a> <a name="line-103"></a><a name="unsafeTail"></a><span class='hs-comment'>-- | A variety of 'tail' for non-empty ByteStrings. 'unsafeTail' omits the</span> <a name="line-104"></a><span class='hs-comment'>-- check for the empty case. As with 'unsafeHead', the programmer must</span> <a name="line-105"></a><span class='hs-comment'>-- provide a separate proof that the ByteString is non-empty.</span> <a name="line-106"></a><span class='hs-definition'>unsafeTail</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>ByteString</span> <a name="line-107"></a><span class='hs-definition'>unsafeTail</span> <span class='hs-layout'>(</span><span class='hs-conid'>PS</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>s</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>assert</span> <span class='hs-layout'>(</span><span class='hs-varid'>l</span> <span class='hs-varop'>></span> <span class='hs-num'>0</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-conid'>PS</span> <span class='hs-varid'>ps</span> <span class='hs-layout'>(</span><span class='hs-varid'>s</span><span class='hs-varop'>+</span><span class='hs-num'>1</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>l</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-layout'>)</span> <a name="line-108"></a><span class='hs-comment'>{-# INLINE unsafeTail #-}</span> <a name="line-109"></a> <a name="line-110"></a><a name="unsafeIndex"></a><span class='hs-comment'>-- | Unsafe 'ByteString' index (subscript) operator, starting from 0, returning a 'Word8'</span> <a name="line-111"></a><span class='hs-comment'>-- This omits the bounds check, which means there is an accompanying</span> <a name="line-112"></a><span class='hs-comment'>-- obligation on the programmer to ensure the bounds are checked in some</span> <a name="line-113"></a><span class='hs-comment'>-- other way.</span> <a name="line-114"></a><span class='hs-definition'>unsafeIndex</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Word8</span> <a name="line-115"></a><span class='hs-definition'>unsafeIndex</span> <span class='hs-layout'>(</span><span class='hs-conid'>PS</span> <span class='hs-varid'>x</span> <span class='hs-varid'>s</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-varid'>i</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>assert</span> <span class='hs-layout'>(</span><span class='hs-varid'>i</span> <span class='hs-varop'>>=</span> <span class='hs-num'>0</span> <span class='hs-varop'>&&</span> <span class='hs-varid'>i</span> <span class='hs-varop'><</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <a name="line-116"></a> <span class='hs-varid'>inlinePerformIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>withForeignPtr</span> <span class='hs-varid'>x</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>p</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>peekByteOff</span> <span class='hs-varid'>p</span> <span class='hs-layout'>(</span><span class='hs-varid'>s</span><span class='hs-varop'>+</span><span class='hs-varid'>i</span><span class='hs-layout'>)</span> <a name="line-117"></a><span class='hs-comment'>{-# INLINE unsafeIndex #-}</span> <a name="line-118"></a> <a name="line-119"></a><a name="unsafeTake"></a><span class='hs-comment'>-- | A variety of 'take' which omits the checks on @n@ so there is an</span> <a name="line-120"></a><span class='hs-comment'>-- obligation on the programmer to provide a proof that @0 <= n <= 'length' xs@.</span> <a name="line-121"></a><span class='hs-definition'>unsafeTake</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>ByteString</span> <a name="line-122"></a><span class='hs-definition'>unsafeTake</span> <span class='hs-varid'>n</span> <span class='hs-layout'>(</span><span class='hs-conid'>PS</span> <span class='hs-varid'>x</span> <span class='hs-varid'>s</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>assert</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-varop'><=</span> <span class='hs-varid'>n</span> <span class='hs-varop'>&&</span> <span class='hs-varid'>n</span> <span class='hs-varop'><=</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-conid'>PS</span> <span class='hs-varid'>x</span> <span class='hs-varid'>s</span> <span class='hs-varid'>n</span> <a name="line-123"></a><span class='hs-comment'>{-# INLINE unsafeTake #-}</span> <a name="line-124"></a> <a name="line-125"></a><a name="unsafeDrop"></a><span class='hs-comment'>-- | A variety of 'drop' which omits the checks on @n@ so there is an</span> <a name="line-126"></a><span class='hs-comment'>-- obligation on the programmer to provide a proof that @0 <= n <= 'length' xs@.</span> <a name="line-127"></a><span class='hs-definition'>unsafeDrop</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>ByteString</span> <a name="line-128"></a><span class='hs-definition'>unsafeDrop</span> <span class='hs-varid'>n</span> <span class='hs-layout'>(</span><span class='hs-conid'>PS</span> <span class='hs-varid'>x</span> <span class='hs-varid'>s</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>assert</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-varop'><=</span> <span class='hs-varid'>n</span> <span class='hs-varop'>&&</span> <span class='hs-varid'>n</span> <span class='hs-varop'><=</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-conid'>PS</span> <span class='hs-varid'>x</span> <span class='hs-layout'>(</span><span class='hs-varid'>s</span><span class='hs-varop'>+</span><span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>l</span><span class='hs-comment'>-</span><span class='hs-varid'>n</span><span class='hs-layout'>)</span> <a name="line-129"></a><span class='hs-comment'>{-# INLINE unsafeDrop #-}</span> <a name="line-130"></a> <a name="line-131"></a> <a name="line-132"></a><span class='hs-cpp'>#if defined(__GLASGOW_HASKELL__)</span> <a name="line-133"></a><a name="unsafePackAddress"></a><span class='hs-comment'>-- | /O(n)/ Pack a null-terminated sequence of bytes, pointed to by an</span> <a name="line-134"></a><span class='hs-comment'>-- Addr\# (an arbitrary machine address assumed to point outside the</span> <a name="line-135"></a><span class='hs-comment'>-- garbage-collected heap) into a @ByteString@. A much faster way to</span> <a name="line-136"></a><span class='hs-comment'>-- create an Addr\# is with an unboxed string literal, than to pack a</span> <a name="line-137"></a><span class='hs-comment'>-- boxed string. A unboxed string literal is compiled to a static @char</span> <a name="line-138"></a><span class='hs-comment'>-- []@ by GHC. Establishing the length of the string requires a call to</span> <a name="line-139"></a><span class='hs-comment'>-- @strlen(3)@, so the Addr# must point to a null-terminated buffer (as</span> <a name="line-140"></a><span class='hs-comment'>-- is the case with "string"# literals in GHC). Use 'unsafePackAddressLen'</span> <a name="line-141"></a><span class='hs-comment'>-- if you know the length of the string statically.</span> <a name="line-142"></a><span class='hs-comment'>--</span> <a name="line-143"></a><span class='hs-comment'>-- An example:</span> <a name="line-144"></a><span class='hs-comment'>--</span> <a name="line-145"></a><span class='hs-comment'>-- > literalFS = unsafePackAddress "literal"#</span> <a name="line-146"></a><span class='hs-comment'>--</span> <a name="line-147"></a><span class='hs-comment'>-- This function is /unsafe/. If you modify the buffer pointed to by the</span> <a name="line-148"></a><span class='hs-comment'>-- original Addr# this modification will be reflected in the resulting</span> <a name="line-149"></a><span class='hs-comment'>-- @ByteString@, breaking referential transparency.</span> <a name="line-150"></a><span class='hs-comment'>--</span> <a name="line-151"></a><span class='hs-comment'>-- Note this also won't work if you Add# has embedded '\0' characters in</span> <a name="line-152"></a><span class='hs-comment'>-- the string (strlen will fail).</span> <a name="line-153"></a><span class='hs-comment'>--</span> <a name="line-154"></a><span class='hs-definition'>unsafePackAddress</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Addr</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ByteString</span> <a name="line-155"></a><span class='hs-definition'>unsafePackAddress</span> <span class='hs-varid'>addr</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-156"></a> <span class='hs-varid'>p</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>newForeignPtr_</span> <span class='hs-layout'>(</span><span class='hs-varid'>castPtr</span> <span class='hs-varid'>cstr</span><span class='hs-layout'>)</span> <a name="line-157"></a> <span class='hs-varid'>l</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>c_strlen</span> <span class='hs-varid'>cstr</span> <a name="line-158"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>PS</span> <span class='hs-varid'>p</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <a name="line-159"></a> <span class='hs-keyword'>where</span> <a name="line-160"></a> <span class='hs-varid'>cstr</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>CString</span> <a name="line-161"></a> <span class='hs-varid'>cstr</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Ptr</span> <span class='hs-varid'>addr</span><span class='hs-cpp'>#</span> <a name="line-162"></a><span class='hs-comment'>{-# INLINE unsafePackAddress #-}</span> <a name="line-163"></a> <a name="line-164"></a><a name="unsafePackAddressLen"></a><span class='hs-comment'>-- | /O(1)/ 'unsafePackAddressLen' provides constant-time construction of</span> <a name="line-165"></a><span class='hs-comment'>-- 'ByteStrings' which is ideal for string literals. It packs a sequence</span> <a name="line-166"></a><span class='hs-comment'>-- of bytes into a 'ByteString', given a raw 'Addr#' to the string, and</span> <a name="line-167"></a><span class='hs-comment'>-- the length of the string.</span> <a name="line-168"></a><span class='hs-comment'>--</span> <a name="line-169"></a><span class='hs-comment'>-- This function is /unsafe/ in two ways:</span> <a name="line-170"></a><span class='hs-comment'>--</span> <a name="line-171"></a><span class='hs-comment'>-- * the length argument is assumed to be correct. If the length</span> <a name="line-172"></a><span class='hs-comment'>-- argument is incorrect, it is possible to overstep the end of the</span> <a name="line-173"></a><span class='hs-comment'>-- byte array.</span> <a name="line-174"></a><span class='hs-comment'>--</span> <a name="line-175"></a><span class='hs-comment'>-- * if the underying Addr# is later modified, this change will be</span> <a name="line-176"></a><span class='hs-comment'>-- reflected in resulting @ByteString@, breaking referential</span> <a name="line-177"></a><span class='hs-comment'>-- transparency.</span> <a name="line-178"></a><span class='hs-comment'>--</span> <a name="line-179"></a><span class='hs-comment'>-- If in doubt, don't use these functions.</span> <a name="line-180"></a><span class='hs-comment'>--</span> <a name="line-181"></a><span class='hs-definition'>unsafePackAddressLen</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Addr</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ByteString</span> <a name="line-182"></a><span class='hs-definition'>unsafePackAddressLen</span> <span class='hs-varid'>len</span> <span class='hs-varid'>addr</span><span class='hs-cpp'>#</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-183"></a> <span class='hs-varid'>p</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>newForeignPtr_</span> <span class='hs-layout'>(</span><span class='hs-conid'>Ptr</span> <span class='hs-varid'>addr</span><span class='hs-cpp'>#</span><span class='hs-layout'>)</span> <a name="line-184"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>PS</span> <span class='hs-varid'>p</span> <span class='hs-num'>0</span> <span class='hs-varid'>len</span> <a name="line-185"></a><span class='hs-comment'>{-# INLINE unsafePackAddressLen #-}</span> <a name="line-186"></a> <a name="line-187"></a><a name="unsafePackCStringFinalizer"></a><span class='hs-comment'>-- | /O(1)/ Construct a 'ByteString' given a Ptr Word8 to a buffer, a</span> <a name="line-188"></a><span class='hs-comment'>-- length, and an IO action representing a finalizer. This function is</span> <a name="line-189"></a><span class='hs-comment'>-- not available on Hugs.</span> <a name="line-190"></a><span class='hs-comment'>--</span> <a name="line-191"></a><span class='hs-comment'>-- This function is /unsafe/, it is possible to break referential</span> <a name="line-192"></a><span class='hs-comment'>-- transparency by modifying the underlying buffer pointed to by the</span> <a name="line-193"></a><span class='hs-comment'>-- first argument. Any changes to the original buffer will be reflected</span> <a name="line-194"></a><span class='hs-comment'>-- in the resulting @ByteString@.</span> <a name="line-195"></a><span class='hs-comment'>--</span> <a name="line-196"></a><span class='hs-definition'>unsafePackCStringFinalizer</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Ptr</span> <span class='hs-conid'>Word8</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ByteString</span> <a name="line-197"></a><span class='hs-definition'>unsafePackCStringFinalizer</span> <span class='hs-varid'>p</span> <span class='hs-varid'>l</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-198"></a> <span class='hs-varid'>fp</span> <span class='hs-keyglyph'><-</span> <span class='hs-conid'>FC</span><span class='hs-varop'>.</span><span class='hs-varid'>newForeignPtr</span> <span class='hs-varid'>p</span> <span class='hs-varid'>f</span> <a name="line-199"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>PS</span> <span class='hs-varid'>fp</span> <span class='hs-num'>0</span> <span class='hs-varid'>l</span> <a name="line-200"></a> <a name="line-201"></a><a name="unsafeFinalize"></a><span class='hs-comment'>-- | Explicitly run the finaliser associated with a 'ByteString'.</span> <a name="line-202"></a><span class='hs-comment'>-- References to this value after finalisation may generate invalid memory</span> <a name="line-203"></a><span class='hs-comment'>-- references.</span> <a name="line-204"></a><span class='hs-comment'>--</span> <a name="line-205"></a><span class='hs-comment'>-- This function is /unsafe/, as there may be other</span> <a name="line-206"></a><span class='hs-comment'>-- 'ByteStrings' referring to the same underlying pages. If you use</span> <a name="line-207"></a><span class='hs-comment'>-- this, you need to have a proof of some kind that all 'ByteString's</span> <a name="line-208"></a><span class='hs-comment'>-- ever generated from the underlying byte array are no longer live.</span> <a name="line-209"></a><span class='hs-comment'>--</span> <a name="line-210"></a><span class='hs-definition'>unsafeFinalize</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-211"></a><span class='hs-definition'>unsafeFinalize</span> <span class='hs-layout'>(</span><span class='hs-conid'>PS</span> <span class='hs-varid'>p</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FC</span><span class='hs-varop'>.</span><span class='hs-varid'>finalizeForeignPtr</span> <span class='hs-varid'>p</span> <a name="line-212"></a> <a name="line-213"></a><span class='hs-cpp'>#endif</span> <a name="line-214"></a> <a name="line-215"></a><span class='hs-comment'>------------------------------------------------------------------------</span> <a name="line-216"></a><span class='hs-comment'>-- Packing CStrings into ByteStrings</span> <a name="line-217"></a> <a name="line-218"></a><a name="unsafePackCString"></a><span class='hs-comment'>-- | /O(n)/ Build a @ByteString@ from a @CString@. This value will have /no/</span> <a name="line-219"></a><span class='hs-comment'>-- finalizer associated to it, and will not be garbage collected by</span> <a name="line-220"></a><span class='hs-comment'>-- Haskell. The ByteString length is calculated using /strlen(3)/,</span> <a name="line-221"></a><span class='hs-comment'>-- and thus the complexity is a /O(n)/.</span> <a name="line-222"></a><span class='hs-comment'>--</span> <a name="line-223"></a><span class='hs-comment'>-- This function is /unsafe/. If the @CString@ is later modified, this</span> <a name="line-224"></a><span class='hs-comment'>-- change will be reflected in the resulting @ByteString@, breaking</span> <a name="line-225"></a><span class='hs-comment'>-- referential transparency.</span> <a name="line-226"></a><span class='hs-comment'>--</span> <a name="line-227"></a><span class='hs-definition'>unsafePackCString</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>CString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ByteString</span> <a name="line-228"></a><span class='hs-definition'>unsafePackCString</span> <span class='hs-varid'>cstr</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-229"></a> <span class='hs-varid'>fp</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>newForeignPtr_</span> <span class='hs-layout'>(</span><span class='hs-varid'>castPtr</span> <span class='hs-varid'>cstr</span><span class='hs-layout'>)</span> <a name="line-230"></a> <span class='hs-varid'>l</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>c_strlen</span> <span class='hs-varid'>cstr</span> <a name="line-231"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$!</span> <span class='hs-conid'>PS</span> <span class='hs-varid'>fp</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <a name="line-232"></a> <a name="line-233"></a><a name="unsafePackCStringLen"></a><span class='hs-comment'>-- | /O(1)/ Build a @ByteString@ from a @CStringLen@. This value will</span> <a name="line-234"></a><span class='hs-comment'>-- have /no/ finalizer associated with it, and will not be garbage</span> <a name="line-235"></a><span class='hs-comment'>-- collected by Haskell. This operation has /O(1)/ complexity as we</span> <a name="line-236"></a><span class='hs-comment'>-- already know the final size, so no /strlen(3)/ is required.</span> <a name="line-237"></a><span class='hs-comment'>--</span> <a name="line-238"></a><span class='hs-comment'>-- This funtion is /unsafe/. If the original @CStringLen@ is later</span> <a name="line-239"></a><span class='hs-comment'>-- modified, this change will be reflected in the resulting @ByteString@,</span> <a name="line-240"></a><span class='hs-comment'>-- breaking referential transparency.</span> <a name="line-241"></a><span class='hs-comment'>--</span> <a name="line-242"></a><span class='hs-definition'>unsafePackCStringLen</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>CStringLen</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ByteString</span> <a name="line-243"></a><span class='hs-definition'>unsafePackCStringLen</span> <span class='hs-layout'>(</span><span class='hs-varid'>ptr</span><span class='hs-layout'>,</span><span class='hs-varid'>len</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-244"></a> <span class='hs-varid'>fp</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>newForeignPtr_</span> <span class='hs-layout'>(</span><span class='hs-varid'>castPtr</span> <span class='hs-varid'>ptr</span><span class='hs-layout'>)</span> <a name="line-245"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$!</span> <span class='hs-conid'>PS</span> <span class='hs-varid'>fp</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>len</span><span class='hs-layout'>)</span> <a name="line-246"></a> <a name="line-247"></a><a name="unsafePackMallocCString"></a><span class='hs-comment'>-- | /O(n)/ Build a @ByteString@ from a malloced @CString@. This value will</span> <a name="line-248"></a><span class='hs-comment'>-- have a @free(3)@ finalizer associated to it.</span> <a name="line-249"></a><span class='hs-comment'>--</span> <a name="line-250"></a><span class='hs-comment'>-- This funtion is /unsafe/. If the original @CString@ is later</span> <a name="line-251"></a><span class='hs-comment'>-- modified, this change will be reflected in the resulting @ByteString@,</span> <a name="line-252"></a><span class='hs-comment'>-- breaking referential transparency.</span> <a name="line-253"></a><span class='hs-comment'>--</span> <a name="line-254"></a><span class='hs-comment'>-- This function is also unsafe if you call its finalizer twice,</span> <a name="line-255"></a><span class='hs-comment'>-- which will result in a /double free/ error, or if you pass it</span> <a name="line-256"></a><span class='hs-comment'>-- a CString not allocated with 'malloc'.</span> <a name="line-257"></a><span class='hs-comment'>--</span> <a name="line-258"></a><span class='hs-definition'>unsafePackMallocCString</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>CString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ByteString</span> <a name="line-259"></a><span class='hs-definition'>unsafePackMallocCString</span> <span class='hs-varid'>cstr</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-260"></a> <span class='hs-varid'>fp</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>newForeignPtr</span> <span class='hs-varid'>c_free_finalizer</span> <span class='hs-layout'>(</span><span class='hs-varid'>castPtr</span> <span class='hs-varid'>cstr</span><span class='hs-layout'>)</span> <a name="line-261"></a> <span class='hs-varid'>len</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>c_strlen</span> <span class='hs-varid'>cstr</span> <a name="line-262"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$!</span> <span class='hs-conid'>PS</span> <span class='hs-varid'>fp</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>len</span><span class='hs-layout'>)</span> <a name="line-263"></a> <a name="line-264"></a><span class='hs-comment'>-- ---------------------------------------------------------------------</span> <a name="line-265"></a> <a name="line-266"></a><a name="unsafeUseAsCString"></a><span class='hs-comment'>-- | /O(1) construction/ Use a @ByteString@ with a function requiring a</span> <a name="line-267"></a><span class='hs-comment'>-- @CString@.</span> <a name="line-268"></a><span class='hs-comment'>--</span> <a name="line-269"></a><span class='hs-comment'>-- This function does zero copying, and merely unwraps a @ByteString@ to</span> <a name="line-270"></a><span class='hs-comment'>-- appear as a @CString@. It is /unsafe/ in two ways:</span> <a name="line-271"></a><span class='hs-comment'>--</span> <a name="line-272"></a><span class='hs-comment'>-- * After calling this function the @CString@ shares the underlying</span> <a name="line-273"></a><span class='hs-comment'>-- byte buffer with the original @ByteString@. Thus modifying the</span> <a name="line-274"></a><span class='hs-comment'>-- @CString@, either in C, or using poke, will cause the contents of the</span> <a name="line-275"></a><span class='hs-comment'>-- @ByteString@ to change, breaking referential transparency. Other</span> <a name="line-276"></a><span class='hs-comment'>-- @ByteStrings@ created by sharing (such as those produced via 'take'</span> <a name="line-277"></a><span class='hs-comment'>-- or 'drop') will also reflect these changes. Modifying the @CString@</span> <a name="line-278"></a><span class='hs-comment'>-- will break referential transparency. To avoid this, use</span> <a name="line-279"></a><span class='hs-comment'>-- @useAsCString@, which makes a copy of the original @ByteString@.</span> <a name="line-280"></a><span class='hs-comment'>--</span> <a name="line-281"></a><span class='hs-comment'>-- * @CStrings@ are often passed to functions that require them to be</span> <a name="line-282"></a><span class='hs-comment'>-- null-terminated. If the original @ByteString@ wasn't null terminated,</span> <a name="line-283"></a><span class='hs-comment'>-- neither will the @CString@ be. It is the programmers responsibility</span> <a name="line-284"></a><span class='hs-comment'>-- to guarantee that the @ByteString@ is indeed null terminated. If in</span> <a name="line-285"></a><span class='hs-comment'>-- doubt, use @useAsCString@.</span> <a name="line-286"></a><span class='hs-comment'>--</span> <a name="line-287"></a><span class='hs-definition'>unsafeUseAsCString</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-layout'>(</span><span class='hs-conid'>CString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span> <a name="line-288"></a><span class='hs-definition'>unsafeUseAsCString</span> <span class='hs-layout'>(</span><span class='hs-conid'>PS</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-varid'>ac</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>withForeignPtr</span> <span class='hs-varid'>ps</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>p</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>ac</span> <span class='hs-layout'>(</span><span class='hs-varid'>castPtr</span> <span class='hs-varid'>p</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <a name="line-289"></a> <a name="line-290"></a><a name="unsafeUseAsCStringLen"></a><span class='hs-comment'>-- | /O(1) construction/ Use a @ByteString@ with a function requiring a</span> <a name="line-291"></a><span class='hs-comment'>-- @CStringLen@.</span> <a name="line-292"></a><span class='hs-comment'>-- </span> <a name="line-293"></a><span class='hs-comment'>-- This function does zero copying, and merely unwraps a @ByteString@ to</span> <a name="line-294"></a><span class='hs-comment'>-- appear as a @CStringLen@. It is /unsafe/:</span> <a name="line-295"></a><span class='hs-comment'>--</span> <a name="line-296"></a><span class='hs-comment'>-- * After calling this function the @CStringLen@ shares the underlying</span> <a name="line-297"></a><span class='hs-comment'>-- byte buffer with the original @ByteString@. Thus modifying the</span> <a name="line-298"></a><span class='hs-comment'>-- @CStringLen@, either in C, or using poke, will cause the contents of the</span> <a name="line-299"></a><span class='hs-comment'>-- @ByteString@ to change, breaking referential transparency. Other</span> <a name="line-300"></a><span class='hs-comment'>-- @ByteStrings@ created by sharing (such as those produced via 'take'</span> <a name="line-301"></a><span class='hs-comment'>-- or 'drop') will also reflect these changes. Modifying the @CStringLen@</span> <a name="line-302"></a><span class='hs-comment'>-- will break referential transparency. To avoid this, use</span> <a name="line-303"></a><span class='hs-comment'>-- @useAsCStringLen@, which makes a copy of the original @ByteString@.</span> <a name="line-304"></a><span class='hs-comment'>--</span> <a name="line-305"></a><span class='hs-definition'>unsafeUseAsCStringLen</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-layout'>(</span><span class='hs-conid'>CStringLen</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span> <a name="line-306"></a><span class='hs-definition'>unsafeUseAsCStringLen</span> <span class='hs-layout'>(</span><span class='hs-conid'>PS</span> <span class='hs-varid'>ps</span> <span class='hs-varid'>s</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>withForeignPtr</span> <span class='hs-varid'>ps</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>p</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>f</span> <span class='hs-layout'>(</span><span class='hs-varid'>castPtr</span> <span class='hs-varid'>p</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>s</span><span class='hs-layout'>,</span><span class='hs-varid'>l</span><span class='hs-layout'>)</span> </pre></body> </html>