lemon/lgf_reader.h
author Alpar Juttner <alpar@cs.elte.hu>
Sat, 17 May 2008 06:30:02 +0100
changeset 156 e561aa7675de
parent 148 4e2581021300
child 162 33247f6fff16
permissions -rw-r--r--
More flexible header names in .lgf + largely improved doc
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@127
   271
    
deba@127
   272
  }
alpar@156
   273
alpar@156
   274
  /// \ingroup lemon_io
alpar@156
   275
  ///  
alpar@156
   276
  /// \brief LGF reader for directed graphs
alpar@156
   277
  ///
alpar@156
   278
  /// This utility reads an \ref lgf-format "LGF" file.
alpar@156
   279
  ///
alpar@156
   280
  /// The reading method does a batch processing. The user creates a
alpar@156
   281
  /// reader object, then various reading rules can be added to the
alpar@156
   282
  /// reader, and eventually the reading is executed with the \c run()
alpar@156
   283
  /// member function. A map reading rule can be added to the reader
alpar@156
   284
  /// with the \c nodeMap() or \c arcMap() members. An optional
alpar@156
   285
  /// converter parameter can also be added as a standard functor converting from
alpar@156
   286
  /// std::string to the value type of the map. If it is set, it will
alpar@156
   287
  /// determine how the tokens in the file should be is converted to the map's
alpar@156
   288
  /// value type. If the functor is not set, then a default conversion
alpar@156
   289
  /// will be used. One map can be read into multiple map objects at the
alpar@156
   290
  /// same time. The \c attribute(), \c node() and \c arc() functions
alpar@156
   291
  /// are used to add attribute reading rules.
alpar@156
   292
  ///
alpar@156
   293
  ///\code
alpar@156
   294
  ///     DigraphReader<Digraph>(std::cin, digraph).
alpar@156
   295
  ///       nodeMap("coordinates", coord_map).
alpar@156
   296
  ///       arcMap("capacity", cap_map).
alpar@156
   297
  ///       node("source", src).
alpar@156
   298
  ///       node("target", trg).
alpar@156
   299
  ///       attribute("caption", caption).
alpar@156
   300
  ///       run();
alpar@156
   301
  ///\endcode
alpar@156
   302
  ///
alpar@156
   303
  /// By default the reader uses the first section in the file of the
alpar@156
   304
  /// proper type. If a section has an optional name, then it can be
alpar@156
   305
  /// selected for reading by giving an optional name parameter to
alpar@156
   306
  /// the \c nodes(), \c arcs() or \c attributes()
alpar@156
   307
  /// functions.
alpar@156
   308
  ///
alpar@156
   309
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
alpar@156
   310
  /// that the nodes or arcs should not be constructed (added to the
alpar@156
   311
  /// graph) during the reading, but instead the label map of the items
alpar@156
   312
  /// are given as a parameter of these functions. An
alpar@156
   313
  /// application of these function is multipass reading, which is
alpar@156
   314
  /// important if two \e \@arcs sections must be read from the
alpar@156
   315
  /// file. In this example the first phase would read the node set and one
alpar@156
   316
  /// of the arc sets, while the second phase would read the second arc
alpar@156
   317
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
alpar@156
   318
  /// The previously read label node map should be passed to the \c
alpar@156
   319
  /// useNodes() functions. Another application of multipass reading when
alpar@156
   320
  /// paths are given as a node map or an arc map. It is impossible read this in
alpar@156
   321
  /// a single pass, because the arcs are not constructed when the node
alpar@156
   322
  /// maps are read.
deba@127
   323
  template <typename _Digraph>
