lemon/lgf_reader.h
author Balazs Dezso <deba@inf.elte.hu>
Sat, 31 May 2008 12:34:44 +0200
changeset 164 00d297da491e
parent 162 33247f6fff16
child 165 b4c336c27a03
permissions -rw-r--r--
Reworking demo file
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@127
   103
    class ValueStorageBase {
deba@127
   104
    public:
deba@127
   105
      ValueStorageBase() {}
deba@127
   106
      virtual ~ValueStorageBase() {}
deba@127
   107
deba@127
   108
      virtual void set(const std::string&) = 0;
deba@127
   109
    };
deba@127
   110
deba@127
   111
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
deba@127
   112
    class ValueStorage : public ValueStorageBase {
deba@127
   113
    public:
deba@127
   114
      typedef _Value Value;
deba@127
   115
      typedef _Converter Converter;
deba@127
   116
deba@127
   117
    private:
deba@127
   118
      Value& _value;
deba@127
   119
      Converter _converter;
deba@127
   120
deba@127
   121
    public:
deba@127
   122
      ValueStorage(Value& value, const Converter& converter = Converter())
deba@127
   123
 	: _value(value), _converter(converter) {}
deba@127
   124
deba@127
   125
      virtual void set(const std::string& value) {
deba@127
   126
	_value = _converter(value);
deba@127
   127
      }
deba@127
   128
    };
deba@127
   129
deba@127
   130
    template <typename Value>
deba@127
   131
    struct MapLookUpConverter {
deba@127
   132
      const std::map<std::string, Value>& _map;
deba@127
   133
deba@127
   134
      MapLookUpConverter(const std::map<std::string, Value>& map)
deba@127
   135
        : _map(map) {}
deba@127
   136
deba@127
   137
      Value operator()(const std::string& str) {
deba@127
   138
        typename std::map<std::string, Value>::const_iterator it =
deba@127
   139
          _map.find(str);
deba@127
   140
        if (it == _map.end()) {
deba@127
   141
          std::ostringstream msg;
deba@127
   142
          msg << "Item not found: " << str;
deba@127
   143
          throw DataFormatError(msg.str().c_str());
deba@127
   144
        }
deba@127
   145
        return it->second;
deba@127
   146
      }
deba@127
   147
    };
deba@127
   148
deba@127
   149
    bool isWhiteSpace(char c) {
deba@127
   150
      return c == ' ' || c == '\t' || c == '\v' || 
deba@127
   151
        c == '\n' || c == '\r' || c == '\f'; 
deba@127
   152
    }
deba@127
   153
    
deba@127
   154
    bool isOct(char c) {
deba@127
   155
      return '0' <= c && c <='7'; 
deba@127
   156
    }
deba@127
   157
    
deba@127
   158
    int valueOct(char c) {
deba@127
   159
      LEMON_ASSERT(isOct(c), "The character is not octal.");
deba@127
   160
      return c - '0';
deba@127
   161
    }
deba@127
   162
deba@127
   163
    bool isHex(char c) {
deba@127
   164
      return ('0' <= c && c <= '9') || 
deba@127
   165
	('a' <= c && c <= 'z') || 
deba@127
   166
	('A' <= c && c <= 'Z'); 
deba@127
   167
    }
deba@127
   168
    
deba@127
   169
    int valueHex(char c) {
deba@127
   170
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
deba@127
   171
      if ('0' <= c && c <= '9') return c - '0';
deba@127
   172
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
deba@127
   173
      return c - 'A' + 10;
deba@127
   174
    }
deba@127
   175
deba@127
   176
    bool isIdentifierFirstChar(char c) {
deba@127
   177
      return ('a' <= c && c <= 'z') ||
deba@127
   178
	('A' <= c && c <= 'Z') || c == '_';
deba@127
   179
    }
deba@127
   180
deba@127
   181
    bool isIdentifierChar(char c) {
deba@127
   182
      return isIdentifierFirstChar(c) ||
deba@127
   183
	('0' <= c && c <= '9');
deba@127
   184
    }
deba@127
   185
deba@127
   186
    char readEscape(std::istream& is) {
deba@127
   187
      char c;
deba@127
   188
      if (!is.get(c))
deba@127
   189
	throw DataFormatError("Escape format error");
deba@127
   190
deba@127
   191
      switch (c) {
deba@127
   192
      case '\\':
deba@127
   193
	return '\\';
deba@127
   194
      case '\"':
deba@127
   195
	return '\"';
deba@127
   196
      case '\'':
deba@127
   197
	return '\'';
deba@127
   198
      case '\?':
deba@127
   199
	return '\?';
deba@127
   200
      case 'a':
deba@127
   201
	return '\a';
deba@127
   202
      case 'b':
deba@127
   203
	return '\b';
deba@127
   204
      case 'f':
deba@127
   205
	return '\f';
deba@127
   206
      case 'n':
deba@127
   207
	return '\n';
deba@127
   208
      case 'r':
deba@127
   209
	return '\r';
deba@127
   210
      case 't':
deba@127
   211
	return '\t';
deba@127
   212
      case 'v':
deba@127
   213
	return '\v';
deba@127
   214
      case 'x':
deba@127
   215
	{
deba@127
   216
	  int code;
deba@127
   217
	  if (!is.get(c) || !isHex(c)) 
deba@127
   218
	    throw DataFormatError("Escape format error");
deba@127
   219
	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
deba@127
   220
	  else code = code * 16 + valueHex(c);
deba@127
   221
	  return code;
deba@127
   222
	}
deba@127
   223
      default:
deba@127
   224
	{
deba@127
   225
	  int code;
deba@127
   226
	  if (!isOct(c)) 
deba@127
   227
	    throw DataFormatError("Escape format error");
deba@127
   228
	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
deba@127
   229
	    is.putback(c);
deba@127
   230
	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
deba@127
   231
	    is.putback(c);
deba@127
   232
	  else code = code * 8 + valueOct(c);
deba@127
   233
	  return code;
deba@127
   234
	}	      
deba@127
   235
      } 
deba@127
   236
    }
deba@127
   237
    
