From: Matt McCutchen Date: Sat, 27 Aug 2011 21:23:35 +0000 (-0400) Subject: Implement TSV internally, remove the "csv" package dependency. X-Git-Url: https://mattmccutchen.net/match/match.git/commitdiff_plain/a70586aac4e53552ace2fe83655af176e6ec9e1a Implement TSV internally, remove the "csv" package dependency. --- diff --git a/program/Main.hs b/program/Main.hs index 4487508..bdc41a2 100644 --- a/program/Main.hs +++ b/program/Main.hs @@ -5,28 +5,15 @@ import System.IO import Data.Array.IArray import Data.Array.Unboxed import ArrayStuff -import Text.CSV +import TSV -- Command-line interface with simple tab-separated input/output formats. -- ./match if c == '\t' then ',' else if c == ',' then '\t' else c) s -removeQuotes s = filter (\c -> not (c == '"')) s - --- Some versions of Text.CSV do not use or accept a trailing newline; compensate for that. -removeTrailingNewline s = if not (null s) && last s == '\n' then init s else s -addTrailingNewline s = if not (null s) && last s /= '\n' then s ++ ['\n'] else s - -parseTSV fname str = case parseCSV fname (swapTabCommaIn $ removeTrailingNewline str) of - Left pe -> Left pe - Right ll -> Right $ map (map swapTabCommaIn) ll -printTSV ll = addTrailingNewline $ removeQuotes $ swapTabCommaIn $ printCSV $ map (map swapTabCommaIn) ll - main = do incsv <- hGetContents stdin -- handle errors another day, or let the platform do it - let Right inll = parseTSV "standard input" incsv + let inll = parseTSV incsv let loadList = head inll let numRvrs = length loadList let loadA = listArray (0, numRvrs-1) (map read loadList) @@ -37,4 +24,4 @@ main = do let prefA = funcArray ((0,0), (numRvrs-1,numProps-1)) (\(i,j) -> read (pxarr ! (j, i))) let theInst = PMInstance numRvrs numProps loadA prefA let PMatching theMatching = doMatching pmDefaults theInst - hPutStr stdout $ printTSV $ map (\(i, j) -> map show [i, j]) theMatching + hPutStr stdout $ formatTSV $ map (\(i, j) -> map show [i, j]) theMatching diff --git a/program/Makefile b/program/Makefile index d72db83..344ddf0 100644 --- a/program/Makefile +++ b/program/Makefile @@ -10,4 +10,4 @@ all-optimized: clean: rm -f *.hi *.o match -# Necessary libraries (on Fedora): ghc-fgl, ghc-csv. Others I miss? +# Necessary libraries (on Fedora): ghc-fgl. Others I miss? diff --git a/program/TSV.hs b/program/TSV.hs new file mode 100644 index 0000000..9b2cf9f --- /dev/null +++ b/program/TSV.hs @@ -0,0 +1,31 @@ +module TSV ( + parseTSV, formatTSV +) where +import Data.List + +-- Simple implementation of tab-separated values with a trailing newline and no +-- quoting support. + +splitList :: Eq a => a -> Bool -> [a] -> [[a]] +splitList delim terminated = + let sl [] | terminated = [] + sl l = case break (== delim) l of + (hh, []) -> [hh] + (hh, {-delim-} _ : t) -> hh : sl t + in sl + +-- We use the Eq only to check the validity... +joinList :: Eq a => a -> Bool -> [[a]] -> [a] +joinList delim terminated l = + if any (any (== delim)) l then error "joinList: item contains delimiter" + else if terminated + then concatMap (++ [delim]) l + else intercalate [delim] l + +type TSV = [[String]] + +formatTSV :: TSV -> String +formatTSV = joinList '\n' True . map (joinList '\t' False) + +parseTSV :: String -> TSV +parseTSV = map (splitList '\t' False) . splitList '\n' True