@@ -21,6 +21,9 @@ module Data.Text.Foreign
2121 , fromPtr
2222 , useAsPtr
2323 , asForeignPtr
24+ -- ** Encoding as UTF-8
25+ , peekCStringLen
26+ , withCStringLen
2427 -- * Unsafe conversion code
2528 , lengthWord16
2629 , unsafeCopyToPtr
@@ -38,14 +41,17 @@ import Control.Monad.ST.Unsafe (unsafeIOToST)
3841#else
3942import Control.Monad.ST (unsafeIOToST)
4043#endif
44+import Data.ByteString.Unsafe (unsafePackCStringLen, unsafeUseAsCStringLen)
45+import Data.Text.Encoding (decodeUtf8, encodeUtf8)
4146import Data.Text.Internal (Text(..), empty)
4247import Data.Text.Unsafe (lengthWord16)
43−import qualified Data.Text.Array as A
4448import Data.Word (Word16)
49+import Foreign.C.String (CStringLen)
50+import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrArray, withForeignPtr)
4551import Foreign.Marshal.Alloc (allocaBytes)
4652import Foreign.Ptr (Ptr, castPtr, plusPtr)
47−import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrArray, withForeignPtr)
4853import Foreign.Storable (peek, poke)
54+import qualified Data.Text.Array as A
4955
5056-- $interop
5157--
@@ -148,3 +154,21 @@ asForeignPtr t@(Text _arr _off len) = do
148154 fp <- mallocForeignPtrArray len
149155 withForeignPtr fp $ unsafeCopyToPtr t
150156 return (fp, I16 len)
157+
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
165+
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.
169+--
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