{-# language BangPatterns #-}
{-# language BinaryLiterals #-}
{-# language DataKinds #-}
{-# language DeriveFunctor #-}
{-# language DerivingStrategies #-}
{-# language GADTSyntax #-}
{-# language KindSignatures #-}
{-# language LambdaCase #-}
{-# language MagicHash #-}
{-# language MultiWayIf #-}
{-# language PolyKinds #-}
{-# language RankNTypes #-}
{-# language ScopedTypeVariables #-}
{-# language StandaloneDeriving #-}
{-# language TypeApplications #-}
{-# language UnboxedSums #-}
{-# language UnboxedTuples #-}
module Data.Bytes.Parser.Ascii
(
Latin.char
, Latin.char2
, Latin.char3
, Latin.char4
, charInsensitive
, any
, any#
, peek
, opt
, shortTrailedBy
, takeShortWhile
, Latin.skipDigits
, Latin.skipDigits1
, Latin.skipChar
, Latin.skipChar1
, skipAlpha
, skipAlpha1
, skipTrailedBy
, skipWhile
, Latin.decWord
, Latin.decWord8
, Latin.decWord16
, Latin.decWord32
) where
import Prelude hiding (length,any,fail,takeWhile)
import Data.Bits (clearBit)
import Data.Bytes.Types (Bytes(..))
import Data.Bytes.Parser.Internal (Parser(..),uneffectful,Result#,uneffectful#)
import Data.Bytes.Parser.Internal (Result(..),indexLatinCharArray,upcastUnitSuccess)
import Data.Char (ord)
import Data.Word (Word8)
import Data.Text.Short (ShortText)
import Control.Monad.ST.Run (runByteArrayST)
import GHC.Exts (Int(I#),Char(C#),Int#,Char#,(-#),(+#),(<#),ord#,indexCharArray#,chr#)
import GHC.Exts (gtChar#)
import qualified Data.ByteString.Short.Internal as BSS
import qualified Data.Text.Short.Unsafe as TS
import qualified Data.Bytes as Bytes
import qualified Data.Bytes.Parser.Latin as Latin
import qualified Data.Bytes.Parser.Unsafe as Unsafe
import qualified Data.Primitive as PM
charInsensitive :: e -> Char -> Parser e s ()
{-# inline charInsensitive #-}
charInsensitive :: forall e s. e -> Char -> Parser e s ()
charInsensitive e
e !Char
c = forall e a s. (Bytes -> Result e a) -> Parser e s a
uneffectful forall a b. (a -> b) -> a -> b
$ \Bytes
chunk -> if Bytes -> Int
length Bytes
chunk forall a. Ord a => a -> a -> Bool
> Int
0
then if forall a. Bits a => a -> Int -> a
clearBit (forall a. Prim a => ByteArray -> Int -> a
PM.indexByteArray (Bytes -> ByteArray
array Bytes
chunk) (Bytes -> Int
offset Bytes
chunk) :: Word8) Int
5 forall a. Eq a => a -> a -> Bool
== Word8
w
then forall e a. a -> Int -> Int -> Result e a
Success () (Bytes -> Int
offset Bytes
chunk forall a. Num a => a -> a -> a
+ Int
1) (Bytes -> Int
length Bytes
chunk forall a. Num a => a -> a -> a
- Int
1)
else forall e a. e -> Result e a
Failure e
e
else forall e a. e -> Result e a
Failure e
e
where
w :: Word8
w = forall a. Bits a => a -> Int -> a
clearBit (forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int @Word8 (Char -> Int
ord Char
c)) Int
5
skipTrailedBy :: e -> Char -> Parser e s ()
{-# inline skipTrailedBy #-}
skipTrailedBy :: forall e s. e -> Char -> Parser e s ()
skipTrailedBy e
e !Char
c = do
let go :: Parser e s ()
go = do
!Char
d <- forall e s. e -> Parser e s Char
any e
e
if Char
d forall a. Eq a => a -> a -> Bool
== Char
c
then forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
else Parser e s ()
go
forall {s}. Parser e s ()
go
takeShortWhile :: (Char -> Bool) -> Parser e s ShortText
{-# inline takeShortWhile #-}
takeShortWhile :: forall e s. (Char -> Bool) -> Parser e s ShortText
takeShortWhile Char -> Bool
p = do
!Int
start <- forall e s. Parser e s Int
Unsafe.cursor
forall e s. (Char -> Bool) -> Parser e s ()
skipWhile Char -> Bool
p
Int
end <- forall e s. Parser e s Int
Unsafe.cursor
ByteArray
src <- forall e s. Parser e s ByteArray
Unsafe.expose
let len :: Int
len = Int
end forall a. Num a => a -> a -> a
- Int
start
!r :: ByteArray
r = (forall s. ST s ByteArray) -> ByteArray
runByteArrayST forall a b. (a -> b) -> a -> b
$ do
MutableByteArray s
marr <- forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
PM.newByteArray Int
len
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m)
-> Int -> ByteArray -> Int -> Int -> m ()
PM.copyByteArray MutableByteArray s
marr Int
0 ByteArray
src Int
start Int
len
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m) -> m ByteArray
PM.unsafeFreezeByteArray MutableByteArray s
marr
forall (f :: * -> *) a. Applicative f => a -> f a
pure
forall a b. (a -> b) -> a -> b
$ ShortByteString -> ShortText
TS.fromShortByteStringUnsafe
forall a b. (a -> b) -> a -> b
$ ByteArray -> ShortByteString
byteArrayToShortByteString
forall a b. (a -> b) -> a -> b
$ ByteArray
r
shortTrailedBy :: e -> Char -> Parser e s ShortText
shortTrailedBy :: forall e s. e -> Char -> Parser e s ShortText
shortTrailedBy e
e !Char
c = do
!Int
start <- forall e s. Parser e s Int
Unsafe.cursor
forall e s. e -> Char -> Parser e s ()
skipTrailedBy e
e Char
c
Int
end <- forall e s. Parser e s Int
Unsafe.cursor
ByteArray
src <- forall e s. Parser e s ByteArray
Unsafe.expose
let len :: Int
len = Int
end forall a. Num a => a -> a -> a
- Int
start forall a. Num a => a -> a -> a
- Int
1
!r :: ByteArray
r = (forall s. ST s ByteArray) -> ByteArray
runByteArrayST forall a b. (a -> b) -> a -> b
$ do
MutableByteArray s
marr <- forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
PM.newByteArray Int
len
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m)
-> Int -> ByteArray -> Int -> Int -> m ()
PM.copyByteArray MutableByteArray s
marr Int
0 ByteArray
src Int
start Int
len
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m) -> m ByteArray
PM.unsafeFreezeByteArray MutableByteArray s
marr
forall (f :: * -> *) a. Applicative f => a -> f a
pure
forall a b. (a -> b) -> a -> b
$ ShortByteString -> ShortText
TS.fromShortByteStringUnsafe
forall a b. (a -> b) -> a -> b
$ ByteArray -> ShortByteString
byteArrayToShortByteString
forall a b. (a -> b) -> a -> b
$ ByteArray
r
any :: e -> Parser e s Char
{-# inline any #-}
any :: forall e s. e -> Parser e s Char
any e
e = forall e a s. (Bytes -> Result e a) -> Parser e s a
uneffectful forall a b. (a -> b) -> a -> b
$ \Bytes
chunk -> if Bytes -> Int
length Bytes
chunk forall a. Ord a => a -> a -> Bool
> Int
0
then
let c :: Char
c = ByteArray -> Int -> Char
indexLatinCharArray (Bytes -> ByteArray
array Bytes
chunk) (Bytes -> Int
offset Bytes
chunk)
in if Char
c forall a. Ord a => a -> a -> Bool
< Char
'\128'
then forall e a. a -> Int -> Int -> Result e a
Success Char
c (Bytes -> Int
offset Bytes
chunk forall a. Num a => a -> a -> a
+ Int
1) (Bytes -> Int
length Bytes
chunk forall a. Num a => a -> a -> a
- Int
1)
else forall e a. e -> Result e a
Failure e
e
else forall e a. e -> Result e a
Failure e
e
any# :: e -> Parser e s Char#
{-# inline any# #-}
any# :: forall e s. e -> Parser e s Char#
any# e
e = forall e s a.
((# ByteArray#, Int#, Int# #) -> ST# s (Result# e a))
-> Parser e s a
Parser
(\(# ByteArray#
arr, Int#
off, Int#
len #) State# s
s0 -> case Int#
len of
Int#
0# -> (# State# s
s0, (# e
e | #) #)
Int#
_ ->
let !w :: Char#
w = ByteArray# -> Int# -> Char#
indexCharArray# ByteArray#
arr Int#
off
in case Char# -> Int#
ord# Char#
w Int# -> Int# -> Int#
<# Int#
128# of
Int#
1# -> (# State# s
s0, (# | (# Char#
w, Int#
off Int# -> Int# -> Int#
+# Int#
1#, Int#
len Int# -> Int# -> Int#
-# Int#
1# #) #) #)
Int#
_ -> (# State# s
s0, (# e
e | #) #)
)
unI :: Int -> Int#
{-# inline unI #-}
unI :: Int -> Int#
unI (I# Int#
w) = Int#
w
peek :: e -> Parser e s Char
{-# inline peek #-}
peek :: forall e s. e -> Parser e s Char
peek e
e = forall e a s. (Bytes -> Result e a) -> Parser e s a
uneffectful forall a b. (a -> b) -> a -> b
$ \Bytes
chunk -> if Bytes -> Int
length Bytes
chunk forall a. Ord a => a -> a -> Bool
> Int
0
then
let w :: Word8
w = forall a. Prim a => ByteArray -> Int -> a
PM.indexByteArray (Bytes -> ByteArray
array Bytes
chunk) (Bytes -> Int
offset Bytes
chunk) :: Word8
in if Word8
w forall a. Ord a => a -> a -> Bool
< Word8
128
then forall e a. a -> Int -> Int -> Result e a
Success
(Char# -> Char
C# (Int# -> Char#
chr# (Int -> Int#
unI (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w))))
(Bytes -> Int
offset Bytes
chunk)
(Bytes -> Int
length Bytes
chunk)
else forall e a. e -> Result e a
Failure e
e
else forall e a. e -> Result e a
Failure e
e
opt :: e -> Parser e s (Maybe Char)
{-# inline opt #-}
opt :: forall e s. e -> Parser e s (Maybe Char)
opt e
e = forall e a s. (Bytes -> Result e a) -> Parser e s a
uneffectful forall a b. (a -> b) -> a -> b
$ \Bytes
chunk -> if Bytes -> Int
length Bytes
chunk forall a. Ord a => a -> a -> Bool
> Int
0
then
let w :: Word8
w = forall a. Prim a => ByteArray -> Int -> a
PM.indexByteArray (Bytes -> ByteArray
array Bytes
chunk) (Bytes -> Int
offset Bytes
chunk) :: Word8
in if Word8
w forall a. Ord a => a -> a -> Bool
< Word8
128
then forall e a. a -> Int -> Int -> Result e a
Success
(forall a. a -> Maybe a
Just (Char# -> Char
C# (Int# -> Char#
chr# (Int -> Int#
unI (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w)))))
(Bytes -> Int
offset Bytes
chunk forall a. Num a => a -> a -> a
+ Int
1)
(Bytes -> Int
length Bytes
chunk forall a. Num a => a -> a -> a
- Int
1)
else forall e a. e -> Result e a
Failure e
e
else forall e a. a -> Int -> Int -> Result e a
Success forall a. Maybe a
Nothing (Bytes -> Int
offset Bytes
chunk) (Bytes -> Int
length Bytes
chunk)
skipWhile :: (Char -> Bool) -> Parser e s ()
{-# inline skipWhile #-}
skipWhile :: forall e s. (Char -> Bool) -> Parser e s ()
skipWhile Char -> Bool
p = forall e s a.
((# ByteArray#, Int#, Int# #) -> ST# s (Result# e a))
-> Parser e s a
Parser
( \(# ByteArray#
arr, Int#
off0, Int#
len0 #) State# s
s0 ->
let go :: Int# -> Int# -> (# (), Int#, Int# #)
go Int#
off Int#
len = case Int#
len of
Int#
0# -> (# (), Int#
off, Int#
0# #)
Int#
_ -> let c :: Char#
c = ByteArray# -> Int# -> Char#
indexCharArray# ByteArray#
arr Int#
off in
case Char -> Bool
p (Char# -> Char
C# Char#
c) of
Bool
True -> case Char# -> Char# -> Int#
gtChar# Char#
c Char#
'\x7F'# of
Int#
1# -> (# (), Int#
off, Int#
len #)
Int#
_ -> Int# -> Int# -> (# (), Int#, Int# #)
go (Int#
off Int# -> Int# -> Int#
+# Int#
1# ) (Int#
len Int# -> Int# -> Int#
-# Int#
1# )
Bool
False -> (# (), Int#
off, Int#
len #)
in (# State# s
s0, (# | Int# -> Int# -> (# (), Int#, Int# #)
go Int#
off0 Int#
len0 #) #)
)
skipAlpha :: Parser e s ()
{-# inline skipAlpha #-}
skipAlpha :: forall e s. Parser e s ()
skipAlpha = forall e a s. (Bytes -> Result# e a) -> Parser e s a
uneffectful# forall a b. (a -> b) -> a -> b
$ \Bytes
c ->
forall e. (# Int#, Int# #) -> Result# e ()
upcastUnitSuccess (Bytes -> (# Int#, Int# #)
skipAlphaAsciiLoop Bytes
c)
skipAlpha1 :: e -> Parser e s ()
{-# inline skipAlpha1 #-}
skipAlpha1 :: forall e s. e -> Parser e s ()
skipAlpha1 e
e = forall e a s. (Bytes -> Result# e a) -> Parser e s a
uneffectful# forall a b. (a -> b) -> a -> b
$ \Bytes
c ->
forall e. e -> Bytes -> Result# e ()
skipAlphaAsciiLoop1Start e
e Bytes
c
skipAlphaAsciiLoop ::
Bytes
-> (# Int#, Int# #)
{-# inline skipAlphaAsciiLoop #-}
skipAlphaAsciiLoop :: Bytes -> (# Int#, Int# #)
skipAlphaAsciiLoop !Bytes
c = if Bytes -> Int
length Bytes
c forall a. Ord a => a -> a -> Bool
> Int
0
then
let w :: Char
w = ByteArray -> Int -> Char
indexLatinCharArray (Bytes -> ByteArray
array Bytes
c) (Bytes -> Int
offset Bytes
c)
in if (Char
w forall a. Ord a => a -> a -> Bool
>= Char
'a' Bool -> Bool -> Bool
&& Char
w forall a. Ord a => a -> a -> Bool
<= Char
'z') Bool -> Bool -> Bool
|| (Char
w forall a. Ord a => a -> a -> Bool
>= Char
'A' Bool -> Bool -> Bool
&& Char
w forall a. Ord a => a -> a -> Bool
<= Char
'Z')
then Bytes -> (# Int#, Int# #)
skipAlphaAsciiLoop (Int -> Bytes -> Bytes
Bytes.unsafeDrop Int
1 Bytes
c)
else (# Int -> Int#
unI (Bytes -> Int
offset Bytes
c), Int -> Int#
unI (Bytes -> Int
length Bytes
c) #)
else (# Int -> Int#
unI (Bytes -> Int
offset Bytes
c), Int -> Int#
unI (Bytes -> Int
length Bytes
c) #)
skipAlphaAsciiLoop1Start ::
e
-> Bytes
-> Result# e ()
{-# inline skipAlphaAsciiLoop1Start #-}
skipAlphaAsciiLoop1Start :: forall e. e -> Bytes -> Result# e ()
skipAlphaAsciiLoop1Start e
e !Bytes
c = if Bytes -> Int
length Bytes
c forall a. Ord a => a -> a -> Bool
> Int
0
then
let w :: Char
w = ByteArray -> Int -> Char
indexLatinCharArray (Bytes -> ByteArray
array Bytes
c) (Bytes -> Int
offset Bytes
c)
in if (Char
w forall a. Ord a => a -> a -> Bool
>= Char
'a' Bool -> Bool -> Bool
&& Char
w forall a. Ord a => a -> a -> Bool
<= Char
'z') Bool -> Bool -> Bool
|| (Char
w forall a. Ord a => a -> a -> Bool
>= Char
'A' Bool -> Bool -> Bool
&& Char
w forall a. Ord a => a -> a -> Bool
<= Char
'Z')
then forall e. (# Int#, Int# #) -> Result# e ()
upcastUnitSuccess (Bytes -> (# Int#, Int# #)
skipAlphaAsciiLoop (Int -> Bytes -> Bytes
Bytes.unsafeDrop Int
1 Bytes
c))
else (# e
e | #)
else (# e
e | #)
byteArrayToShortByteString :: PM.ByteArray -> BSS.ShortByteString
{-# inline byteArrayToShortByteString #-}
byteArrayToShortByteString :: ByteArray -> ShortByteString
byteArrayToShortByteString (PM.ByteArray ByteArray#
x) = ByteArray# -> ShortByteString
BSS.SBS ByteArray#
x