lemon/lgf_reader.h
author Balazs Dezso <deba@inf.elte.hu>
Fri, 04 Jul 2008 15:21:48 +0200
changeset 189 a63ed81c57ba
parent 188 70694e6bdcac
child 190 1e6af6f0843c
permissions -rw-r--r--
Section readers moved to distinct class
deba@127
     1
/* -*- C++ -*-
deba@127
     2
 *
deba@127
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@127
     4
 *
deba@127
     5
 * Copyright (C) 2003-2008
deba@127
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@127
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@127
     8
 *
deba@127
     9
 * Permission to use, modify and distribute this software is granted
deba@127
    10
 * provided that this copyright notice appears in all copies. For
deba@127
    11
 * precise terms see the accompanying LICENSE file.
deba@127
    12
 *
deba@127
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@127
    14
 * express or implied, and with no claim as to its suitability for any
deba@127
    15
 * purpose.
deba@127
    16
 *
deba@127
    17
 */
deba@127
    18
deba@127
    19
///\ingroup lemon_io
deba@127
    20
///\file
deba@127
    21
///\brief Lemon Graph Format reader.
deba@127
    22
deba@127
    23
deba@127
    24
#ifndef LEMON_LGF_READER_H
deba@127
    25
#define LEMON_LGF_READER_H
deba@127
    26
deba@127
    27
#include <iostream>
deba@127
    28
#include <fstream>
deba@127
    29
#include <sstream>
deba@127
    30
deba@127
    31
#include <set>
deba@127
    32
#include <map>
deba@127
    33
deba@127
    34
#include <lemon/assert.h>
deba@127
    35
#include <lemon/graph_utils.h>
deba@127
    36
deba@127
    37
#include <lemon/lgf_writer.h>
deba@127
    38
deba@127
    39
#include <lemon/concept_check.h>
deba@127
    40
#include <lemon/concepts/maps.h>
deba@127
    41
deba@127
    42
namespace lemon {
deba@127
    43
deba@127
    44
  namespace _reader_bits {
deba@127
    45
deba@127
    46
    template <typename Value>
deba@127
    47
    struct DefaultConverter {
deba@127
    48
      Value operator()(const std::string& str) {
deba@127
    49
	std::istringstream is(str);
deba@127
    50
	Value value;
deba@127
    51
	is >> value;
deba@127
    52
deba@127
    53
	char c;
deba@127
    54
	if (is >> std::ws >> c) {
deba@127
    55
	  throw DataFormatError("Remaining characters in token");
deba@127
    56
	}
deba@127
    57
	return value;
deba@127
    58
      }
deba@127
    59
    };
deba@127
    60
deba@127
    61
    template <>
deba@127
    62
    struct DefaultConverter<std::string> {
deba@127
    63
      std::string operator()(const std::string& str) {
deba@127
    64
	return str;
deba@127
    65
      }
deba@127
    66
    };
deba@127
    67
deba@127
    68
    template <typename _Item>    
deba@127
    69
    class MapStorageBase {
deba@127
    70
    public:
deba@127
    71
      typedef _Item Item;
deba@127
    72
deba@127
    73
    public:
deba@127
    74
      MapStorageBase() {}
deba@127
    75
      virtual ~MapStorageBase() {}
deba@127
    76
deba@127
    77
      virtual void set(const Item& item, const std::string& value) = 0;
deba@127
    78
deba@127
    79
    };
deba@127
    80
deba@127
    81
    template <typename _Item, typename _Map, 
deba@127
    82
	      typename _Converter = DefaultConverter<typename _Map::Value> >
deba@127
    83
    class MapStorage : public MapStorageBase<_Item> {
deba@127
    84
    public:
deba@127
    85
      typedef _Map Map;
deba@127
    86
      typedef _Converter Converter;
deba@127
    87
      typedef _Item Item;
deba@127
    88
      
deba@127
    89
    private:
deba@127
    90
      Map& _map;
deba@127
    91
      Converter _converter;
deba@127
    92
deba@127
    93
    public:
deba@127
    94
      MapStorage(Map& map, const Converter& converter = Converter()) 
deba@127
    95
	: _map(map), _converter(converter) {}
deba@127
    96
      virtual ~MapStorage() {}
deba@127
    97
deba@127
    98
      virtual void set(const Item& item ,const std::string& value) {
deba@127
    99
	_map.set(item, _converter(value));
deba@127
   100
      }
deba@127
   101
    };
deba@127
   102
deba@165
   103
    template <typename _Graph, bool _dir, typename _Map, 
deba@165
   104
	      typename _Converter = DefaultConverter<typename _Map::Value> >
deba@165
   105
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
deba@165
   106
    public:
deba@165
   107
      typedef _Map Map;
deba@165
   108
      typedef _Converter Converter;
deba@165
   109
      typedef _Graph Graph;
deba@165
   110
      typedef typename Graph::Edge Item;
deba@165
   111
      static const bool dir = _dir;
deba@165
   112
      
deba@165
   113
    private:
deba@165
   114
      const Graph& _graph;
deba@165
   115
      Map& _map;
deba@165
   116
      Converter _converter;
deba@165
   117
deba@165
   118
    public:
deba@165
   119
      GraphArcMapStorage(const Graph& graph, Map& map, 
deba@165
   120
			 const Converter& converter = Converter()) 
deba@165
   121
	: _graph(graph), _map(map), _converter(converter) {}
deba@165
   122
      virtual ~GraphArcMapStorage() {}
deba@165
   123
deba@165
   124
      virtual void set(const Item& item ,const std::string& value) {
deba@165
   125
	_map.set(_graph.direct(item, dir), _converter(value));
deba@165
   126
      }
deba@165
   127
    };
deba@165
   128
deba@127
   129
    class ValueStorageBase {
deba@127
   130
    public:
deba@127
   131
      ValueStorageBase() {}
deba@127
   132
      virtual ~ValueStorageBase() {}
deba@127
   133
deba@127
   134
      virtual void set(const std::string&) = 0;
deba@127
   135
    };
deba@127
   136
deba@127
   137
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
deba@127
   138
    class ValueStorage : public ValueStorageBase {
deba@127
   139
    public:
deba@127
   140
      typedef _Value Value;
deba@127
   141
      typedef _Converter Converter;
deba@127
   142
deba@127
   143
    private:
deba@127
   144
      Value& _value;
deba@127
   145
      Converter _converter;
deba@127
   146
deba@127
   147
    public:
deba@127
   148
      ValueStorage(Value& value, const Converter& converter = Converter())
deba@127
   149
 	: _value(value), _converter(converter) {}
deba@127
   150
deba@127
   151
      virtual void set(const std::string& value) {
deba@127
   152
	_value = _converter(value);
deba@127
   153
      }
deba@127
   154
    };
deba@127
   155
deba@127
   156
    template <typename Value>
deba@127
   157
    struct MapLookUpConverter {
deba@127
   158
      const std::map<std::string, Value>& _map;
deba@127
   159
deba@127
   160
      MapLookUpConverter(const std::map<std::string, Value>& map)
deba@127
   161
        : _map(map) {}
deba@127
   162
deba@127
   163
      Value operator()(const std::string& str) {
deba@127
   164
        typename std::map<std::string, Value>::const_iterator it =
deba@127
   165
          _map.find(str);
deba@127
   166
        if (it == _map.end()) {
deba@127
   167
          std::ostringstream msg;
deba@127
   168
          msg << "Item not found: " << str;
deba@127
   169
          throw DataFormatError(msg.str().c_str());
deba@127
   170
        }
deba@127
   171
        return it->second;
deba@127
   172
      }
deba@127
   173
    };
deba@127
   174
deba@165
   175
    template <typename Graph>
deba@165
   176
    struct GraphArcLookUpConverter {
deba@165
   177
      const Graph& _graph;
deba@165
   178
      const std::map<std::string, typename Graph::Edge>& _map;
deba@165
   179
      
deba@165
   180
      GraphArcLookUpConverter(const Graph& graph, 
deba@165
   181
			      const std::map<std::string,
deba@165
   182
			                     typename Graph::Edge>& map) 
deba@165
   183
	: _graph(graph), _map(map) {}
deba@165
   184
      
deba@165
   185
      typename Graph::Arc operator()(const std::string& str) {
deba@165
   186
	if (str.empty() || (str[0] != '+' && str[0] != '-')) {
deba@165
   187
	  throw DataFormatError("Item must start with '+' or '-'");
deba@165
   188
	}
deba@165
   189
	typename std::map<std::string, typename Graph::Edge>
deba@165
   190
	  ::const_iterator it = _map.find(str.substr(1));
deba@165
   191
	if (it == _map.end()) {
deba@165
   192
	  throw DataFormatError("Item not found");
deba@165
   193
	}
deba@165
   194
	return _graph.direct(it->second, str[0] == '+');
deba@165
   195
      }
deba@165
   196
    };
deba@165
   197
deba@127
   198
    bool isWhiteSpace(char c) {
deba@127
   199
      return c == ' ' || c == '\t' || c == '\v' || 
deba@127
   200
        c == '\n' || c == '\r' || c == '\f'; 
deba@127
   201
    }
deba@127
   202
    
deba@127
   203
    bool isOct(char c) {
deba@127
   204
      return '0' <= c && c <='7'; 
deba@127
   205
    }
deba@127
   206
    
deba@127
   207
    int valueOct(char c) {
deba@127
   208
      LEMON_ASSERT(isOct(c), "The character is not octal.");
deba@127
   209
      return c - '0';
deba@127
   210
    }
deba@127
   211
deba@127
   212
    bool isHex(char c) {
deba@127
   213
      return ('0' <= c && c <= '9') || 
deba@127
   214
	('a' <= c && c <= 'z') || 
deba@127
   215
	('A' <= c && c <= 'Z'); 
deba@127
   216
    }
deba@127
   217
    
deba@127
   218
    int valueHex(char c) {
deba@127
   219
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
deba@127
   220
      if ('0' <= c && c <= '9') return c - '0';
deba@127
   221
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
deba@127
   222
      return c - 'A' + 10;
deba@127
   223
    }
deba@127
   224
deba@127
   225
    bool isIdentifierFirstChar(char c) {
deba@127
   226
      return ('a' <= c && c <= 'z') ||
deba@127
   227
	('A' <= c && c <= 'Z') || c == '_';
deba@127
   228
    }
deba@127
   229
deba@127
   230
    bool isIdentifierChar(char c) {
deba@127
   231
      return isIdentifierFirstChar(c) ||
deba@127
   232
	('0' <= c && c <= '9');
deba@127
   233
    }
deba@127
   234
deba@127
   235
    char readEscape(std::istream& is) {
deba@127
   236
      char c;
deba@127
   237
      if (!is.get(c))
deba@127
   238
	throw DataFormatError("Escape format error");
deba@127
   239
deba@127
   240
      switch (c) {
deba@127
   241
      case '\\':
deba@127
   242
	return '\\';
deba@127
   243
      case '\"':
deba@127
   244
	return '\"';
deba@127
   245
      case '\'':
deba@127
   246
	return '\'';
deba@127
   247
      case '\?':
deba@127
   248
	return '\?';
deba@127
   249
      case 'a':
deba@127
   250
	return '\a';
deba@127
   251
      case 'b':
deba@127
   252
	return '\b';
deba@127
   253
      case 'f':
deba@127
   254
	return '\f';
deba@127
   255
      case 'n':
deba@127
   256
	return '\n';
deba@127
   257
      case 'r':
deba@127
   258
	return '\r';
deba@127
   259
      case 't':
deba@127
   260
	return '\t';
deba@127
   261
      case 'v':
deba@127
   262
	return '\v';
deba@127
   263
      case 'x':
deba@127
   264
	{
deba@127
   265
	  int code;
deba@127
   266
	  if (!is.get(c) || !isHex(c)) 
deba@127
   267
	    throw DataFormatError("Escape format error");
deba@127
   268
	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
deba@127
   269
	  else code = code * 16 + valueHex(c);
deba@127
   270
	  return code;
deba@127
   271
	}
deba@127
   272
      default:
deba@127
   273
	{
deba@127
   274
	  int code;
deba@127
   275
	  if (!isOct(c)) 
deba@127
   276
	    throw DataFormatError("Escape format error");
deba@127
   277
	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
deba@127
   278
	    is.putback(c);
deba@127
   279
	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
deba@127
   280
	    is.putback(c);
deba@127
   281
	  else code = code * 8 + valueOct(c);
deba@127
   282
	  return code;
deba@127
   283
	}	      
deba@127
   284
      } 
deba@127
   285
    }
deba@127
   286
    
deba@127
   287
    std::istream& readToken(std::istream& is, std::string& str) {
deba@127
   288
      std::ostringstream os;
deba@127
   289
deba@127
   290
      char c;
deba@127
   291
      is >> std::ws;
deba@127
   292
      
deba@127
   293
      if (!is.get(c)) 
deba@127
   294
	return is;
deba@127
   295
deba@127
   296
      if (c == '\"') {
deba@127
   297
	while (is.get(c) && c != '\"') {
deba@127
   298
	  if (c == '\\') 
deba@127
   299
	    c = readEscape(is);
deba@127
   300
	  os << c;
deba@127
   301
	}
deba@127
   302
	if (!is) 
deba@127
   303
	  throw DataFormatError("Quoted format error");
deba@127
   304
      } else {
deba@127
   305
	is.putback(c);
deba@127
   306
	while (is.get(c) && !isWhiteSpace(c)) {
deba@127
   307
	  if (c == '\\') 
deba@127
   308
	    c = readEscape(is);
deba@127
   309
	  os << c;
deba@127
   310
	}
deba@127
   311
	if (!is) {
deba@127
   312
	  is.clear();
deba@127
   313
	} else {
deba@127
   314
	  is.putback(c);
deba@127
   315
	}
deba@127
   316
      }
deba@127
   317
      str = os.str();
deba@127
   318
      return is;
deba@127
   319
    }
deba@162
   320
deba@162
   321
    class Section {
deba@162
   322
    public:
deba@162
   323
      virtual ~Section() {}
deba@162
   324
      virtual void process(std::istream& is, int& line_num) = 0;
deba@162
   325
    };
deba@162
   326
deba@162
   327
    template <typename Functor>
deba@162
   328
    class LineSection : public Section {
deba@162
   329
    private:
deba@162
   330
deba@162
   331
      Functor _functor;
deba@162
   332
deba@162
   333
    public:
deba@162
   334
      
deba@162
   335
      LineSection(const Functor& functor) : _functor(functor) {}
deba@162
   336
      virtual ~LineSection() {}
deba@162
   337
deba@162
   338
      virtual void process(std::istream& is, int& line_num) {
deba@162
   339
	char c;
deba@162
   340
	std::string line;
deba@162
   341
	while (is.get(c) && c != '@') {
deba@162
   342
	  if (c == '\n') {
deba@162
   343
	    ++line_num;
deba@162
   344
	  } else if (c == '#') {
deba@162
   345
	    getline(is, line);
deba@162
   346
	    ++line_num;
deba@162
   347
	  } else if (!isWhiteSpace(c)) {
deba@162
   348
	    is.putback(c);
deba@162
   349
	    getline(is, line);
deba@162
   350
	    _functor(line);
deba@162
   351
	    ++line_num;
deba@162
   352
	  }
deba@162
   353
	}
deba@162
   354
	if (is) is.putback(c);
deba@162
   355
	else if (is.eof()) is.clear();
deba@162
   356
      }
deba@162
   357
    };
deba@162
   358
deba@162
   359
    template <typename Functor>
deba@162
   360
    class StreamSection : public Section {
deba@162
   361
    private:
deba@162
   362
deba@162
   363
      Functor _functor;
deba@162
   364
deba@162
   365
    public:
deba@162
   366
      
deba@162
   367
      StreamSection(const Functor& functor) : _functor(functor) {}
deba@162
   368
      virtual ~StreamSection() {} 
deba@162
   369
deba@162
   370
      virtual void process(std::istream& is, int& line_num) {
deba@162
   371
	_functor(is, line_num);
deba@162
   372
	char c;
deba@162
   373
	std::string line;
deba@162
   374
	while (is.get(c) && c != '@') {
deba@162
   375
	  if (c == '\n') {
deba@162
   376
	    ++line_num;
deba@162
   377
	  } else if (!isWhiteSpace(c)) {
deba@162
   378
	    getline(is, line);
deba@162
   379
	    ++line_num;
deba@162
   380
	  }
deba@162
   381
	}
deba@162
   382
	if (is) is.putback(c);
deba@162
   383
	else if (is.eof()) is.clear();	
deba@162
   384
      }
deba@162
   385
    };
deba@127
   386
    
deba@127
   387
  }
