[project @ 2004-08-13 13:04:50 by simonmar]
[ghc-hetmet.git] / ghc / compiler / utils / FastString.lhs
index 7523f92..8dbfefa 100644 (file)
@@ -3,8 +3,18 @@
 %
 \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
@@ -47,7 +57,6 @@ module FastString
 #include "HsVersions.h"
 
 #if __GLASGOW_HASKELL__ < 503
-import PrelPack                hiding (packString)
 import PrelIOBase      ( IO(..) )
 #else
 import GHC.IOBase      ( IO(..) )
@@ -56,7 +65,7 @@ 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
@@ -107,6 +116,7 @@ instance Eq FastString where
   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  }
@@ -127,7 +137,7 @@ nullFastString (UnicodeStr _ []) = 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]
@@ -392,9 +402,9 @@ hashSubStrBA ba# start# len# =
    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#
@@ -419,20 +429,21 @@ cmpFS (UnicodeStr u1# s1) (UnicodeStr u2# s2) = if u1# ==# u2# then EQ
     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
@@ -497,7 +508,6 @@ hPutFS handle (UnicodeStr _ is)
 -- 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#