{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE InstanceSigs          #-}
{-# LANGUAGE MultiParamTypeClasses #-}

module HaskellWorks.Data.Xml.Type where

import Data.Char
import Data.Word8                                as W8
import HaskellWorks.Data.Bits.BitWise
import HaskellWorks.Data.Drop
import HaskellWorks.Data.Positioning
import HaskellWorks.Data.RankSelect.Base.Rank0
import HaskellWorks.Data.RankSelect.Base.Rank1
import HaskellWorks.Data.RankSelect.Base.Select1
import HaskellWorks.Data.Xml.Succinct
import Prelude                                   hiding (drop)

import qualified Data.ByteString                  as BS
import qualified HaskellWorks.Data.BalancedParens as BP

{- HLINT ignore "Reduce duplication"  -}

data XmlType
  = XmlTypeElement
  | XmlTypeAttrList
  | XmlTypeToken
  deriving (XmlType -> XmlType -> Bool
(XmlType -> XmlType -> Bool)
-> (XmlType -> XmlType -> Bool) -> Eq XmlType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: XmlType -> XmlType -> Bool
$c/= :: XmlType -> XmlType -> Bool
== :: XmlType -> XmlType -> Bool
$c== :: XmlType -> XmlType -> Bool
Eq, Int -> XmlType -> ShowS
[XmlType] -> ShowS
XmlType -> String
(Int -> XmlType -> ShowS)
-> (XmlType -> String) -> ([XmlType] -> ShowS) -> Show XmlType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [XmlType] -> ShowS
$cshowList :: [XmlType] -> ShowS
show :: XmlType -> String
$cshow :: XmlType -> String
showsPrec :: Int -> XmlType -> ShowS
$cshowsPrec :: Int -> XmlType -> ShowS
Show)

class XmlTypeAt a where
  xmlTypeAtPosition :: Position -> a -> Maybe XmlType
  xmlTypeAt :: a -> Maybe XmlType

instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => XmlTypeAt (XmlCursor String v w) where
  xmlTypeAtPosition :: Position -> XmlCursor String v w -> Maybe XmlType
xmlTypeAtPosition Position
p XmlCursor String v w
k = case Count -> ShowS
forall v. Drop v => Count -> v -> v
drop (Position -> Count
forall a. ToCount a => a -> Count
toCount Position
p) (XmlCursor String v w -> String
forall t v w. XmlCursor t v w -> t
cursorText XmlCursor String v w
k) of
    Char
c:String
_ | Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_less     -> XmlType -> Maybe XmlType
forall a. a -> Maybe a
Just XmlType
XmlTypeElement
    Char
c:String
_ | Word8 -> Bool
W8.isSpace (Word8 -> Bool) -> Word8 -> Bool
forall a b. (a -> b) -> a -> b
$ Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c) -> XmlType -> Maybe XmlType
forall a. a -> Maybe a
Just XmlType
XmlTypeAttrList
    String
_                                       -> XmlType -> Maybe XmlType
forall a. a -> Maybe a
Just XmlType
XmlTypeToken

  xmlTypeAt :: XmlCursor String v w -> Maybe XmlType
xmlTypeAt XmlCursor String v w
k = Position -> XmlCursor String v w -> Maybe XmlType
forall a. XmlTypeAt a => Position -> a -> Maybe XmlType
xmlTypeAtPosition Position
p XmlCursor String v w
k
    where p :: Position
p   = Count -> Position
lastPositionOf (v -> Count -> Count
forall v. Select1 v => v -> Count -> Count
select1 v
ik (w -> Count -> Count
forall v. Rank1 v => v -> Count -> Count
rank1 w
bpk (XmlCursor String v w -> Count
forall t v w. XmlCursor t v w -> Count
cursorRank XmlCursor String v w
k)))
          ik :: v
ik  = XmlCursor String v w -> v
forall t v w. XmlCursor t v w -> v
interests XmlCursor String v w
k
          bpk :: w
bpk = XmlCursor String v w -> w
forall t v w. XmlCursor t v w -> w
balancedParens XmlCursor String v w
k

instance (BP.BalancedParens w, Rank0 w, Rank1 w, Select1 v, TestBit w) => XmlTypeAt (XmlCursor BS.ByteString v w) where
  xmlTypeAtPosition :: Position -> XmlCursor ByteString v w -> Maybe XmlType
xmlTypeAtPosition Position
p XmlCursor ByteString v w
k = case ByteString -> Maybe (Word8, ByteString)
BS.uncons (Count -> ByteString -> ByteString
forall v. Drop v => Count -> v -> v
drop (Position -> Count
forall a. ToCount a => a -> Count
toCount Position
p) (XmlCursor ByteString v w -> ByteString
forall t v w. XmlCursor t v w -> t
cursorText XmlCursor ByteString v w
k)) of
    Just (Word8
c, ByteString
_) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_less   -> XmlType -> Maybe XmlType
forall a. a -> Maybe a
Just XmlType
XmlTypeElement
    Just (Word8
c, ByteString
_) | Word8 -> Bool
W8.isSpace Word8
c -> XmlType -> Maybe XmlType
forall a. a -> Maybe a
Just XmlType
XmlTypeAttrList
    Maybe (Word8, ByteString)
_                          -> XmlType -> Maybe XmlType
forall a. a -> Maybe a
Just XmlType
XmlTypeToken

  xmlTypeAt :: XmlCursor ByteString v w -> Maybe XmlType
xmlTypeAt XmlCursor ByteString v w
k = Position -> XmlCursor ByteString v w -> Maybe XmlType
forall a. XmlTypeAt a => Position -> a -> Maybe XmlType
xmlTypeAtPosition Position
p XmlCursor ByteString v w
k
    where p :: Position
p   = Count -> Position
lastPositionOf (v -> Count -> Count
forall v. Select1 v => v -> Count -> Count
select1 v
ik (w -> Count -> Count
forall v. Rank1 v => v -> Count -> Count
rank1 w
bpk (XmlCursor ByteString v w -> Count
forall t v w. XmlCursor t v w -> Count
cursorRank XmlCursor ByteString v w
k)))
          ik :: v
ik  = XmlCursor ByteString v w -> v
forall t v w. XmlCursor t v w -> v
interests XmlCursor ByteString v w
k
          bpk :: w
bpk = XmlCursor ByteString v w -> w
forall t v w. XmlCursor t v w -> w
balancedParens XmlCursor ByteString v w
k