1 % -----------------------------------------------------------------------------
2 % $Id: PrelCString.lhs,v 1.1 2001/01/11 17:25:57 simonmar Exp $
4 % (c) The FFI task force, 2000
7 Utilities for primitive marshaling
10 module PrelCString where
14 import PrelMarshalArray
15 import PrelMarshalAlloc
26 #ifdef __GLASGOW_HASKELL__
27 import PrelIOBase hiding (malloc, _malloc)
30 -----------------------------------------------------------------------------
33 -- representation of strings in C
34 -- ------------------------------
36 type CString = Ptr CChar -- conventional NUL terminates strings
37 type CStringLen = (CString, Int) -- strings with explicit length
43 -- * the following routines apply the default conversion when converting the
44 -- C-land character encoding into the Haskell-land character encoding
46 -- ** NOTE: The current implementation doesn't handle conversions yet! **
48 -- * the routines using an explicit length tolerate NUL characters in the
52 -- marshal a NUL terminated C string into a Haskell string
54 peekCString :: CString -> IO String
55 peekCString cp = liftM cCharsToChars $ peekArray0 nUL cp
57 -- marshal a C string with explicit length into a Haskell string
59 peekCStringLen :: CStringLen -> IO String
60 peekCStringLen (cp, len) = liftM cCharsToChars $ peekArray len cp
62 -- marshal a Haskell string into a NUL terminated C strings
64 -- * the Haskell string may *not* contain any NUL characters
66 -- * new storage is allocated for the C string and must be explicitly freed
68 newCString :: String -> IO CString
69 newCString = newArray0 nUL . charsToCChars
71 -- marshal a Haskell string into a C string (ie, character array) with
72 -- explicit length information
74 -- * new storage is allocated for the C string and must be explicitly freed
76 newCStringLen :: String -> IO CStringLen
77 newCStringLen str = liftM (pairLength str) $ newArray (charsToCChars str)
79 -- marshal a Haskell string into a NUL terminated C strings using temporary
82 -- * the Haskell string may *not* contain any NUL characters
84 -- * see the lifetime constraints of `MarshalAlloc.alloca'
86 withCString :: String -> (CString -> IO a) -> IO a
87 withCString = withArray0 nUL . charsToCChars
89 -- marshal a Haskell string into a NUL terminated C strings using temporary
92 -- * the Haskell string may *not* contain any NUL characters
94 -- * see the lifetime constraints of `MarshalAlloc.alloca'
96 withCStringLen :: String -> (CStringLen -> IO a) -> IO a
97 withCStringLen str act = withArray (charsToCChars str) $ act . pairLength str
99 -- auxilliary definitions
100 -- ----------------------
102 -- C's end of string character
105 nUL = castCharToCChar '\0'
107 -- pair a C string with the length of the given Haskell string
109 pairLength :: String -> CString -> CStringLen
110 pairLength = flip (,) . length
112 -- cast [CChar] to [Char]
114 cCharsToChars :: [CChar] -> [Char]
115 cCharsToChars = map castCCharToChar
117 -- cast [Char] to [CChar]
119 charsToCChars :: [Char] -> [CChar]
120 charsToCChars = map castCharToCChar
122 castCCharToChar :: CChar -> Char
123 -- castCCharToChar ch = chr (fromIntegral (fromIntegral ch :: Word8))
124 -- The above produces horrible code. Word and Int modules really
125 -- should be cleaned up... Here is an ugly but fast version:
126 castCCharToChar ch = case fromIntegral (fromIntegral ch :: Int32) of
127 I# i# -> C# (chr# (word2Int# (int2Word# i# `and#` int2Word# 0xFF#)))
129 castCharToCChar :: Char -> CChar
130 castCharToCChar ch = fromIntegral (ord ch)
136 #if __GLASGOW_HASKELL__
137 newtype UnsafeCString = UnsafeCString (ByteArray Int)
138 withUnsafeCString s f = f (UnsafeCString (packString s))
140 newtype UnsafeCString = UnsafeCString (Ptr CChar)
141 withUnsafeCString s f = withCString s (\p -> f (UnsafeCString p))