williamr@2: //======================================================================= williamr@2: // Copyright 2001 Universite Joseph Fourier, Grenoble. williamr@2: // Author: François Faure williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: //======================================================================= williamr@2: #ifndef BOOST_GRAPH_ADJACENCY_LIST_IO_HPP williamr@2: #define BOOST_GRAPH_ADJACENCY_LIST_IO_HPP williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: // Method read to parse an adjacency list from an input stream. Examples: williamr@2: // cin >> read( G ); williamr@2: // cin >> read( G, NodePropertySubset(), EdgepropertySubset() ); williamr@2: // williamr@2: // Method write to print an adjacency list to an output stream. Examples: williamr@2: // cout << write( G ); williamr@2: // cout << write( G, NodePropertySubset(), EdgepropertySubset() ); williamr@2: williamr@2: namespace boost { williamr@2: williamr@2: /* outline williamr@2: - basic property input williamr@2: - get property subset williamr@2: - graph parser williamr@2: - property printer williamr@2: - graph printer williamr@2: - user methods williamr@2: */ williamr@2: williamr@2: //=========================================================================== williamr@2: // basic property input williamr@2: williamr@2: template williamr@2: std::istream& operator >> ( std::istream& in, property& p ) williamr@2: { williamr@2: in >> p.m_value >> *(static_cast(&p)); // houpla !! williamr@2: return in; williamr@2: } williamr@2: williamr@2: template williamr@2: std::istream& operator >> ( std::istream& in, property& p ) williamr@2: { williamr@2: in >> p.m_value; williamr@2: return in; williamr@2: } williamr@2: williamr@2: inline std::istream& operator >> ( std::istream& in, no_property& ) williamr@2: { williamr@2: return in; williamr@2: } williamr@2: williamr@2: // basic property input williamr@2: //=========================================================================== williamr@2: // get property subsets williamr@2: williamr@2: // get a single property tagged Stag williamr@2: template williamr@2: void get williamr@2: ( property& p, const V& v, Stag s ) williamr@2: { williamr@2: get( *(static_cast(&p)),v,s ); williamr@2: } williamr@2: williamr@2: template williamr@2: void get williamr@2: ( property& p, const V& v, Stag ) williamr@2: { williamr@2: p.m_value = v; williamr@2: } williamr@2: williamr@2: // get a subset of properties tagged Stag williamr@2: template williamr@2: void getSubset williamr@2: ( property& p, const property& s ) williamr@2: { williamr@2: get( p, s.m_value, Stag() ); williamr@2: getSubset( p, Snext(s) ); williamr@2: } williamr@2: williamr@2: template williamr@2: void getSubset williamr@2: ( property& p, const property& s) williamr@2: { williamr@2: get( p, s.m_value, Stag() ); williamr@2: } williamr@2: williamr@2: inline void getSubset williamr@2: ( no_property& p, const no_property& s ) williamr@2: { williamr@2: } williamr@2: williamr@2: #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) williamr@2: template williamr@2: void getSubset(T& p, const U& s) williamr@2: { williamr@2: p = s; williamr@2: } williamr@2: williamr@2: template williamr@2: void getSubset(T&, const no_property&) williamr@2: { williamr@2: } williamr@2: williamr@2: williamr@2: #endif williamr@2: williamr@2: // get property subset williamr@2: //=========================================================================== williamr@2: // graph parser williamr@2: typedef enum{ PARSE_NUM_NODES, PARSE_VERTEX, PARSE_EDGE } GraphParserState; williamr@2: williamr@2: template williamr@2: struct GraphParser williamr@2: { williamr@2: williamr@2: typedef Graph_t Graph; williamr@2: williamr@2: GraphParser( Graph* g ): graph(g) williamr@2: {} williamr@2: williamr@2: GraphParser& operator () ( std::istream& in ) williamr@2: { williamr@2: typedef typename graph_traits::vertex_descriptor Vertex; williamr@2: std::vector nodes; williamr@2: williamr@2: GraphParserState state = PARSE_VERTEX; williamr@2: williamr@2: unsigned int numLine = 1; williamr@2: char c; williamr@2: while ( in.get(c) ) williamr@2: { williamr@2: if( c== '#' ) skip(in); williamr@2: else if( c== 'n' ) state = PARSE_NUM_NODES; williamr@2: else if( c== 'v' ) state = PARSE_VERTEX; williamr@2: else if( c== 'e' ) state = PARSE_EDGE; williamr@2: else if( c== '\n' ) numLine++; williamr@2: else if( !std::isspace(c) ){ williamr@2: in.putback(c); williamr@2: if( state == PARSE_VERTEX ){ williamr@2: VertexPropertySubset readProp; williamr@2: if( in >> readProp ) williamr@2: { williamr@2: VertexProperty vp; williamr@2: getSubset( vp, readProp ); williamr@2: nodes.push_back( add_vertex(vp, *graph) ); williamr@2: } williamr@2: else williamr@2: std::cerr<<"read vertex, parse error at line"<> source >> target; williamr@2: if( in >> readProp ) williamr@2: { williamr@2: EdgeProperty ep; williamr@2: getSubset( ep, readProp ); williamr@2: add_edge(nodes[source], nodes[target], ep, *graph); williamr@2: } williamr@2: else williamr@2: std::cerr<<"read edge, parse error at line"<> n ){ williamr@2: for( int i=0; i williamr@2: struct PropertyPrinter williamr@2: { williamr@2: typedef typename Property::value_type Value; williamr@2: typedef typename Property::tag_type Tag; williamr@2: typedef typename Property::next_type Next; williamr@2: williamr@2: PropertyPrinter( const Graph& g ):graph(&g){} williamr@2: williamr@2: template williamr@2: PropertyPrinter& operator () ( std::ostream& out, Iterator it ) williamr@2: { williamr@2: typename property_map::type ps = get(Tag(), *graph); williamr@2: out << ps[ *it ] <<" "; williamr@2: PropertyPrinter print(*graph); williamr@2: print(out, it); williamr@2: return (*this); williamr@2: } williamr@2: private: williamr@2: const Graph* graph; williamr@2: }; williamr@2: #else williamr@2: template williamr@2: struct PropertyPrinter williamr@2: { williamr@2: PropertyPrinter( const Graph& g ):graph(&g){} williamr@2: williamr@2: template williamr@2: PropertyPrinter& operator () ( std::ostream& out, Iterator it ) williamr@2: { williamr@2: out << (*graph)[ *it ] <<" "; williamr@2: return (*this); williamr@2: } williamr@2: private: williamr@2: const Graph* graph; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct PropertyPrinter > williamr@2: { williamr@2: PropertyPrinter( const Graph& g ):graph(&g){} williamr@2: williamr@2: template williamr@2: PropertyPrinter& operator () ( std::ostream& out, Iterator it ) williamr@2: { williamr@2: typename property_map::type ps = get(Tag(), *graph); williamr@2: out << ps[ *it ] <<" "; williamr@2: PropertyPrinter print(*graph); williamr@2: print(out, it); williamr@2: return (*this); williamr@2: } williamr@2: private: williamr@2: const Graph* graph; williamr@2: }; williamr@2: #endif williamr@2: williamr@2: template williamr@2: struct PropertyPrinter williamr@2: { williamr@2: PropertyPrinter( const Graph& ){} williamr@2: williamr@2: template williamr@2: PropertyPrinter& operator () ( std::ostream&, Iterator it ){ return *this; } williamr@2: }; williamr@2: williamr@2: // property printer williamr@2: //========================================================================= williamr@2: // graph printer williamr@2: williamr@2: template williamr@2: struct EdgePrinter williamr@2: { williamr@2: williamr@2: typedef Graph_t Graph; williamr@2: typedef typename graph_traits::vertex_descriptor Vertex; williamr@2: williamr@2: EdgePrinter( const Graph& g ) williamr@2: : graph(g) williamr@2: {} williamr@2: williamr@2: const EdgePrinter& operator () ( std::ostream& out ) const williamr@2: { williamr@2: // assign indices to vertices williamr@2: std::map indices; williamr@2: int num = 0; williamr@2: typename graph_traits::vertex_iterator vi; williamr@2: for (vi = vertices(graph).first; vi != vertices(graph).second; ++vi){ williamr@2: indices[*vi] = num++; williamr@2: } williamr@2: williamr@2: // write edges williamr@2: PropertyPrinter print_Edge(graph); williamr@2: out << "e" << std::endl; williamr@2: typename graph_traits::edge_iterator ei; williamr@2: for (ei = edges(graph).first; ei != edges(graph).second; ++ei){ williamr@2: out << indices[source(*ei,graph)] << " " << indices[target(*ei,graph)] << " "; williamr@2: print_Edge(out,ei); williamr@2: out << std::endl; williamr@2: } williamr@2: out << std::endl; williamr@2: return (*this); williamr@2: } williamr@2: williamr@2: protected: williamr@2: williamr@2: const Graph& graph; williamr@2: williamr@2: }; williamr@2: williamr@2: template williamr@2: struct GraphPrinter: public EdgePrinter williamr@2: { williamr@2: GraphPrinter( const Graph& g ) williamr@2: : EdgePrinter(g) williamr@2: {} williamr@2: williamr@2: const GraphPrinter& operator () ( std::ostream& out ) const williamr@2: { williamr@2: PropertyPrinter printNode(this->graph); williamr@2: out << "v"<::vertex_iterator vi; williamr@2: for (vi = vertices(this->graph).first; vi != vertices(this->graph).second; ++vi){ williamr@2: printNode(out,vi); williamr@2: out << std::endl; williamr@2: } williamr@2: williamr@2: EdgePrinter::operator ()( out ); williamr@2: return (*this); williamr@2: } williamr@2: }; williamr@2: williamr@2: template williamr@2: struct GraphPrinter williamr@2: : public EdgePrinter williamr@2: { williamr@2: GraphPrinter( const Graph& g ) williamr@2: : EdgePrinter(g) williamr@2: {} williamr@2: williamr@2: const GraphPrinter& operator () ( std::ostream& out ) const williamr@2: { williamr@2: out << "n "<< num_vertices(this->graph) << std::endl; williamr@2: EdgePrinter::operator ()( out ); williamr@2: return (*this); williamr@2: } williamr@2: }; williamr@2: williamr@2: // graph printer williamr@2: //========================================================================= williamr@2: // user methods williamr@2: williamr@2: /// input stream for reading a graph williamr@2: template williamr@2: std::istream& operator >> ( std::istream& in, GraphParser gp ) williamr@2: { williamr@2: gp(in); williamr@2: return in; williamr@2: } williamr@2: williamr@2: /// graph parser for given subsets of internal vertex and edge properties williamr@2: template williamr@2: GraphParser,VP,EP,VPS,EPS> williamr@2: read( adjacency_list& g, VPS vps, EPS eps ) williamr@2: { williamr@2: return GraphParser,VP,EP,VPS,EPS>(&g); williamr@2: } williamr@2: williamr@2: /// graph parser for all internal vertex and edge properties williamr@2: template williamr@2: GraphParser,VP,EP,VP,EP> williamr@2: read( adjacency_list& g ) williamr@2: { williamr@2: return GraphParser,VP,EP,VP,EP>(&g); williamr@2: } williamr@2: williamr@2: williamr@2: /// output stream for writing a graph williamr@2: template williamr@2: std::ostream& operator << ( std::ostream& out, const GraphPrinter& gp ) williamr@2: { williamr@2: gp(out); williamr@2: return out; williamr@2: } williamr@2: williamr@2: /// write the graph with given property subsets williamr@2: template williamr@2: GraphPrinter,VPS,EPS> williamr@2: write( const adjacency_list& g, VPS, EPS ) williamr@2: { williamr@2: return GraphPrinter,VPS,EPS>(g); williamr@2: } williamr@2: williamr@2: /// write the graph with all internal vertex and edge properties williamr@2: template williamr@2: GraphPrinter,VP,EP> williamr@2: write( const adjacency_list& g ) williamr@2: { williamr@2: return GraphPrinter,VP,EP>(g); williamr@2: } williamr@2: williamr@2: // user methods williamr@2: //========================================================================= williamr@2: }// boost williamr@2: #endif