diff options
author | OzgunAtaman <> | 2011-09-18 21:27:34 (GMT) |
---|---|---|
committer | hdiff <hdiff@luite.com> | 2011-09-18 21:27:34 (GMT) |
commit | dfcf10a17adb2d179e113286656c0df1eb974f21 (patch) | |
tree | a52cc7b495073c63cab49e6c84d1009aa7c197c3 | |
parent | 33513d241b955c688a09f42b0497c5ffd15ff983 (diff) |
version 0.9.30.9.3
-rw-r--r-- | csv-enumerator.cabal | 3 | ||||
-rw-r--r-- | src/Data/CSV/Enumerator.hs | 40 | ||||
-rw-r--r-- | src/Data/CSV/Enumerator/Parser.hs | 100 |
3 files changed, 104 insertions, 39 deletions
diff --git a/csv-enumerator.cabal b/csv-enumerator.cabal index 4c33323..cac6db1 100644 --- a/csv-enumerator.cabal +++ b/csv-enumerator.cabal @@ -1,5 +1,5 @@ Name: csv-enumerator -Version: 0.9.2.1 +Version: 0.9.3 Synopsis: A flexible, fast, enumerator-based CSV parser library for Haskell. Homepage: http://github.com/ozataman/csv-enumerator License: BSD3 @@ -57,6 +57,7 @@ Library hs-source-dirs: src Exposed-modules: Data.CSV.Enumerator + Data.CSV.Enumerator.Parser Other-modules: Data.CSV.Enumerator.Types build-depends: diff --git a/src/Data/CSV/Enumerator.hs b/src/Data/CSV/Enumerator.hs index 051e6ef..65c3b9d 100644 --- a/src/Data/CSV/Enumerator.hs +++ b/src/Data/CSV/Enumerator.hs @@ -72,6 +72,8 @@ import Data.Word (Word8) import Safe (headMay) import Data.CSV.Enumerator.Types +import Data.CSV.Enumerator.Parser + class CSVeable r where @@ -529,41 +531,3 @@ rowParser csvs = E.catchError p handler yield Nothing (E.Chunks []) -row :: CSVSettings -> Parser (Maybe Row) -row csvs = csvrow csvs <|> badrow - -badrow :: Parser (Maybe Row) -badrow = P.takeWhile (not . C8.isEndOfLine) *> - (C8.endOfLine <|> C8.endOfInput) *> return Nothing - -csvrow :: CSVSettings -> Parser (Maybe Row) -csvrow c = - let rowbody = (quotedField' <|> (field c)) `sepBy` C8.char (csvSep c) - properrow = rowbody <* (C8.endOfLine <|> P.endOfInput) - quotedField' = case csvQuoteChar c of - Nothing -> mzero - Just q' -> try (quotedField q') - in do - res <- properrow - return $ Just res - -field :: CSVSettings -> Parser Field -field s = P.takeWhile (isFieldChar s) - -isFieldChar s = notInClass xs' - where xs = csvSep s : "\n\r" - xs' = case csvQuoteChar s of - Nothing -> xs - Just x -> x : xs - -quotedField :: Char -> Parser Field -quotedField c = - let quoted = string dbl *> return c - dbl = B8.pack [c,c] - in do - C8.char c - f <- many (C8.notChar c <|> quoted) - C8.char c - return $ B8.pack f - - diff --git a/src/Data/CSV/Enumerator/Parser.hs b/src/Data/CSV/Enumerator/Parser.hs new file mode 100644 index 0000000..378c7fe --- /dev/null +++ b/src/Data/CSV/Enumerator/Parser.hs @@ -0,0 +1,100 @@ +{-| + + This module exports the underlying Attoparsec row parser. This is helpful if + you want to do some ad-hoc CSV string parsing. + +-} + +module Data.CSV.Enumerator.Parser + +( parseCSV, parseRow, row, csv ) + +where + + +import Control.Applicative hiding (many) +import Control.Monad (mzero, mplus, foldM, when, liftM) +import Control.Monad.IO.Class (liftIO, MonadIO) +import qualified Data.ByteString as B +import qualified Data.ByteString.Char8 as B8 +import Data.ByteString.Char8 (ByteString) +import Data.ByteString.Internal (c2w) +import qualified Data.Map as M + +import Data.Attoparsec as P hiding (take) +import qualified Data.Attoparsec.Char8 as C8 +import Data.Word (Word8) + +import Data.CSV.Enumerator.Types + + +------------------------------------------------------------------------------ +-- | Try to parse given string as CSV +parseCSV :: CSVSettings -> ByteString -> Either String [Row] +parseCSV s = parseOnly $ csv s + + +------------------------------------------------------------------------------ +-- | Try to parse given string as 'Row' +parseRow :: CSVSettings -> ByteString -> Either String (Maybe Row) +parseRow s = parseOnly $ row s + + +------------------------------------------------------------------------------ +-- | Parse CSV +csv :: CSVSettings -> Parser [Row] +csv s = do + r <- row s + end <- atEnd + case end of + True -> case r of + Just x -> return [x] + Nothing -> return [] + False -> do + rest <- csv s + return $ case r of + Just x -> x : rest + Nothing -> rest + + +------------------------------------------------------------------------------ +-- | Parse a CSV row +row :: CSVSettings -> Parser (Maybe Row) +row csvs = csvrow csvs <|> badrow + + +badrow :: Parser (Maybe Row) +badrow = P.takeWhile (not . C8.isEndOfLine) *> + (C8.endOfLine <|> C8.endOfInput) *> return Nothing + +csvrow :: CSVSettings -> Parser (Maybe Row) +csvrow c = + let rowbody = (quotedField' <|> (field c)) `sepBy` C8.char (csvSep c) + properrow = rowbody <* (C8.endOfLine <|> P.endOfInput) + quotedField' = case csvQuoteChar c of + Nothing -> mzero + Just q' -> try (quotedField q') + in do + res <- properrow + return $ Just res + +field :: CSVSettings -> Parser Field +field s = P.takeWhile (isFieldChar s) + +isFieldChar s = notInClass xs' + where xs = csvSep s : "\n\r" + xs' = case csvQuoteChar s of + Nothing -> xs + Just x -> x : xs + +quotedField :: Char -> Parser Field +quotedField c = + let quoted = string dbl *> return c + dbl = B8.pack [c,c] + in do + C8.char c + f <- many (C8.notChar c <|> quoted) + C8.char c + return $ B8.pack f + + |