{-# LANGUAGE Unsafe #-}
{-# LANGUAGE NoImplicitPrelude, MagicHash, UnboxedTuples #-}
{-# OPTIONS_HADDOCK not-home #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  GHC.Pack
-- Copyright   :  (c) The University of Glasgow 1997-2002
-- License     :  see libraries/base/LICENSE
--
-- Maintainer  :  cvs-ghc@haskell.org
-- Stability   :  internal
-- Portability :  non-portable (GHC Extensions)
--
-- This module provides a small set of low-level functions for packing
-- and unpacking a chunk of bytes. Used by code emitted by the compiler
-- plus the prelude libraries.
--
-- The programmer level view of packed strings is provided by a GHC
-- system library PackedString.
--
-----------------------------------------------------------------------------

module GHC.Pack
       (
        -- (**) - emitted by compiler.

        packCString#,
        unpackCString,
        unpackCString#,
        unpackNBytes#,
        unpackFoldrCString#,  -- (**)
        unpackAppendCString#,  -- (**)
       )
        where

import GHC.Base
import GHC.List ( length )
import GHC.ST
import GHC.Ptr

data ByteArray ix              = ByteArray        ix ix ByteArray#
data MutableByteArray s ix     = MutableByteArray ix ix (MutableByteArray# s)

unpackCString :: Ptr a -> [Char]
unpackCString :: forall a. Ptr a -> [Char]
unpackCString a :: Ptr a
a@(Ptr Addr#
addr)
  | Ptr a
a forall a. Eq a => a -> a -> Bool
== forall a. Ptr a
nullPtr  = []
  | Bool
otherwise      = Addr# -> [Char]
unpackCString# Addr#
addr

packCString#         :: [Char]          -> ByteArray#
packCString# :: [Char] -> ByteArray#
packCString# [Char]
str = case ([Char] -> ByteArray Int
packString [Char]
str) of { ByteArray Int
_ Int
_ ByteArray#
bytes -> ByteArray#
bytes }

packString :: [Char] -> ByteArray Int
packString :: [Char] -> ByteArray Int
packString [Char]
str = forall a. (forall s. ST s a) -> a
runST (forall s. [Char] -> ST s (ByteArray Int)
packStringST [Char]
str)

packStringST :: [Char] -> ST s (ByteArray Int)
packStringST :: forall s. [Char] -> ST s (ByteArray Int)
packStringST [Char]
str =
  let len :: Int
len = forall a. [a] -> Int
length [Char]
str  in
  forall s. Int -> [Char] -> ST s (ByteArray Int)
packNBytesST Int
len [Char]
str

packNBytesST :: Int -> [Char] -> ST s (ByteArray Int)
packNBytesST :: forall s. Int -> [Char] -> ST s (ByteArray Int)
packNBytesST (I# Int#
length#) [Char]
str =
  {-
   allocate an array that will hold the string
   (not forgetting the NUL byte at the end)
  -}
 forall s. Int# -> ST s (MutableByteArray s Int)
new_ps_array (Int#
length# Int# -> Int# -> Int#
+# Int#
1#) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ MutableByteArray s Int
ch_array ->
   -- fill in packed string from "str"
 forall s. MutableByteArray s Int -> Int# -> [Char] -> ST s ()
fill_in MutableByteArray s Int
ch_array Int#
0# [Char]
str   forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
   -- freeze the puppy:
 forall s. MutableByteArray s Int -> Int# -> ST s (ByteArray Int)
freeze_ps_array MutableByteArray s Int
ch_array Int#
length#
 where
  fill_in :: MutableByteArray s Int -> Int# -> [Char] -> ST s ()
  fill_in :: forall s. MutableByteArray s Int -> Int# -> [Char] -> ST s ()
fill_in MutableByteArray s Int
arr_in# Int#
idx [] =
   forall s. MutableByteArray s Int -> Int# -> Char# -> ST s ()
write_ps_array MutableByteArray s Int
arr_in# Int#
idx (Int# -> Char#
chr# Int#
0#) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
   forall (m :: * -> *) a. Monad m => a -> m a
return ()

  fill_in MutableByteArray s Int
arr_in# Int#
idx (C# Char#
c : [Char]
cs) =
   forall s. MutableByteArray s Int -> Int# -> Char# -> ST s ()
write_ps_array MutableByteArray s Int
arr_in# Int#
idx Char#
c  forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
   forall s. MutableByteArray s Int -> Int# -> [Char] -> ST s ()
fill_in MutableByteArray s Int
arr_in# (Int#
idx Int# -> Int# -> Int#
+# Int#
1#) [Char]
cs

-- (Very :-) ``Specialised'' versions of some CharArray things...

new_ps_array    :: Int# -> ST s (MutableByteArray s Int)
write_ps_array  :: MutableByteArray s Int -> Int# -> Char# -> ST s ()
freeze_ps_array :: MutableByteArray s Int -> Int# -> ST s (ByteArray Int)

new_ps_array :: forall s. Int# -> ST s (MutableByteArray s Int)
new_ps_array Int#
size = forall s a. STRep s a -> ST s a
ST forall a b. (a -> b) -> a -> b
$ \ State# s
s ->
    case (forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
newByteArray# Int#
size State# s
s)   of { (# State# s
s2#, MutableByteArray# s
barr# #) ->
    (# State# s
s2#, forall s ix.
ix -> ix -> MutableByteArray# s -> MutableByteArray s ix
MutableByteArray forall {a}. a
bot forall {a}. a
bot MutableByteArray# s
barr# #) }
  where
    bot :: a
bot = forall a. [Char] -> a
errorWithoutStackTrace [Char]
"new_ps_array"

write_ps_array :: forall s. MutableByteArray s Int -> Int# -> Char# -> ST s ()
write_ps_array (MutableByteArray Int
_ Int
_ MutableByteArray# s
barr#) Int#
n Char#
ch = forall s a. STRep s a -> ST s a
ST forall a b. (a -> b) -> a -> b
$ \ State# s
s# ->
    case forall d.
MutableByteArray# d -> Int# -> Char# -> State# d -> State# d
writeCharArray# MutableByteArray# s
barr# Int#
n Char#
ch State# s
s#  of { State# s
s2#   ->
    (# State# s
s2#, () #) }

-- same as unsafeFreezeByteArray
freeze_ps_array :: forall s. MutableByteArray s Int -> Int# -> ST s (ByteArray Int)
freeze_ps_array (MutableByteArray Int
_ Int
_ MutableByteArray# s
arr#) Int#
len# = forall s a. STRep s a -> ST s a
ST forall a b. (a -> b) -> a -> b
$ \ State# s
s# ->
    case forall d.
MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
unsafeFreezeByteArray# MutableByteArray# s
arr# State# s
s# of { (# State# s
s2#, ByteArray#
frozen# #) ->
    (# State# s
s2#, forall ix. ix -> ix -> ByteArray# -> ByteArray ix
ByteArray Int
0 (Int# -> Int
I# Int#
len#) ByteArray#
frozen# #) }