module Text.HTML.Tagchup.Parser.Stream where

import Control.Monad.Trans.State (StateT(StateT), gets, put, )
import Control.Monad (guard, mzero, )
import qualified Data.List.HT as L

import qualified Data.ByteString.Char8      as BS
import qualified Data.ByteString.Lazy.Char8 as BL

import qualified Prelude as P
import Prelude hiding (Char, getChar, )


class C stream where
   getChar :: StateT stream Maybe P.Char


class Char char where
   toChar :: char -> P.Char

instance Char P.Char where
   toChar :: Char -> Char
toChar = forall a. a -> a
id


instance Char char => C [char] where
   getChar :: StateT [char] Maybe Char
getChar = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall char. Char char => char -> Char
toChar forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateT forall a. [a] -> Maybe (a, [a])
L.viewL

instance C BS.ByteString where
   getChar :: StateT ByteString Maybe Char
getChar = forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateT ByteString -> Maybe (Char, ByteString)
BS.uncons

instance C BL.ByteString where
   getChar :: StateT ByteString Maybe Char
getChar = forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateT ByteString -> Maybe (Char, ByteString)
BL.uncons


data PointerStrict =
   PointerStrict {PointerStrict -> ByteString
psSource :: !BS.ByteString, PointerStrict -> Int
psIndex :: !Int}

pointerFromByteStringStrict :: BS.ByteString -> PointerStrict
pointerFromByteStringStrict :: ByteString -> PointerStrict
pointerFromByteStringStrict ByteString
str =
   ByteString -> Int -> PointerStrict
PointerStrict ByteString
str Int
0

instance C PointerStrict where
   getChar :: StateT PointerStrict Maybe Char
getChar =
      do ByteString
s <- forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets PointerStrict -> ByteString
psSource
         Int
i <- forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets PointerStrict -> Int
psIndex
         forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Int
i forall a. Ord a => a -> a -> Bool
< ByteString -> Int
BS.length ByteString
s)
         forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put forall a b. (a -> b) -> a -> b
$ ByteString -> Int -> PointerStrict
PointerStrict ByteString
s (Int
iforall a. Num a => a -> a -> a
+Int
1)
         forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> Int -> Char
BS.index ByteString
s Int
i)



data PointerLazy =
   PointerLazy {PointerLazy -> [ByteString]
plSource :: ![BS.ByteString], PointerLazy -> Int
plIndex :: !Int}

pointerFromByteStringLazy :: BL.ByteString -> PointerLazy
pointerFromByteStringLazy :: ByteString -> PointerLazy
pointerFromByteStringLazy ByteString
str =
   [ByteString] -> Int -> PointerLazy
PointerLazy (ByteString -> [ByteString]
BL.toChunks ByteString
str) Int
0

instance C PointerLazy where
   getChar :: StateT PointerLazy Maybe Char
getChar =
      do [ByteString]
s <- forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets PointerLazy -> [ByteString]
plSource
         Int
i <- forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
gets PointerLazy -> Int
plIndex
         case [ByteString]
s of
            [] -> forall (m :: * -> *) a. MonadPlus m => m a
mzero
            (ByteString
c:[ByteString]
cs) ->
               if Int
i forall a. Ord a => a -> a -> Bool
< ByteString -> Int
BS.length ByteString
c
                 then forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put ([ByteString] -> Int -> PointerLazy
PointerLazy [ByteString]
s (Int
iforall a. Num a => a -> a -> a
+Int
1)) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> Int -> Char
BS.index ByteString
c Int
i)
                 else forall (m :: * -> *) s. Monad m => s -> StateT s m ()
put ([ByteString] -> Int -> PointerLazy
PointerLazy [ByteString]
cs (Int
i forall a. Num a => a -> a -> a
- ByteString -> Int
BS.length ByteString
c)) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall stream. C stream => StateT stream Maybe Char
getChar