packages feed

readcsv (empty) → 0.1

raw patch · 4 files changed

+126/−0 lines, 4 filesdep +basesetup-changed

Dependencies added: base

Files

+ COPYING view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2017 George Steel++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ readcsv.cabal view
@@ -0,0 +1,25 @@+name:                readcsv+version:             0.1+synopsis: Lightweight CSV parser/emitter based on ReadP+description: Parses and emits tables of strings formatted according to RFC 4180,+             /"The common Format and MIME Type for Comma-Separated Values (CSV) Files"/.+             Has no dependencies on parsec or any libraries other than base.+homepage:            https://github.com/george-steel/readcsv+license:             MIT+license-file:        COPYING+author:              George Steel+maintainer:          george.steel@gmail.com+copyright:           2017 George Steel+category:            Web+build-type:          Simple+cabal-version:       >=1.10++library+  hs-source-dirs:      src+  exposed-modules:     Text.Read.CSV+  build-depends:       base >= 4 && < 5+  default-language:    Haskell2010++source-repository head+  type:     git+  location: https://github.com/george-steel/readcsv
+ src/Text/Read/CSV.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE LambdaCase #-}++{-|+Module: Text.Read.CSV+Description: CSV parser/emitter based on ReadP+Copyright: © 2017 George Steel+License: MIT+Maintainer: george.steel@gmail.com++Implementation of RFC 4180-compliant CSV parser and emitter.+Works with both LF (Unix) and CRLF (DOS) linebreaks and allows varianble-length records.+The header line (if one is used) is the first item in the parsed list, and can be separated with a pattern match.+-}++module Text.Read.CSV (+    readCSV, writeCSV, writeCSVstrict, csvTableP+) where++import Text.ParserCombinators.ReadP+import Control.Monad+--import Control.Applicative+import Data.List+import Data.Maybe++unescaped :: ReadP String+unescaped = munch (`notElem` ",\"\r\n\t")++notquote :: ReadP String+notquote = munch (/= '"')++singlequoted :: ReadP String+singlequoted = do+    char '"'+    s <- notquote+    char '"'+    return s++fullquoted :: ReadP String+fullquoted = fmap (intercalate "\"") (many1 singlequoted)++csvcell :: ReadP String+csvcell = skipSpaces >> (unescaped +++ fullquoted)++csvrow :: ReadP [String]+csvrow = sepBy1 csvcell (char ',')++crlf :: ReadP ()+crlf = optional (char '\r') >> char '\n' >> return ()++-- | ReadP parser for CSV.+csvTableP :: ReadP [[String]]+csvTableP = sepBy1 csvrow crlf++csvfile :: ReadP [[String]]+csvfile = do+    table <- csvTableP+    optional crlf+    eof+    return table++-- | Parse CSV from a string.+readCSV :: String -> Maybe [[String]]+readCSV = fmap fst . listToMaybe . readP_to_S csvfile+++escapecell :: String -> String+escapecell cs = "\"" ++ (cs >>= \case '"' -> "\"\""; x -> [x]) ++ "\""++escapeifneeded :: String -> String+escapeifneeded cs = if any (`elem` ",\"\r\n\t") cs then escapecell cs else cs++-- | Emit CSV, escaping fields as necessary. Uses Unix linebreaks and a trailing newline.+writeCSV :: [[String]] -> String+writeCSV = join . fmap ((++ "\n") . intercalate "," . fmap escapeifneeded)++-- | Emit CSV with CRLF line breaks ans no trailing newline, as specified by RFC 4180.+writeCSVstrict :: [[String]] -> String+writeCSVstrict = intercalate "\r\n" . fmap (intercalate "," . fmap escapeifneeded)