alpar@156
   388
alpar@156
   389
  /// \ingroup lemon_io
alpar@156
   390
  ///  
alpar@156
   391
  /// \brief LGF reader for directed graphs
alpar@156
   392
  ///
alpar@156
   393
  /// This utility reads an \ref lgf-format "LGF" file.
alpar@156
   394
  ///
alpar@156
   395
  /// The reading method does a batch processing. The user creates a
alpar@156
   396
  /// reader object, then various reading rules can be added to the
alpar@156
   397
  /// reader, and eventually the reading is executed with the \c run()
alpar@156
   398
  /// member function. A map reading rule can be added to the reader
alpar@156
   399
  /// with the \c nodeMap() or \c arcMap() members. An optional
deba@162
   400
  /// converter parameter can also be added as a standard functor
deba@162
   401
  /// converting from std::string to the value type of the map. If it
deba@162
   402
  /// is set, it will determine how the tokens in the file should be
deba@162
   403
  /// is converted to the map's value type. If the functor is not set,
deba@162
   404
  /// then a default conversion will be used. One map can be read into
deba@162
   405
  /// multiple map objects at the same time. The \c attribute(), \c
deba@162
   406
  /// node() and \c arc() functions are used to add attribute reading
deba@162
   407
  /// rules.
alpar@156
   408
  ///
alpar@156
   409
  ///\code
alpar@156
   410
  ///     DigraphReader<Digraph>(std::cin, digraph).
alpar@156
   411
  ///       nodeMap("coordinates", coord_map).
alpar@156
   412
  ///       arcMap("capacity", cap_map).
alpar@156
   413
  ///       node("source", src).
alpar@156
   414
  ///       node("target", trg).
alpar@156
   415
  ///       attribute("caption", caption).
alpar@156
   416
  ///       run();
alpar@156
   417
  ///\endcode
alpar@156
   418
  ///
alpar@156
   419
  /// By default the reader uses the first section in the file of the
alpar@156
   420
  /// proper type. If a section has an optional name, then it can be
deba@162
   421
  /// selected for reading by giving an optional name parameter to the
deba@189
   422
  /// \c nodes(), \c arcs() or \c attributes() functions.
alpar@156
   423
  ///
alpar@156
   424
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
alpar@156
   425
  /// that the nodes or arcs should not be constructed (added to the
alpar@156
   426
  /// graph) during the reading, but instead the label map of the items
alpar@156
   427
  /// are given as a parameter of these functions. An
alpar@156
   428
  /// application of these function is multipass reading, which is
alpar@156
   429
  /// important if two \e \@arcs sections must be read from the
alpar@156
   430
  /// file. In this example the first phase would read the node set and one
alpar@156
   431
  /// of the arc sets, while the second phase would read the second arc
alpar@156
   432
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
alpar@156
   433
  /// The previously read label node map should be passed to the \c
alpar@156
   434
  /// useNodes() functions. Another application of multipass reading when
alpar@156
   435
  /// paths are given as a node map or an arc map. It is impossible read this in
alpar@156
   436
  /// a single pass, because the arcs are not constructed when the node
alpar@156
   437
  /// maps are read.
deba@127
   438
  template <typename _Digraph>
deba@127
   439
  class DigraphReader {
deba@127
   440
  public:
deba@127
   441
deba@127
   442
    typedef _Digraph Digraph;
deba@148
   443
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
deba@127
   444
    
deba@127
   445
  private:
deba@127
   446
deba@127
   447
deba@127
   448
    std::istream* _is;
deba@127
   449
    bool local_is;
deba@127
   450
deba@127
   451
    Digraph& _digraph;
deba@127
   452
deba@127
   453
    std::string _nodes_caption;
deba@127
   454
    std::string _arcs_caption;
deba@127
   455
    std::string _attributes_caption;
deba@127
   456
deba@127
   457
    typedef std::map<std::string, Node> NodeIndex;
deba@127
   458
    NodeIndex _node_index;
deba@127
   459
    typedef std::map<std::string, Arc> ArcIndex;
deba@127
   460
    ArcIndex _arc_index;
deba@127
   461
    
deba@127
   462
    typedef std::vector<std::pair<std::string, 
deba@127
   463
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
deba@127
   464
    NodeMaps _node_maps; 
deba@127
   465
deba@127
   466
    typedef std::vector<std::pair<std::string,
deba@127
   467
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
deba@127
   468
    ArcMaps _arc_maps;
deba@127
   469
deba@127
   470
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
deba@127
   471
      Attributes;
deba@127
   472
    Attributes _attributes;
deba@127
   473
deba@127
   474
    bool _use_nodes;
deba@127
   475
    bool _use_arcs;
deba@127
   476
deba@188
   477
    bool _skip_nodes;
deba@188
   478
    bool _skip_arcs;
deba@188
   479
deba@127
   480
    int line_num;
deba@127
   481
    std::istringstream line;
deba@127
   482
deba@127
   483
  public:
deba@127
   484
alpar@156
   485
    /// \brief Constructor
alpar@156
   486
    ///
alpar@156
   487
    /// Construct a directed graph reader, which reads from the given
alpar@156
   488
    /// input stream.
deba@127
   489
    DigraphReader(std::istream& is, Digraph& digraph) 
deba@127
   490
      : _is(&is), local_is(false), _digraph(digraph),
deba@188
   491
	_use_nodes(false), _use_arcs(false),
deba@188
   492
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   493
alpar@156
   494
    /// \brief Constructor
alpar@156
   495
    ///
alpar@156
   496
    /// Construct a directed graph reader, which reads from the given
alpar@156
   497
    /// file.
deba@127
   498
    DigraphReader(const std::string& fn, Digraph& digraph) 
deba@127
   499
      : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
deba@188
   500
    	_use_nodes(false), _use_arcs(false),
deba@188
   501
	_skip_nodes(false), _skip_arcs(false) {}
alpar@156
   502
    
alpar@156
   503
    /// \brief Constructor
alpar@156
   504
    ///
alpar@156
   505
    /// Construct a directed graph reader, which reads from the given
alpar@156
   506
    /// file.
deba@127
   507
    DigraphReader(const char* fn, Digraph& digraph) 
deba@127
   508
      : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
deba@188
   509
    	_use_nodes(false), _use_arcs(false),
deba@188
   510
	_skip_nodes(false), _skip_arcs(false) {}
deba@127
   511
alpar@156
   512
    /// \brief Copy constructor
alpar@156
   513
    ///
alpar@156
   514
    /// The copy constructor transfers all data from the other reader,
alpar@156
   515
    /// therefore the copied reader will not be usable more. 
deba@127
   516
    DigraphReader(DigraphReader& other) 
deba@127
   517
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
deba@188
   518
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
deba@188
   519
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
deba@127
   520
deba@163
   521
      other._is = 0;
deba@127
   522
      other.local_is = false;
deba@127
   523
      
deba@127
   524
      _node_index.swap(other._node_index);
deba@127
   525
      _arc_index.swap(other._arc_index);
deba@127
   526
deba@127
   527
      _node_maps.swap(other._node_maps);
deba@127
   528
      _arc_maps.swap(other._arc_maps);
deba@127
   529
      _attributes.swap(other._attributes);
deba@127
   530
deba@127
   531
      _nodes_caption = other._nodes_caption;
deba@127
   532
      _arcs_caption = other._arcs_caption;
deba@127
   533
      _attributes_caption = other._attributes_caption;
deba@162
   534
deba@127
   535
    }
deba@127
   536
alpar@156
   537
    /// \brief Destructor
deba@127
   538
    ~DigraphReader() {
deba@127
   539
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
deba@127
   540
	   it != _node_maps.end(); ++it) {
deba@127
   541
	delete it->second;
deba@127
   542
      }
deba@127
   543
deba@127
   544
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
deba@127
   545
	   it != _arc_maps.end(); ++it) {
deba@127
   546
	delete it->second;
deba@127
   547
      }
deba@127
   548
deba@127
   549
      for (typename Attributes::iterator it = _attributes.begin(); 
deba@127
   550
	   it != _attributes.end(); ++it) {
deba@127
   551
	delete it->second;
deba@127
   552
      }
deba@127
   553
deba@127
   554
      if (local_is) {
deba@127
   555
	delete _is;
deba@127
   556
      }
deba@127
   557
deba@127
   558
    }
deba@127
   559
deba@127
   560
  private:
deba@127
   561
    
deba@127
   562
    DigraphReader& operator=(const DigraphReader&);
deba@127
   563
deba@127
   564
  public:
deba@127
   565
alpar@156
   566
    /// \name Reading rules
alpar@156
   567
    /// @{
alpar@156
   568
    
alpar@156
   569
    /// \brief Node map reading rule
alpar@156
   570
    ///
alpar@156
   571
    /// Add a node map reading rule to the reader.
deba@127
   572
    template <typename Map>
deba@127
   573
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
deba@127
   574
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@127
   575
      _reader_bits::MapStorageBase<Node>* storage = 
deba@127
   576
	new _reader_bits::MapStorage<Node, Map>(map);
deba@127
   577
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   578
      return *this;
deba@127
   579
    }
deba@127
   580
alpar@156
   581
    /// \brief Node map reading rule
alpar@156
   582
    ///
alpar@156
   583
    /// Add a node map reading rule with specialized converter to the
alpar@156
   584
    /// reader.
deba@127
   585
    template <typename Map, typename Converter>
deba@127
   586
    DigraphReader& nodeMap(const std::string& caption, Map& map, 
deba@127
   587
			   const Converter& converter = Converter()) {
deba@127
   588
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@127
   589
      _reader_bits::MapStorageBase<Node>* storage = 
deba@127
   590
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   591
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   592
      return *this;
deba@127
   593
    }
deba@127
   594
alpar@156
   595
    /// \brief Arc map reading rule
alpar@156
   596
    ///
alpar@156
   597
    /// Add an arc map reading rule to the reader.
deba@127
   598
    template <typename Map>
deba@127
   599
    DigraphReader& arcMap(const std::string& caption, Map& map) {
deba@127
   600
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
deba@127
   601
      _reader_bits::MapStorageBase<Arc>* storage = 
deba@127
   602
	new _reader_bits::MapStorage<Arc, Map>(map);
deba@127
   603
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   604
      return *this;
deba@127
   605
    }
deba@127
   606
alpar@156
   607
    /// \brief Arc map reading rule
alpar@156
   608
    ///
alpar@156
   609
    /// Add an arc map reading rule with specialized converter to the
alpar@156
   610
    /// reader.
deba@127
   611
    template <typename Map, typename Converter>
deba@127
   612
    DigraphReader& arcMap(const std::string& caption, Map& map, 
deba@127
   613
			  const Converter& converter = Converter()) {
deba@127
   614
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
deba@127
   615
      _reader_bits::MapStorageBase<Arc>* storage = 
deba@127
   616
	new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   617
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   618
      return *this;
deba@127
   619
    }
deba@127
   620
alpar@156
   621
    /// \brief Attribute reading rule
alpar@156
   622
    ///
alpar@156
   623
    /// Add an attribute reading rule to the reader.
deba@127
   624
    template <typename Value>
deba@127
   625
    DigraphReader& attribute(const std::string& caption, Value& value) {
deba@127
   626
      _reader_bits::ValueStorageBase* storage = 
deba@127
   627
	new _reader_bits::ValueStorage<Value>(value);
deba@127
   628
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   629
      return *this;
deba@127
   630
    }
deba@127
   631
alpar@156
   632
    /// \brief Attribute reading rule
alpar@156
   633
    ///
alpar@156
   634
    /// Add an attribute reading rule with specialized converter to the
alpar@156
   635
    /// reader.
deba@127
   636
    template <typename Value, typename Converter>
deba@127
   637
    DigraphReader& attribute(const std::string& caption, Value& value, 
deba@127
   638
			     const Converter& converter = Converter()) {
deba@127
   639
      _reader_bits::ValueStorageBase* storage = 
deba@127
   640
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   641
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   642
      return *this;
deba@127
   643
    }
deba@127
   644
alpar@156
   645
    /// \brief Node reading rule
alpar@156
   646
    ///
alpar@156
   647
    /// Add a node reading rule to reader.
deba@127
   648
    DigraphReader& node(const std::string& caption, Node& node) {
deba@127
   649
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
deba@127
   650
      Converter converter(_node_index);
deba@127
   651
      _reader_bits::ValueStorageBase* storage = 
deba@127
   652
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   653
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   654
      return *this;
deba@127
   655
    }
deba@127
   656
alpar@156
   657
    /// \brief Arc reading rule
alpar@156
   658
    ///
alpar@156
   659
    /// Add an arc reading rule to reader.