deba@127
   324
  class DigraphReader {
deba@127
   325
  public:
deba@127
   326
deba@127
   327
    typedef _Digraph Digraph;
deba@148
   328
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
deba@127
   329
    
deba@127
   330
  private:
deba@127
   331
deba@127
   332
deba@127
   333
    std::istream* _is;
deba@127
   334
    bool local_is;
deba@127
   335
deba@127
   336
    Digraph& _digraph;
deba@127
   337
deba@127
   338
    std::string _nodes_caption;
deba@127
   339
    std::string _arcs_caption;
deba@127
   340
    std::string _attributes_caption;
deba@127
   341
deba@127
   342
    typedef std::map<std::string, Node> NodeIndex;
deba@127
   343
    NodeIndex _node_index;
deba@127
   344
    typedef std::map<std::string, Arc> ArcIndex;
deba@127
   345
    ArcIndex _arc_index;
deba@127
   346
    
deba@127
   347
    typedef std::vector<std::pair<std::string, 
deba@127
   348
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
deba@127
   349
    NodeMaps _node_maps; 
deba@127
   350
deba@127
   351
    typedef std::vector<std::pair<std::string,
deba@127
   352
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
deba@127
   353
    ArcMaps _arc_maps;
deba@127
   354
deba@127
   355
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
deba@127
   356
      Attributes;
deba@127
   357
    Attributes _attributes;
deba@127
   358
deba@127
   359
    bool _use_nodes;
deba@127
   360
    bool _use_arcs;
deba@127
   361
deba@127
   362
    int line_num;
deba@127
   363
    std::istringstream line;
deba@127
   364
deba@127
   365
  public:
deba@127
   366
alpar@156
   367
    /// \brief Constructor
alpar@156
   368
    ///
alpar@156
   369
    /// Construct a directed graph reader, which reads from the given
alpar@156
   370
    /// input stream.
deba@127
   371
    DigraphReader(std::istream& is, Digraph& digraph) 
deba@127
   372
      : _is(&is), local_is(false), _digraph(digraph),
deba@127
   373
	_use_nodes(false), _use_arcs(false) {}
deba@127
   374
alpar@156
   375
    /// \brief Constructor
alpar@156
   376
    ///
alpar@156
   377
    /// Construct a directed graph reader, which reads from the given
alpar@156
   378
    /// file.
deba@127
   379
    DigraphReader(const std::string& fn, Digraph& digraph) 
deba@127
   380
      : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
deba@127
   381
    	_use_nodes(false), _use_arcs(false) {}
alpar@156
   382
    
alpar@156
   383
    /// \brief Constructor
alpar@156
   384
    ///
alpar@156
   385
    /// Construct a directed graph reader, which reads from the given
alpar@156
   386
    /// file.
deba@127
   387
    DigraphReader(const char* fn, Digraph& digraph) 
deba@127
   388
      : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
deba@127
   389
    	_use_nodes(false), _use_arcs(false) {}
deba@127
   390
alpar@156
   391
    /// \brief Copy constructor
alpar@156
   392
    ///
alpar@156
   393
    /// The copy constructor transfers all data from the other reader,
alpar@156
   394
    /// therefore the copied reader will not be usable more. 
deba@127
   395
    DigraphReader(DigraphReader& other) 
deba@127
   396
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
deba@127
   397
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs) {
deba@127
   398
deba@127
   399
      other.is = 0;
deba@127
   400
      other.local_is = false;
deba@127
   401
      
deba@127
   402
      _node_index.swap(other._node_index);
deba@127
   403
      _arc_index.swap(other._arc_index);
deba@127
   404
deba@127
   405
      _node_maps.swap(other._node_maps);
deba@127
   406
      _arc_maps.swap(other._arc_maps);
deba@127
   407
      _attributes.swap(other._attributes);
deba@127
   408
deba@127
   409
      _nodes_caption = other._nodes_caption;
deba@127
   410
      _arcs_caption = other._arcs_caption;
deba@127
   411
      _attributes_caption = other._attributes_caption;
deba@127
   412
    }
deba@127
   413
alpar@156
   414
    /// \brief Destructor
deba@127
   415
    ~DigraphReader() {
deba@127
   416
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
deba@127
   417
	   it != _node_maps.end(); ++it) {
deba@127
   418
	delete it->second;
deba@127
   419
      }
deba@127
   420
deba@127
   421
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
deba@127
   422
	   it != _arc_maps.end(); ++it) {
deba@127
   423
	delete it->second;
deba@127
   424
      }
deba@127
   425
deba@127
   426
      for (typename Attributes::iterator it = _attributes.begin(); 
deba@127
   427
	   it != _attributes.end(); ++it) {
deba@127
   428
	delete it->second;
deba@127
   429
      }
deba@127
   430
deba@127
   431
      if (local_is) {
deba@127
   432
	delete _is;
deba@127
   433
      }
deba@127
   434
deba@127
   435
    }
deba@127
   436
deba@127
   437
  private:
deba@127
   438
    
deba@127
   439
    DigraphReader& operator=(const DigraphReader&);
