packages feed

utf8-string 1 → 1.0.1

raw patch · 3 files changed

+71/−3 lines, 3 filesdep ~base

Dependency ranges changed: base

Files

CHANGELOG.markdown view
@@ -1,3 +1,7 @@+1.0.1+-----+* Improve the performance of Data.ByteString.Lazy.UTF8.fromString. (Thanks, ndmitchell)+ 1 ----- * Remove out all the old utf8 IO support. GHC supports utf8 now.
Data/ByteString/Lazy/UTF8.hs view
@@ -38,16 +38,63 @@ import Data.Bits import Data.Word import Data.Int+import Foreign.Storable+import Foreign.Ptr+import Foreign.ForeignPtr+import Data.Char        (ord)+import Control.Exception        (assert) import qualified Data.ByteString.Lazy as B+import qualified Data.ByteString.Lazy.Internal as B+import qualified Data.ByteString.Internal as S+import System.IO.Unsafe import Prelude hiding (take,drop,splitAt,span,break,foldr,foldl,length,lines) -import Codec.Binary.UTF8.String(encode) import Codec.Binary.UTF8.Generic (buncons) +---------------------------------------------------------------------+-- ENCODING+ -- | Converts a Haskell string into a UTF8 encoded bytestring. fromString :: String -> B.ByteString-fromString xs = B.pack (encode xs)+fromString []  = B.empty+fromString xs0 = packChunks 32 xs0+  where+    packChunks n xs = case packUptoLenBytes n xs of+        (bs, [] ) -> B.chunk bs B.Empty+        (bs, xs') -> B.Chunk bs (packChunks (min (n * 2) B.smallChunkSize) xs') +    packUptoLenBytes :: Int -> String -> (S.ByteString, String)+    packUptoLenBytes len xs = unsafeCreateUptoN' len $ \ptr -> do+        (end, xs') <- go ptr (ptr `plusPtr` (len-4)) xs+        return (end `minusPtr` ptr, xs')++    -- end is the last position at which you can write a whole 4 byte sequence safely+    go :: Ptr Word8 -> Ptr Word8 -> String -> IO (Ptr Word8, String)+    go !ptr !end xs | ptr > end = return (ptr, xs)+    go !ptr !_   [] = return (ptr, [])+    go !ptr !end (x:xs)+        | x <= '\x7f' = poke ptr (S.c2w x) >> go (plusPtr ptr 1) end xs+        | otherwise = case ord x of+            oc | oc <= 0x7ff -> do+                    poke ptr $ fromIntegral $ 0xc0 + (oc `shiftR` 6)+                    pokeElemOff ptr 1 $ fromIntegral $ 0x80 + oc .&. 0x3f+                    go (plusPtr ptr 2) end xs+               | oc <= 0xffff -> do+                    poke ptr $ fromIntegral $ 0xe0 + (oc `shiftR` 12)+                    pokeElemOff ptr 1 $ fromIntegral $ 0x80 + ((oc `shiftR` 6) .&. 0x3f)+                    pokeElemOff ptr 2 $ fromIntegral $ 0x80 + oc .&. 0x3f+                    go (plusPtr ptr 3) end xs+               | otherwise -> do+                    poke ptr $ fromIntegral $ 0xf0 + (oc `shiftR` 18)+                    pokeElemOff ptr 1 $ fromIntegral $ 0x80 + ((oc `shiftR` 12) .&. 0x3f)+                    pokeElemOff ptr 2 $ fromIntegral $ 0x80 + ((oc `shiftR` 6) .&. 0x3f)+                    pokeElemOff ptr 3 $ fromIntegral $ 0x80 + oc .&. 0x3f+                    go (plusPtr ptr 4) end xs+++---------------------------------------------------------------------+-- DECODING+ -- | Convert a UTF8 encoded bytestring into a Haskell string. -- Invalid characters are replaced with '\xFFFD'. toString :: B.ByteString -> String@@ -221,3 +268,20 @@                         in xs : lines' ys               Nothing -> [bs] ++---------------------------------------------------------------------+-- COPIED FROM BYTESTRING+-- These functions are copied verbatum from Data.ByteString.Internal+-- I suspect their lack of export is an oversight++unsafeCreateUptoN' :: Int -> (Ptr Word8 -> IO (Int, a)) -> (S.ByteString, a)+unsafeCreateUptoN' l f = unsafeDupablePerformIO (createUptoN' l f)+{-# INLINE unsafeCreateUptoN' #-}++-- | Create ByteString of up to size @l@ and use action @f@ to fill it's contents which returns its true size.+createUptoN' :: Int -> (Ptr Word8 -> IO (Int, a)) -> IO (S.ByteString, a)+createUptoN' l f = do+    fp <- S.mallocByteString l+    (l', res) <- withForeignPtr fp $ \p -> f p+    assert (l' <= l) $ return (S.PS fp 0 l', res)+{-# INLINE createUptoN' #-}
utf8-string.cabal view
@@ -1,5 +1,5 @@ Name:               utf8-string-Version:            1+Version:            1.0.1 Author:             Eric Mertens Maintainer:         emertens@galois.com License:            BSD3