@@ -21,6 +21,9 @@ module Data.Text.Foreign
22 , useAsPtr
22 , useAsPtr
23 , asForeignPtr
23 , asForeignPtr
24+ -- ** Encoding as UTF-8
24 -- * Unsafe conversion code
27 -- * Unsafe conversion code
25 , lengthWord16
28 , lengthWord16
26 , unsafeCopyToPtr
29 , unsafeCopyToPtr
@@ -38,14 +41,17 @@ import Control.Monad.ST.Unsafe (unsafeIOToST)
39import Control.Monad.ST (unsafeIOToST)
42import Control.Monad.ST (unsafeIOToST)
44+import Data.ByteString.Unsafe (unsafePackCStringLen, unsafeUseAsCStringLen)
45+import Data.Text.Encoding (decodeUtf8, encodeUtf8)
41import Data.Text.Internal (Text(..), empty)
46import Data.Text.Internal (Text(..), empty)
42import Data.Text.Unsafe (lengthWord16)
47import Data.Text.Unsafe (lengthWord16)
43−import qualified Data.Text.Array as A
44import Data.Word (Word16)
48import Data.Word (Word16)
49+import Foreign.C.String (CStringLen)
50+import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrArray, withForeignPtr)
45import Foreign.Marshal.Alloc (allocaBytes)
51import Foreign.Marshal.Alloc (allocaBytes)
46import Foreign.Ptr (Ptr, castPtr, plusPtr)
52import Foreign.Ptr (Ptr, castPtr, plusPtr)
47−import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrArray, withForeignPtr)
48import Foreign.Storable (peek, poke)
53import Foreign.Storable (peek, poke)
54+import qualified Data.Text.Array as A
50-- $interop
56-- $interop
@@ -148,3 +154,21 @@ asForeignPtr t@(Text _arr _off len) = do
148 fp <- mallocForeignPtrArray len
154 fp <- mallocForeignPtrArray len
149 withForeignPtr fp $ unsafeCopyToPtr t
155 withForeignPtr fp $ unsafeCopyToPtr t
150 return (fp, I16 len)
156 return (fp, I16 len)
158+-- | /O(n)/ Decode a C string with explicit length, which is assumed
159+-- to have been encoded as UTF-8. If decoding fails, a
160+-- 'UnicodeException' is thrown.
161+peekCStringLen :: CStringLen -> IO Text
162+peekCStringLen cs = do
163+ bs <- unsafePackCStringLen cs
164+ return $! decodeUtf8 bs
166+-- | Marshal a 'Text' into a C string encoded as UTF-8 in temporary
167+-- storage, with explicit length information. The encoded string may
168+-- contain NUL bytes, and is not followed by a trailing NUL byte.
170+-- The temporary storage is freed when the subcomputation terminates
171+-- (either normally or via an exception), so the pointer to the
172+-- temporary storage must /not/ be used after this function returns.
173+withCStringLen :: Text -> (CStringLen -> IO a) -> IO a
174+withCStringLen t act = unsafeUseAsCStringLen (encodeUtf8 t) act