gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Add more docs to LGF function interface (#109)
0 2 0
default
2 files changed with 309 insertions and 190 deletions:
↑ Collapse diff ↑
Ignore white space 192 line context
... ...
@@ -8,279 +8,279 @@
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
///\ingroup lemon_io
20 20
///\file
21 21
///\brief \ref lgf-format "LEMON Graph Format" reader.
22 22

	
23 23

	
24 24
#ifndef LEMON_LGF_READER_H
25 25
#define LEMON_LGF_READER_H
26 26

	
27 27
#include <iostream>
28 28
#include <fstream>
29 29
#include <sstream>
30 30

	
31 31
#include <set>
32 32
#include <map>
33 33

	
34 34
#include <lemon/core.h>
35 35

	
36 36
#include <lemon/lgf_writer.h>
37 37

	
38 38
#include <lemon/concept_check.h>
39 39
#include <lemon/concepts/maps.h>
40 40

	
41 41
namespace lemon {
42 42

	
43 43
  namespace _reader_bits {
44 44

	
45 45
    template <typename Value>
46 46
    struct DefaultConverter {
47 47
      Value operator()(const std::string& str) {
48 48
        std::istringstream is(str);
49 49
        Value value;
50 50
        if (!(is >> value)) {
51 51
          throw FormatError("Cannot read token");
52 52
        }
53 53

	
54 54
        char c;
55 55
        if (is >> std::ws >> c) {
56 56
          throw FormatError("Remaining characters in token");
57 57
        }
58 58
        return value;
59 59
      }
60 60
    };
61 61

	
62 62
    template <>
63 63
    struct DefaultConverter<std::string> {
64 64
      std::string operator()(const std::string& str) {
65 65
        return str;
66 66
      }
67 67
    };
68 68

	
69 69
    template <typename _Item>
70 70
    class MapStorageBase {
71 71
    public:
72 72
      typedef _Item Item;
73 73

	
74 74
    public:
75 75
      MapStorageBase() {}
76 76
      virtual ~MapStorageBase() {}
77 77

	
78 78
      virtual void set(const Item& item, const std::string& value) = 0;
79 79

	
80 80
    };
81 81

	
82 82
    template <typename _Item, typename _Map,
83 83
              typename _Converter = DefaultConverter<typename _Map::Value> >
84 84
    class MapStorage : public MapStorageBase<_Item> {
85 85
    public:
86 86
      typedef _Map Map;
87 87
      typedef _Converter Converter;
88 88
      typedef _Item Item;
89 89

	
90 90
    private:
91 91
      Map& _map;
92 92
      Converter _converter;
93 93

	
94 94
    public:
95 95
      MapStorage(Map& map, const Converter& converter = Converter())
96 96
        : _map(map), _converter(converter) {}
97 97
      virtual ~MapStorage() {}
98 98

	
99 99
      virtual void set(const Item& item ,const std::string& value) {
100 100
        _map.set(item, _converter(value));
101 101
      }
102 102
    };
103 103

	
104
    template <typename _Graph, bool _dir, typename _Map,
104
    template <typename _GR, bool _dir, typename _Map,
105 105
              typename _Converter = DefaultConverter<typename _Map::Value> >
106
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
106
    class GraphArcMapStorage : public MapStorageBase<typename _GR::Edge> {
107 107
    public:
108 108
      typedef _Map Map;
109 109
      typedef _Converter Converter;
110
      typedef _Graph Graph;
111
      typedef typename Graph::Edge Item;
110
      typedef _GR GR;
111
      typedef typename GR::Edge Item;
112 112
      static const bool dir = _dir;
113 113

	
114 114
    private:
115
      const Graph& _graph;
115
      const GR& _graph;
116 116
      Map& _map;
117 117
      Converter _converter;
118 118

	
119 119
    public:
120
      GraphArcMapStorage(const Graph& graph, Map& map,
120
      GraphArcMapStorage(const GR& graph, Map& map,
121 121
                         const Converter& converter = Converter())
122 122
        : _graph(graph), _map(map), _converter(converter) {}
123 123
      virtual ~GraphArcMapStorage() {}
124 124

	
125 125
      virtual void set(const Item& item ,const std::string& value) {
126 126
        _map.set(_graph.direct(item, dir), _converter(value));
127 127
      }
128 128
    };
129 129

	
130 130
    class ValueStorageBase {
131 131
    public:
132 132
      ValueStorageBase() {}
133 133
      virtual ~ValueStorageBase() {}
134 134

	
135 135
      virtual void set(const std::string&) = 0;
136 136
    };
137 137

	
138 138
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
139 139
    class ValueStorage : public ValueStorageBase {
140 140
    public:
141 141
      typedef _Value Value;
142 142
      typedef _Converter Converter;
143 143

	
144 144
    private:
145 145
      Value& _value;
146 146
      Converter _converter;
147 147

	
148 148
    public:
149 149
      ValueStorage(Value& value, const Converter& converter = Converter())
150 150
        : _value(value), _converter(converter) {}
151 151

	
152 152
      virtual void set(const std::string& value) {
153 153
        _value = _converter(value);
154 154
      }
155 155
    };
156 156

	
157 157
    template <typename Value>
158 158
    struct MapLookUpConverter {
159 159
      const std::map<std::string, Value>& _map;
160 160

	
161 161
      MapLookUpConverter(const std::map<std::string, Value>& map)
162 162
        : _map(map) {}
163 163

	
164 164
      Value operator()(const std::string& str) {
165 165
        typename std::map<std::string, Value>::const_iterator it =
166 166
          _map.find(str);
167 167
        if (it == _map.end()) {
168 168
          std::ostringstream msg;
169 169
          msg << "Item not found: " << str;
170 170
          throw FormatError(msg.str());
171 171
        }
172 172
        return it->second;
173 173
      }
174 174
    };
175 175

	
176
    template <typename Graph>
176
    template <typename GR>
177 177
    struct GraphArcLookUpConverter {
178
      const Graph& _graph;
179
      const std::map<std::string, typename Graph::Edge>& _map;
180

	
181
      GraphArcLookUpConverter(const Graph& graph,
178
      const GR& _graph;
179
      const std::map<std::string, typename GR::Edge>& _map;
180

	
181
      GraphArcLookUpConverter(const GR& graph,
182 182
                              const std::map<std::string,
183
                                             typename Graph::Edge>& map)
183
                                             typename GR::Edge>& map)
184 184
        : _graph(graph), _map(map) {}
185 185

	
186
      typename Graph::Arc operator()(const std::string& str) {
186
      typename GR::Arc operator()(const std::string& str) {
187 187
        if (str.empty() || (str[0] != '+' && str[0] != '-')) {
188 188
          throw FormatError("Item must start with '+' or '-'");
189 189
        }
190
        typename std::map<std::string, typename Graph::Edge>
190
        typename std::map<std::string, typename GR::Edge>
191 191
          ::const_iterator it = _map.find(str.substr(1));
192 192
        if (it == _map.end()) {
193 193
          throw FormatError("Item not found");
194 194
        }
195 195
        return _graph.direct(it->second, str[0] == '+');
196 196
      }
197 197
    };
198 198

	
199 199
    inline bool isWhiteSpace(char c) {
200 200
      return c == ' ' || c == '\t' || c == '\v' ||
201 201
        c == '\n' || c == '\r' || c == '\f';
202 202
    }
203 203

	
204 204
    inline bool isOct(char c) {
205 205
      return '0' <= c && c <='7';
206 206
    }
207 207

	
208 208
    inline int valueOct(char c) {
209 209
      LEMON_ASSERT(isOct(c), "The character is not octal.");
210 210
      return c - '0';
211 211
    }
212 212

	
213 213
    inline bool isHex(char c) {
214 214
      return ('0' <= c && c <= '9') ||
215 215
        ('a' <= c && c <= 'z') ||
216 216
        ('A' <= c && c <= 'Z');
217 217
    }
218 218

	
219 219
    inline int valueHex(char c) {
220 220
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
221 221
      if ('0' <= c && c <= '9') return c - '0';
222 222
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
223 223
      return c - 'A' + 10;
224 224
    }
225 225

	
226 226
    inline bool isIdentifierFirstChar(char c) {
227 227
      return ('a' <= c && c <= 'z') ||
228 228
        ('A' <= c && c <= 'Z') || c == '_';
229 229
    }
230 230

	
231 231
    inline bool isIdentifierChar(char c) {
232 232
      return isIdentifierFirstChar(c) ||
233 233
        ('0' <= c && c <= '9');
234 234
    }
235 235

	
236 236
    inline char readEscape(std::istream& is) {
237 237
      char c;
238 238
      if (!is.get(c))
239 239
        throw FormatError("Escape format error");
240 240

	
241 241
      switch (c) {
242 242
      case '\\':
243 243
        return '\\';
244 244
      case '\"':
245 245
        return '\"';
246 246
      case '\'':
247 247
        return '\'';
248 248
      case '\?':
249 249
        return '\?';
250 250
      case 'a':
251 251
        return '\a';
252 252
      case 'b':
253 253
        return '\b';
254 254
      case 'f':
255 255
        return '\f';
256 256
      case 'n':
257 257
        return '\n';
258 258
      case 'r':
259 259
        return '\r';
260 260
      case 't':
261 261
        return '\t';
262 262
      case 'v':
263 263
        return '\v';
264 264
      case 'x':
265 265
        {
266 266
          int code;
267 267
          if (!is.get(c) || !isHex(c))
268 268
            throw FormatError("Escape format error");
269 269
          else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
270 270
          else code = code * 16 + valueHex(c);
271 271
          return code;
272 272
        }
273 273
      default:
274 274
        {
275 275
          int code;
276 276
          if (!isOct(c))
277 277
            throw FormatError("Escape format error");
278 278
          else if (code = valueOct(c), !is.get(c) || !isOct(c))
279 279
            is.putback(c);
280 280
          else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
281 281
            is.putback(c);
282 282
          else code = code * 8 + valueOct(c);
283 283
          return code;
284 284
        }
285 285
      }
286 286
    }
... ...
@@ -294,372 +294,371 @@
294 294
      if (!is.get(c))
295 295
        return is;
296 296

	
297 297
      if (c == '\"') {
298 298
        while (is.get(c) && c != '\"') {
299 299
          if (c == '\\')
300 300
            c = readEscape(is);
301 301
          os << c;
302 302
        }
303 303
        if (!is)
304 304
          throw FormatError("Quoted format error");
305 305
      } else {
306 306
        is.putback(c);
307 307
        while (is.get(c) && !isWhiteSpace(c)) {
308 308
          if (c == '\\')
309 309
            c = readEscape(is);
310 310
          os << c;
311 311
        }
312 312
        if (!is) {
313 313
          is.clear();
314 314
        } else {
315 315
          is.putback(c);
316 316
        }
317 317
      }
318 318
      str = os.str();
319 319
      return is;
320 320
    }
321 321

	
322 322
    class Section {
323 323
    public:
324 324
      virtual ~Section() {}
325 325
      virtual void process(std::istream& is, int& line_num) = 0;
326 326
    };
327 327

	
328 328
    template <typename Functor>
329 329
    class LineSection : public Section {
330 330
    private:
331 331

	
332 332
      Functor _functor;
333 333

	
334 334
    public:
335 335

	
336 336
      LineSection(const Functor& functor) : _functor(functor) {}
337 337
      virtual ~LineSection() {}
338 338

	
339 339
      virtual void process(std::istream& is, int& line_num) {
340 340
        char c;
341 341
        std::string line;
342 342
        while (is.get(c) && c != '@') {
343 343
          if (c == '\n') {
344 344
            ++line_num;
345 345
          } else if (c == '#') {
346 346
            getline(is, line);
347 347
            ++line_num;
348 348
          } else if (!isWhiteSpace(c)) {
349 349
            is.putback(c);
350 350
            getline(is, line);
351 351
            _functor(line);
352 352
            ++line_num;
353 353
          }
354 354
        }
355 355
        if (is) is.putback(c);
356 356
        else if (is.eof()) is.clear();
357 357
      }
358 358
    };
359 359

	
360 360
    template <typename Functor>
361 361
    class StreamSection : public Section {
362 362
    private:
363 363

	
364 364
      Functor _functor;
365 365

	
366 366
    public:
367 367

	
368 368
      StreamSection(const Functor& functor) : _functor(functor) {}
369 369
      virtual ~StreamSection() {}
370 370

	
371 371
      virtual void process(std::istream& is, int& line_num) {
372 372
        _functor(is, line_num);
373 373
        char c;
374 374
        std::string line;
375 375
        while (is.get(c) && c != '@') {
376 376
          if (c == '\n') {
377 377
            ++line_num;
378 378
          } else if (!isWhiteSpace(c)) {
379 379
            getline(is, line);
380 380
            ++line_num;
381 381
          }
382 382
        }
383 383
        if (is) is.putback(c);
384 384
        else if (is.eof()) is.clear();
385 385
      }
386 386
    };
387 387

	
388 388
  }
389 389

	
390
  template <typename Digraph>
390
  template <typename DGR>
391 391
  class DigraphReader;
392 392

	
393
  template <typename Digraph>
394
  DigraphReader<Digraph> digraphReader(Digraph& digraph, 
395
                                       std::istream& is = std::cin);
396
  template <typename Digraph>
397
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const std::string& fn);
398
  template <typename Digraph>
399
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const char *fn);
393
  template <typename TDGR>
394
  DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is = std::cin);
395
  template <typename TDGR>
396
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn);
397
  template <typename TDGR>
398
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
400 399

	
401 400
  /// \ingroup lemon_io
402 401
  ///
403 402
  /// \brief \ref lgf-format "LGF" reader for directed graphs
404 403
  ///
405 404
  /// This utility reads an \ref lgf-format "LGF" file.
406 405
  ///
407 406
  /// The reading method does a batch processing. The user creates a
408 407
  /// reader object, then various reading rules can be added to the
409 408
  /// reader, and eventually the reading is executed with the \c run()
410 409
  /// member function. A map reading rule can be added to the reader
411 410
  /// with the \c nodeMap() or \c arcMap() members. An optional
412 411
  /// converter parameter can also be added as a standard functor
413 412
  /// converting from \c std::string to the value type of the map. If it
414 413
  /// is set, it will determine how the tokens in the file should be
415 414
  /// converted to the value type of the map. If the functor is not set,
416 415
  /// then a default conversion will be used. One map can be read into
417 416
  /// multiple map objects at the same time. The \c attribute(), \c
418 417
  /// node() and \c arc() functions are used to add attribute reading
419 418
  /// rules.
420 419
  ///
421 420
  ///\code
422
  /// DigraphReader<Digraph>(digraph, std::cin).
421
  /// DigraphReader<DGR>(digraph, std::cin).
423 422
  ///   nodeMap("coordinates", coord_map).
424 423
  ///   arcMap("capacity", cap_map).
425 424
  ///   node("source", src).
426 425
  ///   node("target", trg).
427 426
  ///   attribute("caption", caption).
428 427
  ///   run();
429 428
  ///\endcode
430 429
  ///
431 430
  /// By default the reader uses the first section in the file of the
432 431
  /// proper type. If a section has an optional name, then it can be
433 432
  /// selected for reading by giving an optional name parameter to the
434 433
  /// \c nodes(), \c arcs() or \c attributes() functions.
435 434
  ///
436 435
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
437 436
  /// that the nodes or arcs should not be constructed (added to the
438 437
  /// graph) during the reading, but instead the label map of the items
439 438
  /// are given as a parameter of these functions. An
440 439
  /// application of these functions is multipass reading, which is
441 440
  /// important if two \c \@arcs sections must be read from the
442 441
  /// file. In this case the first phase would read the node set and one
443 442
  /// of the arc sets, while the second phase would read the second arc
444 443
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
445 444
  /// The previously read label node map should be passed to the \c
446 445
  /// useNodes() functions. Another application of multipass reading when
447 446
  /// paths are given as a node map or an arc map.
448 447
  /// It is impossible to read this in
449 448
  /// a single pass, because the arcs are not constructed when the node
450 449
  /// maps are read.
451
  template <typename GR>
450
  template <typename DGR>