deba@127
   440
deba@127
   441
  public:
deba@127
   442
alpar@156
   443
    /// \name Reading rules
alpar@156
   444
    /// @{
alpar@156
   445
    
alpar@156
   446
    /// \brief Node map reading rule
alpar@156
   447
    ///
alpar@156
   448
    /// Add a node map reading rule to the reader.
deba@127
   449
    template <typename Map>
deba@127
   450
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
deba@127
   451
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@127
   452
      _reader_bits::MapStorageBase<Node>* storage = 
deba@127
   453
	new _reader_bits::MapStorage<Node, Map>(map);
deba@127
   454
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   455
      return *this;
deba@127
   456
    }
deba@127
   457
alpar@156
   458
    /// \brief Node map reading rule
alpar@156
   459
    ///
alpar@156
   460
    /// Add a node map reading rule with specialized converter to the
alpar@156
   461
    /// reader.
deba@127
   462
    template <typename Map, typename Converter>
deba@127
   463
    DigraphReader& nodeMap(const std::string& caption, Map& map, 
deba@127
   464
			   const Converter& converter = Converter()) {
deba@127
   465
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
deba@127
   466
      _reader_bits::MapStorageBase<Node>* storage = 
deba@127
   467
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   468
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   469
      return *this;
deba@127
   470
    }
deba@127
   471
alpar@156
   472
    /// \brief Arc map reading rule
alpar@156
   473
    ///
alpar@156
   474
    /// Add an arc map reading rule to the reader.
deba@127
   475
    template <typename Map>
deba@127
   476
    DigraphReader& arcMap(const std::string& caption, Map& map) {
deba@127
   477
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
deba@127
   478
      _reader_bits::MapStorageBase<Arc>* storage = 
deba@127
   479
	new _reader_bits::MapStorage<Arc, Map>(map);
deba@127
   480
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   481
      return *this;
deba@127
   482
    }
deba@127
   483
alpar@156
   484
    /// \brief Arc map reading rule
alpar@156
   485
    ///
alpar@156
   486
    /// Add an arc map reading rule with specialized converter to the
alpar@156
   487
    /// reader.
deba@127
   488
    template <typename Map, typename Converter>
deba@127
   489
    DigraphReader& arcMap(const std::string& caption, Map& map, 
deba@127
   490
			  const Converter& converter = Converter()) {
deba@127
   491
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
deba@127
   492
      _reader_bits::MapStorageBase<Arc>* storage = 
deba@127
   493
	new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   494
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   495
      return *this;
deba@127
   496
    }
deba@127
   497
alpar@156
   498
    /// \brief Attribute reading rule
alpar@156
   499
    ///
alpar@156
   500
    /// Add an attribute reading rule to the reader.
deba@127
   501
    template <typename Value>
deba@127
   502
    DigraphReader& attribute(const std::string& caption, Value& value) {
deba@127
   503
      _reader_bits::ValueStorageBase* storage = 
deba@127
   504
	new _reader_bits::ValueStorage<Value>(value);
deba@127
   505
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   506
      return *this;
deba@127
   507
    }
deba@127
   508
alpar@156
   509
    /// \brief Attribute reading rule
alpar@156
   510
    ///
alpar@156
   511
    /// Add an attribute reading rule with specialized converter to the
alpar@156
   512
    /// reader.
deba@127
   513
    template <typename Value, typename Converter>
deba@127
   514
    DigraphReader& attribute(const std::string& caption, Value& value, 
deba@127
   515
			     const Converter& converter = Converter()) {
deba@127
   516
      _reader_bits::ValueStorageBase* storage = 
deba@127
   517
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   518
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   519
      return *this;
deba@127
   520
    }
deba@127
   521
alpar@156
   522
    /// \brief Node reading rule
alpar@156
   523
    ///
alpar@156
   524
    /// Add a node reading rule to reader.
deba@127
   525
    DigraphReader& node(const std::string& caption, Node& node) {
deba@127
   526
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
deba@127
   527
      Converter converter(_node_index);
deba@127
   528
      _reader_bits::ValueStorageBase* storage = 
deba@127
   529
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   530
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   531
      return *this;
deba@127
   532
    }
deba@127
   533
alpar@156
   534
    /// \brief Arc reading rule
alpar@156
   535
    ///