deba@127
   238
    std::istream& readToken(std::istream& is, std::string& str) {
deba@127
   239
      std::ostringstream os;
deba@127
   240
deba@127
   241
      char c;
deba@127
   242
      is >> std::ws;
deba@127
   243
      
deba@127
   244
      if (!is.get(c)) 
deba@127
   245
	return is;
deba@127
   246
deba@127
   247
      if (c == '\"') {
deba@127
   248
	while (is.get(c) && c != '\"') {
deba@127
   249
	  if (c == '\\') 
deba@127
   250
	    c = readEscape(is);
deba@127
   251
	  os << c;
deba@127
   252
	}
deba@127
   253
	if (!is) 
deba@127
   254
	  throw DataFormatError("Quoted format error");
deba@127
   255
      } else {
deba@127
   256
	is.putback(c);
deba@127
   257
	while (is.get(c) && !isWhiteSpace(c)) {
deba@127
   258
	  if (c == '\\') 
deba@127
   259
	    c = readEscape(is);
deba@127
   260
	  os << c;
deba@127
   261
	}
deba@127
   262
	if (!is) {
deba@127
   263
	  is.clear();
deba@127
   264
	} else {
deba@127
   265
	  is.putback(c);
deba@127
   266
	}
deba@127
   267
      }
deba@127
   268
      str = os.str();
deba@127
   269
      return is;
deba@127
   270
    }
deba@162
   271
deba@162
   272
    class Section {
deba@162
   273
    public:
deba@162
   274
      virtual ~Section() {}
deba@162
   275
      virtual void process(std::istream& is, int& line_num) = 0;
deba@162
   276
    };
deba@162
   277
deba@162
   278
    template <typename Functor>
deba@162
   279
    class LineSection : public Section {
deba@162
   280
    private:
deba@162
   281
deba@162
   282
      Functor _functor;
deba@162
   283
deba@162
   284
    public:
deba@162
   285
      
deba@162
   286
      LineSection(const Functor& functor) : _functor(functor) {}
deba@162
   287
      virtual ~LineSection() {}
deba@162
   288
deba@162
   289
      virtual void process(std::istream& is, int& line_num) {
deba@162
   290
	char c;
deba@162
   291
	std::string line;
deba@162
   292
	while (is.get(c) && c != '@') {
deba@162
   293
	  if (c == '\n') {
deba@162
   294
	    ++line_num;
deba@162
   295
	  } else if (c == '#') {
deba@162
   296
	    getline(is, line);
deba@162
   297
	    ++line_num;
deba@162
   298
	  } else if (!isWhiteSpace(c)) {
deba@162
   299
	    is.putback(c);
deba@162
   300
	    getline(is, line);
deba@162
   301
	    _functor(line);
deba@162
   302
	    ++line_num;
deba@162
   303
	  }
deba@162
   304
	}
deba@162
   305
	if (is) is.putback(c);
deba@162
   306
	else if (is.eof()) is.clear();
deba@162
   307
      }
deba@162
   308
    };
deba@162
   309
deba@162
   310
    template <typename Functor>
deba@162
   311
    class StreamSection : public Section {
deba@162
   312
    private:
deba@162
   313
deba@162
   314
      Functor _functor;
deba@162
   315
deba@162
   316
    public:
deba@162
   317
      
deba@162
   318
      StreamSection(const Functor& functor) : _functor(functor) {}
deba@162
   319
      virtual ~StreamSection() {} 
deba@162
   320
deba@162
   321
      virtual void process(std::istream& is, int& line_num) {
deba@162
   322
	_functor(is, line_num);
deba@162
   323
	char c;
deba@162
   324
	std::string line;
deba@162
   325
	while (is.get(c) && c != '@') {
deba@162
   326
	  if (c == '\n') {
deba@162
   327
	    ++line_num;
deba@162
   328
	  } else if (!isWhiteSpace(c)) {
deba@162
   329
	    getline(is, line);
deba@162
   330
	    ++line_num;
deba@162
   331
	  }
deba@162
   332
	}
deba@162
   333
	if (is) is.putback(c);
deba@162
   334
	else if (is.eof()) is.clear();	
deba@162
   335
      }
deba@162
   336
    };
deba@127
   337
    
deba@127
   338
  }
alpar@156
   339
alpar@156
   340
  /// \ingroup lemon_io
alpar@156
   341
  ///  
alpar@156
   342
  /// \brief LGF reader for directed graphs
alpar@156
   343
  ///
alpar@156
   344
  /// This utility reads an \ref lgf-format "LGF" file.
alpar@156
   345
  ///
alpar@156
   346
  /// The reading method does a batch processing. The user creates a
alpar@156
   347
  /// reader object, then various reading rules can be added to the
alpar@156
   348
  /// reader, and eventually the reading is executed with the \c run()
alpar@156
   349
  /// member function. A map reading rule can be added to the reader
alpar@156
   350
  /// with the \c nodeMap() or \c arcMap() members. An optional
deba@162
   351
  /// converter parameter can also be added as a standard functor
deba@162
   352
  /// converting from std::string to the value type of the map. If it
deba@162
   353
  /// is set, it will determine how the tokens in the file should be
deba@162
   354
  /// is converted to the map's value type. If the functor is not set,
deba@162
   355
  /// then a default conversion will be used. One map can be read into
deba@162
   356
  /// multiple map objects at the same time. The \c attribute(), \c
deba@162
   357
  /// node() and \c arc() functions are used to add attribute reading
deba@162
   358
  /// rules.
alpar@156
   359
  ///
alpar@156
   360
  ///\code
alpar@156
   361
  ///     DigraphReader<Digraph>(std::cin, digraph).
alpar@156
   362
  ///       nodeMap("coordinates", coord_map).
alpar@156
   363
  ///       arcMap("capacity", cap_map).
alpar@156
   364
  ///       node("source", src).
alpar@156
   365
  ///       node("target", trg).
alpar@156
   366
  ///       attribute("caption", caption).
alpar@156
   367
  ///       run();
alpar@156
   368
  ///\endcode
alpar@156
   369
  ///
