hark-0.2: src/Parsers/Content.hs
{-----------------------------------------------------------------
(c) 2008-2009 Markus Dittrich
This program is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License Version 3 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License Version 3 for more details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
--------------------------------------------------------------------}
-- | this module parses the contents of a package and
-- puts everything into a list of PackageContent data
-- structures
module Parsers.Content ( defaultContent
, get_content
, FileType(..)
, PackageContentItem(..)
, retrieve_package_content
) where
-- basic imports
import qualified Data.ByteString as B(ByteString, null, split, concat)
import Prelude
import System.FilePath.Posix((</>))
import Text.Regex.PCRE((=~))
-- local imports
import Helpers.ByteString(newlineW, remove_last_newline, spaceChar,
spaceCharW)
import Helpers.FileIO(read_file)
-- | data type for describing the type of "file"
-- in the PackageContent
data FileType = None | Dir | Sym | Obj
deriving(Eq)
-- | data structure for holding a single entry in the
-- CONTENTS file of a package
data PackageContentItem = PackageContentItem {
fileType :: FileType,
name :: B.ByteString,
md5 :: B.ByteString,
size :: B.ByteString
} deriving(Eq)
-- | default Dependency data structure
defaultContent :: PackageContentItem
defaultContent = PackageContentItem {
fileType = None,
name = spaceChar,
md5 = spaceChar,
size = spaceChar
}
-- | read the CONTENT of a file and return it as a raw
-- ByteString
get_content :: FilePath -> IO B.ByteString
get_content path = read_file (path </> "CONTENTS")
-- | retrieve content of package located at location path
retrieve_package_content :: FilePath -> IO [PackageContentItem]
retrieve_package_content path = get_content path
>>= return . content_parser
-- | split the content into list of lines and then hands them
-- over for parsing of each line
-- NOTE: the passed string may be empty so we need to check
content_parser :: B.ByteString -> [PackageContentItem]
content_parser content
| B.null content = []
| otherwise = map (parse_line) splitLines
where
lineList = B.split newlineW $ remove_last_newline content
splitLines = map (B.split spaceCharW) lineList
-- | parse each line and create a corresponding
-- PackageContentItem entry
parse_line :: [B.ByteString] -> PackageContentItem
parse_line [] = defaultContent
parse_line (x:xs)
| x =~ "dir" = defaultContent {
fileType = Dir,
name = head xs
}
| x =~ "sym" = defaultContent {
fileType = Sym,
name = assemble_link xs,
size = (!!) xs 3
}
| x =~ "obj" = defaultContent {
fileType = Obj,
name = (!!) xs 0,
md5 = (!!) xs 1,
size = (!!) xs 2
}
| otherwise = defaultContent
where
assemble_link :: [B.ByteString] -> B.ByteString
assemble_link (a:b:c:_) =
B.concat [a, spaceChar, b, spaceChar, c]
assemble_link _ = spaceChar