2 % (c) The GRASP/AQUA Project, Glasgow University, 1997
4 \section[PrelPack]{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
11 system library PackedString.
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 unpackNBytesAccST, -- :: Addr -> Int -> [Char] -> ST s [Char]
29 unpackCString#, -- :: Addr# -> [Char] **
30 unpackNBytes#, -- :: Addr# -> Int# -> [Char] **
31 unpackNBytesST#, -- :: Addr# -> Int# -> ST s [Char]
33 unpackCStringBA, -- :: ByteArray Int -> [Char]
34 unpackNBytesBA, -- :: ByteArray Int -> Int -> [Char]
35 unpackCStringBA#, -- :: ByteArray# -> Int# -> [Char]
36 unpackNBytesBA#, -- :: ByteArray# -> Int# -> [Char]
39 unpackFoldrCString#, -- **
40 unpackAppendCString#, -- **
42 new_ps_array, -- Int# -> ST s (MutableByteArray s Int)
43 write_ps_array, -- MutableByteArray s Int -> Int# -> Char# -> ST s ()
44 freeze_ps_array -- MutableByteArray s Int -> Int# -> ST s (ByteArray Int)
50 import {-# SOURCE #-} PrelErr ( 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) = unpackNBytesAccST# addr l []
91 unpackNBytesAccST :: Addr -> Int -> [Char] -> ST s [Char]
92 unpackNBytesAccST (A# addr) (I# l) rest = unpackNBytesAccST# addr l rest
94 unpackNBytes# :: Addr# -> Int# -> [Char]
95 -- This one is called by the compiler to unpack literal strings with NULs in them; rare.
97 unpackNBytes# addr 0# = []
98 unpackNBytes# addr len# = unpack [] (len# -# 1#)
103 case indexCharOffAddr# addr i# of
104 ch -> unpack (C# ch : acc) (i# -# 1#)
106 unpackNBytesST# :: Addr# -> Int# -> ST s [Char]
107 unpackNBytesST# addr# l# = unpackNBytesAccST# addr# l# []
109 unpackNBytesAccST# :: Addr# -> Int# -> [Char] -> ST s [Char]
110 unpackNBytesAccST# addr 0# rest = return rest
111 unpackNBytesAccST# addr len# rest = unpack rest (len# -# 1#)
114 | i# <# 0# = return acc
116 case indexCharOffAddr# addr i# of
117 ch -> unpack (C# ch : acc) (i# -# 1#)
121 %********************************************************
123 \subsection{Unpacking ByteArrays}
125 %********************************************************
127 Converting byte arrays into list of chars:
130 unpackCStringBA :: ByteArray Int -> [Char]
131 unpackCStringBA (ByteArray (l@(I# l#),u@(I# u#)) bytes)
133 | otherwise = unpackCStringBA# bytes (u# -# l# +# 1#)
136 unpack until NUL or end of BA is reached, whatever comes first.
138 unpackCStringBA# :: ByteArray# -> Int# -> [Char]
139 unpackCStringBA# bytes len
144 ch `eqChar#` '\0'# = []
145 | otherwise = C# ch : unpack (nh +# 1#)
147 ch = indexCharArray# bytes nh
149 unpackNBytesBA :: ByteArray Int -> Int -> [Char]
150 unpackNBytesBA (ByteArray (l,u) bytes) i
151 = unpackNBytesBA# bytes len#
153 len# = case max 0 (min i len) of I# v# -> v#
157 unpackNBytesBA# :: ByteArray# -> Int# -> [Char]
158 unpackNBytesBA# bytes 0# = []
159 unpackNBytesBA# bytes len# = unpack [] (len# -# 1#)
164 case indexCharArray# bytes i# of
165 ch -> unpack (C# ch : acc) (i# -# 1#)
170 %********************************************************
172 \subsection{Packing Strings}
174 %********************************************************
176 Converting a list of chars into a packed @ByteArray@ representation.
179 packCString# :: [Char] -> ByteArray#
180 packCString# str = case (packString str) of { ByteArray _ bytes -> bytes }
182 packString :: [Char] -> ByteArray Int
183 packString str = runST (packStringST str)
185 packStringST :: [Char] -> ST s (ByteArray Int)
187 let len = length str in
190 packNBytesST :: Int -> [Char] -> ST s (ByteArray Int)
191 packNBytesST len@(I# length#) str =
193 allocate an array that will hold the string
194 (not forgetting the NUL byte at the end)
196 new_ps_array (length# +# 1#) >>= \ ch_array ->
197 -- fill in packed string from "str"
198 fill_in ch_array 0# str >>
200 freeze_ps_array ch_array length#
202 fill_in :: MutableByteArray s Int -> Int# -> [Char] -> ST s ()
203 fill_in arr_in# idx [] =
204 write_ps_array arr_in# idx (chr# 0#) >>
207 fill_in arr_in# idx (C# c : cs) =
208 write_ps_array arr_in# idx c >>
209 fill_in arr_in# (idx +# 1#) cs
213 (Very :-) ``Specialised'' versions of some CharArray things...
216 new_ps_array :: Int# -> ST s (MutableByteArray s Int)
217 write_ps_array :: MutableByteArray s Int -> Int# -> Char# -> ST s ()
218 freeze_ps_array :: MutableByteArray s Int -> Int# -> ST s (ByteArray Int)
220 new_ps_array size = ST $ \ s ->
221 case (newCharArray# size s) of { (# s2#, barr# #) ->
222 (# s2#, MutableByteArray bot barr# #) }
224 bot = error "new_ps_array"
226 write_ps_array (MutableByteArray _ barr#) n ch = ST $ \ s# ->
227 case writeCharArray# barr# n ch s# of { s2# ->
230 -- same as unsafeFreezeByteArray
231 freeze_ps_array (MutableByteArray _ arr#) len# = ST $ \ s# ->
232 case unsafeFreezeByteArray# arr# s# of { (# s2#, frozen# #) ->
233 (# s2#, ByteArray (0,I# len#) frozen# #) }
237 %********************************************************
241 %********************************************************
243 The compiler may emit these two
246 unpackAppendCString# :: Addr# -> [Char] -> [Char]
247 unpackAppendCString# addr rest
251 | ch `eqChar#` '\0'# = rest
252 | otherwise = C# ch : unpack (nh +# 1#)
254 ch = indexCharOffAddr# addr nh
256 unpackFoldrCString# :: Addr# -> (Char -> a -> a) -> a -> a
257 unpackFoldrCString# addr f z
261 | ch `eqChar#` '\0'# = z
262 | otherwise = C# ch `f` unpack (nh +# 1#)
264 ch = indexCharOffAddr# addr nh