alpar@156
   370
  /// By default the reader uses the first section in the file of the
alpar@156
   371
  /// proper type. If a section has an optional name, then it can be
deba@162
   372
  /// selected for reading by giving an optional name parameter to the
deba@162
   373
  /// \c nodes(), \c arcs() or \c attributes() functions. The readers
deba@162
   374
  /// also can load extra sections with the \c sectionLines() and
deba@162
   375
  /// sectionStream() functions.
alpar@156
   376
  ///
alpar@156
   377
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
alpar@156
   378
  /// that the nodes or arcs should not be constructed (added to the
alpar@156
   379
  /// graph) during the reading, but instead the label map of the items
alpar@156
   380
  /// are given as a parameter of these functions. An
alpar@156
   381
  /// application of these function is multipass reading, which is
alpar@156
   382
  /// important if two \e \@arcs sections must be read from the
alpar@156
   383
  /// file. In this example the first phase would read the node set and one
alpar@156
   384
  /// of the arc sets, while the second phase would read the second arc
alpar@156
   385
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
alpar@156
   386
  /// The previously read label node map should be passed to the \c
alpar@156
   387
  /// useNodes() functions. Another application of multipass reading when
alpar@156
   388
  /// paths are given as a node map or an arc map. It is impossible read this in
alpar@156
   389
  /// a single pass, because the arcs are not constructed when the node
alpar@156
   390
  /// maps are read.
deba@127
   391
  template <typename _Digraph>
deba@127
   392
  class DigraphReader {
deba@127
   393
  public:
deba@127
   394
deba@127
   395
    typedef _Digraph Digraph;
deba@148
   396
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
deba@127
   397
    
deba@127
   398
  private:
deba@127
   399
deba@127
   400
deba@127
   401
    std::istream* _is;
deba@127
   402
    bool local_is;
deba@127
   403
deba@127
   404
    Digraph& _digraph;
deba@127
   405
deba@127
   406
    std::string _nodes_caption;
deba@127
   407
    std::string _arcs_caption;
deba@127
   408
    std::string _attributes_caption;
deba@127
   409
deba@127
   410
    typedef std::map<std::string, Node> NodeIndex;
deba@127
   411
    NodeIndex _node_index;
deba@127
   412
    typedef std::map<std::string, Arc> ArcIndex;
deba@127
   413
    ArcIndex _arc_index;
deba@127
   414
    
deba@127
   415
    typedef std::vector<std::pair<std::string, 
deba@127
   416
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
deba@127
   417
    NodeMaps _node_maps; 
deba@127
   418
deba@127
   419
    typedef std::vector<std::pair<std::string,
deba@127
   420
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
deba@127
   421
    ArcMaps _arc_maps;
deba@127
   422
deba@127
   423
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
deba@127
   424
      Attributes;
deba@127
   425
    Attributes _attributes;
deba@127
   426
deba@162
   427
    typedef std::map<std::string, _reader_bits::Section*> Sections;
deba@162
   428
    Sections _sections;
deba@162
   429
deba@127
   430
    bool _use_nodes;
deba@127
   431
    bool _use_arcs;
deba@127
   432
deba@127
   433
    int line_num;
deba@127
   434
    std::istringstream line;
deba@127
   435
deba@127
   436
  public:
deba@127
   437
alpar@156
   438
    /// \brief Constructor
alpar@156
   439
    ///
alpar@156
   440
    /// Construct a directed graph reader, which reads from the given
alpar@156
   441
    /// input stream.
deba@127
   442
    DigraphReader(std::istream& is, Digraph& digraph) 
deba@127
   443
      : _is(&is), local_is(false), _digraph(digraph),
deba@127
   444
	_use_nodes(false), _use_arcs(false) {}
deba@127
   445
alpar@156
   446
    /// \brief Constructor
alpar@156
   447
    ///
alpar@156
   448
    /// Construct a directed graph reader, which reads from the given
alpar@156
   449
    /// file.
deba@127
   450
    DigraphReader(const std::string& fn, Digraph& digraph) 
deba@127
   451
      : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
deba@127
   452
    	_use_nodes(false), _use_arcs(false) {}
alpar@156
   453
    
alpar@156
   454
    /// \brief Constructor
alpar@156
   455
    ///
alpar@156
   456
    /// Construct a directed graph reader, which reads from the given
alpar@156
   457
    /// file.
deba@127
   458
    DigraphReader(const char* fn, Digraph& digraph) 
deba@127
   459
      : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
deba@127
   460
    	_use_nodes(false), _use_arcs(false) {}
deba@127
   461
alpar@156
   462
    /// \brief Copy constructor
alpar@156
   463
    ///
alpar@156
   464
    /// The copy constructor transfers all data from the other reader,
alpar@156
   465
    /// therefore the copied reader will not be usable more. 
deba@127
   466
    DigraphReader(DigraphReader& other) 
deba@127
   467
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
deba@127
   468
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs) {
deba@127
   469
deba@163
   470
      other._is = 0;
deba@127
   471
      other.local_is = false;
deba@127
   472
      
deba@127
   473
      _node_index.swap(other._node_index);
deba@127
   474
      _arc_index.swap(other._arc_index);
deba@127
   475
deba@127
   476
      _node_maps.swap(other._node_maps);
deba@127
   477
      _arc_maps.swap(other._arc_maps);
deba@127
   478
      _attributes.swap(other._attributes);
deba@127
   479
deba@127
   480
      _nodes_caption = other._nodes_caption;
deba@127
   481
      _arcs_caption = other._arcs_caption;
deba@127
   482
      _attributes_caption = other._attributes_caption;
deba@162
   483
deba@162
   484
      _sections.swap(other._sections);
deba@127
   485
    }
deba@127
   486
alpar@156
   487
    /// \brief Destructor
deba@127
   488
    ~DigraphReader() {
deba@127
   489
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
deba@127
   490
	   it != _node_maps.end(); ++it) {
deba@127
   491
	delete it->second;
deba@127
   492
      }
deba@127
   493
deba@127
   494
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
deba@127
   495
	   it != _arc_maps.end(); ++it) {
deba@127
   496
	delete it->second;
deba@127
   497
      }
