2 % (c) The GRASP/AQUA Project, Glasgow University, 1997
4 \section[PackBase]{Packing/unpacking bytes}
6 This module provides a small set of low-level functions for packing
7 and unpacking a chunk of bytes. Used by code emitted by the compiler
8 plus the prelude libraries.
10 The programmer level view of packed strings is provided by a GHC system library
14 {-# OPTIONS -fno-implicit-prelude #-}
18 -- (**) - emitted by compiler.
20 packCString#, -- :: [Char] -> ByteArray# **
21 packString, -- :: [Char] -> ByteArray Int
22 packStringST, -- :: [Char] -> ST s (ByteArray Int)
23 packNBytesST, -- :: Int -> [Char] -> ST s (ByteArray Int)
25 unpackCString, -- :: Addr -> [Char]
26 unpackNBytes, -- :: Addr -> Int -> [Char]
27 unpackNBytesST, -- :: Addr -> Int -> ST s [Char]
28 unpackCString#, -- :: Addr# -> [Char] **
29 unpackNBytes#, -- :: Addr# -> Int# -> [Char] **
30 unpackNBytesST#, -- :: Addr# -> Int# -> ST s [Char]
32 unpackCStringBA, -- :: ByteArray Int -> [Char]
33 unpackNBytesBA, -- :: ByteArray Int -> Int -> [Char]
34 unpackCStringBA#, -- :: ByteArray# -> Int# -> [Char]
35 unpackNBytesBA#, -- :: ByteArray# -> Int# -> [Char]
37 #ifndef __PARALLEL_HASKELL__
38 unpackCStringFO, -- :: ForeignObj -> [Char]
39 unpackNBytesFO, -- :: ForeignObj -> Int -> [Char]
40 unpackCStringFO#, -- :: ForeignObj# -> [Char]
41 unpackNBytesFO#, -- :: ForeignObj# -> Int# -> [Char]
44 unpackFoldrCString#, -- **
45 unpackAppendCString# -- **
50 import {-# SOURCE #-} IOBase ( error )
51 import PrelList ( length )
58 %*********************************************************
60 \subsection{Unpacking Addrs}
62 %*********************************************************
64 Primitives for converting Addrs pointing to external
65 sequence of bytes into a list of @Char@s:
68 unpackCString :: Addr{- ptr. to NUL terminated string-} -> [Char]
69 unpackCString a@(A# addr) =
75 unpackCString# :: Addr# -> [Char]
80 | ch `eqChar#` '\0'# = []
81 | otherwise = C# ch : unpack (nh +# 1#)
83 ch = indexCharOffAddr# addr nh
85 unpackNBytes :: Addr -> Int -> [Char]
86 unpackNBytes (A# addr) (I# l) = unpackNBytes# addr l
88 unpackNBytesST :: Addr -> Int -> ST s [Char]
89 unpackNBytesST (A# addr) (I# l) = unpackNBytesST# addr l
91 unpackNBytes# :: Addr# -> Int# -> [Char]
92 -- This one is called by the compiler to unpack literal strings with NULs in them; rare.
93 unpackNBytes# addr len
98 | otherwise = C# ch : unpack (i +# 1#)
100 ch = indexCharOffAddr# addr i
102 unpackNBytesST# :: Addr# -> Int# -> ST s [Char]
103 unpackNBytesST# addr len
107 | i >=# len = return []
109 case indexCharOffAddr# addr i of
110 ch -> unpack (i +# 1#) >>= \ ls -> return (C# ch : ls)
115 %*********************************************************
117 \subsection{Unpacking Foreigns}
119 %*********************************************************
121 Primitives for converting Foreigns pointing to external
122 sequence of bytes into a list of @Char@s (a renamed version
126 #ifndef __PARALLEL_HASKELL__
127 unpackCStringFO :: ForeignObj -> [Char]
128 unpackCStringFO (ForeignObj fo#) = unpackCStringFO# fo#
130 unpackCStringFO# :: ForeignObj# -> [Char]
131 unpackCStringFO# fo {- ptr. to NUL terminated string-}
135 | ch `eqChar#` '\0'# = []
136 | otherwise = C# ch : unpack (nh +# 1#)
138 ch = indexCharOffForeignObj# fo nh
140 unpackNBytesFO :: ForeignObj -> Int -> [Char]
141 unpackNBytesFO (ForeignObj fo) (I# l) = unpackNBytesFO# fo l
143 unpackNBytesFO# :: ForeignObj# -> Int# -> [Char]
144 -- This one is called by the compiler to unpack literal strings with NULs in them; rare.
145 unpackNBytesFO# fo len
150 | otherwise = C# ch : unpack (i +# 1#)
152 ch = indexCharOffForeignObj# fo i
157 %********************************************************
159 \subsection{Unpacking ByteArrays}
161 %********************************************************
163 Converting byte arrays into list of chars:
166 unpackCStringBA :: ByteArray Int -> [Char]
167 unpackCStringBA (ByteArray (l@(I# l#),u@(I# u#)) bytes)
169 | otherwise = unpackCStringBA# bytes (u# -# l# +# 1#)
172 unpack until NUL or end of BA is reached, whatever comes first.
174 unpackCStringBA# :: ByteArray# -> Int# -> [Char]
175 unpackCStringBA# bytes len
180 ch `eqChar#` '\0'# = []
181 | otherwise = C# ch : unpack (nh +# 1#)
183 ch = indexCharArray# bytes nh
185 unpackNBytesBA :: ByteArray Int -> Int -> [Char]
186 unpackNBytesBA (ByteArray (l,u) bytes) i
187 = unpackNBytesBA# bytes len#
189 len# = case max 0 (min i len) of I# v# -> v#
193 unpackNBytesBA# :: ByteArray# -> Int# -> [Char]
194 unpackNBytesBA# bytes nh
199 | otherwise = C# ch : unpack (i +# 1#)
201 ch = indexCharArray# bytes i
205 %********************************************************
207 \subsection{Packing Strings}
209 %********************************************************
211 Converting a list of chars into a packed @ByteArray@ representation.
214 packCString# :: [Char] -> ByteArray#
215 packCString# str = case (packString str) of { ByteArray _ bytes -> bytes }
217 packString :: [Char] -> ByteArray Int
218 packString str = runST (packStringST str)
220 packStringST :: [Char] -> ST s (ByteArray Int)
222 let len = length str in
225 packNBytesST :: Int -> [Char] -> ST s (ByteArray Int)
226 packNBytesST len@(I# length#) str =
228 allocate an array that will hold the string
229 (not forgetting the NUL byte at the end)
231 new_ps_array (length# +# 1#) >>= \ ch_array ->
232 -- fill in packed string from "str"
233 fill_in ch_array 0# str >>
235 freeze_ps_array ch_array length#
237 fill_in :: MutableByteArray s Int -> Int# -> [Char] -> ST s ()
238 fill_in arr_in# idx [] =
239 write_ps_array arr_in# idx (chr# 0#) >>
242 fill_in arr_in# idx (C# c : cs) =
243 write_ps_array arr_in# idx c >>
244 fill_in arr_in# (idx +# 1#) cs
248 (Very :-) ``Specialised'' versions of some CharArray things...
251 new_ps_array :: Int# -> ST s (MutableByteArray s Int)
252 write_ps_array :: MutableByteArray s Int -> Int# -> Char# -> ST s ()
253 freeze_ps_array :: MutableByteArray s Int -> Int# -> ST s (ByteArray Int)
255 new_ps_array size = ST $ \ s ->
256 case (newCharArray# size s) of { StateAndMutableByteArray# s2# barr# ->
257 STret s2# (MutableByteArray bot barr#) }
259 bot = error "new_ps_array"
261 write_ps_array (MutableByteArray _ barr#) n ch = ST $ \ s# ->
262 case writeCharArray# barr# n ch s# of { s2# ->
265 -- same as unsafeFreezeByteArray
266 freeze_ps_array (MutableByteArray _ arr#) len# = ST $ \ s# ->
267 case unsafeFreezeByteArray# arr# s# of { StateAndByteArray# s2# frozen# ->
268 STret s2# (ByteArray (0,I# len#) frozen#) }
272 %********************************************************
276 %********************************************************
278 The compiler may emit these two
281 unpackAppendCString# :: Addr# -> [Char] -> [Char]
282 unpackAppendCString# addr rest
286 | ch `eqChar#` '\0'# = rest
287 | otherwise = C# ch : unpack (nh +# 1#)
289 ch = indexCharOffAddr# addr nh
291 unpackFoldrCString# :: Addr# -> (Char -> a -> a) -> a -> a
292 unpackFoldrCString# addr f z
296 | ch `eqChar#` '\0'# = z
297 | otherwise = C# ch `f` unpack (nh +# 1#)
299 ch = indexCharOffAddr# addr nh