{-# LANGUAGE PatternSynonyms #-}
{-# OPTIONS_HADDOCK not-home #-}

-- | The bytes of UTF-8 encoded YAML and the classes of characters that the
-- parser, the renderer and the error messages share.
--
-- This module is intended for internal use only, and may change without warning
-- in subsequent releases.
module Yamlet.Internal.Chars
  ( -- * Characters
    pattern TAB
  , pattern LF
  , pattern CR
  , pattern SPACE
  , pattern EXCL
  , pattern DQUOTE
  , pattern HASH
  , pattern PERCENT
  , pattern AMP
  , pattern SQUOTE
  , pattern STAR
  , pattern PLUS
  , pattern COMMA
  , pattern MINUS
  , pattern DOT
  , pattern DIGIT_0
  , pattern DIGIT_1
  , pattern DIGIT_9
  , pattern COLON
  , pattern LESS
  , pattern GREATER
  , pattern QUESTION
  , pattern AT
  , pattern UPPER_A
  , pattern UPPER_F
  , pattern UPPER_Z
  , pattern LBRACKET
  , pattern BACKSLASH
  , pattern RBRACKET
  , pattern GRAVE
  , pattern LOWER_A
  , pattern LOWER_F
  , pattern LOWER_U
  , pattern LOWER_Z
  , pattern LBRACE
  , pattern PIPE
  , pattern RBRACE
  , pattern DEL
  , isWhite
  , isBreak
  , isAsciiByte
  , asciiChar
  , isCharStart
  , isNsChar
  , isFlowIndicator
  , isIndicator
  , isDecDigit
  , isHexDigit'
  , hexValue
  , isWordChar
  , isUriChar
  , isTagChar
  , isAnchorChar
  , bomLength
  , isBomIn
  , skipBomsIn
  ) where

import Data.Bits
import Data.Char
import Data.Text.Array qualified as A
import Data.Word

pattern
  TAB
  , LF
  , CR
  , SPACE
  , EXCL
  , DQUOTE
  , HASH
  , PERCENT
  , AMP
  , SQUOTE
  , STAR
  , PLUS
  , COMMA
  , MINUS
  , DOT
  , DIGIT_0
  , DIGIT_1
  , DIGIT_9
  , COLON
  , LESS
  , GREATER
  , QUESTION
  , AT
  , UPPER_A
  , UPPER_F
  , UPPER_Z
  , LBRACKET
  , BACKSLASH
  , RBRACKET
  , GRAVE
  , LOWER_A
  , LOWER_F
  , LOWER_U
  , LOWER_Z
  , LBRACE
  , PIPE
  , RBRACE
  , DEL
    :: Word8
pattern $bTAB :: Word8
$mTAB :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
TAB = 0x09
pattern $bLF :: Word8
$mLF :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
LF = 0x0A
pattern $bCR :: Word8
$mCR :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
CR = 0x0D
pattern $bSPACE :: Word8
$mSPACE :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
SPACE = 0x20
pattern $bEXCL :: Word8
$mEXCL :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
EXCL = 0x21
pattern $bDQUOTE :: Word8
$mDQUOTE :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
DQUOTE = 0x22
pattern $bHASH :: Word8
$mHASH :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
HASH = 0x23
pattern $bPERCENT :: Word8
$mPERCENT :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
PERCENT = 0x25
pattern $bAMP :: Word8
$mAMP :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
AMP = 0x26
pattern $bSQUOTE :: Word8
$mSQUOTE :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
SQUOTE = 0x27
pattern $bSTAR :: Word8
$mSTAR :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
STAR = 0x2A
pattern $bPLUS :: Word8
$mPLUS :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
PLUS = 0x2B
pattern $bCOMMA :: Word8
$mCOMMA :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
COMMA = 0x2C
pattern $bMINUS :: Word8
$mMINUS :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
MINUS = 0x2D
pattern $bDOT :: Word8
$mDOT :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
DOT = 0x2E
pattern $bDIGIT_0 :: Word8
$mDIGIT_0 :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
DIGIT_0 = 0x30
pattern $bDIGIT_1 :: Word8
$mDIGIT_1 :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
DIGIT_1 = 0x31
pattern $bDIGIT_9 :: Word8
$mDIGIT_9 :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
DIGIT_9 = 0x39
pattern $bCOLON :: Word8
$mCOLON :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
COLON = 0x3A
pattern $bLESS :: Word8
$mLESS :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
LESS = 0x3C
pattern $bGREATER :: Word8
$mGREATER :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
GREATER = 0x3E
pattern $bQUESTION :: Word8
$mQUESTION :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
QUESTION = 0x3F
pattern $bAT :: Word8
$mAT :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
AT = 0x40
pattern $bUPPER_A :: Word8
$mUPPER_A :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
UPPER_A = 0x41
pattern $bUPPER_F :: Word8
$mUPPER_F :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
UPPER_F = 0x46
pattern $bUPPER_Z :: Word8
$mUPPER_Z :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
UPPER_Z = 0x5A
pattern $bLBRACKET :: Word8
$mLBRACKET :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
LBRACKET = 0x5B
pattern $bBACKSLASH :: Word8
$mBACKSLASH :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
BACKSLASH = 0x5C
pattern $bRBRACKET :: Word8
$mRBRACKET :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
RBRACKET = 0x5D
pattern $bGRAVE :: Word8
$mGRAVE :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
GRAVE = 0x60
pattern $bLOWER_A :: Word8
$mLOWER_A :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
LOWER_A = 0x61
pattern $bLOWER_F :: Word8
$mLOWER_F :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
LOWER_F = 0x66
pattern $bLOWER_U :: Word8
$mLOWER_U :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
LOWER_U = 0x75
pattern $bLOWER_Z :: Word8
$mLOWER_Z :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
LOWER_Z = 0x7A
pattern $bLBRACE :: Word8
$mLBRACE :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
LBRACE = 0x7B
pattern $bPIPE :: Word8
$mPIPE :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
PIPE = 0x7C
pattern $bRBRACE :: Word8
$mRBRACE :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
RBRACE = 0x7D
pattern $bDEL :: Word8
$mDEL :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
DEL = 0x7F

isWhite :: Word8 -> Bool
isWhite :: Word8 -> Bool
isWhite Word8
w = Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
SPACE Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
TAB

isBreak :: Word8 -> Bool
isBreak :: Word8 -> Bool
isBreak Word8
w = Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
LF Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
CR

isAsciiByte :: Word8 -> Bool
isAsciiByte :: Word8 -> Bool
isAsciiByte Word8
w = Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
0x80

-- | A predicate on bytes for a character, e.g. 'isFlowIndicator' for the
-- emitter. A character beyond ASCII does not satisfy it.
asciiChar :: (Word8 -> Bool) -> Char -> Bool
asciiChar :: (Word8 -> Bool) -> Char -> Bool
asciiChar Word8 -> Bool
p Char
c = Char -> Bool
isAscii Char
c Bool -> Bool -> Bool
&& Word8 -> Bool
p (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c))

-- | The byte starts a character in UTF-8, i.e. it is not a continuation byte.
isCharStart :: Word8 -> Bool
isCharStart :: Word8 -> Bool
isCharStart Word8
w = Word8 -> Bool
isAsciiByte Word8
w Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0xC0

-- | ns-char. Every byte of a multibyte character counts, because the input
-- contains printable characters only, except in quoted scalars, which the
-- parser checks after it parses the stream.
isNsChar :: Word8 -> Bool
isNsChar :: Word8 -> Bool
isNsChar Word8
w = Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
SPACE Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
DEL

isFlowIndicator :: Word8 -> Bool
isFlowIndicator :: Word8 -> Bool
isFlowIndicator Word8
w =
  Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
COMMA
    Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
LBRACKET
    Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
RBRACKET
    Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
LBRACE
    Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
RBRACE

isIndicator :: Word8 -> Bool
isIndicator :: Word8 -> Bool
isIndicator Word8
w = Word8 -> Bool
isAsciiByte Word8
w Bool -> Bool -> Bool
&& Integer -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Integer
indicators (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w)
  where
    indicators :: Integer
    indicators :: Integer
indicators = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr @[] (\Char
c Integer
acc -> Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
setBit Integer
acc (Char -> Int
ord Char
c)) Integer
0 [Char]
"-?:,[]{}#&*!|>'\"%@`"

isDecDigit :: Word8 -> Bool
isDecDigit :: Word8 -> Bool
isDecDigit Word8
w = Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
DIGIT_0 Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
DIGIT_9

isHexDigit' :: Word8 -> Bool
isHexDigit' :: Word8 -> Bool
isHexDigit' Word8
w =
  Word8 -> Bool
isDecDigit Word8
w Bool -> Bool -> Bool
|| (Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
UPPER_A Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
UPPER_F) Bool -> Bool -> Bool
|| (Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
LOWER_A Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
LOWER_F)

hexValue :: Word8 -> Int
hexValue :: Word8 -> Int
hexValue Word8
w
  | Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
DIGIT_9 = Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
DIGIT_0)
  | Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
