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

import Data.Function
import Data.Word
import HaskellWorks.Data.Dsv.Lazy.Cursor.Internal
import HaskellWorks.Data.Dsv.Lazy.Cursor.Type
import HaskellWorks.Data.Vector.AsVector64s
import Prelude

import qualified Data.ByteString.Lazy                  as LBS
import qualified Data.Vector.Storable                  as DVS
import qualified HaskellWorks.Data.Dsv.Internal.Char   as C
import qualified HaskellWorks.Data.Dsv.Internal.Vector as DVS
import qualified HaskellWorks.Data.Simd.Comparison     as DVS

makeIndexes :: [DVS.Vector Word64] -> [DVS.Vector Word64] -> [DVS.Vector Word64] -> ([DVS.Vector Word64], [DVS.Vector Word64])
makeIndexes :: [Vector Word64]
-> [Vector Word64]
-> [Vector Word64]
-> ([Vector Word64], [Vector Word64])
makeIndexes [Vector Word64]
ds [Vector Word64]
ns [Vector Word64]
qs = [(Vector Word64, Vector Word64)]
-> ([Vector Word64], [Vector Word64])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(Vector Word64, Vector Word64)]
 -> ([Vector Word64], [Vector Word64]))
-> [(Vector Word64, Vector Word64)]
-> ([Vector Word64], [Vector Word64])
forall a b. (a -> b) -> a -> b
$ Word64
-> Word64
-> [Vector Word64]
-> [Vector Word64]
-> [Vector Word64]
-> [(Vector Word64, Vector Word64)]
go Word64
0 Word64
0 [Vector Word64]
ds [Vector Word64]
ns [Vector Word64]
qs
  where go :: Word64
-> Word64
-> [Vector Word64]
-> [Vector Word64]
-> [Vector Word64]
-> [(Vector Word64, Vector Word64)]
go Word64
pc Word64
carry (Vector Word64
dv:[Vector Word64]
dvs) (Vector Word64
nv:[Vector Word64]
nvs) (Vector Word64
qv:[Vector Word64]
qvs) =
          let (Vector Word64
dv', Vector Word64
nv', Word64
pc', Word64
carry') = Word64
-> Word64
-> Vector Word64
-> Vector Word64
-> Vector Word64
-> (Vector Word64, Vector Word64, Word64, Word64)
DVS.indexCsvChunk Word64
pc Word64
carry Vector Word64
dv Vector Word64
nv Vector Word64
qv in
          (Vector Word64
dv', Vector Word64
nv')(Vector Word64, Vector Word64)
-> [(Vector Word64, Vector Word64)]
-> [(Vector Word64, Vector Word64)]
forall a. a -> [a] -> [a]
:Word64
-> Word64
-> [Vector Word64]
-> [Vector Word64]
-> [Vector Word64]
-> [(Vector Word64, Vector Word64)]
go Word64
pc' Word64
carry' [Vector Word64]
dvs [Vector Word64]
nvs [Vector Word64]
qvs
        go Word64
_ Word64
_ [] [] [] = [(Vector Word64
DVS.empty64, Vector Word64
DVS.empty64)]
        go Word64
_ Word64
_ [Vector Word64]
_ [Vector Word64]
_ [Vector Word64]
_ = [Char] -> [(Vector Word64, Vector Word64)]
forall a. HasCallStack => [Char] -> a
error [Char]
"Unbalanced inputs"

makeCursor :: Word8 -> LBS.ByteString -> DsvCursor
makeCursor :: Word8 -> ByteString -> DsvCursor
makeCursor Word8
delimiter ByteString
lbs = DsvCursor
  { dsvCursorText :: ByteString
dsvCursorText      = ByteString
lbs
  , dsvCursorMarkers :: [Vector Word64]
dsvCursorMarkers   = [Vector Word64]
ib
  , dsvCursorNewlines :: [Vector Word64]
dsvCursorNewlines  = [Vector Word64]
nls
  , dsvCursorPosition :: Word64
dsvCursorPosition  = Word64
0
  }
  where ws :: [Vector Word64]
ws  = Int -> ByteString -> [Vector Word64]
forall a. AsVector64s a => Int -> a -> [Vector Word64]
asVector64s Int
64 ByteString
lbs
        ibq :: [Vector Word64]
ibq = Word8 -> Vector Word64 -> Vector Word64
forall a. CmpEqWord8s a => Word8 -> a -> a
DVS.cmpEqWord8s Word8
C.doubleQuote (Vector Word64 -> Vector Word64)
-> [Vector Word64] -> [Vector Word64]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Vector Word64]
ws
        ibn :: [Vector Word64]
ibn = Word8 -> Vector Word64 -> Vector Word64
forall a. CmpEqWord8s a => Word8 -> a -> a
DVS.cmpEqWord8s Word8
C.newline     (Vector Word64 -> Vector Word64)
-> [Vector Word64] -> [Vector Word64]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Vector Word64]
ws
        ibd :: [Vector Word64]
ibd = Word8 -> Vector Word64 -> Vector Word64
forall a. CmpEqWord8s a => Word8 -> a -> a
DVS.cmpEqWord8s Word8
delimiter     (Vector Word64 -> Vector Word64)
-> [Vector Word64] -> [Vector Word64]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Vector Word64]
ws
        ([Vector Word64]
ib, [Vector Word64]
nls) = [Vector Word64]
-> [Vector Word64]
-> [Vector Word64]
-> ([Vector Word64], [Vector Word64])
makeIndexes [Vector Word64]
ibd [Vector Word64]
ibn [Vector Word64]
ibq
{-# INLINE makeCursor #-}