%
\section{Fast strings}
-Compact representations of character strings with
-unique identifiers (hash-cons'ish).
+FastString: A compact, hash-consed, representation of character strings.
+ Comparison is O(1), and you can get a Unique from them.
+ Generated by the FSLIT macro
+ Turn into SDoc with Outputable.ftext
+
+LitString: Just a wrapper for the Addr# of a C string (Ptr CChar).
+ Practically no operations
+ Outputing them is fast
+ Generated by the SLIT macro
+ Turn into SDoc with Outputable.ptext
+
+Use LitString unless you want the facilities of FastString
\begin{code}
module FastString
#include "HsVersions.h"
#if __GLASGOW_HASKELL__ < 503
-import PrelPack hiding (packString)
import PrelIOBase ( IO(..) )
#else
import GHC.IOBase ( IO(..) )
import PrimPacked
import GLAEXTS
import UNSAFE_IO ( unsafePerformIO )
-import ST ( stToIO )
+import MONAD_ST ( stToIO )
import DATA_IOREF ( IORef, newIORef, readIORef, writeIORef )
#if __GLASGOW_HASKELL__ < 503
a /= b = case cmpFS a b of { LT -> True; EQ -> False; GT -> True }
instance Ord FastString where
+ -- Compares lexicographically, not by unique
a <= b = case cmpFS a b of { LT -> True; EQ -> True; GT -> False }
a < b = case cmpFS a b of { LT -> True; EQ -> False; GT -> False }
a >= b = case cmpFS a b of { LT -> False; EQ -> True; GT -> True }
nullFastString (UnicodeStr _ (_:_)) = False
unpackFS :: FastString -> String
-unpackFS (FastString _ l# ba#) = unpackCStringBA (BA ba#) (I# l#)
+unpackFS (FastString _ l# ba#) = unpackNBytesBA (BA ba#) (I# l#)
unpackFS (UnicodeStr _ s) = map chr s
unpackIntFS :: FastString -> [Int]
2# -> ((ord# c0 *# 631#) +# (ord# c1 *# 217#) +# len#) `remInt#` hASH_TBL_SIZE#
_ -> ((ord# c0 *# 631#) +# (ord# c1 *# 217#) +# (ord# c2 *# 43#) +# len#) `remInt#` hASH_TBL_SIZE#
where
- c0 = indexCharArray# ba# 0#
- c1 = indexCharArray# ba# (len# `quotInt#` 2# -# 1#)
- c2 = indexCharArray# ba# (len# -# 1#)
+ c0 = indexCharArray# ba# (start# +# 0#)
+ c1 = indexCharArray# ba# (start# +# (len# `quotInt#` 2# -# 1#))
+ c2 = indexCharArray# ba# (start# +# (len# -# 1#))
-- c1 = indexCharArray# ba# 1#
-- c2 = indexCharArray# ba# 2#
else compare s1 s2
cmpFS (UnicodeStr _ s1) s2 = compare s1 (unpackIntFS s2)
cmpFS s1 (UnicodeStr _ s2) = compare (unpackIntFS s1) s2
-cmpFS (FastString u1# _ b1#) (FastString u2# _ b2#) = -- assume non-null chars
- if u1# ==# u2# then
- EQ
- else
- unsafePerformIO (
- strcmp b1# b2# >>= \ (I# res) ->
+cmpFS (FastString u1# l1# b1#) (FastString u2# l2# b2#) =
+ if u1# ==# u2# then EQ else
+ let l# = if l1# <=# l2# then l1# else l2# in
+ unsafePerformIO (
+ memcmp b1# b2# l# >>= \ (I# res) ->
return (
if res <# 0# then LT
- else if res ==# 0# then EQ
+ else if res ==# 0# then
+ if l1# ==# l2# then EQ
+ else if l1# <# l2# then LT else GT
else GT
))
-foreign import ccall "strcmp" unsafe
- strcmp :: ByteArray# -> ByteArray# -> IO Int
+foreign import ccall "ghc_memcmp" unsafe
+ memcmp :: ByteArray# -> ByteArray# -> Int# -> IO Int
-- -----------------------------------------------------------------------------
-- Outputting 'FastString's
-- LitStrings, here for convenience only.
type LitString = Ptr ()
--- ToDo: make it a Ptr when we don't have to support 4.08 any more
mkLitString# :: Addr# -> LitString
mkLitString# a# = Ptr a#