UPPER_F = Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
UPPER_A) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
10
  | Bool
otherwise = Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
LOWER_A) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
10

isWordChar :: Word8 -> Bool
isWordChar :: Word8 -> Bool
isWordChar Word8
w =
  Word8 -> Bool
isDecDigit Word8
w
    Bool -> Bool -> Bool
|| (Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
UPPER_A Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
UPPER_Z)
    Bool -> Bool -> Bool
|| (Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
LOWER_A Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
LOWER_Z)
    Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
MINUS

-- | ns-uri-char without the escaped characters.
isUriChar :: Word8 -> Bool
isUriChar :: Word8 -> Bool
isUriChar Word8
w = Word8 -> Bool
isWordChar Word8
w Bool -> Bool -> Bool
|| Word8
w Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8]
extra
  where
    extra :: [Word8]
    extra :: [Word8]
extra = (Char -> Word8) -> [Char] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> (Char -> Int) -> Char -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
ord) [Char]
"#;/?:@&=+$,_.!~*'()[]"

-- | ns-tag-char without the escaped characters.
isTagChar :: Word8 -> Bool
isTagChar :: Word8 -> Bool
isTagChar Word8
w = Word8 -> Bool
isUriChar Word8
w Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
EXCL Bool -> Bool -> Bool
&& Bool -> Bool
not (Word8 -> Bool
isFlowIndicator Word8
w)

