[project @ 2002-05-09 13:05:46 by simonmar]
[packages/random.git] / GHC / Pack.lhs
1 \begin{code}
2 {-# OPTIONS -fno-implicit-prelude #-}
3 -----------------------------------------------------------------------------
4 -- |
5 -- Module      :  GHC.Pack
6 -- Copyright   :  (c) The University of Glasgow 1997-2002
7 -- License     :  see libraries/base/LICENSE
8 -- 
9 -- Maintainer  :  cvs-ghc@haskell.org
10 -- Stability   :  internal
11 -- Portability :  non-portable (GHC Extensions)
12 --
13 -- This module provides a small set of low-level functions for packing
14 -- and unpacking a chunk of bytes. Used by code emitted by the compiler
15 -- plus the prelude libraries.
16 -- 
17 -- The programmer level view of packed strings is provided by a GHC
18 -- system library PackedString.
19 --
20 -----------------------------------------------------------------------------
21
22 module GHC.Pack
23        (
24         -- (**) - emitted by compiler.
25
26         packCString#,      -- :: [Char] -> ByteArray#    (**)
27         unpackCString,
28         unpackCString#,    -- :: Addr# -> [Char]         (**)
29         unpackNBytes#,     -- :: Addr# -> Int# -> [Char] (**)
30         unpackFoldrCString#,  -- (**)
31         unpackAppendCString#,  -- (**)
32        ) 
33         where
34
35 import GHC.Base
36 import {-# SOURCE #-} GHC.Err ( error )
37 import GHC.List ( length )
38 import GHC.ST
39 import GHC.Num
40 import GHC.Ptr
41
42 data ByteArray ix              = ByteArray        ix ix ByteArray#
43 data MutableByteArray s ix     = MutableByteArray ix ix (MutableByteArray# s)
44
45 unpackCString :: Ptr a -> [Char]
46 unpackCString a@(Ptr addr)
47   | a == nullPtr  = []
48   | otherwise      = unpackCString# addr
49
50 packCString#         :: [Char]          -> ByteArray#
51 packCString# str = case (packString str) of { ByteArray _ _ bytes -> bytes }
52
53 packString :: [Char] -> ByteArray Int
54 packString str = runST (packStringST str)
55
56 packStringST :: [Char] -> ST s (ByteArray Int)
57 packStringST str =
58   let len = length str  in
59   packNBytesST len str
60
61 packNBytesST :: Int -> [Char] -> ST s (ByteArray Int)
62 packNBytesST (I# length#) str =
63   {- 
64    allocate an array that will hold the string
65    (not forgetting the NUL byte at the end)
66   -}
67  new_ps_array (length# +# 1#) >>= \ ch_array ->
68    -- fill in packed string from "str"
69  fill_in ch_array 0# str   >>
70    -- freeze the puppy:
71  freeze_ps_array ch_array length#
72  where
73   fill_in :: MutableByteArray s Int -> Int# -> [Char] -> ST s ()
74   fill_in arr_in# idx [] =
75    write_ps_array arr_in# idx (chr# 0#) >>
76    return ()
77
78   fill_in arr_in# idx (C# c : cs) =
79    write_ps_array arr_in# idx c  >>
80    fill_in arr_in# (idx +# 1#) cs
81
82 -- (Very :-) ``Specialised'' versions of some CharArray things...
83
84 new_ps_array    :: Int# -> ST s (MutableByteArray s Int)
85 write_ps_array  :: MutableByteArray s Int -> Int# -> Char# -> ST s () 
86 freeze_ps_array :: MutableByteArray s Int -> Int# -> ST s (ByteArray Int)
87
88 new_ps_array size = ST $ \ s ->
89     case (newByteArray# size s)   of { (# s2#, barr# #) ->
90     (# s2#, MutableByteArray bot bot barr# #) }
91   where
92     bot = error "new_ps_array"
93
94 write_ps_array (MutableByteArray _ _ barr#) n ch = ST $ \ s# ->
95     case writeCharArray# barr# n ch s#  of { s2#   ->
96     (# s2#, () #) }
97
98 -- same as unsafeFreezeByteArray
99 freeze_ps_array (MutableByteArray _ _ arr#) len# = ST $ \ s# ->
100     case unsafeFreezeByteArray# arr# s# of { (# s2#, frozen# #) ->
101     (# s2#, ByteArray 0 (I# len#) frozen# #) }
102 \end{code}