New graph reader interface.
authordeba
Mon, 09 May 2005 11:24:26 +0000
changeset 1408892c29484414
parent 1407 7152559e3d08
child 1409 d2d1f8fa187b
New graph reader interface.
src/lemon/Makefile.am
src/lemon/bits/item_reader.h
src/lemon/graph_reader.h
src/lemon/lemon_reader.h
     1.1 --- a/src/lemon/Makefile.am	Fri May 06 15:39:33 2005 +0000
     1.2 +++ b/src/lemon/Makefile.am	Mon May 09 11:24:26 2005 +0000
     1.3 @@ -52,6 +52,7 @@
     1.4  	xy.h \
     1.5  	concept_check.h \
     1.6  	utility.h \
     1.7 +	lemon_reader.h \
     1.8  	graph_reader.h \
     1.9  	graph_writer.h \
    1.10  	bits/alteration_notifier.h \
    1.11 @@ -64,7 +65,8 @@
    1.12  	bits/extendable_graph_extender.h \
    1.13  	bits/clearable_graph_extender.h \
    1.14  	bits/erasable_graph_extender.h \
    1.15 -	bits/undir_graph_extender.h
    1.16 +	bits/undir_graph_extender.h \
    1.17 +	bits/item_reader.h
    1.18  
    1.19  noinst_HEADERS = \
    1.20  	concept/graph.h \
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/lemon/bits/item_reader.h	Mon May 09 11:24:26 2005 +0000
     2.3 @@ -0,0 +1,395 @@
     2.4 +/* -*- C++ -*-
     2.5 + * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
     2.6 + *
     2.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     2.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
     2.9 + *
    2.10 + * Permission to use, modify and distribute this software is granted
    2.11 + * provided that this copyright notice appears in all copies. For
    2.12 + * precise terms see the accompanying LICENSE file.
    2.13 + *
    2.14 + * This software is provided "AS IS" with no warranty of any kind,
    2.15 + * express or implied, and with no claim as to its suitability for any
    2.16 + * purpose.
    2.17 + *
    2.18 + */
    2.19 +
    2.20 +/// \ingroup io_group
    2.21 +/// \file
    2.22 +/// \brief Item reader bits for lemon input.
    2.23 +
    2.24 +#ifndef LEMON_BITS_ITEM_READER_H
    2.25 +#define LEMON_BITS_ITEM_READER_H
    2.26 +
    2.27 +#include <iostream>
    2.28 +#include <string>
    2.29 +
    2.30 +#include <vector>
    2.31 +#include <deque>
    2.32 +#include <list>
    2.33 +#include <set>
    2.34 +
    2.35 +namespace lemon {
    2.36 +  
    2.37 +  template <typename Value>
    2.38 +  class DefaultReader;
    2.39 +
    2.40 +  /// \ingroup io_group
    2.41 +  ///
    2.42 +  /// \brief Reader class for quoted strings.
    2.43 +  ///
    2.44 +  /// Reader class for quoted strings. It can process the escape
    2.45 +  /// sequences in the string.
    2.46 +  ///
    2.47 +  /// \author Balazs Dezso
    2.48 +  class QuotedStringReader {
    2.49 +  public:
    2.50 +    /// \brief The value type of reader.
    2.51 +    ///
    2.52 +    /// The value type of reader.
    2.53 +    typedef std::string Value;
    2.54 +    
    2.55 +    /// \brief Constructor for the reader.
    2.56 +    ///
    2.57 +    /// Constructor for the reader. If the given parameter is true
    2.58 +    /// the reader processes the escape sequences.
    2.59 +    QuotedStringReader(bool _escaped = true) 
    2.60 +      : escaped(_escaped) {}
    2.61 +    
    2.62 +    /// \brief Reads a quoted string from the given stream.
    2.63 +    ///
    2.64 +    /// Reads a quoted string from the given stream.
    2.65 +    void read(std::istream& is, std::string& value) const {
    2.66 +      char c;
    2.67 +      value.clear();
    2.68 +      is >> std::ws;
    2.69 +      if (!is.get(c) || c != '\"') 
    2.70 +	throw DataFormatError("Quoted string format error");
    2.71 +      while (is.get(c) && c != '\"') {
    2.72 +	if (escaped && c == '\\') {
    2.73 +	  value += readEscape(is);
    2.74 +	} else {
    2.75 +	  value += c;
    2.76 +	}
    2.77 +      }
    2.78 +      if (!is) throw DataFormatError("Quoted string format error");
    2.79 +    }
    2.80 +
    2.81 +  private:
    2.82 +    
    2.83 +    static char readEscape(std::istream& is) {
    2.84 +      char c;
    2.85 +      switch (is.get(c), c) {
    2.86 +      case '\\':
    2.87 +	return '\\';
    2.88 +      case '\"':
    2.89 +	return '\"';
    2.90 +      case '\'':
    2.91 +	return '\'';
    2.92 +      case '\?':
    2.93 +	return '\?';
    2.94 +      case 'a':
    2.95 +	return '\a';
    2.96 +      case 'b':
    2.97 +	return '\b';
    2.98 +      case 'f':
    2.99 +	return '\f';
   2.100 +      case 'n':
   2.101 +	return '\n';
   2.102 +      case 'r':
   2.103 +	return '\r';
   2.104 +      case 't':
   2.105 +	return '\t';
   2.106 +      case 'v':
   2.107 +	return '\v';
   2.108 +      case 'x':
   2.109 +	{
   2.110 +	  int code;
   2.111 +	  if (!is.get(c) || !isHex(c)) 
   2.112 +	    throw DataFormatError("Escape format error");
   2.113 +	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
   2.114 +	  else code = code * 16 + valueHex(c);
   2.115 +	  return code;
   2.116 +	}
   2.117 +      default:
   2.118 +	{
   2.119 +	  int code;
   2.120 +	  if (!isOct(c)) 
   2.121 +	    throw DataFormatError("Escape format error");
   2.122 +	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
   2.123 +	    is.putback(c);
   2.124 +	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
   2.125 +	    is.putback(c);
   2.126 +	  else code = code * 8 + valueOct(c);
   2.127 +	  return code;
   2.128 +	}	      
   2.129 +      } 
   2.130 +    }
   2.131 +
   2.132 +    static bool isOct(char c) {
   2.133 +      return '0' <= c && c <='7'; 
   2.134 +    }
   2.135 +    
   2.136 +    static int valueOct(char c) {
   2.137 +      return c - '0';
   2.138 +    }
   2.139 +
   2.140 +   static bool isHex(char c) {
   2.141 +      return ('0' <= c && c <= '9') || 
   2.142 +	('a' <= c && c <= 'z') || 
   2.143 +	('A' <= c && c <= 'Z'); 
   2.144 +    }
   2.145 +    
   2.146 +    static int valueHex(char c) {
   2.147 +      if ('0' <= c && c <= '9') return c - '0';
   2.148 +      if ('a' <= c && c <= 'z') return c - 'a' + 10;
   2.149 +      return c - 'A' + 10;
   2.150 +    }
   2.151 +
   2.152 +    bool escaped;
   2.153 +  };
   2.154 +
   2.155 +  /// \ingroup io_group
   2.156 +  /// \brief Reader for standard containers.
   2.157 +  ///
   2.158 +  /// Reader for back insertable standard containers. The representation
   2.159 +  /// of the container is the values enumerated between an open and a
   2.160 +  /// close parse. 
   2.161 +  ///
   2.162 +  /// \author Balazs Dezso
   2.163 +  template <
   2.164 +    typename _Container, 
   2.165 +    typename _ItemReader = DefaultReader<typename _Container::value_type> 
   2.166 +  >
   2.167 +  class PushBackReader {
   2.168 +  public:
   2.169 +    typedef _Container Value;
   2.170 +    typedef _ItemReader ItemReader;
   2.171 +
   2.172 +  private:
   2.173 +
   2.174 +    ItemReader item_reader;
   2.175 +
   2.176 +  public:
   2.177 +
   2.178 +    /// \brief Reads the values into the container from the given stream.
   2.179 +    ///
   2.180 +    /// Reads the values into the container from the given stream.
   2.181 +    void read(std::istream& is, Value& value) const {
   2.182 +      char c;
   2.183 +      if (!(is >> c) || c != '(') 
   2.184 +	throw DataFormatError("PushBackReader format error");
   2.185 +      while (is >> c && c != ')') {
   2.186 +	is.putback(c);
   2.187 +	typename ItemReader::Value item;
   2.188 +	item_reader.read(is, item);
   2.189 +	value.push_back(item);
   2.190 +      }
   2.191 +      if (!is) throw DataFormatError("PushBackReader format error");
   2.192 +      is.putback(c);
   2.193 +    }
   2.194 +
   2.195 +  };
   2.196 +
   2.197 +  /// \ingroup io_group
   2.198 +  ///
   2.199 +  /// \brief Reader for standard containers.
   2.200 +  ///
   2.201 +  /// Reader for insertable standard containers. The representation
   2.202 +  /// of the container is the values enumerated between an open and a
   2.203 +  /// close parse. 
   2.204 +  ///
   2.205 +  /// \author Balazs Dezso
   2.206 +  template <
   2.207 +    typename _Container, 
   2.208 +    typename _ItemReader = DefaultReader<typename _Container::value_type> 
   2.209 +  >
   2.210 +  class InsertReader {
   2.211 +  public:
   2.212 +    typedef _Container Value;
   2.213 +    typedef _ItemReader ItemReader;
   2.214 +
   2.215 +  private:
   2.216 +
   2.217 +    ItemReader item_reader;
   2.218 +
   2.219 +  public:
   2.220 +
   2.221 +    /// \brief Reads the values into the container from the given stream.
   2.222 +    ///
   2.223 +    /// Reads the values into the container from the given stream.
   2.224 +    void read(std::istream& is, Value& value) const {
   2.225 +      char c;
   2.226 +      if (!(is >> c) || c != '(') 
   2.227 +	throw DataFormatError("InsertReader format error");
   2.228 +      while (is >> c && c != ')') {
   2.229 +	is.putback(c);
   2.230 +	typename ItemReader::Value item;
   2.231 +	item_reader.read(is, item);
   2.232 +	value.insert(item);
   2.233 +      }
   2.234 +      if (!is) throw DataFormatError("PushBackReader format error");
   2.235 +      is.putback(c);
   2.236 +    }
   2.237 +
   2.238 +  };
   2.239 +
   2.240 +  /// \ingroup io_group
   2.241 +  /// \brief Reader for parsed string.
   2.242 +  ///
   2.243 +  /// Reader for parsed strings. You can give the open and close
   2.244 +  /// parse characters.
   2.245 +  ///
   2.246 +  /// \author Balazs Dezso
   2.247 +  class ParsedStringReader {
   2.248 +  public:
   2.249 +    typedef std::string Value;
   2.250 +
   2.251 +    /// \brief Constructor.
   2.252 +    ///
   2.253 +    /// Constructor for ParsedStringReader. You can give as parameter
   2.254 +    /// the open and close parse characters.
   2.255 +    ParsedStringReader(char _open = '(', char _close = ')')
   2.256 +      : open(_open), close(_close) {}
   2.257 +    
   2.258 +    
   2.259 +    /// \brief Reads the parsed string from the given stream.
   2.260 +    ///
   2.261 +    /// Reads the parsed string from the given stream.
   2.262 +    void read(std::istream& is, Value& value) const {
   2.263 +      char c;
   2.264 +      if (!(is >> c) || c != open) {
   2.265 +	throw DataFormatError("ParsedStringReader format error");
   2.266 +      }
   2.267 +      value += c;
   2.268 +      int counter = 1;
   2.269 +      while (counter > 0 && is >> c) {
   2.270 +	if (c == close) {
   2.271 +	  --counter;
   2.272 +	} else if (c == open) {
   2.273 +	  ++counter;
   2.274 +	}
   2.275 +	value += c;
   2.276 +      }
   2.277 +      if (!is) {
   2.278 +	throw DataFormatError("ParsedStrinReader format error");
   2.279 +      }
   2.280 +    }
   2.281 +
   2.282 +  private:
   2.283 +    char open, close;
   2.284 +
   2.285 +  };
   2.286 +
   2.287 +  /// \ingroup io_group
   2.288 +  /// \brief Reader for read the whole line.
   2.289 +  ///
   2.290 +  /// Reader for read the whole line.
   2.291 +  ///
   2.292 +  /// \author Balazs Dezso
   2.293 +  class LineReader {
   2.294 +  public:
   2.295 +    typedef std::string Value;
   2.296 +
   2.297 +    /// \brief Constructor.
   2.298 +    ///
   2.299 +    /// Constructor for the LineReader. If the given parameter is
   2.300 +    /// true then the spaces before the first not space character are
   2.301 +    /// skipped.
   2.302 +    LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
   2.303 +    
   2.304 +    /// \brief Reads the line from the given stream.
   2.305 +    ///
   2.306 +    /// Reads the line from the given stream.
   2.307 +    void read(std::istream& is, Value& value) {
   2.308 +      if (skipSpaces) is >> std::ws;
   2.309 +      if (!getline(is, value)) {
   2.310 +	throw DataFormatError("LineReader forma error");
   2.311 +      }
   2.312 +    }
   2.313 +  private:
   2.314 +    bool skipSpaces;
   2.315 +  };
   2.316 +
   2.317 +  /// \ingroup io_group
   2.318 +  /// 
   2.319 +  /// \brief The default item reader template class.
   2.320 +  ///
   2.321 +  /// The default item reader template class. If some section reader
   2.322 +  /// needs to read a value from a stream it will give the default way for it.
   2.323 +  ///
   2.324 +  /// \author Balazs Dezso
   2.325 +  template <typename _Value>
   2.326 +  class DefaultReader {
   2.327 +  public:
   2.328 +    /// The value type.
   2.329 +    typedef _Value Value;
   2.330 +    /// \brief Reads a value from the given stream.
   2.331 +    ///
   2.332 +    /// Reads a value from the given stream.
   2.333 +    void read(std::istream& is, Value& value) const {
   2.334 +      if (!(is >> value)) 
   2.335 +	throw DataFormatError("DefaultReader format error");
   2.336 +    }
   2.337 +  };
   2.338 +
   2.339 +  template <typename Item>
   2.340 +  class DefaultReader<std::vector<Item> > 
   2.341 +    : public PushBackReader<std::vector<Item> > {};
   2.342 +
   2.343 +  template <typename Item>
   2.344 +  class DefaultReader<std::deque<Item> > 
   2.345 +    : public PushBackReader<std::deque<Item> > {};
   2.346 +
   2.347 +  template <typename Item>
   2.348 +  class DefaultReader<std::list<Item> > 
   2.349 +    : public PushBackReader<std::list<Item> > {};
   2.350 +
   2.351 +  template <typename Item>
   2.352 +  class DefaultReader<std::set<Item> > 
   2.353 +    : public InsertReader<std::set<Item> > {};
   2.354 +
   2.355 +  template <typename Item>
   2.356 +  class DefaultReader<std::multiset<Item> > 
   2.357 +    : public InsertReader<std::multiset<Item> > {};
   2.358 +
   2.359 +  /// \ingroup io_group
   2.360 +  class DefaultSkipper {
   2.361 +  public:
   2.362 +    typedef std::string Value;
   2.363 +    
   2.364 +    void read(std::istream& is, Value& value) const {
   2.365 +      char c;
   2.366 +      if (!(is >> c)) return;
   2.367 +      is.putback(c);
   2.368 +      switch (c) {
   2.369 +      case '\"':
   2.370 +	QuotedStringReader().read(is, value);
   2.371 +	break;
   2.372 +      case '(':
   2.373 +	ParsedStringReader().read(is, value);
   2.374 +	break;
   2.375 +      default:
   2.376 +	DefaultReader<std::string>().read(is, value); 
   2.377 +	break;
   2.378 +      }
   2.379 +    }
   2.380 +  };
   2.381 +  
   2.382 +  /// \brief Standard ReaderTraits for the GraphReader class.
   2.383 +  ///
   2.384 +  /// Standard ReaderTraits for the GraphReader class.
   2.385 +  /// It defines standard reading method for all type of value. 
   2.386 +  /// \author Balazs Dezso
   2.387 +  struct DefaultReaderTraits {
   2.388 +
   2.389 +    template <typename _Value>
   2.390 +    struct Reader : DefaultReader<_Value> {};
   2.391 +
   2.392 +    typedef DefaultSkipper Skipper;
   2.393 +
   2.394 +  };
   2.395 +
   2.396 +}
   2.397 +
   2.398 +#endif
     3.1 --- a/src/lemon/graph_reader.h	Fri May 06 15:39:33 2005 +0000
     3.2 +++ b/src/lemon/graph_reader.h	Mon May 09 11:24:26 2005 +0000
     3.3 @@ -22,173 +22,17 @@
     3.4  #define LEMON_GRAPH_READER_H
     3.5  
     3.6  #include <iostream>
     3.7 -#include <sstream>
     3.8 -
     3.9 -#include <map>
    3.10 -#include <vector>
    3.11 -
    3.12 -#include <memory>
    3.13  
    3.14  #include <lemon/error.h>
    3.15 -
    3.16 +#include <lemon/lemon_reader.h>
    3.17  
    3.18  namespace lemon {
    3.19  
    3.20    /// \addtogroup io_group
    3.21    /// @{
    3.22  
    3.23 -  /// \brief Standard ReaderTraits for the GraphReader class.
    3.24 -  ///
    3.25 -  /// Standard ReaderTraits for the GraphReader class.
    3.26 -  /// It defines standard reading method for all type of value. 
    3.27 -  /// \author Balazs Dezso
    3.28 -  struct DefaultReaderTraits {
    3.29 -
    3.30 -    /// \brief Template class for reading an value.
    3.31 -    ///
    3.32 -    /// Template class for reading an value.
    3.33 -    /// \author Balazs Dezso
    3.34 -    template <typename _Value>
    3.35 -    struct Reader {
    3.36 -      /// The value type.
    3.37 -      typedef _Value Value;
    3.38 -      /// \brief Reads a value from the given stream.
    3.39 -      ///
    3.40 -      /// Reads a value from the given stream.
    3.41 -      void read(std::istream& is, Value& value) {
    3.42 -	if (!(is >> value)) 
    3.43 -	  throw DataFormatError("Default reader format exception");
    3.44 -      }
    3.45 -    };
    3.46 -
    3.47 -    /// \brief Returns wheter this name is an ID map name.
    3.48 -    ///
    3.49 -    /// Returns wheter this name is an ID map name.
    3.50 -    static bool idMapName(const std::string& name) {
    3.51 -      return name == "id";
    3.52 -    }
    3.53 -
    3.54 -    /// The reader class for the not needed maps.
    3.55 -    typedef Reader<std::string> DefaultReader;
    3.56 -
    3.57 -  };
    3.58 -
    3.59 -  /// \brief Reader class for quoted strings.
    3.60 -  ///
    3.61 -  /// Reader class for quoted strings. It can process the escape
    3.62 -  /// sequences in the string.
    3.63 -  /// \author Balazs Dezso
    3.64 -  class QuotedStringReader {
    3.65 -  public:
    3.66 -    typedef std::string Value;
    3.67 -    
    3.68 -    /// \brief Constructor for the reader.
    3.69 -    ///
    3.70 -    /// Constructor for the reader. If the given parameter is true
    3.71 -    /// the reader processes the escape sequences.
    3.72 -    QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
    3.73 -    
    3.74 -    /// \brief Reads a quoted string from the given stream.
    3.75 -    ///
    3.76 -    /// Reads a quoted string from the given stream.
    3.77 -    void read(std::istream& is, std::string& value) {
    3.78 -      char c;
    3.79 -      value.clear();
    3.80 -      is >> std::ws;
    3.81 -      if (!is.get(c) || c != '\"') 
    3.82 -	throw DataFormatError("Quoted string format error");
    3.83 -      while (is.get(c) && c != '\"') {
    3.84 -	if (escaped && c == '\\') {
    3.85 -	  value += readEscape(is);
    3.86 -	} else {
    3.87 -	  value += c;
    3.88 -	}
    3.89 -      }
    3.90 -      if (!is) throw DataFormatError("Quoted string format error");
    3.91 -    }
    3.92 -
    3.93 -  private:
    3.94 -    
    3.95 -    static char readEscape(std::istream& is) {
    3.96 -      char c;
    3.97 -      switch (is.get(c), c) {
    3.98 -      case '\\':
    3.99 -	return '\\';
   3.100 -      case '\"':
   3.101 -	return '\"';
   3.102 -      case '\'':
   3.103 -	return '\'';
   3.104 -      case '\?':
   3.105 -	return '\?';
   3.106 -      case 'a':
   3.107 -	return '\a';
   3.108 -      case 'b':
   3.109 -	return '\b';
   3.110 -      case 'f':
   3.111 -	return '\f';
   3.112 -      case 'n':
   3.113 -	return '\n';
   3.114 -      case 'r':
   3.115 -	return '\r';
   3.116 -      case 't':
   3.117 -	return '\t';
   3.118 -      case 'v':
   3.119 -	return '\v';
   3.120 -      case 'x':
   3.121 -	{
   3.122 -	  int code;
   3.123 -	  if (!is.get(c) || !isHex(c)) 
   3.124 -	    throw DataFormatError("Escape format error");
   3.125 -	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
   3.126 -	  else code = code * 16 + valueHex(c);
   3.127 -	  return code;
   3.128 -	}
   3.129 -      default:
   3.130 -	{
   3.131 -	  int code;
   3.132 -	  if (!isOct(c)) 
   3.133 -	    throw DataFormatError("Escape format error");
   3.134 -	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
   3.135 -	    is.putback(c);
   3.136 -	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
   3.137 -	    is.putback(c);
   3.138 -	  else code = code * 8 + valueOct(c);
   3.139 -	  return code;
   3.140 -	}	      
   3.141 -      } 
   3.142 -    }
   3.143 -
   3.144 -    static bool isOct(char c) {
   3.145 -      return '0' <= c && c <='7'; 
   3.146 -    }
   3.147 -    
   3.148 -    static int valueOct(char c) {
   3.149 -      return c - '0';
   3.150 -    }
   3.151 -
   3.152 -   static bool isHex(char c) {
   3.153 -      return ('0' <= c && c <= '9') || 
   3.154 -	('a' <= c && c <= 'z') || 
   3.155 -	('A' <= c && c <= 'Z'); 
   3.156 -    }
   3.157 -    
   3.158 -    static int valueHex(char c) {
   3.159 -      if ('0' <= c && c <= '9') return c - '0';
   3.160 -      if ('a' <= c && c <= 'z') return c - 'a' + 10;
   3.161 -      return c - 'A' + 10;
   3.162 -    }
   3.163 -
   3.164 -    bool escaped;
   3.165 -  };
   3.166 -
   3.167 -  class GUIReader {
   3.168 -  public:
   3.169 -    virtual void read(std::istream& is) = 0;
   3.170 -  };
   3.171 -
   3.172    /// \brief The graph reader class.
   3.173    ///
   3.174 -  ///
   3.175    /// The given file format may contain several maps and labeled nodes or 
   3.176    /// edges.
   3.177    ///
   3.178 @@ -229,8 +73,8 @@
   3.179    /// reader.readEdgeMap("label", labelMap);
   3.180    /// \endcode
   3.181    ///
   3.182 -  /// With \c readNode() and \c readEdge() functions you can read labeled Nodes 
   3.183 -  /// and Edges.
   3.184 +  /// With \c readNode() and \c readEdge() functions you can read 
   3.185 +  /// labeled Nodes and Edges.
   3.186    ///
   3.187    /// \code
   3.188    /// reader.readNode("source", sourceNode);
   3.189 @@ -239,6 +83,10 @@
   3.190    /// reader.readEdge("observed", edge);
   3.191    /// \endcode
   3.192    ///
   3.193 +  /// With the \c readAttribute() functions you can read an attribute
   3.194 +  /// in a variable. You can specify the reader for the attribute as
   3.195 +  /// the nodemaps.
   3.196 +  ///
   3.197    /// After you give all read commands you must call the \c run() member
   3.198    /// function, which execute all the commands.
   3.199    ///
   3.200 @@ -260,31 +108,56 @@
   3.201      typedef typename Graph::Edge Edge;
   3.202  
   3.203      typedef _ReaderTraits ReaderTraits;
   3.204 -    typedef typename ReaderTraits::DefaultReader DefaultReader;
   3.205 +    typedef typename ReaderTraits::Skipper DefaultSkipper;
   3.206  
   3.207      /// \brief Construct a new GraphReader.
   3.208      ///
   3.209      /// Construct a new GraphReader. It reads into the given graph
   3.210      /// and it use the given reader as the default skipper.
   3.211      GraphReader(std::istream& _is, Graph& _graph, 
   3.212 -		const DefaultReader& _reader = DefaultReader()) 
   3.213 -      : gui_reader(0), is(_is), graph(_graph), 
   3.214 -	nodeSkipper(_reader), edgeSkipper(_reader) {}
   3.215 +		const DefaultSkipper& _skipper = DefaultSkipper()) 
   3.216 +      : reader(new LemonReader(_is)), own_reader(true), 
   3.217 +	graph(_graph), skipper(_skipper),
   3.218 +	nodeset_reader(*reader, graph, std::string(), skipper),
   3.219 +	edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
   3.220 +	node_reader(*reader, nodeset_reader, std::string()),
   3.221 +	edge_reader(*reader, edgeset_reader, std::string()),
   3.222 +	attribute_reader(*reader, std::string()) {}
   3.223 +
   3.224 +    /// \brief Construct a new GraphReader.
   3.225 +    ///
   3.226 +    /// Construct a new GraphReader. It reads into the given graph
   3.227 +    /// and it use the given reader as the default skipper.
   3.228 +    GraphReader(const std::string& _filename, Graph& _graph, 
   3.229 +		const DefaultSkipper& _skipper = DefaultSkipper()) 
   3.230 +      : reader(new LemonReader(_filename)), own_reader(true), 
   3.231 +	graph(_graph), skipper(_skipper),
   3.232 +	nodeset_reader(*reader, graph, std::string(), skipper),
   3.233 +	edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
   3.234 +	node_reader(*reader, nodeset_reader, std::string()),
   3.235 +	edge_reader(*reader, edgeset_reader, std::string()),
   3.236 +	attribute_reader(*reader, std::string()) {}
   3.237 +
   3.238 +    /// \brief Construct a new GraphReader.
   3.239 +    ///
   3.240 +    /// Construct a new GraphReader. It reads into the given graph
   3.241 +    /// and it use the given reader as the default skipper.
   3.242 +    GraphReader(LemonReader& _reader, Graph& _graph, 
   3.243 +		const DefaultSkipper& _skipper = DefaultSkipper()) 
   3.244 +      : reader(_reader), own_reader(false), 
   3.245 +	graph(_graph), skipper(_skipper),
   3.246 +	nodeset_reader(*reader, graph, std::string(), skipper),
   3.247 +	edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
   3.248 +	node_reader(*reader, nodeset_reader, std::string()),
   3.249 +	edge_reader(*reader, edgeset_reader, std::string()),
   3.250 +	attribute_reader(*reader, std::string()) {}
   3.251  
   3.252      /// \brief Destruct the graph reader.
   3.253      ///
   3.254      /// Destruct the graph reader.
   3.255      ~GraphReader() {
   3.256 -      for (typename NodeMapReaders::iterator it = node_map_readers.begin(); 
   3.257 -	   it != node_map_readers.end(); ++it) {
   3.258 -	delete it->second;
   3.259 -      }
   3.260 -
   3.261 -      for (typename EdgeMapReaders::iterator it = edge_map_readers.begin(); 
   3.262 -	   it != edge_map_readers.end(); ++it) {
   3.263 -	delete it->second;
   3.264 -      }
   3.265 -
   3.266 +      if (own_reader) 
   3.267 +	delete reader;
   3.268      }
   3.269  
   3.270      /// \brief Add a new node map reader command for the reader.
   3.271 @@ -292,8 +165,8 @@
   3.272      /// Add a new node map reader command for the reader.
   3.273      template <typename Map>
   3.274      GraphReader& readNodeMap(std::string name, Map& map) {
   3.275 -      return readNodeMap<typename ReaderTraits::template 
   3.276 -	Reader<typename Map::Value>, Map>(name, map);
   3.277 +      nodeset_reader.readMap(name, map);
   3.278 +      return *this;
   3.279      }
   3.280  
   3.281      /// \brief Add a new node map reader command for the reader.
   3.282 @@ -302,13 +175,7 @@
   3.283      template <typename Reader, typename Map>
   3.284      GraphReader& readNodeMap(std::string name, Map& map, 
   3.285  			     const Reader& reader = Reader()) {
   3.286 -      if (node_map_readers.find(name) != node_map_readers.end()) {
   3.287 -	ErrorMessage msg;
   3.288 -	msg << "Multiple read rule for node map: " << name;
   3.289 -	throw IOParameterError(msg.message());
   3.290 -      }
   3.291 -      node_map_readers.insert(
   3.292 -        make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
   3.293 +      nodeset_reader.readMap(name, map, reader);
   3.294        return *this;
   3.295      }
   3.296  
   3.297 @@ -318,13 +185,7 @@
   3.298      template <typename Reader>
   3.299      GraphReader& skipNodeMap(std::string name, 
   3.300  			     const Reader& reader = Reader()) {
   3.301 -      if (node_map_readers.find(name) != node_map_readers.end()) {
   3.302 -	ErrorMessage msg;
   3.303 -	msg << "Multiple read rule for node map: " << name;
   3.304 -	throw IOParameterError(msg.message());
   3.305 -      }
   3.306 -      node_map_readers.insert(
   3.307 -        make_pair(name, new SkipReader<Node, Reader>(reader)));
   3.308 +      nodeset_reader.skipMap(name, reader);
   3.309        return *this;
   3.310      }
   3.311  
   3.312 @@ -333,8 +194,8 @@
   3.313      /// Add a new edge map reader command for the reader.
   3.314      template <typename Map>
   3.315      GraphReader& readEdgeMap(std::string name, Map& map) { 
   3.316 -      return readEdgeMap<typename ReaderTraits::template
   3.317 -	Reader<typename Map::Value>, Map>(name, map);
   3.318 +      edgeset_reader.readMap(name, map);
   3.319 +      return *this;
   3.320      }
   3.321  
   3.322  
   3.323 @@ -344,13 +205,7 @@
   3.324      template <typename Reader, typename Map>
   3.325      GraphReader& readEdgeMap(std::string name, Map& map,
   3.326  			     const Reader& reader = Reader()) {
   3.327 -      if (edge_map_readers.find(name) != edge_map_readers.end()) {
   3.328 -	ErrorMessage msg;
   3.329 -	msg << "Multiple read rule for edge map: " << name;
   3.330 -	throw IOParameterError(msg.message());
   3.331 -      }
   3.332 -      edge_map_readers.insert(
   3.333 -        make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
   3.334 +      edgeset_reader.readMap(name, map, reader);
   3.335        return *this;
   3.336      }
   3.337  
   3.338 @@ -360,13 +215,8 @@
   3.339      template <typename Reader>
   3.340      GraphReader& skipEdgeMap(std::string name,
   3.341  			     const Reader& reader = Reader()) {
   3.342 -      if (edge_map_readers.find(name) != edge_map_readers.end()) {
   3.343 -	ErrorMessage msg;
   3.344 -	msg << "Multiple read rule for edge map: " << name;
   3.345 -	throw IOParameterError(msg.message());
   3.346 -      }
   3.347 -      edge_map_readers.insert(
   3.348 -        make_pair(name, new SkipReader<Edge, Reader>(reader)));
   3.349 +
   3.350 +      edgeset_reader.skipMap(name, reader);
   3.351        return *this;
   3.352      }
   3.353  
   3.354 @@ -374,12 +224,7 @@
   3.355      ///
   3.356      /// Add a new labeled node reader for the reader.
   3.357      GraphReader& readNode(std::string name, Node& node) {
   3.358 -      if (node_readers.find(name) != node_readers.end()) {
   3.359 -	ErrorMessage msg;
   3.360 -	msg << "Multiple read rule for node: " << name;
   3.361 -	throw IOParameterError(msg.message());
   3.362 -      }
   3.363 -      node_readers.insert(make_pair(name, &node));
   3.364 +      node_reader.readNode(name, node);
   3.365        return *this;
   3.366      }
   3.367  
   3.368 @@ -387,385 +232,61 @@
   3.369      ///
   3.370      /// Add a new labeled edge reader for the reader.
   3.371      GraphReader& readEdge(std::string name, Edge& edge) {
   3.372 -      if (edge_readers.find(name) != edge_readers.end()) {
   3.373 -	ErrorMessage msg;
   3.374 -	msg << "Multiple read rule for edge: " << name;
   3.375 -	throw IOParameterError(msg.message());
   3.376 -      }
   3.377 -      edge_readers.insert(make_pair(name, &edge));
   3.378 +      edge_reader.readEdge(name, edge);
   3.379 +    }
   3.380 +
   3.381 +    /// \brief Add a new attribute reader command.
   3.382 +    ///
   3.383 +    ///  Add a new attribute reader command.
   3.384 +    template <typename Value>
   3.385 +    GraphReader& readAttribute(std::string name, Value& value) {
   3.386 +      attribute_reader.readAttribute(name, value);
   3.387        return *this;
   3.388      }
   3.389 +    
   3.390 +    /// \brief Add a new attribute reader command.
   3.391 +    ///
   3.392 +    ///  Add a new attribute reader command.
   3.393 +    template <typename Reader, typename Value>
   3.394 +    GraphReader& readAttribute(std::string name, Value& value, 
   3.395 +			       const Reader& reader) {
   3.396 +      attribute_reader.readAttribute<Reader>(name, value, reader);
   3.397 +      return *this;
   3.398 +    }
   3.399 +
   3.400 +    /// \brief Conversion operator to LemonReader.
   3.401 +    ///
   3.402 +    /// Conversion operator to LemonReader. It make possible
   3.403 +    /// to access the encapsulated \e LemonReader, this way
   3.404 +    /// you can attach to this reader new instances of 
   3.405 +    /// \e LemonReader::SectionReader.
   3.406 +    operator LemonReader&() {
   3.407 +      return *reader;
   3.408 +    }
   3.409  
   3.410      /// \brief Executes the reader commands.
   3.411      ///
   3.412      /// Executes the reader commands.
   3.413      void run() {
   3.414 -      int line_num = 0;
   3.415 -      std::auto_ptr<InverterBase<Node> > nodeInverter;
   3.416 -      std::auto_ptr<InverterBase<Edge> > edgeInverter;
   3.417 -      try {
   3.418 -	std::string line = readNotEmptyLine(is, line_num);
   3.419 -	if (line.find("@nodeset") == 0) {
   3.420 -	  line = readNodeSet(line_num, nodeInverter);
   3.421 -	} 
   3.422 -	if (line.find("@edgeset") == 0) {
   3.423 -	  line = readEdgeSet(line_num, edgeInverter, nodeInverter);
   3.424 -	}
   3.425 -	if (line.find("@nodes") == 0) {
   3.426 -	  line = readNodes(line_num, nodeInverter);
   3.427 -	}
   3.428 -	if (line.find("@edges") == 0) {
   3.429 -	  line = readEdges(line_num, edgeInverter);
   3.430 -	}
   3.431 -	if (line.find("@gui") == 0) {
   3.432 -	  line = readGUI(line_num);
   3.433 -	}
   3.434 -	if (line.find("@end") != 0) {
   3.435 -	  throw DataFormatError("Invalid control sequence error");
   3.436 -	}
   3.437 -      } catch (DataFormatError e) {
   3.438 -	e.line(line_num);
   3.439 -	throw e;
   3.440 -      }
   3.441 -    }
   3.442 -
   3.443 -    GraphReader& readGUI(GUIReader& reader) {
   3.444 -      gui_reader = &reader;
   3.445 -      return *this;
   3.446 +      reader->run();
   3.447      }
   3.448  
   3.449    private:
   3.450  
   3.451 -    template <typename Item> class InverterBase;
   3.452 +    LemonReader* reader;
   3.453 +    bool own_reader;
   3.454  
   3.455 -    std::string readNodeSet(int& line_num, 
   3.456 -			    std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   3.457 -      std::vector<ReaderBase<Node>* > index;
   3.458 -      {
   3.459 -	std::string line = readNotEmptyLine(is, line_num);    
   3.460 -	std::string id;
   3.461 -	std::istringstream ls(line);	
   3.462 -	while (ls >> id) {
   3.463 -	  typename NodeMapReaders::iterator it = node_map_readers.find(id);
   3.464 -	  if (it != node_map_readers.end()) {
   3.465 -	    index.push_back(it->second);
   3.466 -	    node_map_readers.erase(it);
   3.467 -	  } else {
   3.468 -	    index.push_back(&nodeSkipper);
   3.469 -	  }
   3.470 -	  if (ReaderTraits::idMapName(id) && nodeInverter.get() == 0) {
   3.471 -	    nodeInverter.reset(index.back()->getInverter());
   3.472 -	    index.back() = nodeInverter.get();
   3.473 -	  }
   3.474 -	}
   3.475 -      }
   3.476 -
   3.477 -//       if (index.size() == 0) {
   3.478 -// 	throw DataFormatError("Cannot find node id map");
   3.479 -//       }
   3.480 -
   3.481 -//       nodeInverter = 
   3.482 -// 	std::auto_ptr<InverterBase<Node> >(index[0]->getInverter());
   3.483 -      std::string line;
   3.484 -      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   3.485 -	Node node = graph.addNode();
   3.486 -	std::istringstream ls(line);
   3.487 -	for (int i = 0; i < (int)index.size(); ++i) {
   3.488 -	  index[i]->read(ls, node);
   3.489 -	}
   3.490 -      }
   3.491 -      return line;
   3.492 -    }
   3.493 -
   3.494 -    std::string readEdgeSet(int& line_num, 
   3.495 -			    std::auto_ptr<InverterBase<Edge> >& edgeInverter, 
   3.496 -			    std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   3.497 -      std::vector<ReaderBase<Edge>*> index;
   3.498 -      {
   3.499 -	std::string line = readNotEmptyLine(is, line_num);    
   3.500 -	std::string id;
   3.501 -	std::istringstream ls(line);	
   3.502 -	while (ls >> id) {
   3.503 -	  typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
   3.504 -	  if (it != edge_map_readers.end()) {
   3.505 -	    index.push_back(it->second);
   3.506 -	    edge_map_readers.erase(it);
   3.507 -	  } else {
   3.508 -	    index.push_back(&edgeSkipper);
   3.509 -	  }
   3.510 -	  if (ReaderTraits::idMapName(id) && edgeInverter.get() == 0) {
   3.511 -	    edgeInverter.reset(index.back()->getInverter());
   3.512 -	    index.back() = edgeInverter.get();
   3.513 -	  }
   3.514 -	}
   3.515 -      }
   3.516 -      
   3.517 -      if (nodeInverter.get() == 0) {
   3.518 - 	throw DataFormatError("Cannot find node id map");
   3.519 -      }
   3.520 -//       if (index.size() == 0) {
   3.521 -// 	throw DataFormatError("Cannot find edge id map");
   3.522 -//       }
   3.523 -
   3.524 -//       edgeInverter = 
   3.525 -// 	std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
   3.526 -      std::string line;
   3.527 -      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {	
   3.528 -	std::istringstream ls(line);
   3.529 -	Node source = nodeInverter->read(ls);
   3.530 -	Node target = nodeInverter->read(ls);
   3.531 -	Edge edge = graph.addEdge(source, target);
   3.532 -	for (int i = 0; i < (int)index.size(); ++i) {
   3.533 -	  index[i]->read(ls, edge);
   3.534 -	}
   3.535 -      }      
   3.536 -      return line;
   3.537 -    }
   3.538 -
   3.539 -    std::string readNodes(int& line_num, 
   3.540 -			  std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   3.541 -      std::string line;
   3.542 -      if (nodeInverter.get() == 0) {
   3.543 - 	throw DataFormatError("Cannot find node id map");
   3.544 -      }
   3.545 -      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   3.546 -	std::istringstream ls(line);
   3.547 -	std::string name;
   3.548 -	ls >> name;
   3.549 -	typename NodeReaders::iterator it = node_readers.find(name);
   3.550 -	if (it != node_readers.end()) {
   3.551 -	  *(it -> second) = nodeInverter->read(ls);
   3.552 -	} 
   3.553 -      }        
   3.554 -      return line;
   3.555 -    }
   3.556 -
   3.557 -    std::string readEdges(int& line_num, 
   3.558 -			  std::auto_ptr<InverterBase<Edge> >& edgeInverter) {
   3.559 -      std::string line;
   3.560 -      if (edgeInverter.get() == 0) {
   3.561 - 	throw DataFormatError("Cannot find edge id map");
   3.562 -      }
   3.563 -      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   3.564 -	std::istringstream ls(line);
   3.565 -	std::string name;
   3.566 -	ls >> name;
   3.567 -	typename EdgeReaders::iterator it = edge_readers.find(name);
   3.568 -	if (it != edge_readers.end()) {
   3.569 -	  *(it -> second) = edgeInverter->read(ls);
   3.570 -	} 
   3.571 -      }        
   3.572 -      return line;    
   3.573 -    }
   3.574 -
   3.575 -    std::string readGUI(int& line_num) {
   3.576 -      std::stringstream section;
   3.577 -      std::string line;
   3.578 -      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   3.579 -	section << line << std::endl;
   3.580 -      }
   3.581 -      if (gui_reader != 0) {
   3.582 -	gui_reader->read(section);
   3.583 -      }
   3.584 -      return line;
   3.585 -    }
   3.586 -
   3.587 -    std::string readNotEmptyLine(std::istream& is, int& line_num) {
   3.588 -      std::string line;
   3.589 -      while (++line_num, getline(is, line)) {	
   3.590 -	int vi = line.find('#');
   3.591 -	if (vi != (int)::std::string::npos) {
   3.592 -	  line = line.substr(0, vi);
   3.593 -	}
   3.594 -	vi = line.find_first_not_of(" \t");
   3.595 -	if (vi != (int)std::string::npos) { 
   3.596 -	  return line.substr(vi);
   3.597 -	}
   3.598 -      }
   3.599 -      throw DataFormatError("End of stream error");
   3.600 -    }
   3.601 -    
   3.602 -    template <typename _Item>
   3.603 -    class ReaderBase;
   3.604 -    
   3.605 -    template <typename _Item>
   3.606 -    class InverterBase : public ReaderBase<_Item> {
   3.607 -    public:
   3.608 -      typedef _Item Item;
   3.609 -      virtual void read(std::istream&, const Item&) = 0;
   3.610 -      virtual Item read(std::istream&) = 0;
   3.611 -
   3.612 -      virtual InverterBase<_Item>* getInverter() {
   3.613 -	return this;
   3.614 -      }
   3.615 -    };
   3.616 -
   3.617 -    template <typename _Item, typename _Map, typename _Reader>
   3.618 -    class MapReaderInverter : public InverterBase<_Item> {
   3.619 -    public:
   3.620 -      typedef _Item Item;
   3.621 -      typedef _Reader Reader;
   3.622 -      typedef typename Reader::Value Value;
   3.623 -      typedef _Map Map;
   3.624 -      typedef std::map<Value, Item> Inverse;
   3.625 -
   3.626 -      Map& map;
   3.627 -      Reader reader;
   3.628 -      Inverse inverse;
   3.629 -
   3.630 -      MapReaderInverter(Map& _map, const Reader& _reader) 
   3.631 -	: map(_map), reader(_reader) {}
   3.632 -
   3.633 -      virtual ~MapReaderInverter() {}
   3.634 -
   3.635 -      virtual void read(std::istream& is, const Item& item) {
   3.636 -	Value value;
   3.637 -	reader.read(is, value);
   3.638 -	map.set(item, value);
   3.639 -	typename Inverse::iterator it = inverse.find(value);
   3.640 -	if (it == inverse.end()) {
   3.641 -	  inverse.insert(std::make_pair(value, item));
   3.642 -	} else {
   3.643 -	  throw DataFormatError("Multiple ID occurence");
   3.644 -	}
   3.645 -      }
   3.646 -
   3.647 -      virtual Item read(std::istream& is) {
   3.648 -	Value value;
   3.649 -	reader.read(is, value);	
   3.650 -	typename Inverse::const_iterator it = inverse.find(value);
   3.651 -	if (it != inverse.end()) {
   3.652 -	  return it->second;
   3.653 -	} else {
   3.654 -	  throw DataFormatError("Invalid ID error");
   3.655 -	}
   3.656 -      }      
   3.657 -    };
   3.658 -
   3.659 -    template <typename _Item, typename _Reader>
   3.660 -    class SkipReaderInverter : public InverterBase<_Item> {
   3.661 -    public:
   3.662 -      typedef _Item Item;
   3.663 -      typedef _Reader Reader;
   3.664 -      typedef typename Reader::Value Value;
   3.665 -      typedef std::map<Value, Item> Inverse;
   3.666 -
   3.667 -      Reader reader;
   3.668 -
   3.669 -      SkipReaderInverter(const Reader& _reader) 
   3.670 -	: reader(_reader) {}
   3.671 -
   3.672 -      virtual ~SkipReaderInverter() {}
   3.673 -
   3.674 -      virtual void read(std::istream& is, const Item& item) {
   3.675 -	Value value;
   3.676 -	reader.read(is, value);
   3.677 -	typename Inverse::iterator it = inverse.find(value);
   3.678 -	if (it == inverse.end()) {
   3.679 -	  inverse.insert(std::make_pair(value, item));
   3.680 -	} else {
   3.681 -	  throw DataFormatError("Multiple ID occurence error");
   3.682 -	}
   3.683 -      }
   3.684 -
   3.685 -      virtual Item read(std::istream& is) {
   3.686 -	Value value;
   3.687 -	reader.read(is, value);	
   3.688 -	typename Inverse::const_iterator it = inverse.find(value);
   3.689 -	if (it != inverse.end()) {
   3.690 -	  return it->second;
   3.691 -	} else {
   3.692 -	  throw DataFormatError("Invalid ID error");
   3.693 -	}
   3.694 -      }      
   3.695 -    private:
   3.696 -      Inverse inverse;
   3.697 -    };
   3.698 -
   3.699 -    // Readers
   3.700 -
   3.701 -    template <typename _Item>    
   3.702 -    class ReaderBase {
   3.703 -    public:
   3.704 -      typedef _Item Item;
   3.705 -
   3.706 -      //      virtual ~ReaderBase() {}
   3.707 -
   3.708 -      virtual void read(std::istream& is, const Item& item) = 0;
   3.709 -      virtual InverterBase<_Item>* getInverter() = 0;
   3.710 -    };
   3.711 -
   3.712 -    template <typename _Item, typename _Map, typename _Reader>
   3.713 -    class MapReader : public ReaderBase<_Item> {
   3.714 -    public:
   3.715 -      typedef _Map Map;
   3.716 -      typedef _Reader Reader;
   3.717 -      typedef typename Reader::Value Value;
   3.718 -      typedef _Item Item;
   3.719 -      
   3.720 -      Map& map;
   3.721 -      Reader reader;
   3.722 -
   3.723 -      MapReader(Map& _map, const Reader& _reader) 
   3.724 -	: map(_map), reader(_reader) {}
   3.725 -
   3.726 -      virtual ~MapReader() {}
   3.727 -
   3.728 -      virtual void read(std::istream& is, const Item& item) {
   3.729 -	Value value;
   3.730 -	reader.read(is, value);
   3.731 -	map.set(item, value);
   3.732 -      }
   3.733 -
   3.734 -      virtual InverterBase<_Item>* getInverter() {
   3.735 -	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   3.736 -      }
   3.737 -    };
   3.738 -
   3.739 -
   3.740 -    template <typename _Item, typename _Reader>
   3.741 -    class SkipReader : public ReaderBase<_Item> {
   3.742 -    public:
   3.743 -      typedef _Reader Reader;
   3.744 -      typedef typename Reader::Value Value;
   3.745 -      typedef _Item Item;
   3.746 -
   3.747 -      Reader reader;
   3.748 -      SkipReader(const Reader& _reader) : reader(_reader) {}
   3.749 -
   3.750 -      virtual ~SkipReader() {}
   3.751 -
   3.752 -      virtual void read(std::istream& is, const Item&) {
   3.753 -	Value value;
   3.754 -	reader.read(is, value);
   3.755 -      }      
   3.756 -
   3.757 -      virtual InverterBase<Item>* getInverter() {
   3.758 -	return new SkipReaderInverter<Item, Reader>(reader);
   3.759 -      }
   3.760 -    };
   3.761 -
   3.762 -
   3.763 -    typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
   3.764 -    NodeMapReaders node_map_readers;
   3.765 -
   3.766 -    typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
   3.767 -    EdgeMapReaders edge_map_readers;
   3.768 -
   3.769 -    typedef std::map<std::string, Node*> NodeReaders;
   3.770 -    NodeReaders node_readers;
   3.771 -
   3.772 -    typedef std::map<std::string, Edge*> EdgeReaders;
   3.773 -    EdgeReaders edge_readers;
   3.774 -
   3.775 -    GUIReader* gui_reader;
   3.776 -
   3.777 -    std::istream& is;
   3.778      Graph& graph;
   3.779  
   3.780 -    SkipReader<Node, DefaultReader> nodeSkipper;
   3.781 -    SkipReader<Edge, DefaultReader> edgeSkipper;
   3.782 +    DefaultSkipper skipper;
   3.783  
   3.784 +    NodeSetReader<Graph, ReaderTraits> nodeset_reader;
   3.785 +    EdgeSetReader<Graph, ReaderTraits> edgeset_reader;
   3.786 +
   3.787 +    NodeReader<Graph> node_reader;
   3.788 +    EdgeReader<Graph> edge_reader;
   3.789 +    
   3.790 +    AttributeReader<ReaderTraits> attribute_reader;
   3.791    };
   3.792  
   3.793    /// \brief Read a graph from the input.
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/lemon/lemon_reader.h	Mon May 09 11:24:26 2005 +0000
     4.3 @@ -0,0 +1,977 @@
     4.4 +/* -*- C++ -*-
     4.5 + * src/lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
     4.6 + *
     4.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     4.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
     4.9 + *
    4.10 + * Permission to use, modify and distribute this software is granted
    4.11 + * provided that this copyright notice appears in all copies. For
    4.12 + * precise terms see the accompanying LICENSE file.
    4.13 + *
    4.14 + * This software is provided "AS IS" with no warranty of any kind,
    4.15 + * express or implied, and with no claim as to its suitability for any
    4.16 + * purpose.
    4.17 + *
    4.18 + */
    4.19 +
    4.20 +///\ingroup io_group
    4.21 +///\file
    4.22 +///\brief Lemon Format reader.
    4.23 +
    4.24 +#ifndef LEMON_LEMON_READER_H
    4.25 +#define LEMON_LEMON_READER_H
    4.26 +
    4.27 +#include <iostream>
    4.28 +#include <fstream>
    4.29 +#include <string>
    4.30 +#include <vector>
    4.31 +#include <algorithm>
    4.32 +#include <map>
    4.33 +#include <memory>
    4.34 +
    4.35 +#include <lemon/error.h>
    4.36 +#include "item_reader.h"
    4.37 +
    4.38 +
    4.39 +namespace lemon {
    4.40 +
    4.41 +  /// \addtogroup io_group
    4.42 +  /// @{
    4.43 +
    4.44 +  /// \brief Lemon Format reader class.
    4.45 +  /// 
    4.46 +  class LemonReader {
    4.47 +  private:
    4.48 +    
    4.49 +    class FilterStreamBuf : public std::streambuf {
    4.50 +    public:
    4.51 +
    4.52 +      typedef std::streambuf Parent;
    4.53 +      typedef Parent::char_type char_type;
    4.54 +      FilterStreamBuf(std::istream& is, int& num) 
    4.55 +	: _is(is), _base(0), _eptr(0), 
    4.56 +	  _num(num), skip_state(after_endl) {}
    4.57 +
    4.58 +    protected:
    4.59 +
    4.60 +      enum skip_state_type {
    4.61 +	no_skip,
    4.62 +	after_comment,
    4.63 +	after_endl,
    4.64 +	empty_line
    4.65 +      };
    4.66 +
    4.67 +      char_type small_buf[1];
    4.68 +
    4.69 +
    4.70 +      std::istream& _is;
    4.71 +
    4.72 +      char_type* _base;
    4.73 +      char_type* _eptr;
    4.74 +
    4.75 +      int& _num;
    4.76 +
    4.77 +      skip_state_type skip_state;
    4.78 +
    4.79 +
    4.80 +      char_type* base() { return _base; }
    4.81 +
    4.82 +      char_type* eptr() { return _eptr; }
    4.83 +
    4.84 +      int blen() { return _eptr - _base; }
    4.85 +
    4.86 +      void setb(char_type* buf, int len) {
    4.87 +	_base = buf;
    4.88 +	_eptr = buf + len;
    4.89 +      }
    4.90 +  
    4.91 +      virtual std::streambuf* setbuf(char *buf, int len) {
    4.92 +	if (base()) return 0;
    4.93 +	if (buf != 0 && len >= (int)sizeof(small_buf)) {
    4.94 +	  setb(buf, len);
    4.95 +	} else {
    4.96 +	  setb(small_buf, sizeof(small_buf));
    4.97 +	}
    4.98 +	setg(0, 0, 0);
    4.99 +	return this;
   4.100 +      }
   4.101 +
   4.102 +      bool put_char(char c) {
   4.103 +	switch (skip_state) {
   4.104 +	case no_skip:
   4.105 +	  switch (c) {
   4.106 +	  case '\n': 
   4.107 +	    skip_state = after_endl;
   4.108 +	    return true;
   4.109 +	  case '#':
   4.110 +	    skip_state = after_comment;
   4.111 +	    return false;
   4.112 +	  default:
   4.113 +	    return true;
   4.114 +	  }
   4.115 +	case after_comment:
   4.116 +	  switch (c) {
   4.117 +	  case '\n': 
   4.118 +	    skip_state = after_endl;
   4.119 +	    return true;
   4.120 +	  default:
   4.121 +	    return false;
   4.122 +	  }        
   4.123 +	case after_endl:
   4.124 +	  switch (c) {
   4.125 +	  case '@':
   4.126 +	    return false;
   4.127 +	  case '\n': 
   4.128 +	    return false;
   4.129 +	  case '#':
   4.130 +	    skip_state = empty_line;
   4.131 +	    return false;
   4.132 +	  default:
   4.133 +	    if (!isspace(c)) {
   4.134 +	      skip_state = no_skip;
   4.135 +	      return true;
   4.136 +	    } else {
   4.137 +	      return false;
   4.138 +	    }
   4.139 +	  }
   4.140 +	  break;
   4.141 +	case empty_line:
   4.142 +	  switch (c) {
   4.143 +	  case '\n': 
   4.144 +	    skip_state = after_endl;
   4.145 +	    return false;
   4.146 +	  default:
   4.147 +	    return false;
   4.148 +	  }
   4.149 +	}
   4.150 +	return false;
   4.151 +      }
   4.152 +
   4.153 +      virtual int underflow() {
   4.154 +	char c;
   4.155 +	if (_is.read(&c, 1)) {
   4.156 +	  _is.putback(c);
   4.157 +	  if (c == '@') {
   4.158 +	    return EOF;
   4.159 +	  }
   4.160 +	} else {
   4.161 +	  return EOF;
   4.162 +	}
   4.163 +	char_type *ptr;
   4.164 +	for (ptr = base(); ptr != eptr(); ++ptr) {
   4.165 +	  if (_is.read(&c, 1)) {
   4.166 +	    if (c == '\n') ++_num;
   4.167 +	    if (put_char(c)) {
   4.168 +	      *ptr = c;
   4.169 +	    } else {
   4.170 +	      if (skip_state == after_endl && c == '@') {
   4.171 +		_is.putback('@');
   4.172 +		break;
   4.173 +	      }
   4.174 +	      --ptr;
   4.175 +	    }
   4.176 +	  } else {
   4.177 +	    break;
   4.178 +	  }
   4.179 +	}
   4.180 +	setg(base(), base(), ptr);
   4.181 +	return *base();
   4.182 +      }
   4.183 +
   4.184 +      virtual int sync() {
   4.185 +	return EOF;
   4.186 +      }
   4.187 +    };
   4.188 +
   4.189 +  public:
   4.190 +
   4.191 +    class SectionReader {
   4.192 +    public:
   4.193 +      /// \e
   4.194 +      virtual bool header(const std::string& line) = 0;
   4.195 +      /// \e
   4.196 +      virtual void read(std::istream& is) = 0;
   4.197 +    };
   4.198 +
   4.199 +    /// \e
   4.200 +    LemonReader(std::istream& _is) 
   4.201 +      : is(&_is), own_is(false) {}
   4.202 +
   4.203 +    LemonReader(const std::string& filename) 
   4.204 +      : is(0), own_is(true) {
   4.205 +      is = new std::ifstream(filename.c_str());
   4.206 +    }
   4.207 +
   4.208 +
   4.209 +    ~LemonReader() {
   4.210 +      if (own_is) {
   4.211 +	delete is;
   4.212 +      }
   4.213 +    }
   4.214 +
   4.215 +  private:
   4.216 +    LemonReader(const LemonReader&);
   4.217 +    void operator=(const LemonReader&);
   4.218 +
   4.219 +  public:
   4.220 +    
   4.221 +    /// \e
   4.222 +    void attach(SectionReader& reader) {
   4.223 +      readers.push_back(&reader);
   4.224 +    }
   4.225 +
   4.226 +    /// \e
   4.227 +    void detach(SectionReader& reader) {
   4.228 +      std::vector<SectionReader*>::iterator it = 
   4.229 +	std::find(readers.begin(), readers.end(), &reader);
   4.230 +      if (it != readers.end()) {
   4.231 +	readers.erase(it);
   4.232 +      }
   4.233 +    }
   4.234 +
   4.235 +    /// \e
   4.236 +    void run() {
   4.237 +      int line_num = 0;
   4.238 +      std::string line;
   4.239 +      try {
   4.240 +	while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
   4.241 +	  SectionReaders::iterator it;
   4.242 +	  for (it = readers.begin(); it != readers.end(); ++it) {
   4.243 +	    if ((*it)->header(line)) {
   4.244 +	      char buf[2048];
   4.245 +	      FilterStreamBuf buffer(*is, line_num);
   4.246 +	      buffer.pubsetbuf(buf, sizeof(buf));
   4.247 +	      std::istream is(&buffer);
   4.248 +	      (*it)->read(is);
   4.249 +	      break;
   4.250 +	    }
   4.251 +	  }
   4.252 +	}
   4.253 +      } catch (DataFormatError& error) {
   4.254 +	error.line(line_num);
   4.255 +	throw error;
   4.256 +      }	
   4.257 +    }
   4.258 +
   4.259 +
   4.260 +  private:
   4.261 +
   4.262 +    std::istream* is;
   4.263 +    bool own_is;
   4.264 +
   4.265 +    typedef std::vector<SectionReader*> SectionReaders;
   4.266 +    SectionReaders readers;
   4.267 +
   4.268 +  };
   4.269 +
   4.270 +
   4.271 +  /// \e
   4.272 +  class CommonSectionReaderBase : public LemonReader::SectionReader {
   4.273 +  protected:
   4.274 +    template <typename _Item>
   4.275 +    class ReaderBase;
   4.276 +    
   4.277 +    template <typename _Item>
   4.278 +    class InverterBase : public ReaderBase<_Item> {
   4.279 +    public:
   4.280 +      typedef _Item Item;
   4.281 +      virtual void read(std::istream&, const Item&) = 0;
   4.282 +      virtual Item read(std::istream&) const = 0;
   4.283 +
   4.284 +      virtual InverterBase<_Item>* getInverter() {
   4.285 +	return this;
   4.286 +      }
   4.287 +
   4.288 +
   4.289 +    };
   4.290 +
   4.291 +    template <typename _Item, typename _Map, typename _Reader>
   4.292 +    class MapReaderInverter : public InverterBase<_Item> {
   4.293 +    public:
   4.294 +      typedef _Item Item;
   4.295 +      typedef _Reader Reader;
   4.296 +      typedef typename Reader::Value Value;
   4.297 +      typedef _Map Map;
   4.298 +      typedef std::map<Value, Item> Inverse;
   4.299 +
   4.300 +      Map& map;
   4.301 +      Reader reader;
   4.302 +      Inverse inverse;
   4.303 +
   4.304 +      MapReaderInverter(Map& _map, const Reader& _reader) 
   4.305 +	: map(_map), reader(_reader) {}
   4.306 +
   4.307 +      virtual ~MapReaderInverter() {}
   4.308 +
   4.309 +      virtual void read(std::istream& is, const Item& item) {
   4.310 +	Value value;
   4.311 +	reader.read(is, value);
   4.312 +	map.set(item, value);
   4.313 +	typename Inverse::iterator it = inverse.find(value);
   4.314 +	if (it == inverse.end()) {
   4.315 +	  inverse.insert(std::make_pair(value, item));
   4.316 +	} else {
   4.317 +	  throw DataFormatError("Multiple ID occurence");
   4.318 +	}
   4.319 +      }
   4.320 +
   4.321 +      virtual Item read(std::istream& is) const {
   4.322 +	Value value;
   4.323 +	reader.read(is, value);	
   4.324 +	typename Inverse::const_iterator it = inverse.find(value);
   4.325 +	if (it != inverse.end()) {
   4.326 +	  return it->second;
   4.327 +	} else {
   4.328 +	  throw DataFormatError("Invalid ID error");
   4.329 +	}
   4.330 +      }      
   4.331 +
   4.332 +    };
   4.333 +
   4.334 +    template <typename _Item, typename _Reader>
   4.335 +    class SkipReaderInverter : public InverterBase<_Item> {
   4.336 +    public:
   4.337 +      typedef _Item Item;
   4.338 +      typedef _Reader Reader;
   4.339 +      typedef typename Reader::Value Value;
   4.340 +      typedef std::map<Value, Item> Inverse;
   4.341 +
   4.342 +      Reader reader;
   4.343 +
   4.344 +      SkipReaderInverter(const Reader& _reader) 
   4.345 +	: reader(_reader) {}
   4.346 +
   4.347 +      virtual ~SkipReaderInverter() {}
   4.348 +
   4.349 +      virtual void read(std::istream& is, const Item& item) {
   4.350 +	Value value;
   4.351 +	reader.read(is, value);
   4.352 +	typename Inverse::iterator it = inverse.find(value);
   4.353 +	if (it == inverse.end()) {
   4.354 +	  inverse.insert(std::make_pair(value, item));
   4.355 +	} else {
   4.356 +	  throw DataFormatError("Multiple ID occurence error");
   4.357 +	}
   4.358 +      }
   4.359 +
   4.360 +      virtual Item read(std::istream& is) const {
   4.361 +	Value value;
   4.362 +	reader.read(is, value);	
   4.363 +	typename Inverse::const_iterator it = inverse.find(value);
   4.364 +	if (it != inverse.end()) {
   4.365 +	  return it->second;
   4.366 +	} else {
   4.367 +	  throw DataFormatError("Invalid ID error");
   4.368 +	}
   4.369 +      }
   4.370 +
   4.371 +    private:
   4.372 +      Inverse inverse;
   4.373 +    };
   4.374 +
   4.375 +    // Readers
   4.376 +
   4.377 +    template <typename _Item>    
   4.378 +    class ReaderBase {
   4.379 +    public:
   4.380 +      typedef _Item Item;
   4.381 +
   4.382 +      virtual ~ReaderBase() {}
   4.383 +
   4.384 +      virtual void read(std::istream& is, const Item& item) = 0;
   4.385 +      virtual InverterBase<_Item>* getInverter() = 0;
   4.386 +    };
   4.387 +
   4.388 +    template <typename _Item, typename _Map, typename _Reader>
   4.389 +    class MapReader : public ReaderBase<_Item> {
   4.390 +    public:
   4.391 +      typedef _Map Map;
   4.392 +      typedef _Reader Reader;
   4.393 +      typedef typename Reader::Value Value;
   4.394 +      typedef _Item Item;
   4.395 +      
   4.396 +      Map& map;
   4.397 +      Reader reader;
   4.398 +
   4.399 +      MapReader(Map& _map, const Reader& _reader) 
   4.400 +	: map(_map), reader(_reader) {}
   4.401 +
   4.402 +      virtual ~MapReader() {}
   4.403 +
   4.404 +      virtual void read(std::istream& is, const Item& item) {
   4.405 +	Value value;
   4.406 +	reader.read(is, value);
   4.407 +	map.set(item, value);
   4.408 +      }
   4.409 +
   4.410 +      virtual InverterBase<_Item>* getInverter() {
   4.411 +	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   4.412 +      }
   4.413 +    };
   4.414 +
   4.415 +
   4.416 +    template <typename _Item, typename _Reader>
   4.417 +    class SkipReader : public ReaderBase<_Item> {
   4.418 +    public:
   4.419 +      typedef _Reader Reader;
   4.420 +      typedef typename Reader::Value Value;
   4.421 +      typedef _Item Item;
   4.422 +
   4.423 +      Reader reader;
   4.424 +      SkipReader(const Reader& _reader) : reader(_reader) {}
   4.425 +
   4.426 +      virtual ~SkipReader() {}
   4.427 +
   4.428 +      virtual void read(std::istream& is, const Item&) {
   4.429 +	Value value;
   4.430 +	reader.read(is, value);
   4.431 +      }      
   4.432 +
   4.433 +      virtual InverterBase<Item>* getInverter() {
   4.434 +	return new SkipReaderInverter<Item, Reader>(reader);
   4.435 +      }
   4.436 +    };
   4.437 +
   4.438 +    template <typename _Item>
   4.439 +    class ResolverReaderBase {
   4.440 +    public:
   4.441 +      typedef _Item Item;
   4.442 +      virtual Item resolve(std::istream& is) const = 0;
   4.443 +    };
   4.444 +
   4.445 +    template <typename _Item, typename _Resolver>
   4.446 +    class ResolverReader : public ResolverReaderBase<_Item> {
   4.447 +    public:
   4.448 +      typedef _Item Item;
   4.449 +      typedef _Resolver Resolver;
   4.450 +
   4.451 +      const Resolver& resolver;
   4.452 +
   4.453 +      ResolverReader(const Resolver& _resolver) 
   4.454 +	: resolver(_resolver) {}
   4.455 +
   4.456 +      virtual Item resolve(std::istream& is) const {
   4.457 +	return resolver.resolve(is);
   4.458 +      }
   4.459 +    };
   4.460 +
   4.461 +    class ValueReaderBase {
   4.462 +    public:
   4.463 +      virtual void read(std::istream&) {};
   4.464 +    };
   4.465 +
   4.466 +    template <typename _Value, typename _Reader>
   4.467 +    class ValueReader : public ValueReaderBase {
   4.468 +    public:
   4.469 +      typedef _Value Value;
   4.470 +      typedef _Reader Reader;
   4.471 +
   4.472 +      ValueReader(Value& _value, const Reader& _reader)
   4.473 + 	: value(_value), reader(_reader) {}
   4.474 +
   4.475 +      virtual void read(std::istream& is) {
   4.476 +	reader.read(is, value);
   4.477 +      }
   4.478 +    private:
   4.479 +      Value& value;
   4.480 +      Reader reader;
   4.481 +    };
   4.482 +    
   4.483 +  };
   4.484 +
   4.485 +
   4.486 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   4.487 +  class NodeSetReader : public CommonSectionReaderBase {
   4.488 +    typedef CommonSectionReaderBase Parent;
   4.489 +  public:
   4.490 +
   4.491 +    typedef _Graph Graph;
   4.492 +    typedef _Traits Traits;
   4.493 +    typedef typename Graph::Node Item;
   4.494 +    typedef typename Traits::Skipper DefaultSkipper;
   4.495 +
   4.496 +    NodeSetReader(LemonReader& _reader, Graph& _graph, 
   4.497 +		  const std::string& _id = std::string(),
   4.498 +		  const DefaultSkipper& _defreader = DefaultSkipper()) 
   4.499 +      : graph(_graph), id(_id), skipper(_defreader) {
   4.500 +      _reader.attach(*this);
   4.501 +    } 
   4.502 +
   4.503 +    virtual ~NodeSetReader() {
   4.504 +      for (typename MapReaders::iterator it = readers.begin(); 
   4.505 +	   it != readers.end(); ++it) {
   4.506 +	delete it->second;
   4.507 +      }
   4.508 +    }
   4.509 +
   4.510 +  private:
   4.511 +    NodeSetReader(const NodeSetReader&);
   4.512 +    void operator=(const NodeSetReader&);
   4.513 +  
   4.514 +  public:
   4.515 +
   4.516 +    /// \brief Add a new node map reader command for the reader.
   4.517 +    ///
   4.518 +    /// Add a new node map reader command for the reader.
   4.519 +    template <typename Map>
   4.520 +    NodeSetReader& readMap(std::string name, Map& map) {
   4.521 +      return readMap<typename Traits::
   4.522 +	template Reader<typename Map::Value>, Map>(name, map);
   4.523 +    }
   4.524 +
   4.525 +    /// \brief Add a new node map reader command for the reader.
   4.526 +    ///
   4.527 +    /// Add a new node map reader command for the reader.
   4.528 +    template <typename Reader, typename Map>
   4.529 +    NodeSetReader& readMap(std::string name, Map& map, 
   4.530 +			     const Reader& reader = Reader()) {
   4.531 +      if (readers.find(name) != readers.end()) {
   4.532 +	ErrorMessage msg;
   4.533 +	msg << "Multiple read rule for node map: " << name;
   4.534 +	throw IOParameterError(msg.message());
   4.535 +      }
   4.536 +      readers.insert(
   4.537 +	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   4.538 +      return *this;
   4.539 +    }
   4.540 +
   4.541 +    /// \brief Add a new node map skipper command for the reader.
   4.542 +    ///
   4.543 +    /// Add a new node map skipper command for the reader.
   4.544 +    template <typename Reader>
   4.545 +    NodeSetReader& skipMap(std::string name, 
   4.546 +			   const Reader& reader = Reader()) {
   4.547 +      if (readers.find(name) != readers.end()) {
   4.548 +	ErrorMessage msg;
   4.549 +	msg << "Multiple read rule for node map: " << name;
   4.550 +	throw IOParameterError(msg.message());
   4.551 +      }
   4.552 +      readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   4.553 +      return *this;
   4.554 +    }
   4.555 +
   4.556 +    /// \e
   4.557 +    virtual bool header(const std::string& line) {
   4.558 +      std::istringstream ls(line);
   4.559 +      std::string command;
   4.560 +      std::string name;
   4.561 +      ls >> command >> name;
   4.562 +      return command == "@nodeset" && name == id;
   4.563 +    }
   4.564 +
   4.565 +    /// \e
   4.566 +    virtual void read(std::istream& is) {
   4.567 +      std::vector<ReaderBase<Item>* > index;
   4.568 +      std::string line;
   4.569 +
   4.570 +      getline(is, line);
   4.571 +      std::istringstream ls(line);	
   4.572 +      while (ls >> id) {
   4.573 +	typename MapReaders::iterator it = readers.find(id);
   4.574 +	if (it != readers.end()) {
   4.575 +	  index.push_back(it->second);
   4.576 +	} else {
   4.577 +	  index.push_back(&skipper);
   4.578 +	}
   4.579 +	if (id == "id" && inverter.get() == 0) {
   4.580 +	  inverter.reset(index.back()->getInverter());
   4.581 +	  index.back() = inverter.get();
   4.582 +	}
   4.583 +      }
   4.584 +      while (getline(is, line)) {	
   4.585 +	typename Graph::Node node = graph.addNode();
   4.586 +	std::istringstream ls(line);
   4.587 +	for (int i = 0; i < (int)index.size(); ++i) {
   4.588 +	  index[i]->read(ls, node);
   4.589 +	}
   4.590 +      }
   4.591 +    }
   4.592 +
   4.593 +    bool isResolver() const {
   4.594 +      return inverter.get() != 0;
   4.595 +    }
   4.596 +
   4.597 +    typename Graph::Node resolve(std::istream& is) const {
   4.598 +      return inverter->read(is);
   4.599 +    } 
   4.600 +
   4.601 +  private:
   4.602 +
   4.603 +    typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   4.604 +    MapReaders readers;
   4.605 +   
   4.606 +    Graph& graph;   
   4.607 +    std::string id;
   4.608 +    SkipReader<Item, DefaultSkipper> skipper;
   4.609 +
   4.610 +    std::auto_ptr<InverterBase<Item> > inverter;
   4.611 +  };
   4.612 +
   4.613 +
   4.614 + 
   4.615 +  /// \e
   4.616 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   4.617 +  class EdgeSetReader : public CommonSectionReaderBase {
   4.618 +    typedef CommonSectionReaderBase Parent;
   4.619 +  public:
   4.620 +
   4.621 +    typedef _Graph Graph;
   4.622 +    typedef _Traits Traits;
   4.623 +    typedef typename Graph::Edge Item;
   4.624 +    typedef typename Traits::Skipper DefaultSkipper;
   4.625 +
   4.626 +    template <typename Resolver>
   4.627 +    EdgeSetReader(LemonReader& _reader, Graph& _graph, 
   4.628 +		  const Resolver& _nodeResolver, 
   4.629 +		  const std::string& _id = std::string(),
   4.630 +		  const DefaultSkipper& _defreader = DefaultSkipper()) 
   4.631 +      : graph(_graph), id(_id), skipper(_defreader),
   4.632 +      nodeResolver(new ResolverReader<typename Graph::Node, Resolver>
   4.633 +		   (_nodeResolver)) {
   4.634 +      _reader.attach(*this);
   4.635 +    } 
   4.636 +
   4.637 +    virtual ~EdgeSetReader() {
   4.638 +      for (typename MapReaders::iterator it = readers.begin(); 
   4.639 +	   it != readers.end(); ++it) {
   4.640 +	delete it->second;
   4.641 +      }
   4.642 +    }
   4.643 +
   4.644 +  private:
   4.645 +    EdgeSetReader(const EdgeSetReader&);
   4.646 +    void operator=(const EdgeSetReader&);
   4.647 +
   4.648 +  public:
   4.649 +
   4.650 +    /// \brief Add a new node map reader command for the reader.
   4.651 +    ///
   4.652 +    /// Add a new node map reader command for the reader.
   4.653 +    template <typename Map>
   4.654 +    EdgeSetReader& readMap(std::string name, Map& map) {
   4.655 +      return readMap<typename Traits::
   4.656 +	template Reader<typename Map::Value>, Map>(name, map);
   4.657 +    }
   4.658 +
   4.659 +    /// \brief Add a new node map reader command for the reader.
   4.660 +    ///
   4.661 +    /// Add a new node map reader command for the reader.
   4.662 +    template <typename Reader, typename Map>
   4.663 +    EdgeSetReader& readMap(std::string name, Map& map, 
   4.664 +			     const Reader& reader = Reader()) {
   4.665 +      if (readers.find(name) != readers.end()) {
   4.666 +	ErrorMessage msg;
   4.667 +	msg << "Multiple read rule for edge map: " << name;
   4.668 +	throw IOParameterError(msg.message());
   4.669 +      }
   4.670 +      readers.insert(
   4.671 +	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   4.672 +      return *this;
   4.673 +    }
   4.674 +
   4.675 +    /// \brief Add a new node map skipper command for the reader.
   4.676 +    ///
   4.677 +    /// Add a new node map skipper command for the reader.
   4.678 +    template <typename Reader>
   4.679 +    EdgeSetReader& skipMap(std::string name, 
   4.680 +			   const Reader& reader = Reader()) {
   4.681 +      if (readers.find(name) != readers.end()) {
   4.682 +	ErrorMessage msg;
   4.683 +	msg << "Multiple read rule for node map: " << name;
   4.684 +	throw IOParameterError(msg.message());
   4.685 +      }
   4.686 +      readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   4.687 +      return *this;
   4.688 +    }
   4.689 +
   4.690 +    /// \e
   4.691 +    virtual bool header(const std::string& line) {
   4.692 +      std::istringstream ls(line);
   4.693 +      std::string command;
   4.694 +      std::string name;
   4.695 +      ls >> command >> name;
   4.696 +      return command == "@edgeset" && name == id;
   4.697 +    }
   4.698 +
   4.699 +    /// \e
   4.700 +    virtual void read(std::istream& is) {
   4.701 +      std::vector<ReaderBase<Item>* > index;
   4.702 +      std::string line;
   4.703 +
   4.704 +      getline(is, line);
   4.705 +      std::istringstream ls(line);	
   4.706 +      while (ls >> id) {
   4.707 +	typename MapReaders::iterator it = readers.find(id);
   4.708 +	if (it != readers.end()) {
   4.709 +	  index.push_back(it->second);
   4.710 +	} else {
   4.711 +	  index.push_back(&skipper);
   4.712 +	}
   4.713 +	if (id == "id" && inverter.get() == 0) {
   4.714 +	  inverter.reset(index.back()->getInverter());
   4.715 +	  index.back() = inverter.get();
   4.716 +	}
   4.717 +      }
   4.718 +      while (getline(is, line)) {	
   4.719 +	std::istringstream ls(line);
   4.720 +	typename Graph::Node from = nodeResolver->resolve(ls);
   4.721 +	typename Graph::Node to = nodeResolver->resolve(ls);
   4.722 +	typename Graph::Edge edge = graph.addEdge(from, to);
   4.723 +	for (int i = 0; i < (int)index.size(); ++i) {
   4.724 +	  index[i]->read(ls, edge);
   4.725 +	}
   4.726 +      }
   4.727 +    }
   4.728 +
   4.729 +    bool isResolver() const {
   4.730 +      return inverter.get() != 0;
   4.731 +    }
   4.732 +
   4.733 +    typename Graph::Edge resolve(std::istream& is) {
   4.734 +      return inverter->read(is);
   4.735 +    } 
   4.736 +
   4.737 +  private:
   4.738 +
   4.739 +    typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   4.740 +    MapReaders readers;
   4.741 +   
   4.742 +    Graph& graph;   
   4.743 +    std::string id;
   4.744 +    SkipReader<Item, DefaultSkipper> skipper;
   4.745 +
   4.746 +    std::auto_ptr<InverterBase<Item> > inverter;
   4.747 +    std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
   4.748 +  };
   4.749 +
   4.750 +
   4.751 +  /// \e
   4.752 +  template <typename _Traits = DefaultReaderTraits>
   4.753 +  class AttributeReader : public CommonSectionReaderBase {
   4.754 +    typedef CommonSectionReaderBase Parent;
   4.755 +    typedef _Traits Traits; 
   4.756 +  public:
   4.757 +    /// \e
   4.758 +    AttributeReader(LemonReader& _reader, 
   4.759 +		    const std::string& _id = std::string()) : id(_id) {
   4.760 +      _reader.attach(*this);
   4.761 +    }
   4.762 +
   4.763 +    /// \e
   4.764 +    virtual ~AttributeReader() {
   4.765 +      for (typename Readers::iterator it = readers.begin(); 
   4.766 +	   it != readers.end(); ++it) {
   4.767 +	delete it->second;
   4.768 +      }
   4.769 +    }
   4.770 +
   4.771 +  private:
   4.772 +    AttributeReader(const AttributeReader&);
   4.773 +    void operator=(AttributeReader&);
   4.774 +
   4.775 +  public:
   4.776 +    /// \e
   4.777 +    template <typename Value>
   4.778 +    AttributeReader& readAttribute(const std::string& id, Value& value) {
   4.779 +      return readAttribute<typename Traits::template Reader<Value> >
   4.780 +	(id, value);
   4.781 +    }
   4.782 +
   4.783 +    /// \e
   4.784 +    template <typename Reader, typename Value>
   4.785 +    AttributeReader& readAttribute(const std::string& name, Value& value,
   4.786 +				   const Reader& reader = Reader()) {
   4.787 +      if (readers.find(name) != readers.end()) {
   4.788 +	ErrorMessage msg;
   4.789 +	msg << "Multiple read rule for attribute: " << name;
   4.790 +	throw IOParameterError(msg.message());
   4.791 +      }
   4.792 +      readers.insert(make_pair(name, new ValueReader<Value, Reader>
   4.793 +      			       (value, reader)));
   4.794 +      return *this;
   4.795 +    }
   4.796 +
   4.797 +    /// \e
   4.798 +    bool header(const std::string& line) {
   4.799 +      std::istringstream ls(line);
   4.800 +      std::string command;
   4.801 +      std::string name;
   4.802 +      ls >> command >> name;
   4.803 +      return command == "@attributes" && name == id;
   4.804 +    }
   4.805 +
   4.806 +    /// \e
   4.807 +    void read(std::istream& is) {
   4.808 +      std::string line;
   4.809 +      while (getline(is, line)) {
   4.810 +	std::istringstream ls(line);
   4.811 +	std::string id;
   4.812 +	ls >> id;
   4.813 +	typename Readers::iterator it = readers.find(id);
   4.814 +	if (it != readers.end()) {
   4.815 +	  it->second->read(ls);
   4.816 +	}
   4.817 +      }
   4.818 +    }    
   4.819 +
   4.820 +  private:
   4.821 +    std::string id;
   4.822 +
   4.823 +    typedef std::map<std::string, ValueReaderBase*> Readers;
   4.824 +    Readers readers;
   4.825 +  
   4.826 +  };
   4.827 +
   4.828 +  template <typename _Graph>
   4.829 +  class NodeReader : public CommonSectionReaderBase {
   4.830 +    typedef CommonSectionReaderBase Parent;
   4.831 +    typedef _Graph Graph;
   4.832 +    typedef typename Graph::Node Item;
   4.833 +  public:
   4.834 +    
   4.835 +    template <typename Resolver>
   4.836 +    NodeReader(LemonReader& _reader, const Resolver& _resolver, 
   4.837 +	       const std::string& _id = std::string()) 
   4.838 +      : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
   4.839 +		     (_resolver)) {
   4.840 +      _reader.attach(*this);
   4.841 +    } 
   4.842 +
   4.843 +    virtual ~NodeReader() {}
   4.844 +
   4.845 +  private:
   4.846 +    NodeReader(const NodeReader&);
   4.847 +    void operator=(const NodeReader&);
   4.848 +
   4.849 +  public:
   4.850 +
   4.851 +    void readNode(const std::string& name, Item& item) {
   4.852 +      if (readers.find(name) != readers.end()) {
   4.853 +	ErrorMessage msg;
   4.854 +	msg << "Multiple read rule for node: " << name;
   4.855 +	throw IOParameterError(msg.message());
   4.856 +      }
   4.857 +      readers.insert(make_pair(name, &item));
   4.858 +    }
   4.859 +
   4.860 +    virtual bool header(const std::string& line) {
   4.861 +      std::istringstream ls(line);
   4.862 +      std::string command;
   4.863 +      std::string name;
   4.864 +      ls >> command >> name;
   4.865 +      return command == "@nodes" && name == id;
   4.866 +    }
   4.867 +
   4.868 +    virtual void read(std::istream& is) {
   4.869 +      std::string line;
   4.870 +      while (getline(is, line)) {
   4.871 +	std::istringstream ls(line);
   4.872 +	std::string id;
   4.873 +	ls >> id;
   4.874 +	typename ItemReaders::iterator it = readers.find(id);
   4.875 +	if (it != readers.end()) {
   4.876 +	  *(it->second) = resolver->resolve(ls); 
   4.877 +	}	
   4.878 +      }
   4.879 +    }
   4.880 +    
   4.881 +  private:
   4.882 +
   4.883 +    std::string id;
   4.884 +
   4.885 +    typedef std::map<std::string, Item*> ItemReaders;
   4.886 +    ItemReaders readers;
   4.887 +    std::auto_ptr<ResolverReaderBase<Item> > resolver;
   4.888 +  };
   4.889 +
   4.890 +  template <typename _Graph>
   4.891 +  class EdgeReader : public CommonSectionReaderBase {
   4.892 +    typedef CommonSectionReaderBase Parent;
   4.893 +    typedef _Graph Graph;
   4.894 +    typedef typename Graph::Edge Item;
   4.895 +  public:
   4.896 +    
   4.897 +    template <typename Resolver>
   4.898 +    EdgeReader(LemonReader& _reader, const Resolver& _resolver, 
   4.899 +	       const std::string& _id = std::string()) 
   4.900 +      : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
   4.901 +		     (_resolver)) {
   4.902 +      _reader.attach(*this);
   4.903 +    } 
   4.904 +
   4.905 +    virtual ~EdgeReader() {}
   4.906 +  private:
   4.907 +    EdgeReader(const EdgeReader&);
   4.908 +    void operator=(const EdgeReader&);
   4.909 +
   4.910 +  public:
   4.911 +
   4.912 +    void readEdge(const std::string& name, Item& item) {
   4.913 +      if (readers.find(name) != readers.end()) {
   4.914 +	ErrorMessage msg;
   4.915 +	msg << "Multiple read rule for edge: " << name;
   4.916 +	throw IOParameterError(msg.message());
   4.917 +      }
   4.918 +      readers.insert(make_pair(name, &item));
   4.919 +    }
   4.920 +
   4.921 +
   4.922 +    virtual bool header(const std::string& line) {
   4.923 +      std::istringstream ls(line);
   4.924 +      std::string command;
   4.925 +      std::string name;
   4.926 +      ls >> command >> name;
   4.927 +      return command == "@nodes" && name == id;
   4.928 +    }
   4.929 +
   4.930 +    virtual void read(std::istream& is) {
   4.931 +      std::string line;
   4.932 +      while (getline(is, line)) {
   4.933 +	std::istringstream ls(line);
   4.934 +	std::string id;
   4.935 +	ls >> id;
   4.936 +	typename ItemReaders::iterator it = readers.find(id);
   4.937 +	if (it != readers.end()) {
   4.938 +	  *(it->second) = resolver->resolve(ls); 
   4.939 +	}	
   4.940 +      }
   4.941 +    }
   4.942 +    
   4.943 +  private:
   4.944 +
   4.945 +    std::string id;
   4.946 +
   4.947 +    typedef std::map<std::string, Item*> ItemReaders;
   4.948 +    ItemReaders readers;
   4.949 +    std::auto_ptr<ResolverReaderBase<Item> > resolver;
   4.950 +  };
   4.951 +
   4.952 +  /// \e
   4.953 +  class PrintReader : public LemonReader::SectionReader {
   4.954 +    typedef LemonReader::SectionReader Parent;
   4.955 +  public:
   4.956 +
   4.957 +    /// \e
   4.958 +    PrintReader(LemonReader& reader) {
   4.959 +      reader.attach(*this);
   4.960 +    }
   4.961 +
   4.962 +    /// \e
   4.963 +    bool header(const std::string& line) {
   4.964 +      std::cout << "Asked header: " << line << std::endl; 
   4.965 +      return true;
   4.966 +    }
   4.967 +
   4.968 +    /// \e
   4.969 +    void read(std::istream& is) {
   4.970 +      std::string line;
   4.971 +      while (std::getline(is, line)) {
   4.972 +	std::cout << line << std::endl;
   4.973 +      }
   4.974 +    }
   4.975 +  
   4.976 +  };
   4.977 +
   4.978 +  /// @}
   4.979 +}
   4.980 +#endif