@@ -1,37 +1,42 @@
11{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
2−{-# LANGUAGE BangPatterns, EmptyDataDecls, FlexibleInstances, MagicHash, UnboxedTuples #-}
2+{-# LANGUAGE BangPatterns, FlexibleInstances, MagicHash, UnboxedTuples #-}
33module Data.Utf8
4− ( String
5− , Utf8(..)
6− , VeryLong
7− , Under256
4+ ( Utf8(..)
85 , isEmpty
96 , empty
107 , size
118 , contains
12− , containsDouble
139 , startsWith
1410 , startsWithChar
15− , endsWithWord
11+ , endsWithWord8
1612 , split
1713 , join
18− , all
19− , any
20− , toWord16
21− , fromWord16
22− -- conversions
23− , fromChars
14+ --
15+ , getUnder256
16+ , putUnder256
17+ --
18+ , getVeryLong
19+ , putVeryLong
20+ --
2421 , toChars
2522 , toBuilder
23+ , toEscapedBuilder
24+ --
2625 , fromPtr
27− , fromChunks
28− , Chunk(..)
26+ , fromSnippet
27+ , fromChars
28+ --
29+ , MBA
30+ , newByteArray
31+ , copyFromPtr
32+ , writeWord8
33+ , freeze
2934 )
3035 where
3136
3237
3338import Prelude hiding (String, all, any, concat)
34−import Data.Binary (Binary(..), Get, getWord8, putWord8)
39+import Data.Binary (Get, get, getWord8, Put, put, putWord8)
3540import Data.Binary.Put (putBuilder)
3641import Data.Binary.Get.Internal (readN)
3742import Data.Bits ((.&.), shiftR)
@@ -39,7 +44,6 @@ import qualified Data.ByteString.Internal as B
3944import qualified Data.ByteString.Builder.Internal as B
4045import qualified Data.Char as Char
4146import qualified Data.List as List
42−import Data.String (IsString(..))
4347import Foreign.ForeignPtr (touchForeignPtr)
4448import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
4549import Foreign.Ptr (minusPtr, plusPtr)
@@ -54,36 +58,35 @@ import GHC.Exts
5458 , copyByteArray#
5559 , copyAddrToByteArray#
5660 , copyByteArrayToAddr#
57− , writeWord8Array#,
61+ , writeWord8Array#
5862 )
5963import GHC.IO
6064import GHC.ST (ST(ST), runST)
6165import GHC.Prim
6266import GHC.Word (Word8(W8#), Word16(W16#))
6367
68+import qualified Parse.Primitives as P
69+
6470
6571
6672-- UTF-8
6773
6874
69−data Utf8 size tipe =
75+data Utf8 tipe =
7076 Utf8 ByteArray#
7177
7278
73−type String = Utf8 VERY_LONG STRING
74−type VeryLong t = Utf8 VERY_LONG t
75−type Under256 t = Utf8 UNDER_256 t
76−
77−data STRING
78−data VERY_LONG
79−data UNDER_256
8079
80+-- EMPTY
8181
8282
83−-- IS EMPTY
83+{-# NOINLINE empty #-}
84+empty :: Utf8 t
85+empty =
86+ runST (freeze =<< newByteArray 0)
8487
8588
86−isEmpty :: Utf8 l t -> Bool
89+isEmpty :: Utf8 t -> Bool
8790isEmpty (Utf8 ba#) =
8891 isTrue# (sizeofByteArray# ba# ==# 0#)
8992
@@ -92,7 +95,7 @@ isEmpty (Utf8 ba#) =
9295-- SIZE
9396
9497
95−size :: Utf8 l t -> Int
98+size :: Utf8 t -> Int
9699size (Utf8 ba#) =
97100 I# (sizeofByteArray# ba#)
98101
@@ -101,7 +104,7 @@ size (Utf8 ba#) =
101104-- CONTAINS
102105
103106
104−contains :: Word8 -> Utf8 l t -> Bool
107+contains :: Word8 -> Utf8 t -> Bool
105108contains (W8# word#) (Utf8 ba#) =
106109 containsHelp word# ba# 0# (sizeofByteArray# ba#)
107110
@@ -117,32 +120,11 @@ containsHelp word# ba# !offset# len# =
117120
118121
119122
120−-- CONTAINS DOUBLE
121−
122−
123−containsDouble :: Word8 -> Utf8 l t -> Bool
124−containsDouble (W8# word#) (Utf8 ba#) =
125− containsDoubleHelp word# ba# 0# (sizeofByteArray# ba#)
126−
127−
128−containsDoubleHelp :: Word# -> ByteArray# -> Int# -> Int# -> Bool
129−containsDoubleHelp word# ba# !offset# len# =
130− let !offset1# = offset# +# 1# in
131− if isTrue# (offset1# <# len#) then
132− if isTrue# (eqWord# word# (indexWord8Array# ba# offset# ))
133− && isTrue# (eqWord# word# (indexWord8Array# ba# offset1#))
134− then True
135− else containsDoubleHelp word# ba# (offset# +# 1#) len#
136− else
137− False
138−
139−
140−
141123-- STARTS WITH
142124
143125
144126{-# INLINE startsWith #-}
145−startsWith :: Utf8 l t -> Utf8 l t -> Bool
127+startsWith :: Utf8 t -> Utf8 t -> Bool
146128startsWith (Utf8 ba1#) (Utf8 ba2#) =
147129 let
148130 !len1# = sizeofByteArray# ba1#
@@ -157,9 +139,9 @@ startsWith (Utf8 ba1#) (Utf8 ba2#) =
157139-- STARTS WITH CHAR
158140
159141
160−startsWithChar :: (Char -> Bool) -> Utf8 l t -> Bool
161−startsWithChar isGood str@(Utf8 ba#) =
162− if isEmpty str then
142+startsWithChar :: (Char -> Bool) -> Utf8 t -> Bool
143+startsWithChar isGood bytes@(Utf8 ba#) =
144+ if isEmpty bytes then
163145 False
164146 else
165147 let
@@ -177,8 +159,8 @@ startsWithChar isGood str@(Utf8 ba#) =
177159-- ENDS WITH WORD
178160
179161
180−endsWithWord :: Word8 -> Utf8 l t -> Bool
181−endsWithWord (W8# w#) (Utf8 ba#) =
162+endsWithWord8 :: Word8 -> Utf8 t -> Bool
163+endsWithWord8 (W8# w#) (Utf8 ba#) =
182164 let len# = sizeofByteArray# ba# in
183165 isTrue# (len# ># 0#)
184166 &&
@@ -189,12 +171,12 @@ endsWithWord (W8# w#) (Utf8 ba#) =
189171-- SPLIT
190172
191173
192−split :: Word8 -> String -> [String]
174+split :: Word8 -> Utf8 t -> [Utf8 t]
193175split (W8# divider#) str@(Utf8 ba#) =
194176 splitHelp str 0 (findDividers divider# ba# 0# (sizeofByteArray# ba#) [])
195177
196178
197−splitHelp :: String -> Int -> [Int] -> [String]
179+splitHelp :: Utf8 t -> Int -> [Int] -> [Utf8 t]
198180splitHelp str start offsets =
199181 case offsets of
200182 [] ->
@@ -215,7 +197,7 @@ findDividers divider# ba# !offset# len# revOffsets =
215197 reverse revOffsets
216198
217199
218−unsafeSlice :: String -> Int -> Int -> String
200+unsafeSlice :: Utf8 t -> Int -> Int -> Utf8 t
219201unsafeSlice str start end =
220202 let !len = end - start in
221203 if len == 0 then
@@ -231,7 +213,7 @@ unsafeSlice str start end =
231213-- JOIN
232214
233215
234−join :: Word8 -> [String] -> String
216+join :: Word8 -> [Utf8 t] -> Utf8 t
235217join sep strings =
236218 case strings of
237219 [] ->
@@ -245,7 +227,7 @@ join sep strings =
245227 freeze mba
246228
247229
248−joinHelp :: Word8 -> MBA s -> Int -> String -> [String] -> ST s ()
230+joinHelp :: Word8 -> MBA s -> Int -> Utf8 t -> [Utf8 t] -> ST s ()
249231joinHelp sep mba offset str strings =
250232 let
251233 !len = size str
@@ -263,46 +245,10 @@ joinHelp sep mba offset str strings =
263245
264246
265247
266−-- ALL
267−
268−
269−all :: (Char -> Bool) -> Utf8 l t -> Bool
270−all isGood utf8 =
271− not (any (not . isGood) utf8)
272−
273−
274−
275−-- ANY
276−
277−
278−any :: (Char -> Bool) -> Utf8 l t -> Bool
279−any isGood (Utf8 ba#) =
280− anyHelp isGood ba# 0# (sizeofByteArray# ba#)
281−
282−
283−anyHelp :: (Char -> Bool) -> ByteArray# -> Int# -> Int# -> Bool
284−anyHelp isGood ba# offset# len# =
285− if isTrue# (offset# >=# len#) then
286− False
287− else
288− let
289− !w# = indexWord8Array# ba# offset#
290− !(# char, width# #)
291− | isTrue# (ltWord# w# 0xC0##) = (# C# (chr# (word2Int# w#)), 1# #)
292− | isTrue# (ltWord# w# 0xE0##) = (# chr2 ba# offset# w#, 2# #)
293− | isTrue# (ltWord# w# 0xF0##) = (# chr3 ba# offset# w#, 3# #)
294− | True = (# chr4 ba# offset# w#, 4# #)
295− in
296− if isGood char
297− then True
298− else anyHelp isGood ba# (offset# +# width#) len#
299−
300−
301−
302248-- EQUAL
303249
304250
305−instance Eq (Utf8 l t) where
251+instance Eq (Utf8 t) where
306252 (==) (Utf8 ba1#) (Utf8 ba2#) =
307253 let
308254 !len1# = sizeofByteArray# ba1#
@@ -317,7 +263,7 @@ instance Eq (Utf8 l t) where
317263-- COMPARE
318264
319265
320−instance Ord (Utf8 l t) where
266+instance Ord (Utf8 t) where
321267 compare (Utf8 ba1#) (Utf8 ba2#) =
322268 let
323269 !len1# = sizeofByteArray# ba1#
@@ -334,84 +280,20 @@ instance Ord (Utf8 l t) where
334280
335281
336282
337−-- TO WORD16
338−
339−
340−toWord16 :: String -> Maybe Word16
341−toWord16 (Utf8 ba#) =
342− let !len# = sizeofByteArray# ba# in
343− if isTrue# (len# ==# 0#) then
344− Nothing
345− else
346− let !w# = indexWord8Array# ba# 0# in
347− if isTrue# (eqWord# w# 0x30##) then
348− if isTrue# (len# ==# 1#) then Just 0 else Nothing
349− else
350− toWordHelp ba# 0# len# 0##
351−
352−
353−toWordHelp :: ByteArray# -> Int# -> Int# -> Word# -> Maybe Word16
354−toWordHelp ba# offset# len# number# =
355− if isTrue# (offset# <# len#) then
356− let !w# = indexWord8Array# ba# offset# in
357− if isTrue# (leWord# w# 0x39##) && isTrue# (geWord# w# 0x30##) then
358− let !newNumber# = plusWord# (timesWord# 10## number#) (minusWord# w# 0x30##) in
359− toWordHelp ba# (offset# +# 1#) len# newNumber#
360− else
361− Nothing
362− else
363− Just (W16# number#)
364−
365−
366−
367−-- FROM WORD16
368−
369−
370−fromWord16 :: Word16 -> String
371−fromWord16 n =
372− runST $
373− do let !size = getWordSize n
374− mba <- newByteArray size
375− writeDigits mba (size - 1) n
376− freeze mba
377−
378−
379−getWordSize :: Word16 -> Int
380−getWordSize n
381− | n < 10 = 1
382− | n < 100 = 2
383− | True = ceiling (logBase 10 (fromIntegral n + 1) :: Float)
384−
385−
386−writeDigits :: MBA s -> Int -> Word16 -> ST s ()
387−writeDigits !mba !offset !n =
388− do let (q,r) = quotRem n 10
389− writeWord8 mba offset (0x30 + fromIntegral r)
390− if q <= 0
391− then return ()
392− else writeDigits mba (offset-1) q
393−
394−
395−
396283-- FROM STRING
397284
398285
399−fromChars :: [Char] -> Utf8 l t
400−fromChars =
401− fromString
402−
403−
404−instance IsString (Utf8 l t) where
405− fromString str =
406− runST
407− (
408− do mba <- newByteArray (sum (map getWidth str))
409− writeString mba 0 str
410− )
286+fromChars :: [Char] -> Utf8 t
287+fromChars chars =
288+ runST
289+ (
290+ do mba <- newByteArray (sum (map getWidth chars))
291+ writeChars mba 0 chars
292+ )
411293
412294
413−writeString :: MBA s -> Int -> [Char] -> ST s (Utf8 l t)
414−writeString !mba !offset chars =
295+writeChars :: MBA s -> Int -> [Char] -> ST s (Utf8 t)
296+writeChars !mba !offset chars =
415297 case chars of
416298 [] ->
417299 freeze mba
@@ -419,25 +301,25 @@ writeString !mba !offset chars =
419301 char : chars
420302 | n < 0x80 ->
421303 do writeWord8 mba (offset ) (fromIntegral n)
422− writeString mba (offset + 1) chars
304+ writeChars mba (offset + 1) chars
423305
424306 | n < 0x800 ->
425307 do writeWord8 mba (offset ) (fromIntegral ((shiftR n 6 ) + 0xC0))
426308 writeWord8 mba (offset + 1) (fromIntegral (( n .&. 0x3F) + 0x80))
427− writeString mba (offset + 2) chars
309+ writeChars mba (offset + 2) chars
428310
429311 | n < 0x10000 ->
430312 do writeWord8 mba (offset ) (fromIntegral ((shiftR n 12 ) + 0xE0))
431313 writeWord8 mba (offset + 1) (fromIntegral ((shiftR n 6 .&. 0x3F) + 0x80))
432314 writeWord8 mba (offset + 2) (fromIntegral (( n .&. 0x3F) + 0x80))
433− writeString mba (offset + 3) chars
315+ writeChars mba (offset + 3) chars
434316
435317 | otherwise ->
436318 do writeWord8 mba (offset ) (fromIntegral ((shiftR n 18 ) + 0xF0))
437319 writeWord8 mba (offset + 1) (fromIntegral ((shiftR n 12 .&. 0x3F) + 0x80))
438320 writeWord8 mba (offset + 2) (fromIntegral ((shiftR n 6 .&. 0x3F) + 0x80))
439321 writeWord8 mba (offset + 3) (fromIntegral (( n .&. 0x3F) + 0x80))
440− writeString mba (offset + 4) chars
322+ writeChars mba (offset + 4) chars
441323
442324 where
443325 n = Char.ord char
@@ -455,10 +337,10 @@ getWidth char
455337
456338
457339
458−-- TO STRING
340+-- TO CHARS
459341
460342
461−toChars :: Utf8 l t -> [Char]
343+toChars :: Utf8 t -> [Char]
462344toChars (Utf8 ba#) =
463345 toCharsHelp ba# 0# (sizeofByteArray# ba#)
464346
@@ -528,13 +410,13 @@ chr4 ba# offset# firstWord# =
528410
529411
530412{-# INLINE toBuilder #-}
531−toBuilder :: Utf8 l t -> B.Builder
413+toBuilder :: Utf8 t -> B.Builder
532414toBuilder =
533415 \bytes -> B.builder (toBuilderHelp bytes)
534416
535417
536418{-# INLINE toBuilderHelp #-}
537−toBuilderHelp :: Utf8 l t -> B.BuildStep a -> B.BuildStep a
419+toBuilderHelp :: Utf8 t -> B.BuildStep a -> B.BuildStep a
538420toBuilderHelp !bytes@(Utf8 ba#) k =
539421 go 0 (I# (sizeofByteArray# ba#))
540422 where
@@ -554,144 +436,109 @@ toBuilderHelp !bytes@(Utf8 ba#) k =
554436
555437
556438
557−-- FROM PTR
439+-- TO ESCAPED BUILDER
558440
559441
560−fromPtr :: Ptr Word8 -> Ptr Word8 -> Utf8 l t
561−fromPtr pos end =
562− unsafeDupablePerformIO (stToIO (
563− do let !len = minusPtr end pos
564− mba <- newByteArray len
565− copyFromPtr pos mba 0 len
566− freeze mba
567− ))
442+{-# INLINE toEscapedBuilder #-}
443+toEscapedBuilder :: Word8 -> Word8 -> Utf8 t -> B.Builder
444+toEscapedBuilder before after =
445+ \name -> B.builder (toEscapedBuilderHelp before after name)
568446
569447
448+{-# INLINE toEscapedBuilderHelp #-}
449+toEscapedBuilderHelp :: Word8 -> Word8 -> Utf8 t -> B.BuildStep a -> B.BuildStep a
450+toEscapedBuilderHelp before after !name@(Utf8 ba#) k =
451+ go 0 (I# (sizeofByteArray# ba#))
452+ where
453+ go !offset !len !(B.BufferRange bOffset bEnd) =
454+ let
455+ !bLen = minusPtr bEnd bOffset
456+ in
457+ if len <= bLen then
458+ do -- TODO test if writing word-by-word is faster
459+ copyToPtr name offset bOffset len
460+ escape before after bOffset name offset len 0
461+ let !newBufferRange = B.BufferRange (plusPtr bOffset len) bEnd
462+ k newBufferRange
463+ else
464+ do copyToPtr name offset bOffset bLen
465+ escape before after bOffset name offset bLen 0
466+ let !newOffset = offset + bLen
467+ let !newLength = len - bLen
468+ return $ B.bufferFull 1 bEnd (go newOffset newLength)
469+
470+
471+escape :: Word8 -> Word8 -> Ptr a -> Utf8 t -> Int -> Int -> Int -> IO ()
472+escape before@(W8# before#) after ptr name@(Utf8 ba#) offset@(I# offset#) len@(I# len#) i@(I# i#) =
473+ if isTrue# (i# <# len#) then
474+ if isTrue# (eqWord# before# (indexWord8Array# ba# (offset# +# i#)))
475+ then
476+ do writeWordToPtr ptr i after
477+ escape before after ptr name offset len (i + 1)
478+ else
479+ do escape before after ptr name offset len (i + 1)
480+
481+ else
482+ return ()
570483
571−-- FROM CHUNKS
572484
573485
574−data Chunk
575− = Slice (Ptr Word8) Int
576− | Escape Word8
577− | CodePoint Int
486+-- FROM PTR
578487
579488
580−fromChunks :: [Chunk] -> Utf8 l t
581−fromChunks chunks =
489+fromPtr :: Ptr Word8 -> Ptr Word8 -> Utf8 t
490+fromPtr pos end =
582491 unsafeDupablePerformIO (stToIO (
583− do let !len = sum (map chunkToWidth chunks)
492+ do let !len = minusPtr end pos
584493 mba <- newByteArray len
585− writeChunks mba 0 chunks
494+ copyFromPtr pos mba 0 len
586495 freeze mba
587496 ))
588497
589498
590−chunkToWidth :: Chunk -> Int
591−chunkToWidth chunk =
592− case chunk of
593− Slice _ len ->
594− len
595−
596− Escape _ ->
597− 2
598−
599− CodePoint code ->
600− if code < 0xFFFF then 6 else 12
601−
602−
603−writeChunks :: MBA RealWorld -> Int -> [Chunk] -> ST RealWorld ()
604−writeChunks mba offset chunks =
605− case chunks of
606− [] ->
607− return ()
608−
609− chunk : chunks ->
610− case chunk of
611− Slice ptr len ->
612− do copyFromPtr ptr mba offset len
613− let !newOffset = offset + len
614− writeChunks mba newOffset chunks
615−
616− Escape word ->
617− do writeWord8 mba offset 0x5C {- \ -}
618− writeWord8 mba (offset + 1) word
619− let !newOffset = offset + 2
620− writeChunks mba newOffset chunks
621−
622− CodePoint code ->
623− if code < 0xFFFF then
624− do writeCode mba offset code
625− let !newOffset = offset + 6
626− writeChunks mba newOffset chunks
627− else
628− do let (hi,lo) = divMod (code - 0x10000) 0x400
629− writeCode mba (offset ) (hi + 0xD800)
630− writeCode mba (offset + 6) (lo + 0xDC00)
631− let !newOffset = offset + 12
632− writeChunks mba newOffset chunks
633−
634−
635−-- TODO see if it is faster to writeWord32 a block of hex-as-ascii
636−writeCode :: MBA RealWorld -> Int -> Int -> ST RealWorld ()
637−writeCode mba offset code =
638− do writeWord8 mba offset 0x5C {- \ -}
639− writeWord8 mba (offset + 1) 0x75 {- u -}
640− writeHex mba (offset + 2) (shiftR code 12)
641− writeHex mba (offset + 3) (shiftR code 8)
642− writeHex mba (offset + 4) (shiftR code 4)
643− writeHex mba (offset + 5) code
644−
645−
646−writeHex :: MBA RealWorld -> Int -> Int -> ST RealWorld ()
647−writeHex mba !offset !bits =
648− do let !n = fromIntegral bits .&. 0x0F
649− writeWord8 mba offset (if n < 10 then 0x30 + n else 0x37 + n)
650499
500+-- FROM SNIPPET
651501
652502
653−-- UNDER 256 BINARY
654−
655−
656−instance Binary (Utf8 UNDER_256 t) where
657− put bytes@(Utf8 ba#) =
658− do putWord8 (W8# (int2Word# (sizeofByteArray# ba#)))
659− putBuilder (toBuilder bytes)
660− get =
661− getUnder256 =<< getWord8
503+fromSnippet :: P.Snippet -> Utf8 t
504+fromSnippet (P.Snippet fptr off len _ _) =
505+ unsafeDupablePerformIO (stToIO (
506+ do mba <- newByteArray len
507+ let !pos = plusPtr (unsafeForeignPtrToPtr fptr) off
508+ copyFromPtr pos mba 0 len
509+ freeze mba
510+ ))
662511
663512
664−{-# INLINE getUnder256 #-}
665−getUnder256 :: Word8 -> Get (Utf8 UNDER_256 t)
666−getUnder256 w =
667− let !n = fromIntegral w in
668− readN n (copyFromByteString n)
669513
514+-- BINARY
670515
671516
672−-- VERY LONG BINARY
517+putUnder256 :: Utf8 t -> Put
518+putUnder256 bytes =
519+ do putWord8 (fromIntegral (size bytes))
520+ putBuilder (toBuilder bytes)
673521
674522
675−instance Binary (Utf8 VERY_LONG t) where
676− put str =
677− do put (size str)
678− putBuilder (toBuilder str)
679− get =
680− getVeryLong =<< get
523+getUnder256 :: Get (Utf8 t)
524+getUnder256 =
525+ do word <- getWord8
526+ let !n = fromIntegral word
527+ readN n (copyFromByteString n)
681528
682529
683−{-# INLINE getVeryLong #-}
684−getVeryLong :: Int -> Get (Utf8 VERY_LONG t)
685−getVeryLong n =
686− if n > 0
687− then readN n (copyFromByteString n)
688− else return empty
530+putVeryLong :: Utf8 t -> Put
531+putVeryLong bytes =
532+ do put (size bytes)
533+ putBuilder (toBuilder bytes)
689534
690535
691−{-# NOINLINE empty #-}
692−empty :: Utf8 l t
693−empty =
694− runST (freeze =<< newByteArray 0)
536+getVeryLong :: Get (Utf8 t)
537+getVeryLong =
538+ do n <- get
539+ if n > 0
540+ then readN n (copyFromByteString n)
541+ else return empty
695542
696543
697544
@@ -699,7 +546,7 @@ empty =
699546
700547
701548{-# INLINE copyFromByteString #-}
702−copyFromByteString :: Int -> B.ByteString -> Utf8 l t
549+copyFromByteString :: Int -> B.ByteString -> Utf8 t
703550copyFromByteString len (B.PS fptr offset _) =
704551 unsafeDupablePerformIO
705552 (
@@ -725,14 +572,14 @@ newByteArray (I# len#) =
725572 (# s, mba# #) -> (# s, MBA# mba# #)
726573
727574
728−freeze :: MBA s -> ST s (Utf8 l t)
575+freeze :: MBA s -> ST s (Utf8 t)
729576freeze (MBA# mba#) =
730577 ST $ \s ->
731578 case unsafeFreezeByteArray# mba# s of
732579 (# s, ba# #) -> (# s, Utf8 ba# #)
733580
734581
735−copy :: Utf8 l t -> Int -> MBA s -> Int -> Int -> ST s ()
582+copy :: Utf8 t -> Int -> MBA s -> Int -> Int -> ST s ()
736583copy (Utf8 ba#) (I# offset#) (MBA# mba#) (I# i#) (I# len#) =
737584 ST $ \s ->
738585 case copyByteArray# ba# offset# mba# i# len# s of
@@ -746,7 +593,7 @@ copyFromPtr (Ptr src#) (MBA# mba#) (I# offset#) (I# len#) =
746593 s -> (# s, () #)
747594
748595
749−copyToPtr :: Utf8 l t -> Int -> Ptr a -> Int -> IO ()
596+copyToPtr :: Utf8 t -> Int -> Ptr a -> Int -> IO ()
750597copyToPtr (Utf8 ba#) (I# offset#) (Ptr mba#) (I# len#) =
751598 IO $ \s ->
752599 case copyByteArrayToAddr# ba# offset# mba# len# s of
@@ -759,3 +606,11 @@ writeWord8 (MBA# mba#) (I# offset#) (W8# w#) =
759606 ST $ \s ->
760607 case writeWord8Array# mba# offset# w# s of
761608 s -> (# s, () #)
609+
610+
611+{-# INLINE writeWordToPtr #-}
612+writeWordToPtr :: Ptr a -> Int -> Word8 -> IO ()
613+writeWordToPtr (Ptr addr#) (I# offset#) (W8# word#) =
614+ IO $ \s ->
615+ case writeWord8OffAddr# addr# offset# word# s of
616+ s -> (# s, () #)