deba@127
   498
deba@127
   499
      for (typename Attributes::iterator it = _attributes.begin(); 
deba@127
   500
	   it != _attributes.end(); ++it) {
deba@127
   501
	delete it->second;
deba@127
   502
      }
deba@127
   503
deba@162
   504
      for (typename Sections::iterator it = _sections.begin(); 
deba@162
   505
	   it != _sections.end(); ++it) {
deba@162
   506
	delete it->second;
deba@162
   507
      }
deba@162
   508
deba@127
   509
      if (local_is) {
deba@127
   510
	delete _is;
deba@127
   511
      }
deba@127
   512
deba@127
   513
    }
deba@127
   514
deba@127
   515
  private:
deba@127
   516
    
deba@127
   517
    DigraphReader& operator=(const DigraphReader&);
deba@127
   518
deba@127
   519
  public:
deba@127
   520
alpar@156
   521
    /// \name Reading rules
alpar@156
   522
    /// @{
alpar@156
   523
    
alpar@156
   524
    /// \brief Node map reading rule
alpar@156
   525
    ///
alpar@156
   526
    /// Add a node map reading rule to the reader.
deba@127
   527
    template <typename Map>
deba@127
   528
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
deba@127
   529
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@127
   530
      _reader_bits::MapStorageBase<Node>* storage = 
deba@127
   531
	new _reader_bits::MapStorage<Node, Map>(map);
deba@127
   532
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   533
      return *this;
deba@127
   534
    }
deba@127
   535
alpar@156
   536
    /// \brief Node map reading rule
alpar@156
   537
    ///
alpar@156
   538
    /// Add a node map reading rule with specialized converter to the
alpar@156
   539
    /// reader.
deba@127
   540
    template <typename Map, typename Converter>
deba@127
   541
    DigraphReader& nodeMap(const std::string& caption, Map& map, 
deba@127
   542
			   const Converter& converter = Converter()) {
deba@127
   543
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@127
   544
      _reader_bits::MapStorageBase<Node>* storage = 
deba@127
   545
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   546
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   547
      return *this;
deba@127
   548
    }
deba@127
   549
alpar@156
   550
    /// \brief Arc map reading rule
alpar@156
   551
    ///
alpar@156
   552
    /// Add an arc map reading rule to the reader.
deba@127
   553
    template <typename Map>
deba@127
   554
    DigraphReader& arcMap(const std::string& caption, Map& map) {
deba@127
   555
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
deba@127
   556
      _reader_bits::MapStorageBase<Arc>* storage = 
deba@127
   557
	new _reader_bits::MapStorage<Arc, Map>(map);
deba@127
   558
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   559
      return *this;
deba@127
   560
    }
deba@127
   561
alpar@156
   562
    /// \brief Arc map reading rule
alpar@156
   563
    ///
alpar@156
   564
    /// Add an arc map reading rule with specialized converter to the
alpar@156
   565
    /// reader.
deba@127
   566
    template <typename Map, typename Converter>
deba@127
   567
    DigraphReader& arcMap(const std::string& caption, Map& map, 
deba@127
   568
			  const Converter& converter = Converter()) {
deba@127
   569
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
deba@127
   570
      _reader_bits::MapStorageBase<Arc>* storage = 
deba@127
   571
	new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   572
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   573
      return *this;
deba@127
   574
    }
deba@127
   575
alpar@156
   576
    /// \brief Attribute reading rule
alpar@156
   577
    ///
alpar@156
   578
    /// Add an attribute reading rule to the reader.
deba@127
   579
    template <typename Value>
deba@127
   580
    DigraphReader& attribute(const std::string& caption, Value& value) {
deba@127
   581
      _reader_bits::ValueStorageBase* storage = 
deba@127
   582
	new _reader_bits::ValueStorage<Value>(value);
deba@127
   583
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   584
      return *this;
deba@127
   585
    }
deba@127
   586
alpar@156
   587
    /// \brief Attribute reading rule
alpar@156
   588
    ///
alpar@156
   589
    /// Add an attribute reading rule with specialized converter to the
alpar@156
   590
    /// reader.
deba@127
   591
    template <typename Value, typename Converter>
deba@127
   592
    DigraphReader& attribute(const std::string& caption, Value& value, 
deba@127
   593
			     const Converter& converter = Converter()) {
deba@127
   594
      _reader_bits::ValueStorageBase* storage = 
deba@127
   595
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   596
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   597
      return *this;
deba@127
   598
    }
deba@127
   599
alpar@156
   600
    /// \brief Node reading rule
alpar@156
   601
    ///
alpar@156
   602
    /// Add a node reading rule to reader.
deba@127
   603
    DigraphReader& node(const std::string& caption, Node& node) {
deba@127
   604
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
deba@127
   605
      Converter converter(_node_index);
deba@127
   606
      _reader_bits::ValueStorageBase* storage = 
deba@127
   607
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   608
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   609
      return *this;
deba@127
   610
    }
deba@127
   611
alpar@156
   612
    /// \brief Arc reading rule
alpar@156
   613
    ///
alpar@156
   614
    /// Add an arc reading rule to reader.
deba@127
   615
    DigraphReader& arc(const std::string& caption, Arc& arc) {
deba@127
   616
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
deba@127
   617
      Converter converter(_arc_index);
deba@127
   618
      _reader_bits::ValueStorageBase* storage = 
deba@127
   619
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   620
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   621
      return *this;
deba@127
   622
    }
deba@127
   623
alpar@156
   624
    /// @}
alpar@156
   625
alpar@156
   626
    /// \name Select section by name
alpar@156
   627
    /// @{
alpar@156
   628
alpar@156
   629
    /// \brief Set \c \@nodes section to be read
alpar@156
   630
    ///
alpar@156
   631
    /// Set \c \@nodes section to be read
deba@127
   632
    DigraphReader& nodes(const std::string& caption) {
deba@127
   633
      _nodes_caption = caption;
deba@127
   634
      return *this;
deba@127
   635
    }
deba@127
   636
