{-# LANGUAGE ExplicitForAll   #-}
{-# LANGUAGE FlexibleContexts #-}

module HaskellWorks.Data.Dsv.Lazy.Cursor.Internal
  ( nextField
  , nextPosition
  , atEnd
  , nextRow
  , trim
  , advanceField
  ) where

import HaskellWorks.Data.Dsv.Lazy.Cursor.Type
import HaskellWorks.Data.Positioning
import HaskellWorks.Data.RankSelect.Base.Rank1
import HaskellWorks.Data.RankSelect.Base.Select1
import Prelude

import qualified Data.ByteString.Lazy as LBS

advanceField :: Count -> DsvCursor -> DsvCursor
advanceField :: Word64 -> DsvCursor -> DsvCursor
advanceField Word64
n DsvCursor
cursor = DsvCursor
cursor
  { dsvCursorPosition = newPos
  }
  where currentRank :: Word64
currentRank = [Vector Word64] -> Word64 -> Word64
forall v. Rank1 v => v -> Word64 -> Word64
rank1   (DsvCursor -> [Vector Word64]
dsvCursorMarkers DsvCursor
cursor) (DsvCursor -> Word64
dsvCursorPosition DsvCursor
cursor)
        newPos :: Word64
newPos      = [Vector Word64] -> Word64 -> Word64
forall v. Select1 v => v -> Word64 -> Word64
select1 (DsvCursor -> [Vector Word64]
dsvCursorMarkers DsvCursor
cursor) (Word64
currentRank Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
n) Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1
{-# INLINE advanceField #-}

nextField :: DsvCursor -> DsvCursor
nextField :: DsvCursor -> DsvCursor
nextField DsvCursor
cursor = DsvCursor
cursor
  { dsvCursorPosition = newPos
  }
  where currentRank :: Word64
currentRank = [Vector Word64] -> Word64 -> Word64
forall v. Rank1 v => v -> Word64 -> Word64
rank1   (DsvCursor -> [Vector Word64]
dsvCursorMarkers DsvCursor
cursor) (DsvCursor -> Word64
dsvCursorPosition DsvCursor
cursor)
        newPos :: Word64
newPos      = [Vector Word64] -> Word64 -> Word64
forall v. Select1 v => v -> Word64 -> Word64
select1 (DsvCursor -> [Vector Word64]
dsvCursorMarkers DsvCursor
cursor) (Word64
currentRank Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1) Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1
{-# INLINE nextField #-}

nextPosition :: DsvCursor -> DsvCursor
nextPosition :: DsvCursor -> DsvCursor
nextPosition DsvCursor
cursor = DsvCursor
cursor
    { dsvCursorPosition = if LBS.null (LBS.drop (fromIntegral newPos) (dsvCursorText cursor))
                            then fromIntegral (LBS.length (dsvCursorText cursor))
                            else newPos
    }
  where newPos :: Word64
newPos  = DsvCursor -> Word64
dsvCursorPosition DsvCursor
cursor Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1
{-# INLINE nextPosition #-}

atEnd :: DsvCursor -> Bool
atEnd :: DsvCursor -> Bool
atEnd DsvCursor
c = ByteString -> Bool
LBS.null (Int64 -> ByteString -> ByteString
LBS.drop (Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (DsvCursor -> Word64
dsvCursorPosition DsvCursor
c)) (DsvCursor -> ByteString
dsvCursorText DsvCursor
c))
{-# INLINE atEnd #-}

nextRow :: DsvCursor -> DsvCursor
nextRow :: DsvCursor -> DsvCursor
nextRow DsvCursor
cursor = DsvCursor
cursor
  { dsvCursorPosition = if newPos > dsvCursorPosition cursor
                          then newPos
                          else fromIntegral (LBS.length (dsvCursorText cursor))

  }
  where currentRank :: Word64
currentRank = [Vector Word64] -> Word64 -> Word64
forall v. Rank1 v => v -> Word64 -> Word64
rank1   (DsvCursor -> [Vector Word64]
dsvCursorNewlines DsvCursor
cursor) (DsvCursor -> Word64
dsvCursorPosition DsvCursor
cursor)
        newPos :: Word64
newPos      = [Vector Word64] -> Word64 -> Word64
forall v. Select1 v => v -> Word64 -> Word64
select1 (DsvCursor -> [Vector Word64]
dsvCursorNewlines DsvCursor
cursor) (Word64
currentRank Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1) Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1
{-# INLINE nextRow #-}

trim :: DsvCursor -> DsvCursor
trim :: DsvCursor -> DsvCursor
trim DsvCursor
c = if DsvCursor -> Word64
dsvCursorPosition DsvCursor
c Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word64
512
  then DsvCursor -> DsvCursor
trim DsvCursor
c
    { dsvCursorText     = LBS.drop 512 (dsvCursorText c)
    , dsvCursorMarkers  = drop 1 (dsvCursorMarkers c)
    , dsvCursorNewlines = drop 1 (dsvCursorNewlines c)
    , dsvCursorPosition = dsvCursorPosition c - 512
    }
  else DsvCursor
c
{-# INLINE trim #-}