src/lemon/graph_reader.h
changeset 1408 892c29484414
parent 1396 56f9a4ba9149
child 1421 7a21e1414c38
     1.1 --- a/src/lemon/graph_reader.h	Fri May 06 15:39:33 2005 +0000
     1.2 +++ b/src/lemon/graph_reader.h	Mon May 09 11:24:26 2005 +0000
     1.3 @@ -22,173 +22,17 @@
     1.4  #define LEMON_GRAPH_READER_H
     1.5  
     1.6  #include <iostream>
     1.7 -#include <sstream>
     1.8 -
     1.9 -#include <map>
    1.10 -#include <vector>
    1.11 -
    1.12 -#include <memory>
    1.13  
    1.14  #include <lemon/error.h>
    1.15 -
    1.16 +#include <lemon/lemon_reader.h>
    1.17  
    1.18  namespace lemon {
    1.19  
    1.20    /// \addtogroup io_group
    1.21    /// @{
    1.22  
    1.23 -  /// \brief Standard ReaderTraits for the GraphReader class.
    1.24 -  ///
    1.25 -  /// Standard ReaderTraits for the GraphReader class.
    1.26 -  /// It defines standard reading method for all type of value. 
    1.27 -  /// \author Balazs Dezso
    1.28 -  struct DefaultReaderTraits {
    1.29 -
    1.30 -    /// \brief Template class for reading an value.
    1.31 -    ///
    1.32 -    /// Template class for reading an value.
    1.33 -    /// \author Balazs Dezso
    1.34 -    template <typename _Value>
    1.35 -    struct Reader {
    1.36 -      /// The value type.
    1.37 -      typedef _Value Value;
    1.38 -      /// \brief Reads a value from the given stream.
    1.39 -      ///
    1.40 -      /// Reads a value from the given stream.
    1.41 -      void read(std::istream& is, Value& value) {
    1.42 -	if (!(is >> value)) 
    1.43 -	  throw DataFormatError("Default reader format exception");
    1.44 -      }
    1.45 -    };
    1.46 -
    1.47 -    /// \brief Returns wheter this name is an ID map name.
    1.48 -    ///
    1.49 -    /// Returns wheter this name is an ID map name.
    1.50 -    static bool idMapName(const std::string& name) {
    1.51 -      return name == "id";
    1.52 -    }
    1.53 -
    1.54 -    /// The reader class for the not needed maps.
    1.55 -    typedef Reader<std::string> DefaultReader;
    1.56 -
    1.57 -  };
    1.58 -
    1.59 -  /// \brief Reader class for quoted strings.
    1.60 -  ///
    1.61 -  /// Reader class for quoted strings. It can process the escape
    1.62 -  /// sequences in the string.
    1.63 -  /// \author Balazs Dezso
    1.64 -  class QuotedStringReader {
    1.65 -  public:
    1.66 -    typedef std::string Value;
    1.67 -    
    1.68 -    /// \brief Constructor for the reader.
    1.69 -    ///
    1.70 -    /// Constructor for the reader. If the given parameter is true
    1.71 -    /// the reader processes the escape sequences.
    1.72 -    QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
    1.73 -    
    1.74 -    /// \brief Reads a quoted string from the given stream.
    1.75 -    ///
    1.76 -    /// Reads a quoted string from the given stream.
    1.77 -    void read(std::istream& is, std::string& value) {
    1.78 -      char c;
    1.79 -      value.clear();
    1.80 -      is >> std::ws;
    1.81 -      if (!is.get(c) || c != '\"') 
    1.82 -	throw DataFormatError("Quoted string format error");
    1.83 -      while (is.get(c) && c != '\"') {
    1.84 -	if (escaped && c == '\\') {
    1.85 -	  value += readEscape(is);
    1.86 -	} else {
    1.87 -	  value += c;
    1.88 -	}
    1.89 -      }
    1.90 -      if (!is) throw DataFormatError("Quoted string format error");
    1.91 -    }
    1.92 -
    1.93 -  private:
    1.94 -    
    1.95 -    static char readEscape(std::istream& is) {
    1.96 -      char c;
    1.97 -      switch (is.get(c), c) {
    1.98 -      case '\\':
    1.99 -	return '\\';
   1.100 -      case '\"':
   1.101 -	return '\"';
   1.102 -      case '\'':
   1.103 -	return '\'';
   1.104 -      case '\?':
   1.105 -	return '\?';
   1.106 -      case 'a':
   1.107 -	return '\a';
   1.108 -      case 'b':
   1.109 -	return '\b';
   1.110 -      case 'f':
   1.111 -	return '\f';
   1.112 -      case 'n':
   1.113 -	return '\n';
   1.114 -      case 'r':
   1.115 -	return '\r';
   1.116 -      case 't':
   1.117 -	return '\t';
   1.118 -      case 'v':
   1.119 -	return '\v';
   1.120 -      case 'x':
   1.121 -	{
   1.122 -	  int code;
   1.123 -	  if (!is.get(c) || !isHex(c)) 
   1.124 -	    throw DataFormatError("Escape format error");
   1.125 -	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
   1.126 -	  else code = code * 16 + valueHex(c);
   1.127 -	  return code;
   1.128 -	}
   1.129 -      default:
   1.130 -	{
   1.131 -	  int code;
   1.132 -	  if (!isOct(c)) 
   1.133 -	    throw DataFormatError("Escape format error");
   1.134 -	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
   1.135 -	    is.putback(c);
   1.136 -	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
   1.137 -	    is.putback(c);
   1.138 -	  else code = code * 8 + valueOct(c);
   1.139 -	  return code;
   1.140 -	}	      
   1.141 -      } 
   1.142 -    }
   1.143 -
   1.144 -    static bool isOct(char c) {
   1.145 -      return '0' <= c && c <='7'; 
   1.146 -    }
   1.147 -    
   1.148 -    static int valueOct(char c) {
   1.149 -      return c - '0';
   1.150 -    }
   1.151 -
   1.152 -   static bool isHex(char c) {
   1.153 -      return ('0' <= c && c <= '9') || 
   1.154 -	('a' <= c && c <= 'z') || 
   1.155 -	('A' <= c && c <= 'Z'); 
   1.156 -    }
   1.157 -    
   1.158 -    static int valueHex(char c) {
   1.159 -      if ('0' <= c && c <= '9') return c - '0';
   1.160 -      if ('a' <= c && c <= 'z') return c - 'a' + 10;
   1.161 -      return c - 'A' + 10;
   1.162 -    }
   1.163 -
   1.164 -    bool escaped;
   1.165 -  };
   1.166 -
   1.167 -  class GUIReader {
   1.168 -  public:
   1.169 -    virtual void read(std::istream& is) = 0;
   1.170 -  };
   1.171 -
   1.172    /// \brief The graph reader class.
   1.173    ///
   1.174 -  ///
   1.175    /// The given file format may contain several maps and labeled nodes or 
   1.176    /// edges.
   1.177    ///
   1.178 @@ -229,8 +73,8 @@
   1.179    /// reader.readEdgeMap("label", labelMap);
   1.180    /// \endcode
   1.181    ///
   1.182 -  /// With \c readNode() and \c readEdge() functions you can read labeled Nodes 
   1.183 -  /// and Edges.
   1.184 +  /// With \c readNode() and \c readEdge() functions you can read 
   1.185 +  /// labeled Nodes and Edges.
   1.186    ///
   1.187    /// \code
   1.188    /// reader.readNode("source", sourceNode);
   1.189 @@ -239,6 +83,10 @@
   1.190    /// reader.readEdge("observed", edge);
   1.191    /// \endcode
   1.192    ///
   1.193 +  /// With the \c readAttribute() functions you can read an attribute
   1.194 +  /// in a variable. You can specify the reader for the attribute as
   1.195 +  /// the nodemaps.
   1.196 +  ///
   1.197    /// After you give all read commands you must call the \c run() member
   1.198    /// function, which execute all the commands.
   1.199    ///
   1.200 @@ -260,31 +108,56 @@
   1.201      typedef typename Graph::Edge Edge;
   1.202  
   1.203      typedef _ReaderTraits ReaderTraits;
   1.204 -    typedef typename ReaderTraits::DefaultReader DefaultReader;
   1.205 +    typedef typename ReaderTraits::Skipper DefaultSkipper;
   1.206  
   1.207      /// \brief Construct a new GraphReader.
   1.208      ///
   1.209      /// Construct a new GraphReader. It reads into the given graph
   1.210      /// and it use the given reader as the default skipper.
   1.211      GraphReader(std::istream& _is, Graph& _graph, 
   1.212 -		const DefaultReader& _reader = DefaultReader()) 
   1.213 -      : gui_reader(0), is(_is), graph(_graph), 
   1.214 -	nodeSkipper(_reader), edgeSkipper(_reader) {}
   1.215 +		const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.216 +      : reader(new LemonReader(_is)), own_reader(true), 
   1.217 +	graph(_graph), skipper(_skipper),
   1.218 +	nodeset_reader(*reader, graph, std::string(), skipper),
   1.219 +	edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
   1.220 +	node_reader(*reader, nodeset_reader, std::string()),
   1.221 +	edge_reader(*reader, edgeset_reader, std::string()),
   1.222 +	attribute_reader(*reader, std::string()) {}
   1.223 +
   1.224 +    /// \brief Construct a new GraphReader.
   1.225 +    ///
   1.226 +    /// Construct a new GraphReader. It reads into the given graph
   1.227 +    /// and it use the given reader as the default skipper.
   1.228 +    GraphReader(const std::string& _filename, Graph& _graph, 
   1.229 +		const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.230 +      : reader(new LemonReader(_filename)), own_reader(true), 
   1.231 +	graph(_graph), skipper(_skipper),
   1.232 +	nodeset_reader(*reader, graph, std::string(), skipper),
   1.233 +	edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
   1.234 +	node_reader(*reader, nodeset_reader, std::string()),
   1.235 +	edge_reader(*reader, edgeset_reader, std::string()),
   1.236 +	attribute_reader(*reader, std::string()) {}
   1.237 +
   1.238 +    /// \brief Construct a new GraphReader.
   1.239 +    ///
   1.240 +    /// Construct a new GraphReader. It reads into the given graph
   1.241 +    /// and it use the given reader as the default skipper.
   1.242 +    GraphReader(LemonReader& _reader, Graph& _graph, 
   1.243 +		const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.244 +      : reader(_reader), own_reader(false), 
   1.245 +	graph(_graph), skipper(_skipper),
   1.246 +	nodeset_reader(*reader, graph, std::string(), skipper),
   1.247 +	edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
   1.248 +	node_reader(*reader, nodeset_reader, std::string()),
   1.249 +	edge_reader(*reader, edgeset_reader, std::string()),
   1.250 +	attribute_reader(*reader, std::string()) {}
   1.251  
   1.252      /// \brief Destruct the graph reader.
   1.253      ///
   1.254      /// Destruct the graph reader.
   1.255      ~GraphReader() {
   1.256 -      for (typename NodeMapReaders::iterator it = node_map_readers.begin(); 
   1.257 -	   it != node_map_readers.end(); ++it) {
   1.258 -	delete it->second;
   1.259 -      }
   1.260 -
   1.261 -      for (typename EdgeMapReaders::iterator it = edge_map_readers.begin(); 
   1.262 -	   it != edge_map_readers.end(); ++it) {
   1.263 -	delete it->second;
   1.264 -      }
   1.265 -
   1.266 +      if (own_reader) 
   1.267 +	delete reader;
   1.268      }
   1.269  
   1.270      /// \brief Add a new node map reader command for the reader.
   1.271 @@ -292,8 +165,8 @@
   1.272      /// Add a new node map reader command for the reader.
   1.273      template <typename Map>
   1.274      GraphReader& readNodeMap(std::string name, Map& map) {
   1.275 -      return readNodeMap<typename ReaderTraits::template 
   1.276 -	Reader<typename Map::Value>, Map>(name, map);
   1.277 +      nodeset_reader.readMap(name, map);
   1.278 +      return *this;
   1.279      }
   1.280  
   1.281      /// \brief Add a new node map reader command for the reader.
   1.282 @@ -302,13 +175,7 @@
   1.283      template <typename Reader, typename Map>
   1.284      GraphReader& readNodeMap(std::string name, Map& map, 
   1.285  			     const Reader& reader = Reader()) {
   1.286 -      if (node_map_readers.find(name) != node_map_readers.end()) {
   1.287 -	ErrorMessage msg;
   1.288 -	msg << "Multiple read rule for node map: " << name;
   1.289 -	throw IOParameterError(msg.message());
   1.290 -      }
   1.291 -      node_map_readers.insert(
   1.292 -        make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
   1.293 +      nodeset_reader.readMap(name, map, reader);
   1.294        return *this;
   1.295      }
   1.296  
   1.297 @@ -318,13 +185,7 @@
   1.298      template <typename Reader>
   1.299      GraphReader& skipNodeMap(std::string name, 
   1.300  			     const Reader& reader = Reader()) {
   1.301 -      if (node_map_readers.find(name) != node_map_readers.end()) {
   1.302 -	ErrorMessage msg;
   1.303 -	msg << "Multiple read rule for node map: " << name;
   1.304 -	throw IOParameterError(msg.message());
   1.305 -      }
   1.306 -      node_map_readers.insert(
   1.307 -        make_pair(name, new SkipReader<Node, Reader>(reader)));
   1.308 +      nodeset_reader.skipMap(name, reader);
   1.309        return *this;
   1.310      }
   1.311  
   1.312 @@ -333,8 +194,8 @@
   1.313      /// Add a new edge map reader command for the reader.
   1.314      template <typename Map>
   1.315      GraphReader& readEdgeMap(std::string name, Map& map) { 
   1.316 -      return readEdgeMap<typename ReaderTraits::template
   1.317 -	Reader<typename Map::Value>, Map>(name, map);
   1.318 +      edgeset_reader.readMap(name, map);
   1.319 +      return *this;
   1.320      }
   1.321  
   1.322  
   1.323 @@ -344,13 +205,7 @@
   1.324      template <typename Reader, typename Map>
   1.325      GraphReader& readEdgeMap(std::string name, Map& map,
   1.326  			     const Reader& reader = Reader()) {
   1.327 -      if (edge_map_readers.find(name) != edge_map_readers.end()) {
   1.328 -	ErrorMessage msg;
   1.329 -	msg << "Multiple read rule for edge map: " << name;
   1.330 -	throw IOParameterError(msg.message());
   1.331 -      }
   1.332 -      edge_map_readers.insert(
   1.333 -        make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
   1.334 +      edgeset_reader.readMap(name, map, reader);
   1.335        return *this;
   1.336      }
   1.337  
   1.338 @@ -360,13 +215,8 @@
   1.339      template <typename Reader>
   1.340      GraphReader& skipEdgeMap(std::string name,
   1.341  			     const Reader& reader = Reader()) {
   1.342 -      if (edge_map_readers.find(name) != edge_map_readers.end()) {
   1.343 -	ErrorMessage msg;
   1.344 -	msg << "Multiple read rule for edge map: " << name;
   1.345 -	throw IOParameterError(msg.message());
   1.346 -      }
   1.347 -      edge_map_readers.insert(
   1.348 -        make_pair(name, new SkipReader<Edge, Reader>(reader)));
   1.349 +
   1.350 +      edgeset_reader.skipMap(name, reader);
   1.351        return *this;
   1.352      }
   1.353  
   1.354 @@ -374,12 +224,7 @@
   1.355      ///
   1.356      /// Add a new labeled node reader for the reader.
   1.357      GraphReader& readNode(std::string name, Node& node) {
   1.358 -      if (node_readers.find(name) != node_readers.end()) {
   1.359 -	ErrorMessage msg;
   1.360 -	msg << "Multiple read rule for node: " << name;
   1.361 -	throw IOParameterError(msg.message());
   1.362 -      }
   1.363 -      node_readers.insert(make_pair(name, &node));
   1.364 +      node_reader.readNode(name, node);
   1.365        return *this;
   1.366      }
   1.367  
   1.368 @@ -387,385 +232,61 @@
   1.369      ///
   1.370      /// Add a new labeled edge reader for the reader.
   1.371      GraphReader& readEdge(std::string name, Edge& edge) {
   1.372 -      if (edge_readers.find(name) != edge_readers.end()) {
   1.373 -	ErrorMessage msg;
   1.374 -	msg << "Multiple read rule for edge: " << name;
   1.375 -	throw IOParameterError(msg.message());
   1.376 -      }
   1.377 -      edge_readers.insert(make_pair(name, &edge));
   1.378 +      edge_reader.readEdge(name, edge);
   1.379 +    }
   1.380 +
   1.381 +    /// \brief Add a new attribute reader command.
   1.382 +    ///
   1.383 +    ///  Add a new attribute reader command.
   1.384 +    template <typename Value>
   1.385 +    GraphReader& readAttribute(std::string name, Value& value) {
   1.386 +      attribute_reader.readAttribute(name, value);
   1.387        return *this;
   1.388      }
   1.389 +    
   1.390 +    /// \brief Add a new attribute reader command.
   1.391 +    ///
   1.392 +    ///  Add a new attribute reader command.
   1.393 +    template <typename Reader, typename Value>
   1.394 +    GraphReader& readAttribute(std::string name, Value& value, 
   1.395 +			       const Reader& reader) {
   1.396 +      attribute_reader.readAttribute<Reader>(name, value, reader);
   1.397 +      return *this;
   1.398 +    }
   1.399 +
   1.400 +    /// \brief Conversion operator to LemonReader.
   1.401 +    ///
   1.402 +    /// Conversion operator to LemonReader. It make possible
   1.403 +    /// to access the encapsulated \e LemonReader, this way
   1.404 +    /// you can attach to this reader new instances of 
   1.405 +    /// \e LemonReader::SectionReader.
   1.406 +    operator LemonReader&() {
   1.407 +      return *reader;
   1.408 +    }
   1.409  
   1.410      /// \brief Executes the reader commands.
   1.411      ///
   1.412      /// Executes the reader commands.
   1.413      void run() {
   1.414 -      int line_num = 0;
   1.415 -      std::auto_ptr<InverterBase<Node> > nodeInverter;
   1.416 -      std::auto_ptr<InverterBase<Edge> > edgeInverter;
   1.417 -      try {
   1.418 -	std::string line = readNotEmptyLine(is, line_num);
   1.419 -	if (line.find("@nodeset") == 0) {
   1.420 -	  line = readNodeSet(line_num, nodeInverter);
   1.421 -	} 
   1.422 -	if (line.find("@edgeset") == 0) {
   1.423 -	  line = readEdgeSet(line_num, edgeInverter, nodeInverter);
   1.424 -	}
   1.425 -	if (line.find("@nodes") == 0) {
   1.426 -	  line = readNodes(line_num, nodeInverter);
   1.427 -	}
   1.428 -	if (line.find("@edges") == 0) {
   1.429 -	  line = readEdges(line_num, edgeInverter);
   1.430 -	}
   1.431 -	if (line.find("@gui") == 0) {
   1.432 -	  line = readGUI(line_num);
   1.433 -	}
   1.434 -	if (line.find("@end") != 0) {
   1.435 -	  throw DataFormatError("Invalid control sequence error");
   1.436 -	}
   1.437 -      } catch (DataFormatError e) {
   1.438 -	e.line(line_num);
   1.439 -	throw e;
   1.440 -      }
   1.441 -    }
   1.442 -
   1.443 -    GraphReader& readGUI(GUIReader& reader) {
   1.444 -      gui_reader = &reader;
   1.445 -      return *this;
   1.446 +      reader->run();
   1.447      }
   1.448  
   1.449    private:
   1.450  
   1.451 -    template <typename Item> class InverterBase;
   1.452 +    LemonReader* reader;
   1.453 +    bool own_reader;
   1.454  
   1.455 -    std::string readNodeSet(int& line_num, 
   1.456 -			    std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   1.457 -      std::vector<ReaderBase<Node>* > index;
   1.458 -      {
   1.459 -	std::string line = readNotEmptyLine(is, line_num);    
   1.460 -	std::string id;
   1.461 -	std::istringstream ls(line);	
   1.462 -	while (ls >> id) {
   1.463 -	  typename NodeMapReaders::iterator it = node_map_readers.find(id);
   1.464 -	  if (it != node_map_readers.end()) {
   1.465 -	    index.push_back(it->second);
   1.466 -	    node_map_readers.erase(it);
   1.467 -	  } else {
   1.468 -	    index.push_back(&nodeSkipper);
   1.469 -	  }
   1.470 -	  if (ReaderTraits::idMapName(id) && nodeInverter.get() == 0) {
   1.471 -	    nodeInverter.reset(index.back()->getInverter());
   1.472 -	    index.back() = nodeInverter.get();
   1.473 -	  }
   1.474 -	}
   1.475 -      }
   1.476 -
   1.477 -//       if (index.size() == 0) {
   1.478 -// 	throw DataFormatError("Cannot find node id map");
   1.479 -//       }
   1.480 -
   1.481 -//       nodeInverter = 
   1.482 -// 	std::auto_ptr<InverterBase<Node> >(index[0]->getInverter());
   1.483 -      std::string line;
   1.484 -      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   1.485 -	Node node = graph.addNode();
   1.486 -	std::istringstream ls(line);
   1.487 -	for (int i = 0; i < (int)index.size(); ++i) {
   1.488 -	  index[i]->read(ls, node);
   1.489 -	}
   1.490 -      }
   1.491 -      return line;
   1.492 -    }
   1.493 -
   1.494 -    std::string readEdgeSet(int& line_num, 
   1.495 -			    std::auto_ptr<InverterBase<Edge> >& edgeInverter, 
   1.496 -			    std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   1.497 -      std::vector<ReaderBase<Edge>*> index;
   1.498 -      {
   1.499 -	std::string line = readNotEmptyLine(is, line_num);    
   1.500 -	std::string id;
   1.501 -	std::istringstream ls(line);	
   1.502 -	while (ls >> id) {
   1.503 -	  typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
   1.504 -	  if (it != edge_map_readers.end()) {
   1.505 -	    index.push_back(it->second);
   1.506 -	    edge_map_readers.erase(it);
   1.507 -	  } else {
   1.508 -	    index.push_back(&edgeSkipper);
   1.509 -	  }
   1.510 -	  if (ReaderTraits::idMapName(id) && edgeInverter.get() == 0) {
   1.511 -	    edgeInverter.reset(index.back()->getInverter());
   1.512 -	    index.back() = edgeInverter.get();
   1.513 -	  }
   1.514 -	}
   1.515 -      }
   1.516 -      
   1.517 -      if (nodeInverter.get() == 0) {
   1.518 - 	throw DataFormatError("Cannot find node id map");
   1.519 -      }
   1.520 -//       if (index.size() == 0) {
   1.521 -// 	throw DataFormatError("Cannot find edge id map");
   1.522 -//       }
   1.523 -
   1.524 -//       edgeInverter = 
   1.525 -// 	std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
   1.526 -      std::string line;
   1.527 -      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {	
   1.528 -	std::istringstream ls(line);
   1.529 -	Node source = nodeInverter->read(ls);
   1.530 -	Node target = nodeInverter->read(ls);
   1.531 -	Edge edge = graph.addEdge(source, target);
   1.532 -	for (int i = 0; i < (int)index.size(); ++i) {
   1.533 -	  index[i]->read(ls, edge);
   1.534 -	}
   1.535 -      }      
   1.536 -      return line;
   1.537 -    }
   1.538 -
   1.539 -    std::string readNodes(int& line_num, 
   1.540 -			  std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   1.541 -      std::string line;
   1.542 -      if (nodeInverter.get() == 0) {
   1.543 - 	throw DataFormatError("Cannot find node id map");
   1.544 -      }
   1.545 -      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   1.546 -	std::istringstream ls(line);
   1.547 -	std::string name;
   1.548 -	ls >> name;
   1.549 -	typename NodeReaders::iterator it = node_readers.find(name);
   1.550 -	if (it != node_readers.end()) {
   1.551 -	  *(it -> second) = nodeInverter->read(ls);
   1.552 -	} 
   1.553 -      }        
   1.554 -      return line;
   1.555 -    }
   1.556 -
   1.557 -    std::string readEdges(int& line_num, 
   1.558 -			  std::auto_ptr<InverterBase<Edge> >& edgeInverter) {
   1.559 -      std::string line;
   1.560 -      if (edgeInverter.get() == 0) {
   1.561 - 	throw DataFormatError("Cannot find edge id map");
   1.562 -      }
   1.563 -      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   1.564 -	std::istringstream ls(line);
   1.565 -	std::string name;
   1.566 -	ls >> name;
   1.567 -	typename EdgeReaders::iterator it = edge_readers.find(name);
   1.568 -	if (it != edge_readers.end()) {
   1.569 -	  *(it -> second) = edgeInverter->read(ls);
   1.570 -	} 
   1.571 -      }        
   1.572 -      return line;    
   1.573 -    }
   1.574 -
   1.575 -    std::string readGUI(int& line_num) {
   1.576 -      std::stringstream section;
   1.577 -      std::string line;
   1.578 -      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   1.579 -	section << line << std::endl;
   1.580 -      }
   1.581 -      if (gui_reader != 0) {
   1.582 -	gui_reader->read(section);
   1.583 -      }
   1.584 -      return line;
   1.585 -    }
   1.586 -
   1.587 -    std::string readNotEmptyLine(std::istream& is, int& line_num) {
   1.588 -      std::string line;
   1.589 -      while (++line_num, getline(is, line)) {	
   1.590 -	int vi = line.find('#');
   1.591 -	if (vi != (int)::std::string::npos) {
   1.592 -	  line = line.substr(0, vi);
   1.593 -	}
   1.594 -	vi = line.find_first_not_of(" \t");
   1.595 -	if (vi != (int)std::string::npos) { 
   1.596 -	  return line.substr(vi);
   1.597 -	}
   1.598 -      }
   1.599 -      throw DataFormatError("End of stream error");
   1.600 -    }
   1.601 -    
   1.602 -    template <typename _Item>
   1.603 -    class ReaderBase;
   1.604 -    
   1.605 -    template <typename _Item>
   1.606 -    class InverterBase : public ReaderBase<_Item> {
   1.607 -    public:
   1.608 -      typedef _Item Item;
   1.609 -      virtual void read(std::istream&, const Item&) = 0;
   1.610 -      virtual Item read(std::istream&) = 0;
   1.611 -
   1.612 -      virtual InverterBase<_Item>* getInverter() {
   1.613 -	return this;
   1.614 -      }
   1.615 -    };
   1.616 -
   1.617 -    template <typename _Item, typename _Map, typename _Reader>
   1.618 -    class MapReaderInverter : public InverterBase<_Item> {
   1.619 -    public:
   1.620 -      typedef _Item Item;
   1.621 -      typedef _Reader Reader;
   1.622 -      typedef typename Reader::Value Value;
   1.623 -      typedef _Map Map;
   1.624 -      typedef std::map<Value, Item> Inverse;
   1.625 -
   1.626 -      Map& map;
   1.627 -      Reader reader;
   1.628 -      Inverse inverse;
   1.629 -
   1.630 -      MapReaderInverter(Map& _map, const Reader& _reader) 
   1.631 -	: map(_map), reader(_reader) {}
   1.632 -
   1.633 -      virtual ~MapReaderInverter() {}
   1.634 -
   1.635 -      virtual void read(std::istream& is, const Item& item) {
   1.636 -	Value value;
   1.637 -	reader.read(is, value);
   1.638 -	map.set(item, value);
   1.639 -	typename Inverse::iterator it = inverse.find(value);
   1.640 -	if (it == inverse.end()) {
   1.641 -	  inverse.insert(std::make_pair(value, item));
   1.642 -	} else {
   1.643 -	  throw DataFormatError("Multiple ID occurence");
   1.644 -	}
   1.645 -      }
   1.646 -
   1.647 -      virtual Item read(std::istream& is) {
   1.648 -	Value value;
   1.649 -	reader.read(is, value);	
   1.650 -	typename Inverse::const_iterator it = inverse.find(value);
   1.651 -	if (it != inverse.end()) {
   1.652 -	  return it->second;
   1.653 -	} else {
   1.654 -	  throw DataFormatError("Invalid ID error");
   1.655 -	}
   1.656 -      }      
   1.657 -    };
   1.658 -
   1.659 -    template <typename _Item, typename _Reader>
   1.660 -    class SkipReaderInverter : public InverterBase<_Item> {
   1.661 -    public:
   1.662 -      typedef _Item Item;
   1.663 -      typedef _Reader Reader;
   1.664 -      typedef typename Reader::Value Value;
   1.665 -      typedef std::map<Value, Item> Inverse;
   1.666 -
   1.667 -      Reader reader;
   1.668 -
   1.669 -      SkipReaderInverter(const Reader& _reader) 
   1.670 -	: reader(_reader) {}
   1.671 -
   1.672 -      virtual ~SkipReaderInverter() {}
   1.673 -
   1.674 -      virtual void read(std::istream& is, const Item& item) {
   1.675 -	Value value;
   1.676 -	reader.read(is, value);
   1.677 -	typename Inverse::iterator it = inverse.find(value);
   1.678 -	if (it == inverse.end()) {
   1.679 -	  inverse.insert(std::make_pair(value, item));
   1.680 -	} else {
   1.681 -	  throw DataFormatError("Multiple ID occurence error");
   1.682 -	}
   1.683 -      }
   1.684 -
   1.685 -      virtual Item read(std::istream& is) {
   1.686 -	Value value;
   1.687 -	reader.read(is, value);	
   1.688 -	typename Inverse::const_iterator it = inverse.find(value);
   1.689 -	if (it != inverse.end()) {
   1.690 -	  return it->second;
   1.691 -	} else {
   1.692 -	  throw DataFormatError("Invalid ID error");
   1.693 -	}
   1.694 -      }      
   1.695 -    private:
   1.696 -      Inverse inverse;
   1.697 -    };
   1.698 -
   1.699 -    // Readers
   1.700 -
   1.701 -    template <typename _Item>    
   1.702 -    class ReaderBase {
   1.703 -    public:
   1.704 -      typedef _Item Item;
   1.705 -
   1.706 -      //      virtual ~ReaderBase() {}
   1.707 -
   1.708 -      virtual void read(std::istream& is, const Item& item) = 0;
   1.709 -      virtual InverterBase<_Item>* getInverter() = 0;
   1.710 -    };
   1.711 -
   1.712 -    template <typename _Item, typename _Map, typename _Reader>
   1.713 -    class MapReader : public ReaderBase<_Item> {
   1.714 -    public:
   1.715 -      typedef _Map Map;
   1.716 -      typedef _Reader Reader;
   1.717 -      typedef typename Reader::Value Value;
   1.718 -      typedef _Item Item;
   1.719 -      
   1.720 -      Map& map;
   1.721 -      Reader reader;
   1.722 -
   1.723 -      MapReader(Map& _map, const Reader& _reader) 
   1.724 -	: map(_map), reader(_reader) {}
   1.725 -
   1.726 -      virtual ~MapReader() {}
   1.727 -
   1.728 -      virtual void read(std::istream& is, const Item& item) {
   1.729 -	Value value;
   1.730 -	reader.read(is, value);
   1.731 -	map.set(item, value);
   1.732 -      }
   1.733 -
   1.734 -      virtual InverterBase<_Item>* getInverter() {
   1.735 -	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   1.736 -      }
   1.737 -    };
   1.738 -
   1.739 -
   1.740 -    template <typename _Item, typename _Reader>
   1.741 -    class SkipReader : public ReaderBase<_Item> {
   1.742 -    public:
   1.743 -      typedef _Reader Reader;
   1.744 -      typedef typename Reader::Value Value;
   1.745 -      typedef _Item Item;
   1.746 -
   1.747 -      Reader reader;
   1.748 -      SkipReader(const Reader& _reader) : reader(_reader) {}
   1.749 -
   1.750 -      virtual ~SkipReader() {}
   1.751 -
   1.752 -      virtual void read(std::istream& is, const Item&) {
   1.753 -	Value value;
   1.754 -	reader.read(is, value);
   1.755 -      }      
   1.756 -
   1.757 -      virtual InverterBase<Item>* getInverter() {
   1.758 -	return new SkipReaderInverter<Item, Reader>(reader);
   1.759 -      }
   1.760 -    };
   1.761 -
   1.762 -
   1.763 -    typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
   1.764 -    NodeMapReaders node_map_readers;
   1.765 -
   1.766 -    typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
   1.767 -    EdgeMapReaders edge_map_readers;
   1.768 -
   1.769 -    typedef std::map<std::string, Node*> NodeReaders;
   1.770 -    NodeReaders node_readers;
   1.771 -
   1.772 -    typedef std::map<std::string, Edge*> EdgeReaders;
   1.773 -    EdgeReaders edge_readers;
   1.774 -
   1.775 -    GUIReader* gui_reader;
   1.776 -
   1.777 -    std::istream& is;
   1.778      Graph& graph;
   1.779  
   1.780 -    SkipReader<Node, DefaultReader> nodeSkipper;
   1.781 -    SkipReader<Edge, DefaultReader> edgeSkipper;
   1.782 +    DefaultSkipper skipper;
   1.783  
   1.784 +    NodeSetReader<Graph, ReaderTraits> nodeset_reader;
   1.785 +    EdgeSetReader<Graph, ReaderTraits> edgeset_reader;
   1.786 +
   1.787 +    NodeReader<Graph> node_reader;
   1.788 +    EdgeReader<Graph> edge_reader;
   1.789 +    
   1.790 +    AttributeReader<ReaderTraits> attribute_reader;
   1.791    };
   1.792  
   1.793    /// \brief Read a graph from the input.