[project @ 2001-04-14 22:28:46 by qrczak]
[ghc-hetmet.git] / ghc / lib / std / PrelCString.lhs
1 % -----------------------------------------------------------------------------
2 % $Id: PrelCString.lhs,v 1.3 2001/04/14 22:28:46 qrczak Exp $
3 %
4 % (c) The FFI task force, 2000
5 %
6
7 Utilities for primitive marshaling
8
9 \begin{code}
10 module PrelCString where
11
12 import Monad
13
14 import PrelMarshalArray
15 import PrelPtr
16 import PrelStorable
17 import PrelCTypes
18 import PrelWord
19 import PrelByteArr
20 import PrelPack
21 import PrelBase
22
23 #ifdef __GLASGOW_HASKELL__
24 import PrelIOBase hiding (malloc, _malloc)
25 #endif
26
27 -----------------------------------------------------------------------------
28 -- Strings
29
30 -- representation of strings in C
31 -- ------------------------------
32
33 type CString    = Ptr CChar             -- conventional NUL terminates strings
34 type CStringLen = (CString, Int)        -- strings with explicit length
35
36
37 -- exported functions
38 -- ------------------
39 --
40 -- * the following routines apply the default conversion when converting the
41 --   C-land character encoding into the Haskell-land character encoding
42 --
43 --   ** NOTE: The current implementation doesn't handle conversions yet! **
44 --
45 -- * the routines using an explicit length tolerate NUL characters in the
46 --   middle of a string
47 --
48
49 -- marshal a NUL terminated C string into a Haskell string 
50 --
51 peekCString    :: CString -> IO String
52 peekCString cp  = liftM cCharsToChars $ peekArray0 nUL cp
53
54 -- marshal a C string with explicit length into a Haskell string 
55 --
56 peekCStringLen           :: CStringLen -> IO String
57 peekCStringLen (cp, len)  = liftM cCharsToChars $ peekArray len cp
58
59 -- marshal a Haskell string into a NUL terminated C strings
60 --
61 -- * the Haskell string may *not* contain any NUL characters
62 --
63 -- * new storage is allocated for the C string and must be explicitly freed
64 --
65 newCString :: String -> IO CString
66 newCString  = newArray0 nUL . charsToCChars
67
68 -- marshal a Haskell string into a C string (ie, character array) with
69 -- explicit length information
70 --
71 -- * new storage is allocated for the C string and must be explicitly freed
72 --
73 newCStringLen     :: String -> IO CStringLen
74 newCStringLen str  = liftM (pairLength str) $ newArray (charsToCChars str)
75
76 -- marshal a Haskell string into a NUL terminated C strings using temporary
77 -- storage
78 --
79 -- * the Haskell string may *not* contain any NUL characters
80 --
81 -- * see the lifetime constraints of `MarshalAlloc.alloca'
82 --
83 withCString :: String -> (CString -> IO a) -> IO a
84 withCString  = withArray0 nUL . charsToCChars
85
86 -- marshal a Haskell string into a NUL terminated C strings using temporary
87 -- storage
88 --
89 -- * the Haskell string may *not* contain any NUL characters
90 --
91 -- * see the lifetime constraints of `MarshalAlloc.alloca'
92 --
93 withCStringLen         :: String -> (CStringLen -> IO a) -> IO a
94 withCStringLen str act  = withArray (charsToCChars str) $ act . pairLength str
95
96 -- auxilliary definitions
97 -- ----------------------
98
99 -- C's end of string character
100 --
101 nUL :: CChar
102 nUL  = 0
103
104 -- pair a C string with the length of the given Haskell string
105 --
106 pairLength :: String -> CString -> CStringLen
107 pairLength  = flip (,) . length
108
109 -- cast [CChar] to [Char]
110 --
111 cCharsToChars :: [CChar] -> [Char]
112 cCharsToChars  = map castCCharToChar
113
114 -- cast [Char] to [CChar]
115 --
116 charsToCChars :: [Char] -> [CChar]
117 charsToCChars  = map castCharToCChar
118
119 castCCharToChar :: CChar -> Char
120 castCCharToChar ch = unsafeChr (fromIntegral (fromIntegral ch :: Word8))
121
122 castCharToCChar :: Char -> CChar
123 castCharToCChar ch = fromIntegral (ord ch)
124
125
126 -- unsafe CStrings
127 -- ---------------
128
129 withUnsafeCString :: String -> (UnsafeCString -> IO a) -> IO a
130 #if __GLASGOW_HASKELL__
131 newtype UnsafeCString = UnsafeCString (ByteArray Int)
132 withUnsafeCString s f = f (UnsafeCString (packString s))
133 #else
134 newtype UnsafeCString = UnsafeCString (Ptr CChar)
135 withUnsafeCString s f = withCString s (\p -> f (UnsafeCString p))
136 #endif
137 \end{code}