alpar@156
   536
    /// Add an arc reading rule to reader.
deba@127
   537
    DigraphReader& arc(const std::string& caption, Arc& arc) {
deba@127
   538
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
deba@127
   539
      Converter converter(_arc_index);
deba@127
   540
      _reader_bits::ValueStorageBase* storage = 
deba@127
   541
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   542
      _attributes.insert(std::make_pair(caption, storage));
deba@127
   543
      return *this;
deba@127
   544
    }
deba@127
   545
alpar@156
   546
    /// @}
alpar@156
   547
alpar@156
   548
    /// \name Select section by name
alpar@156
   549
    /// @{
alpar@156
   550
alpar@156
   551
    /// \brief Set \c \@nodes section to be read
alpar@156
   552
    ///
alpar@156
   553
    /// Set \c \@nodes section to be read
deba@127
   554
    DigraphReader& nodes(const std::string& caption) {
deba@127
   555
      _nodes_caption = caption;
deba@127
   556
      return *this;
deba@127
   557
    }
deba@127
   558
alpar@156
   559
    /// \brief Set \c \@arcs section to be read
alpar@156
   560
    ///
alpar@156
   561
    /// Set \c \@arcs section to be read
deba@127
   562
    DigraphReader& arcs(const std::string& caption) {
deba@127
   563
      _arcs_caption = caption;
deba@127
   564
      return *this;
deba@127
   565
    }
deba@127
   566
alpar@156
   567
    /// \brief Set \c \@attributes section to be read
alpar@156
   568
    ///
alpar@156
   569
    /// Set \c \@attributes section to be read
deba@127
   570
    DigraphReader& attributes(const std::string& caption) {
deba@127
   571
      _attributes_caption = caption;
deba@127
   572
      return *this;
deba@127
   573
    }
deba@127
   574
alpar@156
   575
    /// @}
alpar@156
   576
alpar@156
   577
    /// \name Using previously constructed node or arc set
alpar@156
   578
    /// @{
alpar@156
   579
alpar@156
   580
    /// \brief Use previously constructed node set
alpar@156
   581
    ///
alpar@156
   582
    /// Use previously constructed node set, and specify the node
alpar@156
   583
    /// label map.
deba@127
   584
    template <typename Map>
deba@127
   585
    DigraphReader& useNodes(const Map& map) {
deba@127
   586
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   587
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
deba@127
   588
      _use_nodes = true;
deba@127
   589
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@127
   590
      for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@127
   591
	_node_index.insert(std::make_pair(converter(map[n]), n));
deba@127
   592
      }
deba@127
   593
      return *this;
deba@127
   594
    }
deba@127
   595
alpar@156
   596
    /// \brief Use previously constructed node set
alpar@156
   597
    ///
alpar@156
   598
    /// Use previously constructed node set, and specify the node
alpar@156
   599
    /// label map and a functor which converts the label map values to
alpar@156
   600
    /// std::string.
deba@127
   601
    template <typename Map, typename Converter>
deba@127
   602
    DigraphReader& useNodes(const Map& map, 
deba@127
   603
			    const Converter& converter = Converter()) {
deba@127
   604
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@127
   605
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
deba@127
   606
      _use_nodes = true;
deba@127
   607
      for (NodeIt n(_digraph); n != INVALID; ++n) {
deba@127
   608
	_node_index.insert(std::make_pair(converter(map[n]), n));
deba@127
   609
      }
deba@127
   610
      return *this;
deba@127
   611
    }
deba@127
   612
alpar@156
   613
    /// \brief Use previously constructed arc set
alpar@156
   614
    ///
alpar@156
   615
    /// Use previously constructed arc set, and specify the arc
alpar@156
   616
    /// label map.
deba@127
   617
    template <typename Map>
deba@127
   618
    DigraphReader& useArcs(const Map& map) {
deba@127
   619
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   620
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
deba@127
   621
      _use_arcs = true;
deba@127
   622
      _writer_bits::DefaultConverter<typename Map::Value> converter;
deba@127
   623
      for (ArcIt a(_digraph); a != INVALID; ++a) {
deba@127
   624
	_arc_index.insert(std::make_pair(converter(map[a]), a));
deba@127
   625
      }
deba@127
   626
      return *this;
deba@127
   627
    }
deba@127
   628
alpar@156
   629
    /// \brief Use previously constructed arc set
