[project @ 2001-08-17 12:50:34 by simonmar]
[ghc-base.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   :  provisional
10 -- Portability :  portable
11 --
12 -- $Id: String.hs,v 1.3 2001/08/17 12:50:34 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   ) where
44
45 import Foreign.Marshal.Array
46 import Foreign.C.Types
47 import Foreign.Ptr
48
49 import Data.Word
50
51 #ifdef __GLASGOW_HASKELL__
52 import GHC.ByteArr
53 import GHC.Pack
54 import GHC.List
55 import GHC.Real
56 import GHC.Num
57 import GHC.IOBase
58 import GHC.Base
59 #endif
60
61 -----------------------------------------------------------------------------
62 -- Strings
63
64 -- representation of strings in C
65 -- ------------------------------
66
67 type CString    = Ptr CChar             -- conventional NUL terminates strings
68 type CStringLen = (CString, Int)        -- strings with explicit length
69
70
71 -- exported functions
72 -- ------------------
73 --
74 -- * the following routines apply the default conversion when converting the
75 --   C-land character encoding into the Haskell-land character encoding
76 --
77 --   ** NOTE: The current implementation doesn't handle conversions yet! **
78 --
79 -- * the routines using an explicit length tolerate NUL characters in the
80 --   middle of a string
81 --
82
83 -- marshal a NUL terminated C string into a Haskell string 
84 --
85 peekCString    :: CString -> IO String
86 peekCString cp  = do cs <- peekArray0 nUL cp; return (cCharsToChars cs)
87
88 -- marshal a C string with explicit length into a Haskell string 
89 --
90 peekCStringLen           :: CStringLen -> IO String
91 peekCStringLen (cp, len)  = do cs <- peekArray len cp; return (cCharsToChars cs)
92
93 -- marshal a Haskell string into a NUL terminated C strings
94 --
95 -- * the Haskell string may *not* contain any NUL characters
96 --
97 -- * new storage is allocated for the C string and must be explicitly freed
98 --
99 newCString :: String -> IO CString
100 newCString  = newArray0 nUL . charsToCChars
101
102 -- marshal a Haskell string into a C string (ie, character array) with
103 -- explicit length information
104 --
105 -- * new storage is allocated for the C string and must be explicitly freed
106 --
107 newCStringLen     :: String -> IO CStringLen
108 newCStringLen str  = do a <- newArray (charsToCChars str)
109                         return (pairLength str a)
110
111 -- marshal a Haskell string into a NUL terminated C strings using temporary
112 -- storage
113 --
114 -- * the Haskell string may *not* contain any NUL characters
115 --
116 -- * see the lifetime constraints of `MarshalAlloc.alloca'
117 --
118 withCString :: String -> (CString -> IO a) -> IO a
119 withCString  = withArray0 nUL . charsToCChars
120
121 -- marshal a Haskell string into a NUL terminated C strings using temporary
122 -- storage
123 --
124 -- * the Haskell string may *not* contain any NUL characters
125 --
126 -- * see the lifetime constraints of `MarshalAlloc.alloca'
127 --
128 withCStringLen         :: String -> (CStringLen -> IO a) -> IO a
129 withCStringLen str act  = withArray (charsToCChars str) $ act . pairLength str
130
131 -- auxilliary definitions
132 -- ----------------------
133
134 -- C's end of string character
135 --
136 nUL :: CChar
137 nUL  = 0
138
139 -- pair a C string with the length of the given Haskell string
140 --
141 pairLength :: String -> CString -> CStringLen
142 pairLength  = flip (,) . length
143
144 -- cast [CChar] to [Char]
145 --
146 cCharsToChars :: [CChar] -> [Char]
147 cCharsToChars  = map castCCharToChar
148
149 -- cast [Char] to [CChar]
150 --
151 charsToCChars :: [Char] -> [CChar]
152 charsToCChars  = map castCharToCChar
153
154 castCCharToChar :: CChar -> Char
155 castCCharToChar ch = unsafeChr (fromIntegral (fromIntegral ch :: Word8))
156
157 castCharToCChar :: Char -> CChar
158 castCharToCChar ch = fromIntegral (ord ch)