Improve rule description
[sat-britney.git] / ControlParser.hs
1 {-# LANGUAGE OverloadedStrings #-}
2
3 -- |
4 -- Module: ControlParser
5 -- Copyright: (c) 2011 Joachim Breitner
6 -- License: GPL-2
7 --
8 module ControlParser where
9
10 import Data.Word
11 import qualified Data.ByteString as DBS
12 import qualified Data.ByteString.Char8 as BS
13 import Data.Functor
14 import Data.Char
15
16 data Para = Para
17     { packageField :: !BS.ByteString
18     , versionField :: !BS.ByteString
19     , architectureField :: !BS.ByteString
20     , dependsField :: !BS.ByteString
21     , preDependsField :: !BS.ByteString
22     , providesField :: !BS.ByteString
23     , conflictsField :: !BS.ByteString
24     , breaksField :: !BS.ByteString
25     , sourceField :: !BS.ByteString
26     , sectionField :: !BS.ByteString
27     }
28     deriving (Eq, Show)
29
30 emptyPara :: Para
31 emptyPara = Para BS.empty BS.empty BS.empty BS.empty BS.empty BS.empty BS.empty BS.empty BS.empty BS.empty
32
33 parseControlFile :: FilePath -> IO [Para]
34 parseControlFile filename = parseLines . BS.lines <$> BS.readFile filename
35
36 parseLines :: [BS.ByteString] -> [Para]
37 parseLines = go emptyPara
38   where go para (l:ls) | BS.null l && valid para = para : go emptyPara ls
39                        | BS.null l               =        go emptyPara ls
40                        | otherwise               =        go (addField l para) ls
41         go para []     | valid para              = [para]
42                        | otherwise               = []
43
44 valid :: Para -> Bool
45 valid = not . BS.null . packageField
46
47 addField :: BS.ByteString -> Para -> Para
48 addField l para =
49     if n == "Package"      then para { packageField = v } else
50     if n == "Version"      then para { versionField = v } else
51     if n == "Architecture" then para { architectureField = v } else
52     if n == "Depends"      then para { dependsField = v } else
53     if n == "Pre-Depends"  then para { preDependsField = v } else
54     if n == "Provides"     then para { providesField = v } else
55     if n == "Conflicts"    then para { conflictsField = v } else
56     if n == "Breaks"       then para { breaksField = v } else
57     if n == "Source"       then para { sourceField = v } else
58     if n == "Section"      then para { sectionField = v } else
59     para
60  where (n,v') = DBS.breakByte colon l
61        v = BS.dropWhile isSpace (BS.tail v')
62
63 colon :: Word8
64 colon = fromIntegral (ord ':')