452 451
  class DigraphReader {
453 452
  public:
454 453

	
455
    typedef GR Digraph;
454
    typedef DGR Digraph;
456 455

	
457 456
  private:
458 457

	
459
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
458
    TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
460 459

	
461 460
    std::istream* _is;
462 461
    bool local_is;
463 462
    std::string _filename;
464 463

	
465
    Digraph& _digraph;
464
    DGR& _digraph;
466 465

	
467 466
    std::string _nodes_caption;
468 467
    std::string _arcs_caption;
469 468
    std::string _attributes_caption;
470 469

	
471 470
    typedef std::map<std::string, Node> NodeIndex;
472 471
    NodeIndex _node_index;
473 472
    typedef std::map<std::string, Arc> ArcIndex;
474 473
    ArcIndex _arc_index;
475 474

	
476 475
    typedef std::vector<std::pair<std::string,
477 476
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
478 477
    NodeMaps _node_maps;
479 478

	
480 479
    typedef std::vector<std::pair<std::string,
481 480
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
482 481
    ArcMaps _arc_maps;
483 482

	
484 483
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
485 484
      Attributes;
486 485
    Attributes _attributes;
487 486

	
488 487
    bool _use_nodes;
489 488
    bool _use_arcs;
490 489

	
491 490
    bool _skip_nodes;
492 491
    bool _skip_arcs;
493 492

	
494 493
    int line_num;
495 494
    std::istringstream line;
496 495

	
497 496
  public:
498 497

	
499 498
    /// \brief Constructor
500 499
    ///
501 500
    /// Construct a directed graph reader, which reads from the given
502 501
    /// input stream.
503
    DigraphReader(Digraph& digraph, std::istream& is = std::cin)
502
    DigraphReader(DGR& digraph, std::istream& is = std::cin)
504 503
      : _is(&is), local_is(false), _digraph(digraph),
505 504
        _use_nodes(false), _use_arcs(false),
506 505
        _skip_nodes(false), _skip_arcs(false) {}
507 506

	
508 507
    /// \brief Constructor
509 508
    ///
510 509
    /// Construct a directed graph reader, which reads from the given
511 510
    /// file.
512
    DigraphReader(Digraph& digraph, const std::string& fn)
511
    DigraphReader(DGR& digraph, const std::string& fn)
513 512
      : _is(new std::ifstream(fn.c_str())), local_is(true),
514 513
        _filename(fn), _digraph(digraph),
515 514
        _use_nodes(false), _use_arcs(false),
516 515
        _skip_nodes(false), _skip_arcs(false) {
517 516
      if (!(*_is)) {
518 517
        delete _is;
519 518
        throw IoError("Cannot open file", fn);
520 519
      }
521 520
    }
522 521

	
523 522
    /// \brief Constructor
524 523
    ///
525 524
    /// Construct a directed graph reader, which reads from the given
526 525
    /// file.
527
    DigraphReader(Digraph& digraph, const char* fn)
526
    DigraphReader(DGR& digraph, const char* fn)
528 527
      : _is(new std::ifstream(fn)), local_is(true),
529 528
        _filename(fn), _digraph(digraph),
530 529
        _use_nodes(false), _use_arcs(false),
531 530
        _skip_nodes(false), _skip_arcs(false) {
532 531
      if (!(*_is)) {
533 532
        delete _is;
534 533
        throw IoError("Cannot open file", fn);
535 534
      }
536 535
    }
537 536

	
538 537
    /// \brief Destructor
539 538
    ~DigraphReader() {
540 539
      for (typename NodeMaps::iterator it = _node_maps.begin();
541 540
           it != _node_maps.end(); ++it) {
542 541
        delete it->second;
543 542
      }
544 543

	
545 544
      for (typename ArcMaps::iterator it = _arc_maps.begin();
546 545
           it != _arc_maps.end(); ++it) {
547 546
        delete it->second;
548 547
      }
549 548

	
550 549
      for (typename Attributes::iterator it = _attributes.begin();
551 550
           it != _attributes.end(); ++it) {
552 551
        delete it->second;
553 552
      }
554 553

	
555 554
      if (local_is) {
556 555
        delete _is;
557 556
      }
558 557

	
559 558
    }
560 559

	
561 560
  private:
562 561

	
563
    template <typename DGR>
564
    friend DigraphReader<DGR> digraphReader(DGR& digraph, std::istream& is);
565
    template <typename DGR>
566
    friend DigraphReader<DGR> digraphReader(DGR& digraph, 
567
                                            const std::string& fn);
568
    template <typename DGR>
569
    friend DigraphReader<DGR> digraphReader(DGR& digraph, const char *fn);
562
    template <typename TDGR>
563
    friend DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is);
564
    template <typename TDGR>
565
    friend DigraphReader<TDGR> digraphReader(TDGR& digraph, 
566
                                             const std::string& fn);
567
    template <typename TDGR>
568
    friend DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
570 569

	
571 570
    DigraphReader(DigraphReader& other)
572 571
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
573 572
        _use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
574 573
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
575 574

	
576 575
      other._is = 0;
577 576
      other.local_is = false;
578 577

	
579 578
      _node_index.swap(other._node_index);
580 579
      _arc_index.swap(other._arc_index);
581 580

	
582 581
      _node_maps.swap(other._node_maps);
583 582
      _arc_maps.swap(other._arc_maps);
584 583
      _attributes.swap(other._attributes);
585 584

	
586 585
      _nodes_caption = other._nodes_caption;
587 586
      _arcs_caption = other._arcs_caption;
588 587
      _attributes_caption = other._attributes_caption;
589 588

	
590 589
    }
591 590

	
592 591
    DigraphReader& operator=(const DigraphReader&);
593 592

	
594 593
  public:
595 594

	
596 595
    /// \name Reading rules
597 596
    /// @{
598 597

	
599 598
    /// \brief Node map reading rule
600 599
    ///
601 600
    /// Add a node map reading rule to the reader.
602 601
    template <typename Map>
603 602
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
604 603
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
605 604
      _reader_bits::MapStorageBase<Node>* storage =
606 605
        new _reader_bits::MapStorage<Node, Map>(map);
607 606
      _node_maps.push_back(std::make_pair(caption, storage));
608 607
      return *this;
609 608
    }
610 609

	
611 610
    /// \brief Node map reading rule
612 611
    ///
613 612
    /// Add a node map reading rule with specialized converter to the
614 613
    /// reader.
615 614
    template <typename Map, typename Converter>
616 615
    DigraphReader& nodeMap(const std::string& caption, Map& map,
617 616
                           const Converter& converter = Converter()) {
618 617
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
619 618
      _reader_bits::MapStorageBase<Node>* storage =
620 619
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
621 620
      _node_maps.push_back(std::make_pair(caption, storage));
622 621
      return *this;
623 622
    }
624 623

	
625 624
    /// \brief Arc map reading rule
626 625
    ///
627 626
    /// Add an arc map reading rule to the reader.
628 627
    template <typename Map>
629 628
    DigraphReader& arcMap(const std::string& caption, Map& map) {
630 629
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
631 630
      _reader_bits::MapStorageBase<Arc>* storage =
632 631
        new _reader_bits::MapStorage<Arc, Map>(map);
633 632
      _arc_maps.push_back(std::make_pair(caption, storage));
634 633
      return *this;
635 634
    }
636 635

	
637 636
    /// \brief Arc map reading rule
638 637
    ///
639 638
    /// Add an arc map reading rule with specialized converter to the
640 639
    /// reader.
641 640
    template <typename Map, typename Converter>
642 641
    DigraphReader& arcMap(const std::string& caption, Map& map,
643 642
                          const Converter& converter = Converter()) {
644 643
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
645 644
      _reader_bits::MapStorageBase<Arc>* storage =
646 645
        new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
647 646
      _arc_maps.push_back(std::make_pair(caption, storage));
648 647
      return *this;
649 648
    }
650 649

	
651 650
    /// \brief Attribute reading rule
652 651
    ///
653 652
    /// Add an attribute reading rule to the reader.
654 653
    template <typename Value>
655 654
    DigraphReader& attribute(const std::string& caption, Value& value) {
656 655
      _reader_bits::ValueStorageBase* storage =
657 656
        new _reader_bits::ValueStorage<Value>(value);
658 657
      _attributes.insert(std::make_pair(caption, storage));
659 658
      return *this;
660 659
    }
661 660

	
662 661
    /// \brief Attribute reading rule
663 662
    ///
664 663
    /// Add an attribute reading rule with specialized converter to the
665 664
    /// reader.
... ...
@@ -1095,535 +1094,562 @@
1095 1094
        {
1096 1095
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1097 1096
          while (it != _attributes.end() && it->first == attr) {
1098 1097
            it->second->set(token);
1099 1098
            ++it;
1100 1099
          }
1101 1100
        }
1102 1101

	
1103 1102
      }
1104 1103
      if (readSuccess()) {
1105 1104
        line.putback(c);
1106 1105
      }
1107 1106
      for (typename Attributes::iterator it = _attributes.begin();
1108 1107
           it != _attributes.end(); ++it) {
1109 1108
        if (read_attr.find(it->first) == read_attr.end()) {
1110 1109
          std::ostringstream msg;
1111 1110
          msg << "Attribute not found: " << it->first;
1112 1111
          throw FormatError(msg.str());
1113 1112
        }
1114 1113
      }
1115 1114
    }
1116 1115

	
1117 1116
  public:
1118 1117

	
1119 1118
    /// \name Execution of the reader
1120 1119
    /// @{
1121 1120

	
1122 1121
    /// \brief Start the batch processing
1123 1122
    ///
1124 1123
    /// This function starts the batch processing
1125 1124
    void run() {
1126 1125
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1127 1126

	
1128 1127
      bool nodes_done = _skip_nodes;
1129 1128
      bool arcs_done = _skip_arcs;
1130 1129
      bool attributes_done = false;
1131 1130

	
1132 1131
      line_num = 0;
1133 1132
      readLine();
1134 1133
      skipSection();
1135 1134

	
1136 1135
      while (readSuccess()) {
1137 1136
        try {
1138 1137
          char c;
1139 1138
          std::string section, caption;
1140 1139
          line >> c;
1141 1140
          _reader_bits::readToken(line, section);
1142 1141
          _reader_bits::readToken(line, caption);
1143 1142

	
1144 1143
          if (line >> c)
1145 1144
            throw FormatError("Extra character at the end of line");
1146 1145

	
1147 1146
          if (section == "nodes" && !nodes_done) {
1148 1147
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1149 1148
              readNodes();
1150 1149
              nodes_done = true;
1151 1150
            }
1152 1151
          } else if ((section == "arcs" || section == "edges") &&
1153 1152
                     !arcs_done) {
1154 1153
            if (_arcs_caption.empty() || _arcs_caption == caption) {
1155 1154
              readArcs();
1156 1155
              arcs_done = true;
1157 1156
            }
1158 1157
          } else if (section == "attributes" && !attributes_done) {
1159 1158
            if (_attributes_caption.empty() || _attributes_caption == caption) {
1160 1159
              readAttributes();
1161 1160
              attributes_done = true;
1162 1161
            }
1163 1162
          } else {
1164 1163
            readLine();
1165 1164
            skipSection();
1166 1165
          }
1167 1166
        } catch (FormatError& error) {
1168 1167
          error.line(line_num);
1169 1168
          error.file(_filename);
1170 1169
          throw;
1171 1170
        }
1172 1171
      }
1173 1172

	
1174 1173
      if (!nodes_done) {
1175 1174
        throw FormatError("Section @nodes not found");
1176 1175
      }
1177 1176

	
1178 1177
      if (!arcs_done) {
1179 1178
        throw FormatError("Section @arcs not found");
1180 1179
      }
1181 1180

	
1182 1181
      if (!attributes_done && !_attributes.empty()) {
1183 1182
        throw FormatError("Section @attributes not found");
1184 1183
      }
1185 1184

	
1186 1185
    }
1187 1186

	
1188 1187
    /// @}
1189 1188

	
1190 1189
  };
1190
  
1191
  /// \ingroup lemon_io
1192
  ///
1193
  /// \brief Return a \ref DigraphReader class
1194
  ///
1195
  /// This function just returns a \ref DigraphReader class.
1196
  ///
1197
  /// With this function a digraph can be read from an 
1198
  /// \ref lgf-format "LGF" file or input stream with several maps and
1199
  /// attributes. For example, there is network flow problem on a
1200
  /// digraph, i.e. a digraph with a \e capacity map on the arcs and
1201
  /// \e source and \e target nodes. This digraph can be read with the
1202
  /// following code:
1203
  ///
1204
  ///\code
1205
  ///ListDigraph digraph;
1206
  ///ListDigraph::ArcMap<int> cm(digraph);
1207
  ///ListDigraph::Node src, trg;
1208
  ///digraphReader(digraph, std::cin).
1209
  ///  arcMap("capacity", cap).
1210
  ///  node("source", src).
1211
  ///  node("target", trg).
1212
  ///  run();
1213
  ///\endcode
1214
  ///
1215
  /// For a complete documentation, please see the \ref DigraphReader
1216
  /// class documentation.
1217
  /// \warning Don't forget to put the \ref DigraphReader::run() "run()"
1218
  /// to the end of the parameter list.
1219
  /// \relates DigraphReader
1220
  /// \sa digraphReader(TDGR& digraph, const std::string& fn)
1221
  /// \sa digraphReader(TDGR& digraph, const char* fn)
1222
  template <typename TDGR>
1223
  DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is) {
1224
    DigraphReader<TDGR> tmp(digraph, is);
1225
    return tmp;
1226
  }
1191 1227

	
1192 1228
  /// \brief Return a \ref DigraphReader class
1193 1229
  ///
1194 1230
  /// This function just returns a \ref DigraphReader class.
1195 1231
  /// \relates DigraphReader
1196
  template <typename Digraph>
1197
  DigraphReader<Digraph> digraphReader(Digraph& digraph, std::istream& is) {
1198
    DigraphReader<Digraph> tmp(digraph, is);
1232
  /// \sa digraphReader(TDGR& digraph, std::istream& is)
1233
  template <typename TDGR>
1234
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn) {
1235
    DigraphReader<TDGR> tmp(digraph, fn);
1199 1236
    return tmp;
1200 1237
  }
1201 1238

	
1202 1239
  /// \brief Return a \ref DigraphReader class
1203 1240
  ///
1204 1241
  /// This function just returns a \ref DigraphReader class.
1205 1242
  /// \relates DigraphReader
1206
  template <typename Digraph>
1207
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
1208
                                       const std::string& fn) {
1209
    DigraphReader<Digraph> tmp(digraph, fn);
1243
  /// \sa digraphReader(TDGR& digraph, std::istream& is)
1244
  template <typename TDGR>
1245
  DigraphReader<TDGR> digraphReader(TDGR& digraph, const char* fn) {
1246
    DigraphReader<TDGR> tmp(digraph, fn);
1210 1247
    return tmp;
1211 1248
  }
1212 1249

	
1213
  /// \brief Return a \ref DigraphReader class
1214
  ///
1215
  /// This function just returns a \ref DigraphReader class.
1216
  /// \relates DigraphReader
1217
  template <typename Digraph>
1218
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const char* fn) {
1219
    DigraphReader<Digraph> tmp(digraph, fn);
1220
    return tmp;
1221
  }
1222

	
1223
  template <typename Graph>
1250
  template <typename GR>
1224 1251
  class GraphReader;
1225 1252
 
1226
  template <typename Graph>
1227
  GraphReader<Graph> graphReader(Graph& graph, 
1228
                                 std::istream& is = std::cin);
1229
  template <typename Graph>
1230
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn);
1231
  template <typename Graph>
1232
  GraphReader<Graph> graphReader(Graph& graph, const char *fn);
1253
  template <typename TGR>
1254
  GraphReader<TGR> graphReader(TGR& graph, std::istream& is = std::cin);
1255
  template <typename TGR>
1256
  GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
1257
  template <typename TGR>
1258
  GraphReader<TGR> graphReader(TGR& graph, const char *fn);
1233 1259

	
1234 1260
  /// \ingroup lemon_io
1235 1261
  ///
1236 1262
  /// \brief \ref lgf-format "LGF" reader for undirected graphs
1237 1263
  ///
1238 1264
  /// This utility reads an \ref lgf-format "LGF" file.
1239 1265
  ///
1240 1266
  /// It can be used almost the same way as \c DigraphReader.
1241 1267
  /// The only difference is that this class can handle edges and
1242 1268
  /// edge maps as well as arcs and arc maps.
1243 1269
  ///
1244 1270
  /// The columns in the \c \@edges (or \c \@arcs) section are the
1245 1271
  /// edge maps. However, if there are two maps with the same name
1246 1272
  /// prefixed with \c '+' and \c '-', then these can be read into an
1247 1273
  /// arc map.  Similarly, an attribute can be read into an arc, if
1248 1274
  /// it's value is an edge label prefixed with \c '+' or \c '-'.
1249 1275
  template <typename GR>