deba@127
   660
    DigraphReader& arc(const std::string& caption, Arc& arc) {
deba@127
   661
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
deba@127
   662
      Converter converter(_arc_index);
deba@127
   663
      _reader_bits::ValueStorageBase* storage = 
deba@127
   664
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   665
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   666
      return *this;
deba@127
   667
    }
deba@127
   668
alpar@156
   669
    /// @}
alpar@156
   670
alpar@156
   671
    /// \name Select section by name
alpar@156
   672
    /// @{
alpar@156
   673
alpar@156
   674
    /// \brief Set \c \@nodes section to be read
alpar@156
   675
    ///
alpar@156
   676
    /// Set \c \@nodes section to be read
deba@127
   677
    DigraphReader& nodes(const std::string& caption) {
deba@127
   678
      _nodes_caption = caption;
deba@127
   679
      return *this;
deba@127
   680
    }
deba@127
   681
alpar@156
   682
    /// \brief Set \c \@arcs section to be read
alpar@156
   683
    ///
alpar@156
   684
    /// Set \c \@arcs section to be read
deba@127
   685
    DigraphReader& arcs(const std::string& caption) {
deba@127
   686
      _arcs_caption = caption;
deba@127
   687
      return *this;
deba@127
   688
    }
deba@127
   689
alpar@156
   690
    /// \brief Set \c \@attributes section to be read
alpar@156
   691
    ///
alpar@156
   692
    /// Set \c \@attributes section to be read
deba@127
   693
    DigraphReader& attributes(const std::string& caption) {
deba@127
   694
      _attributes_caption = caption;
deba@127
   695
      return *this;
deba@127
   696
    }
deba@127
   697
alpar@156
   698
    /// @}
alpar@156
   699
alpar@156
   700
    /// \name Using previously constructed node or arc set
alpar@156
   701
    /// @{
alpar@156
   702
alpar@156
   703
    /// \brief Use previously constructed node set
alpar@156
   704
    ///
alpar@156
   705
    /// Use previously constructed node set, and specify the node
alpar@156
   706
    /// label map.
deba@127
   707
    template <typename Map>
deba@127
   708
    DigraphReader& useNodes(const Map& map) {
deba@127
   709
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   710
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
deba@127
   711
      _use_nodes = true;
deba@127
   712
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@127
   713
      for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@127
   714
	_node_index.insert(std::make_pair(converter(map[n]), n));
deba@127
   715
      }
deba@127
   716
      return *this;
deba@127
   717
    }
deba@127
   718
alpar@156
   719
    /// \brief Use previously constructed node set
alpar@156
   720
    ///
alpar@156
   721
    /// Use previously constructed node set, and specify the node
alpar@156
   722
    /// label map and a functor which converts the label map values to
alpar@156
   723
    /// std::string.
deba@127
   724
    template <typename Map, typename Converter>
deba@127
   725
    DigraphReader& useNodes(const Map& map, 
deba@127
   726
			    const Converter& converter = Converter()) {
deba@127
   727
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   728
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
deba@127
   729
      _use_nodes = true;
deba@127
   730
      for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@127
   731
	_node_index.insert(std::make_pair(converter(map[n]), n));
deba@127
   732
      }
deba@127
   733
      return *this;
deba@127
   734
    }
deba@127
   735
alpar@156
   736
    /// \brief Use previously constructed arc set
alpar@156
   737
    ///
alpar@156
   738
    /// Use previously constructed arc set, and specify the arc
alpar@156
   739
    /// label map.
deba@127
   740
    template <typename Map>
deba@127
   741
    DigraphReader& useArcs(const Map& map) {
deba@127
   742
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   743
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
deba@127
   744
      _use_arcs = true;
deba@127
   745
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@127
   746
      for (ArcIt a(_digraph); a != INVALID; ++a) {
deba@127
   747
	_arc_index.insert(std::make_pair(converter(map[a]), a));
deba@127
   748
      }
deba@127
   749
      return *this;
deba@127
   750
    }
deba@127
   751
alpar@156
   752
    /// \brief Use previously constructed arc set
alpar@156
   753
    ///
alpar@156
   754
    /// Use previously constructed arc set, and specify the arc
alpar@156
   755
    /// label map and a functor which converts the label map values to
alpar@156
   756
    /// std::string.
deba@127
   757
    template <typename Map, typename Converter>
deba@127
   758
    DigraphReader& useArcs(const Map& map, 
deba@188
   759
			   const Converter& converter = Converter()) {
deba@127
   760
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   761
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); 
deba@127
   762
      _use_arcs = true;
deba@127
   763
      for (ArcIt a(_digraph); a != INVALID; ++a) {
deba@127
   764
	_arc_index.insert(std::make_pair(converter(map[a]), a));
deba@127
   765
      }
deba@127
   766
      return *this;
deba@127
   767
    }
deba@127
   768
deba@188
   769
    /// \brief Skips the reading of node section
deba@188
   770
    ///
deba@188
   771
    /// Omit the reading of the node section. This implies that each node
deba@188
   772
    /// map reading rule will be abanoned, and the nodes of the graph
deba@188
   773
    /// will not be constructed, which usually cause that the arc set
deba@188
   774
    /// could not be read due to lack of node name
deba@188
   775
    /// resolving. Therefore, the \c skipArcs() should be used too, or
deba@188
   776
    /// the useNodes() member function should be used to specify the
deba@188
   777
    /// label of the nodes.
deba@188
   778
    DigraphReader& skipNodes() {
deba@188
   779
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); 
deba@188
   780
      _skip_nodes = true;
deba@188
   781
      return *this;
deba@188
   782
    }
deba@188
   783
deba@188
   784
    /// \brief Skips the reading of arc section
deba@188
   785
    ///
deba@188
   786
    /// Omit the reading of the arc section. This implies that each arc
deba@188
   787
    /// map reading rule will be abanoned, and the arcs of the graph
deba@188
   788
    /// will not be constructed.
deba@188
   789
    DigraphReader& skipArcs() {
deba@188
   790
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set"); 
deba@188
   791
      _skip_arcs = true;
deba@188
   792
      return *this;
deba@188
   793
    }
deba@188
   794
alpar@156
   795
    /// @}
alpar@156
   796
deba@127
   797
  private:
deba@127
   798
deba@127
   799
    bool readLine() {
deba@127
   800
      std::string str;
deba@127
   801
      while(++line_num, std::getline(*_is, str)) {
deba@127
   802
	line.clear(); line.str(str);
deba@127
   803
	char c;
deba@127
   804
	if (line >> std::ws >> c && c != '#') {
deba@127
   805
	  line.putback(c);
deba@127
   806
	  return true;
deba@127
   807
	}
deba@127
   808
      }
deba@127
   809
      return false;
deba@127
   810
    }
deba@127
   811
deba@127
   812
    bool readSuccess() {
deba@127
   813
      return static_cast<bool>(*_is);
deba@127
   814
    }
deba@127
   815
    
deba@127
   816
    void skipSection() {
deba@127
   817
      char c;
deba@127
   818
      while (readSuccess() && line >> c && c != '@') {
deba@127
   819
	readLine();
deba@127
   820
      }
deba@127
   821
      line.putback(c);
deba@127
   822
    }
deba@127
   823
deba@127
   824
    void readNodes() {
deba@127
   825
deba@127
   826
      std::vector<int> map_index(_node_maps.size());
deba@127
   827
      int map_num, label_index;
deba@127
   828
deba@186
   829
      char c;
deba@186
   830
      if (!readLine() || !(line >> c) || c == '@') {
deba@186
   831
	if (readSuccess() && line) line.putback(c);
deba@186
   832
	if (!_node_maps.empty()) 
deba@186
   833
	  throw DataFormatError("Cannot find map names");
deba@186
   834
	return;
deba@186
   835
      }
deba@186
   836
      line.putback(c);
deba@186
   837
deba@127
   838
      {
deba@127
   839
	std::map<std::string, int> maps;
deba@127
   840
	
deba@127
   841
	std::string map;
deba@127
   842
	int index = 0;
alpar@156
   843
	while (_reader_bits::readToken(line, map)) {
deba@127
   844
	  if (maps.find(map) != maps.end()) {
deba@127
   845
	    std::ostringstream msg;
deba@127
   846
	    msg << "Multiple occurence of node map: " << map;
deba@127
   847
	    throw DataFormatError(msg.str().c_str());
deba@127
   848
	  }
deba@127
   849
	  maps.insert(std::make_pair(map, index));
deba@127
   850
	  ++index;
deba@127
   851
	}
deba@127
   852
	
deba@127
   853
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
deba@127
   854
	  std::map<std::string, int>::iterator jt = 
deba@127
   855
	    maps.find(_node_maps[i].first);
deba@127
   856
	  if (jt == maps.end()) {
deba@127
   857
	    std::ostringstream msg;
deba@127
   858
	    msg << "Map not found in file: " << _node_maps[i].first;
deba@127
   859
	    throw DataFormatError(msg.str().c_str());
deba@127
   860
	  }
deba@127
   861
	  map_index[i] = jt->second;
deba@127
   862
	}
deba@127
   863
deba@127
   864
	{
deba@127
   865
	  std::map<std::string, int>::iterator jt = maps.find("label");
deba@186
   866
	  if (jt != maps.end()) {
deba@186
   867
	    label_index = jt->second;
deba@186
   868
	  } else {
deba@186
   869
	    label_index = -1;
deba@186
   870
	  }
deba@127
   871
	}
deba@127
   872
	map_num = maps.size();
deba@127
   873
      }
deba@127
   874
deba@127
   875
      while (readLine() && line >> c && c != '@') {
deba@127
   876
	line.putback(c);
deba@127
   877
deba@127
   878
	std::vector<std::string> tokens(map_num);
deba@127
   879
	for (int i = 0; i < map_num; ++i) {
deba@127
   880
	  if (!_reader_bits::readToken(line, tokens[i])) {
deba@127
   881
	    std::ostringstream msg;
deba@127
   882
	    msg << "Column not found (" << i + 1 << ")";
deba@127
   883
	    throw DataFormatError(msg.str().c_str());
deba@127
   884
	  }
deba@127
   885
	}
deba@127
   886
	if (line >> std::ws >> c)
deba@127
   887
	  throw DataFormatError("Extra character on the end of line");
deba@127
   888
	
deba@127
   889
	Node n;
deba@127
   890
	if (!_use_nodes) {
deba@127
   891
	  n = _digraph.addNode();
deba@186
   892
	  if (label_index != -1)
deba@186
   893
	    _node_index.insert(std::make_pair(tokens[label_index], n));
deba@127
   894
	} else {
deba@186
   895
	  if (label_index == -1) 
deba@186
   896
	    throw DataFormatError("Label map not found in file");
deba@127
   897
	  typename std::map<std::string, Node>::iterator it =
deba@127
   898
	    _node_index.find(tokens[label_index]);
deba@127
   899
	  if (it == _node_index.end()) {
deba@127
   900
	    std::ostringstream msg;
deba@127
   901
	    msg << "Node with label not found: " << tokens[label_index];
deba@127
   902
	    throw DataFormatError(msg.str().c_str());	    
deba@127
   903
	  }
deba@127
   904
	  n = it->second;
deba@127
   905
	}
deba@127
   906
deba@127
   907
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
deba@127
   908
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
deba@127
   909
	}
deba@127
   910
deba@127
   911
      }
deba@127
   912
      if (readSuccess()) {
deba@127
   913
	line.putback(c);
deba@127
   914
      }
deba@127
   915
    }
deba@127
   916
deba@127
   917
    void readArcs() {
deba@127
   918
deba@127
   919
      std::vector<int> map_index(_arc_maps.size());
deba@127
   920
      int map_num, label_index;
deba@127
   921
deba@186
   922
      char c;
deba@186
   923
      if (!readLine() || !(line >> c) || c == '@') {
deba@186
   924
	if (readSuccess() && line) line.putback(c);
deba@186
   925
	if (!_arc_maps.empty()) 
deba@186
   926
	  throw DataFormatError("Cannot find map names");
deba@186
   927
	return;
deba@186
   928
      }
deba@186
   929
      line.putback(c);
deba@127
   930
      
deba@127
   931
      {
deba@127
   932
	std::map<std::string, int> maps;
deba@127
   933
	
deba@127
   934
	std::string map;
deba@127
   935
	int index = 0;
alpar@156
   936
	while (_reader_bits::readToken(line, map)) {
deba@127
   937
	  if (maps.find(map) != maps.end()) {
deba@127
   938
	    std::ostringstream msg;
deba@127
   939
	    msg << "Multiple occurence of arc map: " << map;
deba@127
   940
	    throw DataFormatError(msg.str().c_str());
deba@127
   941
	  }
deba@127
   942
	  maps.insert(std::make_pair(map, index));
deba@127
   943
	  ++index;
deba@127
   944
	}
deba@127
   945
	
deba@127
   946
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
deba@127
   947
	  std::map<std::string, int>::iterator jt = 
deba@127
   948
	    maps.find(_arc_maps[i].first);
deba@127
   949
	  if (jt == maps.end()) {
deba@127
   950
	    std::ostringstream msg;
deba@127
   951
	    msg << "Map not found in file: " << _arc_maps[i].first;
deba@127
   952
	    throw DataFormatError(msg.str().c_str());
deba@127
   953
	  }
deba@127
   954
	  map_index[i] = jt->second;
deba@127
   955
	}
deba@127
   956
deba@127
   957
	{
deba@127
   958
	  std::map<std::string, int>::iterator jt = maps.find("label");
deba@186
   959
	  if (jt != maps.end()) {
deba@186
   960
	    label_index = jt->second;
deba@186
   961
	  } else {
deba@186
   962
	    label_index = -1;
deba@186
   963
	  }
deba@127
   964
	}
deba@127
   965
	map_num = maps.size();
deba@127
   966
      }
deba@127
   967
