planar-graph-1.0.0.0: Data/Graph/Planar/Serialisation/PlanarCode.hs
{-# LANGUAGE TypeFamilies, OverloadedStrings #-}
{- |
Module : Data.Graph.Planar.Serialisation.PlanarCode
Description : Implementation of PLANAR CODE.
Copyright : (c) Ivan Lazar Miljenovic
License : 3-Clause BSD-style
Maintainer : Ivan.Miljenovic@gmail.com
-}
module Data.Graph.Planar.Serialisation.PlanarCode(PlanarCode(..)) where
import Data.Graph.Planar(SerialisedGraph)
import Data.Graph.Planar.Serialisation.Internal
import Blaze.ByteString.Builder
import Data.Attoparsec.ByteString.Lazy
import qualified Data.ByteString as SBS
import Data.Foldable(foldMap)
import Control.Applicative((<*))
import Data.Monoid(Monoid(..))
import Control.Monad(replicateM)
-- -----------------------------------------------------------------------------
{- |
PLANAR_CODE is the most common encoding for planar graphs, and is
supported by various generation and visualisation tools. It is a
binary format and not intended to be human-readable.
The default encoding only supports graphs with @<256@ nodes, and
takes @2*|E|+|N|+1@ bytes per graph.
Please note that PLANAR_CODE is /not/ suitable for graphs with
multiple loops on vertices (multiple edges with distinct endpoints
however are catered for). As such, no guarantees are made about what
happens with multiple loops.
-}
data PlanarCode = PlanarCode
deriving (Eq, Ord, Show, Read)
instance PlanarEncoding PlanarCode where
type NLabel PlanarCode = ()
type ELabel PlanarCode = ()
putSG = const putPlanarCode
getSG = const getPlanarCode
putName = const $ fromByteString ">>planar_code<<"
getName = string ">>planar_code<<" >> return PlanarCode
sepByNewline = const False
putPlanarCode :: ((Int,Int),SerialisedGraph n e) -> Builder
putPlanarCode ((ord,_),sg) = fromWord8 (fromIntegral ord)
`mappend` foldMap (fromWrite . putNode . nodeEdgesSer)
sg
where
putNode es = foldMap (writeWord8 . succ . fromIntegral . toNodeSer) es
`mappend` writeWord8 0
-- Need succ here, because the SerialisedGraph is 0-based, but PC is 1-based.
getPlanarCode :: Parser (SerialisedGraph () ())
getPlanarCode = do num <- fromIntegral `fmap` anyWord8
ess <- replicateM num getNode
-- Convert to 0-based Word values
let ess' = map (map $ fromIntegral . pred) ess
return $ processPC ess'
where
getNode = SBS.unpack `fmap` takeWhile1 (/= 0) <* anyWord8 -- will be 0