1250 1276
  class GraphReader {
1251 1277
  public:
1252 1278

	
1253 1279
    typedef GR Graph;
1254 1280

	
1255 1281
  private:
1256 1282

	
1257
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1283
    TEMPLATE_GRAPH_TYPEDEFS(GR);
1258 1284

	
1259 1285
    std::istream* _is;
1260 1286
    bool local_is;
1261 1287
    std::string _filename;
1262 1288

	
1263
    Graph& _graph;
1289
    GR& _graph;
1264 1290

	
1265 1291
    std::string _nodes_caption;
1266 1292
    std::string _edges_caption;
1267 1293
    std::string _attributes_caption;
1268 1294

	
1269 1295
    typedef std::map<std::string, Node> NodeIndex;
1270 1296
    NodeIndex _node_index;
1271 1297
    typedef std::map<std::string, Edge> EdgeIndex;
1272 1298
    EdgeIndex _edge_index;
1273 1299

	
1274 1300
    typedef std::vector<std::pair<std::string,
1275 1301
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
1276 1302
    NodeMaps _node_maps;
1277 1303

	
1278 1304
    typedef std::vector<std::pair<std::string,
1279 1305
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1280 1306
    EdgeMaps _edge_maps;
1281 1307

	
1282 1308
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1283 1309
      Attributes;
1284 1310
    Attributes _attributes;
1285 1311

	
1286 1312
    bool _use_nodes;
1287 1313
    bool _use_edges;
1288 1314

	
1289 1315
    bool _skip_nodes;
1290 1316
    bool _skip_edges;
1291 1317

	
1292 1318
    int line_num;
1293 1319
    std::istringstream line;
1294 1320

	
1295 1321
  public:
1296 1322

	
1297 1323
    /// \brief Constructor
1298 1324
    ///
1299 1325
    /// Construct an undirected graph reader, which reads from the given
1300 1326
    /// input stream.
1301
    GraphReader(Graph& graph, std::istream& is = std::cin)
1327
    GraphReader(GR& graph, std::istream& is = std::cin)
1302 1328
      : _is(&is), local_is(false), _graph(graph),
1303 1329
        _use_nodes(false), _use_edges(false),
1304 1330
        _skip_nodes(false), _skip_edges(false) {}
1305 1331

	
1306 1332
    /// \brief Constructor
1307 1333
    ///
1308 1334
    /// Construct an undirected graph reader, which reads from the given
1309 1335
    /// file.
1310
    GraphReader(Graph& graph, const std::string& fn)
1336
    GraphReader(GR& graph, const std::string& fn)
1311 1337
      : _is(new std::ifstream(fn.c_str())), local_is(true),
1312 1338
        _filename(fn), _graph(graph),
1313 1339
        _use_nodes(false), _use_edges(false),
1314 1340
        _skip_nodes(false), _skip_edges(false) {
1315 1341
      if (!(*_is)) {
1316 1342
        delete _is;
1317 1343
        throw IoError("Cannot open file", fn);
1318 1344
      }
1319 1345
    }
1320 1346

	
1321 1347
    /// \brief Constructor
1322 1348
    ///
1323 1349
    /// Construct an undirected graph reader, which reads from the given
1324 1350
    /// file.
1325
    GraphReader(Graph& graph, const char* fn)
1351
    GraphReader(GR& graph, const char* fn)
1326 1352
      : _is(new std::ifstream(fn)), local_is(true),
1327 1353
        _filename(fn), _graph(graph),
1328 1354
        _use_nodes(false), _use_edges(false),
1329 1355
        _skip_nodes(false), _skip_edges(false) {
1330 1356
      if (!(*_is)) {
1331 1357
        delete _is;
1332 1358
        throw IoError("Cannot open file", fn);
1333 1359
      }
1334 1360
    }
1335 1361

	
1336 1362
    /// \brief Destructor
1337 1363
    ~GraphReader() {
1338 1364
      for (typename NodeMaps::iterator it = _node_maps.begin();
1339 1365
           it != _node_maps.end(); ++it) {
1340 1366
        delete it->second;
1341 1367
      }
1342 1368

	
1343 1369
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1344 1370
           it != _edge_maps.end(); ++it) {
1345 1371
        delete it->second;
1346 1372
      }
1347 1373

	
1348 1374
      for (typename Attributes::iterator it = _attributes.begin();
1349 1375
           it != _attributes.end(); ++it) {
1350 1376
        delete it->second;
1351 1377
      }
1352 1378

	
1353 1379
      if (local_is) {
1354 1380
        delete _is;
1355 1381
      }
1356 1382

	
1357 1383
    }
1358 1384

	
1359 1385
  private:
1360
    template <typename Graph>
1361
    friend GraphReader<Graph> graphReader(Graph& graph, std::istream& is);
1362
    template <typename Graph>
1363
    friend GraphReader<Graph> graphReader(Graph& graph, const std::string& fn); 
1364
    template <typename Graph>
1365
    friend GraphReader<Graph> graphReader(Graph& graph, const char *fn);
1386
    template <typename TGR>
1387
    friend GraphReader<TGR> graphReader(TGR& graph, std::istream& is);
1388
    template <typename TGR>
1389
    friend GraphReader<TGR> graphReader(TGR& graph, const std::string& fn); 
1390
    template <typename TGR>
1391
    friend GraphReader<TGR> graphReader(TGR& graph, const char *fn);
1366 1392

	
1367 1393
    GraphReader(GraphReader& other)
1368 1394
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1369 1395
        _use_nodes(other._use_nodes), _use_edges(other._use_edges),
1370 1396
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1371 1397

	
1372 1398
      other._is = 0;
1373 1399
      other.local_is = false;
1374 1400

	
1375 1401
      _node_index.swap(other._node_index);
1376 1402
      _edge_index.swap(other._edge_index);
1377 1403

	
1378 1404
      _node_maps.swap(other._node_maps);
1379 1405
      _edge_maps.swap(other._edge_maps);
1380 1406
      _attributes.swap(other._attributes);
1381 1407

	
1382 1408
      _nodes_caption = other._nodes_caption;
1383 1409
      _edges_caption = other._edges_caption;
1384 1410
      _attributes_caption = other._attributes_caption;
1385 1411

	
1386 1412
    }
1387 1413

	
1388 1414
    GraphReader& operator=(const GraphReader&);
1389 1415

	
1390 1416
  public:
1391 1417

	
1392 1418
    /// \name Reading rules
1393 1419
    /// @{
1394 1420

	
1395 1421
    /// \brief Node map reading rule
1396 1422
    ///
1397 1423
    /// Add a node map reading rule to the reader.
1398 1424
    template <typename Map>
1399 1425
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1400 1426
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1401 1427
      _reader_bits::MapStorageBase<Node>* storage =
1402 1428
        new _reader_bits::MapStorage<Node, Map>(map);
1403 1429
      _node_maps.push_back(std::make_pair(caption, storage));
1404 1430
      return *this;
1405 1431
    }
1406 1432

	
1407 1433
    /// \brief Node map reading rule
1408 1434
    ///
1409 1435
    /// Add a node map reading rule with specialized converter to the
1410 1436
    /// reader.
1411 1437
    template <typename Map, typename Converter>
1412 1438
    GraphReader& nodeMap(const std::string& caption, Map& map,
1413 1439
                           const Converter& converter = Converter()) {
1414 1440
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1415 1441
      _reader_bits::MapStorageBase<Node>* storage =
1416 1442
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1417 1443
      _node_maps.push_back(std::make_pair(caption, storage));
1418 1444
      return *this;
1419 1445
    }
1420 1446

	
1421 1447
    /// \brief Edge map reading rule
1422 1448
    ///
1423 1449
    /// Add an edge map reading rule to the reader.
1424 1450
    template <typename Map>
1425 1451
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1426 1452
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1427 1453
      _reader_bits::MapStorageBase<Edge>* storage =
1428 1454
        new _reader_bits::MapStorage<Edge, Map>(map);
1429 1455
      _edge_maps.push_back(std::make_pair(caption, storage));
1430 1456
      return *this;
1431 1457
    }
1432 1458

	
1433 1459
    /// \brief Edge map reading rule
1434 1460
    ///
1435 1461
    /// Add an edge map reading rule with specialized converter to the
1436 1462
    /// reader.
1437 1463
    template <typename Map, typename Converter>
1438 1464
    GraphReader& edgeMap(const std::string& caption, Map& map,
1439 1465
                          const Converter& converter = Converter()) {
1440 1466
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1441 1467
      _reader_bits::MapStorageBase<Edge>* storage =
1442 1468
        new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1443 1469
      _edge_maps.push_back(std::make_pair(caption, storage));
1444 1470
      return *this;
1445 1471
    }
1446 1472

	
1447 1473
    /// \brief Arc map reading rule
1448 1474
    ///
1449 1475
    /// Add an arc map reading rule to the reader.
1450 1476
    template <typename Map>
1451 1477
    GraphReader& arcMap(const std::string& caption, Map& map) {
1452 1478
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1453 1479
      _reader_bits::MapStorageBase<Edge>* forward_storage =
1454 1480
        new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1455 1481
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1456 1482
      _reader_bits::MapStorageBase<Edge>* backward_storage =
1457
        new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1483
        new _reader_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
1458 1484
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1459 1485
      return *this;
1460 1486
    }
1461 1487

	
1462 1488
    /// \brief Arc map reading rule
1463 1489
    ///
1464 1490
    /// Add an arc map reading rule with specialized converter to the
1465 1491
    /// reader.
1466 1492
    template <typename Map, typename Converter>
1467 1493
    GraphReader& arcMap(const std::string& caption, Map& map,
1468 1494
                          const Converter& converter = Converter()) {
1469 1495
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1470 1496
      _reader_bits::MapStorageBase<Edge>* forward_storage =
1471
        new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1497
        new _reader_bits::GraphArcMapStorage<GR, true, Map, Converter>
1472 1498
        (_graph, map, converter);
1473 1499
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1474 1500
      _reader_bits::MapStorageBase<Edge>* backward_storage =
1475
        new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1501
        new _reader_bits::GraphArcMapStorage<GR, false, Map, Converter>
1476 1502
        (_graph, map, converter);
1477 1503
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1478 1504
      return *this;
1479 1505
    }
1480 1506

	
1481 1507
    /// \brief Attribute reading rule
1482 1508
    ///
1483 1509
    /// Add an attribute reading rule to the reader.
1484 1510
    template <typename Value>
1485 1511
    GraphReader& attribute(const std::string& caption, Value& value) {
1486 1512
      _reader_bits::ValueStorageBase* storage =
1487 1513
        new _reader_bits::ValueStorage<Value>(value);
1488 1514
      _attributes.insert(std::make_pair(caption, storage));
1489 1515
      return *this;
1490 1516
    }
1491 1517

	
1492 1518
    /// \brief Attribute reading rule
1493 1519
    ///
1494 1520
    /// Add an attribute reading rule with specialized converter to the
1495 1521
    /// reader.
1496 1522
    template <typename Value, typename Converter>
1497 1523
    GraphReader& attribute(const std::string& caption, Value& value,
1498 1524
                             const Converter& converter = Converter()) {
1499 1525
      _reader_bits::ValueStorageBase* storage =
1500 1526
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1501 1527
      _attributes.insert(std::make_pair(caption, storage));
1502 1528
      return *this;
1503 1529
    }
1504 1530

	
1505 1531
    /// \brief Node reading rule
1506 1532
    ///
1507 1533
    /// Add a node reading rule to reader.
1508 1534
    GraphReader& node(const std::string& caption, Node& node) {
1509 1535
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1510 1536
      Converter converter(_node_index);
1511 1537
      _reader_bits::ValueStorageBase* storage =
1512 1538
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1513 1539
      _attributes.insert(std::make_pair(caption, storage));
1514 1540
      return *this;
1515 1541
    }
1516 1542

	
1517 1543
    /// \brief Edge reading rule
1518 1544
    ///
1519 1545
    /// Add an edge reading rule to reader.
1520 1546
    GraphReader& edge(const std::string& caption, Edge& edge) {
1521 1547
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1522 1548
      Converter converter(_edge_index);
1523 1549
      _reader_bits::ValueStorageBase* storage =
1524 1550
        new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1525 1551
      _attributes.insert(std::make_pair(caption, storage));
1526 1552
      return *this;
1527 1553
    }
1528 1554

	
1529 1555
    /// \brief Arc reading rule
1530 1556
    ///
1531 1557
    /// Add an arc reading rule to reader.
1532 1558
    GraphReader& arc(const std::string& caption, Arc& arc) {
1533
      typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
1559
      typedef _reader_bits::GraphArcLookUpConverter<GR> Converter;
1534 1560
      Converter converter(_graph, _edge_index);
1535 1561
      _reader_bits::ValueStorageBase* storage =
1536 1562
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1537 1563
      _attributes.insert(std::make_pair(caption, storage));
1538 1564
      return *this;
1539 1565
    }
1540 1566

	
1541 1567
    /// @}
1542 1568

	
1543 1569
    /// \name Select section by name
1544 1570
    /// @{
1545 1571

	
1546 1572
    /// \brief Set \c \@nodes section to be read
1547 1573
    ///
1548 1574
    /// Set \c \@nodes section to be read.
1549 1575
    GraphReader& nodes(const std::string& caption) {
1550 1576
      _nodes_caption = caption;
1551 1577
      return *this;
1552 1578
    }
1553 1579

	
1554 1580
    /// \brief Set \c \@edges section to be read
1555 1581
    ///
1556 1582
    /// Set \c \@edges section to be read.
1557 1583
    GraphReader& edges(const std::string& caption) {
1558 1584
      _edges_caption = caption;
1559 1585
      return *this;
1560 1586
    }
1561 1587

	
1562 1588
    /// \brief Set \c \@attributes section to be read
1563 1589
    ///
1564 1590
    /// Set \c \@attributes section to be read.
1565 1591
    GraphReader& attributes(const std::string& caption) {
1566 1592
      _attributes_caption = caption;
1567 1593
      return *this;
1568 1594
    }
1569 1595

	
1570 1596
    /// @}
1571 1597

	
1572 1598
    /// \name Using previously constructed node or edge set
1573 1599
    /// @{
1574 1600

	
1575 1601
    /// \brief Use previously constructed node set
1576 1602
    ///
1577 1603
    /// Use previously constructed node set, and specify the node
1578 1604
    /// label map.
1579 1605
    template <typename Map>
1580 1606
    GraphReader& useNodes(const Map& map) {
1581 1607
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1582 1608
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1583 1609
      _use_nodes = true;
1584 1610
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1585 1611
      for (NodeIt n(_graph); n != INVALID; ++n) {
1586 1612
        _node_index.insert(std::make_pair(converter(map[n]), n));
1587 1613
      }
1588 1614
      return *this;
1589 1615
    }
1590 1616

	
1591 1617
    /// \brief Use previously constructed node set
1592 1618
    ///
1593 1619
    /// Use previously constructed node set, and specify the node
1594 1620
    /// label map and a functor which converts the label map values to
1595 1621
    /// \c std::string.
1596 1622
    template <typename Map, typename Converter>
1597 1623
    GraphReader& useNodes(const Map& map,
1598 1624
                            const Converter& converter = Converter()) {
1599 1625
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1600 1626
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1601 1627
      _use_nodes = true;
1602 1628
      for (NodeIt n(_graph); n != INVALID; ++n) {
1603 1629
        _node_index.insert(std::make_pair(converter(map[n]), n));
1604 1630
      }
1605 1631
      return *this;
1606 1632
    }
1607 1633

	
1608 1634
    /// \brief Use previously constructed edge set
1609 1635
    ///
1610 1636
    /// Use previously constructed edge set, and specify the edge
1611 1637
    /// label map.
1612 1638
    template <typename Map>
1613 1639
    GraphReader& useEdges(const Map& map) {
1614 1640
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1615 1641
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1616 1642
      _use_edges = true;
1617 1643
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1618 1644
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1619 1645
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1620 1646
      }
1621 1647
      return *this;
1622 1648
    }
1623 1649

	
1624 1650
    /// \brief Use previously constructed edge set
1625 1651
    ///
1626 1652
    /// Use previously constructed edge set, and specify the edge
1627 1653
    /// label map and a functor which converts the label map values to
1628 1654
    /// \c std::string.
1629 1655
    template <typename Map, typename Converter>
... ...
@@ -1940,219 +1966,244 @@
1940 1966
          while (it != _attributes.end() && it->first == attr) {
1941 1967
            it->second->set(token);
1942 1968
            ++it;
1943 1969
          }
1944 1970
        }
1945 1971

	
1946 1972
      }
1947 1973
      if (readSuccess()) {
1948 1974
        line.putback(c);
1949 1975
      }