alpar@156
   637
    /// \brief Set \c \@arcs section to be read
alpar@156
   638
    ///
alpar@156
   639
    /// Set \c \@arcs section to be read
deba@127
   640
    DigraphReader& arcs(const std::string& caption) {
deba@127
   641
      _arcs_caption = caption;
deba@127
   642
      return *this;
deba@127
   643
    }
deba@127
   644
alpar@156
   645
    /// \brief Set \c \@attributes section to be read
alpar@156
   646
    ///
alpar@156
   647
    /// Set \c \@attributes section to be read
deba@127
   648
    DigraphReader& attributes(const std::string& caption) {
deba@127
   649
      _attributes_caption = caption;
deba@127
   650
      return *this;
deba@127
   651
    }
deba@127
   652
alpar@156
   653
    /// @}
alpar@156
   654
deba@162
   655
    /// \name Section readers
deba@162
   656
    /// @{
deba@162
   657
deba@162
   658
    /// \brief Add a section processor with line oriented reading
deba@162
   659
    ///
deba@162
   660
    /// In the \e LGF file extra sections can be placed, which contain
deba@162
   661
    /// any data in arbitrary format. These sections can be read with
deba@162
   662
    /// this function line by line. The first parameter is the type
deba@162
   663
    /// descriptor of the section, the second is a functor, which
deba@162
   664
    /// takes just one \c std::string parameter. At the reading
deba@162
   665
    /// process, each line of the section will be given to the functor
deba@162
   666
    /// object. However, the empty lines and the comment lines are
deba@162
   667
    /// filtered out, and the leading whitespaces are stipped from
deba@162
   668
    /// each processed string.
deba@162
   669
    ///
deba@162
   670
    /// For example let's see a section, which contain several
deba@162
   671
    /// integers, which should be inserted into a vector.
deba@162
   672
    ///\code
deba@162
   673
    ///  @numbers
deba@162
   674
    ///  12 45 23
deba@162
   675
    ///  4
deba@162
   676
    ///  23 6
deba@162
   677
    ///\endcode
deba@162
   678
    ///
deba@162
   679
    /// The functor is implemented as an struct:
deba@162
   680
    ///\code
deba@162
   681
    ///  struct NumberSection {
deba@162
   682
    ///    std::vector<int>& _data;
deba@162
   683
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
deba@162
   684
    ///    void operator()(const std::string& line) {
deba@162
   685
    ///      std::istringstream ls(line);
deba@162
   686
    ///      int value;
deba@162
   687
    ///      while (ls >> value) _data.push_back(value);
deba@162
   688
    ///    }
deba@162
   689
    ///  };
deba@162
   690
    ///
deba@162
   691
    ///  // ...
deba@162
   692
    ///
deba@162
   693
    ///  reader.sectionLines("numbers", NumberSection(vec));  
deba@162
   694
    ///\endcode
deba@162
   695
    template <typename Functor>
deba@162
   696
    DigraphReader& sectionLines(const std::string& type, Functor functor) {
deba@162
   697
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
deba@162
   698
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
deba@162
   699
		   "Multiple reading of section.");
deba@162
   700
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
deba@162
   701
		   type != "attributes", "Multiple reading of section.");
deba@162
   702
      _sections.insert(std::make_pair(type, 
deba@162
   703
        new _reader_bits::LineSection<Functor>(functor)));
deba@162
   704
      return *this;
deba@162
   705
    }
deba@162
   706
deba@162
   707
deba@162
   708
    /// \brief Add a section processor with stream oriented reading
deba@162
   709
    ///
deba@162
   710
    /// In the \e LGF file extra sections can be placed, which contain
deba@162
   711
    /// any data in arbitrary format. These sections can be read
deba@162
   712
    /// directly with this function. The first parameter is the type
deba@162
   713
    /// of the section, the second is a functor, which takes an \c
deba@162
   714
    /// std::istream& and an int& parameter, the latter regard to the
deba@162
   715
    /// line number of stream. The functor can read the input while
deba@162
   716
    /// the section go on, and the line number should be modified
deba@162
   717
    /// accordingly.
deba@162
   718
    template <typename Functor>
deba@162
   719
    DigraphReader& sectionStream(const std::string& type, Functor functor) {
deba@162
   720
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
deba@162
   721
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
deba@162
   722
		   "Multiple reading of section.");
deba@162
   723
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
deba@162
   724
		   type != "attributes", "Multiple reading of section.");
deba@162
   725
      _sections.insert(std::make_pair(type, 
deba@162
   726
	 new _reader_bits::StreamSection<Functor>(functor)));
deba@162
   727
      return *this;
deba@162
   728
    }    
deba@162
   729
    
deba@162
   730
    /// @}
deba@162
   731
alpar@156
   732
    /// \name Using previously constructed node or arc set
alpar@156
   733
    /// @{
alpar@156
   734
alpar@156
   735
    /// \brief Use previously constructed node set
alpar@156
   736
    ///
alpar@156
   737
    /// Use previously constructed node set, and specify the node
alpar@156
   738
    /// label map.
deba@127
   739
    template <typename Map>
deba@127
   740
    DigraphReader& useNodes(const Map& map) {
deba@127
   741
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   742
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
deba@127
   743
      _use_nodes = true;
deba@127
   744
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@127
   745
      for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@127
   746
	_node_index.insert(std::make_pair(converter(map[n]), n));
deba@127
   747
      }
deba@127
   748
      return *this;
deba@127
   749
    }
deba@127
   750
alpar@156
   751
    /// \brief Use previously constructed node set
alpar@156
   752
    ///
alpar@156
   753
    /// Use previously constructed node set, and specify the node
alpar@156
   754
    /// label map and a functor which converts the label map values to
alpar@156
   755
    /// std::string.
deba@127
   756
    template <typename Map, typename Converter>
deba@127
   757
    DigraphReader& useNodes(const Map& map, 
deba@127
   758
			    const Converter& converter = Converter()) {
deba@127
   759
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   760
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
deba@127
   761
      _use_nodes = true;
deba@127
   762
      for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@127
   763
	_node_index.insert(std::make_pair(converter(map[n]), n));
deba@127
   764
      }