alpar@156
   630
    ///
alpar@156
   631
    /// Use previously constructed arc set, and specify the arc
alpar@156
   632
    /// label map and a functor which converts the label map values to
alpar@156
   633
    /// std::string.
deba@127
   634
    template <typename Map, typename Converter>
deba@127
   635
    DigraphReader& useArcs(const Map& map, 
deba@127
   636
			    const Converter& converter = Converter()) {
deba@127
   637
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@127
   638
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); 
deba@127
   639
      _use_arcs = true;
deba@127
   640
      for (ArcIt a(_digraph); a != INVALID; ++a) {
deba@127
   641
	_arc_index.insert(std::make_pair(converter(map[a]), a));
deba@127
   642
      }
deba@127
   643
      return *this;
deba@127
   644
    }
deba@127
   645
alpar@156
   646
    /// @}
alpar@156
   647
deba@127
   648
  private:
deba@127
   649
deba@127
   650
    bool readLine() {
deba@127
   651
      std::string str;
deba@127
   652
      while(++line_num, std::getline(*_is, str)) {
deba@127
   653
	line.clear(); line.str(str);
deba@127
   654
	char c;
deba@127
   655
	if (line >> std::ws >> c && c != '#') {
deba@127
   656
	  line.putback(c);
deba@127
   657
	  return true;
deba@127
   658
	}
deba@127
   659
      }
deba@127
   660
      return false;
deba@127
   661
    }
deba@127
   662
deba@127
   663
    bool readSuccess() {
deba@127
   664
      return static_cast<bool>(*_is);
deba@127
   665
    }
deba@127
   666
    
deba@127
   667
    void skipSection() {
deba@127
   668
      char c;
deba@127
   669
      while (readSuccess() && line >> c && c != '@') {
deba@127
   670
	readLine();
deba@127
   671
      }
deba@127
   672
      line.putback(c);
deba@127
   673
    }
deba@127
   674
deba@127
   675
    void readNodes() {
deba@127
   676
deba@127
   677
      std::vector<int> map_index(_node_maps.size());
deba@127
   678
      int map_num, label_index;
deba@127
   679
deba@127
   680
      if (!readLine()) 
deba@127
   681
	throw DataFormatError("Cannot find map captions");
deba@127
   682
      
deba@127
   683
      {
deba@127
   684
	std::map<std::string, int> maps;
deba@127
   685
	
deba@127
   686
	std::string map;
deba@127
   687
	int index = 0;
alpar@156
   688
	while (_reader_bits::readToken(line, map)) {
deba@127
   689
	  if (maps.find(map) != maps.end()) {
deba@127
   690
	    std::ostringstream msg;
deba@127
   691
	    msg << "Multiple occurence of node map: " << map;
deba@127
   692
	    throw DataFormatError(msg.str().c_str());
deba@127
   693
	  }
deba@127
   694
	  maps.insert(std::make_pair(map, index));
deba@127
   695
	  ++index;
deba@127
   696
	}
deba@127
   697
	
deba@127
   698
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
deba@127
   699
	  std::map<std::string, int>::iterator jt = 
deba@127
   700
	    maps.find(_node_maps[i].first);
deba@127
   701
	  if (jt == maps.end()) {
deba@127
   702
	    std::ostringstream msg;
deba@127
   703
	    msg << "Map not found in file: " << _node_maps[i].first;
deba@127
   704
	    throw DataFormatError(msg.str().c_str());
deba@127
   705
	  }
deba@127
   706
	  map_index[i] = jt->second;
deba@127
   707
	}
deba@127
   708
deba@127
   709
	{
deba@127
   710
	  std::map<std::string, int>::iterator jt = maps.find("label");
deba@127
   711
	  if (jt == maps.end())
deba@127
   712
	    throw DataFormatError("Label map not found in file");
deba@127
   713
	  label_index = jt->second;
deba@127
   714
	}
deba@127
   715
	map_num = maps.size();
deba@127
   716
      }
deba@127
   717
deba@127
   718
      char c;
