{-# 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 :: container -> Offset Word8 -> StepASCII
nextAscii container
ba Offset Word8
n = Word8 -> StepASCII
StepASCII Word8
w
  where
    !w :: Word8
w = container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n
{-# INLINE nextAscii #-}

-- | nextAsciiBa specialized to get a digit between 0 and 9 (included)
nextAsciiDigit :: Indexable container Word8 => container -> Offset Word8 -> StepDigit
nextAsciiDigit :: container -> Offset Word8 -> StepDigit
nextAsciiDigit container
ba Offset Word8
n = Word8 -> StepDigit
StepDigit (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n Word8 -> Word8 -> Difference Word8
forall a. Subtractive a => a -> a -> Difference a
- Word8
0x30)
{-# INLINE nextAsciiDigit #-}

expectAscii :: Indexable container Word8 => container -> Offset Word8 -> Word8 -> Bool
expectAscii :: container -> Offset Word8 -> Word8 -> Bool
expectAscii container
ba Offset Word8
n Word8
v = container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
v
{-# INLINE expectAscii #-}

next :: Indexable container Word8 => container -> Offset8 -> Step
next :: 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 Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1)
        Int
1 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Char
toChar2 StepASCII
h (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1))) (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
2)
        Int
2 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Word8 -> Char
toChar3 StepASCII
h (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1))
                             (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
2))) (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
3)
        Int
3 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Word8 -> Word8 -> Char
toChar4 StepASCII
h (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1))
                             (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
2))
                             (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
3))) (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
4)
        Int