deba@127
   968
      while (readLine() && line >> c && c != '@') {
deba@127
   969
	line.putback(c);
deba@127
   970
deba@127
   971
	std::string source_token;
deba@127
   972
	std::string target_token;
deba@127
   973
deba@127
   974
	if (!_reader_bits::readToken(line, source_token))
deba@127
   975
	  throw DataFormatError("Source not found");
deba@127
   976
deba@127
   977
	if (!_reader_bits::readToken(line, target_token))
deba@186
   978
	  throw DataFormatError("Target not found");
deba@127
   979
	
deba@127
   980
	std::vector<std::string> tokens(map_num);
deba@127
   981
	for (int i = 0; i < map_num; ++i) {
deba@127
   982
	  if (!_reader_bits::readToken(line, tokens[i])) {
deba@127
   983
	    std::ostringstream msg;
deba@127
   984
	    msg << "Column not found (" << i + 1 << ")";
deba@127
   985
	    throw DataFormatError(msg.str().c_str());
deba@127
   986
	  }
deba@127
   987
	}
deba@127
   988
	if (line >> std::ws >> c)
deba@127
   989
	  throw DataFormatError("Extra character on the end of line");
deba@127
   990
	
deba@127
   991
	Arc a;
deba@127
   992
	if (!_use_arcs) {
deba@127
   993
deba@127
   994
          typename NodeIndex::iterator it;
deba@127
   995
 
deba@127
   996
          it = _node_index.find(source_token);
deba@127
   997
          if (it == _node_index.end()) {
deba@127
   998
            std::ostringstream msg;
deba@127
   999
            msg << "Item not found: " << source_token;
deba@127
  1000
            throw DataFormatError(msg.str().c_str());
deba@127
  1001
          }
deba@127
  1002
          Node source = it->second;
deba@127
  1003
deba@127
  1004
          it = _node_index.find(target_token);
deba@127
  1005
          if (it == _node_index.end()) {       
deba@127
  1006
            std::ostringstream msg;            
deba@127
  1007
            msg << "Item not found: " << target_token;
deba@127
  1008
            throw DataFormatError(msg.str().c_str());
deba@127
  1009
          }                                          
deba@127
  1010
          Node target = it->second;                            
deba@127
  1011
deba@127
  1012
	  a = _digraph.addArc(source, target);
deba@186
  1013
	  if (label_index != -1) 
deba@186
  1014
	    _arc_index.insert(std::make_pair(tokens[label_index], a));
deba@127
  1015
	} else {
deba@186
  1016
	  if (label_index == -1) 
deba@186
  1017
	    throw DataFormatError("Label map not found in file");
deba@127
  1018
	  typename std::map<std::string, Arc>::iterator it =
deba@127
  1019
	    _arc_index.find(tokens[label_index]);
deba@127
  1020
	  if (it == _arc_index.end()) {
deba@127
  1021
	    std::ostringstream msg;
deba@127
  1022
	    msg << "Arc with label not found: " << tokens[label_index];
deba@127
  1023
	    throw DataFormatError(msg.str().c_str());	    
deba@127
  1024
	  }
deba@127
  1025
	  a = it->second;
deba@127
  1026
	}
deba@127
  1027
deba@127
  1028
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
deba@127
  1029
	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
deba@127
  1030
	}
deba@127
  1031
deba@127
  1032
      }
deba@127
  1033
      if (readSuccess()) {
deba@127
  1034
	line.putback(c);
deba@127
  1035
      }
deba@127
  1036
    }
deba@127
  1037
deba@127
  1038
    void readAttributes() {
deba@127
  1039
deba@127
  1040
      std::set<std::string> read_attr;
deba@127
  1041
deba@127
  1042
      char c;
deba@127
  1043
      while (readLine() && line >> c && c != '@') {
deba@127
  1044
	line.putback(c);
deba@127
  1045
	
deba@127
  1046
	std::string attr, token;
alpar@156
  1047
	if (!_reader_bits::readToken(line, attr))
deba@127
  1048
	  throw DataFormatError("Attribute name not found");
deba@127
  1049
	if (!_reader_bits::readToken(line, token))
deba@127
  1050
	  throw DataFormatError("Attribute value not found");
deba@127
  1051
	if (line >> c)
deba@127
  1052
	  throw DataFormatError("Extra character on the end of line");	  
deba@127
  1053
deba@127
  1054
	{
deba@127
  1055
	  std::set<std::string>::iterator it = read_attr.find(attr);
deba@127
  1056
	  if (it != read_attr.end()) {
deba@127
  1057
	    std::ostringstream msg;
deba@127
  1058
	    msg << "Multiple occurence of attribute " << attr;
deba@127
  1059
	    throw DataFormatError(msg.str().c_str());
deba@127
  1060
	  }
deba@127
  1061
	  read_attr.insert(attr);
deba@127
  1062
	}
deba@127
  1063
	
deba@127
  1064
	{
deba@127
  1065
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
deba@127
  1066
	  while (it != _attributes.end() && it->first == attr) {
deba@127
  1067
	    it->second->set(token);
deba@127
  1068
	    ++it;
deba@127
  1069
	  }
deba@127
  1070
	}
deba@127
  1071
deba@127
  1072
      }
deba@127
  1073
      if (readSuccess()) {
deba@127
  1074
	line.putback(c);
deba@127
  1075
      }
deba@127
  1076
      for (typename Attributes::iterator it = _attributes.begin();
deba@127
  1077
	   it != _attributes.end(); ++it) {
deba@127
  1078
	if (read_attr.find(it->first) == read_attr.end()) {
deba@127
  1079
	  std::ostringstream msg;
deba@127
  1080
	  msg << "Attribute not found in file: " << it->first;
deba@127
  1081
	  throw DataFormatError(msg.str().c_str());
deba@127
  1082
	}	
deba@127
  1083
      }
deba@127
  1084
    }
deba@127
  1085
deba@127
  1086
  public:
alpar@156
  1087
alpar@156
  1088
    /// \name Execution of the reader    
alpar@156
  1089
    /// @{
alpar@156
  1090
alpar@156
  1091
    /// \brief Start the batch processing
alpar@156
  1092
    ///
alpar@156
  1093
    /// This function starts the batch processing
deba@127
  1094
    void run() {
deba@127
  1095
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
deba@163
  1096
      if (!*_is) {
deba@163
  1097
	throw DataFormatError("Cannot find file");
deba@163
  1098
      }
deba@127
  1099
      
deba@188
  1100
      bool nodes_done = _skip_nodes;
deba@188
  1101
      bool arcs_done = _skip_arcs;
deba@127
  1102
      bool attributes_done = false;
deba@127
  1103
deba@127
  1104
      line_num = 0;      
deba@127
  1105
      readLine();
deba@172
  1106
      skipSection();
deba@127
  1107
deba@127
  1108
      while (readSuccess()) {
deba@127
  1109
	try {
deba@127
  1110
	  char c;
deba@127
  1111
	  std::string section, caption;
deba@127
  1112
	  line >> c;
alpar@156
  1113
	  _reader_bits::readToken(line, section);
alpar@156
  1114
	  _reader_bits::readToken(line, caption);
deba@127
  1115
deba@127
  1116
	  if (line >> c) 
deba@127
  1117
	    throw DataFormatError("Extra character on the end of line");
deba@127
  1118
deba@127
  1119
	  if (section == "nodes" && !nodes_done) {
deba@127
  1120
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
deba@127
  1121
	      readNodes();
deba@127
  1122
	      nodes_done = true;
deba@127
  1123
	    }
deba@127
  1124
	  } else if ((section == "arcs" || section == "edges") && 
deba@127
  1125
		     !arcs_done) {
deba@127
  1126
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
deba@127
  1127
	      readArcs();
deba@127
  1128
	      arcs_done = true;
deba@127
  1129
	    }
deba@127
  1130
	  } else if (section == "attributes" && !attributes_done) {
deba@127
  1131
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
deba@127
  1132
	      readAttributes();
deba@127
  1133
	      attributes_done = true;
deba@127
  1134
	    }
deba@127
  1135
	  } else {
deba@172
  1136
	    readLine();
deba@172
  1137
	    skipSection();
deba@127
  1138
	  }
deba@127
  1139
	} catch (DataFormatError& error) {
deba@127
  1140
	  error.line(line_num);
deba@127
  1141
	  throw;
deba@127
  1142
	}	
deba@127
  1143
      }
deba@127
  1144
deba@127
  1145
      if (!nodes_done) {
deba@127
  1146
	throw DataFormatError("Section @nodes not found");
deba@127
  1147
      }
deba@127
  1148
deba@127
  1149
      if (!arcs_done) {
deba@127
  1150
	throw DataFormatError("Section @arcs not found");
deba@127
  1151
      }
deba@127
  1152
deba@127
  1153
      if (!attributes_done && !_attributes.empty()) {
deba@127
  1154
	throw DataFormatError("Section @attributes not found");
deba@127
  1155
      }
deba@127
  1156
deba@127
  1157
    }
alpar@156
  1158
alpar@156
  1159
    /// @}
deba@127
  1160
    
deba@127
  1161
  };
deba@127
  1162
alpar@156
  1163
  /// \relates DigraphReader
deba@127
  1164
  template <typename Digraph>
deba@127
  1165
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
deba@163
  1166
    DigraphReader<Digraph> tmp(is, digraph);
deba@163
  1167
    return tmp;
deba@127
  1168
  }
deba@127
  1169
alpar@156
  1170
  /// \relates DigraphReader
deba@127
  1171
  template <typename Digraph>
deba@127
  1172
  DigraphReader<Digraph> digraphReader(const std::string& fn, 
deba@127
  1173
				       Digraph& digraph) {
deba@163
  1174
    DigraphReader<Digraph> tmp(fn, digraph);
deba@163
  1175
    return tmp;
deba@127
  1176
  }
deba@127
  1177
alpar@156
  1178
  /// \relates DigraphReader
deba@127
  1179
  template <typename Digraph>
deba@127
  1180
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
deba@163
  1181
    DigraphReader<Digraph> tmp(fn, digraph);
deba@163
  1182
    return tmp;
deba@127
  1183
  }
deba@165
  1184
deba@165
  1185
  /// \ingroup lemon_io
deba@165
  1186
  ///  
deba@165
  1187
  /// \brief LGF reader for undirected graphs
deba@165
  1188
  ///
deba@165
  1189
  /// This utility reads an \ref lgf-format "LGF" file.
deba@165
  1190
  template <typename _Graph>
deba@165
  1191
  class GraphReader {
deba@165
  1192
  public:
deba@165
  1193
deba@165
  1194
    typedef _Graph Graph;
deba@165
  1195
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
deba@165
  1196
    
deba@165
  1197
  private:
deba@165
  1198
deba@165
  1199
    std::istream* _is;
deba@165
  1200
    bool local_is;
deba@165
  1201
deba@165
  1202
    Graph& _graph;
deba@165
  1203
deba@165
  1204
    std::string _nodes_caption;
deba@165
  1205
    std::string _edges_caption;
deba@165
  1206
    std::string _attributes_caption;
deba@165
  1207
deba@165
  1208
    typedef std::map<std::string, Node> NodeIndex;
deba@165
  1209
    NodeIndex _node_index;
deba@165
  1210
    typedef std::map<std::string, Edge> EdgeIndex;
deba@165
  1211
    EdgeIndex _edge_index;
deba@165
  1212
    
deba@165
  1213
    typedef std::vector<std::pair<std::string, 
deba@165
  1214
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
deba@165
  1215
    NodeMaps _node_maps; 
deba@165
  1216
deba@165
  1217
    typedef std::vector<std::pair<std::string,
deba@165
  1218
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
deba@165
  1219
    EdgeMaps _edge_maps;
deba@165
  1220
deba@165
  1221
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
deba@165
  1222
      Attributes;
deba@165
  1223
    Attributes _attributes;
deba@165
  1224
deba@165
  1225
    bool _use_nodes;
deba@165
  1226
    bool _use_edges;
deba@165
  1227
deba@188
  1228
    bool _skip_nodes;
deba@188
  1229
    bool _skip_edges;
deba@188
  1230
deba@165
  1231
    int line_num;
deba@165
  1232
    std::istringstream line;
deba@165
  1233
deba@165
  1234
  public:
deba@165
  1235
deba@165
  1236
    /// \brief Constructor
deba@165
  1237
    ///
deba@165
  1238
    /// Construct a undirected graph reader, which reads from the given
deba@165
  1239
    /// input stream.
deba@165
  1240
    GraphReader(std::istream& is, Graph& graph) 
deba@165
  1241
      : _is(&is), local_is(false), _graph(graph),
deba@188
  1242
	_use_nodes(false), _use_edges(false),
deba@188
  1243
	_skip_nodes(false), _skip_edges(false) {}
deba@165
  1244
deba@165
  1245
    /// \brief Constructor
deba@165
  1246
    ///
deba@165
  1247
    /// Construct a undirected graph reader, which reads from the given
deba@165
  1248
    /// file.
deba@165
  1249
    GraphReader(const std::string& fn, Graph& graph) 
deba@165
  1250
      : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
deba@188
  1251
    	_use_nodes(false), _use_edges(false),
deba@188
  1252
	_skip_nodes(false), _skip_edges(false) {}
deba@165
  1253
    
deba@165
  1254
    /// \brief Constructor
deba@165
  1255
    ///
deba@165
  1256
    /// Construct a undirected graph reader, which reads from the given
deba@165
  1257
    /// file.
deba@165
  1258
    GraphReader(const char* fn, Graph& graph) 
deba@165
  1259
      : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
deba@188
  1260
    	_use_nodes(false), _use_edges(false),
deba@188
  1261
	_skip_nodes(false), _skip_edges(false) {}
deba@165
  1262
deba@165
  1263
    /// \brief Copy constructor
deba@165
  1264
    ///
deba@165
  1265
    /// The copy constructor transfers all data from the other reader,
deba@165
  1266
    /// therefore the copied reader will not be usable more. 
deba@165
  1267
    GraphReader(GraphReader& other) 
deba@165
  1268
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
deba@188
  1269
	_use_nodes(other._use_nodes), _use_edges(other._use_edges),
deba@188
  1270
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@165
  1271
deba@165
  1272
      other._is = 0;
deba@165
  1273
      other.local_is = false;
deba@165
  1274
      
deba@165
  1275
      _node_index.swap(other._node_index);
deba@165
  1276
      _edge_index.swap(other._edge_index);
deba@165
  1277
deba@165
  1278
      _node_maps.swap(other._node_maps);
deba@165
  1279
      _edge_maps.swap(other._edge_maps);
deba@165
  1280
      _attributes.swap(other._attributes);
deba@165
  1281
deba@165
  1282
      _nodes_caption = other._nodes_caption;
deba@165
  1283
      _edges_caption = other._edges_caption;
deba@165
  1284
      _attributes_caption = other._attributes_caption;
deba@165
  1285
deba@165
  1286
    }
deba@165
  1287
deba@165
  1288
    /// \brief Destructor
deba@165
  1289
    ~GraphReader() {
deba@165
  1290
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
deba@165
  1291
	   it != _node_maps.end(); ++it) {
deba@165
  1292
	delete it->second;
deba@165
  1293
      }
deba@165
  1294
deba@165
  1295
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
deba@165
  1296
	   it != _edge_maps.end(); ++it) {
deba@165
  1297
	delete it->second;
deba@165
  1298
      }
deba@165
  1299
deba@165
  1300
      for (typename Attributes::iterator it = _attributes.begin(); 
deba@165
  1301
	   it != _attributes.end(); ++it) {
deba@165
  1302
	delete it->second;
deba@165
  1303
      }
