{-| Module : HaskellWorks.Data.Dsv.Lazy.Cursor.Strict Description : Extraction functions that yields lazy bytestrings -} module HaskellWorks.Data.Dsv.Lazy.Cursor.Lazy ( snippet , getRowListBetween , getRowVectorBetween , toListList , toListVector , toVectorVector , selectListList , mapSelectListList ) 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.Lazy as LBS import qualified Data.List as L import qualified Data.Vector as DV {- HLINT ignore "Reduce duplication" -} snippet :: DsvCursor -> LBS.ByteString snippet c = LBS.take (len `max` 0) $ LBS.drop posC $ dsvCursorText c where d = nextField c posC = fromIntegral $ dsvCursorPosition c posD = fromIntegral $ dsvCursorPosition d len = posD - posC {-# INLINE snippet #-} getRowVectorBetween :: DsvCursor -> DsvCursor -> Bool -> DV.Vector LBS.ByteString getRowVectorBetween c d dEnd = DV.unfoldrN fields go c where cr = rank1 (dsvCursorMarkers c) (dsvCursorPosition c) dr = rank1 (dsvCursorMarkers d) (dsvCursorPosition d) c2d = fromIntegral (dr - cr) fields = if dEnd then c2d +1 else c2d go :: DsvCursor -> Maybe (LBS.ByteString, DsvCursor) go e = case nextField e of f -> case nextPosition f of g -> case snippet e of s -> Just (s, g) {-# INLINE go #-} {-# INLINE getRowVectorBetween #-} getRowListBetween :: DsvCursor -> DsvCursor -> Bool -> [LBS.ByteString] getRowListBetween c d dEnd = take fields (L.unfoldr go c) where cr = rank1 (dsvCursorMarkers c) (dsvCursorPosition c) dr = rank1 (dsvCursorMarkers d) (dsvCursorPosition d) c2d = fromIntegral (dr - cr) fields = if dEnd then c2d +1 else c2d go :: DsvCursor -> Maybe (LBS.ByteString, DsvCursor) go e = case nextField e of f -> case nextPosition f of g -> case snippet e of s -> Just (s, g) {-# INLINE go #-} {-# INLINE getRowListBetween #-} toListList :: DsvCursor -> [[LBS.ByteString]] toListList c = if dsvCursorPosition d > dsvCursorPosition c && not (atEnd c) then getRowListBetween c d dEnd:toListList (trim d) else [] where nr = nextRow c d = nextPosition nr dEnd = atEnd nr {-# INLINE toListList #-} toListVector :: DsvCursor -> [DV.Vector LBS.ByteString] toListVector c = if dsvCursorPosition d > dsvCursorPosition c && not (atEnd c) then getRowVectorBetween c d dEnd:toListVector (trim d) else [] where nr = nextRow c d = nextPosition nr dEnd = atEnd nr {-# INLINE toListVector #-} toVectorVector :: DsvCursor -> DV.Vector (DV.Vector LBS.ByteString) toVectorVector = DV.fromList . toListVector {-# INLINE toVectorVector #-} selectRowFrom :: [Int] -> DsvCursor -> [LBS.ByteString] selectRowFrom sel c = go <$> sel where go :: Int -> LBS.ByteString go n = snippet nc where nc = nextPosition (advanceField (fromIntegral n) c) {-# INLINE go #-} {-# INLINE selectRowFrom #-} mapSelectRowFrom :: [(Int, LBS.ByteString -> LBS.ByteString)] -> DsvCursor -> [LBS.ByteString] mapSelectRowFrom sel c = uncurry go <$> sel where go :: Int -> (LBS.ByteString -> LBS.ByteString) -> LBS.ByteString go n f = f (snippet nc) where nc = nextPosition (advanceField (fromIntegral n) c) {-# INLINE go #-} {-# INLINE mapSelectRowFrom #-} selectListList :: [Int] -> DsvCursor -> [[LBS.ByteString]] selectListList sel c = if dsvCursorPosition d > dsvCursorPosition c && not (atEnd c) then selectRowFrom sel c:selectListList sel (trim d) else [] where nr = nextRow c d = nextPosition nr {-# INLINE selectListList #-} mapSelectListList :: [(Int, LBS.ByteString -> LBS.ByteString)] -> DsvCursor -> [[LBS.ByteString]] mapSelectListList sel c = if dsvCursorPosition d > dsvCursorPosition c && not (atEnd c) then mapSelectRowFrom sel c:mapSelectListList sel (trim d) else [] where nr = nextRow c d = nextPosition nr {-# INLINE mapSelectListList #-}