deba@127
   765
      return *this;
deba@127
   766
    }
deba@127
   767
alpar@156
   768
    /// \brief Use previously constructed arc set
alpar@156
   769
    ///
alpar@156
   770
    /// Use previously constructed arc set, and specify the arc
alpar@156
   771
    /// label map.
deba@127
   772
    template <typename Map>
deba@127
   773
    DigraphReader& useArcs(const Map& map) {
deba@127
   774
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   775
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
deba@127
   776
      _use_arcs = true;
deba@127
   777
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@127
   778
      for (ArcIt a(_digraph); a != INVALID; ++a) {
deba@127
   779
	_arc_index.insert(std::make_pair(converter(map[a]), a));
deba@127
   780
      }
deba@127
   781
      return *this;
deba@127
   782
    }
deba@127
   783
alpar@156
   784
    /// \brief Use previously constructed arc set
alpar@156
   785
    ///
alpar@156
   786
    /// Use previously constructed arc set, and specify the arc
alpar@156
   787
    /// label map and a functor which converts the label map values to
alpar@156
   788
    /// std::string.
deba@127
   789
    template <typename Map, typename Converter>
deba@127
   790
    DigraphReader& useArcs(const Map& map, 
deba@127
   791
			    const Converter& converter = Converter()) {
deba@127
   792
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   793
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); 
deba@127
   794
      _use_arcs = true;
deba@127
   795
      for (ArcIt a(_digraph); a != INVALID; ++a) {
deba@127
   796
	_arc_index.insert(std::make_pair(converter(map[a]), a));
deba@127
   797
      }
deba@127
   798
      return *this;
deba@127
   799
    }
deba@127
   800
alpar@156
   801
    /// @}
alpar@156
   802
deba@127
   803
  private:
deba@127
   804
deba@127
   805
    bool readLine() {
deba@127
   806
      std::string str;
deba@127
   807
      while(++line_num, std::getline(*_is, str)) {
deba@127
   808
	line.clear(); line.str(str);
deba@127
   809
	char c;
deba@127
   810
	if (line >> std::ws >> c && c != '#') {
deba@127
   811
	  line.putback(c);
deba@127
   812
	  return true;
deba@127
   813
	}
deba@127
   814
      }
deba@127
   815
      return false;
deba@127
   816
    }
deba@127
   817
deba@127
   818
    bool readSuccess() {
deba@127
   819
      return static_cast<bool>(*_is);
deba@127
   820
    }
deba@127
   821
    
deba@127
   822
    void skipSection() {
deba@127
   823
      char c;
deba@127
   824
      while (readSuccess() && line >> c && c != '@') {
deba@127
   825
	readLine();
deba@127
   826
      }
deba@127
   827
      line.putback(c);
deba@127
   828
    }
deba@127
   829
deba@127
   830
    void readNodes() {
deba@127
   831
deba@127
   832
      std::vector<int> map_index(_node_maps.size());
deba@127
   833
      int map_num, label_index;
deba@127
   834
deba@127
   835
      if (!readLine()) 
deba@127
   836
	throw DataFormatError("Cannot find map captions");
deba@127
   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@127
   866
	  if (jt == maps.end())
deba@127
   867
	    throw DataFormatError("Label map not found in file");
deba@127
   868
	  label_index = jt->second;
deba@127
   869
	}
deba@127
   870
	map_num = maps.size();
deba@127
   871
      }
deba@127
   872
deba@127
   873
      char c;
deba@127
   874
      while (readLine() && line >> c && c != '@') {
deba@127
   875
	line.putback(c);
deba@127
   876
deba@127
   877
	std::vector<std::string> tokens(map_num);
deba@127
   878
	for (int i = 0; i < map_num; ++i) {
deba@127
   879
	  if (!_reader_bits::readToken(line, tokens[i])) {
deba@127
   880
	    std::ostringstream msg;
deba@127
   881
	    msg << "Column not found (" << i + 1 << ")";
deba@127
   882
	    throw DataFormatError(msg.str().c_str());
deba@127
   883
	  }
deba@127
   884
	}
deba@127
   885
	if (line >> std::ws >> c)
deba@127
   886
	  throw DataFormatError("Extra character on the end of line");
deba@127
   887
	
deba@127
   888
	Node n;
deba@127
   889
	if (!_use_nodes) {
deba@127
   890
	  n = _digraph.addNode();
deba@127
   891
	  _node_index.insert(std::make_pair(tokens[label_index], n));
deba@127
   892
	} else {
deba@127
   893
	  typename std::map<std::string, Node>::iterator it =
deba@127
   894
	    _node_index.find(tokens[label_index]);
deba@127
   895
	  if (it == _node_index.end()) {
deba@127
   896
	    std::ostringstream msg;
deba@127
   897
	    msg << "Node with label not found: " << tokens[label_index];
deba@127
   898
	    throw DataFormatError(msg.str().c_str());	    
deba@127
   899
	  }
deba@127
   900
	  n = it->second;
deba@127
   901
	}
deba@127
   902
deba@127
   903
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
deba@127
   904
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
deba@127
   905
	}
deba@127
   906
deba@127
   907
      }
deba@127
   908
      if (readSuccess()) {
deba@127
   909
	line.putback(c);
deba@127
   910
      }
deba@127
   911
    }
deba@127
   912