r -> [Char] -> Step
forall a. HasCallStack => [Char] -> a
error ([Char]
"next: internal error: invalid input: offset=" [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Offset Word8 -> [Char]
forall a. Show a => a -> [Char]
show Offset Word8
n [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" table=" [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Int -> [Char]
forall a. Show a => a -> [Char]
show Int
r [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" h=" [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Word8 -> [Char]
forall a. Show a => a -> [Char]
show (StepASCII -> Word8
stepAsciiRawValue StepASCII
h))
  where
    !h :: StepASCII
h = container -> Offset Word8 -> StepASCII
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 :: container -> Offset Word8 -> Offset Word8
nextSkip container
ba Offset Word8
n = Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
1 Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset (StepASCII -> Int
getNbBytes (container -> Offset Word8 -> StepASCII
forall container.
Indexable container Word8 =>
container -> Offset Word8 -> StepASCII
nextAscii container
ba Offset Word8
n))
{-# INLINE nextSkip #-}

-- | special case for only non ascii next'er function
nextWith :: Indexable container Word8
         => StepASCII
         -> container
         -> Offset8
         -> Step
nextWith :: 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 (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n)) (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1)
        Int
2 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Word8 -> Char
toChar3 StepASCII
h (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n) (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1))) (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
2)
        Int
3 -> Char -> Offset Word8 -> Step
Step (StepASCII -> Word8 -> Word8 -> Word8 -> Char
toChar4 StepASCII
h (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
n)
                             (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1))
                             (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
2))) (Offset Word8
n Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
3)
        Int
r -> [Char] -> Step
forall a. HasCallStack => [Char] -> a
error ([Char]
"nextWith: internal error: invalid input: offset=" [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Offset Word8 -> [Char]
forall a. Show a => a -> [Char]
show Offset Word8
n [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" table=" [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Int -> [Char]
forall a. Show a => a -> [Char]
show Int
r [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" h=" [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Word8 -> [Char]
forall a. Show a => a -> [Char]
show (StepASCII -> Word8
stepAsciiRawValue StepASCII
h))
{-# INLINE nextWith #-}

-- Given a non null offset, give the previous character and the offset of this character
-- will fail bad if apply at the beginning of string or an empty string.
prev :: Indexable container Word8 => container -> Offset Word8 -> StepBack
prev :: container -> Offset Word8 -> StepBack
prev container
ba Offset Word8
offset =
    case Word8 -> Word
forall a b. IntegralUpsize a b => a -> b
integralUpsize (Word8 -> Word) -> Word8 -> Word
forall a b. (a -> b) -> a -> b
$ container -> Offset Word8 -> Word8
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 = Int -> CountOf ty
forall ty. Int -> CountOf ty
CountOf Int
1
    !prevOfs1 :: Offset Word8
prevOfs1 = Offset Word8
offset Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` CountOf Word8
forall ty. CountOf ty
sz1
    prevOfs2 :: Offset Word8
prevOfs2 = Offset Word8
prevOfs1 Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` CountOf Word8
forall ty. CountOf ty
sz1
    prevOfs3 :: Offset Word8
prevOfs3 = Offset Word8
prevOfs2 Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` CountOf Word8
forall ty. CountOf ty
sz1
    prevOfs4 :: Offset Word8
prevOfs4 = Offset Word8
prevOfs3 Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` CountOf Word8
forall ty. CountOf ty
sz1
    atLeast2 :: Word# -> StepBack
atLeast2 !Word#
v  =
        case Word8 -> Word
forall a b. IntegralUpsize a b => a -> b
integralUpsize (Word8 -> Word) -> Word8 -> Word
forall a b. (a -> b) -> a -> b
$ container -> Offset Word8 -> Word8
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 Word8 -> Word
forall a b. IntegralUpsize a b => a -> b
integralUpsize (Word8 -> Word) -> Word8 -> Word
forall a b. (a -> b) -> a -> b
$ container -> Offset Word8 -> Word8
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 Word8 -> Word
forall a b. IntegralUpsize a b => a -> b
integralUpsize (Word8 -> Word) -> Word8 -> Word
forall a b. (a -> b) -> a -> b
$ container -> Offset Word8 -> Word8
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 :: container -> Offset Word8 -> Offset Word8
prevSkip container
ba Offset Word8
offset = Offset Word8 -> Offset Word8
loop (Offset Word8
offset Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` CountOf Word8
forall ty. CountOf ty
sz1)
  where
    sz1 :: CountOf ty
sz1 = Int -> CountOf ty
forall ty. Int -> CountOf ty
CountOf Int
1
    loop :: Offset Word8 -> Offset Word8
loop Offset Word8
o
        | Word8 -> Bool
isContinuation (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
ba Offset Word8
o) = Offset Word8 -> Offset Word8
loop (Offset Word8
o Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetMinusE` CountOf Word8
forall ty. CountOf ty
sz1)
        | Bool
otherwise                       = Offset Word8
o

writeASCII :: (PrimMonad prim, RandomAccess container prim Word8)
           => container -> Offset8 -> Char7 -> prim ()
writeASCII :: container -> Offset Word8 -> Char7 -> prim ()
writeASCII container
mba !Offset Word8
i (Char7 Word8
c) = container -> Offset Word8 -> Word8 -> prim ()
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 :: 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) = Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
c
    !x :: Word#
x       = Int# -> Word#
int2Word# Int#
xi

    encode1 :: prim (Offset Word8)
encode1 = container -> Offset Word8 -> Word8 -> prim ()
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba Offset Word8
i (Word# -> Word8
W8# (Word# -> Word#
wordToWord8# Word#
x)) prim () -> prim (Offset Word8) -> prim (Offset Word8)
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Offset Word8 -> prim (Offset Word8)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Offset Word8
i Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
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
        container -> Offset Word8 -> Word8 -> prim ()
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba Offset Word8
i     (Word# -> Word8
W8# (Word# -> Word#
wordToWord8# Word#
x1))
        container -> Offset Word8 -> Word8 -> prim ()
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iOffset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+Offset Word8
1) (Word# -> Word8
W8# (Word# -> Word#
wordToWord8# Word#
x2))
        Offset Word8 -> prim (Offset Word8)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Offset Word8
i Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
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
        container -> Offset Word8 -> Word8 -> prim ()
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba Offset Word8
i            (Word# -> Word8
W8# (Word# -> Word#
wordToWord8# Word#
x1))
        container -> Offset Word8 -> Word8 -> prim ()
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iOffset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1) (Word# -> Word8
W8# (Word# -> Word#
wordToWord8# Word#
x2))
        container -> Offset Word8 -> Word8 -> prim ()
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iOffset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
2) (Word# -> Word8
W8# (Word# -> Word#
wordToWord8# Word#
x3))
        Offset Word8 -> prim (Offset Word8)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Offset Word8
i Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
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
        container -> Offset Word8 -> Word8 -> prim ()
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba Offset Word8
i            (Word# -> Word8
W8# (Word# -> Word#
wordToWord8# Word#
x1))
        container -> Offset Word8 -> Word8 -> prim ()
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iOffset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1) (Word# -> Word8
W8# (Word# -> Word#
wordToWord8# Word#
x2))
        container -> Offset Word8 -> Word8 -> prim ()
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iOffset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
2) (Word# -> Word8
W8# (Word# -> Word#
wordToWord8# Word#
x3))
        container -> Offset Word8 -> Word8 -> prim ()
forall container (prim :: * -> *) ty.
RandomAccess container prim ty =>
container -> Offset ty -> ty -> prim ()
write container
mba (Offset Word8
iOffset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
3) (Word# -> Word8
W8# (Word# -> Word#
wordToWord8# Word#
x4))
        Offset Word8 -> prim (Offset Word8)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Offset Word8
i Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Int -> Offset Word8
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 :: 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 Offset Word8 -> Offset Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Offset Word8
end = []
        | Bool
otherwise  = Char
c Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: Offset Word8 -> [Char]
loop Offset Word8
idx'
      where (Step Char
c Offset Word8
idx') = container -> Offset Word8 -> Step
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 :: (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 Offset Word8 -> Offset Word8 -> Bool
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') = container -> Offset Word8 -> Step
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 :: (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 Offset Word8 -> Offset Word8 -> Bool
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') = container -> Offset Word8 -> Step
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 :: 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 Offset Word8 -> Offset Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Offset Word8
end  = a
acc
        | Bool
otherwise =
            let (Step Char
c Offset Word8
i') = container -> Offset Word8 -> Step
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 :: container -> Offset Word8 -> Offset Word8 -> CountOf Char
length container
dat Offset Word8
start Offset Word8
end
    | Offset Word8
start Offset Word8 -> Offset Word8 -> Bool
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 = Offset Word8 -> Offset Word64
forall a. PrimType a => Offset Word8 -> Offset a
offsetInElements Offset Word8
end

    prx64 :: Proxy Word64
    prx64 :: Proxy Word64
prx64 = Proxy Word64
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 Offset Word8 -> Offset Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Offset Word8
end                = CountOf Char
c
        | Proxy Word64 -> Offset Word8 -> Bool
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 (Offset Word8 -> Offset Word64
forall a. PrimType a => Offset Word8 -> Offset a
offsetInElements Offset Word8
i)
        | Bool
otherwise               =
            let h :: Word8
h    = container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
dat Offset Word8
i
                cont :: Bool
cont = (Word8
h Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0xc0) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x80
                c' :: CountOf Char
c'   = if Bool
cont then CountOf Char
c else CountOf Char
cCountOf Char -> CountOf Char -> CountOf Char
forall a. Additive a => a -> a -> a
+CountOf Char
1
             in CountOf Char -> Offset Word8 -> CountOf Char
processStart CountOf Char
c' (Offset Word8
iOffset Word8 -> Offset Word8 -> Offset Word8
forall 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 Offset Word64 -> Offset Word64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Offset Word64
end64 = CountOf Char -> Offset Word8 -> CountOf Char
processEnd CountOf Char
c (Offset Word64 -> Offset Word8
forall a. PrimType a => Offset a -> Offset Word8
offsetInBytes Offset Word64
i)
        | Bool
otherwise  =
            let !h :: Word64
h   = container -> Offset Word64 -> Word64
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
dat Offset Word64
i -- Word64
                !h80 :: Word64
h80 = Word64
h Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
mask64_80
             in if Word64
h80 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
0
                 then CountOf Char -> Offset Word64 -> CountOf Char
processAligned (CountOf Char
cCountOf Char -> CountOf Char -> CountOf Char
forall a. Additive a => a -> a -> a
+CountOf Char
8) (Offset Word64
iOffset Word64 -> Offset Word64 -> Offset Word64
forall a. Additive a => a -> a -> a
+Offset Word64
1)
                 else let !nbAscii :: CountOf Char
nbAscii = if Word64
h80 Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
mask64_80 then CountOf Char
0 else Int -> CountOf Char
forall ty. Int -> CountOf ty
CountOf (Int
8 Int -> Int -> Difference Int
forall a. Subtractive a => a -> a -> Difference a
- Word64 -> Int
forall a. Bits a => a -> Int
popCount Word64
h80)
                          !nbHigh :: CountOf Char
nbHigh  = Int -> CountOf Char
forall ty. Int -> CountOf ty
CountOf (Int -> CountOf Char) -> Int -> CountOf Char
forall a b. (a -> b) -> a -> b
$ Word64 -> Int
forall a. Bits a => a -> Int
popCount (Word64
h Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. (Word64
h80 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
1))
                       in CountOf Char -> Offset Word64 -> CountOf Char
processAligned (CountOf Char
c CountOf Char -> CountOf Char -> CountOf Char
forall a. Additive a => a -> a -> a
+ CountOf Char
nbAscii CountOf Char -> CountOf Char -> CountOf Char
forall a. Additive a => a -> a -> a
+ CountOf Char
nbHigh) (Offset Word64
iOffset Word64 -> Offset Word64 -> Offset Word64
forall 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 Offset Word8 -> Offset Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Offset Word8
end  = CountOf Char
c
        | Bool
otherwise =
            let h :: Word8
h    = container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
dat Offset Word8
i
                cont :: Bool
cont = (Word8
h Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0xc0) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x80
                c' :: CountOf Char
c'   = if Bool
cont then CountOf Char
c else CountOf Char
cCountOf Char -> CountOf Char -> CountOf Char
forall a. Additive a => a -> a -> a
+CountOf Char
1
             in CountOf Char -> Offset Word8 -> CountOf Char
processStart CountOf Char
c' (Offset Word8
iOffset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+Offset Word8
1)
{-# INLINE length #-}

reverse :: (PrimMonad prim, Indexable container Word8)
        => MutableByteArray# (PrimState prim) -- ^ Destination buffer
        -> Offset Word8                       -- ^ Destination start
        -> container                          -- ^ Source buffer
        -> Offset Word8                       -- ^ Source start
        -> Offset Word8                       -- ^ Source end
        -> prim ()
reverse :: 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 Offset Word8 -> Offset Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Offset Word8
end = () -> prim ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    | Bool
otherwise    = Offset Word8 -> Offset Word8 -> prim ()
loop (Offset Word8
dstOfs Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` (Offset Word8 -> CountOf Word8
forall a. Offset a -> CountOf a
offsetAsSize (Offset Word8
end Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
start)) Offset Word8 -> Offset Word8 -> Offset Word8
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 Offset Word8 -> Offset Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Offset Word8
end        = () -> prim ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        | StepASCII -> Bool
headerIsAscii StepASCII
h = MutableByteArray# (PrimState prim)
-> Offset Word8 -> Word8 -> prim ()
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) prim () -> prim () -> prim ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Offset Word8 -> Offset Word8 -> prim ()
loop (Offset Word8
d Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
1) (Offset Word8
s Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
1)
        | Bool
otherwise       = do
            case StepASCII -> Int
getNbBytes StepASCII
h of
                Int
1 -> do
                    MutableByteArray# (PrimState prim)
-> Offset Word8 -> Word8 -> prim ()
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
1) (StepASCII -> Word8
stepAsciiRawValue StepASCII
h)
                    MutableByteArray# (PrimState prim)
-> Offset Word8 -> Word8 -> prim ()
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst Offset Word8
d                 (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
1))
                    Offset Word8 -> Offset Word8 -> prim ()
loop (Offset Word8
d Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
2) (Offset Word8
s Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
2)
                Int
2 -> do
                    MutableByteArray# (PrimState prim)
-> Offset Word8 -> Word8 -> prim ()
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
2) (StepASCII -> Word8
stepAsciiRawValue StepASCII
h)
                    MutableByteArray# (PrimState prim)
-> Offset Word8 -> Word8 -> prim ()
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
1) (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
1))
                    MutableByteArray# (PrimState prim)
-> Offset Word8 -> Word8 -> prim ()
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst Offset Word8
d                 (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
2))
                    Offset Word8 -> Offset Word8 -> prim ()
loop (Offset Word8
d Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
3) (Offset Word8
s Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
3)
                Int
3 -> do
                    MutableByteArray# (PrimState prim)
-> Offset Word8 -> Word8 -> prim ()
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
3) (StepASCII -> Word8
stepAsciiRawValue StepASCII
h)
                    MutableByteArray# (PrimState prim)
-> Offset Word8 -> Word8 -> prim ()
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
2) (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
1))
                    MutableByteArray# (PrimState prim)
-> Offset Word8 -> Word8 -> prim ()
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst (Offset Word8
d Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
1) (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
2))
                    MutableByteArray# (PrimState prim)
-> Offset Word8 -> Word8 -> prim ()
forall ty (prim :: * -> *).
(PrimType ty, PrimMonad prim) =>
MutableByteArray# (PrimState prim) -> Offset ty -> ty -> prim ()
primMbaWrite MutableByteArray# (PrimState prim)
dst Offset Word8
d                 (container -> Offset Word8 -> Word8
forall container ty.
Indexable container ty =>
container -> Offset ty -> ty
index container
src (Offset Word8
s Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
3))
                    Offset Word8 -> Offset Word8 -> prim ()
loop (Offset Word8
d Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Offset a -> Offset a -> Offset a
`offsetSub` Offset Word8
4) (Offset Word8
s Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
4)
                Int
_ -> [Char] -> prim ()
forall a. HasCallStack => [Char] -> a
error [Char]
"impossible"
      where h :: StepASCII
h = container -> Offset Word8 -> StepASCII
forall container.
Indexable container Word8 =>
container -> Offset Word8 -> StepASCII
nextAscii container
src Offset Word8
s
{-# INLINE reverse #-}