{-# LANGUAGE BangPatterns #-}
module DataFrame.IO.CSV.Internal.Sink (
Env (..),
MissingMode (..),
Sink (..),
SliceCol,
Cells (..),
cellAt,
withCell,
newSliceCol,
feedSink,
nullSink,
freezeCells,
sliceBS,
) where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Unsafe as BSU
import qualified Data.IntMap.Strict as IM
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import Control.Monad.ST (RealWorld, stToIO)
import Data.IORef
import Data.Word (Word8)
import DataFrame.IO.CSV.Internal.Scanner
import DataFrame.Internal.ColumnBuilder
import DataFrame.Internal.Parsing.Fast (
isMissingFieldSlice,
parseDoubleFieldSlice,
parseIntFieldSlice,
)
import Foreign.Ptr (Ptr, castPtr, plusPtr)
data MissingMode = MissNone | MissCanonical | MissCustom
data Env = Env
{ Env -> ByteString
envBS :: !BS.ByteString
, Env -> Ptr Word8
envPtr :: !(Ptr Word8)
, Env -> MissingMode
envMode :: !MissingMode
, Env -> [Text]
envTexts :: ![T.Text]
}
data Sink
= SinkInt !(IntBuilder RealWorld)
| SinkDouble !(DoubleBuilder RealWorld)
| SinkText !(TextBuilder RealWorld)
| SinkBS !SliceCol
data SliceCol = SliceCol
{ SliceCol -> IORef (IOVector Int)
scOffs :: !(IORef (VUM.IOVector Int))
, SliceCol -> IORef (IOVector Word8)
scValid :: !(IORef (VUM.IOVector Word8))
, SliceCol -> IORef (IntMap ByteString)
scEsc :: !(IORef (IM.IntMap BS.ByteString))
}
data Cells = Cells
{ Cells -> ByteString
cBS :: !BS.ByteString
, Cells -> Vector Int
cOffs :: !(VU.Vector Int)
, Cells -> IntMap ByteString
cEsc :: !(IM.IntMap BS.ByteString)
, Cells -> Vector Word8
cValid :: !(VU.Vector Word8)
, Cells -> Int
cLen :: !Int
}
withCell :: Cells -> Int -> (BS.ByteString -> Int -> Int -> r) -> r
withCell :: forall r. Cells -> Int -> (ByteString -> Int -> Int -> r) -> r
withCell Cells
c !Int
i ByteString -> Int -> Int -> r
k =
let s :: Int
s = Vector Int -> Int -> Int
forall a. Unbox a => Vector a -> Int -> a
VU.unsafeIndex (Cells -> Vector Int
cOffs Cells
c) (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i)
e :: Int
e = Vector Int -> Int -> Int
forall a. Unbox a => Vector a -> Int -> a
VU.unsafeIndex (Cells -> Vector Int
cOffs Cells
c) (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
in if Int
s Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0
then ByteString -> Int -> Int -> r
k (Cells -> ByteString
cBS Cells
c) Int
s Int
e
else let cell :: ByteString
cell = Cells -> IntMap ByteString
cEsc Cells
c IntMap ByteString -> Int -> ByteString
forall a. IntMap a -> Int -> a
IM.! Int
e in ByteString -> Int -> Int -> r
k ByteString
cell Int
0 (ByteString -> Int
BS.length ByteString
cell)
{-# INLINE withCell #-}
cellAt :: Cells -> Int -> BS.ByteString
cellAt :: Cells -> Int -> ByteString
cellAt Cells
c Int
i = Cells
-> Int -> (ByteString -> Int -> Int -> ByteString) -> ByteString
forall r. Cells -> Int -> (ByteString -> Int -> Int -> r) -> r
withCell Cells
c Int
i ByteString -> Int -> Int -> ByteString
sliceBS
{-# INLINE cellAt #-}
newSliceCol :: Int -> IO SliceCol
newSliceCol :: Int -> IO SliceCol
newSliceCol Int
hint = do
let cap :: Int
cap = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
16 Int
hint
IOVector Int
offs <- Int -> IO (MVector (PrimState IO) Int)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
Int -> m (MVector (PrimState m) a)
VUM.unsafeNew (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
cap)
IOVector Word8
val <- Int -> IO (MVector (PrimState IO) Word8)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
Int -> m (MVector (PrimState m) a)
VUM.unsafeNew Int
cap
IORef (IOVector Int)
-> IORef (IOVector Word8) -> IORef (IntMap ByteString) -> SliceCol
SliceCol (IORef (IOVector Int)
-> IORef (IOVector Word8) -> IORef (IntMap ByteString) -> SliceCol)
-> IO (IORef (IOVector Int))
-> IO
(IORef (IOVector Word8) -> IORef (IntMap ByteString) -> SliceCol)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IOVector Int -> IO (IORef (IOVector Int))
forall a. a -> IO (IORef a)
newIORef IOVector Int
offs IO
(IORef (IOVector Word8) -> IORef (IntMap ByteString) -> SliceCol)
-> IO (IORef (IOVector Word8))
-> IO (IORef (IntMap ByteString) -> SliceCol)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IOVector Word8 -> IO (IORef (IOVector Word8))
forall a. a -> IO (IORef a)
newIORef IOVector Word8
val IO (IORef (IntMap ByteString) -> SliceCol)
-> IO (IORef (IntMap ByteString)) -> IO SliceCol
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IntMap ByteString -> IO (IORef (IntMap ByteString))
forall a. a -> IO (IORef a)
newIORef IntMap ByteString
forall a. IntMap a
IM.empty
appendSliceCol :: SliceCol -> Int -> Int -> Int -> Word8 -> IO ()
appendSliceCol :: SliceCol -> Int -> Int -> Int -> Word8 -> IO ()
appendSliceCol (SliceCol IORef (IOVector Int)
oRef IORef (IOVector Word8)
vRef IORef (IntMap ByteString)
_) !Int
row !Int
s !Int
e !Word8
ok = do
IOVector Int
offs <- IORef (IOVector Int) -> IO (IOVector Int)
forall a. IORef a -> IO a
readIORef IORef (IOVector Int)
oRef
IOVector Int
offs' <-
if Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
row Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< IOVector Int -> Int
forall a s. Unbox a => MVector s a -> Int
VUM.length IOVector Int
offs
then IOVector Int -> IO (IOVector Int)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure IOVector Int
offs
else do
IOVector Int
o <- MVector (PrimState IO) Int
-> Int -> IO (MVector (PrimState IO) Int)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
VUM.unsafeGrow IOVector Int
MVector (PrimState IO) Int
offs (IOVector Int -> Int
forall a s. Unbox a => MVector s a -> Int
VUM.length IOVector Int
offs)
IORef (IOVector Int) -> IOVector Int -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef (IOVector Int)
oRef IOVector Int
o
IOVector Int -> IO (IOVector Int)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure IOVector Int
o
MVector (PrimState IO) Int -> Int -> Int -> IO ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite IOVector Int
MVector (PrimState IO) Int
offs' (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
row) Int
s
MVector (PrimState IO) Int -> Int -> Int -> IO ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite IOVector Int
MVector (PrimState IO) Int
offs' (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
row Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int
e
IOVector Word8
val <- IORef (IOVector Word8) -> IO (IOVector Word8)
forall a. IORef a -> IO a
readIORef IORef (IOVector Word8)
vRef
IOVector Word8
val' <-
if Int
row Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< IOVector Word8 -> Int
forall a s. Unbox a => MVector s a -> Int
VUM.length IOVector Word8
val
then IOVector Word8 -> IO (IOVector Word8)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure IOVector Word8
val
else do
IOVector Word8
v <- MVector (PrimState IO) Word8
-> Int -> IO (MVector (PrimState IO) Word8)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
VUM.unsafeGrow IOVector Word8
MVector (PrimState IO) Word8
val (IOVector Word8 -> Int
forall a s. Unbox a => MVector s a -> Int
VUM.length IOVector Word8
val)
IORef (IOVector Word8) -> IOVector Word8 -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef (IOVector Word8)
vRef IOVector Word8
v
IOVector Word8 -> IO (IOVector Word8)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure IOVector Word8
v
MVector (PrimState IO) Word8 -> Int -> Word8 -> IO ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite IOVector Word8
MVector (PrimState IO) Word8
val' Int
row Word8
ok
{-# INLINE appendSliceCol #-}
freezeCells :: BS.ByteString -> SliceCol -> Int -> IO Cells
freezeCells :: ByteString -> SliceCol -> Int -> IO Cells
freezeCells ByteString
bs (SliceCol IORef (IOVector Int)
oRef IORef (IOVector Word8)
vRef IORef (IntMap ByteString)
eRef) Int
n = do
IOVector Int
offs <- IORef (IOVector Int) -> IO (IOVector Int)
forall a. IORef a -> IO a
readIORef IORef (IOVector Int)
oRef
IOVector Word8
val <- IORef (IOVector Word8) -> IO (IOVector Word8)
forall a. IORef a -> IO a
readIORef IORef (IOVector Word8)
vRef
IntMap ByteString
esc <- IORef (IntMap ByteString) -> IO (IntMap ByteString)
forall a. IORef a -> IO a
readIORef IORef (IntMap ByteString)
eRef
ByteString
-> Vector Int -> IntMap ByteString -> Vector Word8 -> Int -> Cells
Cells ByteString
bs
(Vector Int -> IntMap ByteString -> Vector Word8 -> Int -> Cells)
-> IO (Vector Int)
-> IO (IntMap ByteString -> Vector Word8 -> Int -> Cells)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MVector (PrimState IO) Int -> IO (Vector Int)
forall a (m :: * -> *).
(Unbox a, PrimMonad m) =>
MVector (PrimState m) a -> m (Vector a)
VU.freeze (Int -> Int -> IOVector Int -> IOVector Int
forall a s. Unbox a => Int -> Int -> MVector s a -> MVector s a
VUM.slice Int
0 (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
n) IOVector Int
offs)
IO (IntMap ByteString -> Vector Word8 -> Int -> Cells)
-> IO (IntMap ByteString) -> IO (Vector Word8 -> Int -> Cells)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IntMap ByteString -> IO (IntMap ByteString)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure IntMap ByteString
esc
IO (Vector Word8 -> Int -> Cells)
-> IO (Vector Word8) -> IO (Int -> Cells)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> MVector (PrimState IO) Word8 -> IO (Vector Word8)
forall a (m :: * -> *).
(Unbox a, PrimMonad m) =>
MVector (PrimState m) a -> m (Vector a)
VU.freeze (Int -> Int -> IOVector Word8 -> IOVector Word8
forall a s. Unbox a => Int -> Int -> MVector s a -> MVector s a
VUM.slice Int
0 Int
n IOVector Word8
val)
IO (Int -> Cells) -> IO Int -> IO Cells
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
n
sliceBS :: BS.ByteString -> Int -> Int -> BS.ByteString
sliceBS :: ByteString -> Int -> Int -> ByteString
sliceBS ByteString
bs Int
s Int
e = Int -> ByteString -> ByteString
BSU.unsafeTake (Int
e Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
s) (Int -> ByteString -> ByteString
BSU.unsafeDrop Int
s ByteString
bs)
{-# INLINE sliceBS #-}
feedSink :: Env -> Sink -> Int -> Int -> Int -> Bool -> IO ()
feedSink :: Env -> Sink -> Int -> Int -> Int -> Bool -> IO ()
feedSink Env
env Sink
sink !Int
row !Int
s !Int
e !Bool
unesc = case Sink
sink of
SinkBS SliceCol
sc
| Bool
unesc -> do
let fresh :: ByteString
fresh = ByteString -> Int -> Int -> ByteString
unescapeQuotes (Env -> ByteString
envBS Env
env) Int
s Int
e
stripped :: ByteString
stripped = ByteString
-> Int -> Int -> (Int -> Int -> ByteString) -> ByteString
forall r. ByteString -> Int -> Int -> (Int -> Int -> r) -> r
withStripC8 ByteString
fresh Int
0 (ByteString -> Int
BS.length ByteString
fresh) (ByteString -> Int -> Int -> ByteString
sliceBS ByteString
fresh)
IORef (IntMap ByteString)
-> (IntMap ByteString -> IntMap ByteString) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' (SliceCol -> IORef (IntMap ByteString)
scEsc SliceCol
sc) (Int -> ByteString -> IntMap ByteString -> IntMap ByteString
forall a. Int -> a -> IntMap a -> IntMap a
IM.insert Int
row ByteString
stripped)
SliceCol -> Int -> Int -> Int -> Word8 -> IO ()
appendSliceCol SliceCol
sc Int
row (-Int
1) Int
row (Env -> ByteString -> Word8
missingOk Env
env ByteString
stripped)
| Bool
otherwise -> ByteString -> Int -> Int -> (Int -> Int -> IO ()) -> IO ()
forall r. ByteString -> Int -> Int -> (Int -> Int -> r) -> r
withStripC8 (Env -> ByteString
envBS Env
env) Int
s Int
e ((Int -> Int -> IO ()) -> IO ()) -> (Int -> Int -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Int
s' Int
e' ->
let ok :: Word8
ok = case Env -> MissingMode
envMode Env
env of
MissingMode
MissNone -> Word8
1
MissingMode
MissCanonical ->
if ByteString -> Int -> Int -> Bool
isMissingFieldSlice (Env -> ByteString
envBS Env
env) Int
s' Int
e' then Word8
0 else Word8
1
MissingMode
MissCustom -> Env -> ByteString -> Word8
missingOk Env
env (ByteString -> Int -> Int -> ByteString
sliceBS (Env -> ByteString
envBS Env
env) Int
s' Int
e')
in SliceCol -> Int -> Int -> Int -> Word8 -> IO ()
appendSliceCol SliceCol
sc Int
row Int
s' Int
e' Word8
ok
Sink
_
| Bool
unesc ->
let fresh :: ByteString
fresh = ByteString -> Int -> Int -> ByteString
unescapeQuotes (Env -> ByteString
envBS Env
env) Int
s Int
e
in ByteString -> (CStringLen -> IO ()) -> IO ()
forall a. ByteString -> (CStringLen -> IO a) -> IO a
BSU.unsafeUseAsCStringLen ByteString
fresh ((CStringLen -> IO ()) -> IO ()) -> (CStringLen -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
p, Int
l) ->
Env -> Sink -> ByteString -> Ptr Word8 -> Int -> Int -> IO ()
feedTyped Env
env Sink
sink ByteString
fresh (Ptr CChar -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr CChar
p) Int
0 Int
l
| Bool
otherwise -> Env -> Sink -> ByteString -> Ptr Word8 -> Int -> Int -> IO ()
feedTyped Env
env Sink
sink (Env -> ByteString
envBS Env
env) (Env -> Ptr Word8
envPtr Env
env) Int
s Int
e
{-# INLINE feedSink #-}
missingOk :: Env -> BS.ByteString -> Word8
missingOk :: Env -> ByteString -> Word8
missingOk Env
env ByteString
cell = case Env -> MissingMode
envMode Env
env of
MissingMode
MissNone -> Word8
1
MissingMode
MissCanonical -> if ByteString -> Int -> Int -> Bool
isMissingFieldSlice ByteString
cell Int
0 (ByteString -> Int
BS.length ByteString
cell) then Word8
0 else Word8
1
MissingMode
MissCustom -> if ByteString -> Text
TE.decodeUtf8Lenient ByteString
cell Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Env -> [Text]
envTexts Env
env then Word8
0 else Word8
1
feedTyped ::
Env -> Sink -> BS.ByteString -> Ptr Word8 -> Int -> Int -> IO ()
feedTyped :: Env -> Sink -> ByteString -> Ptr Word8 -> Int -> Int -> IO ()
feedTyped Env
env Sink
sink ByteString
bs !Ptr Word8
ptr !Int
s !Int
e = case Sink
sink of
SinkInt IntBuilder RealWorld
b -> case ByteString -> Int -> Int -> Maybe Int
parseIntFieldSlice ByteString
bs Int
s Int
e of
Just Int
v -> ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (IntBuilder RealWorld -> Int -> ST RealWorld ()
forall s. IntBuilder s -> Int -> ST s ()
appendInt IntBuilder RealWorld
b Int
v)
Maybe Int
Nothing -> ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (IntBuilder RealWorld -> ST RealWorld ()
forall s. NumBuilder Int s -> ST s ()
forall (b :: * -> *) s. ColumnBuilder b => b s -> ST s ()
appendNull IntBuilder RealWorld
b)
SinkDouble DoubleBuilder RealWorld
b -> case ByteString -> Int -> Int -> Maybe Double
parseDoubleFieldSlice ByteString
bs Int
s Int
e of
Just Double
v -> ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (DoubleBuilder RealWorld -> Double -> ST RealWorld ()
forall s. DoubleBuilder s -> Double -> ST s ()
appendDouble DoubleBuilder RealWorld
b Double
v)
Maybe Double
Nothing -> ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (DoubleBuilder RealWorld -> ST RealWorld ()
forall s. NumBuilder Double s -> ST s ()
forall (b :: * -> *) s. ColumnBuilder b => b s -> ST s ()
appendNull DoubleBuilder RealWorld
b)
SinkText TextBuilder RealWorld
b -> Env
-> TextBuilder RealWorld
-> ByteString
-> Ptr Word8
-> Int
-> Int
-> IO ()
appendTextCell Env
env TextBuilder RealWorld
b ByteString
bs Ptr Word8
ptr Int
s Int
e
SinkBS SliceCol
_ -> [Char] -> IO ()
forall a. HasCallStack => [Char] -> a
error [Char]
"feedTyped: SinkBS handled by feedSink"
{-# INLINE feedTyped #-}
appendTextCell ::
Env ->
TextBuilder RealWorld ->
BS.ByteString ->
Ptr Word8 ->
Int ->
Int ->
IO ()
appendTextCell :: Env
-> TextBuilder RealWorld
-> ByteString
-> Ptr Word8
-> Int
-> Int
-> IO ()
appendTextCell Env
env TextBuilder RealWorld
b ByteString
bs !Ptr Word8
ptr !Int
s !Int
e =
ByteString -> Int -> Int -> (Int -> Int -> IO ()) -> IO ()
forall r. ByteString -> Int -> Int -> (Int -> Int -> r) -> r
withStripAscii ByteString
bs Int
s Int
e ((Int -> Int -> IO ()) -> IO ()) -> (Int -> Int -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Int
s' Int
e' ->
if Int
s' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
e'
Bool -> Bool -> Bool
&& (ByteString -> Int -> Word8
BSU.unsafeIndex ByteString
bs Int
s' Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0x80 Bool -> Bool -> Bool
|| ByteString -> Int -> Word8
BSU.unsafeIndex ByteString
bs (Int
e' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0x80)
then IO ()
slow
else case Env -> MissingMode
envMode Env
env of
MissingMode
MissNone -> Int -> Int -> IO ()
fast Int
s' Int
e'
MissingMode
MissCanonical ->
if ByteString -> Int -> Int -> Bool
isMissingFieldSlice ByteString
bs Int
s' Int
e'
then ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (TextBuilder RealWorld -> ST RealWorld ()
forall s. TextBuilder s -> ST s ()
forall (b :: * -> *) s. ColumnBuilder b => b s -> ST s ()
appendNull TextBuilder RealWorld
b)
else Int -> Int -> IO ()
fast Int
s' Int
e'
MissingMode
MissCustom -> IO ()
slow
where
fast :: Int -> Int -> IO ()
fast Int
s' Int
e' = ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (TextBuilder RealWorld -> Ptr Word8 -> Int -> ST RealWorld ()
forall s. TextBuilder s -> Ptr Word8 -> Int -> ST s ()
appendTextSliceFromPtr TextBuilder RealWorld
b (Ptr Word8
ptr Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
s') (Int
e' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
s'))
slow :: IO ()
slow = do
let t :: Text
t = Text -> Text
T.strip (ByteString -> Text
TE.decodeUtf8Lenient (ByteString -> Int -> Int -> ByteString
sliceBS ByteString
bs Int
s Int
e))
missing :: Bool
missing = case Env -> MissingMode
envMode Env
env of
MissingMode
MissNone -> Bool
False
MissingMode
_ -> Text
t Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Env -> [Text]
envTexts Env
env
if Bool
missing then ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (TextBuilder RealWorld -> ST RealWorld ()
forall s. TextBuilder s -> ST s ()
forall (b :: * -> *) s. ColumnBuilder b => b s -> ST s ()
appendNull TextBuilder RealWorld
b) else ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (TextBuilder RealWorld -> Text -> ST RealWorld ()
forall s. TextBuilder s -> Text -> ST s ()
appendText TextBuilder RealWorld
b Text
t)
{-# INLINE appendTextCell #-}
nullSink :: Sink -> Int -> IO ()
nullSink :: Sink -> Int -> IO ()
nullSink Sink
sink !Int
row = case Sink
sink of
SinkInt IntBuilder RealWorld
b -> ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (IntBuilder RealWorld -> ST RealWorld ()
forall s. NumBuilder Int s -> ST s ()
forall (b :: * -> *) s. ColumnBuilder b => b s -> ST s ()
appendNull IntBuilder RealWorld
b)
SinkDouble DoubleBuilder RealWorld
b -> ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (DoubleBuilder RealWorld -> ST RealWorld ()
forall s. NumBuilder Double s -> ST s ()
forall (b :: * -> *) s. ColumnBuilder b => b s -> ST s ()
appendNull DoubleBuilder RealWorld
b)
SinkText TextBuilder RealWorld
b -> ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (TextBuilder RealWorld -> ST RealWorld ()
forall s. TextBuilder s -> ST s ()
forall (b :: * -> *) s. ColumnBuilder b => b s -> ST s ()
appendNull TextBuilder RealWorld
b)
SinkBS SliceCol
sc -> SliceCol -> Int -> Int -> Int -> Word8 -> IO ()
appendSliceCol SliceCol
sc Int
row Int
0 Int
0 Word8
0
{-# INLINE nullSink #-}