module HaskellWorks.Data.Xml.Internal.BalancedParens
  ( blankedXmlToBalancedParens
  ) where

import Data.ByteString (ByteString)
import Data.Word
import Data.Word8

import qualified Data.ByteString as BS

data MiniBP = MiniN | MiniT | MiniF | MiniTF

blankedXmlToBalancedParens :: [ByteString] -> [ByteString]
blankedXmlToBalancedParens :: [ByteString] -> [ByteString]
blankedXmlToBalancedParens [ByteString]
is = case [ByteString]
is of
  (ByteString
bs:[ByteString]
bss) -> do
    let (ByteString
cs, Maybe (Maybe Bool, ByteString)
_) = Int
-> ((Maybe Bool, ByteString)
    -> Maybe (Word8, (Maybe Bool, ByteString)))
-> (Maybe Bool, ByteString)
-> (ByteString, Maybe (Maybe Bool, ByteString))
forall a.
Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
BS.unfoldrN (ByteString -> Int
BS.length ByteString
bs Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2) (Maybe Bool, ByteString) -> Maybe (Word8, (Maybe Bool, ByteString))
gen (Maybe Bool
forall a. Maybe a
Nothing, ByteString
bs)
    ByteString
csByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString] -> [ByteString]
blankedXmlToBalancedParens [ByteString]
bss
  [] -> []
  where gen :: (Maybe Bool, ByteString) -> Maybe (Word8, (Maybe Bool, ByteString))
        gen :: (Maybe Bool, ByteString) -> Maybe (Word8, (Maybe Bool, ByteString))
gen (Just Bool
True  , ByteString
bs) = (Word8, (Maybe Bool, ByteString))
-> Maybe (Word8, (Maybe Bool, ByteString))
forall a. a -> Maybe a
Just (Word8
0xFF, (Maybe Bool
forall a. Maybe a
Nothing, ByteString
bs))
        gen (Just Bool
False , ByteString
bs) = (Word8, (Maybe Bool, ByteString))
-> Maybe (Word8, (Maybe Bool, ByteString))
forall a. a -> Maybe a
Just (Word8
0x00, (Maybe Bool
forall a. Maybe a
Nothing, ByteString
bs))
        gen (Maybe Bool
Nothing    , ByteString
bs) = case ByteString -> Maybe (Word8, ByteString)
BS.uncons ByteString
bs of
          Just (Word8
c, ByteString
cs) -> case Word8 -> MiniBP
balancedParensOf Word8
c of
            MiniBP
MiniN  -> (Maybe Bool, ByteString) -> Maybe (Word8, (Maybe Bool, ByteString))
gen         (Maybe Bool
forall a. Maybe a
Nothing    , ByteString
cs)
            MiniBP
MiniT  -> (Word8, (Maybe Bool, ByteString))
-> Maybe (Word8, (Maybe Bool, ByteString))
forall a. a -> Maybe a
Just (Word8
0xFF, (Maybe Bool
forall a. Maybe a
Nothing    , ByteString
cs))
            MiniBP
MiniF  -> (Word8, (Maybe Bool, ByteString))
-> Maybe (Word8, (Maybe Bool, ByteString))
forall a. a -> Maybe a
Just (Word8
0x00, (Maybe Bool
forall a. Maybe a
Nothing    , ByteString
cs))
            MiniBP
MiniTF -> (Word8, (Maybe Bool, ByteString))
-> Maybe (Word8, (Maybe Bool, ByteString))
forall a. a -> Maybe a
Just (Word8
0xFF, (Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False , ByteString
cs))
          Maybe (Word8, ByteString)
Nothing   -> Maybe (Word8, (Maybe Bool, ByteString))
forall a. Maybe a
Nothing

balancedParensOf :: Word8 -> MiniBP
balancedParensOf :: Word8 -> MiniBP
balancedParensOf Word8
c = case Word8
c of
    Word8
d | Word8
d Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_less         -> MiniBP
MiniT
    Word8
d | Word8
d Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_greater      -> MiniBP
MiniF
    Word8
d | Word8
d Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_bracketleft  -> MiniBP
MiniT
    Word8
d | Word8
d Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_bracketright -> MiniBP
MiniF
    Word8
d | Word8
d Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_parenleft    -> MiniBP
MiniT
    Word8
d | Word8
d Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_parenright   -> MiniBP
MiniF
    Word8
d | Word8
d Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_t            -> MiniBP
MiniTF
    Word8
d | Word8
d Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_a            -> MiniBP
MiniTF
    Word8
d | Word8
d Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_v            -> MiniBP
MiniTF
    Word8
_                      -> MiniBP
MiniN