isAnchorChar :: Word8 -> Bool
isAnchorChar :: Word8 -> Bool
isAnchorChar Word8
w = Word8 -> Bool
isNsChar Word8
w Bool -> Bool -> Bool
&& Bool -> Bool
not (Word8 -> Bool
isFlowIndicator Word8
w)

-- | The number of bytes of a byte order mark, U+FEFF in UTF-8.
bomLength :: Int
bomLength :: Int
bomLength = Int
3

-- | A byte order mark at the index of the array, before the end index.
isBomIn :: A.Array -> Int -> Int -> Bool
isBomIn :: Array -> Int -> Int -> Bool
isBomIn Array
arr Int
end Int
i =
  Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
bomLength Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
end
    Bool -> Bool -> Bool
&& Array -> Int -> Word8
A.unsafeIndex Array
arr Int
i Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xEF
    Bool -> Bool -> Bool
&& Array -> Int -> Word8
A.unsafeIndex Array
arr (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xBB
    Bool -> Bool -> Bool
&& Array -> Int -> Word8
A.unsafeIndex Array
arr (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xBF

-- | The index after the byte order marks at the index of the array, before
-- the end index.
skipBomsIn :: A.Array -> Int -> Int -> Int
skipBomsIn :: Array -> Int -> Int -> Int
skipBomsIn Array
arr Int
end Int
i = if Array -> Int -> Int -> Bool
isBomIn Array
arr Int
end Int
i then Array -> Int -> Int -> Int
skipBomsIn Array
arr Int
end (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
bomLength) else Int
i