1950 1976
      for (typename Attributes::iterator it = _attributes.begin();
1951 1977
           it != _attributes.end(); ++it) {
1952 1978
        if (read_attr.find(it->first) == read_attr.end()) {
1953 1979
          std::ostringstream msg;
1954 1980
          msg << "Attribute not found: " << it->first;
1955 1981
          throw FormatError(msg.str());
1956 1982
        }
1957 1983
      }
1958 1984
    }
1959 1985

	
1960 1986
  public:
1961 1987

	
1962 1988
    /// \name Execution of the reader
1963 1989
    /// @{
1964 1990

	
1965 1991
    /// \brief Start the batch processing
1966 1992
    ///
1967 1993
    /// This function starts the batch processing
1968 1994
    void run() {
1969 1995

	
1970 1996
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1971 1997

	
1972 1998
      bool nodes_done = _skip_nodes;
1973 1999
      bool edges_done = _skip_edges;
1974 2000
      bool attributes_done = false;
1975 2001

	
1976 2002
      line_num = 0;
1977 2003
      readLine();
1978 2004
      skipSection();
1979 2005

	
1980 2006
      while (readSuccess()) {
1981 2007
        try {
1982 2008
          char c;
1983 2009
          std::string section, caption;
1984 2010
          line >> c;
1985 2011
          _reader_bits::readToken(line, section);
1986 2012
          _reader_bits::readToken(line, caption);
1987 2013

	
1988 2014
          if (line >> c)
1989 2015
            throw FormatError("Extra character at the end of line");
1990 2016

	
1991 2017
          if (section == "nodes" && !nodes_done) {
1992 2018
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1993 2019
              readNodes();
1994 2020
              nodes_done = true;
1995 2021
            }
1996 2022
          } else if ((section == "edges" || section == "arcs") &&
1997 2023
                     !edges_done) {
1998 2024
            if (_edges_caption.empty() || _edges_caption == caption) {
1999 2025
              readEdges();
2000 2026
              edges_done = true;
2001 2027
            }
2002 2028
          } else if (section == "attributes" && !attributes_done) {
2003 2029
            if (_attributes_caption.empty() || _attributes_caption == caption) {
2004 2030
              readAttributes();
2005 2031
              attributes_done = true;
2006 2032
            }
2007 2033
          } else {
2008 2034
            readLine();
2009 2035
            skipSection();
2010 2036
          }
2011 2037
        } catch (FormatError& error) {
2012 2038
          error.line(line_num);
2013 2039
          error.file(_filename);
2014 2040
          throw;
2015 2041
        }
2016 2042
      }
2017 2043

	
2018 2044
      if (!nodes_done) {
2019 2045
        throw FormatError("Section @nodes not found");
2020 2046
      }
2021 2047

	
2022 2048
      if (!edges_done) {
2023 2049
        throw FormatError("Section @edges not found");
2024 2050
      }
2025 2051

	
2026 2052
      if (!attributes_done && !_attributes.empty()) {
2027 2053
        throw FormatError("Section @attributes not found");
2028 2054
      }
2029 2055

	
2030 2056
    }
2031 2057

	
2032 2058
    /// @}
2033 2059

	
2034 2060
  };
2035 2061

	
2062
  /// \ingroup lemon_io
2063
  ///
2064
  /// \brief Return a \ref GraphReader class
2065
  ///
2066
  /// This function just returns a \ref GraphReader class. 
2067
  ///
2068
  /// With this function a graph can be read from an 
2069
  /// \ref lgf-format "LGF" file or input stream with several maps and
2070
  /// attributes. For example, there is weighted matching problem on a
2071
  /// graph, i.e. a graph with a \e weight map on the edges. This
2072
  /// graph can be read with the following code:
2073
  ///
2074
  ///\code
2075
  ///ListGraph graph;
2076
  ///ListGraph::EdgeMap<int> weight(graph);
2077
  ///graphReader(graph, std::cin).
2078
  ///  edgeMap("weight", weight).
2079
  ///  run();
2080
  ///\endcode
2081
  ///
2082
  /// For a complete documentation, please see the \ref GraphReader
2083
  /// class documentation.
2084
  /// \warning Don't forget to put the \ref GraphReader::run() "run()"
2085
  /// to the end of the parameter list.
2086
  /// \relates GraphReader
2087
  /// \sa graphReader(TGR& graph, const std::string& fn)
2088
  /// \sa graphReader(TGR& graph, const char* fn)
2089
  template <typename TGR>
2090
  GraphReader<TGR> graphReader(TGR& graph, std::istream& is) {
2091
    GraphReader<TGR> tmp(graph, is);
2092
    return tmp;
2093
  }
2094

	
2036 2095
  /// \brief Return a \ref GraphReader class
2037 2096
  ///
2038 2097
  /// This function just returns a \ref GraphReader class.
2039 2098
  /// \relates GraphReader
2040
  template <typename Graph>
2041
  GraphReader<Graph> graphReader(Graph& graph, std::istream& is) {
2042
    GraphReader<Graph> tmp(graph, is);
2099
  /// \sa graphReader(TGR& graph, std::istream& is)
2100
  template <typename TGR>
2101
  GraphReader<TGR> graphReader(TGR& graph, const std::string& fn) {
2102
    GraphReader<TGR> tmp(graph, fn);
2043 2103
    return tmp;
2044 2104
  }
2045 2105

	
2046 2106
  /// \brief Return a \ref GraphReader class
2047 2107
  ///
2048 2108
  /// This function just returns a \ref GraphReader class.
2049 2109
  /// \relates GraphReader
2050
  template <typename Graph>
2051
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn) {
2052
    GraphReader<Graph> tmp(graph, fn);
2053
    return tmp;
2054
  }
2055

	
2056
  /// \brief Return a \ref GraphReader class
2057
  ///
2058
  /// This function just returns a \ref GraphReader class.
2059
  /// \relates GraphReader
2060
  template <typename Graph>
2061
  GraphReader<Graph> graphReader(Graph& graph, const char* fn) {
2062
    GraphReader<Graph> tmp(graph, fn);
2110
  /// \sa graphReader(TGR& graph, std::istream& is)
2111
  template <typename TGR>
2112
  GraphReader<TGR> graphReader(TGR& graph, const char* fn) {
2113
    GraphReader<TGR> tmp(graph, fn);
2063 2114
    return tmp;
2064 2115
  }
2065 2116

	
2066 2117
  class SectionReader;
2067 2118

	
2068 2119
  SectionReader sectionReader(std::istream& is);
2069 2120
  SectionReader sectionReader(const std::string& fn);
2070 2121
  SectionReader sectionReader(const char* fn);
2071 2122

	
2072 2123
  /// \ingroup lemon_io
2073 2124
  ///
2074 2125
  /// \brief Section reader class
2075 2126
  ///
2076 2127
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
2077 2128
  /// which contain any data in arbitrary format. Such sections can be
2078 2129
  /// read with this class. A reading rule can be added to the class
2079 2130
  /// with two different functions. With the \c sectionLines() function a
2080 2131
  /// functor can process the section line-by-line, while with the \c
2081 2132
  /// sectionStream() member the section can be read from an input
2082 2133
  /// stream.
2083 2134
  class SectionReader {
2084 2135
  private:
2085 2136

	
2086 2137
    std::istream* _is;
2087 2138
    bool local_is;
2088 2139
    std::string _filename;
2089 2140

	
2090 2141
    typedef std::map<std::string, _reader_bits::Section*> Sections;
2091 2142
    Sections _sections;
2092 2143

	
2093 2144
    int line_num;
2094 2145
    std::istringstream line;
2095 2146

	
2096 2147
  public:
2097 2148

	
2098 2149
    /// \brief Constructor
2099 2150
    ///
2100 2151
    /// Construct a section reader, which reads from the given input
2101 2152
    /// stream.
2102 2153
    SectionReader(std::istream& is)
2103 2154
      : _is(&is), local_is(false) {}
2104 2155

	
2105 2156
    /// \brief Constructor
2106 2157
    ///
2107 2158
    /// Construct a section reader, which reads from the given file.
2108 2159
    SectionReader(const std::string& fn)
2109 2160
      : _is(new std::ifstream(fn.c_str())), local_is(true),
2110 2161
        _filename(fn) {
2111 2162
      if (!(*_is)) {
2112 2163
        delete _is;
2113 2164
        throw IoError("Cannot open file", fn);
2114 2165
      }
2115 2166
    }
2116 2167

	
2117 2168
    /// \brief Constructor
2118 2169
    ///
2119 2170
    /// Construct a section reader, which reads from the given file.
2120 2171
    SectionReader(const char* fn)
2121 2172
      : _is(new std::ifstream(fn)), local_is(true),
2122 2173
        _filename(fn) {
2123 2174
      if (!(*_is)) {
2124 2175
        delete _is;
2125 2176
        throw IoError("Cannot open file", fn);
2126 2177
      }
2127 2178
    }
2128 2179

	
2129 2180
    /// \brief Destructor
2130 2181
    ~SectionReader() {
2131 2182
      for (Sections::iterator it = _sections.begin();
2132 2183
           it != _sections.end(); ++it) {
2133 2184
        delete it->second;
2134 2185
      }
2135 2186

	
2136 2187
      if (local_is) {
2137 2188
        delete _is;
2138 2189
      }
2139 2190

	
2140 2191
    }
2141 2192

	
2142 2193
  private:
2143 2194

	
2144 2195
    friend SectionReader sectionReader(std::istream& is);
2145 2196
    friend SectionReader sectionReader(const std::string& fn);
2146 2197
    friend SectionReader sectionReader(const char* fn);
2147 2198

	
2148 2199
    SectionReader(SectionReader& other)
2149 2200
      : _is(other._is), local_is(other.local_is) {
2150 2201

	
2151 2202
      other._is = 0;
2152 2203
      other.local_is = false;
2153 2204

	
2154 2205
      _sections.swap(other._sections);
2155 2206
    }
2156 2207

	
2157 2208
    SectionReader& operator=(const SectionReader&);
2158 2209

	
... ...
@@ -2223,214 +2274,224 @@
2223 2274
      return *this;
2224 2275
    }
2225 2276

	
2226 2277
    /// @}
2227 2278

	
2228 2279
  private:
2229 2280

	
2230 2281
    bool readLine() {
2231 2282
      std::string str;
2232 2283
      while(++line_num, std::getline(*_is, str)) {
2233 2284
        line.clear(); line.str(str);
2234 2285
        char c;
2235 2286
        if (line >> std::ws >> c && c != '#') {
2236 2287
          line.putback(c);
2237 2288
          return true;
2238 2289
        }
2239 2290
      }
2240 2291
      return false;
2241 2292
    }
2242 2293

	
2243 2294
    bool readSuccess() {
2244 2295
      return static_cast<bool>(*_is);
2245 2296
    }
2246 2297

	
2247 2298
    void skipSection() {
2248 2299
      char c;
2249 2300
      while (readSuccess() && line >> c && c != '@') {
2250 2301
        readLine();
2251 2302
      }
2252 2303
      if (readSuccess()) {
2253 2304
        line.putback(c);
2254 2305
      }
2255 2306
    }
2256 2307

	
2257 2308
  public:
2258 2309

	
2259 2310

	
2260 2311
    /// \name Execution of the reader
2261 2312
    /// @{
2262 2313

	
2263 2314
    /// \brief Start the batch processing
2264 2315
    ///
2265 2316
    /// This function starts the batch processing.
2266 2317
    void run() {
2267 2318

	
2268 2319
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2269 2320

	
2270 2321
      std::set<std::string> extra_sections;
2271 2322

	
2272 2323
      line_num = 0;
2273 2324
      readLine();
2274 2325
      skipSection();
2275 2326

	
2276 2327
      while (readSuccess()) {
2277 2328
        try {
2278 2329
          char c;
2279 2330
          std::string section, caption;
2280 2331
          line >> c;
2281 2332
          _reader_bits::readToken(line, section);
2282 2333
          _reader_bits::readToken(line, caption);
2283 2334

	
2284 2335
          if (line >> c)
2285 2336
            throw FormatError("Extra character at the end of line");
2286 2337

	
2287 2338
          if (extra_sections.find(section) != extra_sections.end()) {
2288 2339
            std::ostringstream msg;
2289 2340
            msg << "Multiple occurence of section: " << section;
2290 2341
            throw FormatError(msg.str());
2291 2342
          }
2292 2343
          Sections::iterator it = _sections.find(section);
2293 2344
          if (it != _sections.end()) {
2294 2345
            extra_sections.insert(section);
2295 2346
            it->second->process(*_is, line_num);
2296 2347
          }
2297 2348
          readLine();
2298 2349
          skipSection();
2299 2350
        } catch (FormatError& error) {
2300 2351
          error.line(line_num);
2301 2352
          error.file(_filename);
2302 2353
          throw;
2303 2354
        }
2304 2355
      }
2305 2356
      for (Sections::iterator it = _sections.begin();
2306 2357
           it != _sections.end(); ++it) {
2307 2358
        if (extra_sections.find(it->first) == extra_sections.end()) {
2308 2359
          std::ostringstream os;
2309 2360
          os << "Cannot find section: " << it->first;
2310 2361
          throw FormatError(os.str());
2311 2362
        }
2312 2363
      }
2313 2364
    }
2314 2365

	
2315 2366
    /// @}
2316 2367

	
2317 2368
  };
2318 2369

	
2370
  /// \ingroup lemon_io
2371
  ///
2372
  /// \brief Return a \ref SectionReader class
2373
  ///
2374
  /// This function just returns a \ref SectionReader class.
2375
  ///
2376
  /// Please see SectionReader documentation about the custom section
2377
  /// input.
2378
  ///
2379
  /// \relates SectionReader
2380
  /// \sa sectionReader(const std::string& fn)
2381
  /// \sa sectionReader(const char *fn)
2382
  inline SectionReader sectionReader(std::istream& is) {
2383
    SectionReader tmp(is);
2384
    return tmp;
2385
  }
2386

	
2319 2387
  /// \brief Return a \ref SectionReader class
2320 2388
  ///
2321 2389
  /// This function just returns a \ref SectionReader class.
2322 2390
  /// \relates SectionReader
