/* -*- C++ -*- * lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ ///\ingroup io_group ///\file ///\brief Lemon Graph Format reader. #ifndef LEMON_GRAPH_READER_H #define LEMON_GRAPH_READER_H #include #include #include namespace lemon { /// \addtogroup io_group /// @{ /// \brief The graph reader class. /// /// The \c GraphReader class provides the graph input. /// Before you read this documentation it might be useful to read the general /// description of \ref graph-io-page "Graph Input-Output". /// /// If you don't need very sophisticated /// behaviour then you can use the versions of the public function /// \ref readGraph() to read a graph (or a max flow instance etc). /// /// The file to be read may contain several maps and labeled nodes or /// edges. /// /// If you read a graph you need not read all the maps and items just those /// that you need. The interface of the \c GraphReader is very similar to /// the GraphWriter but the reading method does not depend on the order the /// given commands (i.e. you don't have to insist on the order in which the /// maps are given in the file). /// /// The reader object assumes that not readed values do not contain /// whitespaces, therefore it has some extra possibilities to control how /// it should skip the values when the string representation contains spaces. /// /// \code /// GraphReader reader(std::cin, graph); /// \endcode /// /// The \c readNodeMap() function reads a map from the \c \@nodeset section. /// If there is a map that you do not want to read from the file and there is /// whitespace in the string represenation of the values then you should /// call the \c skipNodeMap() template member function with proper /// parameters. /// /// \code /// reader.readNodeMap("coords", coords); /// /// reader.readNodeMap("label", labelMap); /// reader.skipNodeMap("description"); /// /// reader.readNodeMap("color", colorMap); /// \endcode /// /// With the \c readEdgeMap() member function you can give an edge map /// reading command similar to the NodeMaps. /// /// \code /// reader.readEdgeMap("weight", weightMap); /// reader.readEdgeMap("label", labelMap); /// \endcode /// /// With \c readNode() and \c readEdge() functions you can read /// labeled Nodes and Edges. /// /// \code /// reader.readNode("source", sourceNode); /// reader.readNode("target", targetNode); /// /// reader.readEdge("observed", edge); /// \endcode /// /// With the \c readAttribute() functions you can read an attribute /// into a variable. You can specify the reader for the attribute as /// the nodemaps. /// /// After you give all read commands you must call the \c run() member /// function, which executes all the commands. /// /// \code /// reader.run(); /// \endcode /// /// \see DefaultReaderTraits /// \see QuotedStringReader /// \see \ref GraphWriter /// \see \ref graph-io-page /// \author Balazs Dezso template class GraphReader { public: typedef _Graph Graph; typedef typename Graph::Node Node; typedef typename Graph::Edge Edge; typedef _ReaderTraits ReaderTraits; typedef typename ReaderTraits::Skipper DefaultSkipper; /// \brief Construct a new GraphReader. /// /// Construct a new GraphReader. It reads into the given graph /// and it uses the given reader as the default skipper. GraphReader(std::istream& _is, Graph& _graph, const DefaultSkipper& _skipper = DefaultSkipper()) : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper), nodeset_reader(*reader, _graph, std::string(), skipper), edgeset_reader(*reader, _graph, nodeset_reader, std::string(), skipper), node_reader(*reader, nodeset_reader, std::string()), edge_reader(*reader, edgeset_reader, std::string()), attribute_reader(*reader, std::string()) {} /// \brief Construct a new GraphReader. /// /// Construct a new GraphReader. It reads into the given graph /// and it uses the given reader as the default skipper. GraphReader(const std::string& _filename, Graph& _graph, const DefaultSkipper& _skipper = DefaultSkipper()) : reader(new LemonReader(_filename)), own_reader(true), skipper(_skipper), nodeset_reader(*reader, _graph, std::string(), skipper), edgeset_reader(*reader, _graph, nodeset_reader, std::string(), skipper), node_reader(*reader, nodeset_reader, std::string()), edge_reader(*reader, edgeset_reader, std::string()), attribute_reader(*reader, std::string()) {} /// \brief Construct a new GraphReader. /// /// Construct a new GraphReader. It reads into the given graph /// and it uses the given reader as the default skipper. GraphReader(LemonReader& _reader, Graph& _graph, const DefaultSkipper& _skipper = DefaultSkipper()) : reader(_reader), own_reader(false), skipper(_skipper), nodeset_reader(*reader, _graph, std::string(), skipper), edgeset_reader(*reader, _graph, nodeset_reader, std::string(), skipper), node_reader(*reader, nodeset_reader, std::string()), edge_reader(*reader, edgeset_reader, std::string()), attribute_reader(*reader, std::string()) {} /// \brief Destruct the graph reader. /// /// Destruct the graph reader. ~GraphReader() { if (own_reader) delete reader; } /// \brief Give a new node map reading command to the reader. /// /// Give a new node map reading command to the reader. template GraphReader& readNodeMap(std::string name, Map& map) { nodeset_reader.readNodeMap(name, map); return *this; } template GraphReader& readNodeMap(std::string name, const Map& map) { nodeset_reader.readNodeMap(name, map); return *this; } /// \brief Give a new node map reading command to the reader. /// /// Give a new node map reading command to the reader. template GraphReader& readNodeMap(std::string name, Map& map, const Reader& reader = Reader()) { nodeset_reader.readNodeMap(name, map, reader); return *this; } template GraphReader& readNodeMap(std::string name, const Map& map, const Reader& reader = Reader()) { nodeset_reader.readNodeMap(name, map, reader); return *this; } /// \brief Give a new node map skipping command to the reader. /// /// Give a new node map skipping command to the reader. template GraphReader& skipNodeMap(std::string name, const Reader& reader = Reader()) { nodeset_reader.skipNodeMap(name, reader); return *this; } /// \brief Give a new edge map reading command to the reader. /// /// Give a new edge map reading command to the reader. template GraphReader& readEdgeMap(std::string name, Map& map) { edgeset_reader.readEdgeMap(name, map); return *this; } template GraphReader& readEdgeMap(std::string name, const Map& map) { edgeset_reader.readEdgeMap(name, map); return *this; } /// \brief Give a new edge map reading command to the reader. /// /// Give a new edge map reading command to the reader. template GraphReader& readEdgeMap(std::string name, Map& map, const Reader& reader = Reader()) { edgeset_reader.readEdgeMap(name, map, reader); return *this; } template GraphReader& readEdgeMap(std::string name, const Map& map, const Reader& reader = Reader()) { edgeset_reader.readEdgeMap(name, map, reader); return *this; } /// \brief Give a new edge map skipping command to the reader. /// /// Give a new edge map skipping command to the reader. template GraphReader& skipEdgeMap(std::string name, const Reader& reader = Reader()) { edgeset_reader.skipEdgeMap(name, reader); return *this; } /// \brief Give a new labeled node reading command to the reader. /// /// Give a new labeled node reading command to the reader. GraphReader& readNode(std::string name, Node& node) { node_reader.readNode(name, node); return *this; } /// \brief Give a new labeled edge reading command to the reader. /// /// Give a new labeled edge reading command to the reader. GraphReader& readEdge(std::string name, Edge& edge) { edge_reader.readEdge(name, edge); return *this; } /// \brief Give a new attribute reading command. /// /// Give a new attribute reading command. template GraphReader& readAttribute(std::string name, Value& value) { attribute_reader.readAttribute(name, value); return *this; } /// \brief Give a new attribute reading command. /// /// Give a new attribute reading command. template GraphReader& readAttribute(std::string name, Value& value, const Reader& reader) { attribute_reader.readAttribute(name, value, reader); return *this; } /// \brief Conversion operator to LemonReader. /// /// Conversion operator to LemonReader. It makes possible to access the /// encapsulated \e LemonReader, this way you can attach to this reader /// new instances of \e LemonReader::SectionReader. For more details see /// the \ref rwbackground "Background of Reading and Writing". operator LemonReader&() { return *reader; } /// \brief Executes the reading commands. /// /// Executes the reading commands. void run() { reader->run(); } /// \brief Gives back the node by its id. /// /// It reads an id from the stream and gives back which node belongs to /// it. It is possible only if there was read an "id" named node map. Node readId(std::istream& is, Node) const { return nodeset_reader.readId(is, Node()); } /// \brief Gives back the edge by its id. /// /// It reads an id from the stream and gives back which edge belongs to /// it. It is possible only if there was read an "id" named edge map. Edge readId(std::istream& is, Edge) const { return edgeset_reader.readId(is, Edge()); } private: LemonReader* reader; bool own_reader; DefaultSkipper skipper; NodeSetReader nodeset_reader; EdgeSetReader edgeset_reader; NodeReader node_reader; EdgeReader edge_reader; AttributeReader attribute_reader; }; /// \brief Read a graph from the input. /// /// It is a helper function to read a graph from the given input /// stream. It gives back an GraphReader object and this object /// can read more maps, labeled nodes, edges and attributes. /// /// \warning Do not forget to call the \c run() function. /// /// \param is The input stream. /// \param g The graph. template GraphReader graphReader(std::istream& is, Graph &g) { return GraphReader(is, g); } /// \brief Read a graph from the input. /// /// It is a helper function to read a graph from the given input /// file. It gives back an GraphReader object and this object /// can read more maps, labeled nodes, edges and attributes. /// /// \warning Do not forget to call the \c run() function. /// /// \param fn The input filename. /// \param g The graph. template GraphReader graphReader(const std::string& fn, Graph &g) { return GraphReader(fn, g); } /// \brief The undirected graph reader class. /// /// The \c UndirGraphReader class provides the graph input. /// Before you read this documentation it might be useful to read the general /// description of \ref graph-io-page "Graph Input-Output". /// /// If you don't need very sophisticated /// behaviour then you can use the versions of the public function /// \ref readGraph() to read a graph (or a max flow instance etc). /// /// The given file format may contain several maps and labeled nodes or /// edges. /// /// If you read a graph you need not read all the maps and items just those /// that you need. The interface of the \c UndirGraphReader is very similar /// to the UndirGraphWriter but the reading method does not depend on the /// order of the given commands. /// /// The reader object suppose that each not readed value does not contain /// whitespaces, therefore it has some extra possibilities to control how /// it should skip the values when the string representation contains spaces. /// /// \code /// UndirGraphReader reader(std::cin, graph); /// \endcode /// /// The \c readNodeMap() function reads a map from the \c \@nodeset section. /// If there is a map that you do not want to read from the file and there is /// whitespace in the string represenation of the values then you should /// call the \c skipNodeMap() template member function with proper /// parameters. /// /// \code /// reader.readNodeMap("coords", coords); /// /// reader.readNodeMap("label", labelMap); /// reader.skipNodeMap("description"); /// /// reader.readNodeMap("color", colorMap); /// \endcode /// /// With the \c readUndirEdgeMap() member function you can give an /// undir edge map reading command similar to the NodeMaps. /// /// \code /// reader.readUndirEdgeMap("capacity", capacityMap); /// \endcode /// /// The reading of the directed edge maps is just a syntactical sugar. /// It reads two undirected edgemaps into a directed edge map. The /// undirected edge maps' name should be start with the \c '+' and the /// \c '-' character and the same. /// /// \code /// reader.readEdgeMap("flow", flowMap); /// \endcode /// /// With \c readNode() and \c readUndirEdge() functions you can read /// labeled Nodes and UndirEdges. /// /// \code /// reader.readNode("source", sourceNode); /// reader.readNode("target", targetNode); /// /// reader.readUndirEdge("observed", undirEdge); /// \endcode /// /// With the \c readAttribute() functions you can read an attribute /// in a variable. You can specify the reader for the attribute as /// the nodemaps. /// /// After you give all read commands you must call the \c run() member /// function, which execute all the commands. /// /// \code /// reader.run(); /// \endcode /// /// \see GraphReader /// \see DefaultReaderTraits /// \see \ref UndirGraphWriter /// \see \ref graph-io-page /// /// \author Balazs Dezso template class UndirGraphReader { public: typedef _Graph Graph; typedef typename Graph::Node Node; typedef typename Graph::Edge Edge; typedef typename Graph::UndirEdge UndirEdge; typedef _ReaderTraits ReaderTraits; typedef typename ReaderTraits::Skipper DefaultSkipper; /// \brief Construct a new UndirGraphReader. /// /// Construct a new UndirGraphReader. It reads into the given graph /// and it use the given reader as the default skipper. UndirGraphReader(std::istream& _is, Graph& _graph, const DefaultSkipper& _skipper = DefaultSkipper()) : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper), nodeset_reader(*reader, _graph, std::string(), skipper), undir_edgeset_reader(*reader, _graph, nodeset_reader, std::string(), skipper), node_reader(*reader, nodeset_reader, std::string()), undir_edge_reader(*reader, undir_edgeset_reader, std::string()), attribute_reader(*reader, std::string()) {} /// \brief Construct a new UndirGraphReader. /// /// Construct a new UndirGraphReader. It reads into the given graph /// and it use the given reader as the default skipper. UndirGraphReader(const std::string& _filename, Graph& _graph, const DefaultSkipper& _skipper = DefaultSkipper()) : reader(new LemonReader(_filename)), own_reader(true), skipper(_skipper), nodeset_reader(*reader, _graph, std::string(), skipper), undir_edgeset_reader(*reader, _graph, nodeset_reader, std::string(), skipper), node_reader(*reader, nodeset_reader, std::string()), undir_edge_reader(*reader, undir_edgeset_reader, std::string()), attribute_reader(*reader, std::string()) {} /// \brief Construct a new UndirGraphReader. /// /// Construct a new UndirGraphReader. It reads into the given graph /// and it use the given reader as the default skipper. UndirGraphReader(LemonReader& _reader, Graph& _graph, const DefaultSkipper& _skipper = DefaultSkipper()) : reader(_reader), own_reader(false), skipper(_skipper), nodeset_reader(*reader, _graph, std::string(), skipper), undir_edgeset_reader(*reader, _graph, nodeset_reader, std::string(), skipper), node_reader(*reader, nodeset_reader, std::string()), undir_edge_reader(*reader, undir_edgeset_reader, std::string()), attribute_reader(*reader, std::string()) {} /// \brief Destruct the graph reader. /// /// Destruct the graph reader. ~UndirGraphReader() { if (own_reader) delete reader; } /// \brief Give a new node map reading command to the reader. /// /// Give a new node map reading command to the reader. template UndirGraphReader& readNodeMap(std::string name, Map& map) { nodeset_reader.readNodeMap(name, map); return *this; } template UndirGraphReader& readNodeMap(std::string name, const Map& map) { nodeset_reader.readNodeMap(name, map); return *this; } /// \brief Give a new node map reading command to the reader. /// /// Give a new node map reading command to the reader. template UndirGraphReader& readNodeMap(std::string name, Map& map, const Reader& reader = Reader()) { nodeset_reader.readNodeMap(name, map, reader); return *this; } template UndirGraphReader& readNodeMap(std::string name, const Map& map, const Reader& reader = Reader()) { nodeset_reader.readNodeMap(name, map, reader); return *this; } /// \brief Give a new node map skipping command to the reader. /// /// Give a new node map skipping command to the reader. template UndirGraphReader& skipNodeMap(std::string name, const Reader& reader = Reader()) { nodeset_reader.skipNodeMap(name, reader); return *this; } /// \brief Give a new undirected edge map reading command to the reader. /// /// Give a new undirected edge map reading command to the reader. template UndirGraphReader& readUndirEdgeMap(std::string name, Map& map) { undir_edgeset_reader.readUndirEdgeMap(name, map); return *this; } template UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map) { undir_edgeset_reader.readUndirEdgeMap(name, map); return *this; } /// \brief Give a new undirected edge map reading command to the reader. /// /// Give a new undirected edge map reading command to the reader. template UndirGraphReader& readUndirEdgeMap(std::string name, Map& map, const Reader& reader = Reader()) { undir_edgeset_reader.readUndirEdgeMap(name, map, reader); return *this; } template UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map, const Reader& reader = Reader()) { undir_edgeset_reader.readUndirEdgeMap(name, map, reader); return *this; } /// \brief Give a new undirected edge map skipping command to the reader. /// /// Give a new undirected edge map skipping command to the reader. template UndirGraphReader& skipUndirEdgeMap(std::string name, const Reader& reader = Reader()) { undir_edgeset_reader.skipUndirMap(name, reader); return *this; } /// \brief Give a new edge map reading command to the reader. /// /// Give a new edge map reading command to the reader. template UndirGraphReader& readEdgeMap(std::string name, Map& map) { undir_edgeset_reader.readEdgeMap(name, map); return *this; } template UndirGraphReader& readEdgeMap(std::string name, const Map& map) { undir_edgeset_reader.readEdgeMap(name, map); return *this; } /// \brief Give a new edge map reading command to the reader. /// /// Give a new edge map reading command to the reader. template UndirGraphReader& readEdgeMap(std::string name, Map& map, const Reader& reader = Reader()) { undir_edgeset_reader.readEdgeMap(name, map, reader); return *this; } template UndirGraphReader& readEdgeMap(std::string name, const Map& map, const Reader& reader = Reader()) { undir_edgeset_reader.readEdgeMap(name, map, reader); return *this; } /// \brief Give a new edge map skipping command to the reader. /// /// Give a new edge map skipping command to the reader. template UndirGraphReader& skipEdgeMap(std::string name, const Reader& reader = Reader()) { undir_edgeset_reader.skipEdgeMap(name, reader); return *this; } /// \brief Give a new labeled node reading command to the reader. /// /// Give a new labeled node reading command to the reader. UndirGraphReader& readNode(std::string name, Node& node) { node_reader.readNode(name, node); return *this; } /// \brief Give a new labeled edge reading command to the reader. /// /// Give a new labeled edge reading command to the reader. UndirGraphReader& readEdge(std::string name, Edge& edge) { undir_edge_reader.readEdge(name, edge); } /// \brief Give a new labeled undirected edge reading command to the /// reader. /// /// Give a new labeled undirected edge reading command to the reader. UndirGraphReader& readUndirEdge(std::string name, UndirEdge& edge) { undir_edge_reader.readUndirEdge(name, edge); } /// \brief Give a new attribute reading command. /// /// Give a new attribute reading command. template UndirGraphReader& readAttribute(std::string name, Value& value) { attribute_reader.readAttribute(name, value); return *this; } /// \brief Give a new attribute reading command. /// /// Give a new attribute reading command. template UndirGraphReader& readAttribute(std::string name, Value& value, const Reader& reader) { attribute_reader.readAttribute(name, value, reader); return *this; } /// \brief Conversion operator to LemonReader. /// /// Conversion operator to LemonReader. It make possible /// to access the encapsulated \e LemonReader, this way /// you can attach to this reader new instances of /// \e LemonReader::SectionReader. operator LemonReader&() { return *reader; } /// \brief Executes the reading commands. /// /// Executes the reading commands. void run() { reader->run(); } /// \brief Gives back the node by its id. /// /// It reads an id from the stream and gives back which node belongs to /// it. It is possible only if there was read an "id" named node map. Node readId(std::istream& is, Node) const { return nodeset_reader.readId(is, Node()); } /// \brief Gives back the edge by its id. /// /// It reads an id from the stream and gives back which edge belongs to /// it. It is possible only if there was read an "id" named edge map. Edge readId(std::istream& is, Edge) const { return undir_edgeset_reader.readId(is, Edge()); } /// \brief Gives back the undirected edge by its id. /// /// It reads an id from the stream and gives back which undirected edge /// belongs to it. It is possible only if there was read an "id" named /// edge map. UndirEdge readId(std::istream& is, UndirEdge) const { return undir_edgeset_reader.readId(is, UndirEdge()); } private: LemonReader* reader; bool own_reader; DefaultSkipper skipper; NodeSetReader nodeset_reader; UndirEdgeSetReader undir_edgeset_reader; NodeReader node_reader; UndirEdgeReader undir_edge_reader; AttributeReader attribute_reader; }; /// \brief Read an undirected graph from the input. /// /// It is a helper function to read an undirected graph from the given input /// stream. It gives back an UndirGraphReader object and this object /// can read more maps, labeled nodes, edges, undirected edges and /// attributes. /// /// \warning Do not forget to call the \c run() function. /// /// \param is The input stream. /// \param g The graph. template UndirGraphReader undirGraphReader(std::istream& is, Graph &g) { return GraphReader(is, g); } /// \brief Read an undirected graph from the input. /// /// It is a helper function to read an undirected graph from the given input /// file. It gives back an UndirGraphReader object and this object /// can read more maps, labeled nodes, edges, undirected edges and /// attributes. /// /// \warning Do not forget to call the \c run() function. /// /// \param fn The input filename. /// \param g The graph. template UndirGraphReader undirGraphReader(const std::string& fn, Graph &g) { return GraphReader(fn, g); } /// @} } #endif