[project @ 2001-06-28 14:15:04 by simonmar]
[packages/pretty.git] / Foreign / C / String.hs
1 {-# OPTIONS -fno-implicit-prelude #-}
2 -----------------------------------------------------------------------------
3 --
4 -- Module : Foreign.C.String
5 -- Copyright : (c) The FFI task force 2001
6 -- License : BSD-style (see the file libraries/core/LICENSE)
7 --
8 -- Maintainer : ffi@haskell.org
9 -- Stability : experimental
10 -- Portability : non-portable
11 --
12 -- $Id: String.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
13 --
14 -- Utilities for primitive marshaling
15 --
16 -----------------------------------------------------------------------------
17
18 module Foreign.C.String ( -- representation of strings in C
19
20 CString, -- = Ptr CChar
21 CStringLen, -- = (CString, Int)
22
23 -- conversion of C strings into Haskell strings
24 --
25 peekCString, -- :: CString -> IO String
26 peekCStringLen, -- :: CStringLen -> IO String
27
28 -- conversion of Haskell strings into C strings
29 --
30 newCString, -- :: String -> IO CString
31 newCStringLen, -- :: String -> IO CStringLen
32
33 -- conversion of Haskell strings into C strings using temporary storage
34 --
35 withCString, -- :: String -> (CString -> IO a) -> IO a
36 withCStringLen, -- :: String -> (CStringLen -> IO a) -> IO a
37
38 -- conversion between Haskell and C characters *ignoring* the encoding
39 --
40 castCharToCChar, -- :: Char -> CChar
41 castCCharToChar, -- :: CChar -> Char
42
43 -- UnsafeCString: these might be more efficient than CStrings when
44 -- passing the string to an "unsafe" foreign import. NOTE: this
45 -- feature might be removed in favour of a more general approach in
46 -- the future.
47 --
48 UnsafeCString, -- abstract
49 withUnsafeCString, -- :: String -> (UnsafeCString -> IO a) -> IO a
50
51 ) where
52
53 import Foreign.Marshal.Array
54 import Foreign.C.Types
55 import Foreign.Ptr
56
57 import Data.Word
58
59 #ifdef __GLASGOW_HASKELL__
60 import GHC.ByteArr
61 import GHC.Pack
62 import GHC.List
63 import GHC.Real
64 import GHC.Num
65 import GHC.IOBase
66 import GHC.Base
67 #endif
68
69 -----------------------------------------------------------------------------
70 -- Strings
71
72 -- representation of strings in C
73 -- ------------------------------
74
75 type CString = Ptr CChar -- conventional NUL terminates strings
76 type CStringLen = (CString, Int) -- strings with explicit length
77
78
79 -- exported functions
80 -- ------------------
81 --
82 -- * the following routines apply the default conversion when converting the
83 -- C-land character encoding into the Haskell-land character encoding
84 --
85 -- ** NOTE: The current implementation doesn't handle conversions yet! **
86 --
87 -- * the routines using an explicit length tolerate NUL characters in the
88 -- middle of a string
89 --
90
91 -- marshal a NUL terminated C string into a Haskell string
92 --
93 peekCString :: CString -> IO String
94 peekCString cp = do cs <- peekArray0 nUL cp; return (cCharsToChars cs)
95
96 -- marshal a C string with explicit length into a Haskell string
97 --
98 peekCStringLen :: CStringLen -> IO String
99 peekCStringLen (cp, len) = do cs <- peekArray len cp; return (cCharsToChars cs)
100
101 -- marshal a Haskell string into a NUL terminated C strings
102 --
103 -- * the Haskell string may *not* contain any NUL characters
104 --
105 -- * new storage is allocated for the C string and must be explicitly freed
106 --
107 newCString :: String -> IO CString
108 newCString = newArray0 nUL . charsToCChars
109
110 -- marshal a Haskell string into a C string (ie, character array) with
111 -- explicit length information
112 --
113 -- * new storage is allocated for the C string and must be explicitly freed
114 --
115 newCStringLen :: String -> IO CStringLen
116 newCStringLen str = do a <- newArray (charsToCChars str)
117 return (pairLength str a)
118
119 -- marshal a Haskell string into a NUL terminated C strings using temporary
120 -- storage
121 --
122 -- * the Haskell string may *not* contain any NUL characters
123 --
124 -- * see the lifetime constraints of `MarshalAlloc.alloca'
125 --
126 withCString :: String -> (CString -> IO a) -> IO a
127 withCString = withArray0 nUL . charsToCChars
128
129 -- marshal a Haskell string into a NUL terminated C strings using temporary
130 -- storage
131 --
132 -- * the Haskell string may *not* contain any NUL characters
133 --
134 -- * see the lifetime constraints of `MarshalAlloc.alloca'
135 --
136 withCStringLen :: String -> (CStringLen -> IO a) -> IO a
137 withCStringLen str act = withArray (charsToCChars str) $ act . pairLength str
138
139 -- auxilliary definitions
140 -- ----------------------
141
142 -- C's end of string character
143 --
144 nUL :: CChar
145 nUL = 0
146
147 -- pair a C string with the length of the given Haskell string
148 --
149 pairLength :: String -> CString -> CStringLen
150 pairLength = flip (,) . length
151
152 -- cast [CChar] to [Char]
153 --
154 cCharsToChars :: [CChar] -> [Char]
155 cCharsToChars = map castCCharToChar
156
157 -- cast [Char] to [CChar]
158 --
159 charsToCChars :: [Char] -> [CChar]
160 charsToCChars = map castCharToCChar
161
162 castCCharToChar :: CChar -> Char
163 castCCharToChar ch = unsafeChr (fromIntegral (fromIntegral ch :: Word8))
164
165 castCharToCChar :: Char -> CChar
166 castCharToCChar ch = fromIntegral (ord ch)
167
168
169 -- unsafe CStrings
170 -- ---------------
171
172 withUnsafeCString :: String -> (UnsafeCString -> IO a) -> IO a
173 #if __GLASGOW_HASKELL__
174 newtype UnsafeCString = UnsafeCString (ByteArray Int)
175 withUnsafeCString s f = f (UnsafeCString (packString s))
176 #else
177 newtype UnsafeCString = UnsafeCString (Ptr CChar)
178 withUnsafeCString s f = withCString s (\p -> f (UnsafeCString p))
179 #endif