{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE CPP #-}
module Basement.Alg.UTF8
( nextAscii
, nextAsciiDigit
, expectAscii
, next
, nextSkip
, nextWith
, prev
, prevSkip
, writeASCII
, writeUTF8
, toList
, all
, any
, foldr
, length
, reverse
) where
import GHC.Types
import GHC.Word
import GHC.Prim
import Data.Bits
import Data.Proxy
import Basement.Alg.Class
import Basement.Compat.Base hiding (toList)
import Basement.Compat.Primitive
import Basement.Monad
import Basement.Numerical.Additive
import Basement.Numerical.Subtractive
import Basement.Types.OffsetSize
import Basement.Types.Char7 (Char7(..))
import Basement.IntegralConv
import Basement.PrimType
import Basement.UTF8.Helper
import Basement.UTF8.Table
import Basement.UTF8.Types
nextAscii :: Indexable container Word8 => container -> Offset Word8 -> StepASCII
nextAscii :: forall container.
Indexable container Word8 =>
container -> Offset Word8 -> StepASCII
nextAscii container
ba Offset Word8
n = Word8 -> StepASCII
StepASCII Word8
w
where
!w :: Word8
w = forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n
{-# INLINE nextAscii #-}
nextAsciiDigit :: Indexable container Word8 => container -> Offset Word8 -> StepDigit
nextAsciiDigit :: forall container.
Indexable container Word8 =>
container -> Offset Word8 -> StepDigit
nextAsciiDigit container
ba Offset Word8
n = Word8 -> StepDigit
StepDigit (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n forall a. Subtractive a => a -> a -> Difference a
- Word8
0x30)
{-# INLINE nextAsciiDigit #-}
expectAscii :: Indexable container Word8 => container -> Offset Word8 -> Word8 -> Bool
expectAscii :: forall container.
Indexable container Word8 =>
container -> Offset Word8 -> Word8 -> Bool
expectAscii container
ba Offset Word8
n Word8
v = forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n forall a. Eq a => a -> a -> Bool
== Word8
v
{-# INLINE expectAscii #-}
next :: Indexable container Word8 => container -> Offset8 -> Step
next :: forall container.
Indexable container Word8 =>
container -> Offset Word8 -> Step
next container
ba Offset Word8
n =
case StepASCII -> Int
getNbBytes StepASCII
h of
Int
0 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Char
toChar1 StepASCII
h) (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
1)
Int
1 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Char
toChar2 StepASCII
h (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
1))) (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
2)
Int
2 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Word8 -> Char
toChar3 StepASCII
h (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
1))
(forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
2))) (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
3)
Int
3 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Word8 -> Word8 -> Char
toChar4 StepASCII
h (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
1))
(forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
2))
(forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
3))) (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
4)
Int
r -> forall a. HasCallStack => [Char] -> a
error ([Char]
"next: internal error: invalid input: offset=" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> [Char]
show Offset Word8
n forall a. Semigroup a => a -> a -> a
<> [Char]
" table=" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> [Char]
show Int
r forall a. Semigroup a => a -> a -> a
<> [Char]
" h=" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> [Char]
show (StepASCII -> Word8
stepAsciiRawValue StepASCII
h))
where
!h :: StepASCII
h = forall container.
Indexable container Word8 =>
container -> Offset Word8 -> StepASCII
nextAscii container
ba Offset Word8
n
{-# INLINE next #-}
nextSkip :: Indexable container Word8 => container -> Offset Word8 -> Offset Word8
nextSkip :: forall container.
Indexable container Word8 =>
container -> Offset Word8 -> Offset Word8
nextSkip container
ba Offset Word8
n = Offset Word8
n forall a. Additive a => a -> a -> a
+ Offset Word8
1 forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset (StepASCII -> Int
getNbBytes (forall container.
Indexable container Word8 =>
container -> Offset Word8 -> StepASCII
nextAscii container
ba Offset Word8
n))
{-# INLINE nextSkip #-}
nextWith :: Indexable container Word8
=> StepASCII
-> container
-> Offset8
-> Step
nextWith :: forall container.
Indexable container Word8 =>
StepASCII -> container -> Offset Word8 -> Step
nextWith StepASCII
h container
ba Offset Word8
n =
case StepASCII -> Int
getNbBytes StepASCII
h of
Int
1 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Char
toChar2 StepASCII
h (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n)) (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
1)
Int
2 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Word8 -> Char
toChar3 StepASCII
h (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n) (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
1))) (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
2)
Int
3 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Word8 -> Word8 -> Char
toChar4 StepASCII
h (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n)
(forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
1))
(forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
2))) (Offset Word8
n forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
3)
Int
r -> forall a. HasCallStack => [Char] -> a
error ([Char]
"nextWith: internal error: invalid input: offset=" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> [Char]
show Offset Word8
n forall a. Semigroup a => a -> a -> a
<> [Char]
" table=" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> [Char]
show Int
r forall a. Semigroup a => a -> a -> a
<> [Char]
" h=" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> [Char]
show (StepASCII -> Word8
stepAsciiRawValue StepASCII
h))
{-# INLINE nextWith #-}
prev :: Indexable container Word8 => container -> Offset Word8 -> StepBack
prev :: forall container.
Indexable container Word8 =>
container -> Offset Word8 -> StepBack
prev container
ba Offset Word8
offset =
case forall a b. IntegralUpsize a b => a -> b
integralUpsize forall a b. (a -> b) -> a -> b
$ forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
prevOfs1 of
(W# Word#
v1) | Word# -> Bool
isContinuationW# Word#
v1 -> Word# -> StepBack
atLeast2 (Word# -> Word#
maskContinuation# Word#
v1)
| Bool
otherwise -> Char -> Offset Word8 -> StepBack
StepBack (Word# -> Char
toChar# Word#
v1) Offset Word8
prevOfs1
where
sz1 :: CountOf ty
sz1 = forall ty. Int -> CountOf ty
CountOf Int
1
!prevOfs1 :: Offset Word8
prevOfs1 = Offset Word8
offset forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` forall {ty}. CountOf ty
sz1
prevOfs2 :: Offset Word8
prevOfs2 = Offset Word8
prevOfs1 forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` forall {ty}. CountOf ty
sz1
prevOfs3 :: Offset Word8
prevOfs3 = Offset Word8
prevOfs2 forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` forall {ty}. CountOf ty
sz1
prevOfs4 :: Offset Word8
prevOfs4 = Offset Word8
prevOfs3 forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` forall {ty}. CountOf ty
sz1
atLeast2 :: Word# -> StepBack
atLeast2 !Word#
v =
case forall a b. IntegralUpsize a b => a -> b
integralUpsize forall a b. (a -> b) -> a -> b
$ forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
prevOfs2 of
(W# Word#
v2) | Word# -> Bool
isContinuationW# Word#
v2 -> Word# -> StepBack
atLeast3 (Word# -> Word# -> Word#
or# (Word# -> Int# -> Word#
uncheckedShiftL# (Word# -> Word#
maskContinuation# Word#
v2) Int#
6#) Word#
v)
| Bool
otherwise -> Char -> Offset Word8 -> StepBack
StepBack (Word# -> Char
toChar# (Word# -> Word# -> Word#
or# (Word# -> Int# -> Word#
uncheckedShiftL# (Word# -> Word#
maskHeader2# Word#
v2) Int#
6#) Word#
v)) Offset Word8
prevOfs2
atLeast3 :: Word# -> StepBack
atLeast3 !Word#
v =
case forall a b. IntegralUpsize a b => a -> b
integralUpsize forall a b. (a -> b) -> a -> b
$ forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
prevOfs3 of
(W# Word#
v3) | Word# -> Bool
isContinuationW# Word#
v3 -> Word# -> StepBack
atLeast4 (Word# -> Word# -> Word#
or# (Word# -> Int# -> Word#
uncheckedShiftL# (Word# -> Word#
maskContinuation# Word#
v3) Int#
12#) Word#
v)
| Bool
otherwise -> Char -> Offset Word8 -> StepBack
StepBack (Word# -> Char
toChar# (Word# -> Word# -> Word#
or# (Word# -> Int# -> Word#
uncheckedShiftL# (Word# -> Word#
maskHeader3# Word#
v3) Int#
12#) Word#
v)) Offset Word8
prevOfs3
atLeast4 :: Word# -> StepBack
atLeast4 !Word#
v =
case forall a b. IntegralUpsize a b => a -> b
integralUpsize forall a b. (a -> b) -> a -> b
$ forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
prevOfs4 of
(W# Word#
v4) -> Char -> Offset Word8 -> StepBack
StepBack (Word# -> Char
toChar# (Word# -> Word# -> Word#
or# (Word# -> Int# -> Word#
uncheckedShiftL# (Word# -> Word#
maskHeader4# Word#
v4) Int#
18#) Word#
v)) Offset Word8
prevOfs4
prevSkip :: Indexable container Word8 => container -> Offset Word8 -> Offset Word8
prevSkip :: forall container.
Indexable container Word8 =>
container -> Offset Word8 -> Offset Word8
prevSkip container
ba Offset Word8
offset = Offset Word8 -> Offset Word8
loop (Offset Word8
offset forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` forall {ty}. CountOf ty
sz1)
where
sz1 :: CountOf ty
sz1 = forall ty. Int -> CountOf ty
CountOf Int
1
loop :: Offset Word8 -> Offset Word8
loop Offset Word8
o
| Word8 -> Bool
isContinuation (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
o) = Offset Word8 -> Offset Word8
loop (Offset Word8
o forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` forall {ty}. CountOf ty
sz1)
| Bool
otherwise = Offset Word8
o
writeASCII :: (PrimMonad prim, RandomAccess container prim Word8)
=> container -> Offset8 -> Char7 -> prim ()
writeASCII :: forall (prim :: * -> *) container.
(PrimMonad prim, RandomAccess container prim Word8) =>
container -> Offset Word8 -> Char7 -> prim ()
writeASCII container
mba !Offset Word8
i (Char7 Word8
c) = forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba Offset Word8
i Word8
c
{-# INLINE writeASCII #-}
writeUTF8 :: (PrimMonad prim, RandomAccess container prim Word8)
=> container -> Offset8 -> Char -> prim Offset8
writeUTF8 :: forall (prim :: * -> *) container.
(PrimMonad prim, RandomAccess container prim Word8) =>
container -> Offset Word8 -> Char -> prim (Offset Word8)
writeUTF8 container
mba !Offset Word8
i !Char
c
| Int# -> Bool
bool# (Word# -> Word# -> Int#
ltWord# Word#
x Word#
0x80## ) = prim (Offset Word8)
encode1
| Int# -> Bool
bool# (Word# -> Word# -> Int#
ltWord# Word#
x Word#
0x800## ) = prim (Offset Word8)
encode2
| Int# -> Bool
bool# (Word# -> Word# -> Int#
ltWord# Word#
x Word#
0x10000##) = prim (Offset Word8)
encode3
| Bool
otherwise = prim (Offset Word8)
encode4
where
!(I# Int#
xi) = forall a. Enum a => a -> Int
fromEnum Char
c
!x :: Word#
x = Int# -> Word#
int2Word# Int#
xi
encode1 :: prim (Offset Word8)
encode1 = forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba Offset Word8
i (Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# Word#
x)) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (f :: * -> *) a. Applicative f => a -> f a
pure (Offset Word8
i forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
1)
encode2 :: prim (Offset Word8)
encode2 = do
let x1 :: Word#
x1 = Word# -> Word# -> Word#
or# (Word# -> Int# -> Word#
uncheckedShiftRL# Word#
x Int#
6#) Word#
0xc0##
x2 :: Word#
x2 = Word# -> Word#
toContinuation Word#
x
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba Offset Word8
i (Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# Word#
x1))
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iforall a. Additive a => a -> a -> a
+Offset Word8
1) (Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# Word#
x2))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Offset Word8
i forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
2)
encode3 :: prim (Offset Word8)
encode3 = do
let x1 :: Word#
x1 = Word# -> Word# -> Word#
or# (Word# -> Int# -> Word#
uncheckedShiftRL# Word#
x Int#
12#) Word#
0xe0##
x2 :: Word#
x2 = Word# -> Word#
toContinuation (Word# -> Int# -> Word#
uncheckedShiftRL# Word#
x Int#
6#)
x3 :: Word#
x3 = Word# -> Word#
toContinuation Word#
x
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba Offset Word8
i (Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# Word#
x1))
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iforall a. Additive a => a -> a -> a
+forall ty. Int -> Offset ty
Offset Int
1) (Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# Word#
x2))
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iforall a. Additive a => a -> a -> a
+forall ty. Int -> Offset ty
Offset Int
2) (Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# Word#
x3))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Offset Word8
i forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
3)
encode4 :: prim (Offset Word8)
encode4 = do
let x1 :: Word#
x1 = Word# -> Word# -> Word#
or# (Word# -> Int# -> Word#
uncheckedShiftRL# Word#
x Int#
18#) Word#
0xf0##
x2 :: Word#
x2 = Word# -> Word#
toContinuation (Word# -> Int# -> Word#
uncheckedShiftRL# Word#
x Int#
12#)
x3 :: Word#
x3 = Word# -> Word#
toContinuation (Word# -> Int# -> Word#
uncheckedShiftRL# Word#
x Int#
6#)
x4 :: Word#
x4 = Word# -> Word#
toContinuation Word#
x
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba Offset Word8
i (Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# Word#
x1))
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iforall a. Additive a => a -> a -> a
+forall ty. Int -> Offset ty
Offset Int
1) (Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# Word#
x2))
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iforall a. Additive a => a -> a -> a
+forall ty. Int -> Offset ty
Offset Int
2) (Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# Word#
x3))
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iforall a. Additive a => a -> a -> a
+forall ty. Int -> Offset ty
Offset Int
3) (Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# Word#
x4))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Offset Word8
i forall a. Additive a => a -> a -> a
+ forall ty. Int -> Offset ty
Offset Int
4)
toContinuation :: Word# -> Word#
toContinuation :: Word# -> Word#
toContinuation Word#
w = Word# -> Word# -> Word#
or# (Word# -> Word# -> Word#
and# Word#
w Word#
0x3f##) Word#
0x80##
{-# INLINE writeUTF8 #-}
toList :: Indexable container Word8 => container -> Offset Word8 -> Offset Word8 -> [Char]
toList :: forall container.
Indexable container Word8 =>
container -> Offset Word8 -> Offset Word8 -> [Char]
toList container
ba !Offset Word8
start !Offset Word8
end = Offset Word8 -> [Char]
loop Offset Word8
start
where
loop :: Offset Word8 -> [Char]
loop !Offset Word8
idx
| Offset Word8
idx forall a. Eq a => a -> a -> Bool
== Offset Word8
end = []
| Bool
otherwise = Char
c forall a. a -> [a] -> [a]
: Offset Word8 -> [Char]
loop Offset Word8
idx'
where (Step Char
c Offset Word8
idx') = forall container.
Indexable container Word8 =>
container -> Offset Word8 -> Step
next container
ba Offset Word8
idx
all :: Indexable container Word8
=> (Char -> Bool) -> container -> Offset Word8 -> Offset Word8 -> Bool
all :: forall container.
Indexable container Word8 =>
(Char -> Bool) -> container -> Offset Word8 -> Offset Word8 -> Bool
all Char -> Bool
predicate container
ba Offset Word8
start Offset Word8
end = Offset Word8 -> Bool
loop Offset Word8
start
where
loop :: Offset Word8 -> Bool
loop !Offset Word8
idx
| Offset Word8
idx forall a. Eq a => a -> a -> Bool
== Offset Word8
end = Bool
True
| Char -> Bool
predicate Char
c = Offset Word8 -> Bool
loop Offset Word8
idx'
| Bool
otherwise = Bool
False
where (Step Char
c Offset Word8
idx') = forall container.
Indexable container Word8 =>
container -> Offset Word8 -> Step
next container
ba Offset Word8
idx
{-# INLINE all #-}
any :: Indexable container Word8
=> (Char -> Bool) -> container -> Offset Word8 -> Offset Word8 -> Bool
any :: forall container.
Indexable container Word8 =>
(Char -> Bool) -> container -> Offset Word8 -> Offset Word8 -> Bool
any Char -> Bool
predicate container
ba Offset Word8
start Offset Word8
end = Offset Word8 -> Bool
loop Offset Word8
start
where
loop :: Offset Word8 -> Bool
loop !Offset Word8
idx
| Offset Word8
idx forall a. Eq a => a -> a -> Bool
== Offset Word8
end = Bool
False
| Char -> Bool
predicate Char
c = Bool
True
| Bool
otherwise = Offset Word8 -> Bool
loop Offset Word8
idx'
where (Step Char
c Offset Word8
idx') = forall container.
Indexable container Word8 =>
container -> Offset Word8 -> Step
next container
ba Offset Word8
idx
{-# INLINE any #-}
foldr :: Indexable container Word8
=> container -> Offset Word8 -> Offset Word8 -> (Char -> a -> a) -> a -> a
foldr :: forall container a.
Indexable container Word8 =>
container
-> Offset Word8 -> Offset Word8 -> (Char -> a -> a) -> a -> a
foldr container
dat Offset Word8
start Offset Word8
end Char -> a -> a
f a
acc = Offset Word8 -> a
loop Offset Word8
start
where
loop :: Offset Word8 -> a
loop !Offset Word8
i
| Offset Word8
i forall a. Eq a => a -> a -> Bool
== Offset Word8
end = a
acc
| Bool
otherwise =
let (Step Char
c Offset Word8
i') = forall container.
Indexable container Word8 =>
container -> Offset Word8 -> Step
next container
dat Offset Word8
i
in Char
c Char -> a -> a
`f` Offset Word8 -> a
loop Offset Word8
i'
{-# INLINE foldr #-}
length :: (Indexable container Word8, Indexable container Word64)
=> container -> Offset Word8 -> Offset Word8 -> CountOf Char
length :: forall container.
(Indexable container Word8, Indexable container Word64) =>
container -> Offset Word8 -> Offset Word8 -> CountOf Char
length container
dat Offset Word8
start Offset Word8
end
| Offset Word8
start forall a. Eq a => a -> a -> Bool
== Offset Word8
end = CountOf Char
0
| Bool
otherwise = CountOf Char -> Offset Word8 -> CountOf Char
processStart CountOf Char
0 Offset Word8
start
where
end64 :: Offset Word64
end64 :: Offset Word64
end64 = forall a. PrimType a => Offset Word8 -> Offset a
offsetInElements Offset Word8
end
prx64 :: Proxy Word64
prx64 :: Proxy Word64
prx64 = forall {k} (t :: k). Proxy t
Proxy
mask64_80 :: Word64
mask64_80 :: Word64
mask64_80 = Word64
0x8080808080808080
processStart :: CountOf Char -> Offset Word8 -> CountOf Char
processStart :: CountOf Char -> Offset Word8 -> CountOf Char
processStart !CountOf Char
c !Offset Word8
i
| Offset Word8
i forall a. Eq a => a -> a -> Bool
== Offset Word8
end = CountOf Char
c
| forall a. PrimType a => Proxy a -> Offset Word8 -> Bool
offsetIsAligned Proxy Word64
prx64 Offset Word8
i = CountOf Char -> Offset Word64 -> CountOf Char
processAligned CountOf Char
c (forall a. PrimType a => Offset Word8 -> Offset a
offsetInElements Offset Word8
i)
| Bool
otherwise =
let h :: Word8
h = forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
dat Offset Word8
i
cont :: Bool
cont = (Word8
h forall a. Bits a => a -> a -> a
.&. Word8
0xc0) forall a. Eq a => a -> a -> Bool
== Word8
0x80
c' :: CountOf Char
c' = if Bool
cont then CountOf Char
c else CountOf Char
cforall a. Additive a => a -> a -> a
+CountOf Char
1
in CountOf Char -> Offset Word8 -> CountOf Char
processStart CountOf Char
c' (Offset Word8
iforall a. Additive a => a -> a -> a
+Offset Word8
1)
processAligned :: CountOf Char -> Offset Word64 -> CountOf Char
processAligned :: CountOf Char -> Offset Word64 -> CountOf Char
processAligned !CountOf Char
c !Offset Word64
i
| Offset Word64
i forall a. Ord a => a -> a -> Bool
>= Offset Word64
end64 = CountOf Char -> Offset Word8 -> CountOf Char
processEnd CountOf Char
c (forall a. PrimType a => Offset a -> Offset Word8
offsetInBytes Offset Word64
i)
| Bool
otherwise =
let !h :: Word64
h = forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
dat Offset Word64
i
!h80 :: Word64
h80 = Word64
h forall a. Bits a => a -> a -> a
.&. Word64
mask64_80
in if Word64
h80 forall a. Eq a => a -> a -> Bool
== Word64
0
then CountOf Char -> Offset Word64 -> CountOf Char
processAligned (CountOf Char
cforall a. Additive a => a -> a -> a
+CountOf Char
8) (Offset Word64
iforall a. Additive a => a -> a -> a
+Offset Word64
1)
else let !nbAscii :: CountOf Char
nbAscii = if Word64
h80 forall a. Eq a => a -> a -> Bool
== Word64
mask64_80 then CountOf Char
0 else forall ty. Int -> CountOf ty
CountOf (Int
8 forall a. Subtractive a => a -> a -> Difference a
- forall a. Bits a => a -> Int
popCount Word64
h80)
!nbHigh :: CountOf Char
nbHigh = forall ty. Int -> CountOf ty
CountOf forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> Int
popCount (Word64
h forall a. Bits a => a -> a -> a
.&. (Word64
h80 forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
1))
in CountOf Char -> Offset Word64 -> CountOf Char
processAligned (CountOf Char
c forall a. Additive a => a -> a -> a
+ CountOf Char
nbAscii forall a. Additive a => a -> a -> a
+ CountOf Char
nbHigh) (Offset Word64
iforall a. Additive a => a -> a -> a
+Offset Word64
1)
processEnd :: CountOf Char -> Offset Word8 -> CountOf Char
processEnd !CountOf Char
c !Offset Word8
i
| Offset Word8
i forall a. Eq a => a -> a -> Bool
== Offset Word8
end = CountOf Char
c
| Bool
otherwise =
let h :: Word8
h = forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
dat Offset Word8
i
cont :: Bool
cont = (Word8
h forall a. Bits a => a -> a -> a
.&. Word8
0xc0) forall a. Eq a => a -> a -> Bool
== Word8
0x80
c' :: CountOf Char
c' = if Bool
cont then CountOf Char
c else CountOf Char
cforall a. Additive a => a -> a -> a
+CountOf Char
1
in CountOf Char -> Offset Word8 -> CountOf Char
processStart CountOf Char
c' (Offset Word8
iforall a. Additive a => a -> a -> a
+Offset Word8
1)
{-# INLINE length #-}
reverse :: (PrimMonad prim, Indexable container Word8)
=> MutableByteArray# (PrimState prim)
-> Offset Word8
-> container
-> Offset Word8
-> Offset Word8
-> prim ()
reverse :: forall (prim :: * -> *) container.
(PrimMonad prim, Indexable container Word8) =>
MutableByteArray# (PrimState prim)
-> Offset Word8
-> container
-> Offset Word8
-> Offset Word8
-> prim ()
reverse MutableByteArray# (PrimState prim)
dst Offset Word8
dstOfs container
src Offset Word8
start Offset Word8
end
| Offset Word8
start forall a. Eq a => a -> a -> Bool
== Offset Word8
end = forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = Offset Word8 -> Offset Word8 -> prim ()
loop (Offset Word8
dstOfs forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` (forall a. Offset a -> CountOf a
offsetAsSize (Offset Word8
end forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
start)) forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
1) Offset Word8
start
where
loop :: Offset Word8 -> Offset Word8 -> prim ()
loop !Offset Word8
d !Offset Word8
s
| Offset Word8
s forall a. Eq a => a -> a -> Bool
== Offset Word8
end = forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| StepASCII -> Bool
headerIsAscii StepASCII
h = forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst Offset Word8
d (StepASCII -> Word8
stepAsciiRawValue StepASCII
h) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Offset Word8 -> Offset Word8 -> prim ()
loop (Offset Word8
d forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
1) (Offset Word8
s forall a. Additive a => a -> a -> a
+ Offset Word8
1)
| Bool
otherwise = do
case StepASCII -> Int
getNbBytes StepASCII
h of
Int
1 -> do
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
1) (StepASCII -> Word8
stepAsciiRawValue StepASCII
h)
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst Offset Word8
d (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s forall a. Additive a => a -> a -> a
+ Offset Word8
1))
Offset Word8 -> Offset Word8 -> prim ()
loop (Offset Word8
d forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
2) (Offset Word8
s forall a. Additive a => a -> a -> a
+ Offset Word8
2)
Int
2 -> do
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
2) (StepASCII -> Word8
stepAsciiRawValue StepASCII
h)
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
1) (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s forall a. Additive a => a -> a -> a
+ Offset Word8
1))
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst Offset Word8
d (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s forall a. Additive a => a -> a -> a
+ Offset Word8
2))
Offset Word8 -> Offset Word8 -> prim ()
loop (Offset Word8
d forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
3) (Offset Word8
s forall a. Additive a => a -> a -> a
+ Offset Word8
3)
Int
3 -> do
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
3) (StepASCII -> Word8
stepAsciiRawValue StepASCII
h)
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
2) (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s forall a. Additive a => a -> a -> a
+ Offset Word8
1))
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
1) (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s forall a. Additive a => a -> a -> a
+ Offset Word8
2))
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst Offset Word8
d (forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s forall a. Additive a => a -> a -> a
+ Offset Word8
3))
Offset Word8 -> Offset Word8 -> prim ()
loop (Offset Word8
d forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
4) (Offset Word8
s forall a. Additive a => a -> a -> a
+ Offset Word8
4)
Int
_ -> forall a. HasCallStack => [Char] -> a
error [Char]
"impossible"
where h :: StepASCII
h = forall container.
Indexable container Word8 =>
container -> Offset Word8 -> StepASCII
nextAscii container
src Offset Word8
s
{-# INLINE reverse #-}