{-# LANGUAGE Safe #-}
module Data.CSV (csvFile, genCsvFile) where
import safe Text.ParserCombinators.Parsec
( char,
noneOf,
string,
endBy,
sepBy,
(<?>),
(<|>),
many,
try,
GenParser,
CharParser )
import Data.List (intersperse)
eol :: forall st. GenParser Char st String
eol :: forall st. GenParser Char st String
eol = (forall tok st a. GenParser tok st a -> GenParser tok st a
try forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"\n\r") forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (forall tok st a. GenParser tok st a -> GenParser tok st a
try forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"\r\n") forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"\n" forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"\r" forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"End of line"
cell :: GenParser Char st String
cell :: forall st. GenParser Char st String
cell = forall st. GenParser Char st String
quotedcell forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many (forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
",\n\r")
quotedchar :: GenParser Char st Char
quotedchar :: forall st. GenParser Char st Char
quotedchar = forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
"\""
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (forall tok st a. GenParser tok st a -> GenParser tok st a
try forall a b. (a -> b) -> a -> b
$ do String
_ <- forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"\"\""
forall (m :: * -> *) a. Monad m => a -> m a
return Char
'"'
)
quotedcell :: CharParser st String
quotedcell :: forall st. GenParser Char st String
quotedcell = do Char
_ <- forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'"'
String
content <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many forall st. GenParser Char st Char
quotedchar
Char
_ <- forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'"'
forall (m :: * -> *) a. Monad m => a -> m a
return String
content
line :: GenParser Char st [String]
line :: forall st. GenParser Char st [String]
line = forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
sepBy forall st. GenParser Char st String
cell (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
',')
csvFile :: CharParser st [[String]]
csvFile :: forall st. CharParser st [[String]]
csvFile = forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
endBy forall st. GenParser Char st [String]
line forall st. GenParser Char st String
eol
genCsvFile :: [[String]] -> String
genCsvFile :: [[String]] -> String
genCsvFile [[String]]
inp =
[String] -> String
unlines forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map [String] -> String
csvline forall a b. (a -> b) -> a -> b
$ [[String]]
inp
where csvline :: [String] -> String
csvline :: [String] -> String
csvline [String]
l = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> [a] -> [a]
intersperse String
"," forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map String -> String
csvcells forall a b. (a -> b) -> a -> b
$ [String]
l
csvcells :: String -> String
csvcells :: String -> String
csvcells String
"" = String
""
csvcells String
c = Char
'"' forall a. a -> [a] -> [a]
: String -> String
convcell String
c forall a. [a] -> [a] -> [a]
++ String
"\""
convcell :: String -> String
convcell :: String -> String
convcell String
c = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> String
convchar String
c
convchar :: Char -> String
convchar Char
'"' = String
"\"\""
convchar Char
x = [Char
x]