module Data.Repa.Flow.Generic.IO.Lines
( sourceLinesFormat
, sourceLinesFormatFromLazyByteString)
where
import Data.Repa.Flow.Generic.IO.Base as F
import Data.Repa.Flow.Generic.Map as F
import Data.Repa.Flow.Generic.Base as F
import Data.Repa.Array.Generic as A
import Data.Repa.Array.Material as A
import qualified Data.Repa.Array.Auto.Format as A
import Data.Repa.Convert.Format as C
import qualified Data.ByteString.Lazy as BSL
import Data.Char
import Data.Word
#include "repa-flow.h"
sourceLinesFormat
:: forall format
. (Unpackable format, Target A (Value format))
=> Integer
-> IO ()
-> IO (Array A Word8 -> IO ())
-> format
-> Array B Bucket
-> IO (Sources Int IO (Array A (Value format)))
sourceLinesFormat nChunk aFailLong _aFailConvert format bs
= do
let !nl = fromIntegral $ ord '\n'
let !nr = fromIntegral $ ord '\r'
sChunk <- sourceChunks nChunk (== nl) aFailLong bs
sRows8 :: Sources Int IO (Array N (Array F Word8))
<- map_i ( A.trimEnds (== nl)
. A.segmentOn (== nl)
. A.filter F (/= nr))
sChunk
let unpackRow :: Array A Word8 -> Value format
unpackRow arr
= case A.unpackFormat format arr of
Nothing -> error ("no convert " ++ show arr)
Just v -> v
F.map_i (A.mapS A (unpackRow . A.convert A)) sRows8
sourceLinesFormatFromLazyByteString
:: (Unpackable format, Target A (Value format))
=> Int
-> IO (Array A Word -> IO ())
-> format
-> BSL.ByteString
-> Int
-> IO (Sources Int IO (Array A (Value format)))
sourceLinesFormatFromLazyByteString n _aFailConvert format bs0 nSkip
= do
let !nl = fromIntegral $ ord '\n'
let !nr = fromIntegral $ ord '\r'
refsBS <- newRefs n bs0
refsSkip <- newRefs n nSkip
let unpackRow arr
= case A.unpackFormat format arr of
Nothing -> error ("no convert "
++ (show $ map (chr . fromIntegral)
$ A.toList arr))
Just v -> v
let pull_fromString i eat eject
= do bs <- readRefs refsBS i
skip <- readRefs refsSkip i
if BSL.null bs
then eject
else do let (bsLine, bsRest)
= BSL.break (== nl) bs
writeRefs refsBS i
$ BSL.dropWhile (== nl) bsRest
if (skip >= 0)
then do writeRefs refsSkip i (skip 1)
pull_fromString i eat eject
else eat $ A.singleton A.A
$ unpackRow
$ A.convert A.A
$ A.fromByteString
$ BSL.toStrict
$ BSL.filter (/= nr) bsLine
return $ Sources n pull_fromString