@@ -53,24 +53,22 @@ import Control.Monad.ST.Unsafe (unsafeIOToST, unsafeSTToIO)
54import Control.Monad.ST (unsafeIOToST, unsafeSTToIO)
54import Control.Monad.ST (unsafeIOToST, unsafeSTToIO)
56−import Data.Bits ((.&.))
57import Data.ByteString as B
56import Data.ByteString as B
58import Data.ByteString.Internal as B
57import Data.ByteString.Internal as B
59import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
58import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
60import Data.Text.Internal (Text(..), textP)
59import Data.Text.Internal (Text(..), textP)
61−import Data.Text.UnsafeChar (ord, unsafeWrite)
60+import Data.Text.UnsafeChar (unsafeWrite)
62−import Data.Text.UnsafeShift (shiftL, shiftR)
63import Data.Word (Word8)
61import Data.Word (Word8)
64import Foreign.C.Types (CSize)
62import Foreign.C.Types (CSize)
65−import Foreign.ForeignPtr (withForeignPtr)
63+import Foreign.ForeignPtr (newForeignPtr, withForeignPtr)
66import Foreign.Marshal.Utils (with)
64import Foreign.Marshal.Utils (with)
67import Foreign.Ptr (Ptr, plusPtr)
65import Foreign.Ptr (Ptr, plusPtr)
68import Foreign.Storable (peek, poke)
66import Foreign.Storable (peek, poke)
69−import GHC.Base (MutableByteArray#)
67+import GHC.Base (ByteArray#, MutableByteArray#)
70import System.IO.Unsafe (unsafePerformIO)
68import System.IO.Unsafe (unsafePerformIO)
71import qualified Data.Text.Array as A
69import qualified Data.Text.Array as A
72import qualified Data.Text.Encoding.Fusion as E
70import qualified Data.Text.Encoding.Fusion as E
73−import qualified Data.Text.Encoding.Utf16 as U16
71+
74import qualified Data.Text.Fusion as F
72import qualified Data.Text.Fusion as F
@@ -145,45 +143,14 @@ decodeUtf8' = unsafePerformIO . try . evaluate . decodeUtf8With strictDecode
146-- | Encode text using UTF-8 encoding.
144-- | Encode text using UTF-8 encoding.
147encodeUtf8 :: Text -> ByteString
145encodeUtf8 :: Text -> ByteString
148−encodeUtf8 (Text arr off len) = unsafePerformIO $ do
146+encodeUtf8 (Text arr off len)
149− let size0 = max len 4
147+ | len == 0 = empty
150− mallocByteString size0 >>= start size0 off 0
148+ | otherwise = unsafePerformIO $ do
151− where
149+ with (fromIntegral len ::CSize) $ \lenPtr -> do
152− start size n0 m0 fp = withForeignPtr fp $ loop n0 m0
150+ dptr <- c_encode_utf8 lenPtr (A.aBA arr) (fromIntegral off)
153− where
151+ fp <- newForeignPtr c_free_finalizer dptr
154− loop n1 m1 ptr = go n1 m1
152+ dlen <- peek lenPtr
157− | n == off+len = return (PS fp 0 m)
153+ return (PS fp 0 (fromIntegral dlen))
159− let poke8 k v = poke (ptr `plusPtr` k) (fromIntegral v :: Word8)
162− | otherwise = {-# SCC "resizeUtf8/ensure" #-} do
163− let newSize = size `shiftL` 1
164− fp' <- mallocByteString newSize
165− withForeignPtr fp' $ \ptr' ->
166− memcpy ptr' ptr (fromIntegral m)
167− start newSize n m fp'
168− {-# INLINE ensure #-}
169− case A.unsafeIndex arr n of
170− w| w <= 0x7F -> poke8 m w >> go (n+1) (m+1)
171− | w <= 0x7FF -> ensure 2 $ do
172− poke8 m $ (w `shiftR` 6) + 0xC0
173− poke8 (m+1) $ (w .&. 0x3f) + 0x80
175− | 0xD800 <= w && w <= 0xDBFF -> ensure 4 $ do
176− let c = ord $ U16.chr2 w (A.unsafeIndex arr (n+1))
177− poke8 m $ (c `shiftR` 18) + 0xF0
178− poke8 (m+1) $ ((c `shiftR` 12) .&. 0x3F) + 0x80
179− poke8 (m+2) $ ((c `shiftR` 6) .&. 0x3F) + 0x80
180− poke8 (m+3) $ (c .&. 0x3F) + 0x80
182− | otherwise -> ensure 3 $ do
183− poke8 m $ (w `shiftR` 12) + 0xE0
184− poke8 (m+1) $ ((w `shiftR` 6) .&. 0x3F) + 0x80
185− poke8 (m+2) $ (w .&. 0x3F) + 0x80
188-- | Decode text from little endian UTF-16 encoding.
155-- | Decode text from little endian UTF-16 encoding.
189decodeUtf16LEWith :: OnDecodeError -> ByteString -> Text
156decodeUtf16LEWith :: OnDecodeError -> ByteString -> Text
@@ -264,3 +231,6 @@ encodeUtf32BE txt = E.unstream (E.restreamUtf32BE (F.stream txt))
264foreign import ccall unsafe "_hs_text_decode_utf8" c_decode_utf8
231foreign import ccall unsafe "_hs_text_decode_utf8" c_decode_utf8
265 :: MutableByteArray# s -> Ptr CSize
232 :: MutableByteArray# s -> Ptr CSize
266 -> Ptr Word8 -> Ptr Word8 -> IO (Ptr Word8)
233 -> Ptr Word8 -> Ptr Word8 -> IO (Ptr Word8)
235+foreign import ccall unsafe "_hs_text_encode_utf8" c_encode_utf8
236+ :: Ptr CSize -> ByteArray# -> CSize -> IO (Ptr Word8)