{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnliftedFFITypes #-}
module Data.Text.Internal.Validate
(
isValidUtf8ByteString
, isValidUtf8ByteArray
, isValidUtf8ByteArrayUnpinned
, isValidUtf8ByteArrayPinned
) where
import Data.Array.Byte (ByteArray(ByteArray))
import Data.ByteString (ByteString)
import GHC.Exts (isTrue#,isByteArrayPinned#)
#ifdef SIMDUTF
import Data.Text.Unsafe (unsafeDupablePerformIO)
import Data.Text.Internal.ByteStringCompat (withBS)
import Data.Text.Internal.Unsafe (unsafeWithForeignPtr)
import Data.Text.Internal.Validate.Simd (c_is_valid_utf8_bytearray_safe,c_is_valid_utf8_bytearray_unsafe,c_is_valid_utf8_ptr_unsafe)
#else
import qualified Data.ByteString as B
import qualified Data.Text.Internal.Validate.Native as N
#endif
isValidUtf8ByteString :: ByteString -> Bool
#ifdef SIMDUTF
isValidUtf8ByteString :: ByteString -> Bool
isValidUtf8ByteString ByteString
bs = ByteString -> (ForeignPtr Word8 -> Int -> Bool) -> Bool
forall r. ByteString -> (ForeignPtr Word8 -> Int -> r) -> r
withBS ByteString
bs ((ForeignPtr Word8 -> Int -> Bool) -> Bool)
-> (ForeignPtr Word8 -> Int -> Bool) -> Bool
forall a b. (a -> b) -> a -> b
$ \ForeignPtr Word8
fp Int
len -> IO Bool -> Bool
forall a. IO a -> a
unsafeDupablePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$
ForeignPtr Word8 -> (Ptr Word8 -> IO Bool) -> IO Bool
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
unsafeWithForeignPtr ForeignPtr Word8
fp ((Ptr Word8 -> IO Bool) -> IO Bool)
-> (Ptr Word8 -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr -> (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
0) (CInt -> Bool) -> IO CInt -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word8 -> CSize -> IO CInt
c_is_valid_utf8_ptr_unsafe Ptr Word8
ptr (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
#else
#if MIN_VERSION_bytestring(0,12,1)
isValidUtf8ByteString = B.isValidUtf8
#else
isValidUtf8ByteString = N.isValidUtf8ByteStringHaskell
#endif
#endif
isValidUtf8ByteArray ::
ByteArray
-> Int
-> Int
-> Bool
isValidUtf8ByteArray :: ByteArray -> Int -> Int -> Bool
isValidUtf8ByteArray b :: ByteArray
b@(ByteArray ByteArray#
b#) !Int
off !Int
len
| Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
131072
, Int# -> Bool
isTrue# (ByteArray# -> Int#
isByteArrayPinned# ByteArray#
b#)
= ByteArray -> Int -> Int -> Bool
isValidUtf8ByteArrayPinned ByteArray
b Int
off Int
len
| Bool
otherwise = ByteArray -> Int -> Int -> Bool
isValidUtf8ByteArrayUnpinned ByteArray
b Int
off Int
len
isValidUtf8ByteArrayUnpinned ::
ByteArray
-> Int
-> Int
-> Bool
#ifdef SIMDUTF
isValidUtf8ByteArrayUnpinned :: ByteArray -> Int -> Int -> Bool
isValidUtf8ByteArrayUnpinned (ByteArray ByteArray#
bs) !Int
off !Int
len =
IO Bool -> Bool
forall a. IO a -> a
unsafeDupablePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
0) (CInt -> Bool) -> IO CInt -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteArray# -> CSize -> CSize -> IO CInt
c_is_valid_utf8_bytearray_unsafe ByteArray#
bs (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
off) (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
#else
isValidUtf8ByteArrayUnpinned = N.isValidUtf8ByteArrayHaskell
#endif
isValidUtf8ByteArrayPinned ::
ByteArray
-> Int
-> Int
-> Bool
#ifdef SIMDUTF
isValidUtf8ByteArrayPinned :: ByteArray -> Int -> Int -> Bool
isValidUtf8ByteArrayPinned (ByteArray ByteArray#
bs) !Int
off !Int
len =
IO Bool -> Bool
forall a. IO a -> a
unsafeDupablePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
0) (CInt -> Bool) -> IO CInt -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteArray# -> CSize -> CSize -> IO CInt
c_is_valid_utf8_bytearray_safe ByteArray#
bs (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
off) (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
#else
isValidUtf8ByteArrayPinned = N.isValidUtf8ByteArrayHaskell
#endif