1 % ------------------------------------------------------------------------------
2 % $Id: PrelPack.lhs,v 1.14 2000/07/07 11:03:58 simonmar Exp $
4 % (c) The University of Glasgow, 1997-2000
7 \section[PrelPack]{Packing/unpacking bytes}
9 This module provides a small set of low-level functions for packing
10 and unpacking a chunk of bytes. Used by code emitted by the compiler
11 plus the prelude libraries.
13 The programmer level view of packed strings is provided by a GHC
14 system library PackedString.
17 {-# OPTIONS -fno-implicit-prelude #-}
21 -- (**) - emitted by compiler.
23 packCString#, -- :: [Char] -> ByteArray# **
24 packString, -- :: [Char] -> ByteArray Int
25 packStringST, -- :: [Char] -> ST s (ByteArray Int)
26 packNBytesST, -- :: Int -> [Char] -> ST s (ByteArray Int)
28 unpackCString, -- :: Addr -> [Char]
29 unpackCStringST, -- :: Addr -> ST s [Char]
30 unpackNBytes, -- :: Addr -> Int -> [Char]
31 unpackNBytesST, -- :: Addr -> Int -> ST s [Char]
32 unpackNBytesAccST, -- :: Addr -> Int -> [Char] -> ST s [Char]
33 unpackCString#, -- :: Addr# -> [Char] **
34 unpackNBytes#, -- :: Addr# -> Int# -> [Char] **
35 unpackNBytesST#, -- :: Addr# -> Int# -> ST s [Char]
37 unpackCStringBA, -- :: ByteArray Int -> [Char]
38 unpackNBytesBA, -- :: ByteArray Int -> Int -> [Char]
39 unpackCStringBA#, -- :: ByteArray# -> Int# -> [Char]
40 unpackNBytesBA#, -- :: ByteArray# -> Int# -> [Char]
43 unpackFoldrCString#, -- **
44 unpackAppendCString#, -- **
46 new_ps_array, -- Int# -> ST s (MutableByteArray s Int)
47 write_ps_array, -- MutableByteArray s Int -> Int# -> Char# -> ST s ()
48 freeze_ps_array -- MutableByteArray s Int -> Int# -> ST s (ByteArray Int)
54 import {-# SOURCE #-} PrelErr ( error )
55 import PrelList ( length )
63 %*********************************************************
65 \subsection{Unpacking Addrs}
67 %*********************************************************
69 Primitives for converting Addrs pointing to external
70 sequence of bytes into a list of @Char@s:
73 unpackCString :: Addr -> [Char]
74 unpackCString a@(A# addr)
76 | otherwise = unpackCString# addr
78 unpackNBytes :: Addr -> Int -> [Char]
79 unpackNBytes (A# addr) (I# l) = unpackNBytes# addr l
81 unpackCStringST :: Addr{- ptr. to NUL terminated string-} -> ST s [Char]
82 unpackCStringST a@(A# addr)
83 | a == nullAddr = return []
84 | otherwise = unpack 0#
87 | ch `eqChar#` '\0'# = return []
89 ls <- unpack (nh +# 1#)
90 return ((C# ch ) : ls)
92 ch = indexCharOffAddr# addr nh
94 unpackNBytesST :: Addr -> Int -> ST s [Char]
95 unpackNBytesST (A# addr) (I# l) = unpackNBytesAccST# addr l []
97 unpackNBytesAccST :: Addr -> Int -> [Char] -> ST s [Char]
98 unpackNBytesAccST (A# addr) (I# l) rest = unpackNBytesAccST# addr l rest
100 unpackNBytesST# :: Addr# -> Int# -> ST s [Char]
101 unpackNBytesST# addr# l# = unpackNBytesAccST# addr# l# []
103 unpackNBytesAccST# :: Addr# -> Int# -> [Char] -> ST s [Char]
104 unpackNBytesAccST# _addr 0# rest = return rest
105 unpackNBytesAccST# addr len# rest = unpack rest (len# -# 1#)
108 | i# <# 0# = return acc
110 case indexCharOffAddr# addr i# of
111 ch -> unpack (C# ch : acc) (i# -# 1#)
115 %********************************************************
117 \subsection{Unpacking ByteArrays}
119 %********************************************************
121 Converting byte arrays into list of chars:
124 unpackCStringBA :: ByteArray Int -> [Char]
125 unpackCStringBA (ByteArray l@(I# l#) u@(I# u#) bytes)
127 | otherwise = unpackCStringBA# bytes (u# -# l# +# 1#)
130 unpack until NUL or end of BA is reached, whatever comes first.
132 unpackCStringBA# :: ByteArray# -> Int# -> [Char]
133 unpackCStringBA# bytes len
138 ch `eqChar#` '\0'# = []
139 | otherwise = C# ch : unpack (nh +# 1#)
141 ch = indexCharArray# bytes nh
143 unpackNBytesBA :: ByteArray Int -> Int -> [Char]
144 unpackNBytesBA (ByteArray l u bytes) i
145 = unpackNBytesBA# bytes len#
147 len# = case max 0 (min i len) of I# v# -> v#
151 unpackNBytesBA# :: ByteArray# -> Int# -> [Char]
152 unpackNBytesBA# _bytes 0# = []
153 unpackNBytesBA# bytes len# = unpack [] (len# -# 1#)
158 case indexCharArray# bytes i# of
159 ch -> unpack (C# ch : acc) (i# -# 1#)
164 %********************************************************
166 \subsection{Packing Strings}
168 %********************************************************
170 Converting a list of chars into a packed @ByteArray@ representation.
173 packCString# :: [Char] -> ByteArray#
174 packCString# str = case (packString str) of { ByteArray _ _ bytes -> bytes }
176 packString :: [Char] -> ByteArray Int
177 packString str = runST (packStringST str)
179 packStringST :: [Char] -> ST s (ByteArray Int)
181 let len = length str in
184 packNBytesST :: Int -> [Char] -> ST s (ByteArray Int)
185 packNBytesST (I# length#) str =
187 allocate an array that will hold the string
188 (not forgetting the NUL byte at the end)
190 new_ps_array (length# +# 1#) >>= \ ch_array ->
191 -- fill in packed string from "str"
192 fill_in ch_array 0# str >>
194 freeze_ps_array ch_array length#
196 fill_in :: MutableByteArray s Int -> Int# -> [Char] -> ST s ()
197 fill_in arr_in# idx [] =
198 write_ps_array arr_in# idx (chr# 0#) >>
201 fill_in arr_in# idx (C# c : cs) =
202 write_ps_array arr_in# idx c >>
203 fill_in arr_in# (idx +# 1#) cs
207 (Very :-) ``Specialised'' versions of some CharArray things...
210 new_ps_array :: Int# -> ST s (MutableByteArray s Int)
211 write_ps_array :: MutableByteArray s Int -> Int# -> Char# -> ST s ()
212 freeze_ps_array :: MutableByteArray s Int -> Int# -> ST s (ByteArray Int)
214 new_ps_array size = ST $ \ s ->
215 case (newCharArray# size s) of { (# s2#, barr# #) ->
216 (# s2#, MutableByteArray bot bot barr# #) }
218 bot = error "new_ps_array"
220 write_ps_array (MutableByteArray _ _ barr#) n ch = ST $ \ s# ->
221 case writeCharArray# barr# n ch s# of { s2# ->
224 -- same as unsafeFreezeByteArray
225 freeze_ps_array (MutableByteArray _ _ arr#) len# = ST $ \ s# ->
226 case unsafeFreezeByteArray# arr# s# of { (# s2#, frozen# #) ->
227 (# s2#, ByteArray 0 (I# len#) frozen# #) }