summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOzgunAtaman <>2011-09-18 21:27:34 (GMT)
committerhdiff <hdiff@luite.com>2011-09-18 21:27:34 (GMT)
commitdfcf10a17adb2d179e113286656c0df1eb974f21 (patch)
treea52cc7b495073c63cab49e6c84d1009aa7c197c3
parent33513d241b955c688a09f42b0497c5ffd15ff983 (diff)
version 0.9.30.9.3
-rw-r--r--csv-enumerator.cabal3
-rw-r--r--src/Data/CSV/Enumerator.hs40
-rw-r--r--src/Data/CSV/Enumerator/Parser.hs100
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
+
+