deba@165
  1304
deba@165
  1305
      if (local_is) {
deba@165
  1306
	delete _is;
deba@165
  1307
      }
deba@165
  1308
deba@165
  1309
    }
deba@165
  1310
deba@165
  1311
  private:
deba@165
  1312
    
deba@165
  1313
    GraphReader& operator=(const GraphReader&);
deba@165
  1314
deba@165
  1315
  public:
deba@165
  1316
deba@165
  1317
    /// \name Reading rules
deba@165
  1318
    /// @{
deba@165
  1319
    
deba@165
  1320
    /// \brief Node map reading rule
deba@165
  1321
    ///
deba@165
  1322
    /// Add a node map reading rule to the reader.
deba@165
  1323
    template <typename Map>
deba@165
  1324
    GraphReader& nodeMap(const std::string& caption, Map& map) {
deba@165
  1325
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@165
  1326
      _reader_bits::MapStorageBase<Node>* storage = 
deba@165
  1327
	new _reader_bits::MapStorage<Node, Map>(map);
deba@165
  1328
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1329
      return *this;
deba@165
  1330
    }
deba@165
  1331
deba@165
  1332
    /// \brief Node map reading rule
deba@165
  1333
    ///
deba@165
  1334
    /// Add a node map reading rule with specialized converter to the
deba@165
  1335
    /// reader.
deba@165
  1336
    template <typename Map, typename Converter>
deba@165
  1337
    GraphReader& nodeMap(const std::string& caption, Map& map, 
deba@165
  1338
			   const Converter& converter = Converter()) {
deba@165
  1339
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@165
  1340
      _reader_bits::MapStorageBase<Node>* storage = 
deba@165
  1341
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@165
  1342
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1343
      return *this;
deba@165
  1344
    }
deba@165
  1345
deba@165
  1346
    /// \brief Edge map reading rule
deba@165
  1347
    ///
deba@165
  1348
    /// Add an edge map reading rule to the reader.
deba@165
  1349
    template <typename Map>
deba@165
  1350
    GraphReader& edgeMap(const std::string& caption, Map& map) {
deba@165
  1351
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@165
  1352
      _reader_bits::MapStorageBase<Edge>* storage = 
deba@165
  1353
	new _reader_bits::MapStorage<Edge, Map>(map);
deba@165
  1354
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1355
      return *this;
deba@165
  1356
    }
deba@165
  1357
deba@165
  1358
    /// \brief Edge map reading rule
deba@165
  1359
    ///
deba@165
  1360
    /// Add an edge map reading rule with specialized converter to the
deba@165
  1361
    /// reader.
deba@165
  1362
    template <typename Map, typename Converter>
deba@165
  1363
    GraphReader& edgeMap(const std::string& caption, Map& map, 
deba@165
  1364
			  const Converter& converter = Converter()) {
deba@165
  1365
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
deba@165
  1366
      _reader_bits::MapStorageBase<Edge>* storage = 
deba@165
  1367
	new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@165
  1368
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1369
      return *this;
deba@165
  1370
    }
deba@165
  1371
deba@165
  1372
    /// \brief Arc map reading rule
deba@165
  1373
    ///
deba@165
  1374
    /// Add an arc map reading rule to the reader.
deba@165
  1375
    template <typename Map>
deba@165
  1376
    GraphReader& arcMap(const std::string& caption, Map& map) {
deba@165
  1377
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
deba@165
  1378
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
deba@165
  1379
	new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
deba@165
  1380
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@165
  1381
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
deba@165
  1382
	new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
deba@165
  1383
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1384
      return *this;
deba@165
  1385
    }
deba@165
  1386
deba@165
  1387
    /// \brief Arc map reading rule
deba@165
  1388
    ///
deba@165
  1389
    /// Add an arc map reading rule with specialized converter to the
deba@165
  1390
    /// reader.
deba@165
  1391
    template <typename Map, typename Converter>
deba@165
  1392
    GraphReader& arcMap(const std::string& caption, Map& map, 
deba@165
  1393
			  const Converter& converter = Converter()) {
deba@165
  1394
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
deba@165
  1395
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
deba@165
  1396
	new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
deba@165
  1397
	(_graph, map, converter);
deba@165
  1398
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@165
  1399
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
deba@165
  1400
	new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
deba@165
  1401
	(_graph, map, converter);
deba@165
  1402
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1403
      return *this;
deba@165
  1404
    }
deba@165
  1405
deba@165
  1406
    /// \brief Attribute reading rule
deba@165
  1407
    ///
deba@165
  1408
    /// Add an attribute reading rule to the reader.
deba@165
  1409
    template <typename Value>
deba@165
  1410
    GraphReader& attribute(const std::string& caption, Value& value) {
deba@165
  1411
      _reader_bits::ValueStorageBase* storage = 
deba@165
  1412
	new _reader_bits::ValueStorage<Value>(value);
deba@165
  1413
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1414
      return *this;
deba@165
  1415
    }
deba@165
  1416
deba@165
  1417
    /// \brief Attribute reading rule
deba@165
  1418
    ///
deba@165
  1419
    /// Add an attribute reading rule with specialized converter to the
deba@165
  1420
    /// reader.
deba@165
  1421
    template <typename Value, typename Converter>
deba@165
  1422
    GraphReader& attribute(const std::string& caption, Value& value, 
deba@165
  1423
			     const Converter& converter = Converter()) {
deba@165
  1424
      _reader_bits::ValueStorageBase* storage = 
deba@165
  1425
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
deba@165
  1426
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1427
      return *this;
deba@165
  1428
    }
deba@165
  1429
deba@165
  1430
    /// \brief Node reading rule
deba@165
  1431
    ///
deba@165
  1432
    /// Add a node reading rule to reader.
deba@165
  1433
    GraphReader& node(const std::string& caption, Node& node) {
deba@165
  1434
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
deba@165
  1435
      Converter converter(_node_index);
deba@165
  1436
      _reader_bits::ValueStorageBase* storage = 
deba@165
  1437
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
deba@165
  1438
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1439
      return *this;
deba@165
  1440
    }
deba@165
  1441
deba@165
  1442
    /// \brief Edge reading rule
deba@165
  1443
    ///
deba@165
  1444
    /// Add an edge reading rule to reader.
deba@165
  1445
    GraphReader& edge(const std::string& caption, Edge& edge) {
deba@165
  1446
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
deba@165
  1447
      Converter converter(_edge_index);
deba@165
  1448
      _reader_bits::ValueStorageBase* storage = 
deba@165
  1449
	new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@165
  1450
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1451
      return *this;
deba@165
  1452
    }
deba@165
  1453
deba@165
  1454
    /// \brief Arc reading rule
deba@165
  1455
    ///
deba@165
  1456
    /// Add an arc reading rule to reader.
deba@165
  1457
    GraphReader& arc(const std::string& caption, Arc& arc) {
deba@165
  1458
      typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
deba@165
  1459
      Converter converter(_graph, _edge_index);
deba@165
  1460
      _reader_bits::ValueStorageBase* storage = 
deba@165
  1461
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@165
  1462
      _attributes.insert(std::make_pair(caption, storage));
deba@165
  1463
      return *this;
deba@165
  1464
    }
deba@165
  1465
deba@165
  1466
    /// @}
deba@165
  1467
deba@165
  1468
    /// \name Select section by name
deba@165
  1469
    /// @{
deba@165
  1470
deba@165
  1471
    /// \brief Set \c \@nodes section to be read
deba@165
  1472
    ///
deba@165
  1473
    /// Set \c \@nodes section to be read
deba@165
  1474
    GraphReader& nodes(const std::string& caption) {
deba@165
  1475
      _nodes_caption = caption;
deba@165
  1476
      return *this;
deba@165
  1477
    }
deba@165
  1478
deba@165
  1479
    /// \brief Set \c \@edges section to be read
deba@165
  1480
    ///
deba@165
  1481
    /// Set \c \@edges section to be read
deba@165
  1482
    GraphReader& edges(const std::string& caption) {
deba@165
  1483
      _edges_caption = caption;
deba@165
  1484
      return *this;
deba@165
  1485
    }
deba@165
  1486
deba@165
  1487
    /// \brief Set \c \@attributes section to be read
deba@165
  1488
    ///
deba@165
  1489
    /// Set \c \@attributes section to be read
deba@165
  1490
    GraphReader& attributes(const std::string& caption) {
deba@165
  1491
      _attributes_caption = caption;
deba@165
  1492
      return *this;
deba@165
  1493
    }
deba@165
  1494
deba@165
  1495
    /// @}
deba@165
  1496
deba@165
  1497
    /// \name Using previously constructed node or edge set
deba@165
  1498
    /// @{
deba@165
  1499
deba@165
  1500
    /// \brief Use previously constructed node set
deba@165
  1501
    ///
deba@165
  1502
    /// Use previously constructed node set, and specify the node
deba@165
  1503
    /// label map.
deba@165
  1504
    template <typename Map>
deba@165
  1505
    GraphReader& useNodes(const Map& map) {
deba@165
  1506
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@165
  1507
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
deba@165
  1508
      _use_nodes = true;
deba@165
  1509
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@165
  1510
      for (NodeIt n(_graph); n != INVALID; ++n) {
deba@165
  1511
	_node_index.insert(std::make_pair(converter(map[n]), n));
deba@165
  1512
      }
deba@165
  1513
      return *this;
deba@165
  1514
    }
deba@165
  1515
deba@165
  1516
    /// \brief Use previously constructed node set
deba@165
  1517
    ///
deba@165
  1518
    /// Use previously constructed node set, and specify the node
deba@165
  1519
    /// label map and a functor which converts the label map values to
deba@165
  1520
    /// std::string.
deba@165
  1521
    template <typename Map, typename Converter>
deba@165
  1522
    GraphReader& useNodes(const Map& map, 
deba@165
  1523
			    const Converter& converter = Converter()) {
deba@165
  1524
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@165
  1525
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
deba@165
  1526
      _use_nodes = true;
deba@165
  1527
      for (NodeIt n(_graph); n != INVALID; ++n) {
deba@165
  1528
	_node_index.insert(std::make_pair(converter(map[n]), n));
deba@165
  1529
      }
deba@165
  1530
      return *this;
deba@165
  1531
    }
deba@165
  1532
deba@165
  1533
    /// \brief Use previously constructed edge set
deba@165
  1534
    ///
deba@165
  1535
    /// Use previously constructed edge set, and specify the edge
deba@165
  1536
    /// label map.
deba@165
  1537
    template <typename Map>
deba@165
  1538
    GraphReader& useEdges(const Map& map) {
deba@165
  1539
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@165
  1540
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
deba@165
  1541
      _use_edges = true;
deba@165
  1542
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@165
  1543
      for (EdgeIt a(_graph); a != INVALID; ++a) {
deba@165
  1544
	_edge_index.insert(std::make_pair(converter(map[a]), a));
deba@165
  1545
      }
deba@165
  1546
      return *this;
deba@165
  1547
    }
deba@165
  1548
deba@165
  1549
    /// \brief Use previously constructed edge set
deba@165
  1550
    ///
deba@165
  1551
    /// Use previously constructed edge set, and specify the edge
deba@165
  1552
    /// label map and a functor which converts the label map values to
deba@165
  1553
    /// std::string.
deba@165
  1554
    template <typename Map, typename Converter>
deba@165
  1555
    GraphReader& useEdges(const Map& map, 
deba@165
  1556
			    const Converter& converter = Converter()) {
deba@165
  1557
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@165
  1558
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member"); 
deba@165
  1559
      _use_edges = true;
deba@165
  1560
      for (EdgeIt a(_graph); a != INVALID; ++a) {
deba@165
  1561
	_edge_index.insert(std::make_pair(converter(map[a]), a));
deba@165
  1562
      }
deba@165
  1563
      return *this;
deba@165
  1564
    }
deba@165
  1565
deba@188
  1566
    /// \brief Skips the reading of node section
deba@188
  1567
    ///
deba@188
  1568
    /// Omit the reading of the node section. This implies that each node
deba@188
  1569
    /// map reading rule will be abanoned, and the nodes of the graph
deba@188
  1570
    /// will not be constructed, which usually cause that the edge set
deba@188
  1571
    /// could not be read due to lack of node name
deba@188
  1572
    /// resolving. Therefore, the \c skipEdges() should be used too, or
deba@188
  1573
    /// the useNodes() member function should be used to specify the
deba@188
  1574
    /// label of the nodes.
deba@188
  1575
    GraphReader& skipNodes() {
deba@188
  1576
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); 
deba@188
  1577
      _skip_nodes = true;
deba@188
  1578
      return *this;
deba@188
  1579
    }
deba@188
  1580
deba@188
  1581
    /// \brief Skips the reading of edge section
deba@188
  1582
    ///
deba@188
  1583
    /// Omit the reading of the edge section. This implies that each edge
deba@188
  1584
    /// map reading rule will be abanoned, and the edges of the graph
deba@188
  1585
    /// will not be constructed.
deba@188
  1586
    GraphReader& skipEdges() {
deba@188
  1587
      LEMON_ASSERT(!_skip_edges, "Skip edges already set"); 
deba@188
  1588
      _skip_edges = true;
deba@188
  1589
      return *this;
deba@188
  1590
    }
deba@188
  1591
deba@165
  1592
    /// @}
deba@165
  1593
deba@165
  1594
  private:
deba@165
  1595
deba@165
  1596
    bool readLine() {
deba@165
  1597
      std::string str;
deba@165
  1598
      while(++line_num, std::getline(*_is, str)) {
deba@165
  1599
	line.clear(); line.str(str);
deba@165
  1600
	char c;
deba@165
  1601
	if (line >> std::ws >> c && c != '#') {
deba@165
  1602
	  line.putback(c);
deba@165
  1603
	  return true;
deba@165
  1604
	}
deba@165
  1605
      }
deba@165
  1606
      return false;
deba@165
  1607
    }
deba@165
  1608
deba@165
  1609
    bool readSuccess() {
deba@165
  1610
      return static_cast<bool>(*_is);
deba@165
  1611
    }
deba@165
  1612
    
deba@165
  1613
    void skipSection() {
deba@165
  1614
      char c;
deba@165
  1615
      while (readSuccess() && line >> c && c != '@') {
deba@165
  1616
	readLine();
deba@165
  1617
      }
deba@165
  1618
      line.putback(c);
deba@165
  1619
    }
deba@165
  1620
