src/lemon/graph_reader.h
changeset 1333 2640cf6547ff
parent 1311 b810a07248a0
child 1341 bda966891ea0
     1.1 --- a/src/lemon/graph_reader.h	Sat Apr 09 19:32:06 2005 +0000
     1.2 +++ b/src/lemon/graph_reader.h	Sat Apr 09 19:35:33 2005 +0000
     1.3 @@ -34,16 +34,20 @@
     1.4  
     1.5  namespace lemon {
     1.6  
     1.7 +  /// \addtogroup io_group
     1.8 +  /// @{
     1.9  
    1.10    /// \brief Standard ReaderTraits for the GraphReader class.
    1.11    ///
    1.12    /// Standard ReaderTraits for the GraphReader class.
    1.13    /// It defines standard reading method for all type of value. 
    1.14 +  /// \author Balazs Dezso
    1.15    struct DefaultReaderTraits {
    1.16  
    1.17 -   /// \brief Template class for reading an value.
    1.18 +    /// \brief Template class for reading an value.
    1.19      ///
    1.20      /// Template class for reading an value.
    1.21 +    /// \author Balazs Dezso
    1.22      template <typename _Value>
    1.23      struct Reader {
    1.24        /// The value type.
    1.25 @@ -57,6 +61,13 @@
    1.26        }
    1.27      };
    1.28  
    1.29 +    /// \brief Returns wheter this name is an ID map name.
    1.30 +    ///
    1.31 +    /// Returns wheter this name is an ID map name.
    1.32 +    static bool idMapName(const std::string& name) {
    1.33 +      return name == "id";
    1.34 +    }
    1.35 +
    1.36      /// The reader class for the not needed maps.
    1.37      typedef Reader<std::string> DefaultReader;
    1.38  
    1.39 @@ -66,6 +77,7 @@
    1.40    ///
    1.41    /// Reader class for quoted strings. It can process the escape
    1.42    /// sequences in the string.
    1.43 +  /// \author Balazs Dezso
    1.44    class QuotedStringReader {
    1.45    public:
    1.46      typedef std::string Value;
    1.47 @@ -171,12 +183,69 @@
    1.48  
    1.49    /// \brief The graph reader class.
    1.50    ///
    1.51 -  /// \ingroup io_group
    1.52 -  /// The reader class for the graph input.
    1.53 +  ///
    1.54 +  /// The given file format may contain several maps and labeled nodes or 
    1.55 +  /// edges.
    1.56 +  ///
    1.57 +  /// If you read a graph you need not read all the maps and items just those
    1.58 +  /// that you need. The interface of the \c GraphReader is very similar to
    1.59 +  /// the GraphWriter but the reading method does not depend on the order the
    1.60 +  /// given commands.
    1.61 +  ///
    1.62 +  /// The reader object suppose that each not readed value does not contain 
    1.63 +  /// whitespaces, therefore it has some extra possibilities to control how
    1.64 +  /// it should skip the values when the string representation contains spaces.
    1.65 +  ///
    1.66 +  /// \code
    1.67 +  /// GraphReader<ListGraph> reader(std::cin, graph);
    1.68 +  /// \endcode
    1.69 +  ///
    1.70 +  /// The \c addNodeMap() function reads a map from the \c \@nodeset section.
    1.71 +  /// If there is a map that you do not want to read from the file and there is
    1.72 +  /// whitespace in the string represenation of the values then you should
    1.73 +  /// call the \c skipNodeMap() template member function with proper 
    1.74 +  /// parameters.
    1.75 +  ///
    1.76 +  /// \code
    1.77 +  /// reader.addNodeMap("x-coord", xCoordMap);
    1.78 +  /// reader.addNodeMap("y-coord", yCoordMap);
    1.79 +  ///
    1.80 +  /// reader.addNodeMap<QuotedStringReader>("label", labelMap);
    1.81 +  /// reader.skipNodeMap<QuotedStringReader>("description");
    1.82 +  ///
    1.83 +  /// reader.addNodeMap("color", colorMap);
    1.84 +  /// \endcode
    1.85 +  ///
    1.86 +  /// With the \c addEdgeMap() member function you can give an edge map
    1.87 +  /// reading command similar to the NodeMaps. 
    1.88 +  ///
    1.89 +  /// \code
    1.90 +  /// reader.addEdgeMap("weight", weightMap);
    1.91 +  /// reader.addEdgeMap("label", labelMap);
    1.92 +  /// \endcode
    1.93 +  ///
    1.94 +  /// With \c addNode() and \c addEdge() functions you can read labeled Nodes 
    1.95 +  /// and Edges.
    1.96 +  ///
    1.97 +  /// \code
    1.98 +  /// reader.addNode("source", sourceNode);
    1.99 +  /// reader.addNode("target", targetNode);
   1.100 +  ///
   1.101 +  /// reader.addEdge("observed", edge);
   1.102 +  /// \endcode
   1.103 +  ///
   1.104 +  /// After you give all read commands you must call the \c run() member
   1.105 +  /// function, which execute all the commands.
   1.106 +  ///
   1.107 +  /// \code
   1.108 +  /// reader.run();
   1.109 +  /// \endcode
   1.110 +  ///
   1.111    /// \see DefaultReaderTraits
   1.112    /// \see QuotedStringReader
   1.113    /// \see \ref GraphWriter
   1.114    /// \see \ref graph-io-page
   1.115 +  /// \author Balazs Dezso
   1.116    template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits> 
   1.117    class GraphReader {
   1.118    public:
   1.119 @@ -200,7 +269,6 @@
   1.120      ///
   1.121      /// Destruct the graph reader.
   1.122      ~GraphReader() {
   1.123 -
   1.124        for (typename NodeMapReaders::iterator it = node_map_readers.begin(); 
   1.125  	   it != node_map_readers.end(); ++it) {
   1.126  	delete it->second;
   1.127 @@ -364,7 +432,6 @@
   1.128  	std::string id;
   1.129  	std::istringstream ls(line);	
   1.130  	while (ls >> id) {
   1.131 -	  if (id[0] == '#') break;
   1.132  	  typename NodeMapReaders::iterator it = node_map_readers.find(id);
   1.133  	  if (it != node_map_readers.end()) {
   1.134  	    index.push_back(it->second);
   1.135 @@ -372,21 +439,24 @@
   1.136  	  } else {
   1.137  	    index.push_back(&nodeSkipper);
   1.138  	  }
   1.139 +	  if (ReaderTraits::idMapName(id) && nodeInverter.get() == 0) {
   1.140 +	    nodeInverter.reset(index.back()->getInverter());
   1.141 +	    index.back() = nodeInverter.get();
   1.142 +	  }
   1.143  	}
   1.144        }
   1.145  
   1.146 -      if (index.size() == 0) {
   1.147 -	throw DataFormatError("Cannot find node id map");
   1.148 -      }
   1.149 +//       if (index.size() == 0) {
   1.150 +// 	throw DataFormatError("Cannot find node id map");
   1.151 +//       }
   1.152  
   1.153 -      nodeInverter = 
   1.154 -	std::auto_ptr<InverterBase<Node> >(index[0]->getInverter());
   1.155 +//       nodeInverter = 
   1.156 +// 	std::auto_ptr<InverterBase<Node> >(index[0]->getInverter());
   1.157        std::string line;
   1.158        while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   1.159  	Node node = graph.addNode();
   1.160  	std::istringstream ls(line);
   1.161 -	nodeInverter->read(ls, node);
   1.162 -	for (int i = 1; i < (int)index.size(); ++i) {
   1.163 +	for (int i = 0; i < (int)index.size(); ++i) {
   1.164  	  index[i]->read(ls, node);
   1.165  	}
   1.166        }
   1.167 @@ -402,7 +472,6 @@
   1.168  	std::string id;
   1.169  	std::istringstream ls(line);	
   1.170  	while (ls >> id) {
   1.171 -	  if (id[0] == '#') break;
   1.172  	  typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
   1.173  	  if (it != edge_map_readers.end()) {
   1.174  	    index.push_back(it->second);
   1.175 @@ -410,23 +479,29 @@
   1.176  	  } else {
   1.177  	    index.push_back(&edgeSkipper);
   1.178  	  }
   1.179 +	  if (ReaderTraits::idMapName(id) && edgeInverter.get() == 0) {
   1.180 +	    edgeInverter.reset(index.back()->getInverter());
   1.181 +	    index.back() = edgeInverter.get();
   1.182 +	  }
   1.183  	}
   1.184        }
   1.185 +      
   1.186 +      if (nodeInverter.get() == 0) {
   1.187 + 	throw DataFormatError("Cannot find node id map");
   1.188 +      }
   1.189 +//       if (index.size() == 0) {
   1.190 +// 	throw DataFormatError("Cannot find edge id map");
   1.191 +//       }
   1.192  
   1.193 -      if (index.size() == 0) {
   1.194 -	throw DataFormatError("Cannot find edge id map");
   1.195 -      }
   1.196 -
   1.197 -      edgeInverter = 
   1.198 -	std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
   1.199 +//       edgeInverter = 
   1.200 +// 	std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
   1.201        std::string line;
   1.202        while (line = readNotEmptyLine(is, line_num), line[0] != '@') {	
   1.203  	std::istringstream ls(line);
   1.204  	Node source = nodeInverter->read(ls);
   1.205  	Node target = nodeInverter->read(ls);
   1.206  	Edge edge = graph.addEdge(source, target);
   1.207 -	edgeInverter->read(ls, edge);
   1.208 -	for (int i = 1; i < (int)index.size(); ++i) {
   1.209 +	for (int i = 0; i < (int)index.size(); ++i) {
   1.210  	  index[i]->read(ls, edge);
   1.211  	}
   1.212        }      
   1.213 @@ -436,6 +511,9 @@
   1.214      std::string readNodes(int& line_num, 
   1.215  			  std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   1.216        std::string line;
   1.217 +      if (nodeInverter.get() == 0) {
   1.218 + 	throw DataFormatError("Cannot find node id map");
   1.219 +      }
   1.220        while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   1.221  	std::istringstream ls(line);
   1.222  	std::string name;
   1.223 @@ -451,6 +529,9 @@
   1.224      std::string readEdges(int& line_num, 
   1.225  			  std::auto_ptr<InverterBase<Edge> >& edgeInverter) {
   1.226        std::string line;
   1.227 +      if (edgeInverter.get() == 0) {
   1.228 + 	throw DataFormatError("Cannot find edge id map");
   1.229 +      }
   1.230        while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   1.231  	std::istringstream ls(line);
   1.232  	std::string name;
   1.233 @@ -466,23 +547,32 @@
   1.234      std::string readNotEmptyLine(std::istream& is, int& line_num) {
   1.235        std::string line;
   1.236        while (++line_num, getline(is, line)) {	
   1.237 -	int vi = line.find_first_not_of(" \t");
   1.238 -	if (vi != (int)std::string::npos && line[vi] != '#') {
   1.239 +	int vi = line.find('#');
   1.240 +	if (vi != (int)::std::string::npos) {
   1.241 +	  line = line.substr(0, vi);
   1.242 +	}
   1.243 +	vi = line.find_first_not_of(" \t");
   1.244 +	if (vi != (int)std::string::npos) { 
   1.245 +	  std::cerr << "Line: " << line.substr(vi) << std::endl;
   1.246  	  return line.substr(vi);
   1.247  	}
   1.248        }
   1.249        throw DataFormatError("End of stream error");
   1.250      }
   1.251      
   1.252 -    // Inverters store and give back the Item from the id,
   1.253 -    // and may put the ids into a map.
   1.254 +    template <typename _Item>
   1.255 +    class ReaderBase;
   1.256      
   1.257      template <typename _Item>
   1.258 -    class InverterBase {
   1.259 +    class InverterBase : public ReaderBase<_Item> {
   1.260      public:
   1.261        typedef _Item Item;
   1.262        virtual void read(std::istream&, const Item&) = 0;
   1.263        virtual Item read(std::istream&) = 0;
   1.264 +
   1.265 +      virtual InverterBase<_Item>* getInverter() {
   1.266 +	return this;
   1.267 +      }
   1.268      };
   1.269  
   1.270      template <typename _Item, typename _Map, typename _Reader>
   1.271 @@ -651,7 +741,15 @@
   1.272  
   1.273    };
   1.274  
   1.275 -  /// Ready to use reader function.  
   1.276 +  /// \brief Read a graph from the input.
   1.277 +  ///
   1.278 +  /// Read a graph from the input.
   1.279 +  /// \param is The input stream.
   1.280 +  /// \param g The graph.
   1.281 +  /// \param capacity The capacity map.
   1.282 +  /// \param s The source node.
   1.283 +  /// \param t The target node.
   1.284 +  /// \param cost The cost map.
   1.285    template<typename Graph, typename CapacityMap, typename CostMap>
   1.286    void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   1.287  		  typename Graph::Node &s, typename Graph::Node &t, 
   1.288 @@ -664,6 +762,14 @@
   1.289      reader.run();
   1.290    }
   1.291  
   1.292 +  /// \brief Read a graph from the input.
   1.293 +  ///
   1.294 +  /// Read a graph from the input.
   1.295 +  /// \param is The input stream.
   1.296 +  /// \param g The graph.
   1.297 +  /// \param capacity The capacity map.
   1.298 +  /// \param s The source node.
   1.299 +  /// \param t The target node.
   1.300    template<typename Graph, typename CapacityMap>
   1.301    void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   1.302  		  typename Graph::Node &s, typename Graph::Node &t) {
   1.303 @@ -674,6 +780,13 @@
   1.304      reader.run();
   1.305    }
   1.306  
   1.307 +  /// \brief Read a graph from the input.
   1.308 +  ///
   1.309 +  /// Read a graph from the input.
   1.310 +  /// \param is The input stream.
   1.311 +  /// \param g The graph.
   1.312 +  /// \param capacity The capacity map.
   1.313 +  /// \param s The source node.
   1.314    template<typename Graph, typename CapacityMap>
   1.315    void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   1.316  		  typename Graph::Node &s) {
   1.317 @@ -683,6 +796,12 @@
   1.318      reader.run();
   1.319    }
   1.320  
   1.321 +  /// \brief Read a graph from the input.
   1.322 +  ///
   1.323 +  /// Read a graph from the input.
   1.324 +  /// \param is The input stream.
   1.325 +  /// \param g The graph.
   1.326 +  /// \param capacity The capacity map.
   1.327    template<typename Graph, typename CapacityMap>
   1.328    void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
   1.329      GraphReader<Graph> reader(is, g);
   1.330 @@ -690,12 +809,18 @@
   1.331      reader.run();
   1.332    }
   1.333  
   1.334 +  /// \brief Read a graph from the input.
   1.335 +  ///
   1.336 +  /// Read a graph from the input.
   1.337 +  /// \param is The input stream.
   1.338 +  /// \param g The graph.
   1.339    template<typename Graph>
   1.340    void readGraph(std::istream& is, Graph &g) {
   1.341      GraphReader<Graph> reader(is, g);
   1.342      reader.run();
   1.343    }
   1.344  
   1.345 +  /// @}
   1.346  }
   1.347  
   1.348  #endif