2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
4 \section{Working with C strings}
6 A collection of lower-level functions to help converting between
7 C strings and Haskell Strings (packed or otherwise).
9 A more user-friendly Haskell interface to packed string representation
10 is the PackedString interface.
15 unpackCString -- :: Addr -> [Char]
16 , unpackNBytes -- :: Addr -> Int -> [Char]
17 , unpackNBytesST -- :: Addr -> Int -> ST s [Char]
18 , unpackNBytesAccST -- :: Addr -> Int -> [Char] -> ST s [Char]
19 , unpackCString# -- :: Addr# -> [Char] **
20 , unpackNBytes# -- :: Addr# -> Int# -> [Char] **
21 , unpackNBytesST# -- :: Addr# -> Int# -> ST s [Char]
24 , unpackCStringIO -- :: Addr -> IO String
25 , unpackCStringLenIO -- :: Addr -> Int -> IO String
26 , unpackNBytesIO -- :: Addr -> Int -> IO [Char]
27 , unpackNBytesAccIO -- :: Addr -> Int -> [Char] -> IO [Char]
28 , unpackNBytesBAIO -- :: ByteArray Int -> Int -> IO [Char]
29 , unpackNBytesAccBAIO -- :: ByteArray Int -> Int -> [Char] -> IO [Char]
31 , packString -- :: [Char] -> ByteArray Int
32 , packStringST -- :: [Char] -> ST s (ByteArray Int)
33 , packStringIO -- :: [Char] -> IO (ByteArray Int)
34 , packNBytesST -- :: Int -> [Char] -> ByteArray Int
35 , packCString# -- :: [Char] -> ByteArray#
37 , unpackCStringBA -- :: ByteArray Int -> [Char]
38 , unpackNBytesBA -- :: ByteArray Int -> Int -> [Char]
39 , unpackCStringBA# -- :: ByteArray# -> Int# -> [Char]
40 , unpackNBytesBA# -- :: ByteArray# -> Int# -> [Char]
42 -- unmarshaling (char*) vectors.
43 , unvectorize -- :: Addr -> Int -> IO [String]
44 , vectorize -- :: [[Char]] -> IO (ByteArray Int)
47 , allocChars -- :: Int -> IO (MutableByteArray RealWorld Int)
48 , allocWords -- :: Int -> IO (MutableByteArray RealWorld Int)
49 , freeze -- :: MutableByteArray RealWorld Int -> IO (ByteArray Int)
50 , strcpy -- :: Addr -> IO String
57 import PrelIOBase ( IO(..) )
62 packStringIO :: [Char] -> IO (ByteArray Int)
63 packStringIO str = stToIO (packStringST str)
67 unpackCStringIO :: Addr -> IO String
69 | addr == ``NULL'' = return ""
70 | otherwise = unpack 0#
73 ch <- readCharOffAddr addr (I# nh)
77 ls <- unpack (nh +# 1#)
81 unpackCStringLenIO :: Addr -> Int -> IO String
82 unpackCStringLenIO addr l@(I# len#)
83 | len# <# 0# = ioError (userError ("CString.unpackCStringLenIO: negative length (" ++ show l ++ ")"))
84 | len# ==# 0# = return ""
85 | otherwise = unpack [] (len# -# 1#)
88 ch <- readCharOffAddr addr (I# 0#)
91 ch <- readCharOffAddr addr (I# nh)
92 unpack (ch:acc) (nh -# 1#)
94 unpackNBytesIO :: Addr -> Int -> IO [Char]
95 unpackNBytesIO a l = stToIO (unpackNBytesST a l)
97 unpackNBytesAccIO :: Addr -> Int -> [Char] -> IO [Char]
98 unpackNBytesAccIO a l acc = stToIO (unpackNBytesAccST a l acc)
100 unpackNBytesBAIO :: ByteArray Int -> Int -> IO [Char]
101 unpackNBytesBAIO ba l = unpackNBytesAccBAIO ba l []
103 -- note: no bounds checking!
104 unpackNBytesAccBAIO :: ByteArray Int -> Int -> [Char] -> IO [Char]
105 unpackNBytesAccBAIO _ 0 rest = return rest
106 unpackNBytesAccBAIO (ByteArray _ ba) (I# len#) rest = unpack rest (len# -# 1#)
109 | i# <# 0# = return acc
111 case indexCharArray# ba i# of
112 ch -> unpack (C# ch : acc) (i# -# 1#)
116 Turn a NULL-terminated vector of null-terminated strings into a string list
117 (ToDo: create a module of common marshaling functions)
120 unvectorize :: Addr -> Int -> IO [String]
122 | str == ``NULL'' = return []
124 x <- unpackCStringIO str
125 xs <- unvectorize ptr (n+1)
128 str = indexAddrOffAddr ptr n
132 Turn a string list into a NULL-terminated vector of null-terminated
133 strings No indices...I hate indices. Death to Ix.
136 vectorize :: [String] -> IO (ByteArray Int)
138 arr <- allocWords (len + 1)
145 fill :: MutableByteArray RealWorld Int -> Int -> [String] -> IO ()
147 _casm_ ``((PP_)%0)[%1] = NULL;'' arr n
149 packStringIO x >>= \ barr ->
150 _casm_ ``((PP_)%0)[%1] = (P_)%2;'' arr n barr
156 Allocating chunks of memory in the Haskell heap, leaving
157 out the bounds - use with care.
160 -- Allocate a mutable array of characters with no indices.
161 allocChars :: Int -> IO (MutableByteArray RealWorld Int)
162 allocChars (I# size#) = IO $ \ s# ->
163 case newCharArray# size# s# of
165 (# s2#, (MutableByteArray (I# 1#, I# size#) barr#) #)
167 allocWords :: Int -> IO (MutableByteArray RealWorld Int)
168 allocWords (I# size#) = IO $ \ s# ->
169 case newIntArray# size# s# of
171 (# s2#, (MutableByteArray (I# 1#, I# size#) barr#) #)
173 -- Freeze these index-free mutable arrays
174 freeze :: MutableByteArray RealWorld Int -> IO (ByteArray Int)
175 freeze (MutableByteArray ixs arr#) = IO $ \ s# ->
176 case unsafeFreezeByteArray# arr# s# of
177 (# s2#, frozen# #) ->
178 (# s2#, (ByteArray ixs frozen#) #)
180 -- Copy a null-terminated string from outside the heap to
181 -- Haskellized nonsense inside the heap
182 strcpy :: Addr -> IO String
183 strcpy str = unpackCStringIO str