2323
  inline SectionReader sectionReader(std::istream& is) {
2324
    SectionReader tmp(is);
2391
  /// \sa sectionReader(std::istream& is)
2392
  inline SectionReader sectionReader(const std::string& fn) {
2393
    SectionReader tmp(fn);
2325 2394
    return tmp;
2326 2395
  }
2327 2396

	
2328 2397
  /// \brief Return a \ref SectionReader class
2329 2398
  ///
2330 2399
  /// This function just returns a \ref SectionReader class.
2331 2400
  /// \relates SectionReader
2332
  inline SectionReader sectionReader(const std::string& fn) {
2333
    SectionReader tmp(fn);
2334
    return tmp;
2335
  }
2336

	
2337
  /// \brief Return a \ref SectionReader class
2338
  ///
2339
  /// This function just returns a \ref SectionReader class.
2340
  /// \relates SectionReader
2401
  /// \sa sectionReader(std::istream& is)
2341 2402
  inline SectionReader sectionReader(const char* fn) {
2342 2403
    SectionReader tmp(fn);
2343 2404
    return tmp;
2344 2405
  }
2345 2406

	
2346 2407
  /// \ingroup lemon_io
2347 2408
  ///
2348 2409
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file
2349 2410
  ///
2350 2411
  /// This class can be used to read the sections, the map names and
2351 2412
  /// the attributes from a file. Usually, the LEMON programs know
2352 2413
  /// that, which type of graph, which maps and which attributes
2353 2414
  /// should be read from a file, but in general tools (like glemon)
2354 2415
  /// the contents of an LGF file should be guessed somehow. This class
2355 2416
  /// reads the graph and stores the appropriate information for
2356 2417
  /// reading the graph.
2357 2418
  ///
2358 2419
  ///\code
2359 2420
  /// LgfContents contents("graph.lgf");
2360 2421
  /// contents.run();
2361 2422
  ///
2362 2423
  /// // Does it contain any node section and arc section?
2363 2424
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
2364 2425
  ///   std::cerr << "Failure, cannot find graph." << std::endl;
2365 2426
  ///   return -1;
2366 2427
  /// }
2367 2428
  /// std::cout << "The name of the default node section: "
2368 2429
  ///           << contents.nodeSection(0) << std::endl;
2369 2430
  /// std::cout << "The number of the arc maps: "
2370 2431
  ///           << contents.arcMaps(0).size() << std::endl;
2371 2432
  /// std::cout << "The name of second arc map: "
2372 2433
  ///           << contents.arcMaps(0)[1] << std::endl;
2373 2434
  ///\endcode
2374 2435
  class LgfContents {
2375 2436
  private:
2376 2437

	
2377 2438
    std::istream* _is;
2378 2439
    bool local_is;
2379 2440

	
2380 2441
    std::vector<std::string> _node_sections;
2381 2442
    std::vector<std::string> _edge_sections;
2382 2443
    std::vector<std::string> _attribute_sections;
2383 2444
    std::vector<std::string> _extra_sections;
2384 2445

	
2385 2446
    std::vector<bool> _arc_sections;
2386 2447

	
2387 2448
    std::vector<std::vector<std::string> > _node_maps;
2388 2449
    std::vector<std::vector<std::string> > _edge_maps;
2389 2450

	
2390 2451
    std::vector<std::vector<std::string> > _attributes;
2391 2452

	
2392 2453

	
2393 2454
    int line_num;
2394 2455
    std::istringstream line;
2395 2456

	
2396 2457
  public:
2397 2458

	
2398 2459
    /// \brief Constructor
2399 2460
    ///
2400 2461
    /// Construct an \e LGF contents reader, which reads from the given
2401 2462
    /// input stream.
2402 2463
    LgfContents(std::istream& is)
2403 2464
      : _is(&is), local_is(false) {}
2404 2465

	
2405 2466
    /// \brief Constructor
2406 2467
    ///
2407 2468
    /// Construct an \e LGF contents reader, which reads from the given
2408 2469
    /// file.
2409 2470
    LgfContents(const std::string& fn)
2410 2471
      : _is(new std::ifstream(fn.c_str())), local_is(true) {
2411 2472
      if (!(*_is)) {
2412 2473
        delete _is;
2413 2474
        throw IoError("Cannot open file", fn);
2414 2475
      }
2415 2476
    }
2416 2477

	
2417 2478
    /// \brief Constructor
2418 2479
    ///
2419 2480
    /// Construct an \e LGF contents reader, which reads from the given
2420 2481
    /// file.
2421 2482
    LgfContents(const char* fn)
2422 2483
      : _is(new std::ifstream(fn)), local_is(true) {
2423 2484
      if (!(*_is)) {
2424 2485
        delete _is;
2425 2486
        throw IoError("Cannot open file", fn);
2426 2487
      }
2427 2488
    }
2428 2489

	
2429 2490
    /// \brief Destructor
2430 2491
    ~LgfContents() {
2431 2492
      if (local_is) delete _is;
2432 2493
    }
2433 2494

	
2434 2495
  private:
2435 2496

	
2436 2497
    LgfContents(const LgfContents&);
Ignore white space 192 line context
... ...
@@ -254,359 +254,357 @@
254 254
        return;
255 255
      case '\f':
256 256
        os << "\\f";
257 257
        return;
258 258
      case '\r':
259 259
        os << "\\r";
260 260
        return;
261 261
      case '\n':
262 262
        os << "\\n";
263 263
        return;
264 264
      case '\t':
265 265
        os << "\\t";
266 266
        return;
267 267
      case '\v':
268 268
        os << "\\v";
269 269
        return;
270 270
      default:
271 271
        if (c < 0x20) {
272 272
          std::ios::fmtflags flags = os.flags();
273 273
          os << '\\' << std::oct << static_cast<int>(c);
274 274
          os.flags(flags);
275 275
        } else {
276 276
          os << c;
277 277
        }
278 278
        return;
279 279
      }
280 280
    }
281 281

	
282 282
    inline bool requireEscape(const std::string& str) {
283 283
      if (str.empty() || str[0] == '@') return true;
284 284
      std::istringstream is(str);
285 285
      char c;
286 286
      while (is.get(c)) {
287 287
        if (isWhiteSpace(c) || isEscaped(c)) {
288 288
          return true;
289 289
        }
290 290
      }
291 291
      return false;
292 292
    }
293 293

	
294 294
    inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
295 295

	
296 296
      if (requireEscape(str)) {
297 297
        os << '\"';
298 298
        for (std::string::const_iterator it = str.begin();
299 299
             it != str.end(); ++it) {
300 300
          writeEscape(os, *it);
301 301
        }
302 302
        os << '\"';
303 303
      } else {
304 304
        os << str;
305 305
      }
306 306
      return os;
307 307
    }
308 308

	
309 309
    class Section {
310 310
    public:
311 311
      virtual ~Section() {}
312 312
      virtual void process(std::ostream& os) = 0;
313 313
    };
314 314

	
315 315
    template <typename Functor>
316 316
    class LineSection : public Section {
317 317
    private:
318 318

	
319 319
      Functor _functor;
320 320

	
321 321
    public:
322 322

	
323 323
      LineSection(const Functor& functor) : _functor(functor) {}
324 324
      virtual ~LineSection() {}
325 325

	
326 326
      virtual void process(std::ostream& os) {
327 327
        std::string line;
328 328
        while (!(line = _functor()).empty()) os << line << std::endl;
329 329
      }
330 330
    };
331 331

	
332 332
    template <typename Functor>
333 333
    class StreamSection : public Section {
334 334
    private:
335 335

	
336 336
      Functor _functor;
337 337

	
338 338
    public:
339 339

	
340 340
      StreamSection(const Functor& functor) : _functor(functor) {}
341 341
      virtual ~StreamSection() {}
342 342

	
343 343
      virtual void process(std::ostream& os) {
344 344
        _functor(os);
345 345
      }
346 346
    };
347 347

	
348 348
  }
349 349

	
350
  template <typename Digraph>
350
  template <typename DGR>
351 351
  class DigraphWriter;
352 352

	
353
  template <typename Digraph>
354
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
355
                                       std::ostream& os = std::cout);
356
  template <typename Digraph>
357
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
358
                                       const std::string& fn);
353
  template <typename TDGR>
354
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, 
355
                                   std::ostream& os = std::cout);
356
  template <typename TDGR>
357
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const std::string& fn);
359 358

	
360
  template <typename Digraph>
361
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
362
                                       const char* fn);
359
  template <typename TDGR>
360
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn);
363 361

	
364 362

	
365 363
  /// \ingroup lemon_io
366 364
  ///
367 365
  /// \brief \ref lgf-format "LGF" writer for directed graphs
368 366
  ///
369 367
  /// This utility writes an \ref lgf-format "LGF" file.
370 368
  ///
371 369
  /// The writing method does a batch processing. The user creates a
372 370
  /// writer object, then various writing rules can be added to the
373 371
  /// writer, and eventually the writing is executed with the \c run()
374 372
  /// member function. A map writing rule can be added to the writer
375 373
  /// with the \c nodeMap() or \c arcMap() members. An optional
376 374
  /// converter parameter can also be added as a standard functor
377 375
  /// converting from the value type of the map to \c std::string. If it
378 376
  /// is set, it will determine how the value type of the map is written to
379 377
  /// the output stream. If the functor is not set, then a default
380 378
  /// conversion will be used. The \c attribute(), \c node() and \c
381 379
  /// arc() functions are used to add attribute writing rules.
382 380
  ///
383 381
  ///\code
384
  /// DigraphWriter<Digraph>(digraph, std::cout).
382
  /// DigraphWriter<DGR>(digraph, std::cout).
385 383
  ///   nodeMap("coordinates", coord_map).
386 384
  ///   nodeMap("size", size).
387 385
  ///   nodeMap("title", title).
388 386
  ///   arcMap("capacity", cap_map).
389 387
  ///   node("source", src).
390 388
  ///   node("target", trg).
391 389
  ///   attribute("caption", caption).
392 390
  ///   run();
393 391
  ///\endcode
394 392
  ///
395 393
  ///
396 394
  /// By default, the writer does not write additional captions to the
397 395
  /// sections, but they can be give as an optional parameter of
398 396
  /// the \c nodes(), \c arcs() or \c
399 397
  /// attributes() functions.
400 398
  ///
401 399
  /// The \c skipNodes() and \c skipArcs() functions forbid the
402 400
  /// writing of the sections. If two arc sections should be written
403 401
  /// to the output, it can be done in two passes, the first pass
404 402
  /// writes the node section and the first arc section, then the
405 403
  /// second pass skips the node section and writes just the arc
406 404
  /// section to the stream. The output stream can be retrieved with
407 405
  /// the \c ostream() function, hence the second pass can append its
408 406
  /// output to the output of the first pass.
409
  template <typename GR>
407
  template <typename DGR>
410 408
  class DigraphWriter {
411 409
  public:
412 410

	
413
    typedef GR Digraph;
414
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
411
    typedef DGR Digraph;
412
    TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
415 413

	
416 414
  private:
417 415

	
418 416

	
419 417
    std::ostream* _os;
420 418
    bool local_os;
421 419

	
422
    const Digraph& _digraph;
420
    const DGR& _digraph;
423 421

	
424 422
    std::string _nodes_caption;
425 423
    std::string _arcs_caption;
426 424
    std::string _attributes_caption;
427 425

	
428 426
    typedef std::map<Node, std::string> NodeIndex;
429 427
    NodeIndex _node_index;
430 428
    typedef std::map<Arc, std::string> ArcIndex;
431 429
    ArcIndex _arc_index;
432 430

	
433 431
    typedef std::vector<std::pair<std::string,
434 432
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
435 433
    NodeMaps _node_maps;
436 434

	
437 435
    typedef std::vector<std::pair<std::string,
438 436
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
439 437
    ArcMaps _arc_maps;
440 438

	
441 439
    typedef std::vector<std::pair<std::string,
442 440
      _writer_bits::ValueStorageBase*> > Attributes;
443 441
    Attributes _attributes;
444 442

	
445 443
    bool _skip_nodes;
446 444
    bool _skip_arcs;
447 445

	
448 446
  public:
449 447

	
450 448
    /// \brief Constructor
451 449
    ///
452 450
    /// Construct a directed graph writer, which writes to the given
453 451
    /// output stream.
454
    DigraphWriter(const Digraph& digraph, std::ostream& os = std::cout)
452
    DigraphWriter(const DGR& digraph, std::ostream& os = std::cout)
455 453
      : _os(&os), local_os(false), _digraph(digraph),
456 454
        _skip_nodes(false), _skip_arcs(false) {}
457 455

	
458 456
    /// \brief Constructor
459 457
    ///
460 458
    /// Construct a directed graph writer, which writes to the given
461 459
    /// output file.
462
    DigraphWriter(const Digraph& digraph, const std::string& fn)
460
    DigraphWriter(const DGR& digraph, const std::string& fn)
463 461
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
464 462
        _skip_nodes(false), _skip_arcs(false) {
465 463
      if (!(*_os)) {
466 464
        delete _os;
467 465
        throw IoError("Cannot write file", fn);
468 466
      }
469 467
    }
470 468

	
471 469
    /// \brief Constructor
472 470
    ///
473 471
    /// Construct a directed graph writer, which writes to the given
474 472
    /// output file.
475
    DigraphWriter(const Digraph& digraph, const char* fn)
473
    DigraphWriter(const DGR& digraph, const char* fn)
476 474
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
477 475
        _skip_nodes(false), _skip_arcs(false) {
478 476
      if (!(*_os)) {
479 477
        delete _os;
480 478
        throw IoError("Cannot write file", fn);
481 479
      }
482 480
    }
483 481

	
484 482
    /// \brief Destructor
485 483
    ~DigraphWriter() {
486 484
      for (typename NodeMaps::iterator it = _node_maps.begin();
487 485
           it != _node_maps.end(); ++it) {
488 486
        delete it->second;
489 487
      }
490 488

	
491 489
      for (typename ArcMaps::iterator it = _arc_maps.begin();
492 490
           it != _arc_maps.end(); ++it) {
493 491
        delete it->second;
494 492
      }
495 493

	
496 494
      for (typename Attributes::iterator it = _attributes.begin();
497 495
           it != _attributes.end(); ++it) {
498 496
        delete it->second;
499 497
      }
500 498

	
501 499
      if (local_os) {
502 500
        delete _os;
503 501
      }
504 502
    }
505 503

	
506 504
  private:
507 505

	
508
    template <typename DGR>
509
    friend DigraphWriter<DGR> digraphWriter(const DGR& digraph, 
510
                                            std::ostream& os);
511
    template <typename DGR>
512
    friend DigraphWriter<DGR> digraphWriter(const DGR& digraph,
513
                                            const std::string& fn);
514
    template <typename DGR>
515
    friend DigraphWriter<DGR> digraphWriter(const DGR& digraph,
516
                                            const char *fn);
506
    template <typename TDGR>
507
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, 
508
                                             std::ostream& os);
509
    template <typename TDGR>
510
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
511
                                             const std::string& fn);
512
    template <typename TDGR>
513
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
514
                                             const char *fn);
517 515

	
518 516
    DigraphWriter(DigraphWriter& other)
519 517
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
520 518
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
521 519

	
522 520
      other._os = 0;
523 521
      other.local_os = false;
524 522

	
525 523
      _node_index.swap(other._node_index);
526 524
      _arc_index.swap(other._arc_index);
527 525

	
528 526
      _node_maps.swap(other._node_maps);
529 527
      _arc_maps.swap(other._arc_maps);
530 528
      _attributes.swap(other._attributes);
531 529

	
532 530
      _nodes_caption = other._nodes_caption;
533 531
      _arcs_caption = other._arcs_caption;
534 532
      _attributes_caption = other._attributes_caption;
535 533
    }
536 534

	
537 535
    DigraphWriter& operator=(const DigraphWriter&);
538 536

	
539 537
  public:
540 538

	
541 539
    /// \name Writing rules
542 540
    /// @{
543 541

	
544 542
    /// \brief Node map writing rule
545 543
    ///
546 544
    /// Add a node map writing rule to the writer.
547 545
    template <typename Map>
548 546
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
549 547
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
550 548
      _writer_bits::MapStorageBase<Node>* storage =
551 549
        new _writer_bits::MapStorage<Node, Map>(map);
552 550
      _node_maps.push_back(std::make_pair(caption, storage));
553 551
      return *this;
554 552
    }
555 553

	
556 554
    /// \brief Node map writing rule
557 555
    ///
558 556
    /// Add a node map writing rule with specialized converter to the
559 557
    /// writer.
560 558
    template <typename Map, typename Converter>
561 559
    DigraphWriter& nodeMap(const std::string& caption, const Map& map,
562 560
                           const Converter& converter = Converter()) {
563 561
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
564 562
      _writer_bits::MapStorageBase<Node>* storage =
565 563
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
566 564
      _node_maps.push_back(std::make_pair(caption, storage));
567 565
      return *this;
568 566
    }
569 567

	
570 568
    /// \brief Arc map writing rule
571 569
    ///
572 570
    /// Add an arc map writing rule to the writer.
573 571
    template <typename Map>
574 572
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
575 573
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
576 574
      _writer_bits::MapStorageBase<Arc>* storage =
577 575
        new _writer_bits::MapStorage<Arc, Map>(map);
578 576
      _arc_maps.push_back(std::make_pair(caption, storage));
579 577
      return *this;
580 578
    }
581 579

	
582 580
    /// \brief Arc map writing rule
583 581
    ///
584 582
    /// Add an arc map writing rule with specialized converter to the
585 583
    /// writer.
586 584
    template <typename Map, typename Converter>
587 585
    DigraphWriter& arcMap(const std::string& caption, const Map& map,
588 586
                          const Converter& converter = Converter()) {
589 587
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
590 588
      _writer_bits::MapStorageBase<Arc>* storage =
591 589
        new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
592 590
      _arc_maps.push_back(std::make_pair(caption, storage));
593 591
      return *this;
594 592
    }
595 593

	
596 594
    /// \brief Attribute writing rule
597 595
    ///
598 596
    /// Add an attribute writing rule to the writer.
599 597
    template <typename Value>
600 598
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
601 599
      _writer_bits::ValueStorageBase* storage =
602 600
        new _writer_bits::ValueStorage<Value>(value);
603 601
      _attributes.push_back(std::make_pair(caption, storage));
604 602
      return *this;
605 603
    }
606 604

	
607 605
    /// \brief Attribute writing rule
608 606
    ///
609 607
    /// Add an attribute writing rule with specialized converter to the
610 608
    /// writer.
611 609
    template <typename Value, typename Converter>
612 610
    DigraphWriter& attribute(const std::string& caption, const Value& value,
... ...
@@ -631,1147 +629,1207 @@
631 629

	
632 630
    /// \brief Arc writing rule
633 631
    ///
634 632
    /// Add an arc writing rule to writer.
635 633
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
636 634
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
637 635
      Converter converter(_arc_index);
638 636
      _writer_bits::ValueStorageBase* storage =
639 637
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
640 638
      _attributes.push_back(std::make_pair(caption, storage));
641 639
      return *this;
642 640
    }
643 641

	
644 642
    /// \name Section captions
645 643
    /// @{