deba@127
   719
      while (readLine() && line >> c && c != '@') {
deba@127
   720
	line.putback(c);
deba@127
   721
deba@127
   722
	std::vector<std::string> tokens(map_num);
deba@127
   723
	for (int i = 0; i < map_num; ++i) {
deba@127
   724
	  if (!_reader_bits::readToken(line, tokens[i])) {
deba@127
   725
	    std::ostringstream msg;
deba@127
   726
	    msg << "Column not found (" << i + 1 << ")";
deba@127
   727
	    throw DataFormatError(msg.str().c_str());
deba@127
   728
	  }
deba@127
   729
	}
deba@127
   730
	if (line >> std::ws >> c)
deba@127
   731
	  throw DataFormatError("Extra character on the end of line");
deba@127
   732
	
deba@127
   733
	Node n;
deba@127
   734
	if (!_use_nodes) {
deba@127
   735
	  n = _digraph.addNode();
deba@127
   736
	  _node_index.insert(std::make_pair(tokens[label_index], n));
deba@127
   737
	} else {
deba@127
   738
	  typename std::map<std::string, Node>::iterator it =
deba@127
   739
	    _node_index.find(tokens[label_index]);
deba@127
   740
	  if (it == _node_index.end()) {
deba@127
   741
	    std::ostringstream msg;
deba@127
   742
	    msg << "Node with label not found: " << tokens[label_index];
deba@127
   743
	    throw DataFormatError(msg.str().c_str());	    
deba@127
   744
	  }
deba@127
   745
	  n = it->second;
deba@127
   746
	}
deba@127
   747
deba@127
   748
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
deba@127
   749
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
deba@127
   750
	}
deba@127
   751
deba@127
   752
      }
deba@127
   753
      if (readSuccess()) {
deba@127
   754
	line.putback(c);
deba@127
   755
      }
deba@127
   756
    }
deba@127
   757
deba@127
   758
    void readArcs() {
deba@127
   759
deba@127
   760
      std::vector<int> map_index(_arc_maps.size());
deba@127
   761
      int map_num, label_index;
deba@127
   762
deba@127
   763
      if (!readLine()) 
deba@127
   764
	throw DataFormatError("Cannot find map captions");
deba@127
   765
      
deba@127
   766
      {
deba@127
   767
	std::map<std::string, int> maps;
deba@127
   768
	
deba@127
   769
	std::string map;
deba@127
   770
	int index = 0;
alpar@156
   771
	while (_reader_bits::readToken(line, map)) {
deba@127
   772
	  if (maps.find(map) != maps.end()) {
deba@127
   773
	    std::ostringstream msg;
deba@127
   774
	    msg << "Multiple occurence of arc map: " << map;
deba@127
   775
	    throw DataFormatError(msg.str().c_str());
deba@127
   776
	  }
deba@127
   777
	  maps.insert(std::make_pair(map, index));
deba@127
   778
	  ++index;
deba@127
   779
	}
deba@127
   780
	
deba@127
   781
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
deba@127
   782
	  std::map<std::string, int>::iterator jt = 
deba@127
   783
	    maps.find(_arc_maps[i].first);
deba@127
   784
	  if (jt == maps.end()) {
deba@127
   785
	    std::ostringstream msg;
deba@127
   786
	    msg << "Map not found in file: " << _arc_maps[i].first;
deba@127
   787
	    throw DataFormatError(msg.str().c_str());
deba@127
   788
	  }
deba@127
   789
	  map_index[i] = jt->second;
deba@127
   790
	}
deba@127
   791
deba@127
   792
	{
deba@127
   793
	  std::map<std::string, int>::iterator jt = maps.find("label");
deba@127
   794
	  if (jt == maps.end())
deba@127
   795
	    throw DataFormatError("Label map not found in file");
deba@127
   796
	  label_index = jt->second;
deba@127
   797
	}
deba@127
   798
	map_num = maps.size();
deba@127
   799
      }
deba@127
   800
deba@127
   801
      char c;
