For efficiency of my FFI, I want to work directly with buffers holding strings which are produced by C functions, without the copying&conversion to String
done by peekCString
, as seen for example in fdRead
(see the code below).
Are there such types analogous to String
implemented? With standard string functions and perhaps the ability to pattern match against string literals.
Perhaps something among the Memory efficient strings in Haskell?
I've already found out that w.r.t. memory management, I'd need a ForeignPtr
(to let the garbage collector free unused buffers that have been allocated to hold the data created by foreign functions).
Referenced code examples
fdRead
using peekCString
:
-- -----------------------------------------------------------------------------
-- fd{Read,Write}
-- | Read data from an 'Fd' and convert it to a 'String' using the locale encoding.
-- Throws an exception if this is an invalid descriptor, or EOF has been
-- reached.
fdRead :: Fd
-> ByteCount -- ^How many bytes to read
-> IO (String, ByteCount) -- ^The bytes read, how many bytes were read.
fdRead _fd 0 = return ("", 0)
fdRead fd nbytes = do
allocaBytes (fromIntegral nbytes) $ \ buf -> do
rc <- fdReadBuf fd buf nbytes
case rc of
0 -> ioError (ioeSetErrorString (mkIOError EOF "fdRead" Nothing Nothing) "EOF")
n -> do
s <- peekCStringLen (castPtr buf, fromIntegral n)
return (s, n)
-- | Read data from an 'Fd' into memory. This is exactly equivalent
-- to the POSIX @read@ function.
fdReadBuf :: Fd
-> Ptr Word8 -- ^ Memory in which to put the data
-> ByteCount -- ^ Maximum number of bytes to read
-> IO ByteCount -- ^ Number of bytes read (zero for EOF)
fdReadBuf _fd _buf 0 = return 0
fdReadBuf fd buf nbytes =
fmap fromIntegral $
throwErrnoIfMinus1Retry "fdReadBuf" $
c_safe_read (fromIntegral fd) (castPtr buf) nbytes
foreign import ccall safe "read"
c_safe_read :: CInt -> Ptr CChar -> CSize -> IO CSsize