deba@165
  1621
    void readNodes() {
deba@165
  1622
deba@165
  1623
      std::vector<int> map_index(_node_maps.size());
deba@165
  1624
      int map_num, label_index;
deba@165
  1625
deba@186
  1626
      char c;
deba@186
  1627
      if (!readLine() || !(line >> c) || c == '@') {
deba@186
  1628
	if (readSuccess() && line) line.putback(c);
deba@186
  1629
	if (!_node_maps.empty()) 
deba@186
  1630
	  throw DataFormatError("Cannot find map names");
deba@186
  1631
	return;
deba@186
  1632
      }
deba@186
  1633
      line.putback(c);
deba@165
  1634
      
deba@165
  1635
      {
deba@165
  1636
	std::map<std::string, int> maps;
deba@165
  1637
	
deba@165
  1638
	std::string map;
deba@165
  1639
	int index = 0;
deba@165
  1640
	while (_reader_bits::readToken(line, map)) {
deba@165
  1641
	  if (maps.find(map) != maps.end()) {
deba@165
  1642
	    std::ostringstream msg;
deba@165
  1643
	    msg << "Multiple occurence of node map: " << map;
deba@165
  1644
	    throw DataFormatError(msg.str().c_str());
deba@165
  1645
	  }
deba@165
  1646
	  maps.insert(std::make_pair(map, index));
deba@165
  1647
	  ++index;
deba@165
  1648
	}
deba@165
  1649
	
deba@165
  1650
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
deba@165
  1651
	  std::map<std::string, int>::iterator jt = 
deba@165
  1652
	    maps.find(_node_maps[i].first);
deba@165
  1653
	  if (jt == maps.end()) {
deba@165
  1654
	    std::ostringstream msg;
deba@165
  1655
	    msg << "Map not found in file: " << _node_maps[i].first;
deba@165
  1656
	    throw DataFormatError(msg.str().c_str());
deba@165
  1657
	  }
deba@165
  1658
	  map_index[i] = jt->second;
deba@165
  1659
	}
deba@165
  1660
deba@165
  1661
	{
deba@165
  1662
	  std::map<std::string, int>::iterator jt = maps.find("label");
deba@186
  1663
	  if (jt != maps.end()) {
deba@186
  1664
	    label_index = jt->second;
deba@186
  1665
	  } else {
deba@186
  1666
	    label_index = -1;
deba@186
  1667
	  }
deba@165
  1668
	}
deba@165
  1669
	map_num = maps.size();
deba@165
  1670
      }
deba@165
  1671
deba@165
  1672
      while (readLine() && line >> c && c != '@') {
deba@165
  1673
	line.putback(c);
deba@165
  1674
deba@165
  1675
	std::vector<std::string> tokens(map_num);
deba@165
  1676
	for (int i = 0; i < map_num; ++i) {
deba@165
  1677
	  if (!_reader_bits::readToken(line, tokens[i])) {
deba@165
  1678
	    std::ostringstream msg;
deba@165
  1679
	    msg << "Column not found (" << i + 1 << ")";
deba@165
  1680
	    throw DataFormatError(msg.str().c_str());
deba@165
  1681
	  }
deba@165
  1682
	}
deba@165
  1683
	if (line >> std::ws >> c)
deba@165
  1684
	  throw DataFormatError("Extra character on the end of line");
deba@165
  1685
	
deba@165
  1686
	Node n;
deba@165
  1687
	if (!_use_nodes) {
deba@165
  1688
	  n = _graph.addNode();
deba@186
  1689
	  if (label_index != -1) 
deba@186
  1690
	    _node_index.insert(std::make_pair(tokens[label_index], n));
deba@165
  1691
	} else {
deba@186
  1692
	  if (label_index == -1) 
deba@186
  1693
	    throw DataFormatError("Label map not found in file");
deba@165
  1694
	  typename std::map<std::string, Node>::iterator it =
deba@165
  1695
	    _node_index.find(tokens[label_index]);
deba@165
  1696
	  if (it == _node_index.end()) {
deba@165
  1697
	    std::ostringstream msg;
deba@165
  1698
	    msg << "Node with label not found: " << tokens[label_index];
deba@165
  1699
	    throw DataFormatError(msg.str().c_str());	    
deba@165
  1700
	  }
deba@165
  1701
	  n = it->second;
deba@165
  1702
	}
deba@165
  1703
deba@165
  1704
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
deba@165
  1705
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
deba@165
  1706
	}
deba@165
  1707
deba@165
  1708
      }
deba@165
  1709
      if (readSuccess()) {
deba@165
  1710
	line.putback(c);
deba@165
  1711
      }
deba@165
  1712
    }
deba@165
  1713
deba@165
  1714
    void readEdges() {
deba@165
  1715
deba@165
  1716
      std::vector<int> map_index(_edge_maps.size());
deba@165
  1717
      int map_num, label_index;
deba@165
  1718
deba@186
  1719
      char c;
deba@186
  1720
      if (!readLine() || !(line >> c) || c == '@') {
deba@186
  1721
	if (readSuccess() && line) line.putback(c);
deba@186
  1722
	if (!_edge_maps.empty()) 
deba@186
  1723
	  throw DataFormatError("Cannot find map names");
deba@186
  1724
	return;
deba@186
  1725
      }
deba@186
  1726
      line.putback(c);
deba@165
  1727
      
deba@165
  1728
      {
deba@165
  1729
	std::map<std::string, int> maps;
deba@165
  1730
	
deba@165
  1731
	std::string map;
deba@165
  1732
	int index = 0;
deba@165
  1733
	while (_reader_bits::readToken(line, map)) {
deba@165
  1734
	  if (maps.find(map) != maps.end()) {
deba@165
  1735
	    std::ostringstream msg;
deba@165
  1736
	    msg << "Multiple occurence of edge map: " << map;
deba@165
  1737
	    throw DataFormatError(msg.str().c_str());
deba@165
  1738
	  }
deba@165
  1739
	  maps.insert(std::make_pair(map, index));
deba@165
  1740
	  ++index;
deba@165
  1741
	}
deba@165
  1742
	
deba@165
  1743
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
deba@165
  1744
	  std::map<std::string, int>::iterator jt = 
deba@165
  1745
	    maps.find(_edge_maps[i].first);
deba@165
  1746
	  if (jt == maps.end()) {
deba@165
  1747
	    std::ostringstream msg;
deba@165
  1748
	    msg << "Map not found in file: " << _edge_maps[i].first;
deba@165
  1749
	    throw DataFormatError(msg.str().c_str());
deba@165
  1750
	  }
deba@165
  1751
	  map_index[i] = jt->second;
deba@165
  1752
	}
deba@165
  1753
deba@165
  1754
	{
deba@165
  1755
	  std::map<std::string, int>::iterator jt = maps.find("label");
deba@186
  1756
	  if (jt != maps.end()) {
deba@186
  1757
	    label_index = jt->second;
deba@186
  1758
	  } else {
deba@186
  1759
	    label_index = -1;
deba@186
  1760
	  }
deba@165
  1761
	}
deba@165
  1762
	map_num = maps.size();
deba@165
  1763
      }
deba@165
  1764
deba@165
  1765
      while (readLine() && line >> c && c != '@') {
deba@165
  1766
	line.putback(c);
deba@165
  1767
deba@165
  1768
	std::string source_token;
deba@165
  1769
	std::string target_token;
deba@165
  1770
deba@165
  1771
	if (!_reader_bits::readToken(line, source_token))
deba@186
  1772
	  throw DataFormatError("Node u not found");
deba@165
  1773
deba@165
  1774
	if (!_reader_bits::readToken(line, target_token))
deba@186
  1775
	  throw DataFormatError("Node v not found");
deba@165
  1776
	
deba@165
  1777
	std::vector<std::string> tokens(map_num);
deba@165
  1778
	for (int i = 0; i < map_num; ++i) {
deba@165
  1779
	  if (!_reader_bits::readToken(line, tokens[i])) {
deba@165
  1780
	    std::ostringstream msg;
deba@165
  1781
	    msg << "Column not found (" << i + 1 << ")";
deba@165
  1782
	    throw DataFormatError(msg.str().c_str());
deba@165
  1783
	  }
deba@165
  1784
	}
deba@165
  1785
	if (line >> std::ws >> c)
deba@165
  1786
	  throw DataFormatError("Extra character on the end of line");
deba@165
  1787
	
deba@165
  1788
	Edge e;
deba@165
  1789
	if (!_use_edges) {
deba@165
  1790
deba@165
  1791
          typename NodeIndex::iterator it;
deba@165
  1792
 
deba@165
  1793
          it = _node_index.find(source_token);
deba@165
  1794
          if (it == _node_index.end()) {
deba@165
  1795
            std::ostringstream msg;
deba@165
  1796
            msg << "Item not found: " << source_token;
deba@165
  1797
            throw DataFormatError(msg.str().c_str());
deba@165
  1798
          }
deba@165
  1799
          Node source = it->second;
deba@165
  1800
deba@165
  1801
          it = _node_index.find(target_token);
deba@165
  1802
          if (it == _node_index.end()) {       
deba@165
  1803
            std::ostringstream msg;            
deba@165
  1804
            msg << "Item not found: " << target_token;
deba@165
  1805
            throw DataFormatError(msg.str().c_str());
deba@165
  1806
          }                                          
deba@165
  1807
          Node target = it->second;                            
deba@165
  1808
deba@165
  1809
	  e = _graph.addEdge(source, target);
deba@186
  1810
	  if (label_index != -1) 
deba@186
  1811
	    _edge_index.insert(std::make_pair(tokens[label_index], e));
deba@165
  1812
	} else {
deba@186
  1813
	  if (label_index == -1) 
deba@186
  1814
	    throw DataFormatError("Label map not found in file");
deba@165
  1815
	  typename std::map<std::string, Edge>::iterator it =
deba@165
  1816
	    _edge_index.find(tokens[label_index]);
deba@165
  1817
	  if (it == _edge_index.end()) {
deba@165
  1818
	    std::ostringstream msg;
deba@165
  1819
	    msg << "Edge with label not found: " << tokens[label_index];
deba@165
  1820
	    throw DataFormatError(msg.str().c_str());	    
deba@165
  1821
	  }
deba@165
  1822
	  e = it->second;
deba@165
  1823
	}
deba@165
  1824
deba@165
  1825
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
deba@165
  1826
	  _edge_maps[i].second->set(e, tokens[map_index[i]]);
deba@165
  1827
	}
deba@165
  1828
deba@165
  1829
      }
deba@165
  1830
      if (readSuccess()) {
deba@165
  1831
	line.putback(c);
deba@165
  1832
      }
deba@165
  1833
    }
deba@165
  1834
deba@165
  1835
    void readAttributes() {
deba@165
  1836
deba@165
  1837
      std::set<std::string> read_attr;
deba@165
  1838
deba@165
  1839
      char c;
deba@165
  1840
      while (readLine() && line >> c && c != '@') {
deba@165
  1841
	line.putback(c);
deba@165
  1842
	
deba@165
  1843
	std::string attr, token;
deba@165
  1844
	if (!_reader_bits::readToken(line, attr))
deba@165
  1845
	  throw DataFormatError("Attribute name not found");
deba@165
  1846
	if (!_reader_bits::readToken(line, token))
deba@165
  1847
	  throw DataFormatError("Attribute value not found");
deba@165
  1848
	if (line >> c)
deba@165
  1849
	  throw DataFormatError("Extra character on the end of line");	  
deba@165
  1850
deba@165
  1851
	{
deba@165
  1852
	  std::set<std::string>::iterator it = read_attr.find(attr);
deba@165
  1853
	  if (it != read_attr.end()) {
deba@165
  1854
	    std::ostringstream msg;
deba@165
  1855
	    msg << "Multiple occurence of attribute " << attr;
deba@165
  1856
	    throw DataFormatError(msg.str().c_str());
deba@165
  1857
	  }
deba@165
  1858
	  read_attr.insert(attr);
deba@165
  1859
	}
deba@165
  1860
	
deba@165
  1861
	{
deba@165
  1862
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
deba@165
  1863
	  while (it != _attributes.end() && it->first == attr) {
deba@165
  1864
	    it->second->set(token);
deba@165
  1865
	    ++it;
deba@165
  1866
	  }
deba@165
  1867
	}
deba@165
  1868
deba@165
  1869
      }
deba@165
  1870
      if (readSuccess()) {
deba@165
  1871
	line.putback(c);
deba@165
  1872
      }
deba@165
  1873
      for (typename Attributes::iterator it = _attributes.begin();
deba@165
  1874
	   it != _attributes.end(); ++it) {
deba@165
  1875
	if (read_attr.find(it->first) == read_attr.end()) {
deba@165
  1876
	  std::ostringstream msg;
deba@165
  1877
	  msg << "Attribute not found in file: " << it->first;
deba@165
  1878
	  throw DataFormatError(msg.str().c_str());
deba@165
  1879
	}	
deba@165
  1880
      }
deba@165
  1881
    }
deba@165
  1882
deba@165
  1883
  public:
deba@165
  1884
deba@165
  1885
    /// \name Execution of the reader    
deba@165
  1886
    /// @{
deba@165
  1887
deba@165
  1888
    /// \brief Start the batch processing
deba@165
  1889
    ///
deba@165
  1890
    /// This function starts the batch processing
deba@165
  1891
    void run() {
deba@165
  1892
      
deba@165
  1893
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
deba@165
  1894
      
deba@188
  1895
      bool nodes_done = _skip_nodes;
deba@188
  1896
      bool edges_done = _skip_edges;
deba@165
  1897
      bool attributes_done = false;
deba@165
  1898
deba@165
  1899
      line_num = 0;      
deba@165
  1900
      readLine();
deba@172
  1901
      skipSection();
deba@165
  1902
deba@165
  1903
      while (readSuccess()) {
deba@165
  1904
	try {
deba@165
  1905
	  char c;
deba@165
  1906
	  std::string section, caption;
deba@165
  1907
	  line >> c;
deba@165
  1908
	  _reader_bits::readToken(line, section);
deba@165
  1909
	  _reader_bits::readToken(line, caption);
deba@165
  1910
deba@165
  1911
	  if (line >> c) 
deba@165
  1912
	    throw DataFormatError("Extra character on the end of line");
deba@165
  1913
deba@165
  1914
	  if (section == "nodes" && !nodes_done) {
deba@165
  1915
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
deba@165
  1916
	      readNodes();
deba@165
  1917
	      nodes_done = true;
deba@165
  1918
	    }
deba@165
  1919
	  } else if ((section == "edges" || section == "arcs") && 
deba@165
  1920
		     !edges_done) {
deba@165
  1921
	    if (_edges_caption.empty() || _edges_caption == caption) {
deba@165
  1922
	      readEdges();
deba@165
  1923
	      edges_done = true;
deba@165
  1924
	    }
deba@165
  1925
	  } else if (section == "attributes" && !attributes_done) {
deba@165
  1926
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
deba@165
  1927
	      readAttributes();
deba@165
  1928
	      attributes_done = true;
deba@165
  1929
	    }
deba@165
  1930
	  } else {
deba@172
  1931
	    readLine();
deba@172
  1932
	    skipSection();
deba@165
  1933
	  }
deba@165
  1934
	} catch (DataFormatError& error) {
deba@165
  1935
	  error.line(line_num);
deba@165
  1936
	  throw;
deba@165
  1937
	}	