deba@127
   913
    void readArcs() {
deba@127
   914
deba@127
   915
      std::vector<int> map_index(_arc_maps.size());
deba@127
   916
      int map_num, label_index;
deba@127
   917
deba@127
   918
      if (!readLine()) 
deba@127
   919
	throw DataFormatError("Cannot find map captions");
deba@127
   920
      
deba@127
   921
      {
deba@127
   922
	std::map<std::string, int> maps;
deba@127
   923
	
deba@127
   924
	std::string map;
deba@127
   925
	int index = 0;
alpar@156
   926
	while (_reader_bits::readToken(line, map)) {
deba@127
   927
	  if (maps.find(map) != maps.end()) {
deba@127
   928
	    std::ostringstream msg;
deba@127
   929
	    msg << "Multiple occurence of arc map: " << map;
deba@127
   930
	    throw DataFormatError(msg.str().c_str());
deba@127
   931
	  }
deba@127
   932
	  maps.insert(std::make_pair(map, index));
deba@127
   933
	  ++index;
deba@127
   934
	}
deba@127
   935
	
deba@127
   936
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
deba@127
   937
	  std::map<std::string, int>::iterator jt = 
deba@127
   938
	    maps.find(_arc_maps[i].first);
deba@127
   939
	  if (jt == maps.end()) {
deba@127
   940
	    std::ostringstream msg;
deba@127
   941
	    msg << "Map not found in file: " << _arc_maps[i].first;
deba@127
   942
	    throw DataFormatError(msg.str().c_str());
deba@127
   943
	  }
deba@127
   944
	  map_index[i] = jt->second;
deba@127
   945
	}
deba@127
   946
deba@127
   947
	{
deba@127
   948
	  std::map<std::string, int>::iterator jt = maps.find("label");
deba@127
   949
	  if (jt == maps.end())
deba@127
   950
	    throw DataFormatError("Label map not found in file");
deba@127
   951
	  label_index = jt->second;
deba@127
   952
	}
deba@127
   953
	map_num = maps.size();
deba@127
   954
      }
deba@127
   955
deba@127
   956
      char c;
deba@127
   957
      while (readLine() && line >> c && c != '@') {
deba@127
   958
	line.putback(c);
deba@127
   959
deba@127
   960
	std::string source_token;
deba@127
   961
	std::string target_token;
deba@127
   962
deba@127
   963
	if (!_reader_bits::readToken(line, source_token))
deba@127
   964
	  throw DataFormatError("Source not found");
deba@127
   965
deba@127
   966
	if (!_reader_bits::readToken(line, target_token))
deba@127
   967
	  throw DataFormatError("Source not found");
deba@127
   968
	
deba@127
   969
	std::vector<std::string> tokens(map_num);
deba@127
   970
	for (int i = 0; i < map_num; ++i) {
deba@127
   971
	  if (!_reader_bits::readToken(line, tokens[i])) {
deba@127
   972
	    std::ostringstream msg;
deba@127
   973
	    msg << "Column not found (" << i + 1 << ")";
deba@127
   974
	    throw DataFormatError(msg.str().c_str());
deba@127
   975
	  }
deba@127
   976
	}
deba@127
   977
	if (line >> std::ws >> c)
deba@127
   978
	  throw DataFormatError("Extra character on the end of line");
deba@127
   979
	
deba@127
   980
	Arc a;
deba@127
   981
	if (!_use_arcs) {
deba@127
   982
deba@127
   983
          typename NodeIndex::iterator it;
deba@127
   984
 
deba@127
   985
          it = _node_index.find(source_token);
deba@127
   986
          if (it == _node_index.end()) {
deba@127
   987
            std::ostringstream msg;
deba@127
   988
            msg << "Item not found: " << source_token;
deba@127
   989
            throw DataFormatError(msg.str().c_str());
deba@127
   990
          }
deba@127
   991
          Node source = it->second;
deba@127
   992
deba@127
   993
          it = _node_index.find(target_token);
deba@127
   994
          if (it == _node_index.end()) {       
deba@127
   995
            std::ostringstream msg;            
deba@127
   996
            msg << "Item not found: " << target_token;
deba@127
   997
            throw DataFormatError(msg.str().c_str());
deba@127
   998
          }                                          
deba@127
   999
          Node target = it->second;                            
deba@127
  1000
deba@127
  1001
	  a = _digraph.addArc(source, target);
deba@127
  1002
	  _arc_index.insert(std::make_pair(tokens[label_index], a));
deba@127
  1003
	} else {
deba@127
  1004
	  typename std::map<std::string, Arc>::iterator it =
deba@127
  1005
	    _arc_index.find(tokens[label_index]);
deba@127
  1006
	  if (it == _arc_index.end()) {
deba@127
  1007
	    std::ostringstream msg;
deba@127
  1008
	    msg << "Arc with label not found: " << tokens[label_index];
deba@127
  1009
	    throw DataFormatError(msg.str().c_str());	    
deba@127
  1010
	  }
deba@127
  1011
	  a = it->second;
deba@127
  1012
	}
deba@127
  1013
deba@127
  1014
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
deba@127
  1015
	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
deba@127
  1016
	}
deba@127
  1017
deba@127
  1018
      }
deba@127
  1019
      if (readSuccess()) {
deba@127
  1020
	line.putback(c);
deba@127
  1021
      }
deba@127
  1022
    }
deba@127
  1023
deba@127
  1024
    void readAttributes() {
deba@127
  1025
deba@127
  1026
      std::set<std::string> read_attr;
deba@127
  1027
deba@127
  1028
      char c;
deba@127
  1029
      while (readLine() && line >> c && c != '@') {
deba@127
  1030
	line.putback(c);
deba@127
  1031
	
deba@127
  1032
	std::string attr, token;
alpar@156
  1033
	if (!_reader_bits::readToken(line, attr))
deba@127
  1034
	  throw DataFormatError("Attribute name not found");
deba@127
  1035
	if (!_reader_bits::readToken(line, token))
deba@127
  1036
	  throw DataFormatError("Attribute value not found");
deba@127
  1037
	if (line >> c)
deba@127
  1038
	  throw DataFormatError("Extra character on the end of line");	  
deba@127
  1039
deba@127
  1040
	{
deba@127
  1041
	  std::set<std::string>::iterator it = read_attr.find(attr);
deba@127
  1042
	  if (it != read_attr.end()) {
deba@127
  1043
	    std::ostringstream msg;
deba@127
  1044
	    msg << "Multiple occurence of attribute " << attr;
deba@127
  1045
	    throw DataFormatError(msg.str().c_str());
deba@127
  1046
	  }
deba@127
  1047
	  read_attr.insert(attr);
deba@127
  1048
	}
deba@127
  1049
	
deba@127
  1050
	{
deba@127
  1051
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
deba@127
  1052
	  while (it != _attributes.end() && it->first == attr) {
deba@127
  1053
	    it->second->set(token);
deba@127
  1054
	    ++it;
deba@127
  1055
	  }
deba@127
  1056
	}
deba@127
  1057
deba@127
  1058
      }
deba@127
  1059
      if (readSuccess()) {
deba@127
  1060
	line.putback(c);
deba@127
  1061
      }
deba@127
  1062
      for (typename Attributes::iterator it = _attributes.begin();
deba@127
  1063
	   it != _attributes.end(); ++it) {
deba@127
  1064
	if (read_attr.find(it->first) == read_attr.end()) {
deba@127
  1065
	  std::ostringstream msg;
deba@127
  1066
	  msg << "Attribute not found in file: " << it->first;
deba@127
  1067
	  throw DataFormatError(msg.str().c_str());
deba@127
  1068
	}	
deba@127
  1069
      }
deba@127
  1070
    }