646 644

	
647 645
    /// \brief Add an additional caption to the \c \@nodes section
648 646
    ///
649 647
    /// Add an additional caption to the \c \@nodes section.
650 648
    DigraphWriter& nodes(const std::string& caption) {
651 649
      _nodes_caption = caption;
652 650
      return *this;
653 651
    }
654 652

	
655 653
    /// \brief Add an additional caption to the \c \@arcs section
656 654
    ///
657 655
    /// Add an additional caption to the \c \@arcs section.
658 656
    DigraphWriter& arcs(const std::string& caption) {
659 657
      _arcs_caption = caption;
660 658
      return *this;
661 659
    }
662 660

	
663 661
    /// \brief Add an additional caption to the \c \@attributes section
664 662
    ///
665 663
    /// Add an additional caption to the \c \@attributes section.
666 664
    DigraphWriter& attributes(const std::string& caption) {
667 665
      _attributes_caption = caption;
668 666
      return *this;
669 667
    }
670 668

	
671 669
    /// \name Skipping section
672 670
    /// @{
673 671

	
674 672
    /// \brief Skip writing the node set
675 673
    ///
676 674
    /// The \c \@nodes section will not be written to the stream.
677 675
    DigraphWriter& skipNodes() {
678 676
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
679 677
      _skip_nodes = true;
680 678
      return *this;
681 679
    }
682 680

	
683 681
    /// \brief Skip writing arc set
684 682
    ///
685 683
    /// The \c \@arcs section will not be written to the stream.
686 684
    DigraphWriter& skipArcs() {
687 685
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
688 686
      _skip_arcs = true;
689 687
      return *this;
690 688
    }
691 689

	
692 690
    /// @}
693 691

	
694 692
  private:
695 693

	
696 694
    void writeNodes() {
697 695
      _writer_bits::MapStorageBase<Node>* label = 0;
698 696
      for (typename NodeMaps::iterator it = _node_maps.begin();
699 697
           it != _node_maps.end(); ++it) {
700 698
        if (it->first == "label") {
701 699
          label = it->second;
702 700
          break;
703 701
        }
704 702
      }
705 703

	
706 704
      *_os << "@nodes";
707 705
      if (!_nodes_caption.empty()) {
708 706
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
709 707
      }
710 708
      *_os << std::endl;
711 709

	
712 710
      if (label == 0) {
713 711
        *_os << "label" << '\t';
714 712
      }
715 713
      for (typename NodeMaps::iterator it = _node_maps.begin();
716 714
           it != _node_maps.end(); ++it) {
717 715
        _writer_bits::writeToken(*_os, it->first) << '\t';
718 716
      }
719 717
      *_os << std::endl;
720 718

	
721 719
      std::vector<Node> nodes;
722 720
      for (NodeIt n(_digraph); n != INVALID; ++n) {
723 721
        nodes.push_back(n);
724 722
      }
725 723

	
726 724
      if (label == 0) {
727
        IdMap<Digraph, Node> id_map(_digraph);
728
        _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
725
        IdMap<DGR, Node> id_map(_digraph);
726
        _writer_bits::MapLess<IdMap<DGR, Node> > id_less(id_map);
729 727
        std::sort(nodes.begin(), nodes.end(), id_less);
730 728
      } else {
731 729
        label->sort(nodes);
732 730
      }
733 731

	
734 732
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
735 733
        Node n = nodes[i];
736 734
        if (label == 0) {
737 735
          std::ostringstream os;
738 736
          os << _digraph.id(n);
739 737
          _writer_bits::writeToken(*_os, os.str());
740 738
          *_os << '\t';
741 739
          _node_index.insert(std::make_pair(n, os.str()));
742 740
        }
743 741
        for (typename NodeMaps::iterator it = _node_maps.begin();
744 742
             it != _node_maps.end(); ++it) {
745 743
          std::string value = it->second->get(n);
746 744
          _writer_bits::writeToken(*_os, value);
747 745
          if (it->first == "label") {
748 746
            _node_index.insert(std::make_pair(n, value));
749 747
          }
750 748
          *_os << '\t';
751 749
        }
752 750
        *_os << std::endl;
753 751
      }
754 752
    }
755 753

	
756 754
    void createNodeIndex() {
757 755
      _writer_bits::MapStorageBase<Node>* label = 0;
758 756
      for (typename NodeMaps::iterator it = _node_maps.begin();
759 757
           it != _node_maps.end(); ++it) {
760 758
        if (it->first == "label") {
761 759
          label = it->second;
762 760
          break;
763 761
        }
764 762
      }
765 763

	
766 764
      if (label == 0) {
767 765
        for (NodeIt n(_digraph); n != INVALID; ++n) {
768 766
          std::ostringstream os;
769 767
          os << _digraph.id(n);
770 768
          _node_index.insert(std::make_pair(n, os.str()));
771 769
        }
772 770
      } else {
773 771
        for (NodeIt n(_digraph); n != INVALID; ++n) {
774 772
          std::string value = label->get(n);
775 773
          _node_index.insert(std::make_pair(n, value));
776 774
        }
777 775
      }
778 776
    }
779 777

	
780 778
    void writeArcs() {
781 779
      _writer_bits::MapStorageBase<Arc>* label = 0;
782 780
      for (typename ArcMaps::iterator it = _arc_maps.begin();
783 781
           it != _arc_maps.end(); ++it) {
784 782
        if (it->first == "label") {
785 783
          label = it->second;
786 784
          break;
787 785
        }
788 786
      }
789 787

	
790 788
      *_os << "@arcs";
791 789
      if (!_arcs_caption.empty()) {
792 790
        _writer_bits::writeToken(*_os << ' ', _arcs_caption);
793 791
      }
794 792
      *_os << std::endl;
795 793

	
796 794
      *_os << '\t' << '\t';
797 795
      if (label == 0) {
798 796
        *_os << "label" << '\t';
799 797
      }
800 798
      for (typename ArcMaps::iterator it = _arc_maps.begin();
801 799
           it != _arc_maps.end(); ++it) {
802 800
        _writer_bits::writeToken(*_os, it->first) << '\t';
803 801
      }
804 802
      *_os << std::endl;
805 803

	
806 804
      std::vector<Arc> arcs;
807 805
      for (ArcIt n(_digraph); n != INVALID; ++n) {
808 806
        arcs.push_back(n);
809 807
      }
810 808

	
811 809
      if (label == 0) {
812
        IdMap<Digraph, Arc> id_map(_digraph);
813
        _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
810
        IdMap<DGR, Arc> id_map(_digraph);
811
        _writer_bits::MapLess<IdMap<DGR, Arc> > id_less(id_map);
814 812
        std::sort(arcs.begin(), arcs.end(), id_less);
815 813
      } else {
816 814
        label->sort(arcs);
817 815
      }
818 816

	
819 817
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
820 818
        Arc a = arcs[i];
821 819
        _writer_bits::writeToken(*_os, _node_index.
822 820
                                 find(_digraph.source(a))->second);
823 821
        *_os << '\t';
824 822
        _writer_bits::writeToken(*_os, _node_index.
825 823
                                 find(_digraph.target(a))->second);
826 824
        *_os << '\t';
827 825
        if (label == 0) {
828 826
          std::ostringstream os;
829 827
          os << _digraph.id(a);
830 828
          _writer_bits::writeToken(*_os, os.str());
831 829
          *_os << '\t';
832 830
          _arc_index.insert(std::make_pair(a, os.str()));
833 831
        }
834 832
        for (typename ArcMaps::iterator it = _arc_maps.begin();
835 833
             it != _arc_maps.end(); ++it) {
836 834
          std::string value = it->second->get(a);
837 835
          _writer_bits::writeToken(*_os, value);
838 836
          if (it->first == "label") {
839 837
            _arc_index.insert(std::make_pair(a, value));
840 838
          }
841 839
          *_os << '\t';
842 840
        }
843 841
        *_os << std::endl;
844 842
      }
845 843
    }
846 844

	
847 845
    void createArcIndex() {
848 846
      _writer_bits::MapStorageBase<Arc>* label = 0;
849 847
      for (typename ArcMaps::iterator it = _arc_maps.begin();
850 848
           it != _arc_maps.end(); ++it) {
851 849
        if (it->first == "label") {
852 850
          label = it->second;
853 851
          break;
854 852
        }
855 853
      }
856 854

	
857 855
      if (label == 0) {
858 856
        for (ArcIt a(_digraph); a != INVALID; ++a) {
859 857
          std::ostringstream os;
860 858
          os << _digraph.id(a);
861 859
          _arc_index.insert(std::make_pair(a, os.str()));
862 860
        }
863 861
      } else {
864 862
        for (ArcIt a(_digraph); a != INVALID; ++a) {
865 863
          std::string value = label->get(a);
866 864
          _arc_index.insert(std::make_pair(a, value));
867 865
        }
868 866
      }
869 867
    }
870 868

	
871 869
    void writeAttributes() {
872 870
      if (_attributes.empty()) return;
873 871
      *_os << "@attributes";
874 872
      if (!_attributes_caption.empty()) {
875 873
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
876 874
      }
877 875
      *_os << std::endl;
878 876
      for (typename Attributes::iterator it = _attributes.begin();
879 877
           it != _attributes.end(); ++it) {
880 878
        _writer_bits::writeToken(*_os, it->first) << ' ';
881 879
        _writer_bits::writeToken(*_os, it->second->get());
882 880
        *_os << std::endl;
883 881
      }
884 882
    }
885 883

	
886 884
  public:
887 885

	
888 886
    /// \name Execution of the writer
889 887
    /// @{
890 888

	
891 889
    /// \brief Start the batch processing
892 890
    ///
893 891
    /// This function starts the batch processing.
894 892
    void run() {
895 893
      if (!_skip_nodes) {
896 894
        writeNodes();
897 895
      } else {
898 896
        createNodeIndex();
899 897
      }
900 898
      if (!_skip_arcs) {
901 899
        writeArcs();
902 900
      } else {
903 901
        createArcIndex();
904 902
      }
905 903
      writeAttributes();
906 904
    }
907 905

	
908 906
    /// \brief Give back the stream of the writer
909 907
    ///
910 908
    /// Give back the stream of the writer.
911 909
    std::ostream& ostream() {
912 910
      return *_os;
913 911
    }
914 912

	
915 913
    /// @}
916 914
  };
917 915

	
916
  /// \ingroup lemon_io
917
  ///
918 918
  /// \brief Return a \ref DigraphWriter class
919 919
  ///
920
  /// This function just returns a \ref DigraphWriter class.
920
  /// This function just returns a \ref DigraphWriter class. 
921
  ///
922
  /// With this function a digraph can be write to a file or output
923
  /// stream in \ref lgf-format "LGF" format with several maps and
924
  /// attributes. For example, with the following code a network flow
925
  /// problem can be written to the standard output, i.e. a digraph
926
  /// with a \e capacity map on the arcs and \e source and \e target
927
  /// nodes:
928
  ///
929
  ///\code
930
  ///ListDigraph digraph;
931
  ///ListDigraph::ArcMap<int> cap(digraph);
932
  ///ListDigraph::Node src, trg;
933
  ///  // Setting the capacity map and source and target nodes
934
  ///digraphWriter(digraph, std::cout).
935
  ///  arcMap("capacity", cap).
936
  ///  node("source", src).
937
  ///  node("target", trg).
938
  ///  run();
939
  ///\endcode
940
  ///
941
  /// For a complete documentation, please see the \ref DigraphWriter
942
  /// class documentation.
943
  /// \warning Don't forget to put the \ref DigraphWriter::run() "run()"
944
  /// to the end of the parameter list.
921 945
  /// \relates DigraphWriter
922
  template <typename Digraph>
923
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
924
                                       std::ostream& os) {
925
    DigraphWriter<Digraph> tmp(digraph, os);
946
  /// \sa digraphWriter(const TDGR& digraph, const std::string& fn)
947
  /// \sa digraphWriter(const TDGR& digraph, const char* fn)
948
  template <typename TDGR>
949
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, std::ostream& os) {
950
    DigraphWriter<TDGR> tmp(digraph, os);
926 951
    return tmp;
927 952
  }
928 953

	
929 954
  /// \brief Return a \ref DigraphWriter class
930 955
  ///
931 956
  /// This function just returns a \ref DigraphWriter class.
932 957
  /// \relates DigraphWriter
933
  template <typename Digraph>
934
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
935
                                       const std::string& fn) {
936
    DigraphWriter<Digraph> tmp(digraph, fn);
958
  /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
959
  template <typename TDGR>
960
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, 
961
                                    const std::string& fn) {
962
    DigraphWriter<TDGR> tmp(digraph, fn);
937 963
    return tmp;
938 964
  }
939 965

	
940 966
  /// \brief Return a \ref DigraphWriter class
941 967
  ///
942 968
  /// This function just returns a \ref DigraphWriter class.
943 969
  /// \relates DigraphWriter
944
  template <typename Digraph>
945
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
946
                                       const char* fn) {
947
    DigraphWriter<Digraph> tmp(digraph, fn);
970
  /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
971
  template <typename TDGR>
972
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn) {
973
    DigraphWriter<TDGR> tmp(digraph, fn);
948 974
    return tmp;
949 975
  }
950 976

	
951
  template <typename Graph>
977
  template <typename GR>
952 978
  class GraphWriter;
953 979

	
954
  template <typename Graph>
955
  GraphWriter<Graph> graphWriter(const Graph& graph,
956
                                 std::ostream& os = std::cout);
957
  template <typename Graph>
958
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn);
959
  template <typename Graph>
960
  GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn);
980
  template <typename TGR>
981
  GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os = std::cout);
982
  template <typename TGR>
983
  GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn);
984
  template <typename TGR>
985
  GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn);
961 986

	
962 987
  /// \ingroup lemon_io
963 988
  ///
964 989
  /// \brief \ref lgf-format "LGF" writer for directed graphs
965 990
  ///
966 991
  /// This utility writes an \ref lgf-format "LGF" file.
967 992
  ///
968 993
  /// It can be used almost the same way as \c DigraphWriter.
969 994
  /// The only difference is that this class can handle edges and
970 995
  /// edge maps as well as arcs and arc maps.
971 996
  ///
972 997
  /// The arc maps are written into the file as two columns, the
973 998
  /// caption of the columns are the name of the map prefixed with \c
974 999
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
975 1000
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
976 1001
  /// of the arc) and the label of corresponding edge.
977 1002
  template <typename GR>
978 1003
  class GraphWriter {
979 1004
  public:
980 1005

	
981 1006
    typedef GR Graph;
982
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1007
    TEMPLATE_GRAPH_TYPEDEFS(GR);
983 1008

	
984 1009
  private:
985 1010

	
986 1011

	
987 1012
    std::ostream* _os;
988 1013
    bool local_os;
989 1014

	
990
    const Graph& _graph;
1015
    const GR& _graph;
991 1016

	
992 1017
    std::string _nodes_caption;
993 1018
    std::string _edges_caption;
994 1019
    std::string _attributes_caption;
995 1020

	
996 1021
    typedef std::map<Node, std::string> NodeIndex;
997 1022
    NodeIndex _node_index;
998 1023
    typedef std::map<Edge, std::string> EdgeIndex;
999 1024
    EdgeIndex _edge_index;
1000 1025

	
1001 1026
    typedef std::vector<std::pair<std::string,
1002 1027
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
1003 1028
    NodeMaps _node_maps;
1004 1029

	
1005 1030
    typedef std::vector<std::pair<std::string,
1006 1031
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1007 1032
    EdgeMaps _edge_maps;
1008 1033

	
1009 1034
    typedef std::vector<std::pair<std::string,
1010 1035
      _writer_bits::ValueStorageBase*> > Attributes;
1011 1036
    Attributes _attributes;
1012 1037

	
1013 1038
    bool _skip_nodes;
1014 1039
    bool _skip_edges;
1015 1040

	
1016 1041
  public:
1017 1042

	
1018 1043
    /// \brief Constructor
1019 1044
    ///
1020 1045
    /// Construct a directed graph writer, which writes to the given
1021 1046
    /// output stream.
1022
    GraphWriter(const Graph& graph, std::ostream& os = std::cout)
1047
    GraphWriter(const GR& graph, std::ostream& os = std::cout)
1023 1048
      : _os(&os), local_os(false), _graph(graph),
1024 1049
        _skip_nodes(false), _skip_edges(false) {}
1025 1050

	
1026 1051
    /// \brief Constructor
1027 1052
    ///
1028 1053
    /// Construct a directed graph writer, which writes to the given
1029 1054
    /// output file.
1030
    GraphWriter(const Graph& graph, const std::string& fn)
1055
    GraphWriter(const GR& graph, const std::string& fn)
1031 1056
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1032 1057
        _skip_nodes(false), _skip_edges(false) {
1033 1058
      if (!(*_os)) {
1034 1059
        delete _os;
1035 1060
        throw IoError("Cannot write file", fn);
1036 1061
      }
1037 1062
    }
1038 1063

	
1039 1064
    /// \brief Constructor
1040 1065
    ///
1041 1066
    /// Construct a directed graph writer, which writes to the given
1042 1067
    /// output file.
1043
    GraphWriter(const Graph& graph, const char* fn)
1068
    GraphWriter(const GR& graph, const char* fn)
1044 1069
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1045 1070
        _skip_nodes(false), _skip_edges(false) {
1046 1071
      if (!(*_os)) {
1047 1072
        delete _os;
1048 1073
        throw IoError("Cannot write file", fn);
1049 1074
      }
1050 1075
    }
1051 1076

	
1052 1077
    /// \brief Destructor
1053 1078
    ~GraphWriter() {
1054 1079
      for (typename NodeMaps::iterator it = _node_maps.begin();
1055 1080
           it != _node_maps.end(); ++it) {
1056 1081
        delete it->second;
1057 1082
      }
1058 1083

	
1059 1084
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1060 1085
           it != _edge_maps.end(); ++it) {
1061 1086
        delete it->second;
1062 1087
      }
1063 1088

	
1064 1089
      for (typename Attributes::iterator it = _attributes.begin();
1065 1090
           it != _attributes.end(); ++it) {
1066 1091
        delete it->second;
1067 1092
      }
1068 1093

	
1069 1094
      if (local_os) {
1070 1095
        delete _os;
1071 1096
      }
1072 1097
    }