deba@165
  1938
      }
deba@165
  1939
deba@165
  1940
      if (!nodes_done) {
deba@165
  1941
	throw DataFormatError("Section @nodes not found");
deba@165
  1942
      }
deba@165
  1943
deba@165
  1944
      if (!edges_done) {
deba@165
  1945
	throw DataFormatError("Section @edges not found");
deba@165
  1946
      }
deba@165
  1947
deba@165
  1948
      if (!attributes_done && !_attributes.empty()) {
deba@165
  1949
	throw DataFormatError("Section @attributes not found");
deba@165
  1950
      }
deba@165
  1951
deba@165
  1952
    }
deba@165
  1953
deba@165
  1954
    /// @}
deba@165
  1955
    
deba@165
  1956
  };
deba@165
  1957
deba@165
  1958
  /// \relates GraphReader
deba@165
  1959
  template <typename Graph>
deba@165
  1960
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
deba@165
  1961
    GraphReader<Graph> tmp(is, graph);
deba@165
  1962
    return tmp;
deba@165
  1963
  }
deba@165
  1964
deba@165
  1965
  /// \relates GraphReader
deba@165
  1966
  template <typename Graph>
deba@165
  1967
  GraphReader<Graph> graphReader(const std::string& fn, 
deba@165
  1968
				       Graph& graph) {
deba@165
  1969
    GraphReader<Graph> tmp(fn, graph);
deba@165
  1970
    return tmp;
deba@165
  1971
  }
deba@165
  1972
deba@165
  1973
  /// \relates GraphReader
deba@165
  1974
  template <typename Graph>
deba@165
  1975
  GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
deba@165
  1976
    GraphReader<Graph> tmp(fn, graph);
deba@165
  1977
    return tmp;
deba@165
  1978
  }
deba@173
  1979
deba@189
  1980
  /// \brief Section reader class
deba@189
  1981
  ///
deba@189
  1982
  /// In the \e LGF file extra sections can be placed, which contain
deba@189
  1983
  /// any data in arbitrary format. Such sections can be read with
deba@189
  1984
  /// this class. A reading rule can be added with two different
deba@189
  1985
  /// functions, with the \c sectionLines() function a functor can
deba@189
  1986
  /// process the section line-by-line. While with the \c
deba@189
  1987
  /// sectionStream() member the section can be read from an input
deba@189
  1988
  /// stream.
deba@189
  1989
  class SectionReader {
deba@189
  1990
  private:
deba@189
  1991
    
deba@189
  1992
    std::istream* _is;
deba@189
  1993
    bool local_is;
deba@189
  1994
deba@189
  1995
    typedef std::map<std::string, _reader_bits::Section*> Sections;
deba@189
  1996
    Sections _sections;
deba@189
  1997
deba@189
  1998
    int line_num;
deba@189
  1999
    std::istringstream line;
deba@189
  2000
deba@189
  2001
  public:
deba@189
  2002
deba@189
  2003
    /// \brief Constructor
deba@189
  2004
    ///
deba@189
  2005
    /// Construct a section reader, which reads from the given input
deba@189
  2006
    /// stream.
deba@189
  2007
    SectionReader(std::istream& is) 
deba@189
  2008
      : _is(&is), local_is(false) {}
deba@189
  2009
deba@189
  2010
    /// \brief Constructor
deba@189
  2011
    ///
deba@189
  2012
    /// Construct a section reader, which reads from the given file.
deba@189
  2013
    SectionReader(const std::string& fn) 
deba@189
  2014
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
deba@189
  2015
    
deba@189
  2016
    /// \brief Constructor
deba@189
  2017
    ///
deba@189
  2018
    /// Construct a section reader, which reads from the given file.
deba@189
  2019
    SectionReader(const char* fn) 
deba@189
  2020
      : _is(new std::ifstream(fn)), local_is(true) {}
deba@189
  2021
deba@189
  2022
    /// \brief Copy constructor
deba@189
  2023
    ///
deba@189
  2024
    /// The copy constructor transfers all data from the other reader,
deba@189
  2025
    /// therefore the copied reader will not be usable more. 
deba@189
  2026
    SectionReader(SectionReader& other) 
deba@189
  2027
      : _is(other._is), local_is(other.local_is) {
deba@189
  2028
deba@189
  2029
      other._is = 0;
deba@189
  2030
      other.local_is = false;
deba@189
  2031
      
deba@189
  2032
      _sections.swap(other._sections);
deba@189
  2033
    }
deba@189
  2034
deba@189
  2035
    /// \brief Destructor
deba@189
  2036
    ~SectionReader() {
deba@189
  2037
      for (Sections::iterator it = _sections.begin(); 
deba@189
  2038
	   it != _sections.end(); ++it) {
deba@189
  2039
	delete it->second;
deba@189
  2040
      }
deba@189
  2041
deba@189
  2042
      if (local_is) {
deba@189
  2043
	delete _is;
deba@189
  2044
      }
deba@189
  2045
deba@189
  2046
    }
deba@189
  2047
deba@189
  2048
  private:
deba@189
  2049
    
deba@189
  2050
    SectionReader& operator=(const SectionReader&);
deba@189
  2051
deba@189
  2052
  public:
deba@189
  2053
deba@189
  2054
    /// \name Section readers
deba@189
  2055
    /// @{
deba@189
  2056
deba@189
  2057
    /// \brief Add a section processor with line oriented reading
deba@189
  2058
    ///
deba@189
  2059
    /// The first parameter is the type descriptor of the section, the
deba@189
  2060
    /// second is a functor, which takes just one \c std::string
deba@189
  2061
    /// parameter. At the reading process, each line of the section
deba@189
  2062
    /// will be given to the functor object. However, the empty lines
deba@189
  2063
    /// and the comment lines are filtered out, and the leading
deba@189
  2064
    /// whitespaces are trimmed from each processed string.
deba@189
  2065
    ///
deba@189
  2066
    /// For example let's see a section, which contain several
deba@189
  2067
    /// integers, which should be inserted into a vector.
deba@189
  2068
    ///\code
deba@189
  2069
    ///  @numbers
deba@189
  2070
    ///  12 45 23
deba@189
  2071
    ///  4
deba@189
  2072
    ///  23 6
deba@189
  2073
    ///\endcode
deba@189
  2074
    ///
deba@189
  2075
    /// The functor is implemented as an struct:
deba@189
  2076
    ///\code
deba@189
  2077
    ///  struct NumberSection {
deba@189
  2078
    ///    std::vector<int>& _data;
deba@189
  2079
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
deba@189
  2080
    ///    void operator()(const std::string& line) {
deba@189
  2081
    ///      std::istringstream ls(line);
deba@189
  2082
    ///      int value;
deba@189
  2083
    ///      while (ls >> value) _data.push_back(value);
deba@189
  2084
    ///    }
deba@189
  2085
    ///  };
deba@189
  2086
    ///
deba@189
  2087
    ///  // ...
deba@189
  2088
    ///
deba@189
  2089
    ///  reader.sectionLines("numbers", NumberSection(vec));  
deba@189
  2090
    ///\endcode
deba@189
  2091
    template <typename Functor>
deba@189
  2092
    SectionReader& sectionLines(const std::string& type, Functor functor) {
deba@189
  2093
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
deba@189
  2094
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
deba@189
  2095
		   "Multiple reading of section.");
deba@189
  2096
      _sections.insert(std::make_pair(type, 
deba@189
  2097
        new _reader_bits::LineSection<Functor>(functor)));
deba@189
  2098
      return *this;
deba@189
  2099
    }
deba@189
  2100
deba@189
  2101
deba@189
  2102
    /// \brief Add a section processor with stream oriented reading
deba@189
  2103
    ///
deba@189
  2104
    /// The first parameter is the type of the section, the second is
deba@189
  2105
    /// a functor, which takes an \c std::istream& and an int&
deba@189
  2106
    /// parameter, the latter regard to the line number of stream. The
deba@189
  2107
    /// functor can read the input while the section go on, and the
deba@189
  2108
    /// line number should be modified accordingly.
deba@189
  2109
    template <typename Functor>
deba@189
  2110
    SectionReader& sectionStream(const std::string& type, Functor functor) {
deba@189
  2111
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
deba@189
  2112
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
deba@189
  2113
		   "Multiple reading of section.");
deba@189
  2114
      _sections.insert(std::make_pair(type, 
deba@189
  2115
	 new _reader_bits::StreamSection<Functor>(functor)));
deba@189
  2116
      return *this;
deba@189
  2117
    }    
deba@189
  2118
    
deba@189
  2119
    /// @}
deba@189
  2120
deba@189
  2121
  private:
deba@189
  2122
deba@189
  2123
    bool readLine() {
deba@189
  2124
      std::string str;
deba@189
  2125
      while(++line_num, std::getline(*_is, str)) {
deba@189
  2126
	line.clear(); line.str(str);
deba@189
  2127
	char c;
deba@189
  2128
	if (line >> std::ws >> c && c != '#') {
deba@189
  2129
	  line.putback(c);
deba@189
  2130
	  return true;
deba@189
  2131
	}
deba@189
  2132
      }
deba@189
  2133
      return false;
deba@189
  2134
    }
deba@189
  2135
deba@189
  2136
    bool readSuccess() {
deba@189
  2137
      return static_cast<bool>(*_is);
deba@189
  2138
    }
deba@189
  2139
    
deba@189
  2140
    void skipSection() {
deba@189
  2141
      char c;
deba@189
  2142
      while (readSuccess() && line >> c && c != '@') {
deba@189
  2143
	readLine();
deba@189
  2144
      }
deba@189
  2145
      line.putback(c);
deba@189
  2146
    }
deba@189
  2147
deba@189
  2148
  public:
deba@189
  2149
deba@189
  2150
deba@189
  2151
    /// \name Execution of the reader    
deba@189
  2152
    /// @{
deba@189
  2153
deba@189
  2154
    /// \brief Start the batch processing
deba@189
  2155
    ///
deba@189
  2156
    /// This function starts the batch processing
deba@189
  2157
    void run() {
deba@189
  2158
      
deba@189
  2159
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
deba@189
  2160
      
deba@189
  2161
      std::set<std::string> extra_sections;
deba@189
  2162
deba@189
  2163
      line_num = 0;      
deba@189
  2164
      readLine();
deba@189
  2165
      skipSection();
deba@189
  2166
deba@189
  2167
      while (readSuccess()) {
deba@189
  2168
	try {
deba@189
  2169
	  char c;
deba@189
  2170
	  std::string section, caption;
deba@189
  2171
	  line >> c;
deba@189
  2172
	  _reader_bits::readToken(line, section);
deba@189
  2173
	  _reader_bits::readToken(line, caption);
deba@189
  2174
deba@189
  2175
	  if (line >> c) 
deba@189
  2176
	    throw DataFormatError("Extra character on the end of line");
deba@189
  2177
deba@189
  2178
	  if (extra_sections.find(section) != extra_sections.end()) {
deba@189
  2179
	    std::ostringstream msg;
deba@189
  2180
	    msg << "Multiple occurence of section " << section;
deba@189
  2181
	    throw DataFormatError(msg.str().c_str());
deba@189
  2182
	  }
deba@189
  2183
	  Sections::iterator it = _sections.find(section);
deba@189
  2184
	  if (it != _sections.end()) {
deba@189
  2185
	    extra_sections.insert(section);
deba@189
  2186
	    it->second->process(*_is, line_num);
deba@189
  2187
	  }
deba@189
  2188
	  readLine();
deba@189
  2189
	  skipSection();
deba@189
  2190
	} catch (DataFormatError& error) {
deba@189
  2191
	  error.line(line_num);
deba@189
  2192
	  throw;
deba@189
  2193
	}	
deba@189
  2194
      }
deba@189
  2195
      for (Sections::iterator it = _sections.begin();
deba@189
  2196
	   it != _sections.end(); ++it) {
deba@189
  2197
	if (extra_sections.find(it->first) == extra_sections.end()) {
deba@189
  2198
	  std::ostringstream os;
deba@189
  2199
	  os << "Cannot find section: " << it->first;
deba@189
  2200
	  throw DataFormatError(os.str().c_str());
deba@189
  2201
	}
deba@189
  2202
      }
deba@189
  2203
    }
deba@189
  2204
deba@189
  2205
    /// @}
deba@189
  2206
        
deba@189
  2207
  };
deba@189
  2208
deba@189
  2209
  /// \relates SectionReader
deba@189
  2210
  inline SectionReader sectionReader(std::istream& is) {
deba@189
  2211
    SectionReader tmp(is);
deba@189
  2212
    return tmp;
deba@189
  2213
  }
deba@189
  2214
deba@189
  2215
  /// \relates SectionReader
deba@189
  2216
  inline SectionReader sectionReader(const std::string& fn) {
deba@189
  2217
    SectionReader tmp(fn);
deba@189
  2218
    return tmp;
deba@189
  2219
  }
deba@189
  2220
deba@189
  2221
  /// \relates SectionReader
deba@189
  2222
  inline SectionReader sectionReader(const char* fn) {
deba@189
  2223
    SectionReader tmp(fn);
deba@189
  2224
    return tmp;
deba@189
  2225
  }
deba@189
  2226
deba@173
  2227
  /// \ingroup lemon_io
deba@173
  2228
  ///
alpar@179
  2229
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file 
deba@173
  2230
  ///
deba@173
  2231
  /// This class can be used to read the sections, the map names and
deba@173
  2232
  /// the attributes from a file. Usually, the Lemon programs know
deba@173
  2233
  /// that, which type of graph, which maps and which attributes
deba@173
  2234
  /// should be read from a file, but in general tools (like glemon)
alpar@179
  2235
  /// the contents of an LGF file should be guessed somehow. This class
deba@173
  2236
  /// reads the graph and stores the appropriate information for
deba@173
  2237
  /// reading the graph.
deba@173
  2238
  ///
alpar@179
  2239
  ///\code LgfContents contents("graph.lgf"); 
alpar@179
  2240
  /// contents.run();
deba@173
  2241
  ///
deba@173
  2242
  /// // does it contain any node section and arc section
alpar@179
  2243
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
deba@173
  2244
  ///   std::cerr << "Failure, cannot find graph" << std::endl;
deba@173
  2245
  ///   return -1;
deba@173
  2246
  /// }
