{-# LANGUAGE MagicHash, NoImplicitPrelude, BangPatterns #-}
-----------------------------------------------------------------------------
-- |
-- Module : GHC.CString
-- Copyright : (c) The University of Glasgow 2011
-- License : see libraries/ghc-prim/LICENSE
--
-- Maintainer : cvs-ghc@haskell.org
-- Stability : internal
-- Portability : non-portable (GHC Extensions)
--
-- GHC C strings definitions (previously in GHC.Base).
-- Use GHC.Exts from the base package instead of importing this
-- module directly.
--
-----------------------------------------------------------------------------
module GHC.CString ( unpackCString#, unpackAppendCString#, unpackFoldrCString#, unpackCStringUtf8#, unpackNBytes# ) where import
GHC.Types
import GHC.Prim
-----------------------------------------------------------------------------
-- Unpacking C strings}
-----------------------------------------------------------------------------
-- This code is needed for virtually all programs, since it's used for
-- unpacking the strings of error messages.
-- Used to be in GHC.Base, but was moved to ghc-prim because the new generics
-- stuff uses Strings in the representation, so to give representations for
-- ghc-prim types we need unpackCString#
unpackCString#
::
Addr#
-> [
Char
]
{-# NOINLINE
unpackCString#
#-}
-- There's really no point in inlining this, ever, as the loop doesn't
-- specialise in an interesting But it's pretty small, so there's a danger
-- that it'll be inlined at every literal, which is a waste
unpackCString#
addr
=
unpack
0# where
unpack
nh
|
isTrue#
(
ch
`eqChar#`
'\0'#) = [] |
True
=
C#
ch
:
unpack
(
nh
+#
1#) where !
ch
=
indexCharOffAddr#
addr
nh
unpackAppendCString#
::
Addr#
-> [
Char
] -> [
Char
]
{-# NOINLINE
unpackAppendCString#
#-}
-- See the NOINLINE note on unpackCString#
unpackAppendCString#
addr
rest
=
unpack
0# where
unpack
nh
|
isTrue#
(
ch
`eqChar#`
'\0'#) =
rest
|
True
=
C#
ch
:
unpack
(
nh
+#
1#) where !
ch
=
indexCharOffAddr#
addr
nh
unpackFoldrCString#
::
Addr#
-> (
Char
->
a
->
a
) ->
a
->
a
-- Usually the unpack-list rule turns unpackFoldrCString# into unpackCString#
-- It also has a BuiltInRule in PrelRules.lhs:
-- unpackFoldrCString# "foo" c (unpackFoldrCString# "baz" c n)
-- = unpackFoldrCString# "foobaz" c n
{-# NOINLINE
unpackFoldrCString#
#-}
-- At one stage I had NOINLINE [0] on the grounds that, unlike
-- unpackCString#, there *is* some point in inlining
-- unpackFoldrCString#, because we get better code for the
-- higher-order function call. BUT there may be a lot of
-- literal strings, and making a separate 'unpack' loop for
-- each is highly gratuitous. See nofib/real/anna/PrettyPrint.
unpackFoldrCString#
addr
f
z
=
unpack
0# where
unpack
nh
|
isTrue#
(
ch
`eqChar#`
'\0'#) =
z
|
True
=
C#
ch
`f`
unpack
(
nh
+#
1#) where !
ch
=
indexCharOffAddr#
addr
nh
unpackCStringUtf8#
::
Addr#
-> [
Char
]
unpackCStringUtf8#
addr
=
unpack
0# where
unpack
nh
|
isTrue#
(
ch
`eqChar#`
'\0'# ) = [] |
isTrue#
(
ch
`leChar#`
'\x7F'#) =
C#
ch
:
unpack
(
nh
+#
1#) |
isTrue#
(
ch
`leChar#`
'\xDF'#) =
C#
(
chr#
(((
ord#
ch
-#
0xC0#)
`uncheckedIShiftL#`
6#)
+#
(
ord#
(
indexCharOffAddr#
addr
(
nh
+#
1#))
-#
0x80#)))
:
unpack
(
nh
+#
2#) |
isTrue#
(
ch
`leChar#`
'\xEF'#) =
C#
(
chr#
(((
ord#
ch
-#
0xE0#)
`uncheckedIShiftL#`
12#)
+#
((
ord#
(
indexCharOffAddr#
addr
(
nh
+#
1#))
-#
0x80#)
`uncheckedIShiftL#`
6#)
+#
(
ord#
(
indexCharOffAddr#
addr
(
nh
+#
2#))
-#
0x80#)))
:
unpack
(
nh
+#
3#) |
True
=
C#
(
chr#
(((
ord#
ch
-#
0xF0#)
`uncheckedIShiftL#`
18#)
+#
((
ord#
(
indexCharOffAddr#
addr
(
nh
+#
1#))
-#
0x80#)
`uncheckedIShiftL#`
12#)
+#
((
ord#
(
indexCharOffAddr#
addr
(
nh
+#
2#))
-#
0x80#)
`uncheckedIShiftL#`
6#)
+#
(
ord#
(
indexCharOffAddr#
addr
(
nh
+#
3#))
-#
0x80#)))
:
unpack
(
nh
+#
4#) where !
ch
=
indexCharOffAddr#
addr
nh
unpackNBytes#
::
Addr#
->
Int#
-> [
Char
]
unpackNBytes#
_addr
0# = []
unpackNBytes#
addr
len#
=
unpack
[] (
len#
-#
1#) where
unpack
acc
i#
|
isTrue#
(
i#
<#
0#) =
acc
|
True
= case
indexCharOffAddr#
addr
i#
of
ch
->
unpack
(
C#
ch
:
acc
) (
i#
-#
1#)