deba@127
   802
      while (readLine() && line >> c && c != '@') {
deba@127
   803
	line.putback(c);
deba@127
   804
deba@127
   805
	std::string source_token;
deba@127
   806
	std::string target_token;
deba@127
   807
deba@127
   808
	if (!_reader_bits::readToken(line, source_token))
deba@127
   809
	  throw DataFormatError("Source not found");
deba@127
   810
deba@127
   811
	if (!_reader_bits::readToken(line, target_token))
deba@127
   812
	  throw DataFormatError("Source not found");
deba@127
   813
	
deba@127
   814
	std::vector<std::string> tokens(map_num);
deba@127
   815
	for (int i = 0; i < map_num; ++i) {
deba@127
   816
	  if (!_reader_bits::readToken(line, tokens[i])) {
deba@127
   817
	    std::ostringstream msg;
deba@127
   818
	    msg << "Column not found (" << i + 1 << ")";
deba@127
   819
	    throw DataFormatError(msg.str().c_str());
deba@127
   820
	  }
deba@127
   821
	}
deba@127
   822
	if (line >> std::ws >> c)
deba@127
   823
	  throw DataFormatError("Extra character on the end of line");
deba@127
   824
	
deba@127
   825
	Arc a;
deba@127
   826
	if (!_use_arcs) {
deba@127
   827
deba@127
   828
          typename NodeIndex::iterator it;
deba@127
   829
 
deba@127
   830
          it = _node_index.find(source_token);
deba@127
   831
          if (it == _node_index.end()) {
deba@127
   832
            std::ostringstream msg;
deba@127
   833
            msg << "Item not found: " << source_token;
deba@127
   834
            throw DataFormatError(msg.str().c_str());
deba@127
   835
          }
deba@127
   836
          Node source = it->second;
deba@127
   837
deba@127
   838
          it = _node_index.find(target_token);
deba@127
   839
          if (it == _node_index.end()) {       
deba@127
   840
            std::ostringstream msg;            
deba@127
   841
            msg << "Item not found: " << target_token;
deba@127
   842
            throw DataFormatError(msg.str().c_str());
deba@127
   843
          }                                          
deba@127
   844
          Node target = it->second;                            
deba@127
   845
deba@127
   846
	  a = _digraph.addArc(source, target);
deba@127
   847
	  _arc_index.insert(std::make_pair(tokens[label_index], a));
deba@127
   848
	} else {
deba@127
   849
	  typename std::map<std::string, Arc>::iterator it =
deba@127
   850
	    _arc_index.find(tokens[label_index]);
deba@127
   851
	  if (it == _arc_index.end()) {
deba@127
   852
	    std::ostringstream msg;
deba@127
   853
	    msg << "Arc with label not found: " << tokens[label_index];
deba@127
   854
	    throw DataFormatError(msg.str().c_str());	    
deba@127
   855
	  }
deba@127
   856
	  a = it->second;
deba@127
   857
	}
deba@127
   858
deba@127
   859
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
deba@127
   860
	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
deba@127
   861
	}
deba@127
   862
deba@127
   863
      }
deba@127
   864
      if (readSuccess()) {
deba@127
   865
	line.putback(c);
deba@127
   866
      }
deba@127
   867
    }
deba@127
   868
deba@127
   869
    void readAttributes() {
deba@127
   870
deba@127
   871
      std::set<std::string> read_attr;
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::string attr, token;
alpar@156
   878
	if (!_reader_bits::readToken(line, attr))
deba@127
   879
	  throw DataFormatError("Attribute name not found");
deba@127
   880
	if (!_reader_bits::readToken(line, token))
deba@127
   881
	  throw DataFormatError("Attribute value not found");
deba@127
   882
	if (line >> c)
deba@127
   883
	  throw DataFormatError("Extra character on the end of line");	  
deba@127
   884
deba@127
   885
	{
deba@127
   886
	  std::set<std::string>::iterator it = read_attr.find(attr);
deba@127
   887
	  if (it != read_attr.end()) {
deba@127
   888
	    std::ostringstream msg;
deba@127
   889
	    msg << "Multiple occurence of attribute " << attr;
deba@127
   890
	    throw DataFormatError(msg.str().c_str());
deba@127
   891
	  }
deba@127
   892
	  read_attr.insert(attr);
deba@127
   893
	}
deba@127
   894
	
deba@127
   895
	{
deba@127
   896
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
deba@127
   897
	  while (it != _attributes.end() && it->first == attr) {
deba@127
   898
	    it->second->set(token);
deba@127
   899
	    ++it;
deba@127
   900
	  }
deba@127
   901
	}
deba@127
   902
deba@127
   903
      }
deba@127
   904
      if (readSuccess()) {
deba@127
   905
	line.putback(c);
deba@127
   906
      }