1073 1098

	
1074 1099
  private:
1075 1100

	
1076
    template <typename Graph>
1077
    friend GraphWriter<Graph> graphWriter(const Graph& graph,
1078
                                          std::ostream& os);
1079
    template <typename Graph>
1080
    friend GraphWriter<Graph> graphWriter(const Graph& graph,
1081
                                          const std::string& fn);
1082
    template <typename Graph>
1083
    friend GraphWriter<Graph> graphWriter(const Graph& graph,
1084
                                          const char *fn);
1101
    template <typename TGR>
1102
    friend GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os);
1103
    template <typename TGR>
1104
    friend GraphWriter<TGR> graphWriter(const TGR& graph, 
1105
                                        const std::string& fn);
1106
    template <typename TGR>
1107
    friend GraphWriter<TGR> graphWriter(const TGR& graph, const char *fn);
1085 1108
    
1086 1109
    GraphWriter(GraphWriter& other)
1087 1110
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
1088 1111
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1089 1112

	
1090 1113
      other._os = 0;
1091 1114
      other.local_os = false;
1092 1115

	
1093 1116
      _node_index.swap(other._node_index);
1094 1117
      _edge_index.swap(other._edge_index);
1095 1118

	
1096 1119
      _node_maps.swap(other._node_maps);
1097 1120
      _edge_maps.swap(other._edge_maps);
1098 1121
      _attributes.swap(other._attributes);
1099 1122

	
1100 1123
      _nodes_caption = other._nodes_caption;
1101 1124
      _edges_caption = other._edges_caption;
1102 1125
      _attributes_caption = other._attributes_caption;
1103 1126
    }
1104 1127

	
1105 1128
    GraphWriter& operator=(const GraphWriter&);
1106 1129

	
1107 1130
  public:
1108 1131

	
1109 1132
    /// \name Writing rules
1110 1133
    /// @{
1111 1134

	
1112 1135
    /// \brief Node map writing rule
1113 1136
    ///
1114 1137
    /// Add a node map writing rule to the writer.
1115 1138
    template <typename Map>
1116 1139
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1117 1140
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1118 1141
      _writer_bits::MapStorageBase<Node>* storage =
1119 1142
        new _writer_bits::MapStorage<Node, Map>(map);
1120 1143
      _node_maps.push_back(std::make_pair(caption, storage));
1121 1144
      return *this;
1122 1145
    }
1123 1146

	
1124 1147
    /// \brief Node map writing rule
1125 1148
    ///
1126 1149
    /// Add a node map writing rule with specialized converter to the
1127 1150
    /// writer.
1128 1151
    template <typename Map, typename Converter>
1129 1152
    GraphWriter& nodeMap(const std::string& caption, const Map& map,
1130 1153
                           const Converter& converter = Converter()) {
1131 1154
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1132 1155
      _writer_bits::MapStorageBase<Node>* storage =
1133 1156
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1134 1157
      _node_maps.push_back(std::make_pair(caption, storage));
1135 1158
      return *this;
1136 1159
    }
1137 1160

	
1138 1161
    /// \brief Edge map writing rule
1139 1162
    ///
1140 1163
    /// Add an edge map writing rule to the writer.
1141 1164
    template <typename Map>
1142 1165
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1143 1166
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1144 1167
      _writer_bits::MapStorageBase<Edge>* storage =
1145 1168
        new _writer_bits::MapStorage<Edge, Map>(map);
1146 1169
      _edge_maps.push_back(std::make_pair(caption, storage));
1147 1170
      return *this;
1148 1171
    }
1149 1172

	
1150 1173
    /// \brief Edge map writing rule
1151 1174
    ///
1152 1175
    /// Add an edge map writing rule with specialized converter to the
1153 1176
    /// writer.
1154 1177
    template <typename Map, typename Converter>
1155 1178
    GraphWriter& edgeMap(const std::string& caption, const Map& map,
1156 1179
                          const Converter& converter = Converter()) {
1157 1180
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1158 1181
      _writer_bits::MapStorageBase<Edge>* storage =
1159 1182
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1160 1183
      _edge_maps.push_back(std::make_pair(caption, storage));
1161 1184
      return *this;
1162 1185
    }
1163 1186

	
1164 1187
    /// \brief Arc map writing rule
1165 1188
    ///
1166 1189
    /// Add an arc map writing rule to the writer.
1167 1190
    template <typename Map>
1168 1191
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
1169 1192
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1170 1193
      _writer_bits::MapStorageBase<Edge>* forward_storage =
1171
        new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1194
        new _writer_bits::GraphArcMapStorage<GR, true, Map>(_graph, map);
1172 1195
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1173 1196
      _writer_bits::MapStorageBase<Edge>* backward_storage =
1174
        new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1197
        new _writer_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
1175 1198
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1176 1199
      return *this;
1177 1200
    }
1178 1201

	
1179 1202
    /// \brief Arc map writing rule
1180 1203
    ///
1181 1204
    /// Add an arc map writing rule with specialized converter to the
1182 1205
    /// writer.
1183 1206
    template <typename Map, typename Converter>
1184 1207
    GraphWriter& arcMap(const std::string& caption, const Map& map,
1185 1208
                          const Converter& converter = Converter()) {
1186 1209
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1187 1210
      _writer_bits::MapStorageBase<Edge>* forward_storage =
1188
        new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1211
        new _writer_bits::GraphArcMapStorage<GR, true, Map, Converter>
1189 1212
        (_graph, map, converter);
1190 1213
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1191 1214
      _writer_bits::MapStorageBase<Edge>* backward_storage =
1192
        new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1215
        new _writer_bits::GraphArcMapStorage<GR, false, Map, Converter>
1193 1216
        (_graph, map, converter);
1194 1217
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1195 1218
      return *this;
1196 1219
    }
1197 1220

	
1198 1221
    /// \brief Attribute writing rule
1199 1222
    ///
1200 1223
    /// Add an attribute writing rule to the writer.
1201 1224
    template <typename Value>
1202 1225
    GraphWriter& attribute(const std::string& caption, const Value& value) {
1203 1226
      _writer_bits::ValueStorageBase* storage =
1204 1227
        new _writer_bits::ValueStorage<Value>(value);
1205 1228
      _attributes.push_back(std::make_pair(caption, storage));
1206 1229
      return *this;
1207 1230
    }
1208 1231

	
1209 1232
    /// \brief Attribute writing rule
1210 1233
    ///
1211 1234
    /// Add an attribute writing rule with specialized converter to the
1212 1235
    /// writer.
1213 1236
    template <typename Value, typename Converter>
1214 1237
    GraphWriter& attribute(const std::string& caption, const Value& value,
1215 1238
                             const Converter& converter = Converter()) {
1216 1239
      _writer_bits::ValueStorageBase* storage =
1217 1240
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1218 1241
      _attributes.push_back(std::make_pair(caption, storage));
1219 1242
      return *this;
1220 1243
    }
1221 1244

	
1222 1245
    /// \brief Node writing rule
1223 1246
    ///
1224 1247
    /// Add a node writing rule to the writer.
1225 1248
    GraphWriter& node(const std::string& caption, const Node& node) {
1226 1249
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
1227 1250
      Converter converter(_node_index);
1228 1251
      _writer_bits::ValueStorageBase* storage =
1229 1252
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1230 1253
      _attributes.push_back(std::make_pair(caption, storage));
1231 1254
      return *this;
1232 1255
    }
1233 1256

	
1234 1257
    /// \brief Edge writing rule
1235 1258
    ///
1236 1259
    /// Add an edge writing rule to writer.
1237 1260
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
1238 1261
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1239 1262
      Converter converter(_edge_index);
1240 1263
      _writer_bits::ValueStorageBase* storage =
1241 1264
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1242 1265
      _attributes.push_back(std::make_pair(caption, storage));
1243 1266
      return *this;
1244 1267
    }
1245 1268

	
1246 1269
    /// \brief Arc writing rule
1247 1270
    ///
1248 1271
    /// Add an arc writing rule to writer.
1249 1272
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
1250
      typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1273
      typedef _writer_bits::GraphArcLookUpConverter<GR> Converter;
1251 1274
      Converter converter(_graph, _edge_index);
1252 1275
      _writer_bits::ValueStorageBase* storage =
1253 1276
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1254 1277
      _attributes.push_back(std::make_pair(caption, storage));
1255 1278
      return *this;
1256 1279
    }
1257 1280

	
1258 1281
    /// \name Section captions
1259 1282
    /// @{
1260 1283

	
1261 1284
    /// \brief Add an additional caption to the \c \@nodes section
1262 1285
    ///
1263 1286
    /// Add an additional caption to the \c \@nodes section.
1264 1287
    GraphWriter& nodes(const std::string& caption) {
1265 1288
      _nodes_caption = caption;
1266 1289
      return *this;
1267 1290
    }
1268 1291

	
1269 1292
    /// \brief Add an additional caption to the \c \@arcs section
1270 1293
    ///
1271 1294
    /// Add an additional caption to the \c \@arcs section.
1272 1295
    GraphWriter& edges(const std::string& caption) {
1273 1296
      _edges_caption = caption;
1274 1297
      return *this;
1275 1298
    }
1276 1299

	
1277 1300
    /// \brief Add an additional caption to the \c \@attributes section
1278 1301
    ///
1279 1302
    /// Add an additional caption to the \c \@attributes section.
1280 1303
    GraphWriter& attributes(const std::string& caption) {
1281 1304
      _attributes_caption = caption;
1282 1305
      return *this;
1283 1306
    }
1284 1307

	
1285 1308
    /// \name Skipping section
1286 1309
    /// @{
1287 1310

	
1288 1311
    /// \brief Skip writing the node set
1289 1312
    ///
1290 1313
    /// The \c \@nodes section will not be written to the stream.
1291 1314
    GraphWriter& skipNodes() {
1292 1315
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1293 1316
      _skip_nodes = true;
1294 1317
      return *this;
1295 1318
    }
1296 1319

	
1297 1320
    /// \brief Skip writing edge set
1298 1321
    ///
1299 1322
    /// The \c \@edges section will not be written to the stream.
1300 1323
    GraphWriter& skipEdges() {
1301 1324
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1302 1325
      _skip_edges = true;
1303 1326
      return *this;
1304 1327
    }
1305 1328

	
1306 1329
    /// @}
1307 1330

	
1308 1331
  private:
1309 1332

	
1310 1333
    void writeNodes() {
1311 1334
      _writer_bits::MapStorageBase<Node>* label = 0;
1312 1335
      for (typename NodeMaps::iterator it = _node_maps.begin();
1313 1336
           it != _node_maps.end(); ++it) {
1314 1337
        if (it->first == "label") {
1315 1338
          label = it->second;
1316 1339
          break;
1317 1340
        }
1318 1341
      }
1319 1342

	
1320 1343
      *_os << "@nodes";
1321 1344
      if (!_nodes_caption.empty()) {
1322 1345
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1323 1346
      }
1324 1347
      *_os << std::endl;
1325 1348

	
1326 1349
      if (label == 0) {
1327 1350
        *_os << "label" << '\t';
1328 1351
      }
1329 1352
      for (typename NodeMaps::iterator it = _node_maps.begin();
1330 1353
           it != _node_maps.end(); ++it) {
1331 1354
        _writer_bits::writeToken(*_os, it->first) << '\t';
1332 1355
      }
1333 1356
      *_os << std::endl;
1334 1357

	
1335 1358
      std::vector<Node> nodes;
1336 1359
      for (NodeIt n(_graph); n != INVALID; ++n) {
1337 1360
        nodes.push_back(n);
1338 1361
      }
1339 1362

	
1340 1363
      if (label == 0) {
1341
        IdMap<Graph, Node> id_map(_graph);
1342
        _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1364
        IdMap<GR, Node> id_map(_graph);
1365
        _writer_bits::MapLess<IdMap<GR, Node> > id_less(id_map);
1343 1366
        std::sort(nodes.begin(), nodes.end(), id_less);
1344 1367
      } else {
1345 1368
        label->sort(nodes);
1346 1369
      }
1347 1370

	
1348 1371
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1349 1372
        Node n = nodes[i];
1350 1373
        if (label == 0) {
1351 1374
          std::ostringstream os;
1352 1375
          os << _graph.id(n);
1353 1376
          _writer_bits::writeToken(*_os, os.str());
1354 1377
          *_os << '\t';
1355 1378
          _node_index.insert(std::make_pair(n, os.str()));
1356 1379
        }
1357 1380
        for (typename NodeMaps::iterator it = _node_maps.begin();
1358 1381
             it != _node_maps.end(); ++it) {
1359 1382
          std::string value = it->second->get(n);
1360 1383
          _writer_bits::writeToken(*_os, value);
1361 1384
          if (it->first == "label") {
1362 1385
            _node_index.insert(std::make_pair(n, value));
1363 1386
          }
1364 1387
          *_os << '\t';
1365 1388
        }
1366 1389
        *_os << std::endl;
1367 1390
      }
1368 1391
    }
1369 1392

	
1370 1393
    void createNodeIndex() {
1371 1394
      _writer_bits::MapStorageBase<Node>* label = 0;
1372 1395
      for (typename NodeMaps::iterator it = _node_maps.begin();
1373 1396
           it != _node_maps.end(); ++it) {
1374 1397
        if (it->first == "label") {
1375 1398
          label = it->second;
1376 1399
          break;
1377 1400
        }
1378 1401
      }
1379 1402

	
1380 1403
      if (label == 0) {
1381 1404
        for (NodeIt n(_graph); n != INVALID; ++n) {
1382 1405
          std::ostringstream os;
1383 1406
          os << _graph.id(n);
1384 1407
          _node_index.insert(std::make_pair(n, os.str()));
1385 1408
        }
1386 1409
      } else {
1387 1410
        for (NodeIt n(_graph); n != INVALID; ++n) {
1388 1411
          std::string value = label->get(n);
1389 1412
          _node_index.insert(std::make_pair(n, value));
1390 1413
        }
1391 1414
      }
1392 1415
    }
1393 1416

	
1394 1417
    void writeEdges() {
1395 1418
      _writer_bits::MapStorageBase<Edge>* label = 0;
1396 1419
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1397 1420
           it != _edge_maps.end(); ++it) {
1398 1421
        if (it->first == "label") {
1399 1422
          label = it->second;
1400 1423
          break;
1401 1424
        }
1402 1425
      }
1403 1426

	
1404 1427
      *_os << "@edges";
1405 1428
      if (!_edges_caption.empty()) {
1406 1429
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
1407 1430
      }
1408 1431
      *_os << std::endl;
1409 1432

	
1410 1433
      *_os << '\t' << '\t';
1411 1434
      if (label == 0) {
1412 1435
        *_os << "label" << '\t';
1413 1436
      }
1414 1437
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1415 1438
           it != _edge_maps.end(); ++it) {
1416 1439
        _writer_bits::writeToken(*_os, it->first) << '\t';
1417 1440
      }
1418 1441
      *_os << std::endl;
1419 1442

	
1420 1443
      std::vector<Edge> edges;
