module Gauge.CSV
( Row(..)
, outputRow
, Field
, float
, integral
, string
, write
) where
import Data.List (intercalate)
newtype Field = Field { unField :: String }
deriving (Show,Eq)
newtype Row = Row [Field]
deriving (Show,Eq)
float :: Double -> Field
float d = Field $ show d
integral :: Integral a => a -> Field
integral i = Field $ show (toInteger i)
string :: String -> Field
string s =
case needEscape NoEscape s of
NoEscape -> Field s
Escape -> Field ('"' : (s ++ "\""))
EscapeDoubling -> Field ('"' : doubleQuotes s)
where
needEscape EscapeDoubling _ = EscapeDoubling
needEscape e [] = e
needEscape e (x:xs)
| x == '"' = EscapeDoubling
| x `elem` toEscape = needEscape (max e Escape) xs
| otherwise = needEscape e xs
toEscape = ",\r\n"
doubleQuotes [] = ['"']
doubleQuotes (x:xs)
| x == '"' = '"':'"':doubleQuotes xs
| otherwise = x : doubleQuotes xs
outputRow :: Row -> String
outputRow (Row fields) = intercalate "," $ map unField fields
data Escaping = NoEscape | Escape | EscapeDoubling
deriving (Show,Eq,Ord)
write :: Maybe FilePath
-> Row
-> IO ()
write Nothing _ = return ()
write (Just fp) r = appendFile fp (outputRow r ++ "\r\n")