{-|
Module      : HaskellWorks.Data.Dsv.Lazy.Cursor.Strict
Description : Extraction functions that yields strict bytestrings
-}
module HaskellWorks.Data.Dsv.Lazy.Cursor.Strict
  ( snippet
  , getRowListBetween
  , getRowVectorBetween
  , toListList
  , toListVector
  , toVectorVector
  ) where

import Data.Function
import HaskellWorks.Data.Dsv.Lazy.Cursor.Internal
import HaskellWorks.Data.Dsv.Lazy.Cursor.Type
import HaskellWorks.Data.RankSelect.Base.Rank1
import Prelude

import qualified Data.ByteString      as BS
import qualified Data.ByteString.Lazy as LBS
import qualified Data.List            as L
import qualified Data.Vector          as DV

{- HLINT ignore "Reduce duplication" -}

snippet :: DsvCursor -> Int -> BS.ByteString -> BS.ByteString
snippet :: DsvCursor -> Int -> ByteString -> ByteString
snippet DsvCursor
c Int
offset ByteString
bs = Int -> ByteString -> ByteString
BS.take (Int
len Int -> Int -> Int
forall a. Ord a => a -> a -> a
`max` Int
0) (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
BS.drop Int
posC ByteString
bs
  where d :: DsvCursor
d = DsvCursor -> DsvCursor
nextField DsvCursor
c
        posC :: Int
posC = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (DsvCursor -> Word64
dsvCursorPosition DsvCursor
c) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
offset
        posD :: Int
posD = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (DsvCursor -> Word64
dsvCursorPosition DsvCursor
d) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
offset
        len :: Int
len  = Int
posD Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
posC
{-# INLINE snippet #-}

getRowListBetween :: DsvCursor -> DsvCursor -> Bool -> [BS.ByteString]
getRowListBetween :: DsvCursor -> DsvCursor -> Bool -> [ByteString]
getRowListBetween DsvCursor
c DsvCursor
d Bool
dEnd = Int -> [ByteString] -> [ByteString]
forall a. Int -> [a] -> [a]
take Int
fields ((DsvCursor -> Maybe (ByteString, DsvCursor))
-> DsvCursor -> [ByteString]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
L.unfoldr DsvCursor -> Maybe (ByteString, DsvCursor)
go DsvCursor
c)
  where bsA :: Int64
bsA = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ DsvCursor -> Word64
dsvCursorPosition DsvCursor
c
        bsZ :: Int64
bsZ = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ DsvCursor -> Word64
dsvCursorPosition DsvCursor
d
        bsT :: ByteString
bsT = DsvCursor -> ByteString
dsvCursorText DsvCursor
c
        bs :: ByteString
bs  = ByteString -> ByteString
LBS.toStrict (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Int64 -> ByteString -> ByteString
LBS.take (Int64
bsZ Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int64
bsA) (Int64 -> ByteString -> ByteString
LBS.drop Int64
bsA ByteString
bsT)

        cr :: Word64
cr  = [Vector Word64] -> Word64 -> Word64
forall v. Rank1 v => v -> Word64 -> Word64
rank1 (DsvCursor -> [Vector Word64]
dsvCursorMarkers DsvCursor
c) (DsvCursor -> Word64
dsvCursorPosition DsvCursor
c)
        dr :: Word64
dr  = [Vector Word64] -> Word64 -> Word64
forall v. Rank1 v => v -> Word64 -> Word64
rank1 (DsvCursor -> [Vector Word64]
dsvCursorMarkers DsvCursor
d) (DsvCursor -> Word64
dsvCursorPosition DsvCursor
d)
        c2d :: Int
c2d = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
dr Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
cr)
        fields :: Int
fields = if Bool
dEnd then Int
c2d Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 else Int
c2d
        go :: DsvCursor -> Maybe (BS.ByteString, DsvCursor)
        go :: DsvCursor -> Maybe (ByteString, DsvCursor)
go DsvCursor
e = case DsvCursor -> DsvCursor
nextField DsvCursor
e of
          DsvCursor
f -> case DsvCursor -> DsvCursor
nextPosition DsvCursor
f of
            DsvCursor
g -> case DsvCursor -> Int -> ByteString -> ByteString
snippet DsvCursor
e (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
bsA) ByteString
bs of
              ByteString
s -> (ByteString, DsvCursor) -> Maybe (ByteString, DsvCursor)
forall a. a -> Maybe a
Just (ByteString
s, DsvCursor
g)
        {-# INLINE go #-}
{-# INLINE getRowListBetween #-}

getRowVectorBetween :: DsvCursor -> DsvCursor -> Bool -> DV.Vector BS.ByteString
getRowVectorBetween :: DsvCursor -> DsvCursor -> Bool -> Vector ByteString
getRowVectorBetween DsvCursor
c DsvCursor
d Bool
dEnd = Int
-> (DsvCursor -> Maybe (ByteString, DsvCursor))
-> DsvCursor
-> Vector ByteString
forall b a. Int -> (b -> Maybe (a, b)) -> b -> Vector a
DV.unfoldrN Int
fields DsvCursor -> Maybe (ByteString, DsvCursor)
go DsvCursor
c
  where bsA :: Int64
bsA = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ DsvCursor -> Word64
dsvCursorPosition DsvCursor
c
        bsZ :: Int64
bsZ = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ DsvCursor -> Word64
dsvCursorPosition DsvCursor
d
        bsT :: ByteString
bsT = DsvCursor -> ByteString
dsvCursorText DsvCursor
c
        bs :: ByteString
bs  = ByteString -> ByteString
LBS.toStrict (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Int64 -> ByteString -> ByteString
LBS.take (Int64
bsZ Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int64
bsA) (Int64 -> ByteString -> ByteString
LBS.drop Int64
bsA ByteString
bsT)

        cr :: Word64
cr  = [Vector Word64] -> Word64 -> Word64
forall v. Rank1 v => v -> Word64 -> Word64
rank1 (DsvCursor -> [Vector Word64]
dsvCursorMarkers DsvCursor
c) (DsvCursor -> Word64
dsvCursorPosition DsvCursor
c)
        dr :: Word64
dr  = [Vector Word64] -> Word64 -> Word64
forall v. Rank1 v => v -> Word64 -> Word64
rank1 (DsvCursor -> [Vector Word64]
dsvCursorMarkers DsvCursor
d) (DsvCursor -> Word64
dsvCursorPosition DsvCursor
d)
        c2d :: Int
c2d = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
dr Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
cr)
        fields :: Int
fields = if Bool
dEnd then Int
c2d Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 else Int
c2d
        go :: DsvCursor -> Maybe (BS.ByteString, DsvCursor)
        go :: DsvCursor -> Maybe (ByteString, DsvCursor)
go DsvCursor
e = case DsvCursor -> DsvCursor
nextField DsvCursor
e of
          DsvCursor
f -> case DsvCursor -> DsvCursor
nextPosition DsvCursor
f of
            DsvCursor
g -> case DsvCursor -> Int -> ByteString -> ByteString
snippet DsvCursor
e (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
bsA) ByteString
bs of
              ByteString
s -> (ByteString, DsvCursor) -> Maybe (ByteString, DsvCursor)
forall a. a -> Maybe a
Just (ByteString
s, DsvCursor
g)
        {-# INLINE go #-}
{-# INLINE getRowVectorBetween #-}

toListList :: DsvCursor -> [[BS.ByteString]]
toListList :: DsvCursor -> [[ByteString]]
toListList DsvCursor
c = if DsvCursor -> Word64
dsvCursorPosition DsvCursor
d Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> DsvCursor -> Word64
dsvCursorPosition DsvCursor
c Bool -> Bool -> Bool
&& Bool -> Bool
not (DsvCursor -> Bool
atEnd DsvCursor
c)
  then DsvCursor -> DsvCursor -> Bool -> [ByteString]
getRowListBetween DsvCursor
c DsvCursor
d Bool
dEnd[ByteString] -> [[ByteString]] -> [[ByteString]]
forall a. a -> [a] -> [a]
:DsvCursor -> [[ByteString]]
toListList (DsvCursor -> DsvCursor
trim DsvCursor
d)
  else []
  where nr :: DsvCursor
nr = DsvCursor -> DsvCursor
nextRow DsvCursor
c
        d :: DsvCursor
d = DsvCursor -> DsvCursor
nextPosition DsvCursor
nr
        dEnd :: Bool
dEnd = DsvCursor -> Bool
atEnd DsvCursor
nr
{-# INLINE toListList #-}

toListVector :: DsvCursor -> [DV.Vector BS.ByteString]
toListVector :: DsvCursor -> [Vector ByteString]
toListVector DsvCursor
c = if DsvCursor -> Word64
dsvCursorPosition DsvCursor
d Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> DsvCursor -> Word64
dsvCursorPosition DsvCursor
c Bool -> Bool -> Bool
&& Bool -> Bool
not (DsvCursor -> Bool
atEnd DsvCursor
c)
  then DsvCursor -> DsvCursor -> Bool -> Vector ByteString
getRowVectorBetween DsvCursor
c DsvCursor
d Bool
dEndVector ByteString -> [Vector ByteString] -> [Vector ByteString]
forall a. a -> [a] -> [a]
:DsvCursor -> [Vector ByteString]
toListVector (DsvCursor -> DsvCursor
trim DsvCursor
d)
  else []
  where nr :: DsvCursor
nr = DsvCursor -> DsvCursor
nextRow DsvCursor
c
        d :: DsvCursor
d = DsvCursor -> DsvCursor
nextPosition DsvCursor
nr
        dEnd :: Bool
dEnd = DsvCursor -> Bool
atEnd DsvCursor
nr
{-# INLINE toListVector #-}

toVectorVector :: DsvCursor -> DV.Vector (DV.Vector BS.ByteString)
toVectorVector :: DsvCursor -> Vector (Vector ByteString)
toVectorVector = [Vector ByteString] -> Vector (Vector ByteString)
forall a. [a] -> Vector a
DV.fromList ([Vector ByteString] -> Vector (Vector ByteString))
-> (DsvCursor -> [Vector ByteString])
-> DsvCursor
-> Vector (Vector ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DsvCursor -> [Vector ByteString]
toListVector
{-# INLINE toVectorVector #-}