@@ -1,22 +1,45 @@
1{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
1{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
2−{-# LANGUAGE BangPatterns, MagicHash, UnboxedTuples #-}
2+{-# LANGUAGE BangPatterns, EmptyDataDecls, FlexibleInstances, MagicHash, UnboxedTuples #-}
3module Data.Utf8
3module Data.Utf8
4− ( Utf8(..)
5+ , Utf8(..)
5− , toString
6+ , VeryLong
6 , toBuilder
24 , toBuilder
7 , fromChunks
26 , fromChunks
8 , Chunk(..)
27 , Chunk(..)
32+import Prelude hiding (String, all, any, concat)
13−import Data.Binary (Binary(..), Get)
33+import Data.Binary (Binary(..), Get, getWord8, putWord8)
14import Data.Binary.Put (putBuilder)
34import Data.Binary.Put (putBuilder)
15import Data.Binary.Get.Internal (readN)
35import Data.Binary.Get.Internal (readN)
16import Data.Bits ((.&.), shiftR)
36import Data.Bits ((.&.), shiftR)
17import qualified Data.ByteString.Internal as B
37import qualified Data.ByteString.Internal as B
18import qualified Data.ByteString.Builder.Internal as B
38import qualified Data.ByteString.Builder.Internal as B
39+import qualified Data.Char as Char
40+import qualified Data.List as List
41+import Data.String (IsString(..))
19−import Foreign.ForeignPtr (ForeignPtr, touchForeignPtr)
42+import Foreign.ForeignPtr (touchForeignPtr)
20import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
43import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
21import Foreign.Ptr (minusPtr, plusPtr)
44import Foreign.Ptr (minusPtr, plusPtr)
22import GHC.Exts
45import GHC.Exts
@@ -24,30 +47,261 @@ import GHC.Exts
24 , RealWorld
47 , RealWorld
25 , ByteArray#, MutableByteArray#
48 , ByteArray#, MutableByteArray#
27− , newByteArray#, unsafeFreezeByteArray#
51+ , unsafeFreezeByteArray#
28 , sizeofByteArray#
52 , sizeofByteArray#
29− , copyAddrToByteArray#, copyByteArrayToAddr#
54+ , copyAddrToByteArray#
55+ , copyByteArrayToAddr#
30 , writeWord8Array#,
56 , writeWord8Array#,
32import GHC.IO
58import GHC.IO
33import GHC.ST (ST(ST), runST)
59import GHC.ST (ST(ST), runST)
34import GHC.Prim
60import GHC.Prim
35−import GHC.Word (Word8(W8#))
61+import GHC.Word (Word8(W8#), Word16(W16#))
42−data Utf8 =
68+data Utf8 size tipe =
43 Utf8 ByteArray#
69 Utf8 ByteArray#
72+type String = Utf8 VERY_LONG STRING
73+type VeryLong t = Utf8 VERY_LONG t
74+type Under256 t = Utf8 UNDER_256 t
85+isEmpty :: Utf8 l t -> Bool
87+ isTrue# (sizeofByteArray# ba# ==# 0#)
94+size :: Utf8 l t -> Int
96+ I# (sizeofByteArray# ba#)
103+contains :: Word8 -> Utf8 l t -> Bool
104+contains (W8# word#) (Utf8 ba#) =
105+ containsHelp word# ba# 0# (sizeofByteArray# ba#)
108+containsHelp :: Word# -> ByteArray# -> Int# -> Int# -> Bool
109+containsHelp word# ba# !offset# len# =
110+ if isTrue# (offset# <# len#) then
111+ if isTrue# (eqWord# word# (indexWord8Array# ba# offset#))
113+ else containsHelp word# ba# (offset# +# 1#) len#
122+containsDouble :: Word8 -> Utf8 l t -> Bool
123+containsDouble (W8# word#) (Utf8 ba#) =
124+ containsDoubleHelp word# ba# 0# (sizeofByteArray# ba#)
127+containsDoubleHelp :: Word# -> ByteArray# -> Int# -> Int# -> Bool
128+containsDoubleHelp word# ba# !offset# len# =
129+ let !offset1# = offset# +# 1# in
130+ if isTrue# (offset1# <# len#) then
131+ if isTrue# (eqWord# word# (indexWord8Array# ba# offset# ))
132+ && isTrue# (eqWord# word# (indexWord8Array# ba# offset1#))
134+ else containsDoubleHelp word# ba# (offset# +# 1#) len#
143+{-# INLINE startsWith #-}
144+startsWith :: Utf8 l t -> Utf8 l t -> Bool
145+startsWith (Utf8 ba1#) (Utf8 ba2#) =
147+ !len1# = sizeofByteArray# ba1#
148+ !len2# = sizeofByteArray# ba2#
150+ isTrue# (len1# <=# len2#)
152+ isTrue# (0# ==# compareByteArrays# ba1# 0# ba2# 0# len1#)
159+startsWithChar :: (Char -> Bool) -> Utf8 l t -> Bool
160+startsWithChar isGood str@(Utf8 ba#) =
165+ !w# = indexWord8Array# ba# 0#
167+ | isTrue# (ltWord# w# 0xC0##) = C# (chr# (word2Int# w#))
168+ | isTrue# (ltWord# w# 0xE0##) = chr2 ba# 0# w#
169+ | isTrue# (ltWord# w# 0xF0##) = chr3 ba# 0# w#
170+ | True = chr4 ba# 0# w#
179+endsWithWord :: Word8 -> Utf8 l t -> Bool
180+endsWithWord (W8# w#) (Utf8 ba#) =
181+ let len# = sizeofByteArray# ba# in
182+ isTrue# (len# ># 0#)
184+ isTrue# (eqWord# w# (indexWord8Array# ba# (len# -# 1#)))
191+split :: Word8 -> String -> [String]
192+split (W8# divider#) str@(Utf8 ba#) =
193+ splitHelp str 0 (findDividers divider# ba# 0# (sizeofByteArray# ba#) [])
196+splitHelp :: String -> Int -> [Int] -> [String]
197+splitHelp str start offsets =
200+ [ unsafeSlice str start (size str) ]
203+ unsafeSlice str start offset : splitHelp str (offset + 1) offsets
206+findDividers :: Word# -> ByteArray# -> Int# -> Int# -> [Int] -> [Int]
207+findDividers divider# ba# !offset# len# revOffsets =
208+ if isTrue# (offset# <# len#) then
209+ findDividers divider# ba# (offset# +# 1#) len# $
210+ if isTrue# (eqWord# divider# (indexWord8Array# ba# offset#))
211+ then I# offset# : revOffsets
217+unsafeSlice :: String -> Int -> Int -> String
218+unsafeSlice str start end =
219+ let !len = end - start in
224+ do mba <- newByteArray len
225+ copy str start mba 0 len
233+join :: Word8 -> [String] -> String
241+ do let !len = List.foldl' (\w s -> w + 1 + size s) (size str) strs
242+ mba <- newByteArray len
243+ joinHelp sep mba 0 str strs
247+joinHelp :: Word8 -> MBA s -> Int -> String -> [String] -> ST s ()
248+joinHelp sep mba offset str strings =
254+ copy str 0 mba offset len
257+ do copy str 0 mba offset len
258+ let !dotOffset = offset + len
259+ writeWord8 mba dotOffset sep
260+ let !newOffset = dotOffset + 1
261+ joinHelp sep mba newOffset s ss
268+all :: (Char -> Bool) -> Utf8 l t -> Bool
270+ not (any (not . isGood) utf8)
277+any :: (Char -> Bool) -> Utf8 l t -> Bool
278+any isGood (Utf8 ba#) =
279+ anyHelp isGood ba# 0# (sizeofByteArray# ba#)
282+anyHelp :: (Char -> Bool) -> ByteArray# -> Int# -> Int# -> Bool
283+anyHelp isGood ba# offset# len# =
284+ if isTrue# (offset# >=# len#) then
288+ !w# = indexWord8Array# ba# offset#
290+ | isTrue# (ltWord# w# 0xC0##) = (# C# (chr# (word2Int# w#)), 1# #)
291+ | isTrue# (ltWord# w# 0xE0##) = (# chr2 ba# offset# w#, 2# #)
292+ | isTrue# (ltWord# w# 0xF0##) = (# chr3 ba# offset# w#, 3# #)
293+ | True = (# chr4 ba# offset# w#, 4# #)
297+ else anyHelp isGood ba# (offset# +# width#) len#
50−instance Eq Utf8 where
304+instance Eq (Utf8 l t) where
51 (==) (Utf8 ba1#) (Utf8 ba2#) =
305 (==) (Utf8 ba1#) (Utf8 ba2#) =
53 !len1# = sizeofByteArray# ba1#
307 !len1# = sizeofByteArray# ba1#
@@ -62,7 +316,7 @@ instance Eq Utf8 where
62-- COMPARE
316-- COMPARE
65−instance Ord Utf8 where
319+instance Ord (Utf8 l t) where
66 compare (Utf8 ba1#) (Utf8 ba2#) =
320 compare (Utf8 ba1#) (Utf8 ba2#) =
68 !len1# = sizeofByteArray# ba1#
322 !len1# = sizeofByteArray# ba1#
@@ -79,63 +333,257 @@ instance Ord Utf8 where
82−-- BINARY
336+-- TO WORD16
85−instance Binary Utf8 where
339+toWord16 :: String -> Maybe Word16
86− put utf8@(Utf8 ba#) =
340+toWord16 (Utf8 ba#) =
87− put (I# (sizeofByteArray# ba#)) <> putBuilder (toBuilder utf8)
341+ let !len# = sizeofByteArray# ba# in
88− get =
342+ if isTrue# (len# ==# 0#) then
89− get >>= getUtf8
343+ Nothing
345+ let !w# = indexWord8Array# ba# 0# in
346+ if isTrue# (eqWord# w# 0x30##) then
347+ if isTrue# (len# ==# 1#) then Just 0 else Nothing
349+ toWordHelp ba# 0# len# 0##
352+toWordHelp :: ByteArray# -> Int# -> Int# -> Word# -> Maybe Word16
353+toWordHelp ba# offset# len# number# =
354+ if isTrue# (offset# <# len#) then
355+ let !w# = indexWord8Array# ba# offset# in
356+ if isTrue# (leWord# w# 0x39##) && isTrue# (geWord# w# 0x30##) then
357+ let !newNumber# = plusWord# (timesWord# 10## number#) (minusWord# w# 0x30##) in
358+ toWordHelp ba# (offset# +# 1#) len# newNumber#
369+fromWord16 :: Word16 -> String
372+ do let !size = getWordSize n
373+ mba <- newByteArray size
374+ writeDigits mba (size - 1) n
378+getWordSize :: Word16 -> Int
382+ | True = ceiling (logBase 10 (fromIntegral n + 1) :: Float)
385+writeDigits :: MBA s -> Int -> Word16 -> ST s ()
386+writeDigits !mba !offset !n =
387+ do let (q,r) = quotRem n 10
388+ writeWord8 mba offset (0x30 + fromIntegral r)
391+ else writeDigits mba (offset-1) q
398+fromChars :: [Char] -> Utf8 l t
403+instance IsString (Utf8 l t) where
407+ do mba <- newByteArray (sum (map getWidth str))
408+ writeString mba 0 str
412+writeString :: MBA s -> Int -> [Char] -> ST s (Utf8 l t)
413+writeString !mba !offset chars =
420+ do writeWord8 mba (offset ) (fromIntegral n)
421+ writeString mba (offset + 1) chars
424+ do writeWord8 mba (offset ) (fromIntegral ((shiftR n 6 ) + 0xC0))
425+ writeWord8 mba (offset + 1) (fromIntegral (( n .&. 0x3F) + 0x80))
426+ writeString mba (offset + 2) chars
429+ do writeWord8 mba (offset ) (fromIntegral ((shiftR n 12 ) + 0xE0))
430+ writeWord8 mba (offset + 1) (fromIntegral ((shiftR n 6 .&. 0x3F) + 0x80))
431+ writeWord8 mba (offset + 2) (fromIntegral (( n .&. 0x3F) + 0x80))
432+ writeString mba (offset + 3) chars
435+ do writeWord8 mba (offset ) (fromIntegral ((shiftR n 18 ) + 0xF0))
436+ writeWord8 mba (offset + 1) (fromIntegral ((shiftR n 12 .&. 0x3F) + 0x80))
437+ writeWord8 mba (offset + 2) (fromIntegral ((shiftR n 6 .&. 0x3F) + 0x80))
438+ writeWord8 mba (offset + 3) (fromIntegral (( n .&. 0x3F) + 0x80))
439+ writeString mba (offset + 4) chars
92−{-# INLINE getUtf8 #-}
445+{-# INLINE getWidth #-}
93−getUtf8 :: Int -> Get Utf8
446+getWidth :: Char -> Int
94−getUtf8 n =
447+getWidth char
450+ | code < 0x10000 = 3
453+ code = Char.ord char
460+toChars :: Utf8 l t -> [Char]
462+ toCharsHelp ba# 0# (sizeofByteArray# ba#)
465+toCharsHelp :: ByteArray# -> Int# -> Int# -> [Char]
466+toCharsHelp ba# offset# len# =
95− if n > 0 then
467+ if isTrue# (offset# >=# len#) then
96− readN n (copyFromByteString n)
468+ []
471+ !w# = indexWord8Array# ba# offset#
473+ | isTrue# (ltWord# w# 0xC0##) = (# C# (chr# (word2Int# w#)), 1# #)
474+ | isTrue# (ltWord# w# 0xE0##) = (# chr2 ba# offset# w#, 2# #)
475+ | isTrue# (ltWord# w# 0xF0##) = (# chr3 ba# offset# w#, 3# #)
476+ | True = (# chr4 ba# offset# w#, 4# #)
478+ !newOffset# = offset# +# width#
480+ char : toCharsHelp ba# newOffset# len#
102−copyFromByteString :: Int -> B.ByteString -> Utf8
103−copyFromByteString len (B.PS fptr offset _) =
104− unsafeDupablePerformIO
106− do mba <- stToIO (newByteArray len)
107− stToIO (copyFromPtr (unsafeForeignPtrToPtr fptr `plusPtr` offset) mba 0 len)
108− touchForeignPtr fptr
109− stToIO (unsafeFreeze mba)
484+chr2 :: ByteArray# -> Int# -> Word# -> Char
485+chr2 ba# offset# firstWord# =
487+ !i1# = word2Int# firstWord#
488+ !i2# = word2Int# (indexWord8Array# ba# (offset# +# 1#))
489+ !c1# = uncheckedIShiftL# (i1# -# 0xC0#) 6#
492+ C# (chr# (c1# +# c2#))
113−{-# NOINLINE empty #-}
494+
114−empty :: Utf8
495+{-# INLINE chr3 #-}
115−empty =
496+chr3 :: ByteArray# -> Int# -> Word# -> Char
116− runST (unsafeFreeze =<< newByteArray 0)
497+chr3 ba# offset# firstWord# =
499+ !i1# = word2Int# firstWord#
500+ !i2# = word2Int# (indexWord8Array# ba# (offset# +# 1#))
501+ !i3# = word2Int# (indexWord8Array# ba# (offset# +# 2#))
502+ !c1# = uncheckedIShiftL# (i1# -# 0xE0#) 12#
503+ !c2# = uncheckedIShiftL# (i2# -# 0x80#) 6#
506+ C# (chr# (c1# +# c2# +# c3#))
510+chr4 :: ByteArray# -> Int# -> Word# -> Char
511+chr4 ba# offset# firstWord# =
513+ !i1# = word2Int# firstWord#
514+ !i2# = word2Int# (indexWord8Array# ba# (offset# +# 1#))
515+ !i3# = word2Int# (indexWord8Array# ba# (offset# +# 2#))
516+ !i4# = word2Int# (indexWord8Array# ba# (offset# +# 3#))
517+ !c1# = uncheckedIShiftL# (i1# -# 0xF0#) 18#
518+ !c2# = uncheckedIShiftL# (i2# -# 0x80#) 12#
519+ !c3# = uncheckedIShiftL# (i3# -# 0x80#) 6#
522+ C# (chr# (c1# +# c2# +# c3# +# c4#))
529+{-# INLINE toBuilder #-}
530+toBuilder :: Utf8 l t -> B.Builder
532+ \bytes -> B.builder (toBuilderHelp bytes)
535+{-# INLINE toBuilderHelp #-}
536+toBuilderHelp :: Utf8 l t -> B.BuildStep a -> B.BuildStep a
537+toBuilderHelp !bytes@(Utf8 ba#) k =
538+ go 0 (I# (sizeofByteArray# ba#))
540+ go !offset !end !(B.BufferRange bOffset bEnd) =
542+ !bLen = minusPtr bEnd bOffset
546+ do copyToPtr bytes offset bOffset len
547+ let !br' = B.BufferRange (plusPtr bOffset len) bEnd
550+ do copyToPtr bytes offset bOffset bLen
551+ let !offset' = offset + bLen
552+ return $ B.bufferFull 1 bEnd (go offset' end)
559+fromPtr :: Ptr Word8 -> Ptr Word8 -> Utf8 l t
561+ unsafeDupablePerformIO (stToIO (
562+ do let !len = minusPtr end pos
563+ mba <- newByteArray len
564+ copyFromPtr pos mba 0 len
120−-- CHUNKS
570+-- FROM CHUNKS
123data Chunk
573data Chunk
124− = Slice Int Int -- TODO try UNPACK
574+ = Slice (Ptr Word8) Int
125 | Escape Word8
575 | Escape Word8
126 | CodePoint Int
576 | CodePoint Int
129−fromChunks :: ForeignPtr Word8 -> [Chunk] -> Utf8
579+fromChunks :: [Chunk] -> Utf8 l t
130−fromChunks fptr chunks =
580+fromChunks chunks =
131− unsafeDupablePerformIO
581+ unsafeDupablePerformIO (stToIO (
133 do let !len = sum (map chunkToWidth chunks)
582 do let !len = sum (map chunkToWidth chunks)
134− mba <- stToIO (newByteArray len)
583+ mba <- newByteArray len
135− stToIO (writeChunks (unsafeForeignPtrToPtr fptr) mba 0 chunks)
584+ writeChunks mba 0 chunks
136− touchForeignPtr fptr
585+ freeze mba
137− stToIO (unsafeFreeze mba)
141chunkToWidth :: Chunk -> Int
589chunkToWidth :: Chunk -> Int
@@ -151,36 +599,36 @@ chunkToWidth chunk =
151 if code < 0xFFFF then 6 else 12
599 if code < 0xFFFF then 6 else 12
154−writeChunks :: Ptr Word8 -> MBA RealWorld -> Int -> [Chunk] -> ST RealWorld ()
602+writeChunks :: MBA RealWorld -> Int -> [Chunk] -> ST RealWorld ()
155−writeChunks ptr mba offset chunks =
603+writeChunks mba offset chunks =
156 case chunks of
604 case chunks of
158 return ()
606 return ()
160 chunk : chunks ->
608 chunk : chunks ->
161 case chunk of
609 case chunk of
162− Slice off len ->
610+ Slice ptr len ->
163− do copyFromPtr (plusPtr ptr off) mba offset len
611+ do copyFromPtr ptr mba offset len
164 let !newOffset = offset + len
612 let !newOffset = offset + len
165− writeChunks ptr mba newOffset chunks
613+ writeChunks mba newOffset chunks
167 Escape word ->
615 Escape word ->
168 do writeWord8 mba offset 0x5C {- \ -}
616 do writeWord8 mba offset 0x5C {- \ -}
169 writeWord8 mba (offset + 1) word
617 writeWord8 mba (offset + 1) word
170 let !newOffset = offset + 2
618 let !newOffset = offset + 2
171− writeChunks ptr mba newOffset chunks
619+ writeChunks mba newOffset chunks
173 CodePoint code ->
621 CodePoint code ->
174 if code < 0xFFFF then
622 if code < 0xFFFF then
175 do writeCode mba offset code
623 do writeCode mba offset code
176 let !newOffset = offset + 6
624 let !newOffset = offset + 6
177− writeChunks ptr mba newOffset chunks
625+ writeChunks mba newOffset chunks
179 do let (hi,lo) = divMod (code - 0x10000) 0x400
627 do let (hi,lo) = divMod (code - 0x10000) 0x400
180 writeCode mba (offset ) (hi + 0xD800)
628 writeCode mba (offset ) (hi + 0xD800)
181 writeCode mba (offset + 6) (lo + 0xDC00)
629 writeCode mba (offset + 6) (lo + 0xDC00)
182 let !newOffset = offset + 12
630 let !newOffset = offset + 12
183− writeChunks ptr mba newOffset chunks
631+ writeChunks mba newOffset chunks
186-- TODO see if it is faster to writeWord32 a block of hex-as-ascii
634-- TODO see if it is faster to writeWord32 a block of hex-as-ascii
@@ -201,105 +649,64 @@ writeHex mba !offset !bits =
204−-- TO BUILDER
652+-- UNDER 256 BINARY
207−{-# INLINE toBuilder #-}
655+instance Binary (Utf8 UNDER_256 t) where
208−toBuilder :: Utf8 -> B.Builder
656+ put bytes@(Utf8 ba#) =
657+ do putWord8 (W8# (int2Word# (sizeofByteArray# ba#)))
209−toBuilder =
658+ putBuilder (toBuilder bytes)
210− \utf8 -> B.builder (toBuilderHelp utf8)
659+ get =
660+ getUnder256 =<< getWord8
213−{-# INLINE toBuilderHelp #-}
663+{-# INLINE getUnder256 #-}
214−toBuilderHelp :: Utf8 -> B.BuildStep a -> B.BuildStep a
664+getUnder256 :: Word8 -> Get (Utf8 UNDER_256 t)
215−toBuilderHelp !utf8@(Utf8 ba#) k =
665+getUnder256 w =
216− go 0 (I# (sizeofByteArray# ba#))
666+ let !n = fromIntegral w in
217− where
667+ readN n (copyFromByteString n)
218− go !offset !end !(B.BufferRange bOffset bEnd) =
220− !bLen = minusPtr bEnd bOffset
224− do stToIO (copyToPtr utf8 offset bOffset len)
225− let !br' = B.BufferRange (plusPtr bOffset len) bEnd
228− do stToIO (copyToPtr utf8 offset bOffset bLen)
229− let !offset' = offset + bLen
230− return $ B.bufferFull 1 bEnd (go offset' end)
234−-- TO STRING
671+-- VERY LONG BINARY
237−toString :: Utf8 -> String
674+instance Binary (Utf8 VERY_LONG t) where
238−toString (Utf8 ba#) =
675+ put str =
239− let
676+ do put (size str)
240− !len# = sizeofByteArray# ba#
677+ putBuilder (toBuilder str)
242− toStringHelp ba# 0# len#
679+ getVeryLong =<< get
245−toStringHelp :: ByteArray# -> Int# -> Int# -> String
682+{-# INLINE getVeryLong #-}
246−toStringHelp ba# offset# len# =
683+getVeryLong :: Int -> Get (Utf8 VERY_LONG t)
247− if isTrue# (offset# >=# len#) then
684+getVeryLong n =
686+ then readN n (copyFromByteString n)
249− else
687+ else return empty
251− !w# = indexWord8Array# ba# offset#
253− | isTrue# (ltWord# w# 0xC0##) = (# C# (chr# (word2Int# w#)), 1# #)
254− | isTrue# (ltWord# w# 0xE0##) = (# chr2 ba# offset# w#, 2# #)
255− | isTrue# (ltWord# w# 0xF0##) = (# chr3 ba# offset# w#, 3# #)
256− | True = (# chr4 ba# offset# w#, 4# #)
258− !newOffset# = offset# +# width#
260− char : toStringHelp ba# newOffset# len#
690+{-# NOINLINE empty #-}
693+ runST (freeze =<< newByteArray 0)
264−chr2 :: ByteArray# -> Int# -> Word# -> Char
265−chr2 ba# offset# firstWord# =
267− !i1# = word2Int# firstWord#
268− !i2# = word2Int# (indexWord8Array# ba# (offset# +# 1#))
269− !c1# = uncheckedIShiftL# (i1# -# 0xC0#) 6#
272− C# (chr# (c1# +# c2#))
275−{-# INLINE chr3 #-}
697+-- COPY FROM BYTESTRING
276−chr3 :: ByteArray# -> Int# -> Word# -> Char
277−chr3 ba# offset# firstWord# =
279− !i1# = word2Int# firstWord#
280− !i2# = word2Int# (indexWord8Array# ba# (offset# +# 1#))
281− !i3# = word2Int# (indexWord8Array# ba# (offset# +# 2#))
282− !c1# = uncheckedIShiftL# (i1# -# 0xE0#) 12#
283− !c2# = uncheckedIShiftL# (i2# -# 0x80#) 6#
286− C# (chr# (c1# +# c2# +# c3#))
289−{-# INLINE chr4 #-}
700+{-# INLINE copyFromByteString #-}
290−chr4 :: ByteArray# -> Int# -> Word# -> Char
701+copyFromByteString :: Int -> B.ByteString -> Utf8 l t
291−chr4 ba# offset# firstWord# =
702+copyFromByteString len (B.PS fptr offset _) =
292− let
703+ unsafeDupablePerformIO
293− !i1# = word2Int# firstWord#
704+ (
294− !i2# = word2Int# (indexWord8Array# ba# (offset# +# 1#))
705+ do mba <- stToIO (newByteArray len)
295− !i3# = word2Int# (indexWord8Array# ba# (offset# +# 2#))
706+ stToIO (copyFromPtr (unsafeForeignPtrToPtr fptr `plusPtr` offset) mba 0 len)
296− !i4# = word2Int# (indexWord8Array# ba# (offset# +# 3#))
707+ touchForeignPtr fptr
297− !c1# = uncheckedIShiftL# (i1# -# 0xF0#) 18#
708+ stToIO (freeze mba)
298− !c2# = uncheckedIShiftL# (i2# -# 0x80#) 12#
709+ )
299− !c3# = uncheckedIShiftL# (i3# -# 0x80#) 6#
302− C# (chr# (c1# +# c2# +# c3# +# c4#))
@@ -310,36 +717,44 @@ data MBA s =
310 MBA# (MutableByteArray# s)
717 MBA# (MutableByteArray# s)
313−newByteArray :: Int -> ST s (MBA s)
720+newByteArray :: Int -> ST s (MBA s) -- TODO see if newPinnedByteArray for len > 256 is positive
314newByteArray (I# len#) =
721newByteArray (I# len#) =
315 ST $ \s ->
722 ST $ \s ->
316 case newByteArray# len# s of
723 case newByteArray# len# s of
317 (# s, mba# #) -> (# s, MBA# mba# #)
724 (# s, mba# #) -> (# s, MBA# mba# #)
320−unsafeFreeze :: MBA s -> ST s Utf8
727+freeze :: MBA s -> ST s (Utf8 l t)
321−unsafeFreeze (MBA# mba#) =
728+freeze (MBA# mba#) =
322 ST $ \s ->
729 ST $ \s ->
323 case unsafeFreezeByteArray# mba# s of
730 case unsafeFreezeByteArray# mba# s of
324 (# s, ba# #) -> (# s, Utf8 ba# #)
731 (# s, ba# #) -> (# s, Utf8 ba# #)
734+copy :: Utf8 l t -> Int -> MBA s -> Int -> Int -> ST s ()
735+copy (Utf8 ba#) (I# offset#) (MBA# mba#) (I# i#) (I# len#) =
737+ case copyByteArray# ba# offset# mba# i# len# s of
327copyFromPtr :: Ptr a -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
741copyFromPtr :: Ptr a -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
328−copyFromPtr (Ptr src#) (MBA# mba#) (I# dst_off#) (I# len#) =
742+copyFromPtr (Ptr src#) (MBA# mba#) (I# offset#) (I# len#) =
329 ST $ \s ->
743 ST $ \s ->
330− case copyAddrToByteArray# src# mba# dst_off# len# s of
744+ case copyAddrToByteArray# src# mba# offset# len# s of
331 s -> (# s, () #)
745 s -> (# s, () #)
334−copyToPtr :: Utf8 -> Int -> Ptr a -> Int -> ST RealWorld ()
748+copyToPtr :: Utf8 l t -> Int -> Ptr a -> Int -> IO ()
335copyToPtr (Utf8 ba#) (I# offset#) (Ptr mba#) (I# len#) =
749copyToPtr (Utf8 ba#) (I# offset#) (Ptr mba#) (I# len#) =
336− ST $ \s ->
750+ IO $ \s ->
337 case copyByteArrayToAddr# ba# offset# mba# len# s of
751 case copyByteArrayToAddr# ba# offset# mba# len# s of
338 s -> (# s, () #)
752 s -> (# s, () #)
755+{-# INLINE writeWord8 #-}
341writeWord8 :: MBA s -> Int -> Word8 -> ST s ()
756writeWord8 :: MBA s -> Int -> Word8 -> ST s ()
342−writeWord8 (MBA# mba#) (I# i#) (W8# w#) =
757+writeWord8 (MBA# mba#) (I# offset#) (W8# w#) =
343 ST $ \s ->
758 ST $ \s ->
344− case writeWord8Array# mba# i# w# s of
759+ case writeWord8Array# mba# offset# w# s of
345 s -> (# s, () #)
760 s -> (# s, () #)