planar-graph-1.0.0.0: Data/Graph/Planar/Serialisation.hs
{-# LANGUAGE TypeFamilies #-}
{- |
Module : Data.Graph.Planar.Serialisation
Description : Serialisation for planar graphs.
Copyright : (c) Ivan Lazar Miljenovic
License : 3-Clause BSD-style
Maintainer : Ivan.Miljenovic@gmail.com
-}
module Data.Graph.Planar.Serialisation
( PlanarEncoding(..)
, encodePlanarFile
, encodePlanarFileFrom
, decodePlanarFile
) where
import Data.Graph.Planar hiding (isEmpty)
import Data.Graph.Planar.Serialisation.Internal
import Blaze.ByteString.Builder(toLazyByteString)
import Blaze.ByteString.Builder.Char8(fromChar)
import Data.Attoparsec.ByteString.Lazy(parse, eitherResult, many1, (<?>))
import Data.Attoparsec.ByteString.Char8(endOfLine)
import qualified Data.ByteString.Lazy as B
import Data.Monoid(mempty, mappend)
import Control.Applicative((<*))
import Control.Monad(foldM)
-- -----------------------------------------------------------------------------
-- | Encode a list of planar graphs to file using the specified
-- encoding.
encodePlanarFile :: (PlanarEncoding ser) => ser -> FilePath
-> [PlanarGraph (NLabel ser) (ELabel ser)]
-> IO Int
encodePlanarFile ser fp = encodePlanarFileFrom ser fp . map ((,) Nothing)
-- | Encode a list of planar graphs to file using the specified
-- encoding, with the serialisation traversing from the an
-- optionally specified edge.
encodePlanarFileFrom :: (PlanarEncoding ser) => ser -> FilePath
-> [(Maybe Edge,PlanarGraph (NLabel ser) (ELabel ser))]
-> IO Int
encodePlanarFileFrom ser fp pgs = do B.writeFile fp $ toLazyByteString header
foldM printCount 0 pgs
where
header = putName ser
maybeNewline | sepByNewline ser = fromChar '\n'
| otherwise = mempty
printCount c pg = c `seq` (B.appendFile fp (toB pg) >> return (c+1))
toB pg = toLazyByteString $ putSG ser (toSer pg) `mappend` maybeNewline
toSer (me,pg) = ((order pg, size pg), serialiseBFS pg me)
-- | Read in a file containing encoded graphs. The 'PlanarEncoding'
-- argument is only used for its /type/ to determine which parser to
-- use.
decodePlanarFile :: (PlanarEncoding ser) => ser -> FilePath
-> IO [PlanarGraph (NLabel ser) (ELabel ser)]
decodePlanarFile ser fp = do bs <- B.readFile fp
case eitherResult $ parse parser bs of
Left err -> error $ "Could not parse file " ++ fp ++ " with the error: " ++ err
Right sgs -> return $ map deserialise sgs
where
parser = do nm <- fmap (`asTypeOf` ser) getName <?> "Parsing encoding header"
many1 $ getSG nm <* maybeNewLine
maybeNewLine | sepByNewline ser = endOfLine
| otherwise = return ()