deba@173
  2247
  /// std::cout << "The name of the default node section : " 
alpar@179
  2248
  ///           << contents.nodeSection(0) << std::endl;
deba@173
  2249
  /// std::cout << "The number of the arc maps : " 
alpar@179
  2250
  ///           << contents.arcMaps(0).size() << std::endl;
deba@173
  2251
  /// std::cout << "The name of second arc map : " 
alpar@179
  2252
  ///           << contents.arcMaps(0)[1] << std::endl;
deba@173
  2253
  ///\endcode
alpar@179
  2254
  class LgfContents {    
deba@173
  2255
  private:
deba@173
  2256
deba@173
  2257
    std::istream* _is;
deba@173
  2258
    bool local_is;
deba@173
  2259
deba@173
  2260
    std::vector<std::string> _node_sections;
deba@173
  2261
    std::vector<std::string> _edge_sections;
deba@173
  2262
    std::vector<std::string> _attribute_sections;
deba@173
  2263
    std::vector<std::string> _extra_sections;
deba@173
  2264
deba@173
  2265
    std::vector<bool> _arc_sections;
deba@173
  2266
deba@173
  2267
    std::vector<std::vector<std::string> > _node_maps;
deba@173
  2268
    std::vector<std::vector<std::string> > _edge_maps;
deba@173
  2269
deba@173
  2270
    std::vector<std::vector<std::string> > _attributes;
deba@173
  2271
deba@173
  2272
deba@173
  2273
    int line_num;
deba@173
  2274
    std::istringstream line;
deba@173
  2275
    
deba@173
  2276
  public:
deba@173
  2277
deba@173
  2278
    /// \brief Constructor
deba@173
  2279
    ///
alpar@179
  2280
    /// Construct an \e LGF contents reader, which reads from the given
deba@173
  2281
    /// input stream.
alpar@179
  2282
    LgfContents(std::istream& is) 
deba@173
  2283
      : _is(&is), local_is(false) {}
deba@173
  2284
deba@173
  2285
    /// \brief Constructor
deba@173
  2286
    ///
alpar@179
  2287
    /// Construct an \e LGF contents reader, which reads from the given
deba@173
  2288
    /// file.
alpar@179
  2289
    LgfContents(const std::string& fn) 
deba@173
  2290
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
deba@173
  2291
deba@173
  2292
    /// \brief Constructor
deba@173
  2293
    ///
alpar@179
  2294
    /// Construct an \e LGF contents reader, which reads from the given
deba@173
  2295
    /// file.
alpar@179
  2296
    LgfContents(const char* fn)
deba@173
  2297
      : _is(new std::ifstream(fn)), local_is(true) {}
deba@173
  2298
deba@173
  2299
    /// \brief Copy constructor
deba@173
  2300
    ///
deba@173
  2301
    /// The copy constructor transfers all data from the other reader,
deba@173
  2302
    /// therefore the copied reader will not be usable more. 
alpar@179
  2303
    LgfContents(LgfContents& other)
deba@173
  2304
      : _is(other._is), local_is(other.local_is) {
deba@173
  2305
      
deba@173
  2306
      other._is = 0;
deba@173
  2307
      other.local_is = false;
deba@173
  2308
      
deba@173
  2309
      _node_sections.swap(other._node_sections);
deba@173
  2310
      _edge_sections.swap(other._edge_sections);
deba@173
  2311
      _attribute_sections.swap(other._attribute_sections);
deba@173
  2312
      _extra_sections.swap(other._extra_sections);
deba@173
  2313
deba@173
  2314
      _arc_sections.swap(other._arc_sections);
deba@173
  2315
deba@173
  2316
      _node_maps.swap(other._node_maps);
deba@173
  2317
      _edge_maps.swap(other._edge_maps);
deba@173
  2318
      _attributes.swap(other._attributes);
deba@173
  2319
    }
deba@173
  2320
    
deba@173
  2321
    /// \brief Destructor
alpar@179
  2322
    ~LgfContents() {
deba@173
  2323
      if (local_is) delete _is;
deba@173
  2324
    }
deba@173
  2325
deba@173
  2326
deba@173
  2327
    /// \name Node sections
deba@173
  2328
    /// @{
deba@173
  2329
deba@173
  2330
    /// \brief Gives back the number of node sections in the file.
deba@173
  2331
    ///
deba@173
  2332
    /// Gives back the number of node sections in the file.
deba@173
  2333
    int nodeSectionNum() const {
deba@173
  2334
      return _node_sections.size();
deba@173
  2335
    }
deba@173
  2336
deba@173
  2337
    /// \brief Returns the section name at the given position. 
deba@173
  2338
    ///
deba@173
  2339
    /// Returns the section name at the given position. 
deba@173
  2340
    const std::string& nodeSection(int i) const {
deba@173
  2341
      return _node_sections[i];
deba@173
  2342
    }
deba@173
  2343
deba@173
  2344
    /// \brief Gives back the node maps for the given section.
deba@173
  2345
    ///
deba@173
  2346
    /// Gives back the node maps for the given section.
alpar@182
  2347
    const std::vector<std::string>& nodeMapNames(int i) const {
deba@173
  2348
      return _node_maps[i];
deba@173
  2349
    }
deba@173
  2350
deba@173
  2351
    /// @}
deba@173
  2352
alpar@181
  2353
    /// \name Arc/Edge sections 
deba@173
  2354
    /// @{
deba@173
  2355
alpar@181
  2356
    /// \brief Gives back the number of arc/edge sections in the file.
deba@173
  2357
    ///
alpar@181
  2358
    /// Gives back the number of arc/edge sections in the file.
alpar@181
  2359
    /// \note It is synonym of \c edgeSectionNum().
deba@173
  2360
    int arcSectionNum() const {
deba@173
  2361
      return _edge_sections.size();
deba@173
  2362
    }
deba@173
  2363
deba@173
  2364
    /// \brief Returns the section name at the given position. 
deba@173
  2365
    ///
deba@173
  2366
    /// Returns the section name at the given position. 
alpar@181
  2367
    /// \note It is synonym of \c edgeSection().
deba@173
  2368
    const std::string& arcSection(int i) const {
deba@173
  2369
      return _edge_sections[i];
deba@173
  2370
    }
deba@173
  2371
alpar@181
  2372
    /// \brief Gives back the arc/edge maps for the given section.
deba@173
  2373
    ///
alpar@181
  2374
    /// Gives back the arc/edge maps for the given section.
alpar@182
  2375
    /// \note It is synonym of \c edgeMapNames().
alpar@182
  2376
    const std::vector<std::string>& arcMapNames(int i) const {
deba@173
  2377
      return _edge_maps[i];
deba@173
  2378
    }
deba@173
  2379
deba@173
  2380
    /// @}
deba@173
  2381
alpar@181
  2382
    /// \name Synonyms
deba@173
  2383
    /// @{
deba@173
  2384
alpar@181
  2385
    /// \brief Gives back the number of arc/edge sections in the file.
deba@173
  2386
    ///
alpar@181
  2387
    /// Gives back the number of arc/edge sections in the file.
alpar@181
  2388
    /// \note It is synonym of \c arcSectionNum().
deba@173
  2389
    int edgeSectionNum() const {
deba@173
  2390
      return _edge_sections.size();
deba@173
  2391
    }
deba@173
  2392
deba@173
  2393
    /// \brief Returns the section name at the given position. 
deba@173
  2394
    ///
deba@173
  2395
    /// Returns the section name at the given position. 
alpar@181
  2396
    /// \note It is synonym of \c arcSection().
deba@173
  2397
    const std::string& edgeSection(int i) const {
deba@173
  2398
      return _edge_sections[i];
deba@173
  2399
    }
deba@173
  2400
deba@173
  2401
    /// \brief Gives back the edge maps for the given section.
deba@173
  2402
    ///
deba@173
  2403
    /// Gives back the edge maps for the given section.
alpar@182
  2404
    /// \note It is synonym of \c arcMapNames().
alpar@182
  2405
    const std::vector<std::string>& edgeMapNames(int i) const {
deba@173
  2406
      return _edge_maps[i];
deba@173
  2407
    }
deba@173
  2408
deba@173
  2409
    /// @}
deba@173
  2410
deba@173
  2411
    /// \name Attribute sections   
deba@173
  2412
    /// @{
deba@173
  2413
deba@173
  2414
    /// \brief Gives back the number of attribute sections in the file.
deba@173
  2415
    ///
deba@173
  2416
    /// Gives back the number of attribute sections in the file.
deba@173
  2417
    int attributeSectionNum() const {
deba@173
  2418
      return _attribute_sections.size();
deba@173
  2419
    }
deba@173
  2420
deba@173
  2421
    /// \brief Returns the section name at the given position. 
deba@173
  2422
    ///
deba@173
  2423
    /// Returns the section name at the given position. 
alpar@182
  2424
    const std::string& attributeSectionNames(int i) const {
deba@173
  2425
      return _attribute_sections[i];
deba@173
  2426
    }
deba@173
  2427
deba@173
  2428
    /// \brief Gives back the attributes for the given section.
deba@173
  2429
    ///
deba@173
  2430
    /// Gives back the attributes for the given section.
deba@173
  2431
    const std::vector<std::string>& attributes(int i) const {
deba@173
  2432
      return _attributes[i];
deba@173
  2433
    }
deba@173
  2434
deba@173
  2435
    /// @}
deba@173
  2436
deba@173
  2437
    /// \name Extra sections   
deba@173
  2438
    /// @{
deba@173
  2439
deba@173
  2440
    /// \brief Gives back the number of extra sections in the file.
deba@173
  2441
    ///
deba@173
  2442
    /// Gives back the number of extra sections in the file.
deba@173
  2443
    int extraSectionNum() const {
deba@173
  2444
      return _extra_sections.size();
deba@173
  2445
    }
deba@173
  2446
deba@173
  2447
    /// \brief Returns the extra section type at the given position. 
deba@173
  2448
    ///
deba@173
  2449
    /// Returns the section type at the given position. 
deba@173
  2450
    const std::string& extraSection(int i) const {
deba@173
  2451
      return _extra_sections[i];
deba@173
  2452
    }
deba@173
  2453
deba@173
  2454
    /// @}
deba@173
  2455
deba@173
  2456
  private:
deba@173
  2457
deba@173
  2458
    bool readLine() {
deba@173
  2459
      std::string str;
deba@173
  2460
      while(++line_num, std::getline(*_is, str)) {
deba@173
  2461
	line.clear(); line.str(str);
deba@173
  2462
	char c;
deba@173
  2463
	if (line >> std::ws >> c && c != '#') {
deba@173
  2464
	  line.putback(c);
deba@173
  2465
	  return true;
deba@173
  2466
	}
deba@173
  2467
      }
deba@173
  2468
      return false;
deba@173
  2469
    }
deba@173
  2470
deba@173
  2471
    bool readSuccess() {
deba@173
  2472
      return static_cast<bool>(*_is);
deba@173
  2473
    }
deba@173
  2474
deba@173
  2475
    void skipSection() {
deba@173
  2476
      char c;
deba@173
  2477
      while (readSuccess() && line >> c && c != '@') {
deba@173
  2478
	readLine();
deba@173
  2479
      }
deba@173
  2480
      line.putback(c);
deba@173
  2481
    }
deba@173
  2482
deba@173
  2483
    void readMaps(std::vector<std::string>& maps) {
deba@186
  2484
      char c;
deba@186
  2485
      if (!readLine() || !(line >> c) || c == '@') {
deba@186
  2486
	if (readSuccess() && line) line.putback(c);
deba@186
  2487
	return;
deba@186
  2488
      }
deba@186
  2489
      line.putback(c);
deba@173
  2490
      std::string map;
deba@173
  2491
      while (_reader_bits::readToken(line, map)) {
deba@173
  2492
	maps.push_back(map);
deba@173
  2493
      }
deba@173
  2494
    }
deba@173
  2495
deba@173
  2496
    void readAttributes(std::vector<std::string>& attrs) {
deba@173
  2497
      readLine();
deba@173
  2498
      char c;
deba@173
  2499
      while (readSuccess() && line >> c && c != '@') {
deba@173
  2500
	line.putback(c);
deba@173
  2501
	std::string attr;
deba@173
  2502
	_reader_bits::readToken(line, attr);
deba@173
  2503
	attrs.push_back(attr);
deba@173
  2504
	readLine();
deba@173
  2505
      }
deba@173
  2506
      line.putback(c);
deba@173
  2507
    }
deba@173
  2508
deba@173
  2509
  public:
deba@173
  2510
alpar@179
  2511
    /// \name Execution of the contents reader    
deba@173
  2512
    /// @{
deba@173
  2513
deba@173
  2514
    /// \brief Start the reading
deba@173
  2515
    ///
deba@173
  2516
    /// This function starts the reading
deba@173
  2517
    void run() {
deba@173
  2518
deba@173
  2519
      readLine();
deba@173
  2520
      skipSection();
deba@173
  2521
deba@173
  2522
      while (readSuccess()) {
deba@173
  2523
deba@173
  2524
	char c;
deba@173
  2525
	line >> c;
deba@173
  2526
deba@173
  2527
	std::string section, caption;
deba@173
  2528
	_reader_bits::readToken(line, section);
deba@173
  2529
	_reader_bits::readToken(line, caption);
deba@173
  2530
deba@173
  2531
	if (section == "nodes") {
deba@173
  2532
	  _node_sections.push_back(caption);
deba@173
  2533
	  _node_maps.push_back(std::vector<std::string>());
deba@173
  2534
	  readMaps(_node_maps.back());
deba@173
  2535
	  readLine(); skipSection();
deba@173
  2536
	} else if (section == "arcs" || section == "edges") {
deba@173
  2537
	  _edge_sections.push_back(caption);
deba@173
  2538
	  _arc_sections.push_back(section == "arcs");
deba@173
  2539
	  _edge_maps.push_back(std::vector<std::string>());
deba@173
  2540
	  readMaps(_edge_maps.back());
deba@173
  2541
	  readLine(); skipSection();
deba@173
  2542
	} else if (section == "attributes") {
deba@173
  2543
	  _attribute_sections.push_back(caption);
deba@173
  2544
	  _attributes.push_back(std::vector<std::string>());
deba@173
  2545
	  readAttributes(_attributes.back());
deba@173
  2546
	} else {
deba@173
  2547
	  _extra_sections.push_back(section);
deba@173
  2548
	  readLine(); skipSection();
deba@173
  2549
	}
deba@173
  2550
      }
deba@173
  2551
    }
deba@173
  2552
deba@173
  2553
    /// @}
deba@173
  2554
    
deba@173
  2555
  };
deba@127
  2556
}
deba@127
  2557
deba@127
  2558
#endif