{-# LANGUAGE BangPatterns, CPP, GeneralizedNewtypeDeriving #-}
module Data.Text.Foreign
(
I8
, fromPtr
, useAsPtr
, asForeignPtr
, peekCStringLen
, withCStringLen
, lengthWord8
, unsafeCopyToPtr
, dropWord8
, takeWord8
) where
import Control.Monad.ST.Unsafe (unsafeSTToIO)
import Data.ByteString.Unsafe (unsafePackCStringLen, unsafeUseAsCStringLen)
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Data.Text.Internal (Text(..), empty)
import Data.Text.Internal.Unsafe (unsafeWithForeignPtr)
import Data.Text.Unsafe (lengthWord8)
import Data.Word (Word8)
import Foreign.C.String (CStringLen)
import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrArray)
import Foreign.Marshal.Alloc (allocaBytes)
import Foreign.Ptr (Ptr, castPtr)
import qualified Data.Text.Array as A
newtype I8 = I8 Int
deriving (I8
I8 -> I8 -> Bounded I8
forall a. a -> a -> Bounded a
maxBound :: I8
$cmaxBound :: I8
minBound :: I8
$cminBound :: I8
Bounded, Int -> I8
I8 -> Int
I8 -> [I8]
I8 -> I8
I8 -> I8 -> [I8]
I8 -> I8 -> I8 -> [I8]
(I8 -> I8)
-> (I8 -> I8)
-> (Int -> I8)
-> (I8 -> Int)
-> (I8 -> [I8])
-> (I8 -> I8 -> [I8])
-> (I8 -> I8 -> [I8])
-> (I8 -> I8 -> I8 -> [I8])
-> Enum I8
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: I8 -> I8 -> I8 -> [I8]
$cenumFromThenTo :: I8 -> I8 -> I8 -> [I8]
enumFromTo :: I8 -> I8 -> [I8]
$cenumFromTo :: I8 -> I8 -> [I8]
enumFromThen :: I8 -> I8 -> [I8]
$cenumFromThen :: I8 -> I8 -> [I8]
enumFrom :: I8 -> [I8]
$cenumFrom :: I8 -> [I8]
fromEnum :: I8 -> Int
$cfromEnum :: I8 -> Int
toEnum :: Int -> I8
$ctoEnum :: Int -> I8
pred :: I8 -> I8
$cpred :: I8 -> I8
succ :: I8 -> I8
$csucc :: I8 -> I8
Enum, I8 -> I8 -> Bool
(I8 -> I8 -> Bool) -> (I8 -> I8 -> Bool) -> Eq I8
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: I8 -> I8 -> Bool
$c/= :: I8 -> I8 -> Bool
== :: I8 -> I8 -> Bool
$c== :: I8 -> I8 -> Bool
Eq, Enum I8
Real I8
Real I8
-> Enum I8
-> (I8 -> I8 -> I8)
-> (I8 -> I8 -> I8)
-> (I8 -> I8 -> I8)
-> (I8 -> I8 -> I8)
-> (I8 -> I8 -> (I8, I8))
-> (I8 -> I8 -> (I8, I8))
-> (I8 -> Integer)
-> Integral I8
I8 -> Integer
I8 -> I8 -> (I8, I8)
I8 -> I8 -> I8
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
toInteger :: I8 -> Integer
$ctoInteger :: I8 -> Integer
divMod :: I8 -> I8 -> (I8, I8)
$cdivMod :: I8 -> I8 -> (I8, I8)
quotRem :: I8 -> I8 -> (I8, I8)
$cquotRem :: I8 -> I8 -> (I8, I8)
mod :: I8 -> I8 -> I8
$cmod :: I8 -> I8 -> I8
div :: I8 -> I8 -> I8
$cdiv :: I8 -> I8 -> I8
rem :: I8 -> I8 -> I8
$crem :: I8 -> I8 -> I8
quot :: I8 -> I8 -> I8
$cquot :: I8 -> I8 -> I8
$cp2Integral :: Enum I8
$cp1Integral :: Real I8
Integral, Integer -> I8
I8 -> I8
I8 -> I8 -> I8
(I8 -> I8 -> I8)
-> (I8 -> I8 -> I8)
-> (I8 -> I8 -> I8)
-> (I8 -> I8)
-> (I8 -> I8)
-> (I8 -> I8)
-> (Integer -> I8)
-> Num I8
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> I8
$cfromInteger :: Integer -> I8
signum :: I8 -> I8
$csignum :: I8 -> I8
abs :: I8 -> I8
$cabs :: I8 -> I8
negate :: I8 -> I8
$cnegate :: I8 -> I8
* :: I8 -> I8 -> I8
$c* :: I8 -> I8 -> I8
- :: I8 -> I8 -> I8
$c- :: I8 -> I8 -> I8
+ :: I8 -> I8 -> I8
$c+ :: I8 -> I8 -> I8
Num, Eq I8
Eq I8
-> (I8 -> I8 -> Ordering)
-> (I8 -> I8 -> Bool)
-> (I8 -> I8 -> Bool)
-> (I8 -> I8 -> Bool)
-> (I8 -> I8 -> Bool)
-> (I8 -> I8 -> I8)
-> (I8 -> I8 -> I8)
-> Ord I8
I8 -> I8 -> Bool
I8 -> I8 -> Ordering
I8 -> I8 -> I8
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: I8 -> I8 -> I8
$cmin :: I8 -> I8 -> I8
max :: I8 -> I8 -> I8
$cmax :: I8 -> I8 -> I8
>= :: I8 -> I8 -> Bool
$c>= :: I8 -> I8 -> Bool
> :: I8 -> I8 -> Bool
$c> :: I8 -> I8 -> Bool
<= :: I8 -> I8 -> Bool
$c<= :: I8 -> I8 -> Bool
< :: I8 -> I8 -> Bool
$c< :: I8 -> I8 -> Bool
compare :: I8 -> I8 -> Ordering
$ccompare :: I8 -> I8 -> Ordering
$cp1Ord :: Eq I8
Ord, ReadPrec [I8]
ReadPrec I8
Int -> ReadS I8
ReadS [I8]
(Int -> ReadS I8)
-> ReadS [I8] -> ReadPrec I8 -> ReadPrec [I8] -> Read I8
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [I8]
$creadListPrec :: ReadPrec [I8]
readPrec :: ReadPrec I8
$creadPrec :: ReadPrec I8
readList :: ReadS [I8]
$creadList :: ReadS [I8]
readsPrec :: Int -> ReadS I8
$creadsPrec :: Int -> ReadS I8
Read, Num I8
Ord I8
Num I8 -> Ord I8 -> (I8 -> Rational) -> Real I8
I8 -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: I8 -> Rational
$ctoRational :: I8 -> Rational
$cp2Real :: Ord I8
$cp1Real :: Num I8
Real, Int -> I8 -> ShowS
[I8] -> ShowS
I8 -> String
(Int -> I8 -> ShowS)
-> (I8 -> String) -> ([I8] -> ShowS) -> Show I8
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [I8] -> ShowS
$cshowList :: [I8] -> ShowS
show :: I8 -> String
$cshow :: I8 -> String
showsPrec :: Int -> I8 -> ShowS
$cshowsPrec :: Int -> I8 -> ShowS
Show)
fromPtr :: Ptr Word8
-> I8
-> IO Text
fromPtr :: Ptr Word8 -> I8 -> IO Text
fromPtr Ptr Word8
ptr (I8 Int
len) = ST Any Text -> IO Text
forall s a. ST s a -> IO a
unsafeSTToIO (ST Any Text -> IO Text) -> ST Any Text -> IO Text
forall a b. (a -> b) -> a -> b
$ do
MArray Any
dst <- Int -> ST Any (MArray Any)
forall s. Int -> ST s (MArray s)
A.new Int
len
MArray Any -> Int -> Ptr Word8 -> Int -> ST Any ()
forall s. MArray s -> Int -> Ptr Word8 -> Int -> ST s ()
A.copyFromPointer MArray Any
dst Int
0 Ptr Word8
ptr Int
len
Array
arr <- MArray Any -> ST Any Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray Any
dst
Text -> ST Any Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> ST Any Text) -> Text -> ST Any Text
forall a b. (a -> b) -> a -> b
$! Array -> Int -> Int -> Text
Text Array
arr Int
0 Int
len
takeWord8 :: I8 -> Text -> Text
takeWord8 :: I8 -> Text -> Text
takeWord8 = ((Text, Text) -> Text
forall a b. (a, b) -> a
fst ((Text, Text) -> Text) -> (Text -> (Text, Text)) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Text -> (Text, Text)) -> Text -> Text)
-> (I8 -> Text -> (Text, Text)) -> I8 -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. I8 -> Text -> (Text, Text)
splitAtWord8
dropWord8 :: I8 -> Text -> Text
dropWord8 :: I8 -> Text -> Text
dropWord8 = ((Text, Text) -> Text
forall a b. (a, b) -> b
snd ((Text, Text) -> Text) -> (Text -> (Text, Text)) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Text -> (Text, Text)) -> Text -> Text)
-> (I8 -> Text -> (Text, Text)) -> I8 -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. I8 -> Text -> (Text, Text)
splitAtWord8
splitAtWord8 :: I8 -> Text -> (Text, Text)
splitAtWord8 :: I8 -> Text -> (Text, Text)
splitAtWord8 (I8 Int
n) t :: Text
t@(Text Array
arr Int
off Int
len)
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = (Text
empty, Text
t)
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
len Bool -> Bool -> Bool
|| Int
m Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
len = (Text
t, Text
empty)
| Bool
otherwise = (Array -> Int -> Int -> Text
Text Array
arr Int
off Int
m, Array -> Int -> Int -> Text
Text Array
arr (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
m) (Int
lenInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
m))
where
m :: Int
m | Word8
w0 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
0x80 = Int
n
| Word8
w0 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0xF0 = Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3
| Word8
w0 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0xE0 = Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2
| Word8
w0 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0xC0 = Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1
| Word8
w1 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0xF0 = Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2
| Word8
w1 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0xE0 = Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1
| Word8
w1 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0xC0 = Int
n
| Word8
w2 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0xF0 = Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1
| Bool
otherwise = Int
n
w0 :: Word8
w0 = Array -> Int -> Word8
A.unsafeIndex Array
arr (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
w1 :: Word8
w1 = Array -> Int -> Word8
A.unsafeIndex Array
arr (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2)
w2 :: Word8
w2 = Array -> Int -> Word8
A.unsafeIndex Array
arr (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
3)
unsafeCopyToPtr :: Text -> Ptr Word8 -> IO ()
unsafeCopyToPtr :: Text -> Ptr Word8 -> IO ()
unsafeCopyToPtr (Text Array
arr Int
off Int
len) Ptr Word8
ptr = ST Any () -> IO ()
forall s a. ST s a -> IO a
unsafeSTToIO (ST Any () -> IO ()) -> ST Any () -> IO ()
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Ptr Word8 -> Int -> ST Any ()
forall s. Array -> Int -> Ptr Word8 -> Int -> ST s ()
A.copyToPointer Array
arr Int
off Ptr Word8
ptr Int
len
useAsPtr :: Text -> (Ptr Word8 -> I8 -> IO a) -> IO a
useAsPtr :: Text -> (Ptr Word8 -> I8 -> IO a) -> IO a
useAsPtr t :: Text
t@(Text Array
_arr Int
_off Int
len) Ptr Word8 -> I8 -> IO a
action =
Int -> (Ptr Word8 -> IO a) -> IO a
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
len ((Ptr Word8 -> IO a) -> IO a) -> (Ptr Word8 -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
buf -> do
Text -> Ptr Word8 -> IO ()
unsafeCopyToPtr Text
t Ptr Word8
buf
Ptr Word8 -> I8 -> IO a
action (Ptr Word8 -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
buf) (Int -> I8
I8 Int
len)
asForeignPtr :: Text -> IO (ForeignPtr Word8, I8)
asForeignPtr :: Text -> IO (ForeignPtr Word8, I8)
asForeignPtr t :: Text
t@(Text Array
_arr Int
_off Int
len) = do
ForeignPtr Word8
fp <- Int -> IO (ForeignPtr Word8)
forall a. Storable a => Int -> IO (ForeignPtr a)
mallocForeignPtrArray Int
len
ForeignPtr Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
unsafeWithForeignPtr ForeignPtr Word8
fp ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ Text -> Ptr Word8 -> IO ()
unsafeCopyToPtr Text
t
(ForeignPtr Word8, I8) -> IO (ForeignPtr Word8, I8)
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr Word8
fp, Int -> I8
I8 Int
len)
peekCStringLen :: CStringLen -> IO Text
peekCStringLen :: CStringLen -> IO Text
peekCStringLen CStringLen
cs = do
ByteString
bs <- CStringLen -> IO ByteString
unsafePackCStringLen CStringLen
cs
Text -> IO Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> IO Text) -> Text -> IO Text
forall a b. (a -> b) -> a -> b
$! ByteString -> Text
decodeUtf8 ByteString
bs
withCStringLen :: Text -> (CStringLen -> IO a) -> IO a
withCStringLen :: Text -> (CStringLen -> IO a) -> IO a
withCStringLen Text
t CStringLen -> IO a
act = ByteString -> (CStringLen -> IO a) -> IO a
forall a. ByteString -> (CStringLen -> IO a) -> IO a
unsafeUseAsCStringLen (Text -> ByteString
encodeUtf8 Text
t) CStringLen -> IO a
act