1421 1444
      for (EdgeIt n(_graph); n != INVALID; ++n) {
1422 1445
        edges.push_back(n);
1423 1446
      }
1424 1447

	
1425 1448
      if (label == 0) {
1426
        IdMap<Graph, Edge> id_map(_graph);
1427
        _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1449
        IdMap<GR, Edge> id_map(_graph);
1450
        _writer_bits::MapLess<IdMap<GR, Edge> > id_less(id_map);
1428 1451
        std::sort(edges.begin(), edges.end(), id_less);
1429 1452
      } else {
1430 1453
        label->sort(edges);
1431 1454
      }
1432 1455

	
1433 1456
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1434 1457
        Edge e = edges[i];
1435 1458
        _writer_bits::writeToken(*_os, _node_index.
1436 1459
                                 find(_graph.u(e))->second);
1437 1460
        *_os << '\t';
1438 1461
        _writer_bits::writeToken(*_os, _node_index.
1439 1462
                                 find(_graph.v(e))->second);
1440 1463
        *_os << '\t';
1441 1464
        if (label == 0) {
1442 1465
          std::ostringstream os;
1443 1466
          os << _graph.id(e);
1444 1467
          _writer_bits::writeToken(*_os, os.str());
1445 1468
          *_os << '\t';
1446 1469
          _edge_index.insert(std::make_pair(e, os.str()));
1447 1470
        }
1448 1471
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
1449 1472
             it != _edge_maps.end(); ++it) {
1450 1473
          std::string value = it->second->get(e);
1451 1474
          _writer_bits::writeToken(*_os, value);
1452 1475
          if (it->first == "label") {
1453 1476
            _edge_index.insert(std::make_pair(e, value));
1454 1477
          }
1455 1478
          *_os << '\t';
1456 1479
        }
1457 1480
        *_os << std::endl;
1458 1481
      }
1459 1482
    }
1460 1483

	
1461 1484
    void createEdgeIndex() {
1462 1485
      _writer_bits::MapStorageBase<Edge>* label = 0;
1463 1486
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1464 1487
           it != _edge_maps.end(); ++it) {
1465 1488
        if (it->first == "label") {
1466 1489
          label = it->second;
1467 1490
          break;
1468 1491
        }
1469 1492
      }
1470 1493

	
1471 1494
      if (label == 0) {
1472 1495
        for (EdgeIt e(_graph); e != INVALID; ++e) {
1473 1496
          std::ostringstream os;
1474 1497
          os << _graph.id(e);
1475 1498
          _edge_index.insert(std::make_pair(e, os.str()));
1476 1499
        }
1477 1500
      } else {
1478 1501
        for (EdgeIt e(_graph); e != INVALID; ++e) {
1479 1502
          std::string value = label->get(e);
1480 1503
          _edge_index.insert(std::make_pair(e, value));
1481 1504
        }
1482 1505
      }
1483 1506
    }
1484 1507

	
1485 1508
    void writeAttributes() {
1486 1509
      if (_attributes.empty()) return;
1487 1510
      *_os << "@attributes";
1488 1511
      if (!_attributes_caption.empty()) {
1489 1512
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1490 1513
      }
1491 1514
      *_os << std::endl;
1492 1515
      for (typename Attributes::iterator it = _attributes.begin();
1493 1516
           it != _attributes.end(); ++it) {
1494 1517
        _writer_bits::writeToken(*_os, it->first) << ' ';
1495 1518
        _writer_bits::writeToken(*_os, it->second->get());
1496 1519
        *_os << std::endl;
1497 1520
      }
1498 1521
    }
1499 1522

	
1500 1523
  public:
1501 1524

	
1502 1525
    /// \name Execution of the writer
1503 1526
    /// @{
1504 1527

	
1505 1528
    /// \brief Start the batch processing
1506 1529
    ///
1507 1530
    /// This function starts the batch processing.
1508 1531
    void run() {
1509 1532
      if (!_skip_nodes) {
1510 1533
        writeNodes();
1511 1534
      } else {
1512 1535
        createNodeIndex();
1513 1536
      }
1514 1537
      if (!_skip_edges) {
1515 1538
        writeEdges();
1516 1539
      } else {
1517 1540
        createEdgeIndex();
1518 1541
      }
1519 1542
      writeAttributes();
1520 1543
    }
1521 1544

	
1522 1545
    /// \brief Give back the stream of the writer
1523 1546
    ///
1524 1547
    /// Give back the stream of the writer
1525 1548
    std::ostream& ostream() {
1526 1549
      return *_os;
1527 1550
    }
1528 1551

	
1529 1552
    /// @}
1530 1553
  };
1531 1554

	
1555
  /// \ingroup lemon_io
1556
  ///
1532 1557
  /// \brief Return a \ref GraphWriter class
1533 1558
  ///
1534
  /// This function just returns a \ref GraphWriter class.
1559
  /// This function just returns a \ref GraphWriter class. 
1560
  ///
1561
  /// With this function a graph can be write to a file or output
1562
  /// stream in \ref lgf-format "LGF" format with several maps and
1563
  /// attributes. For example, with the following code a weighted
1564
  /// matching problem can be written to the standard output, i.e. a
1565
  /// graph with a \e weight map on the edges:
1566
  ///
1567
  ///\code
1568
  ///ListGraph graph;
1569
  ///ListGraph::EdgeMap<int> weight(graph);
1570
  ///  // Setting the weight map
1571
  ///graphWriter(graph, std::cout).
1572
  ///  edgeMap("weight", weight).
1573
  ///  run();
1574
  ///\endcode
1575
  ///
1576
  /// For a complete documentation, please see the \ref GraphWriter
1577
  /// class documentation.
1578
  /// \warning Don't forget to put the \ref GraphWriter::run() "run()"
1579
  /// to the end of the parameter list.
1535 1580
  /// \relates GraphWriter
1536
  template <typename Graph>
1537
  GraphWriter<Graph> graphWriter(const Graph& graph,
1538
                                 std::ostream& os) {
1539
    GraphWriter<Graph> tmp(graph, os);
1581
  /// \sa graphWriter(const TGR& graph, const std::string& fn)
1582
  /// \sa graphWriter(const TGR& graph, const char* fn)
1583
  template <typename TGR>
1584
  GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os) {
1585
    GraphWriter<TGR> tmp(graph, os);
1540 1586
    return tmp;
1541 1587
  }
1542 1588

	
1543 1589
  /// \brief Return a \ref GraphWriter class
1544 1590
  ///
1545 1591
  /// This function just returns a \ref GraphWriter class.
1546 1592
  /// \relates GraphWriter
1547
  template <typename Graph>
1548
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
1549
    GraphWriter<Graph> tmp(graph, fn);
1593
  /// \sa graphWriter(const TGR& graph, std::ostream& os)
1594
  template <typename TGR>
1595
  GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn) {
1596
    GraphWriter<TGR> tmp(graph, fn);
1550 1597
    return tmp;
1551 1598
  }
1552 1599

	
1553 1600
  /// \brief Return a \ref GraphWriter class
1554 1601
  ///
1555 1602
  /// This function just returns a \ref GraphWriter class.
1556 1603
  /// \relates GraphWriter
1557
  template <typename Graph>
1558
  GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
1559
    GraphWriter<Graph> tmp(graph, fn);
1604
  /// \sa graphWriter(const TGR& graph, std::ostream& os)
1605
  template <typename TGR>
1606
  GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn) {
1607
    GraphWriter<TGR> tmp(graph, fn);
1560 1608
    return tmp;
1561 1609
  }
1562 1610

	
1563 1611
  class SectionWriter;
1564 1612

	
1565 1613
  SectionWriter sectionWriter(std::istream& is);
1566 1614
  SectionWriter sectionWriter(const std::string& fn);
1567 1615
  SectionWriter sectionWriter(const char* fn);
1568 1616

	
1569 1617
  /// \ingroup lemon_io
1570 1618
  ///
1571 1619
  /// \brief Section writer class
1572 1620
  ///
1573 1621
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
1574 1622
  /// which contain any data in arbitrary format. Such sections can be
1575 1623
  /// written with this class. A writing rule can be added to the
1576 1624
  /// class with two different functions. With the \c sectionLines()
1577 1625
  /// function a generator can write the section line-by-line, while
1578 1626
  /// with the \c sectionStream() member the section can be written to
1579 1627
  /// an output stream.
1580 1628
  class SectionWriter {
1581 1629
  private:
1582 1630

	
1583 1631
    std::ostream* _os;
1584 1632
    bool local_os;
1585 1633

	
1586 1634
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1587 1635
    Sections;
1588 1636

	
1589 1637
    Sections _sections;
1590 1638

	
1591 1639
  public:
1592 1640

	
1593 1641
    /// \brief Constructor
1594 1642
    ///
1595 1643
    /// Construct a section writer, which writes to the given output
1596 1644
    /// stream.
1597 1645
    SectionWriter(std::ostream& os)
1598 1646
      : _os(&os), local_os(false) {}
1599 1647

	
1600 1648
    /// \brief Constructor
1601 1649
    ///
1602 1650
    /// Construct a section writer, which writes into the given file.
1603 1651
    SectionWriter(const std::string& fn)
1604 1652
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
1605 1653
      if (!(*_os)) {
1606 1654
        delete _os;
1607 1655
        throw IoError("Cannot write file", fn);
1608 1656
      }
1609 1657
    }
1610 1658

	
1611 1659
    /// \brief Constructor
1612 1660
    ///
1613 1661
    /// Construct a section writer, which writes into the given file.
1614 1662
    SectionWriter(const char* fn)
1615 1663
      : _os(new std::ofstream(fn)), local_os(true) {
1616 1664
      if (!(*_os)) {
1617 1665
        delete _os;
1618 1666
        throw IoError("Cannot write file", fn);
1619 1667
      }
1620 1668
    }
1621 1669

	
1622 1670
    /// \brief Destructor
1623 1671
    ~SectionWriter() {
1624 1672
      for (Sections::iterator it = _sections.begin();
1625 1673
           it != _sections.end(); ++it) {
1626 1674
        delete it->second;
1627 1675
      }
1628 1676

	
1629 1677
      if (local_os) {
1630 1678
        delete _os;
1631 1679
      }
1632 1680

	
1633 1681
    }
1634 1682

	
1635 1683
  private:
1636 1684

	
1637 1685
    friend SectionWriter sectionWriter(std::ostream& os);
1638 1686
    friend SectionWriter sectionWriter(const std::string& fn);
1639 1687
    friend SectionWriter sectionWriter(const char* fn);
1640 1688

	
1641 1689
    SectionWriter(SectionWriter& other)
1642 1690
      : _os(other._os), local_os(other.local_os) {
1643 1691

	
1644 1692
      other._os = 0;
1645 1693
      other.local_os = false;
1646 1694

	
1647 1695
      _sections.swap(other._sections);
1648 1696
    }
1649 1697

	
1650 1698
    SectionWriter& operator=(const SectionWriter&);
1651 1699

	
1652 1700
  public:
1653 1701

	
1654 1702
    /// \name Section writers
1655 1703
    /// @{
1656 1704

	
1657 1705
    /// \brief Add a section writer with line oriented writing
1658 1706
    ///
1659 1707
    /// The first parameter is the type descriptor of the section, the
1660 1708
    /// second is a generator with std::string values. At the writing
1661 1709
    /// process, the returned \c std::string will be written into the
1662 1710
    /// output file until it is an empty string.
1663 1711
    ///
1664 1712
    /// For example, an integer vector is written into a section.
1665 1713
    ///\code
1666 1714
    ///  @numbers
1667 1715
    ///  12 45 23 78
1668 1716
    ///  4 28 38 28
1669 1717
    ///  23 6 16
1670 1718
    ///\endcode
1671 1719
    ///
1672 1720
    /// The generator is implemented as a struct.
1673 1721
    ///\code
1674 1722
    ///  struct NumberSection {
1675 1723
    ///    std::vector<int>::const_iterator _it, _end;
1676 1724
    ///    NumberSection(const std::vector<int>& data)
1677 1725
    ///      : _it(data.begin()), _end(data.end()) {}
1678 1726
    ///    std::string operator()() {
1679 1727
    ///      int rem_in_line = 4;
1680 1728
    ///      std::ostringstream ls;
1681 1729
    ///      while (rem_in_line > 0 && _it != _end) {
1682 1730
    ///        ls << *(_it++) << ' ';
1683 1731
    ///        --rem_in_line;
1684 1732
    ///      }
1685 1733
    ///      return ls.str();
1686 1734
    ///    }
1687 1735
    ///  };
1688 1736
    ///
1689 1737
    ///  // ...
1690 1738
    ///
1691 1739
    ///  writer.sectionLines("numbers", NumberSection(vec));
1692 1740
    ///\endcode
1693 1741
    template <typename Functor>
1694 1742
    SectionWriter& sectionLines(const std::string& type, Functor functor) {
1695 1743
      LEMON_ASSERT(!type.empty(), "Type is empty.");
1696 1744
      _sections.push_back(std::make_pair(type,
1697 1745
        new _writer_bits::LineSection<Functor>(functor)));
1698 1746
      return *this;
1699 1747
    }
1700 1748

	
1701 1749

	
1702 1750
    /// \brief Add a section writer with stream oriented writing
1703 1751
    ///
1704 1752
    /// The first parameter is the type of the section, the second is
1705 1753
    /// a functor, which takes a \c std::ostream& parameter. The
1706 1754
    /// functor writes the section to the output stream.
1707 1755
    /// \warning The last line must be closed with end-line character.
1708 1756
    template <typename Functor>
1709 1757
    SectionWriter& sectionStream(const std::string& type, Functor functor) {
1710 1758
      LEMON_ASSERT(!type.empty(), "Type is empty.");
1711 1759
      _sections.push_back(std::make_pair(type,
1712 1760
         new _writer_bits::StreamSection<Functor>(functor)));
1713 1761
      return *this;
1714 1762
    }
1715 1763

	
1716 1764
    /// @}
1717 1765

	
1718 1766
  public:
1719 1767

	
1720 1768

	
1721 1769
    /// \name Execution of the writer
1722 1770
    /// @{
1723 1771

	
1724 1772
    /// \brief Start the batch processing
1725 1773
    ///
1726 1774
    /// This function starts the batch processing.
1727 1775
    void run() {
1728 1776

	
1729 1777
      LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1730 1778

	
1731 1779
      for (Sections::iterator it = _sections.begin();
1732 1780
           it != _sections.end(); ++it) {
1733 1781
        (*_os) << '@' << it->first << std::endl;
1734 1782
        it->second->process(*_os);
1735 1783
      }
1736 1784
    }
1737 1785

	
1738 1786
    /// \brief Give back the stream of the writer
1739 1787
    ///
1740 1788
    /// Returns the stream of the writer
1741 1789
    std::ostream& ostream() {
1742 1790
      return *_os;
1743 1791
    }
1744 1792

	
1745 1793
    /// @}
1746 1794

	
1747 1795
  };
1748 1796

	
1797
  /// \ingroup lemon_io
1798
  ///
1749 1799
  /// \brief Return a \ref SectionWriter class
1750 1800
  ///
1751 1801
  /// This function just returns a \ref SectionWriter class.
1802
  ///
1803
  /// Please see SectionWriter documentation about the custom section
1804
  /// output.
1805
  ///
1752 1806
  /// \relates SectionWriter
1807
  /// \sa sectionWriter(const std::string& fn)
1808
  /// \sa sectionWriter(const char *fn)
1753 1809
  inline SectionWriter sectionWriter(std::ostream& os) {
1754 1810
    SectionWriter tmp(os);
1755 1811
    return tmp;
1756 1812
  }
1757 1813

	
1758 1814
  /// \brief Return a \ref SectionWriter class
1759 1815
  ///
1760 1816
  /// This function just returns a \ref SectionWriter class.
1761 1817
  /// \relates SectionWriter
1818
  /// \sa sectionWriter(std::ostream& os)
1762 1819
  inline SectionWriter sectionWriter(const std::string& fn) {
1763 1820
    SectionWriter tmp(fn);
1764 1821
    return tmp;
1765 1822
  }
1766 1823

	
1767 1824
  /// \brief Return a \ref SectionWriter class
1768 1825
  ///
1769 1826
  /// This function just returns a \ref SectionWriter class.
1770 1827
  /// \relates SectionWriter
1828
  /// \sa sectionWriter(std::ostream& os)
1771 1829
  inline SectionWriter sectionWriter(const char* fn) {
1772 1830
    SectionWriter tmp(fn);
1773 1831
    return tmp;
1774 1832
  }
1775 1833
}
1776 1834

	
1777 1835
#endif
0 comments (0 inline)