>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> module Pipes.CSV.Encoder (
> encodeCSV, encodeLazyCSV
> ) where
> import Control.Monad
> import Data.ByteString (ByteString)
> import Data.Cell
> import Pipes
> import Pipes.CSV.Syntax
> import qualified Data.ByteString as ByteString
> import qualified Data.ByteString.Lazy as Lazy
>
>
>
> encodeCSV :: Monad m => Int -> Pipe (Cell ByteString) ByteString m ()
> encodeCSV n = encode1
> where
> encode1 = await >>= encode2
> encode2 (Cell x EOP) = yield fieldDelimiter >> quotePart x >> await >>= encode3
> encode2 (Cell x EOC) = quoteField x >> yield fieldSeparator >> encode1
> encode2 (Cell x EOR) = quoteField x >> yield recordSeparator >> encode1
> encode2 (Cell x EOT) = quoteField x >> yield recordSeparator >> encode1
> encode3 (Cell x EOP) = quotePart x >> await >>= encode3
> encode3 (Cell x EOC) = quotePart x >> yield fieldDelimiter >> yield fieldSeparator >> encode1
> encode3 (Cell x EOR) = quotePart x >> yield fieldDelimiter >> yield recordSeparator >> encode1
> encode3 (Cell x EOT) = quotePart x >> yield fieldDelimiter >> yield recordSeparator >> encode1
> quoteField x
> | requiresQuoting x = yield fieldDelimiter >> quotePart x >> yield fieldDelimiter
> | otherwise = yield' x
> requiresQuoting x = (ByteString.length x > n || ByteString.any isSpecial x)
>
>
>
> encodeLazyCSV :: Monad m => Int -> Pipe (Cell Lazy.ByteString) ByteString m ()
> encodeLazyCSV n = encode1
> where
> encode1 = await >>= encode2
> encode2 (Cell x EOP) = yield fieldDelimiter >> quoteLazyPart x >> await >>= encode3
> encode2 (Cell x EOC) = quoteLazyField x >> yield fieldSeparator >> encode1
> encode2 (Cell x EOR) = quoteLazyField x >> yield recordSeparator >> encode1
> encode2 (Cell x EOT) = quoteLazyField x >> yield recordSeparator >> encode1
> encode3 (Cell x EOP) = quoteLazyPart x >> await >>= encode3
> encode3 (Cell x EOC) = quoteLazyPart x >> yield fieldDelimiter >> yield fieldSeparator >> encode1
> encode3 (Cell x EOR) = quoteLazyPart x >> yield fieldDelimiter >> yield recordSeparator >> encode1
> encode3 (Cell x EOT) = quoteLazyPart x >> yield fieldDelimiter >> yield recordSeparator >> encode1
> quoteLazyField x
> | requiresQuoting n cs = yield fieldDelimiter >> quoteChunks cs >> yield fieldDelimiter
> | otherwise = mapM_ yield' cs
> where
> cs = Lazy.toChunks x
> quoteLazyPart = quoteChunks . Lazy.toChunks
> quoteChunks = mapM_ quotePart
> requiresQuoting n' (c:cs) = (m > n' || ByteString.any isSpecial c || requiresQuoting (n m) cs)
> where m = fromIntegral (ByteString.length c)
> requiresQuoting _ [] = False
> quotePart x =
> case ByteString.elemIndex QC x of
> Just i -> yield' (ByteString.take i x) >> yield quoteSequence >> quotePart (ByteString.drop (i + 1) x)
> Nothing -> yield' x
> yield' x = unless (ByteString.null x) (yield x)