deba@127
   907
      for (typename Attributes::iterator it = _attributes.begin();
deba@127
   908
	   it != _attributes.end(); ++it) {
deba@127
   909
	if (read_attr.find(it->first) == read_attr.end()) {
deba@127
   910
	  std::ostringstream msg;
deba@127
   911
	  msg << "Attribute not found in file: " << it->first;
deba@127
   912
	  throw DataFormatError(msg.str().c_str());
deba@127
   913
	}	
deba@127
   914
      }
deba@127
   915
    }
deba@127
   916
deba@127
   917
  public:
alpar@156
   918
alpar@156
   919
    /// \name Execution of the reader    
alpar@156
   920
    /// @{
alpar@156
   921
alpar@156
   922
    /// \brief Start the batch processing
alpar@156
   923
    ///
alpar@156
   924
    /// This function starts the batch processing
deba@127
   925
    void run() {
deba@127
   926
      
deba@127
   927
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
deba@127
   928
      
deba@127
   929
      bool nodes_done = false;
deba@127
   930
      bool arcs_done = false;
deba@127
   931
      bool attributes_done = false;
deba@127
   932
deba@127
   933
      line_num = 0;      
deba@127
   934
      readLine();
deba@127
   935
deba@127
   936
      while (readSuccess()) {
deba@127
   937
	skipSection();
deba@127
   938
	try {
deba@127
   939
	  char c;
deba@127
   940
	  std::string section, caption;
deba@127
   941
	  line >> c;
alpar@156
   942
	  _reader_bits::readToken(line, section);
alpar@156
   943
	  _reader_bits::readToken(line, caption);
deba@127
   944
deba@127
   945
	  if (line >> c) 
deba@127
   946
	    throw DataFormatError("Extra character on the end of line");
deba@127
   947
deba@127
   948
	  if (section == "nodes" && !nodes_done) {
deba@127
   949
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
deba@127
   950
	      readNodes();
deba@127
   951
	      nodes_done = true;
deba@127
   952
	    }
deba@127
   953
	  } else if ((section == "arcs" || section == "edges") && 
deba@127
   954
		     !arcs_done) {
deba@127
   955
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
deba@127
   956
	      readArcs();
deba@127
   957
	      arcs_done = true;
deba@127
   958
	    }
deba@127
   959
	  } else if (section == "attributes" && !attributes_done) {
deba@127
   960
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
deba@127
   961
	      readAttributes();
deba@127
   962
	      attributes_done = true;
deba@127
   963
	    }
deba@127
   964
	  } else {
deba@127
   965
	    readLine();
deba@127
   966
	    skipSection();
deba@127
   967
	  }
deba@127
   968
	} catch (DataFormatError& error) {
deba@127
   969
	  error.line(line_num);
deba@127
   970
	  throw;
deba@127
   971
	}	
deba@127
   972
      }
deba@127
   973
deba@127
   974
      if (!nodes_done) {
deba@127
   975
	throw DataFormatError("Section @nodes not found");
deba@127
   976
      }
deba@127
   977
deba@127
   978
      if (!arcs_done) {
deba@127
   979
	throw DataFormatError("Section @arcs not found");
deba@127
   980
      }
deba@127
   981
deba@127
   982
      if (!attributes_done && !_attributes.empty()) {
deba@127
   983
	throw DataFormatError("Section @attributes not found");
deba@127
   984
      }
deba@127
   985
deba@127
   986
    }
alpar@156
   987
alpar@156
   988
    /// @}
deba@127
   989
    
deba@127
   990
  };
deba@127
   991
alpar@156
   992
  /// \relates DigraphReader
deba@127
   993
  template <typename Digraph>
deba@127
   994
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
deba@127
   995
    return DigraphReader<Digraph>(is, digraph);
deba@127
   996
  }
deba@127
   997
alpar@156
   998
  /// \relates DigraphReader
deba@127
   999
  template <typename Digraph>
deba@127
  1000
  DigraphReader<Digraph> digraphReader(const std::string& fn, 
deba@127
  1001
				       Digraph& digraph) {
deba@127
  1002
    return DigraphReader<Digraph>(fn, digraph);
deba@127
  1003
  }
deba@127
  1004
alpar@156
  1005
  /// \relates DigraphReader
deba@127
  1006
  template <typename Digraph>
deba@127
  1007
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
deba@127
  1008
    return DigraphReader<Digraph>(fn, digraph);
deba@127
  1009
  }
deba@127
  1010
}
deba@127
  1011
deba@127
  1012
#endif