@@ -21,6 +21,7 @@ module Data.Text.Foreign
2121 , useAsPtr
2222 , asForeignPtr
2323 -- ** Encoding as UTF-8
24+ , withCString
2425 , peekCStringLen
2526 , withCStringLen
2627 -- * Unsafe conversion code
@@ -40,10 +41,11 @@ import Data.Text.Internal.Unsafe (unsafeWithForeignPtr)
4041import Data.Text.Show (addrLen )
4142import Data.Text.Unsafe (lengthWord8 )
4243import Data.Word (Word8 )
43- import Foreign.C.String (CStringLen )
44+ import Foreign.C.String (CString , CStringLen )
4445import Foreign.ForeignPtr (ForeignPtr , mallocForeignPtrArray )
4546import Foreign.Marshal.Alloc (allocaBytes )
4647import Foreign.Ptr (Ptr , castPtr )
48+ import Foreign.Storable (pokeByteOff )
4749import GHC.Exts (Ptr (.. ))
4850import qualified Data.Text.Array as A
4951
@@ -149,6 +151,21 @@ asForeignPtr t@(Text _arr _off len) = do
149151 unsafeWithForeignPtr fp $ unsafeCopyToPtr t
150152 return (fp, I8 len)
151153
154+ -- | Marshal a 'Text' into a C string with a trailing NUL byte,
155+ -- encoded as UTF-8 in temporary storage.
156+ --
157+ -- The temporary storage is freed when the subcomputation terminates
158+ -- (either normally or via an exception), so the pointer to the
159+ -- temporary storage must /not/ be used after this function returns.
160+ --
161+ -- @since 2.0.1
162+ withCString :: Text -> (CString -> IO a ) -> IO a
163+ withCString t@ (Text _arr _off len) action =
164+ allocaBytes (len + 1 ) $ \ buf -> do
165+ unsafeCopyToPtr t buf
166+ pokeByteOff buf len (0 :: Word8 )
167+ action (castPtr buf)
168+
152169-- | /O(n)/ Decode a C string with explicit length, which is assumed
153170-- to have been encoded as UTF-8. If decoding fails, a
154171-- 'UnicodeException' is thrown.
0 commit comments