deba@127
  1071
deba@127
  1072
  public:
alpar@156
  1073
alpar@156
  1074
    /// \name Execution of the reader    
alpar@156
  1075
    /// @{
alpar@156
  1076
alpar@156
  1077
    /// \brief Start the batch processing
alpar@156
  1078
    ///
alpar@156
  1079
    /// This function starts the batch processing
deba@127
  1080
    void run() {
deba@127
  1081
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
deba@163
  1082
      if (!*_is) {
deba@163
  1083
	throw DataFormatError("Cannot find file");
deba@163
  1084
      }
deba@127
  1085
      
deba@127
  1086
      bool nodes_done = false;
deba@127
  1087
      bool arcs_done = false;
deba@127
  1088
      bool attributes_done = false;
deba@162
  1089
      std::set<std::string> extra_sections;
deba@127
  1090
deba@127
  1091
      line_num = 0;      
deba@127
  1092
      readLine();
deba@127
  1093
deba@127
  1094
      while (readSuccess()) {
deba@127
  1095
	skipSection();
deba@127
  1096
	try {
deba@127
  1097
	  char c;
deba@127
  1098
	  std::string section, caption;
deba@127
  1099
	  line >> c;
alpar@156
  1100
	  _reader_bits::readToken(line, section);
alpar@156
  1101
	  _reader_bits::readToken(line, caption);
deba@127
  1102
deba@127
  1103
	  if (line >> c) 
deba@127
  1104
	    throw DataFormatError("Extra character on the end of line");
deba@127
  1105
deba@127
  1106
	  if (section == "nodes" && !nodes_done) {
deba@127
  1107
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
deba@127
  1108
	      readNodes();
deba@127
  1109
	      nodes_done = true;
deba@127
  1110
	    }
deba@127
  1111
	  } else if ((section == "arcs" || section == "edges") && 
deba@127
  1112
		     !arcs_done) {
deba@127
  1113
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
deba@127
  1114
	      readArcs();
deba@127
  1115
	      arcs_done = true;
deba@127
  1116
	    }
deba@127
  1117
	  } else if (section == "attributes" && !attributes_done) {
deba@127
  1118
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
deba@127
  1119
	      readAttributes();
deba@127
  1120
	      attributes_done = true;
deba@127
  1121
	    }
deba@127
  1122
	  } else {
deba@162
  1123
	    if (extra_sections.find(section) != extra_sections.end()) {
deba@162
  1124
	      std::ostringstream msg;
deba@162
  1125
	      msg << "Multiple occurence of section " << section;
deba@162
  1126
	      throw DataFormatError(msg.str().c_str());
deba@162
  1127
	    }
deba@162
  1128
	    Sections::iterator it = _sections.find(section);
deba@162
  1129
	    if (it != _sections.end()) {
deba@162
  1130
	      extra_sections.insert(section);
deba@162
  1131
	      it->second->process(*_is, line_num);
deba@162
  1132
	      readLine();
deba@162
  1133
	    } else {
deba@162
  1134
	      readLine();
deba@162
  1135
	      skipSection();
deba@162
  1136
	    }
deba@127
  1137
	  }
deba@127
  1138
	} catch (DataFormatError& error) {
deba@127
  1139
	  error.line(line_num);
deba@127
  1140
	  throw;
deba@127
  1141
	}	
deba@127
  1142
      }
deba@127
  1143
deba@127
  1144
      if (!nodes_done) {
deba@127
  1145
	throw DataFormatError("Section @nodes not found");
deba@127
  1146
      }
deba@127
  1147
deba@127
  1148
      if (!arcs_done) {
deba@127
  1149
	throw DataFormatError("Section @arcs not found");
deba@127
  1150
      }
deba@127
  1151
deba@127
  1152
      if (!attributes_done && !_attributes.empty()) {
deba@127
  1153
	throw DataFormatError("Section @attributes not found");
deba@127
  1154
      }
deba@127
  1155
deba@127
  1156
    }
alpar@156
  1157
alpar@156
  1158
    /// @}
deba@127
  1159
    
deba@127
  1160
  };
deba@127
  1161
alpar@156
  1162
  /// \relates DigraphReader
deba@127
  1163
  template <typename Digraph>
deba@127
  1164
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
deba@163
  1165
    DigraphReader<Digraph> tmp(is, digraph);
deba@163
  1166
    return tmp;
deba@127
  1167
  }
deba@127
  1168
alpar@156
  1169
  /// \relates DigraphReader
deba@127
  1170
  template <typename Digraph>
deba@127
  1171
  DigraphReader<Digraph> digraphReader(const std::string& fn, 
deba@127
  1172
				       Digraph& digraph) {
deba@163
  1173
    DigraphReader<Digraph> tmp(fn, digraph);
deba@163
  1174
    return tmp;
deba@127
  1175
  }
deba@127
  1176
alpar@156
  1177
  /// \relates DigraphReader
deba@127
  1178
  template <typename Digraph>
deba@127
  1179
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
deba@163
  1180
    DigraphReader<Digraph> tmp(fn, digraph);
deba@163
  1181
    return tmp;
deba@127
  1182
  }
deba@127
  1183
}
deba@127
  1184
deba@127
  1185
#endif