2 % (c) The GRASP/AQUA Project, Glasgow University, 1997
4 \section{Basic ops on packed representations}
6 Some basic operations for working on packed representations of series
7 of bytes (character strings). Used by the interface lexer input
11 #include "HsVersions.h"
15 strLength, -- :: _Addr -> Int
16 copyPrefixStr, -- :: _Addr -> Int -> _ByteArray Int
17 copySubStr, -- :: _Addr -> Int -> Int -> _ByteArray Int
18 copySubStrFO, -- :: ForeignObj -> Int -> Int -> _ByteArray Int
19 copySubStrBA, -- :: _ByteArray Int -> Int -> Int -> _ByteArray Int
21 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 205
22 stringToByteArray, -- :: String -> _ByteArray Int
23 byteArrayToString, -- :: _ByteArray Int -> String
26 eqStrPrefix, -- :: Addr# -> ByteArray# -> Int# -> Bool
27 eqCharStrPrefix, -- :: Addr# -> Addr# -> Int# -> Bool
28 eqStrPrefixBA, -- :: ByteArray# -> ByteArray# -> Int# -> Int# -> Bool
29 eqCharStrPrefixBA, -- :: Addr# -> ByteArray# -> Int# -> Int# -> Bool
30 eqStrPrefixFO, -- :: ForeignObj# -> ByteArray# -> Int# -> Int# -> Bool
32 addrOffset#, -- :: Addr# -> Int# -> Addr#
33 indexCharOffFO# -- :: ForeignObj# -> Int# -> Char#
36 #if __GLASGOW_HASKELL__ <= 201
47 # if __GLASGOW_HASKELL__ == 202
48 import PrelBase ( Char(..) )
51 # if __GLASGOW_HASKELL__ >= 206
55 # if __GLASGOW_HASKELL__ >= 209
63 Return the length of a @\\NUL@ terminated character string:
66 strLength :: _Addr -> Int
69 _ccall_ strlen a `thenPrimIO` \ len@(I# _) ->
75 Copying a char string prefix into a byte array,
76 {\em assuming} the prefix does not contain any
81 copyPrefixStr :: _Addr -> Int -> _ByteArray Int
82 copyPrefixStr (A# a) len@(I# length#) =
84 {- allocate an array that will hold the string
85 (not forgetting the NUL at the end)
87 new_ps_array (length# +# 1#) `thenStrictlyST` \ ch_array ->
88 -- fill in packed string from "addr"
89 fill_in ch_array 0# `thenStrictlyST` \ _ ->
91 freeze_ps_array ch_array `thenStrictlyST` \ barr ->
92 returnStrictlyST barr )
94 fill_in :: _MutableByteArray s Int -> Int# -> _ST s ()
98 = write_ps_array arr_in# idx (chr# 0#) `seqStrictlyST`
101 = case (indexCharOffAddr# a idx) of { ch ->
102 write_ps_array arr_in# idx ch `seqStrictlyST`
103 fill_in arr_in# (idx +# 1#) }
107 Copying out a substring, assume a 0-indexed string:
108 (and positive lengths, thank you).
111 copySubStr :: _Addr -> Int -> Int -> _ByteArray Int
112 copySubStr a start length =
113 unsafePerformPrimIO (
114 _casm_ `` %r= (char *)((char *)%0 + (int)%1); '' a start
115 `thenPrimIO` \ a_start ->
116 returnPrimIO (copyPrefixStr a_start length))
119 Copying a sub-string out of a ForeignObj
122 copySubStrFO :: _ForeignObj -> Int -> Int -> _ByteArray Int
123 copySubStrFO (_ForeignObj fo) (I# start#) len@(I# length#) =
125 {- allocate an array that will hold the string
126 (not forgetting the NUL at the end)
128 new_ps_array (length# +# 1#) `thenStrictlyST` \ ch_array ->
129 -- fill in packed string from "addr"
130 fill_in ch_array 0# `seqStrictlyST`
132 freeze_ps_array ch_array)
134 fill_in :: _MutableByteArray s Int -> Int# -> _ST s ()
138 = write_ps_array arr_in# idx (chr# 0#) `seqStrictlyST`
141 = case (indexCharOffFO# fo (idx +# start#)) of { ch ->
142 write_ps_array arr_in# idx ch `seqStrictlyST`
143 fill_in arr_in# (idx +# 1#) }
145 {- ToDo: add FO primitives.. -}
146 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <=205
147 indexCharOffFO# :: ForeignObj# -> Int# -> Char#
148 indexCharOffFO# fo# i# =
149 case unsafePerformPrimIO (_casm_ ``%r=(char)*((char *)%0 + (int)%1); '' (_ForeignObj fo#) (I# i#)) of
152 indexCharOffFO# :: ForeignObj# -> Int# -> Char#
153 indexCharOffFO# fo i = indexCharOffForeignObj# fo i
156 -- step on (char *) pointer by x units.
157 addrOffset# :: Addr# -> Int# -> Addr#
159 case unsafePerformPrimIO (_casm_ ``%r=(char *)((char *)%0 + (int)%1); '' (A# a#) (I# i#)) of
162 copySubStrBA :: _ByteArray Int -> Int -> Int -> _ByteArray Int
163 copySubStrBA (_ByteArray _ barr#) (I# start#) len@(I# length#) =
165 {- allocate an array that will hold the string
166 (not forgetting the NUL at the end)
168 new_ps_array (length# +# 1#) `thenStrictlyST` \ ch_array ->
169 -- fill in packed string from "addr"
170 fill_in ch_array 0# `seqStrictlyST`
172 freeze_ps_array ch_array)
174 fill_in :: _MutableByteArray s Int -> Int# -> _ST s ()
178 = write_ps_array arr_in# idx (chr# 0#) `seqStrictlyST`
181 = case (indexCharArray# barr# (start# +# idx)) of { ch ->
182 write_ps_array arr_in# idx ch `seqStrictlyST`
183 fill_in arr_in# (idx +# 1#) }
187 (Very :-) ``Specialised'' versions of some CharArray things...
190 new_ps_array :: Int# -> _ST s (_MutableByteArray s Int)
191 write_ps_array :: _MutableByteArray s Int -> Int# -> Char# -> _ST s ()
192 freeze_ps_array :: _MutableByteArray s Int -> _ST s (_ByteArray Int)
195 MkST ( \ STATE_TOK(s#) ->
196 case (newCharArray# size s#) of { StateAndMutableByteArray# s2# barr# ->
197 ST_RET(_MutableByteArray (0, max 0 (I# (size -# 1#))) barr#, STATE_TOK(s2#))})
199 write_ps_array (_MutableByteArray _ barr#) n ch =
200 MkST ( \ STATE_TOK(s#) ->
201 case writeCharArray# barr# n ch s# of { s2# ->
202 ST_RET((), STATE_TOK(s2#) )})
204 -- same as unsafeFreezeByteArray
205 freeze_ps_array (_MutableByteArray ixs arr#) =
206 MkST ( \ STATE_TOK(s#) ->
207 case unsafeFreezeByteArray# arr# s# of { StateAndByteArray# s2# frozen# ->
208 ST_RET((_ByteArray ixs frozen#), STATE_TOK(s2#))})
211 Compare two equal-length strings for equality:
214 eqStrPrefix :: Addr# -> ByteArray# -> Int# -> Bool
215 eqStrPrefix a# barr# len# =
216 unsafePerformPrimIO (
217 _ccall_ strncmp (A# a#) (_ByteArray bottom barr#) (I# len#) `thenPrimIO` \ (I# x#) ->
218 returnPrimIO (x# ==# 0#))
221 bottom = error "eqStrPrefix"
223 eqCharStrPrefix :: Addr# -> Addr# -> Int# -> Bool
224 eqCharStrPrefix a1# a2# len# =
225 unsafePerformPrimIO (
226 _ccall_ strncmp (A# a1#) (A# a2#) (I# len#) `thenPrimIO` \ (I# x#) ->
227 returnPrimIO (x# ==# 0#))
230 bottom = error "eqStrPrefix"
232 eqStrPrefixBA :: ByteArray# -> ByteArray# -> Int# -> Int# -> Bool
233 eqStrPrefixBA b1# b2# start# len# =
234 unsafePerformPrimIO (
235 _casm_ ``%r=(int)strncmp((char *)%0+(int)%1,%2,%3); ''
236 (_ByteArray bottom b2#)
238 (_ByteArray bottom b1#)
239 (I# len#) `thenPrimIO` \ (I# x#) ->
240 returnPrimIO (x# ==# 0#))
243 bottom = error "eqStrPrefixBA"
245 eqCharStrPrefixBA :: Addr# -> ByteArray# -> Int# -> Int# -> Bool
246 eqCharStrPrefixBA a# b2# start# len# =
247 unsafePerformPrimIO (
248 _casm_ ``%r=(int)strncmp((char *)%0+(int)%1,%2,%3); ''
249 (_ByteArray bottom b2#)
252 (I# len#) `thenPrimIO` \ (I# x#) ->
253 returnPrimIO (x# ==# 0#))
256 bottom = error "eqCharStrPrefixBA"
258 eqStrPrefixFO :: ForeignObj# -> ByteArray# -> Int# -> Int# -> Bool
259 eqStrPrefixFO fo# barr# start# len# =
260 unsafePerformPrimIO (
261 _casm_ ``%r=(int)strncmp((char *)%0+(int)%1,%2,%3); ''
264 (_ByteArray bottom barr#)
265 (I# len#) `thenPrimIO` \ (I# x#) ->
266 returnPrimIO (x# ==# 0#))
269 bottom = error "eqStrPrefixFO"
273 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 205
274 byteArrayToString :: _ByteArray Int -> String
275 byteArrayToString (_ByteArray (I# start#,I# end#) barr#) =
280 | otherwise = C# ch : unpack (nh# +# 1#)
282 ch = indexCharArray# barr# nh#
283 #elif defined(__GLASGOW_HASKELL__)
284 byteArrayToString :: _ByteArray Int -> String
285 byteArrayToString = unpackCStringBA
287 #error "byteArrayToString: cannot handle this!"
294 stringToByteArray :: String -> (_ByteArray Int)
295 #if __GLASGOW_HASKELL__ >= 206
296 stringToByteArray = packString
297 #elif defined(__GLASGOW_HASKELL__)
298 stringToByteArray str = _runST (packStringST str)
300 packStringST :: [Char] -> _ST s (_ByteArray Int)
302 let len = length str in
305 packNCharsST :: Int -> [Char] -> _ST s (_ByteArray Int)
306 packNCharsST len@(I# length#) str =
308 allocate an array that will hold the string
309 (not forgetting the NUL byte at the end)
311 new_ps_array (length# +# 1#) `thenStrictlyST` \ ch_array ->
312 -- fill in packed string from "str"
313 fill_in ch_array 0# str `seqStrictlyST`
315 freeze_ps_array ch_array `thenStrictlyST` \ (_ByteArray _ frozen#) ->
316 returnStrictlyST (_ByteArray (0,len) frozen#)
318 fill_in :: _MutableByteArray s Int -> Int# -> [Char] -> _ST s ()
319 fill_in arr_in# idx [] =
320 write_ps_array arr_in# idx (chr# 0#) `seqStrictlyST`
323 fill_in arr_in# idx (C# c : cs) =
324 write_ps_array arr_in# idx c `seqStrictlyST`
325 fill_in arr_in# (idx +# 1#) cs
327 #error "stringToByteArray: cannot handle this"