gravatar
ladanyi@tmit.bme.hu
ladanyi@tmit.bme.hu
Fix compilation with Visual Studio 2005.
0 2 0
default
2 files changed with 94 insertions and 136 deletions:
↑ Collapse diff ↑
Ignore white space 768 line context
... ...
@@ -10,777 +10,799 @@
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/assert.h>
35 35
#include <lemon/core.h>
36 36

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

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

	
42 42
namespace lemon {
43 43

	
44 44
  namespace _reader_bits {
45 45

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

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

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

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

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

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

	
81 81
    };
82 82

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
289 289
    inline std::istream& readToken(std::istream& is, std::string& str) {
290 290
      std::ostringstream os;
291 291

	
292 292
      char c;
293 293
      is >> std::ws;
294 294

	
295 295
      if (!is.get(c))
296 296
        return is;
297 297

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

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

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

	
333 333
      Functor _functor;
334 334

	
335 335
    public:
336 336

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

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

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

	
365 365
      Functor _functor;
366 366

	
367 367
    public:
368 368

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

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

	
389 389
  }
390 390

	
391 391
  template <typename Digraph>
392 392
  class DigraphReader;
393 393

	
394
  /// \brief Return a \ref DigraphReader class
395
  ///
396
  /// This function just returns a \ref DigraphReader class.
397
  /// \relates DigraphReader
394 398
  template <typename Digraph>
395 399
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
396
                                       std::istream& is = std::cin);
397

	
400
                                       std::istream& is = std::cin) {
401
    DigraphReader<Digraph> tmp(digraph, is);
402
    return tmp;
403
  }
404

	
405
  /// \brief Return a \ref DigraphReader class
406
  ///
407
  /// This function just returns a \ref DigraphReader class.
408
  /// \relates DigraphReader
398 409
  template <typename Digraph>
399
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const std::string& fn);
400

	
410
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
411
                                       const std::string& fn) {
412
    DigraphReader<Digraph> tmp(digraph, fn);
413
    return tmp;
414
  }
415

	
416
  /// \brief Return a \ref DigraphReader class
417
  ///
418
  /// This function just returns a \ref DigraphReader class.
419
  /// \relates DigraphReader
401 420
  template <typename Digraph>
402
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const char *fn);
421
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const char* fn) {
422
    DigraphReader<Digraph> tmp(digraph, fn);
423
    return tmp;
424
  }
403 425

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

	
458 480
    typedef _Digraph Digraph;
459 481
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
460 482

	
461 483
  private:
462 484

	
463 485

	
464 486
    std::istream* _is;
465 487
    bool local_is;
466 488
    std::string _filename;
467 489

	
468 490
    Digraph& _digraph;
469 491

	
470 492
    std::string _nodes_caption;
471 493
    std::string _arcs_caption;
472 494
    std::string _attributes_caption;
473 495

	
474 496
    typedef std::map<std::string, Node> NodeIndex;
475 497
    NodeIndex _node_index;
476 498
    typedef std::map<std::string, Arc> ArcIndex;
477 499
    ArcIndex _arc_index;
478 500

	
479 501
    typedef std::vector<std::pair<std::string,
480 502
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
481 503
    NodeMaps _node_maps;
482 504

	
483 505
    typedef std::vector<std::pair<std::string,
484 506
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
485 507
    ArcMaps _arc_maps;
486 508

	
487 509
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
488 510
      Attributes;
489 511
    Attributes _attributes;
490 512

	
491 513
    bool _use_nodes;
492 514
    bool _use_arcs;
493 515

	
494 516
    bool _skip_nodes;
495 517
    bool _skip_arcs;
496 518

	
497 519
    int line_num;
498 520
    std::istringstream line;
499 521

	
500 522
  public:
501 523

	
502 524
    /// \brief Constructor
503 525
    ///
504 526
    /// Construct a directed graph reader, which reads from the given
505 527
    /// input stream.
506 528
    DigraphReader(Digraph& digraph, std::istream& is = std::cin)
507 529
      : _is(&is), local_is(false), _digraph(digraph),
508 530
        _use_nodes(false), _use_arcs(false),
509 531
        _skip_nodes(false), _skip_arcs(false) {}
510 532

	
511 533
    /// \brief Constructor
512 534
    ///
513 535
    /// Construct a directed graph reader, which reads from the given
514 536
    /// file.
515 537
    DigraphReader(Digraph& digraph, const std::string& fn)
516 538
      : _is(new std::ifstream(fn.c_str())), local_is(true),
517 539
        _filename(fn), _digraph(digraph),
518 540
        _use_nodes(false), _use_arcs(false),
519 541
        _skip_nodes(false), _skip_arcs(false) {
520 542
      if (!(*_is)) {
521 543
        delete _is;
522 544
        throw IoError("Cannot open file", fn);
523 545
      }
524 546
    }
525 547

	
526 548
    /// \brief Constructor
527 549
    ///
528 550
    /// Construct a directed graph reader, which reads from the given
529 551
    /// file.
530 552
    DigraphReader(Digraph& digraph, const char* fn)
531 553
      : _is(new std::ifstream(fn)), local_is(true),
532 554
        _filename(fn), _digraph(digraph),
533 555
        _use_nodes(false), _use_arcs(false),
534 556
        _skip_nodes(false), _skip_arcs(false) {
535 557
      if (!(*_is)) {
536 558
        delete _is;
537 559
        throw IoError("Cannot open file", fn);
538 560
      }
539 561
    }
540 562

	
541 563
    /// \brief Destructor
542 564
    ~DigraphReader() {
543 565
      for (typename NodeMaps::iterator it = _node_maps.begin();
544 566
           it != _node_maps.end(); ++it) {
545 567
        delete it->second;
546 568
      }
547 569

	
548 570
      for (typename ArcMaps::iterator it = _arc_maps.begin();
549 571
           it != _arc_maps.end(); ++it) {
550 572
        delete it->second;
551 573
      }
552 574

	
553 575
      for (typename Attributes::iterator it = _attributes.begin();
554 576
           it != _attributes.end(); ++it) {
555 577
        delete it->second;
556 578
      }
557 579

	
558 580
      if (local_is) {
559 581
        delete _is;
560 582
      }
561 583

	
562 584
    }
563 585

	
564 586
  private:
565 587

	
566 588
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
567 589
                                                  std::istream& is);
568 590
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
569 591
                                                  const std::string& fn);
570 592
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
571 593
                                                  const char *fn);
572 594

	
573 595
    DigraphReader(DigraphReader& other)
574 596
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
575 597
        _use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
576 598
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
577 599

	
578 600
      other._is = 0;
579 601
      other.local_is = false;
580 602

	
581 603
      _node_index.swap(other._node_index);
582 604
      _arc_index.swap(other._arc_index);
583 605

	
584 606
      _node_maps.swap(other._node_maps);
585 607
      _arc_maps.swap(other._arc_maps);
586 608
      _attributes.swap(other._attributes);
587 609

	
588 610
      _nodes_caption = other._nodes_caption;
589 611
      _arcs_caption = other._arcs_caption;
590 612
      _attributes_caption = other._attributes_caption;
591 613

	
592 614
    }
593 615

	
594 616
    DigraphReader& operator=(const DigraphReader&);
595 617

	
596 618
  public:
597 619

	
598 620
    /// \name Reading rules
599 621
    /// @{
600 622

	
601 623
    /// \brief Node map reading rule
602 624
    ///
603 625
    /// Add a node map reading rule to the reader.
604 626
    template <typename Map>
605 627
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
606 628
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
607 629
      _reader_bits::MapStorageBase<Node>* storage =
608 630
        new _reader_bits::MapStorage<Node, Map>(map);
609 631
      _node_maps.push_back(std::make_pair(caption, storage));
610 632
      return *this;
611 633
    }
612 634

	
613 635
    /// \brief Node map reading rule
614 636
    ///
615 637
    /// Add a node map reading rule with specialized converter to the
616 638
    /// reader.
617 639
    template <typename Map, typename Converter>
618 640
    DigraphReader& nodeMap(const std::string& caption, Map& map,
619 641
                           const Converter& converter = Converter()) {
620 642
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
621 643
      _reader_bits::MapStorageBase<Node>* storage =
622 644
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
623 645
      _node_maps.push_back(std::make_pair(caption, storage));
624 646
      return *this;
625 647
    }
626 648

	
627 649
    /// \brief Arc map reading rule
628 650
    ///
629 651
    /// Add an arc map reading rule to the reader.
630 652
    template <typename Map>
631 653
    DigraphReader& arcMap(const std::string& caption, Map& map) {
632 654
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
633 655
      _reader_bits::MapStorageBase<Arc>* storage =
634 656
        new _reader_bits::MapStorage<Arc, Map>(map);
635 657
      _arc_maps.push_back(std::make_pair(caption, storage));
636 658
      return *this;
637 659
    }
638 660

	
639 661
    /// \brief Arc map reading rule
640 662
    ///
641 663
    /// Add an arc map reading rule with specialized converter to the
642 664
    /// reader.
643 665
    template <typename Map, typename Converter>
644 666
    DigraphReader& arcMap(const std::string& caption, Map& map,
645 667
                          const Converter& converter = Converter()) {
646 668
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
647 669
      _reader_bits::MapStorageBase<Arc>* storage =
648 670
        new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
649 671
      _arc_maps.push_back(std::make_pair(caption, storage));
650 672
      return *this;
651 673
    }
652 674

	
653 675
    /// \brief Attribute reading rule
654 676
    ///
655 677
    /// Add an attribute reading rule to the reader.
656 678
    template <typename Value>
657 679
    DigraphReader& attribute(const std::string& caption, Value& value) {
658 680
      _reader_bits::ValueStorageBase* storage =
659 681
        new _reader_bits::ValueStorage<Value>(value);
660 682
      _attributes.insert(std::make_pair(caption, storage));
661 683
      return *this;
662 684
    }
663 685

	
664 686
    /// \brief Attribute reading rule
665 687
    ///
666 688
    /// Add an attribute reading rule with specialized converter to the
667 689
    /// reader.
668 690
    template <typename Value, typename Converter>
669 691
    DigraphReader& attribute(const std::string& caption, Value& value,
670 692
                             const Converter& converter = Converter()) {
671 693
      _reader_bits::ValueStorageBase* storage =
672 694
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
673 695
      _attributes.insert(std::make_pair(caption, storage));
674 696
      return *this;
675 697
    }
676 698

	
677 699
    /// \brief Node reading rule
678 700
    ///
679 701
    /// Add a node reading rule to reader.
680 702
    DigraphReader& node(const std::string& caption, Node& node) {
681 703
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
682 704
      Converter converter(_node_index);
683 705
      _reader_bits::ValueStorageBase* storage =
684 706
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
685 707
      _attributes.insert(std::make_pair(caption, storage));
686 708
      return *this;
687 709
    }
688 710

	
689 711
    /// \brief Arc reading rule
690 712
    ///
691 713
    /// Add an arc reading rule to reader.
692 714
    DigraphReader& arc(const std::string& caption, Arc& arc) {
693 715
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
694 716
      Converter converter(_arc_index);
695 717
      _reader_bits::ValueStorageBase* storage =
696 718
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
697 719
      _attributes.insert(std::make_pair(caption, storage));
698 720
      return *this;
699 721
    }
700 722

	
701 723
    /// @}
702 724

	
703 725
    /// \name Select section by name
704 726
    /// @{
705 727

	
706 728
    /// \brief Set \c \@nodes section to be read
707 729
    ///
708 730
    /// Set \c \@nodes section to be read
709 731
    DigraphReader& nodes(const std::string& caption) {
710 732
      _nodes_caption = caption;
711 733
      return *this;
712 734
    }
713 735

	
714 736
    /// \brief Set \c \@arcs section to be read
715 737
    ///
716 738
    /// Set \c \@arcs section to be read
717 739
    DigraphReader& arcs(const std::string& caption) {
718 740
      _arcs_caption = caption;
719 741
      return *this;
720 742
    }
721 743

	
722 744
    /// \brief Set \c \@attributes section to be read
723 745
    ///
724 746
    /// Set \c \@attributes section to be read
725 747
    DigraphReader& attributes(const std::string& caption) {
726 748
      _attributes_caption = caption;
727 749
      return *this;
728 750
    }
729 751

	
730 752
    /// @}
731 753

	
732 754
    /// \name Using previously constructed node or arc set
733 755
    /// @{
734 756

	
735 757
    /// \brief Use previously constructed node set
736 758
    ///
737 759
    /// Use previously constructed node set, and specify the node
738 760
    /// label map.
739 761
    template <typename Map>
740 762
    DigraphReader& useNodes(const Map& map) {
741 763
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
742 764
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
743 765
      _use_nodes = true;
744 766
      _writer_bits::DefaultConverter<typename Map::Value> converter;
745 767
      for (NodeIt n(_digraph); n != INVALID; ++n) {
746 768
        _node_index.insert(std::make_pair(converter(map[n]), n));
747 769
      }
748 770
      return *this;
749 771
    }
750 772

	
751 773
    /// \brief Use previously constructed node set
752 774
    ///
753 775
    /// Use previously constructed node set, and specify the node
754 776
    /// label map and a functor which converts the label map values to
755 777
    /// \c std::string.
756 778
    template <typename Map, typename Converter>
757 779
    DigraphReader& useNodes(const Map& map,
758 780
                            const Converter& converter = Converter()) {
759 781
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
760 782
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
761 783
      _use_nodes = true;
762 784
      for (NodeIt n(_digraph); n != INVALID; ++n) {
763 785
        _node_index.insert(std::make_pair(converter(map[n]), n));
764 786
      }
765 787
      return *this;
766 788
    }
767 789

	
768 790
    /// \brief Use previously constructed arc set
769 791
    ///
770 792
    /// Use previously constructed arc set, and specify the arc
771 793
    /// label map.
772 794
    template <typename Map>
773 795
    DigraphReader& useArcs(const Map& map) {
774 796
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
775 797
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
776 798
      _use_arcs = true;
777 799
      _writer_bits::DefaultConverter<typename Map::Value> converter;
778 800
      for (ArcIt a(_digraph); a != INVALID; ++a) {
779 801
        _arc_index.insert(std::make_pair(converter(map[a]), a));
780 802
      }
781 803
      return *this;
782 804
    }
783 805

	
784 806
    /// \brief Use previously constructed arc set
785 807
    ///
786 808
    /// Use previously constructed arc set, and specify the arc
... ...
@@ -808,813 +830,801 @@
808 830
    /// \c useNodes() should be used to specify the label of the nodes.
809 831
    DigraphReader& skipNodes() {
810 832
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
811 833
      _skip_nodes = true;
812 834
      return *this;
813 835
    }
814 836

	
815 837
    /// \brief Skips the reading of arc section
816 838
    ///
817 839
    /// Omit the reading of the arc section. This implies that each arc
818 840
    /// map reading rule will be abandoned, and the arcs of the graph
819 841
    /// will not be constructed.
820 842
    DigraphReader& skipArcs() {
821 843
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set");
822 844
      _skip_arcs = true;
823 845
      return *this;
824 846
    }
825 847

	
826 848
    /// @}
827 849

	
828 850
  private:
829 851

	
830 852
    bool readLine() {
831 853
      std::string str;
832 854
      while(++line_num, std::getline(*_is, str)) {
833 855
        line.clear(); line.str(str);
834 856
        char c;
835 857
        if (line >> std::ws >> c && c != '#') {
836 858
          line.putback(c);
837 859
          return true;
838 860
        }
839 861
      }
840 862
      return false;
841 863
    }
842 864

	
843 865
    bool readSuccess() {
844 866
      return static_cast<bool>(*_is);
845 867
    }
846 868

	
847 869
    void skipSection() {
848 870
      char c;
849 871
      while (readSuccess() && line >> c && c != '@') {
850 872
        readLine();
851 873
      }
852 874
      line.putback(c);
853 875
    }
854 876

	
855 877
    void readNodes() {
856 878

	
857 879
      std::vector<int> map_index(_node_maps.size());
858 880
      int map_num, label_index;
859 881

	
860 882
      char c;
861 883
      if (!readLine() || !(line >> c) || c == '@') {
862 884
        if (readSuccess() && line) line.putback(c);
863 885
        if (!_node_maps.empty())
864 886
          throw FormatError("Cannot find map names");
865 887
        return;
866 888
      }
867 889
      line.putback(c);
868 890

	
869 891
      {
870 892
        std::map<std::string, int> maps;
871 893

	
872 894
        std::string map;
873 895
        int index = 0;
874 896
        while (_reader_bits::readToken(line, map)) {
875 897
          if (maps.find(map) != maps.end()) {
876 898
            std::ostringstream msg;
877 899
            msg << "Multiple occurence of node map: " << map;
878 900
            throw FormatError(msg.str());
879 901
          }
880 902
          maps.insert(std::make_pair(map, index));
881 903
          ++index;
882 904
        }
883 905

	
884 906
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
885 907
          std::map<std::string, int>::iterator jt =
886 908
            maps.find(_node_maps[i].first);
887 909
          if (jt == maps.end()) {
888 910
            std::ostringstream msg;
889 911
            msg << "Map not found: " << _node_maps[i].first;
890 912
            throw FormatError(msg.str());
891 913
          }
892 914
          map_index[i] = jt->second;
893 915
        }
894 916

	
895 917
        {
896 918
          std::map<std::string, int>::iterator jt = maps.find("label");
897 919
          if (jt != maps.end()) {
898 920
            label_index = jt->second;
899 921
          } else {
900 922
            label_index = -1;
901 923
          }
902 924
        }
903 925
        map_num = maps.size();
904 926
      }
905 927

	
906 928
      while (readLine() && line >> c && c != '@') {
907 929
        line.putback(c);
908 930

	
909 931
        std::vector<std::string> tokens(map_num);
910 932
        for (int i = 0; i < map_num; ++i) {
911 933
          if (!_reader_bits::readToken(line, tokens[i])) {
912 934
            std::ostringstream msg;
913 935
            msg << "Column not found (" << i + 1 << ")";
914 936
            throw FormatError(msg.str());
915 937
          }
916 938
        }
917 939
        if (line >> std::ws >> c)
918 940
          throw FormatError("Extra character at the end of line");
919 941

	
920 942
        Node n;
921 943
        if (!_use_nodes) {
922 944
          n = _digraph.addNode();
923 945
          if (label_index != -1)
924 946
            _node_index.insert(std::make_pair(tokens[label_index], n));
925 947
        } else {
926 948
          if (label_index == -1)
927 949
            throw FormatError("Label map not found");
928 950
          typename std::map<std::string, Node>::iterator it =
929 951
            _node_index.find(tokens[label_index]);
930 952
          if (it == _node_index.end()) {
931 953
            std::ostringstream msg;
932 954
            msg << "Node with label not found: " << tokens[label_index];
933 955
            throw FormatError(msg.str());
934 956
          }
935 957
          n = it->second;
936 958
        }
937 959

	
938 960
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
939 961
          _node_maps[i].second->set(n, tokens[map_index[i]]);
940 962
        }
941 963

	
942 964
      }
943 965
      if (readSuccess()) {
944 966
        line.putback(c);
945 967
      }
946 968
    }
947 969

	
948 970
    void readArcs() {
949 971

	
950 972
      std::vector<int> map_index(_arc_maps.size());
951 973
      int map_num, label_index;
952 974

	
953 975
      char c;
954 976
      if (!readLine() || !(line >> c) || c == '@') {
955 977
        if (readSuccess() && line) line.putback(c);
956 978
        if (!_arc_maps.empty())
957 979
          throw FormatError("Cannot find map names");
958 980
        return;
959 981
      }
960 982
      line.putback(c);
961 983

	
962 984
      {
963 985
        std::map<std::string, int> maps;
964 986

	
965 987
        std::string map;
966 988
        int index = 0;
967 989
        while (_reader_bits::readToken(line, map)) {
968 990
          if (maps.find(map) != maps.end()) {
969 991
            std::ostringstream msg;
970 992
            msg << "Multiple occurence of arc map: " << map;
971 993
            throw FormatError(msg.str());
972 994
          }
973 995
          maps.insert(std::make_pair(map, index));
974 996
          ++index;
975 997
        }
976 998

	
977 999
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
978 1000
          std::map<std::string, int>::iterator jt =
979 1001
            maps.find(_arc_maps[i].first);
980 1002
          if (jt == maps.end()) {
981 1003
            std::ostringstream msg;
982 1004
            msg << "Map not found: " << _arc_maps[i].first;
983 1005
            throw FormatError(msg.str());
984 1006
          }
985 1007
          map_index[i] = jt->second;
986 1008
        }
987 1009

	
988 1010
        {
989 1011
          std::map<std::string, int>::iterator jt = maps.find("label");
990 1012
          if (jt != maps.end()) {
991 1013
            label_index = jt->second;
992 1014
          } else {
993 1015
            label_index = -1;
994 1016
          }
995 1017
        }
996 1018
        map_num = maps.size();
997 1019
      }
998 1020

	
999 1021
      while (readLine() && line >> c && c != '@') {
1000 1022
        line.putback(c);
1001 1023

	
1002 1024
        std::string source_token;
1003 1025
        std::string target_token;
1004 1026

	
1005 1027
        if (!_reader_bits::readToken(line, source_token))
1006 1028
          throw FormatError("Source not found");
1007 1029

	
1008 1030
        if (!_reader_bits::readToken(line, target_token))
1009 1031
          throw FormatError("Target not found");
1010 1032

	
1011 1033
        std::vector<std::string> tokens(map_num);
1012 1034
        for (int i = 0; i < map_num; ++i) {
1013 1035
          if (!_reader_bits::readToken(line, tokens[i])) {
1014 1036
            std::ostringstream msg;
1015 1037
            msg << "Column not found (" << i + 1 << ")";
1016 1038
            throw FormatError(msg.str());
1017 1039
          }
1018 1040
        }
1019 1041
        if (line >> std::ws >> c)
1020 1042
          throw FormatError("Extra character at the end of line");
1021 1043

	
1022 1044
        Arc a;
1023 1045
        if (!_use_arcs) {
1024 1046

	
1025 1047
          typename NodeIndex::iterator it;
1026 1048

	
1027 1049
          it = _node_index.find(source_token);
1028 1050
          if (it == _node_index.end()) {
1029 1051
            std::ostringstream msg;
1030 1052
            msg << "Item not found: " << source_token;
1031 1053
            throw FormatError(msg.str());
1032 1054
          }
1033 1055
          Node source = it->second;
1034 1056

	
1035 1057
          it = _node_index.find(target_token);
1036 1058
          if (it == _node_index.end()) {
1037 1059
            std::ostringstream msg;
1038 1060
            msg << "Item not found: " << target_token;
1039 1061
            throw FormatError(msg.str());
1040 1062
          }
1041 1063
          Node target = it->second;
1042 1064

	
1043 1065
          a = _digraph.addArc(source, target);
1044 1066
          if (label_index != -1)
1045 1067
            _arc_index.insert(std::make_pair(tokens[label_index], a));
1046 1068
        } else {
1047 1069
          if (label_index == -1)
1048 1070
            throw FormatError("Label map not found");
1049 1071
          typename std::map<std::string, Arc>::iterator it =
1050 1072
            _arc_index.find(tokens[label_index]);
1051 1073
          if (it == _arc_index.end()) {
1052 1074
            std::ostringstream msg;
1053 1075
            msg << "Arc with label not found: " << tokens[label_index];
1054 1076
            throw FormatError(msg.str());
1055 1077
          }
1056 1078
          a = it->second;
1057 1079
        }
1058 1080

	
1059 1081
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1060 1082
          _arc_maps[i].second->set(a, tokens[map_index[i]]);
1061 1083
        }
1062 1084

	
1063 1085
      }
1064 1086
      if (readSuccess()) {
1065 1087
        line.putback(c);
1066 1088
      }
1067 1089
    }
1068 1090

	
1069 1091
    void readAttributes() {
1070 1092

	
1071 1093
      std::set<std::string> read_attr;
1072 1094

	
1073 1095
      char c;
1074 1096
      while (readLine() && line >> c && c != '@') {
1075 1097
        line.putback(c);
1076 1098

	
1077 1099
        std::string attr, token;
1078 1100
        if (!_reader_bits::readToken(line, attr))
1079 1101
          throw FormatError("Attribute name not found");
1080 1102
        if (!_reader_bits::readToken(line, token))
1081 1103
          throw FormatError("Attribute value not found");
1082 1104
        if (line >> c)
1083 1105
          throw FormatError("Extra character at the end of line");
1084 1106

	
1085 1107
        {
1086 1108
          std::set<std::string>::iterator it = read_attr.find(attr);
1087 1109
          if (it != read_attr.end()) {
1088 1110
            std::ostringstream msg;
1089 1111
            msg << "Multiple occurence of attribute: " << attr;
1090 1112
            throw FormatError(msg.str());
1091 1113
          }
1092 1114
          read_attr.insert(attr);
1093 1115
        }
1094 1116

	
1095 1117
        {
1096 1118
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1097 1119
          while (it != _attributes.end() && it->first == attr) {
1098 1120
            it->second->set(token);
1099 1121
            ++it;
1100 1122
          }
1101 1123
        }
1102 1124

	
1103 1125
      }
1104 1126
      if (readSuccess()) {
1105 1127
        line.putback(c);
1106 1128
      }
1107 1129
      for (typename Attributes::iterator it = _attributes.begin();
1108 1130
           it != _attributes.end(); ++it) {
1109 1131
        if (read_attr.find(it->first) == read_attr.end()) {
1110 1132
          std::ostringstream msg;
1111 1133
          msg << "Attribute not found: " << it->first;
1112 1134
          throw FormatError(msg.str());
1113 1135
        }
1114 1136
      }
1115 1137
    }
1116 1138

	
1117 1139
  public:
1118 1140

	
1119 1141
    /// \name Execution of the reader
1120 1142
    /// @{
1121 1143

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

	
1128 1150
      bool nodes_done = _skip_nodes;
1129 1151
      bool arcs_done = _skip_arcs;
1130 1152
      bool attributes_done = false;
1131 1153

	
1132 1154
      line_num = 0;
1133 1155
      readLine();
1134 1156
      skipSection();
1135 1157

	
1136 1158
      while (readSuccess()) {
1137 1159
        try {
1138 1160
          char c;
1139 1161
          std::string section, caption;
1140 1162
          line >> c;
1141 1163
          _reader_bits::readToken(line, section);
1142 1164
          _reader_bits::readToken(line, caption);
1143 1165

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

	
1147 1169
          if (section == "nodes" && !nodes_done) {
1148 1170
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1149 1171
              readNodes();
1150 1172
              nodes_done = true;
1151 1173
            }
1152 1174
          } else if ((section == "arcs" || section == "edges") &&
1153 1175
                     !arcs_done) {
1154 1176
            if (_arcs_caption.empty() || _arcs_caption == caption) {
1155 1177
              readArcs();
1156 1178
              arcs_done = true;
1157 1179
            }
1158 1180
          } else if (section == "attributes" && !attributes_done) {
1159 1181
            if (_attributes_caption.empty() || _attributes_caption == caption) {
1160 1182
              readAttributes();
1161 1183
              attributes_done = true;
1162 1184
            }
1163 1185
          } else {
1164 1186
            readLine();
1165 1187
            skipSection();
1166 1188
          }
1167 1189
        } catch (FormatError& error) {
1168 1190
          error.line(line_num);
1169 1191
          error.file(_filename);
1170 1192
          throw;
1171 1193
        }
1172 1194
      }
1173 1195

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

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

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

	
1186 1208
    }
1187 1209

	
1188 1210
    /// @}
1189 1211

	
1190 1212
  };
1191 1213

	
1192
  /// \brief Return a \ref DigraphReader class
1214
  template <typename Graph>
1215
  class GraphReader;
1216

	
1217
  /// \brief Return a \ref GraphReader class
1193 1218
  ///
1194
  /// This function just returns a \ref DigraphReader class.
1195
  /// \relates DigraphReader
1196
  template <typename Digraph>
1197
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
1198
                                       std::istream& is = std::cin) {
1199
    DigraphReader<Digraph> tmp(digraph, is);
1219
  /// This function just returns a \ref GraphReader class.
1220
  /// \relates GraphReader
1221
  template <typename Graph>
1222
  GraphReader<Graph> graphReader(Graph& graph, std::istream& is = std::cin) {
1223
    GraphReader<Graph> tmp(graph, is);
1200 1224
    return tmp;
1201 1225
  }
1202 1226

	
1203
  /// \brief Return a \ref DigraphReader class
1227
  /// \brief Return a \ref GraphReader class
1204 1228
  ///
1205
  /// This function just returns a \ref DigraphReader class.
1206
  /// \relates DigraphReader
1207
  template <typename Digraph>
1208
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
1209
                                       const std::string& fn) {
1210
    DigraphReader<Digraph> tmp(digraph, fn);
1229
  /// This function just returns a \ref GraphReader class.
1230
  /// \relates GraphReader
1231
  template <typename Graph>
1232
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn) {
1233
    GraphReader<Graph> tmp(graph, fn);
1211 1234
    return tmp;
1212 1235
  }
1213 1236

	
1214
  /// \brief Return a \ref DigraphReader class
1237
  /// \brief Return a \ref GraphReader class
1215 1238
  ///
1216
  /// This function just returns a \ref DigraphReader class.
1217
  /// \relates DigraphReader
1218
  template <typename Digraph>
1219
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const char* fn) {
1220
    DigraphReader<Digraph> tmp(digraph, fn);
1239
  /// This function just returns a \ref GraphReader class.
1240
  /// \relates GraphReader
1241
  template <typename Graph>
1242
  GraphReader<Graph> graphReader(Graph& graph, const char* fn) {
1243
    GraphReader<Graph> tmp(graph, fn);
1221 1244
    return tmp;
1222 1245
  }
1223 1246

	
1224
  template <typename Graph>
1225
  class GraphReader;
1226

	
1227
  template <typename Graph>
1228
  GraphReader<Graph> graphReader(Graph& graph,
1229
                                 std::istream& is = std::cin);
1230

	
1231
  template <typename Graph>
1232
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn);
1233

	
1234
  template <typename Graph>
1235
  GraphReader<Graph> graphReader(Graph& graph, const char *fn);
1236

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

	
1256 1266
    typedef _Graph Graph;
1257 1267
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1258 1268

	
1259 1269
  private:
1260 1270

	
1261 1271
    std::istream* _is;
1262 1272
    bool local_is;
1263 1273
    std::string _filename;
1264 1274

	
1265 1275
    Graph& _graph;
1266 1276

	
1267 1277
    std::string _nodes_caption;
1268 1278
    std::string _edges_caption;
1269 1279
    std::string _attributes_caption;
1270 1280

	
1271 1281
    typedef std::map<std::string, Node> NodeIndex;
1272 1282
    NodeIndex _node_index;
1273 1283
    typedef std::map<std::string, Edge> EdgeIndex;
1274 1284
    EdgeIndex _edge_index;
1275 1285

	
1276 1286
    typedef std::vector<std::pair<std::string,
1277 1287
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
1278 1288
    NodeMaps _node_maps;
1279 1289

	
1280 1290
    typedef std::vector<std::pair<std::string,
1281 1291
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1282 1292
    EdgeMaps _edge_maps;
1283 1293

	
1284 1294
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1285 1295
      Attributes;
1286 1296
    Attributes _attributes;
1287 1297

	
1288 1298
    bool _use_nodes;
1289 1299
    bool _use_edges;
1290 1300

	
1291 1301
    bool _skip_nodes;
1292 1302
    bool _skip_edges;
1293 1303

	
1294 1304
    int line_num;
1295 1305
    std::istringstream line;
1296 1306

	
1297 1307
  public:
1298 1308

	
1299 1309
    /// \brief Constructor
1300 1310
    ///
1301 1311
    /// Construct an undirected graph reader, which reads from the given
1302 1312
    /// input stream.
1303 1313
    GraphReader(Graph& graph, std::istream& is = std::cin)
1304 1314
      : _is(&is), local_is(false), _graph(graph),
1305 1315
        _use_nodes(false), _use_edges(false),
1306 1316
        _skip_nodes(false), _skip_edges(false) {}
1307 1317

	
1308 1318
    /// \brief Constructor
1309 1319
    ///
1310 1320
    /// Construct an undirected graph reader, which reads from the given
1311 1321
    /// file.
1312 1322
    GraphReader(Graph& graph, const std::string& fn)
1313 1323
      : _is(new std::ifstream(fn.c_str())), local_is(true),
1314 1324
        _filename(fn), _graph(graph),
1315 1325
        _use_nodes(false), _use_edges(false),
1316 1326
        _skip_nodes(false), _skip_edges(false) {
1317 1327
      if (!(*_is)) {
1318 1328
        delete _is;
1319 1329
        throw IoError("Cannot open file", fn);
1320 1330
      }
1321 1331
    }
1322 1332

	
1323 1333
    /// \brief Constructor
1324 1334
    ///
1325 1335
    /// Construct an undirected graph reader, which reads from the given
1326 1336
    /// file.
1327 1337
    GraphReader(Graph& graph, const char* fn)
1328 1338
      : _is(new std::ifstream(fn)), local_is(true),
1329 1339
        _filename(fn), _graph(graph),
1330 1340
        _use_nodes(false), _use_edges(false),
1331 1341
        _skip_nodes(false), _skip_edges(false) {
1332 1342
      if (!(*_is)) {
1333 1343
        delete _is;
1334 1344
        throw IoError("Cannot open file", fn);
1335 1345
      }
1336 1346
    }
1337 1347

	
1338 1348
    /// \brief Destructor
1339 1349
    ~GraphReader() {
1340 1350
      for (typename NodeMaps::iterator it = _node_maps.begin();
1341 1351
           it != _node_maps.end(); ++it) {
1342 1352
        delete it->second;
1343 1353
      }
1344 1354

	
1345 1355
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1346 1356
           it != _edge_maps.end(); ++it) {
1347 1357
        delete it->second;
1348 1358
      }
1349 1359

	
1350 1360
      for (typename Attributes::iterator it = _attributes.begin();
1351 1361
           it != _attributes.end(); ++it) {
1352 1362
        delete it->second;
1353 1363
      }
1354 1364

	
1355 1365
      if (local_is) {
1356 1366
        delete _is;
1357 1367
      }
1358 1368

	
1359 1369
    }
1360 1370

	
1361 1371
  private:
1362 1372
    friend GraphReader<Graph> graphReader<>(Graph& graph, std::istream& is);
1363 1373
    friend GraphReader<Graph> graphReader<>(Graph& graph,
1364 1374
                                            const std::string& fn);
1365 1375
    friend GraphReader<Graph> graphReader<>(Graph& graph, const char *fn);
1366 1376

	
1367 1377
    GraphReader(GraphReader& other)
1368 1378
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1369 1379
        _use_nodes(other._use_nodes), _use_edges(other._use_edges),
1370 1380
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1371 1381

	
1372 1382
      other._is = 0;
1373 1383
      other.local_is = false;
1374 1384

	
1375 1385
      _node_index.swap(other._node_index);
1376 1386
      _edge_index.swap(other._edge_index);
1377 1387

	
1378 1388
      _node_maps.swap(other._node_maps);
1379 1389
      _edge_maps.swap(other._edge_maps);
1380 1390
      _attributes.swap(other._attributes);
1381 1391

	
1382 1392
      _nodes_caption = other._nodes_caption;
1383 1393
      _edges_caption = other._edges_caption;
1384 1394
      _attributes_caption = other._attributes_caption;
1385 1395

	
1386 1396
    }
1387 1397

	
1388 1398
    GraphReader& operator=(const GraphReader&);
1389 1399

	
1390 1400
  public:
1391 1401

	
1392 1402
    /// \name Reading rules
1393 1403
    /// @{
1394 1404

	
1395 1405
    /// \brief Node map reading rule
1396 1406
    ///
1397 1407
    /// Add a node map reading rule to the reader.
1398 1408
    template <typename Map>
1399 1409
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1400 1410
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1401 1411
      _reader_bits::MapStorageBase<Node>* storage =
1402 1412
        new _reader_bits::MapStorage<Node, Map>(map);
1403 1413
      _node_maps.push_back(std::make_pair(caption, storage));
1404 1414
      return *this;
1405 1415
    }
1406 1416

	
1407 1417
    /// \brief Node map reading rule
1408 1418
    ///
1409 1419
    /// Add a node map reading rule with specialized converter to the
1410 1420
    /// reader.
1411 1421
    template <typename Map, typename Converter>
1412 1422
    GraphReader& nodeMap(const std::string& caption, Map& map,
1413 1423
                           const Converter& converter = Converter()) {
1414 1424
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1415 1425
      _reader_bits::MapStorageBase<Node>* storage =
1416 1426
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1417 1427
      _node_maps.push_back(std::make_pair(caption, storage));
1418 1428
      return *this;
1419 1429
    }
1420 1430

	
1421 1431
    /// \brief Edge map reading rule
1422 1432
    ///
1423 1433
    /// Add an edge map reading rule to the reader.
1424 1434
    template <typename Map>
1425 1435
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1426 1436
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1427 1437
      _reader_bits::MapStorageBase<Edge>* storage =
1428 1438
        new _reader_bits::MapStorage<Edge, Map>(map);
1429 1439
      _edge_maps.push_back(std::make_pair(caption, storage));
1430 1440
      return *this;
1431 1441
    }
1432 1442

	
1433 1443
    /// \brief Edge map reading rule
1434 1444
    ///
1435 1445
    /// Add an edge map reading rule with specialized converter to the
1436 1446
    /// reader.
1437 1447
    template <typename Map, typename Converter>
1438 1448
    GraphReader& edgeMap(const std::string& caption, Map& map,
1439 1449
                          const Converter& converter = Converter()) {
1440 1450
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1441 1451
      _reader_bits::MapStorageBase<Edge>* storage =
1442 1452
        new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1443 1453
      _edge_maps.push_back(std::make_pair(caption, storage));
1444 1454
      return *this;
1445 1455
    }
1446 1456

	
1447 1457
    /// \brief Arc map reading rule
1448 1458
    ///
1449 1459
    /// Add an arc map reading rule to the reader.
1450 1460
    template <typename Map>
1451 1461
    GraphReader& arcMap(const std::string& caption, Map& map) {
1452 1462
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1453 1463
      _reader_bits::MapStorageBase<Edge>* forward_storage =
1454 1464
        new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1455 1465
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1456 1466
      _reader_bits::MapStorageBase<Edge>* backward_storage =
1457 1467
        new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1458 1468
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1459 1469
      return *this;
1460 1470
    }
1461 1471

	
1462 1472
    /// \brief Arc map reading rule
1463 1473
    ///
1464 1474
    /// Add an arc map reading rule with specialized converter to the
1465 1475
    /// reader.
1466 1476
    template <typename Map, typename Converter>
1467 1477
    GraphReader& arcMap(const std::string& caption, Map& map,
1468 1478
                          const Converter& converter = Converter()) {
1469 1479
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1470 1480
      _reader_bits::MapStorageBase<Edge>* forward_storage =
1471 1481
        new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1472 1482
        (_graph, map, converter);
1473 1483
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1474 1484
      _reader_bits::MapStorageBase<Edge>* backward_storage =
1475 1485
        new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1476 1486
        (_graph, map, converter);
1477 1487
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1478 1488
      return *this;
1479 1489
    }
1480 1490

	
1481 1491
    /// \brief Attribute reading rule
1482 1492
    ///
1483 1493
    /// Add an attribute reading rule to the reader.
1484 1494
    template <typename Value>
1485 1495
    GraphReader& attribute(const std::string& caption, Value& value) {
1486 1496
      _reader_bits::ValueStorageBase* storage =
1487 1497
        new _reader_bits::ValueStorage<Value>(value);
1488 1498
      _attributes.insert(std::make_pair(caption, storage));
1489 1499
      return *this;
1490 1500
    }
1491 1501

	
1492 1502
    /// \brief Attribute reading rule
1493 1503
    ///
1494 1504
    /// Add an attribute reading rule with specialized converter to the
1495 1505
    /// reader.
1496 1506
    template <typename Value, typename Converter>
1497 1507
    GraphReader& attribute(const std::string& caption, Value& value,
1498 1508
                             const Converter& converter = Converter()) {
1499 1509
      _reader_bits::ValueStorageBase* storage =
1500 1510
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1501 1511
      _attributes.insert(std::make_pair(caption, storage));
1502 1512
      return *this;
1503 1513
    }
1504 1514

	
1505 1515
    /// \brief Node reading rule
1506 1516
    ///
1507 1517
    /// Add a node reading rule to reader.
1508 1518
    GraphReader& node(const std::string& caption, Node& node) {
1509 1519
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1510 1520
      Converter converter(_node_index);
1511 1521
      _reader_bits::ValueStorageBase* storage =
1512 1522
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1513 1523
      _attributes.insert(std::make_pair(caption, storage));
1514 1524
      return *this;
1515 1525
    }
1516 1526

	
1517 1527
    /// \brief Edge reading rule
1518 1528
    ///
1519 1529
    /// Add an edge reading rule to reader.
1520 1530
    GraphReader& edge(const std::string& caption, Edge& edge) {
1521 1531
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1522 1532
      Converter converter(_edge_index);
1523 1533
      _reader_bits::ValueStorageBase* storage =
1524 1534
        new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1525 1535
      _attributes.insert(std::make_pair(caption, storage));
1526 1536
      return *this;
1527 1537
    }
1528 1538

	
1529 1539
    /// \brief Arc reading rule
1530 1540
    ///
1531 1541
    /// Add an arc reading rule to reader.
1532 1542
    GraphReader& arc(const std::string& caption, Arc& arc) {
1533 1543
      typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
1534 1544
      Converter converter(_graph, _edge_index);
1535 1545
      _reader_bits::ValueStorageBase* storage =
1536 1546
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1537 1547
      _attributes.insert(std::make_pair(caption, storage));
1538 1548
      return *this;
1539 1549
    }
1540 1550

	
1541 1551
    /// @}
1542 1552

	
1543 1553
    /// \name Select section by name
1544 1554
    /// @{
1545 1555

	
1546 1556
    /// \brief Set \c \@nodes section to be read
1547 1557
    ///
1548 1558
    /// Set \c \@nodes section to be read.
1549 1559
    GraphReader& nodes(const std::string& caption) {
1550 1560
      _nodes_caption = caption;
1551 1561
      return *this;
1552 1562
    }
1553 1563

	
1554 1564
    /// \brief Set \c \@edges section to be read
1555 1565
    ///
1556 1566
    /// Set \c \@edges section to be read.
1557 1567
    GraphReader& edges(const std::string& caption) {
1558 1568
      _edges_caption = caption;
1559 1569
      return *this;
1560 1570
    }
1561 1571

	
1562 1572
    /// \brief Set \c \@attributes section to be read
1563 1573
    ///
1564 1574
    /// Set \c \@attributes section to be read.
1565 1575
    GraphReader& attributes(const std::string& caption) {
1566 1576
      _attributes_caption = caption;
1567 1577
      return *this;
1568 1578
    }
1569 1579

	
1570 1580
    /// @}
1571 1581

	
1572 1582
    /// \name Using previously constructed node or edge set
1573 1583
    /// @{
1574 1584

	
1575 1585
    /// \brief Use previously constructed node set
1576 1586
    ///
1577 1587
    /// Use previously constructed node set, and specify the node
1578 1588
    /// label map.
1579 1589
    template <typename Map>
1580 1590
    GraphReader& useNodes(const Map& map) {
1581 1591
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1582 1592
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1583 1593
      _use_nodes = true;
1584 1594
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1585 1595
      for (NodeIt n(_graph); n != INVALID; ++n) {
1586 1596
        _node_index.insert(std::make_pair(converter(map[n]), n));
1587 1597
      }
1588 1598
      return *this;
1589 1599
    }
1590 1600

	
1591 1601
    /// \brief Use previously constructed node set
1592 1602
    ///
1593 1603
    /// Use previously constructed node set, and specify the node
1594 1604
    /// label map and a functor which converts the label map values to
1595 1605
    /// \c std::string.
1596 1606
    template <typename Map, typename Converter>
1597 1607
    GraphReader& useNodes(const Map& map,
1598 1608
                            const Converter& converter = Converter()) {
1599 1609
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1600 1610
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1601 1611
      _use_nodes = true;
1602 1612
      for (NodeIt n(_graph); n != INVALID; ++n) {
1603 1613
        _node_index.insert(std::make_pair(converter(map[n]), n));
1604 1614
      }
1605 1615
      return *this;
1606 1616
    }
1607 1617

	
1608 1618
    /// \brief Use previously constructed edge set
1609 1619
    ///
1610 1620
    /// Use previously constructed edge set, and specify the edge
1611 1621
    /// label map.
1612 1622
    template <typename Map>
1613 1623
    GraphReader& useEdges(const Map& map) {
1614 1624
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1615 1625
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1616 1626
      _use_edges = true;
1617 1627
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1618 1628
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1619 1629
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1620 1630
      }
... ...
@@ -1650,798 +1660,768 @@
1650 1660
    GraphReader& skipNodes() {
1651 1661
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
1652 1662
      _skip_nodes = true;
1653 1663
      return *this;
1654 1664
    }
1655 1665

	
1656 1666
    /// \brief Skip the reading of edge section
1657 1667
    ///
1658 1668
    /// Omit the reading of the edge section. This implies that each edge
1659 1669
    /// map reading rule will be abandoned, and the edges of the graph
1660 1670
    /// will not be constructed.
1661 1671
    GraphReader& skipEdges() {
1662 1672
      LEMON_ASSERT(!_skip_edges, "Skip edges already set");
1663 1673
      _skip_edges = true;
1664 1674
      return *this;
1665 1675
    }
1666 1676

	
1667 1677
    /// @}
1668 1678

	
1669 1679
  private:
1670 1680

	
1671 1681
    bool readLine() {
1672 1682
      std::string str;
1673 1683
      while(++line_num, std::getline(*_is, str)) {
1674 1684
        line.clear(); line.str(str);
1675 1685
        char c;
1676 1686
        if (line >> std::ws >> c && c != '#') {
1677 1687
          line.putback(c);
1678 1688
          return true;
1679 1689
        }
1680 1690
      }
1681 1691
      return false;
1682 1692
    }
1683 1693

	
1684 1694
    bool readSuccess() {
1685 1695
      return static_cast<bool>(*_is);
1686 1696
    }
1687 1697

	
1688 1698
    void skipSection() {
1689 1699
      char c;
1690 1700
      while (readSuccess() && line >> c && c != '@') {
1691 1701
        readLine();
1692 1702
      }
1693 1703
      line.putback(c);
1694 1704
    }
1695 1705

	
1696 1706
    void readNodes() {
1697 1707

	
1698 1708
      std::vector<int> map_index(_node_maps.size());
1699 1709
      int map_num, label_index;
1700 1710

	
1701 1711
      char c;
1702 1712
      if (!readLine() || !(line >> c) || c == '@') {
1703 1713
        if (readSuccess() && line) line.putback(c);
1704 1714
        if (!_node_maps.empty())
1705 1715
          throw FormatError("Cannot find map names");
1706 1716
        return;
1707 1717
      }
1708 1718
      line.putback(c);
1709 1719

	
1710 1720
      {
1711 1721
        std::map<std::string, int> maps;
1712 1722

	
1713 1723
        std::string map;
1714 1724
        int index = 0;
1715 1725
        while (_reader_bits::readToken(line, map)) {
1716 1726
          if (maps.find(map) != maps.end()) {
1717 1727
            std::ostringstream msg;
1718 1728
            msg << "Multiple occurence of node map: " << map;
1719 1729
            throw FormatError(msg.str());
1720 1730
          }
1721 1731
          maps.insert(std::make_pair(map, index));
1722 1732
          ++index;
1723 1733
        }
1724 1734

	
1725 1735
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1726 1736
          std::map<std::string, int>::iterator jt =
1727 1737
            maps.find(_node_maps[i].first);
1728 1738
          if (jt == maps.end()) {
1729 1739
            std::ostringstream msg;
1730 1740
            msg << "Map not found: " << _node_maps[i].first;
1731 1741
            throw FormatError(msg.str());
1732 1742
          }
1733 1743
          map_index[i] = jt->second;
1734 1744
        }
1735 1745

	
1736 1746
        {
1737 1747
          std::map<std::string, int>::iterator jt = maps.find("label");
1738 1748
          if (jt != maps.end()) {
1739 1749
            label_index = jt->second;
1740 1750
          } else {
1741 1751
            label_index = -1;
1742 1752
          }
1743 1753
        }
1744 1754
        map_num = maps.size();
1745 1755
      }
1746 1756

	
1747 1757
      while (readLine() && line >> c && c != '@') {
1748 1758
        line.putback(c);
1749 1759

	
1750 1760
        std::vector<std::string> tokens(map_num);
1751 1761
        for (int i = 0; i < map_num; ++i) {
1752 1762
          if (!_reader_bits::readToken(line, tokens[i])) {
1753 1763
            std::ostringstream msg;
1754 1764
            msg << "Column not found (" << i + 1 << ")";
1755 1765
            throw FormatError(msg.str());
1756 1766
          }
1757 1767
        }
1758 1768
        if (line >> std::ws >> c)
1759 1769
          throw FormatError("Extra character at the end of line");
1760 1770

	
1761 1771
        Node n;
1762 1772
        if (!_use_nodes) {
1763 1773
          n = _graph.addNode();
1764 1774
          if (label_index != -1)
1765 1775
            _node_index.insert(std::make_pair(tokens[label_index], n));
1766 1776
        } else {
1767 1777
          if (label_index == -1)
1768 1778
            throw FormatError("Label map not found");
1769 1779
          typename std::map<std::string, Node>::iterator it =
1770 1780
            _node_index.find(tokens[label_index]);
1771 1781
          if (it == _node_index.end()) {
1772 1782
            std::ostringstream msg;
1773 1783
            msg << "Node with label not found: " << tokens[label_index];
1774 1784
            throw FormatError(msg.str());
1775 1785
          }
1776 1786
          n = it->second;
1777 1787
        }
1778 1788

	
1779 1789
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1780 1790
          _node_maps[i].second->set(n, tokens[map_index[i]]);
1781 1791
        }
1782 1792

	
1783 1793
      }
1784 1794
      if (readSuccess()) {
1785 1795
        line.putback(c);
1786 1796
      }
1787 1797
    }
1788 1798

	
1789 1799
    void readEdges() {
1790 1800

	
1791 1801
      std::vector<int> map_index(_edge_maps.size());
1792 1802
      int map_num, label_index;
1793 1803

	
1794 1804
      char c;
1795 1805
      if (!readLine() || !(line >> c) || c == '@') {
1796 1806
        if (readSuccess() && line) line.putback(c);
1797 1807
        if (!_edge_maps.empty())
1798 1808
          throw FormatError("Cannot find map names");
1799 1809
        return;
1800 1810
      }
1801 1811
      line.putback(c);
1802 1812

	
1803 1813
      {
1804 1814
        std::map<std::string, int> maps;
1805 1815

	
1806 1816
        std::string map;
1807 1817
        int index = 0;
1808 1818
        while (_reader_bits::readToken(line, map)) {
1809 1819
          if (maps.find(map) != maps.end()) {
1810 1820
            std::ostringstream msg;
1811 1821
            msg << "Multiple occurence of edge map: " << map;
1812 1822
            throw FormatError(msg.str());
1813 1823
          }
1814 1824
          maps.insert(std::make_pair(map, index));
1815 1825
          ++index;
1816 1826
        }
1817 1827

	
1818 1828
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1819 1829
          std::map<std::string, int>::iterator jt =
1820 1830
            maps.find(_edge_maps[i].first);
1821 1831
          if (jt == maps.end()) {
1822 1832
            std::ostringstream msg;
1823 1833
            msg << "Map not found: " << _edge_maps[i].first;
1824 1834
            throw FormatError(msg.str());
1825 1835
          }
1826 1836
          map_index[i] = jt->second;
1827 1837
        }
1828 1838

	
1829 1839
        {
1830 1840
          std::map<std::string, int>::iterator jt = maps.find("label");
1831 1841
          if (jt != maps.end()) {
1832 1842
            label_index = jt->second;
1833 1843
          } else {
1834 1844
            label_index = -1;
1835 1845
          }
1836 1846
        }
1837 1847
        map_num = maps.size();
1838 1848
      }
1839 1849

	
1840 1850
      while (readLine() && line >> c && c != '@') {
1841 1851
        line.putback(c);
1842 1852

	
1843 1853
        std::string source_token;
1844 1854
        std::string target_token;
1845 1855

	
1846 1856
        if (!_reader_bits::readToken(line, source_token))
1847 1857
          throw FormatError("Node u not found");
1848 1858

	
1849 1859
        if (!_reader_bits::readToken(line, target_token))
1850 1860
          throw FormatError("Node v not found");
1851 1861

	
1852 1862
        std::vector<std::string> tokens(map_num);
1853 1863
        for (int i = 0; i < map_num; ++i) {
1854 1864
          if (!_reader_bits::readToken(line, tokens[i])) {
1855 1865
            std::ostringstream msg;
1856 1866
            msg << "Column not found (" << i + 1 << ")";
1857 1867
            throw FormatError(msg.str());
1858 1868
          }
1859 1869
        }
1860 1870
        if (line >> std::ws >> c)
1861 1871
          throw FormatError("Extra character at the end of line");
1862 1872

	
1863 1873
        Edge e;
1864 1874
        if (!_use_edges) {
1865 1875

	
1866 1876
          typename NodeIndex::iterator it;
1867 1877

	
1868 1878
          it = _node_index.find(source_token);
1869 1879
          if (it == _node_index.end()) {
1870 1880
            std::ostringstream msg;
1871 1881
            msg << "Item not found: " << source_token;
1872 1882
            throw FormatError(msg.str());
1873 1883
          }
1874 1884
          Node source = it->second;
1875 1885

	
1876 1886
          it = _node_index.find(target_token);
1877 1887
          if (it == _node_index.end()) {
1878 1888
            std::ostringstream msg;
1879 1889
            msg << "Item not found: " << target_token;
1880 1890
            throw FormatError(msg.str());
1881 1891
          }
1882 1892
          Node target = it->second;
1883 1893

	
1884 1894
          e = _graph.addEdge(source, target);
1885 1895
          if (label_index != -1)
1886 1896
            _edge_index.insert(std::make_pair(tokens[label_index], e));
1887 1897
        } else {
1888 1898
          if (label_index == -1)
1889 1899
            throw FormatError("Label map not found");
1890 1900
          typename std::map<std::string, Edge>::iterator it =
1891 1901
            _edge_index.find(tokens[label_index]);
1892 1902
          if (it == _edge_index.end()) {
1893 1903
            std::ostringstream msg;
1894 1904
            msg << "Edge with label not found: " << tokens[label_index];
1895 1905
            throw FormatError(msg.str());
1896 1906
          }
1897 1907
          e = it->second;
1898 1908
        }
1899 1909

	
1900 1910
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1901 1911
          _edge_maps[i].second->set(e, tokens[map_index[i]]);
1902 1912
        }
1903 1913

	
1904 1914
      }
1905 1915
      if (readSuccess()) {
1906 1916
        line.putback(c);
1907 1917
      }
1908 1918
    }
1909 1919

	
1910 1920
    void readAttributes() {
1911 1921

	
1912 1922
      std::set<std::string> read_attr;
1913 1923

	
1914 1924
      char c;
1915 1925
      while (readLine() && line >> c && c != '@') {
1916 1926
        line.putback(c);
1917 1927

	
1918 1928
        std::string attr, token;
1919 1929
        if (!_reader_bits::readToken(line, attr))
1920 1930
          throw FormatError("Attribute name not found");
1921 1931
        if (!_reader_bits::readToken(line, token))
1922 1932
          throw FormatError("Attribute value not found");
1923 1933
        if (line >> c)
1924 1934
          throw FormatError("Extra character at the end of line");
1925 1935

	
1926 1936
        {
1927 1937
          std::set<std::string>::iterator it = read_attr.find(attr);
1928 1938
          if (it != read_attr.end()) {
1929 1939
            std::ostringstream msg;
1930 1940
            msg << "Multiple occurence of attribute: " << attr;
1931 1941
            throw FormatError(msg.str());
1932 1942
          }
1933 1943
          read_attr.insert(attr);
1934 1944
        }
1935 1945

	
1936 1946
        {
1937 1947
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1938 1948
          while (it != _attributes.end() && it->first == attr) {
1939 1949
            it->second->set(token);
1940 1950
            ++it;
1941 1951
          }
1942 1952
        }
1943 1953

	
1944 1954
      }
1945 1955
      if (readSuccess()) {
1946 1956
        line.putback(c);
1947 1957
      }
1948 1958
      for (typename Attributes::iterator it = _attributes.begin();
1949 1959
           it != _attributes.end(); ++it) {
1950 1960
        if (read_attr.find(it->first) == read_attr.end()) {
1951 1961
          std::ostringstream msg;
1952 1962
          msg << "Attribute not found: " << it->first;
1953 1963
          throw FormatError(msg.str());
1954 1964
        }
1955 1965
      }
1956 1966
    }
1957 1967

	
1958 1968
  public:
1959 1969

	
1960 1970
    /// \name Execution of the reader
1961 1971
    /// @{
1962 1972

	
1963 1973
    /// \brief Start the batch processing
1964 1974
    ///
1965 1975
    /// This function starts the batch processing
1966 1976
    void run() {
1967 1977

	
1968 1978
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1969 1979

	
1970 1980
      bool nodes_done = _skip_nodes;
1971 1981
      bool edges_done = _skip_edges;
1972 1982
      bool attributes_done = false;
1973 1983

	
1974 1984
      line_num = 0;
1975 1985
      readLine();
1976 1986
      skipSection();
1977 1987

	
1978 1988
      while (readSuccess()) {
1979 1989
        try {
1980 1990
          char c;
1981 1991
          std::string section, caption;
1982 1992
          line >> c;
1983 1993
          _reader_bits::readToken(line, section);
1984 1994
          _reader_bits::readToken(line, caption);
1985 1995

	
1986 1996
          if (line >> c)
1987 1997
            throw FormatError("Extra character at the end of line");
1988 1998

	
1989 1999
          if (section == "nodes" && !nodes_done) {
1990 2000
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1991 2001
              readNodes();
1992 2002
              nodes_done = true;
1993 2003
            }
1994 2004
          } else if ((section == "edges" || section == "arcs") &&
1995 2005
                     !edges_done) {
1996 2006
            if (_edges_caption.empty() || _edges_caption == caption) {
1997 2007
              readEdges();
1998 2008
              edges_done = true;
1999 2009
            }
2000 2010
          } else if (section == "attributes" && !attributes_done) {
2001 2011
            if (_attributes_caption.empty() || _attributes_caption == caption) {
2002 2012
              readAttributes();
2003 2013
              attributes_done = true;
2004 2014
            }
2005 2015
          } else {
2006 2016
            readLine();
2007 2017
            skipSection();
2008 2018
          }
2009 2019
        } catch (FormatError& error) {
2010 2020
          error.line(line_num);
2011 2021
          error.file(_filename);
2012 2022
          throw;
2013 2023
        }
2014 2024
      }
2015 2025

	
2016 2026
      if (!nodes_done) {
2017 2027
        throw FormatError("Section @nodes not found");
2018 2028
      }
2019 2029

	
2020 2030
      if (!edges_done) {
2021 2031
        throw FormatError("Section @edges not found");
2022 2032
      }
2023 2033

	
2024 2034
      if (!attributes_done && !_attributes.empty()) {
2025 2035
        throw FormatError("Section @attributes not found");
2026 2036
      }
2027 2037

	
2028 2038
    }
2029 2039

	
2030 2040
    /// @}
2031 2041

	
2032 2042
  };
2033 2043

	
2034
  /// \brief Return a \ref GraphReader class
2035
  ///
2036
  /// This function just returns a \ref GraphReader class.
2037
  /// \relates GraphReader
2038
  template <typename Graph>
2039
  GraphReader<Graph> graphReader(Graph& graph, std::istream& is = std::cin) {
2040
    GraphReader<Graph> tmp(graph, is);
2041
    return tmp;
2042
  }
2043

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

	
2054
  /// \brief Return a \ref GraphReader class
2055
  ///
2056
  /// This function just returns a \ref GraphReader class.
2057
  /// \relates GraphReader
2058
  template <typename Graph>
2059
  GraphReader<Graph> graphReader(Graph& graph, const char* fn) {
2060
    GraphReader<Graph> tmp(graph, fn);
2061
    return tmp;
2062
  }
2063

	
2064 2044
  class SectionReader;
2065 2045

	
2066 2046
  SectionReader sectionReader(std::istream& is);
2067 2047
  SectionReader sectionReader(const std::string& fn);
2068 2048
  SectionReader sectionReader(const char* fn);
2069 2049

	
2070 2050
  /// \ingroup lemon_io
2071 2051
  ///
2072 2052
  /// \brief Section reader class
2073 2053
  ///
2074 2054
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
2075 2055
  /// which contain any data in arbitrary format. Such sections can be
2076 2056
  /// read with this class. A reading rule can be added to the class
2077 2057
  /// with two different functions. With the \c sectionLines() function a
2078 2058
  /// functor can process the section line-by-line, while with the \c
2079 2059
  /// sectionStream() member the section can be read from an input
2080 2060
  /// stream.
2081 2061
  class SectionReader {
2082 2062
  private:
2083 2063

	
2084 2064
    std::istream* _is;
2085 2065
    bool local_is;
2086 2066
    std::string _filename;
2087 2067

	
2088 2068
    typedef std::map<std::string, _reader_bits::Section*> Sections;
2089 2069
    Sections _sections;
2090 2070

	
2091 2071
    int line_num;
2092 2072
    std::istringstream line;
2093 2073

	
2094 2074
  public:
2095 2075

	
2096 2076
    /// \brief Constructor
2097 2077
    ///
2098 2078
    /// Construct a section reader, which reads from the given input
2099 2079
    /// stream.
2100 2080
    SectionReader(std::istream& is)
2101 2081
      : _is(&is), local_is(false) {}
2102 2082

	
2103 2083
    /// \brief Constructor
2104 2084
    ///
2105 2085
    /// Construct a section reader, which reads from the given file.
2106 2086
    SectionReader(const std::string& fn)
2107 2087
      : _is(new std::ifstream(fn.c_str())), local_is(true),
2108 2088
        _filename(fn) {
2109 2089
      if (!(*_is)) {
2110 2090
        delete _is;
2111 2091
        throw IoError("Cannot open file", fn);
2112 2092
      }
2113 2093
    }
2114 2094

	
2115 2095
    /// \brief Constructor
2116 2096
    ///
2117 2097
    /// Construct a section reader, which reads from the given file.
2118 2098
    SectionReader(const char* fn)
2119 2099
      : _is(new std::ifstream(fn)), local_is(true),
2120 2100
        _filename(fn) {
2121 2101
      if (!(*_is)) {
2122 2102
        delete _is;
2123 2103
        throw IoError("Cannot open file", fn);
2124 2104
      }
2125 2105
    }
2126 2106

	
2127 2107
    /// \brief Destructor
2128 2108
    ~SectionReader() {
2129 2109
      for (Sections::iterator it = _sections.begin();
2130 2110
           it != _sections.end(); ++it) {
2131 2111
        delete it->second;
2132 2112
      }
2133 2113

	
2134 2114
      if (local_is) {
2135 2115
        delete _is;
2136 2116
      }
2137 2117

	
2138 2118
    }
2139 2119

	
2140 2120
  private:
2141 2121

	
2142 2122
    friend SectionReader sectionReader(std::istream& is);
2143 2123
    friend SectionReader sectionReader(const std::string& fn);
2144 2124
    friend SectionReader sectionReader(const char* fn);
2145 2125

	
2146 2126
    SectionReader(SectionReader& other)
2147 2127
      : _is(other._is), local_is(other.local_is) {
2148 2128

	
2149 2129
      other._is = 0;
2150 2130
      other.local_is = false;
2151 2131

	
2152 2132
      _sections.swap(other._sections);
2153 2133
    }
2154 2134

	
2155 2135
    SectionReader& operator=(const SectionReader&);
2156 2136

	
2157 2137
  public:
2158 2138

	
2159 2139
    /// \name Section readers
2160 2140
    /// @{
2161 2141

	
2162 2142
    /// \brief Add a section processor with line oriented reading
2163 2143
    ///
2164 2144
    /// The first parameter is the type descriptor of the section, the
2165 2145
    /// second is a functor, which takes just one \c std::string
2166 2146
    /// parameter. At the reading process, each line of the section
2167 2147
    /// will be given to the functor object. However, the empty lines
2168 2148
    /// and the comment lines are filtered out, and the leading
2169 2149
    /// whitespaces are trimmed from each processed string.
2170 2150
    ///
2171 2151
    /// For example let's see a section, which contain several
2172 2152
    /// integers, which should be inserted into a vector.
2173 2153
    ///\code
2174 2154
    ///  @numbers
2175 2155
    ///  12 45 23
2176 2156
    ///  4
2177 2157
    ///  23 6
2178 2158
    ///\endcode
2179 2159
    ///
2180 2160
    /// The functor is implemented as a struct:
2181 2161
    ///\code
2182 2162
    ///  struct NumberSection {
2183 2163
    ///    std::vector<int>& _data;
2184 2164
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
2185 2165
    ///    void operator()(const std::string& line) {
2186 2166
    ///      std::istringstream ls(line);
2187 2167
    ///      int value;
2188 2168
    ///      while (ls >> value) _data.push_back(value);
2189 2169
    ///    }
2190 2170
    ///  };
2191 2171
    ///
2192 2172
    ///  // ...
2193 2173
    ///
2194 2174
    ///  reader.sectionLines("numbers", NumberSection(vec));
2195 2175
    ///\endcode
2196 2176
    template <typename Functor>
2197 2177
    SectionReader& sectionLines(const std::string& type, Functor functor) {
2198 2178
      LEMON_ASSERT(!type.empty(), "Type is empty.");
2199 2179
      LEMON_ASSERT(_sections.find(type) == _sections.end(),
2200 2180
                   "Multiple reading of section.");
2201 2181
      _sections.insert(std::make_pair(type,
2202 2182
        new _reader_bits::LineSection<Functor>(functor)));
2203 2183
      return *this;
2204 2184
    }
2205 2185

	
2206 2186

	
2207 2187
    /// \brief Add a section processor with stream oriented reading
2208 2188
    ///
2209 2189
    /// The first parameter is the type of the section, the second is
2210 2190
    /// a functor, which takes an \c std::istream& and an \c int&
2211 2191
    /// parameter, the latter regard to the line number of stream. The
2212 2192
    /// functor can read the input while the section go on, and the
2213 2193
    /// line number should be modified accordingly.
2214 2194
    template <typename Functor>
2215 2195
    SectionReader& sectionStream(const std::string& type, Functor functor) {
2216 2196
      LEMON_ASSERT(!type.empty(), "Type is empty.");
2217 2197
      LEMON_ASSERT(_sections.find(type) == _sections.end(),
2218 2198
                   "Multiple reading of section.");
2219 2199
      _sections.insert(std::make_pair(type,
2220 2200
         new _reader_bits::StreamSection<Functor>(functor)));
2221 2201
      return *this;
2222 2202
    }
2223 2203

	
2224 2204
    /// @}
2225 2205

	
2226 2206
  private:
2227 2207

	
2228 2208
    bool readLine() {
2229 2209
      std::string str;
2230 2210
      while(++line_num, std::getline(*_is, str)) {
2231 2211
        line.clear(); line.str(str);
2232 2212
        char c;
2233 2213
        if (line >> std::ws >> c && c != '#') {
2234 2214
          line.putback(c);
2235 2215
          return true;
2236 2216
        }
2237 2217
      }
2238 2218
      return false;
2239 2219
    }
2240 2220

	
2241 2221
    bool readSuccess() {
2242 2222
      return static_cast<bool>(*_is);
2243 2223
    }
2244 2224

	
2245 2225
    void skipSection() {
2246 2226
      char c;
2247 2227
      while (readSuccess() && line >> c && c != '@') {
2248 2228
        readLine();
2249 2229
      }
2250 2230
      line.putback(c);
2251 2231
    }
2252 2232

	
2253 2233
  public:
2254 2234

	
2255 2235

	
2256 2236
    /// \name Execution of the reader
2257 2237
    /// @{
2258 2238

	
2259 2239
    /// \brief Start the batch processing
2260 2240
    ///
2261 2241
    /// This function starts the batch processing.
2262 2242
    void run() {
2263 2243

	
2264 2244
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2265 2245

	
2266 2246
      std::set<std::string> extra_sections;
2267 2247

	
2268 2248
      line_num = 0;
2269 2249
      readLine();
2270 2250
      skipSection();
2271 2251

	
2272 2252
      while (readSuccess()) {
2273 2253
        try {
2274 2254
          char c;
2275 2255
          std::string section, caption;
2276 2256
          line >> c;
2277 2257
          _reader_bits::readToken(line, section);
2278 2258
          _reader_bits::readToken(line, caption);
2279 2259

	
2280 2260
          if (line >> c)
2281 2261
            throw FormatError("Extra character at the end of line");
2282 2262

	
2283 2263
          if (extra_sections.find(section) != extra_sections.end()) {
2284 2264
            std::ostringstream msg;
2285 2265
            msg << "Multiple occurence of section: " << section;
2286 2266
            throw FormatError(msg.str());
2287 2267
          }
2288 2268
          Sections::iterator it = _sections.find(section);
2289 2269
          if (it != _sections.end()) {
2290 2270
            extra_sections.insert(section);
2291 2271
            it->second->process(*_is, line_num);
2292 2272
          }
2293 2273
          readLine();
2294 2274
          skipSection();
2295 2275
        } catch (FormatError& error) {
2296 2276
          error.line(line_num);
2297 2277
          error.file(_filename);
2298 2278
          throw;
2299 2279
        }
2300 2280
      }
2301 2281
      for (Sections::iterator it = _sections.begin();
2302 2282
           it != _sections.end(); ++it) {
2303 2283
        if (extra_sections.find(it->first) == extra_sections.end()) {
2304 2284
          std::ostringstream os;
2305 2285
          os << "Cannot find section: " << it->first;
2306 2286
          throw FormatError(os.str());
2307 2287
        }
2308 2288
      }
2309 2289
    }
2310 2290

	
2311 2291
    /// @}
2312 2292

	
2313 2293
  };
2314 2294

	
2315 2295
  /// \brief Return a \ref SectionReader class
2316 2296
  ///
2317 2297
  /// This function just returns a \ref SectionReader class.
2318 2298
  /// \relates SectionReader
2319 2299
  inline SectionReader sectionReader(std::istream& is) {
2320 2300
    SectionReader tmp(is);
2321 2301
    return tmp;
2322 2302
  }
2323 2303

	
2324 2304
  /// \brief Return a \ref SectionReader class
2325 2305
  ///
2326 2306
  /// This function just returns a \ref SectionReader class.
2327 2307
  /// \relates SectionReader
2328 2308
  inline SectionReader sectionReader(const std::string& fn) {
2329 2309
    SectionReader tmp(fn);
2330 2310
    return tmp;
2331 2311
  }
2332 2312

	
2333 2313
  /// \brief Return a \ref SectionReader class
2334 2314
  ///
2335 2315
  /// This function just returns a \ref SectionReader class.
2336 2316
  /// \relates SectionReader
2337 2317
  inline SectionReader sectionReader(const char* fn) {
2338 2318
    SectionReader tmp(fn);
2339 2319
    return tmp;
2340 2320
  }
2341 2321

	
2342 2322
  /// \ingroup lemon_io
2343 2323
  ///
2344 2324
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file
2345 2325
  ///
2346 2326
  /// This class can be used to read the sections, the map names and
2347 2327
  /// the attributes from a file. Usually, the LEMON programs know
2348 2328
  /// that, which type of graph, which maps and which attributes
2349 2329
  /// should be read from a file, but in general tools (like glemon)
2350 2330
  /// the contents of an LGF file should be guessed somehow. This class
2351 2331
  /// reads the graph and stores the appropriate information for
2352 2332
  /// reading the graph.
2353 2333
  ///
2354 2334
  ///\code
2355 2335
  /// LgfContents contents("graph.lgf");
2356 2336
  /// contents.run();
2357 2337
  ///
2358 2338
  /// // Does it contain any node section and arc section?
2359 2339
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
2360 2340
  ///   std::cerr << "Failure, cannot find graph." << std::endl;
2361 2341
  ///   return -1;
2362 2342
  /// }
2363 2343
  /// std::cout << "The name of the default node section: "
2364 2344
  ///           << contents.nodeSection(0) << std::endl;
2365 2345
  /// std::cout << "The number of the arc maps: "
2366 2346
  ///           << contents.arcMaps(0).size() << std::endl;
2367 2347
  /// std::cout << "The name of second arc map: "
2368 2348
  ///           << contents.arcMaps(0)[1] << std::endl;
2369 2349
  ///\endcode
2370 2350
  class LgfContents {
2371 2351
  private:
2372 2352

	
2373 2353
    std::istream* _is;
2374 2354
    bool local_is;
2375 2355

	
2376 2356
    std::vector<std::string> _node_sections;
2377 2357
    std::vector<std::string> _edge_sections;
2378 2358
    std::vector<std::string> _attribute_sections;
2379 2359
    std::vector<std::string> _extra_sections;
2380 2360

	
2381 2361
    std::vector<bool> _arc_sections;
2382 2362

	
2383 2363
    std::vector<std::vector<std::string> > _node_maps;
2384 2364
    std::vector<std::vector<std::string> > _edge_maps;
2385 2365

	
2386 2366
    std::vector<std::vector<std::string> > _attributes;
2387 2367

	
2388 2368

	
2389 2369
    int line_num;
2390 2370
    std::istringstream line;
2391 2371

	
2392 2372
  public:
2393 2373

	
2394 2374
    /// \brief Constructor
2395 2375
    ///
2396 2376
    /// Construct an \e LGF contents reader, which reads from the given
2397 2377
    /// input stream.
2398 2378
    LgfContents(std::istream& is)
2399 2379
      : _is(&is), local_is(false) {}
2400 2380

	
2401 2381
    /// \brief Constructor
2402 2382
    ///
2403 2383
    /// Construct an \e LGF contents reader, which reads from the given
2404 2384
    /// file.
2405 2385
    LgfContents(const std::string& fn)
2406 2386
      : _is(new std::ifstream(fn.c_str())), local_is(true) {
2407 2387
      if (!(*_is)) {
2408 2388
        delete _is;
2409 2389
        throw IoError("Cannot open file", fn);
2410 2390
      }
2411 2391
    }
2412 2392

	
2413 2393
    /// \brief Constructor
2414 2394
    ///
2415 2395
    /// Construct an \e LGF contents reader, which reads from the given
2416 2396
    /// file.
2417 2397
    LgfContents(const char* fn)
2418 2398
      : _is(new std::ifstream(fn)), local_is(true) {
2419 2399
      if (!(*_is)) {
2420 2400
        delete _is;
2421 2401
        throw IoError("Cannot open file", fn);
2422 2402
      }
2423 2403
    }
2424 2404

	
2425 2405
    /// \brief Destructor
2426 2406
    ~LgfContents() {
2427 2407
      if (local_is) delete _is;
2428 2408
    }
2429 2409

	
2430 2410
  private:
2431 2411

	
2432 2412
    LgfContents(const LgfContents&);
2433 2413
    LgfContents& operator=(const LgfContents&);
2434 2414

	
2435 2415
  public:
2436 2416

	
2437 2417

	
2438 2418
    /// \name Node sections
2439 2419
    /// @{
2440 2420

	
2441 2421
    /// \brief Gives back the number of node sections in the file.
2442 2422
    ///
2443 2423
    /// Gives back the number of node sections in the file.
2444 2424
    int nodeSectionNum() const {
2445 2425
      return _node_sections.size();
2446 2426
    }
2447 2427

	
Ignore white space 768 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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" writer.
22 22

	
23 23

	
24 24
#ifndef LEMON_LGF_WRITER_H
25 25
#define LEMON_LGF_WRITER_H
26 26

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

	
31 31
#include <algorithm>
32 32

	
33 33
#include <vector>
34 34
#include <functional>
35 35

	
36 36
#include <lemon/assert.h>
37 37
#include <lemon/core.h>
38 38
#include <lemon/maps.h>
39 39

	
40 40
#include <lemon/concept_check.h>
41 41
#include <lemon/concepts/maps.h>
42 42

	
43 43
namespace lemon {
44 44

	
45 45
  namespace _writer_bits {
46 46

	
47 47
    template <typename Value>
48 48
    struct DefaultConverter {
49 49
      std::string operator()(const Value& value) {
50 50
        std::ostringstream os;
51 51
        os << value;
52 52
        return os.str();
53 53
      }
54 54
    };
55 55

	
56 56
    template <typename T>
57 57
    bool operator<(const T&, const T&) {
58 58
      throw FormatError("Label map is not comparable");
59 59
    }
60 60

	
61 61
    template <typename _Map>
62 62
    class MapLess {
63 63
    public:
64 64
      typedef _Map Map;
65 65
      typedef typename Map::Key Item;
66 66

	
67 67
    private:
68 68
      const Map& _map;
69 69

	
70 70
    public:
71 71
      MapLess(const Map& map) : _map(map) {}
72 72

	
73 73
      bool operator()(const Item& left, const Item& right) {
74 74
        return _map[left] < _map[right];
75 75
      }
76 76
    };
77 77

	
78 78
    template <typename _Graph, bool _dir, typename _Map>
79 79
    class GraphArcMapLess {
80 80
    public:
81 81
      typedef _Map Map;
82 82
      typedef _Graph Graph;
83 83
      typedef typename Graph::Edge Item;
84 84

	
85 85
    private:
86 86
      const Graph& _graph;
87 87
      const Map& _map;
88 88

	
89 89
    public:
90 90
      GraphArcMapLess(const Graph& graph, const Map& map)
91 91
        : _graph(graph), _map(map) {}
92 92

	
93 93
      bool operator()(const Item& left, const Item& right) {
94 94
        return _map[_graph.direct(left, _dir)] <
95 95
          _map[_graph.direct(right, _dir)];
96 96
      }
97 97
    };
98 98

	
99 99
    template <typename _Item>
100 100
    class MapStorageBase {
101 101
    public:
102 102
      typedef _Item Item;
103 103

	
104 104
    public:
105 105
      MapStorageBase() {}
106 106
      virtual ~MapStorageBase() {}
107 107

	
108 108
      virtual std::string get(const Item& item) = 0;
109 109
      virtual void sort(std::vector<Item>&) = 0;
110 110
    };
111 111

	
112 112
    template <typename _Item, typename _Map,
113 113
              typename _Converter = DefaultConverter<typename _Map::Value> >
114 114
    class MapStorage : public MapStorageBase<_Item> {
115 115
    public:
116 116
      typedef _Map Map;
117 117
      typedef _Converter Converter;
118 118
      typedef _Item Item;
119 119

	
120 120
    private:
121 121
      const Map& _map;
122 122
      Converter _converter;
123 123

	
124 124
    public:
125 125
      MapStorage(const Map& map, const Converter& converter = Converter())
126 126
        : _map(map), _converter(converter) {}
127 127
      virtual ~MapStorage() {}
128 128

	
129 129
      virtual std::string get(const Item& item) {
130 130
        return _converter(_map[item]);
131 131
      }
132 132
      virtual void sort(std::vector<Item>& items) {
133 133
        MapLess<Map> less(_map);
134 134
        std::sort(items.begin(), items.end(), less);
135 135
      }
136 136
    };
137 137

	
138 138
    template <typename _Graph, bool _dir, typename _Map,
139 139
              typename _Converter = DefaultConverter<typename _Map::Value> >
140 140
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
141 141
    public:
142 142
      typedef _Map Map;
143 143
      typedef _Converter Converter;
144 144
      typedef _Graph Graph;
145 145
      typedef typename Graph::Edge Item;
146 146
      static const bool dir = _dir;
147 147

	
148 148
    private:
149 149
      const Graph& _graph;
150 150
      const Map& _map;
151 151
      Converter _converter;
152 152

	
153 153
    public:
154 154
      GraphArcMapStorage(const Graph& graph, const Map& map,
155 155
                         const Converter& converter = Converter())
156 156
        : _graph(graph), _map(map), _converter(converter) {}
157 157
      virtual ~GraphArcMapStorage() {}
158 158

	
159 159
      virtual std::string get(const Item& item) {
160 160
        return _converter(_map[_graph.direct(item, dir)]);
161 161
      }
162 162
      virtual void sort(std::vector<Item>& items) {
163 163
        GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
164 164
        std::sort(items.begin(), items.end(), less);
165 165
      }
166 166
    };
167 167

	
168 168
    class ValueStorageBase {
169 169
    public:
170 170
      ValueStorageBase() {}
171 171
      virtual ~ValueStorageBase() {}
172 172

	
173 173
      virtual std::string get() = 0;
174 174
    };
175 175

	
176 176
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
177 177
    class ValueStorage : public ValueStorageBase {
178 178
    public:
179 179
      typedef _Value Value;
180 180
      typedef _Converter Converter;
181 181

	
182 182
    private:
183 183
      const Value& _value;
184 184
      Converter _converter;
185 185

	
186 186
    public:
187 187
      ValueStorage(const Value& value, const Converter& converter = Converter())
188 188
        : _value(value), _converter(converter) {}
189 189

	
190 190
      virtual std::string get() {
191 191
        return _converter(_value);
192 192
      }
193 193
    };
194 194

	
195 195
    template <typename Value>
196 196
    struct MapLookUpConverter {
197 197
      const std::map<Value, std::string>& _map;
198 198

	
199 199
      MapLookUpConverter(const std::map<Value, std::string>& map)
200 200
        : _map(map) {}
201 201

	
202 202
      std::string operator()(const Value& str) {
203 203
        typename std::map<Value, std::string>::const_iterator it =
204 204
          _map.find(str);
205 205
        if (it == _map.end()) {
206 206
          throw FormatError("Item not found");
207 207
        }
208 208
        return it->second;
209 209
      }
210 210
    };
211 211

	
212 212
    template <typename Graph>
213 213
    struct GraphArcLookUpConverter {
214 214
      const Graph& _graph;
215 215
      const std::map<typename Graph::Edge, std::string>& _map;
216 216

	
217 217
      GraphArcLookUpConverter(const Graph& graph,
218 218
                              const std::map<typename Graph::Edge,
219 219
                                             std::string>& map)
220 220
        : _graph(graph), _map(map) {}
221 221

	
222 222
      std::string operator()(const typename Graph::Arc& val) {
223 223
        typename std::map<typename Graph::Edge, std::string>
224 224
          ::const_iterator it = _map.find(val);
225 225
        if (it == _map.end()) {
226 226
          throw FormatError("Item not found");
227 227
        }
228 228
        return (_graph.direction(val) ? '+' : '-') + it->second;
229 229
      }
230 230
    };
231 231

	
232 232
    inline bool isWhiteSpace(char c) {
233 233
      return c == ' ' || c == '\t' || c == '\v' ||
234 234
        c == '\n' || c == '\r' || c == '\f';
235 235
    }
236 236

	
237 237
    inline bool isEscaped(char c) {
238 238
      return c == '\\' || c == '\"' || c == '\'' ||
239 239
        c == '\a' || c == '\b';
240 240
    }
241 241

	
242 242
    inline static void writeEscape(std::ostream& os, char c) {
243 243
      switch (c) {
244 244
      case '\\':
245 245
        os << "\\\\";
246 246
        return;
247 247
      case '\"':
248 248
        os << "\\\"";
249 249
        return;
250 250
      case '\a':
251 251
        os << "\\a";
252 252
        return;
253 253
      case '\b':
254 254
        os << "\\b";
255 255
        return;
256 256
      case '\f':
257 257
        os << "\\f";
258 258
        return;
259 259
      case '\r':
260 260
        os << "\\r";
261 261
        return;
262 262
      case '\n':
263 263
        os << "\\n";
264 264
        return;
265 265
      case '\t':
266 266
        os << "\\t";
267 267
        return;
268 268
      case '\v':
269 269
        os << "\\v";
270 270
        return;
271 271
      default:
272 272
        if (c < 0x20) {
273 273
          std::ios::fmtflags flags = os.flags();
274 274
          os << '\\' << std::oct << static_cast<int>(c);
275 275
          os.flags(flags);
276 276
        } else {
277 277
          os << c;
278 278
        }
279 279
        return;
280 280
      }
281 281
    }
282 282

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

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

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

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

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

	
320 320
      Functor _functor;
321 321

	
322 322
    public:
323 323

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

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

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

	
337 337
      Functor _functor;
338 338

	
339 339
    public:
340 340

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

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

	
349 349
  }
350 350

	
351 351
  template <typename Digraph>
352 352
  class DigraphWriter;
353 353

	
354
  /// \brief Return a \ref DigraphWriter class
355
  ///
356
  /// This function just returns a \ref DigraphWriter class.
357
  /// \relates DigraphWriter
354 358
  template <typename Digraph>
355 359
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
356
                                       std::ostream& os = std::cout);
360
                                       std::ostream& os = std::cout) {
361
    DigraphWriter<Digraph> tmp(digraph, os);
362
    return tmp;
363
  }
357 364

	
365
  /// \brief Return a \ref DigraphWriter class
366
  ///
367
  /// This function just returns a \ref DigraphWriter class.
368
  /// \relates DigraphWriter
358 369
  template <typename Digraph>
359 370
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
360
                                       const std::string& fn);
371
                                       const std::string& fn) {
372
    DigraphWriter<Digraph> tmp(digraph, fn);
373
    return tmp;
374
  }
361 375

	
376
  /// \brief Return a \ref DigraphWriter class
377
  ///
378
  /// This function just returns a \ref DigraphWriter class.
379
  /// \relates DigraphWriter
362 380
  template <typename Digraph>
363 381
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
364
                                       const char *fn);
382
                                       const char* fn) {
383
    DigraphWriter<Digraph> tmp(digraph, fn);
384
    return tmp;
385
  }
365 386

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

	
414 435
    typedef _Digraph Digraph;
415 436
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
416 437

	
417 438
  private:
418 439

	
419 440

	
420 441
    std::ostream* _os;
421 442
    bool local_os;
422 443

	
423 444
    const Digraph& _digraph;
424 445

	
425 446
    std::string _nodes_caption;
426 447
    std::string _arcs_caption;
427 448
    std::string _attributes_caption;
428 449

	
429 450
    typedef std::map<Node, std::string> NodeIndex;
430 451
    NodeIndex _node_index;
431 452
    typedef std::map<Arc, std::string> ArcIndex;
432 453
    ArcIndex _arc_index;
433 454

	
434 455
    typedef std::vector<std::pair<std::string,
435 456
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
436 457
    NodeMaps _node_maps;
437 458

	
438 459
    typedef std::vector<std::pair<std::string,
439 460
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
440 461
    ArcMaps _arc_maps;
441 462

	
442 463
    typedef std::vector<std::pair<std::string,
443 464
      _writer_bits::ValueStorageBase*> > Attributes;
444 465
    Attributes _attributes;
445 466

	
446 467
    bool _skip_nodes;
447 468
    bool _skip_arcs;
448 469

	
449 470
  public:
450 471

	
451 472
    /// \brief Constructor
452 473
    ///
453 474
    /// Construct a directed graph writer, which writes to the given
454 475
    /// output stream.
455 476
    DigraphWriter(const Digraph& digraph, std::ostream& os = std::cout)
456 477
      : _os(&os), local_os(false), _digraph(digraph),
457 478
        _skip_nodes(false), _skip_arcs(false) {}
458 479

	
459 480
    /// \brief Constructor
460 481
    ///
461 482
    /// Construct a directed graph writer, which writes to the given
462 483
    /// output file.
463 484
    DigraphWriter(const Digraph& digraph, const std::string& fn)
464 485
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
465 486
        _skip_nodes(false), _skip_arcs(false) {
466 487
      if (!(*_os)) {
467 488
        delete _os;
468 489
        throw IoError("Cannot write file", fn);
469 490
      }
470 491
    }
471 492

	
472 493
    /// \brief Constructor
473 494
    ///
474 495
    /// Construct a directed graph writer, which writes to the given
475 496
    /// output file.
476 497
    DigraphWriter(const Digraph& digraph, const char* fn)
477 498
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
478 499
        _skip_nodes(false), _skip_arcs(false) {
479 500
      if (!(*_os)) {
480 501
        delete _os;
481 502
        throw IoError("Cannot write file", fn);
482 503
      }
483 504
    }
484 505

	
485 506
    /// \brief Destructor
486 507
    ~DigraphWriter() {
487 508
      for (typename NodeMaps::iterator it = _node_maps.begin();
488 509
           it != _node_maps.end(); ++it) {
489 510
        delete it->second;
490 511
      }
491 512

	
492 513
      for (typename ArcMaps::iterator it = _arc_maps.begin();
493 514
           it != _arc_maps.end(); ++it) {
494 515
        delete it->second;
495 516
      }
496 517

	
497 518
      for (typename Attributes::iterator it = _attributes.begin();
498 519
           it != _attributes.end(); ++it) {
499 520
        delete it->second;
500 521
      }
501 522

	
502 523
      if (local_os) {
503 524
        delete _os;
504 525
      }
505 526
    }
506 527

	
507 528
  private:
508 529

	
509 530
    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
510 531
                                                  std::ostream& os);
511 532
    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
512 533
                                                  const std::string& fn);
513 534
    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
514 535
                                                  const char *fn);
515 536

	
516 537
    DigraphWriter(DigraphWriter& other)
517 538
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
518 539
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
519 540

	
520 541
      other._os = 0;
521 542
      other.local_os = false;
522 543

	
523 544
      _node_index.swap(other._node_index);
524 545
      _arc_index.swap(other._arc_index);
525 546

	
526 547
      _node_maps.swap(other._node_maps);
527 548
      _arc_maps.swap(other._arc_maps);
528 549
      _attributes.swap(other._attributes);
529 550

	
530 551
      _nodes_caption = other._nodes_caption;
531 552
      _arcs_caption = other._arcs_caption;
532 553
      _attributes_caption = other._attributes_caption;
533 554
    }
534 555

	
535 556
    DigraphWriter& operator=(const DigraphWriter&);
536 557

	
537 558
  public:
538 559

	
539 560
    /// \name Writing rules
540 561
    /// @{
541 562

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

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

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

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

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

	
605 626
    /// \brief Attribute writing rule
606 627
    ///
607 628
    /// Add an attribute writing rule with specialized converter to the
608 629
    /// writer.
609 630
    template <typename Value, typename Converter>
610 631
    DigraphWriter& attribute(const std::string& caption, const Value& value,
611 632
                             const Converter& converter = Converter()) {
612 633
      _writer_bits::ValueStorageBase* storage =
613 634
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
614 635
      _attributes.push_back(std::make_pair(caption, storage));
615 636
      return *this;
616 637
    }
617 638

	
618 639
    /// \brief Node writing rule
619 640
    ///
620 641
    /// Add a node writing rule to the writer.
621 642
    DigraphWriter& node(const std::string& caption, const Node& node) {
622 643
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
623 644
      Converter converter(_node_index);
624 645
      _writer_bits::ValueStorageBase* storage =
625 646
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
626 647
      _attributes.push_back(std::make_pair(caption, storage));
627 648
      return *this;
628 649
    }
629 650

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

	
642 663
    /// \name Section captions
643 664
    /// @{
644 665

	
645 666
    /// \brief Add an additional caption to the \c \@nodes section
646 667
    ///
647 668
    /// Add an additional caption to the \c \@nodes section.
648 669
    DigraphWriter& nodes(const std::string& caption) {
649 670
      _nodes_caption = caption;
650 671
      return *this;
651 672
    }
652 673

	
653 674
    /// \brief Add an additional caption to the \c \@arcs section
654 675
    ///
655 676
    /// Add an additional caption to the \c \@arcs section.
656 677
    DigraphWriter& arcs(const std::string& caption) {
657 678
      _arcs_caption = caption;
658 679
      return *this;
659 680
    }
660 681

	
661 682
    /// \brief Add an additional caption to the \c \@attributes section
662 683
    ///
663 684
    /// Add an additional caption to the \c \@attributes section.
664 685
    DigraphWriter& attributes(const std::string& caption) {
665 686
      _attributes_caption = caption;
666 687
      return *this;
667 688
    }
668 689

	
669 690
    /// \name Skipping section
670 691
    /// @{
671 692

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

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

	
690 711
    /// @}
691 712

	
692 713
  private:
693 714

	
694 715
    void writeNodes() {
695 716
      _writer_bits::MapStorageBase<Node>* label = 0;
696 717
      for (typename NodeMaps::iterator it = _node_maps.begin();
697 718
           it != _node_maps.end(); ++it) {
698 719
        if (it->first == "label") {
699 720
          label = it->second;
700 721
          break;
701 722
        }
702 723
      }
703 724

	
704 725
      *_os << "@nodes";
705 726
      if (!_nodes_caption.empty()) {
706 727
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
707 728
      }
708 729
      *_os << std::endl;
709 730

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

	
719 740
      std::vector<Node> nodes;
720 741
      for (NodeIt n(_digraph); n != INVALID; ++n) {
721 742
        nodes.push_back(n);
722 743
      }
723 744

	
724 745
      if (label == 0) {
725 746
        IdMap<Digraph, Node> id_map(_digraph);
726 747
        _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
727 748
        std::sort(nodes.begin(), nodes.end(), id_less);
728 749
      } else {
729 750
        label->sort(nodes);
730 751
      }
731 752

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

	
754 775
    void createNodeIndex() {
755 776
      _writer_bits::MapStorageBase<Node>* label = 0;
756 777
      for (typename NodeMaps::iterator it = _node_maps.begin();
757 778
           it != _node_maps.end(); ++it) {
758 779
        if (it->first == "label") {
759 780
          label = it->second;
760 781
          break;
761 782
        }
762 783
      }
763 784

	
764 785
      if (label == 0) {
765 786
        for (NodeIt n(_digraph); n != INVALID; ++n) {
766 787
          std::ostringstream os;
767 788
          os << _digraph.id(n);
768 789
          _node_index.insert(std::make_pair(n, os.str()));
769 790
        }
770 791
      } else {
771 792
        for (NodeIt n(_digraph); n != INVALID; ++n) {
772 793
          std::string value = label->get(n);
773 794
          _node_index.insert(std::make_pair(n, value));
774 795
        }
775 796
      }
776 797
    }
777 798

	
778 799
    void writeArcs() {
779 800
      _writer_bits::MapStorageBase<Arc>* label = 0;
780 801
      for (typename ArcMaps::iterator it = _arc_maps.begin();
781 802
           it != _arc_maps.end(); ++it) {
782 803
        if (it->first == "label") {
783 804
          label = it->second;
784 805
          break;
785 806
        }
786 807
      }
787 808

	
788 809
      *_os << "@arcs";
789 810
      if (!_arcs_caption.empty()) {
790 811
        _writer_bits::writeToken(*_os << ' ', _arcs_caption);
791 812
      }
792 813
      *_os << std::endl;
793 814

	
794 815
      *_os << '\t' << '\t';
795 816
      if (label == 0) {
796 817
        *_os << "label" << '\t';
797 818
      }
798 819
      for (typename ArcMaps::iterator it = _arc_maps.begin();
799 820
           it != _arc_maps.end(); ++it) {
800 821
        _writer_bits::writeToken(*_os, it->first) << '\t';
801 822
      }
802 823
      *_os << std::endl;
803 824

	
804 825
      std::vector<Arc> arcs;
805 826
      for (ArcIt n(_digraph); n != INVALID; ++n) {
806 827
        arcs.push_back(n);
807 828
      }
808 829

	
809 830
      if (label == 0) {
810 831
        IdMap<Digraph, Arc> id_map(_digraph);
811 832
        _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
812 833
        std::sort(arcs.begin(), arcs.end(), id_less);
813 834
      } else {
814 835
        label->sort(arcs);
815 836
      }
816 837

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

	
845 866
    void createArcIndex() {
846 867
      _writer_bits::MapStorageBase<Arc>* label = 0;
847 868
      for (typename ArcMaps::iterator it = _arc_maps.begin();
848 869
           it != _arc_maps.end(); ++it) {
849 870
        if (it->first == "label") {
850 871
          label = it->second;
851 872
          break;
852 873
        }
853 874
      }
854 875

	
855 876
      if (label == 0) {
856 877
        for (ArcIt a(_digraph); a != INVALID; ++a) {
857 878
          std::ostringstream os;
858 879
          os << _digraph.id(a);
859 880
          _arc_index.insert(std::make_pair(a, os.str()));
860 881
        }
861 882
      } else {
862 883
        for (ArcIt a(_digraph); a != INVALID; ++a) {
863 884
          std::string value = label->get(a);
864 885
          _arc_index.insert(std::make_pair(a, value));
865 886
        }
866 887
      }
867 888
    }
868 889

	
869 890
    void writeAttributes() {
870 891
      if (_attributes.empty()) return;
871 892
      *_os << "@attributes";
872 893
      if (!_attributes_caption.empty()) {
873 894
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
874 895
      }
875 896
      *_os << std::endl;
876 897
      for (typename Attributes::iterator it = _attributes.begin();
877 898
           it != _attributes.end(); ++it) {
878 899
        _writer_bits::writeToken(*_os, it->first) << ' ';
879 900
        _writer_bits::writeToken(*_os, it->second->get());
880 901
        *_os << std::endl;
881 902
      }
882 903
    }
883 904

	
884 905
  public:
885 906

	
886 907
    /// \name Execution of the writer
887 908
    /// @{
888 909

	
889 910
    /// \brief Start the batch processing
890 911
    ///
891 912
    /// This function starts the batch processing.
892 913
    void run() {
893 914
      if (!_skip_nodes) {
894 915
        writeNodes();
895 916
      } else {
896 917
        createNodeIndex();
897 918
      }
898 919
      if (!_skip_arcs) {
899 920
        writeArcs();
900 921
      } else {
901 922
        createArcIndex();
902 923
      }
903 924
      writeAttributes();
904 925
    }
905 926

	
906 927
    /// \brief Give back the stream of the writer
907 928
    ///
908 929
    /// Give back the stream of the writer.
909 930
    std::ostream& ostream() {
910 931
      return *_os;
911 932
    }
912 933

	
913 934
    /// @}
914 935
  };
915 936

	
916
  /// \brief Return a \ref DigraphWriter class
937
  template <typename Graph>
938
  class GraphWriter;
939

	
940
  /// \brief Return a \ref GraphWriter class
917 941
  ///
918
  /// This function just returns a \ref DigraphWriter class.
919
  /// \relates DigraphWriter
920
  template <typename Digraph>
921
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
922
                                       std::ostream& os = std::cout) {
923
    DigraphWriter<Digraph> tmp(digraph, os);
942
  /// This function just returns a \ref GraphWriter class.
943
  /// \relates GraphWriter
944
  template <typename Graph>
945
  GraphWriter<Graph> graphWriter(const Graph& graph,
946
                                 std::ostream& os = std::cout) {
947
    GraphWriter<Graph> tmp(graph, os);
924 948
    return tmp;
925 949
  }
926 950

	
927
  /// \brief Return a \ref DigraphWriter class
951
  /// \brief Return a \ref GraphWriter class
928 952
  ///
929
  /// This function just returns a \ref DigraphWriter class.
930
  /// \relates DigraphWriter
931
  template <typename Digraph>
932
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
933
                                       const std::string& fn) {
934
    DigraphWriter<Digraph> tmp(digraph, fn);
953
  /// This function just returns a \ref GraphWriter class.
954
  /// \relates GraphWriter
955
  template <typename Graph>
956
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
957
    GraphWriter<Graph> tmp(graph, fn);
935 958
    return tmp;
936 959
  }
937 960

	
938
  /// \brief Return a \ref DigraphWriter class
961
  /// \brief Return a \ref GraphWriter class
939 962
  ///
940
  /// This function just returns a \ref DigraphWriter class.
941
  /// \relates DigraphWriter
942
  template <typename Digraph>
943
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
944
                                       const char* fn) {
945
    DigraphWriter<Digraph> tmp(digraph, fn);
963
  /// This function just returns a \ref GraphWriter class.
964
  /// \relates GraphWriter
965
  template <typename Graph>
966
  GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
967
    GraphWriter<Graph> tmp(graph, fn);
946 968
    return tmp;
947 969
  }
948 970

	
949
  template <typename Graph>
950
  class GraphWriter;
951

	
952
  template <typename Graph>
953
  GraphWriter<Graph> graphWriter(const Graph& graph,
954
                                 std::ostream& os = std::cout);
955

	
956
  template <typename Graph>
957
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn);
958

	
959
  template <typename Graph>
960
  GraphWriter<Graph> graphWriter(const Graph& graph, const char *fn);
961

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

	
981 990
    typedef _Graph Graph;
982 991
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
983 992

	
984 993
  private:
985 994

	
986 995

	
987 996
    std::ostream* _os;
988 997
    bool local_os;
989 998

	
990 999
    const Graph& _graph;
991 1000

	
992 1001
    std::string _nodes_caption;
993 1002
    std::string _edges_caption;
994 1003
    std::string _attributes_caption;
995 1004

	
996 1005
    typedef std::map<Node, std::string> NodeIndex;
997 1006
    NodeIndex _node_index;
998 1007
    typedef std::map<Edge, std::string> EdgeIndex;
999 1008
    EdgeIndex _edge_index;
1000 1009

	
1001 1010
    typedef std::vector<std::pair<std::string,
1002 1011
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
1003 1012
    NodeMaps _node_maps;
1004 1013

	
1005 1014
    typedef std::vector<std::pair<std::string,
1006 1015
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1007 1016
    EdgeMaps _edge_maps;
1008 1017

	
1009 1018
    typedef std::vector<std::pair<std::string,
1010 1019
      _writer_bits::ValueStorageBase*> > Attributes;
1011 1020
    Attributes _attributes;
1012 1021

	
1013 1022
    bool _skip_nodes;
1014 1023
    bool _skip_edges;
1015 1024

	
1016 1025
  public:
1017 1026

	
1018 1027
    /// \brief Constructor
1019 1028
    ///
1020 1029
    /// Construct a directed graph writer, which writes to the given
1021 1030
    /// output stream.
1022 1031
    GraphWriter(const Graph& graph, std::ostream& os = std::cout)
1023 1032
      : _os(&os), local_os(false), _graph(graph),
1024 1033
        _skip_nodes(false), _skip_edges(false) {}
1025 1034

	
1026 1035
    /// \brief Constructor
1027 1036
    ///
1028 1037
    /// Construct a directed graph writer, which writes to the given
1029 1038
    /// output file.
1030 1039
    GraphWriter(const Graph& graph, const std::string& fn)
1031 1040
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1032 1041
        _skip_nodes(false), _skip_edges(false) {
1033 1042
      if (!(*_os)) {
1034 1043
        delete _os;
1035 1044
        throw IoError("Cannot write file", fn);
1036 1045
      }
1037 1046
    }
1038 1047

	
1039 1048
    /// \brief Constructor
1040 1049
    ///
1041 1050
    /// Construct a directed graph writer, which writes to the given
1042 1051
    /// output file.
1043 1052
    GraphWriter(const Graph& graph, const char* fn)
1044 1053
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1045 1054
        _skip_nodes(false), _skip_edges(false) {
1046 1055
      if (!(*_os)) {
1047 1056
        delete _os;
1048 1057
        throw IoError("Cannot write file", fn);
1049 1058
      }
1050 1059
    }
1051 1060

	
1052 1061
    /// \brief Destructor
1053 1062
    ~GraphWriter() {
1054 1063
      for (typename NodeMaps::iterator it = _node_maps.begin();
1055 1064
           it != _node_maps.end(); ++it) {
1056 1065
        delete it->second;
1057 1066
      }
1058 1067

	
1059 1068
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1060 1069
           it != _edge_maps.end(); ++it) {
1061 1070
        delete it->second;
1062 1071
      }
1063 1072

	
1064 1073
      for (typename Attributes::iterator it = _attributes.begin();
1065 1074
           it != _attributes.end(); ++it) {
1066 1075
        delete it->second;
1067 1076
      }
1068 1077

	
1069 1078
      if (local_os) {
1070 1079
        delete _os;
1071 1080
      }
1072 1081
    }
1073 1082

	
1074 1083
  private:
1075 1084

	
1076 1085
    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1077 1086
                                            std::ostream& os);
1078 1087
    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1079 1088
                                            const std::string& fn);
1080 1089
    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1081 1090
                                            const char *fn);
1082 1091

	
1083 1092
    GraphWriter(GraphWriter& other)
1084 1093
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
1085 1094
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1086 1095

	
1087 1096
      other._os = 0;
1088 1097
      other.local_os = false;
1089 1098

	
1090 1099
      _node_index.swap(other._node_index);
1091 1100
      _edge_index.swap(other._edge_index);
1092 1101

	
1093 1102
      _node_maps.swap(other._node_maps);
1094 1103
      _edge_maps.swap(other._edge_maps);
1095 1104
      _attributes.swap(other._attributes);
1096 1105

	
1097 1106
      _nodes_caption = other._nodes_caption;
1098 1107
      _edges_caption = other._edges_caption;
1099 1108
      _attributes_caption = other._attributes_caption;
1100 1109
    }
1101 1110

	
1102 1111
    GraphWriter& operator=(const GraphWriter&);
1103 1112

	
1104 1113
  public:
1105 1114

	
1106 1115
    /// \name Writing rules
1107 1116
    /// @{
1108 1117

	
1109 1118
    /// \brief Node map writing rule
1110 1119
    ///
1111 1120
    /// Add a node map writing rule to the writer.
1112 1121
    template <typename Map>
1113 1122
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1114 1123
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1115 1124
      _writer_bits::MapStorageBase<Node>* storage =
1116 1125
        new _writer_bits::MapStorage<Node, Map>(map);
1117 1126
      _node_maps.push_back(std::make_pair(caption, storage));
1118 1127
      return *this;
1119 1128
    }
1120 1129

	
1121 1130
    /// \brief Node map writing rule
1122 1131
    ///
1123 1132
    /// Add a node map writing rule with specialized converter to the
1124 1133
    /// writer.
1125 1134
    template <typename Map, typename Converter>
1126 1135
    GraphWriter& nodeMap(const std::string& caption, const Map& map,
1127 1136
                           const Converter& converter = Converter()) {
1128 1137
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1129 1138
      _writer_bits::MapStorageBase<Node>* storage =
1130 1139
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1131 1140
      _node_maps.push_back(std::make_pair(caption, storage));
1132 1141
      return *this;
1133 1142
    }
1134 1143

	
1135 1144
    /// \brief Edge map writing rule
1136 1145
    ///
1137 1146
    /// Add an edge map writing rule to the writer.
1138 1147
    template <typename Map>
1139 1148
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1140 1149
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1141 1150
      _writer_bits::MapStorageBase<Edge>* storage =
1142 1151
        new _writer_bits::MapStorage<Edge, Map>(map);
1143 1152
      _edge_maps.push_back(std::make_pair(caption, storage));
1144 1153
      return *this;
1145 1154
    }
1146 1155

	
1147 1156
    /// \brief Edge map writing rule
1148 1157
    ///
1149 1158
    /// Add an edge map writing rule with specialized converter to the
1150 1159
    /// writer.
1151 1160
    template <typename Map, typename Converter>
1152 1161
    GraphWriter& edgeMap(const std::string& caption, const Map& map,
1153 1162
                          const Converter& converter = Converter()) {
1154 1163
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1155 1164
      _writer_bits::MapStorageBase<Edge>* storage =
1156 1165
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1157 1166
      _edge_maps.push_back(std::make_pair(caption, storage));
1158 1167
      return *this;
1159 1168
    }
1160 1169

	
1161 1170
    /// \brief Arc map writing rule
1162 1171
    ///
1163 1172
    /// Add an arc map writing rule to the writer.
1164 1173
    template <typename Map>
1165 1174
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
1166 1175
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1167 1176
      _writer_bits::MapStorageBase<Edge>* forward_storage =
1168 1177
        new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1169 1178
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1170 1179
      _writer_bits::MapStorageBase<Edge>* backward_storage =
1171 1180
        new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1172 1181
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1173 1182
      return *this;
1174 1183
    }
1175 1184

	
1176 1185
    /// \brief Arc map writing rule
1177 1186
    ///
1178 1187
    /// Add an arc map writing rule with specialized converter to the
1179 1188
    /// writer.
1180 1189
    template <typename Map, typename Converter>
1181 1190
    GraphWriter& arcMap(const std::string& caption, const Map& map,
1182 1191
                          const Converter& converter = Converter()) {
1183 1192
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1184 1193
      _writer_bits::MapStorageBase<Edge>* forward_storage =
1185 1194
        new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1186 1195
        (_graph, map, converter);
1187 1196
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1188 1197
      _writer_bits::MapStorageBase<Edge>* backward_storage =
1189 1198
        new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1190 1199
        (_graph, map, converter);
1191 1200
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1192 1201
      return *this;
1193 1202
    }
1194 1203

	
1195 1204
    /// \brief Attribute writing rule
1196 1205
    ///
1197 1206
    /// Add an attribute writing rule to the writer.
1198 1207
    template <typename Value>
1199 1208
    GraphWriter& attribute(const std::string& caption, const Value& value) {
1200 1209
      _writer_bits::ValueStorageBase* storage =
1201 1210
        new _writer_bits::ValueStorage<Value>(value);
1202 1211
      _attributes.push_back(std::make_pair(caption, storage));
1203 1212
      return *this;
1204 1213
    }
1205 1214

	
1206 1215
    /// \brief Attribute writing rule
1207 1216
    ///
1208 1217
    /// Add an attribute writing rule with specialized converter to the
1209 1218
    /// writer.
1210 1219
    template <typename Value, typename Converter>
1211 1220
    GraphWriter& attribute(const std::string& caption, const Value& value,
1212 1221
                             const Converter& converter = Converter()) {
1213 1222
      _writer_bits::ValueStorageBase* storage =
1214 1223
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1215 1224
      _attributes.push_back(std::make_pair(caption, storage));
1216 1225
      return *this;
1217 1226
    }
1218 1227

	
1219 1228
    /// \brief Node writing rule
1220 1229
    ///
1221 1230
    /// Add a node writing rule to the writer.
1222 1231
    GraphWriter& node(const std::string& caption, const Node& node) {
1223 1232
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
1224 1233
      Converter converter(_node_index);
1225 1234
      _writer_bits::ValueStorageBase* storage =
1226 1235
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1227 1236
      _attributes.push_back(std::make_pair(caption, storage));
1228 1237
      return *this;
1229 1238
    }
1230 1239

	
1231 1240
    /// \brief Edge writing rule
1232 1241
    ///
1233 1242
    /// Add an edge writing rule to writer.
1234 1243
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
1235 1244
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1236 1245
      Converter converter(_edge_index);
1237 1246
      _writer_bits::ValueStorageBase* storage =
1238 1247
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1239 1248
      _attributes.push_back(std::make_pair(caption, storage));
1240 1249
      return *this;
1241 1250
    }
1242 1251

	
1243 1252
    /// \brief Arc writing rule
1244 1253
    ///
1245 1254
    /// Add an arc writing rule to writer.
1246 1255
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
1247 1256
      typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1248 1257
      Converter converter(_graph, _edge_index);
1249 1258
      _writer_bits::ValueStorageBase* storage =
1250 1259
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1251 1260
      _attributes.push_back(std::make_pair(caption, storage));
1252 1261
      return *this;
1253 1262
    }
1254 1263

	
1255 1264
    /// \name Section captions
1256 1265
    /// @{
1257 1266

	
1258 1267
    /// \brief Add an additional caption to the \c \@nodes section
1259 1268
    ///
1260 1269
    /// Add an additional caption to the \c \@nodes section.
1261 1270
    GraphWriter& nodes(const std::string& caption) {
1262 1271
      _nodes_caption = caption;
1263 1272
      return *this;
1264 1273
    }
1265 1274

	
1266 1275
    /// \brief Add an additional caption to the \c \@arcs section
1267 1276
    ///
1268 1277
    /// Add an additional caption to the \c \@arcs section.
1269 1278
    GraphWriter& edges(const std::string& caption) {
1270 1279
      _edges_caption = caption;
1271 1280
      return *this;
1272 1281
    }
1273 1282

	
1274 1283
    /// \brief Add an additional caption to the \c \@attributes section
1275 1284
    ///
1276 1285
    /// Add an additional caption to the \c \@attributes section.
1277 1286
    GraphWriter& attributes(const std::string& caption) {
1278 1287
      _attributes_caption = caption;
1279 1288
      return *this;
1280 1289
    }
1281 1290

	
1282 1291
    /// \name Skipping section
1283 1292
    /// @{
1284 1293

	
1285 1294
    /// \brief Skip writing the node set
1286 1295
    ///
1287 1296
    /// The \c \@nodes section will not be written to the stream.
1288 1297
    GraphWriter& skipNodes() {
1289 1298
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1290 1299
      _skip_nodes = true;
1291 1300
      return *this;
1292 1301
    }
1293 1302

	
1294 1303
    /// \brief Skip writing edge set
1295 1304
    ///
1296 1305
    /// The \c \@edges section will not be written to the stream.
1297 1306
    GraphWriter& skipEdges() {
1298 1307
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1299 1308
      _skip_edges = true;
1300 1309
      return *this;
1301 1310
    }
1302 1311

	
1303 1312
    /// @}
1304 1313

	
1305 1314
  private:
1306 1315

	
1307 1316
    void writeNodes() {
1308 1317
      _writer_bits::MapStorageBase<Node>* label = 0;
1309 1318
      for (typename NodeMaps::iterator it = _node_maps.begin();
1310 1319
           it != _node_maps.end(); ++it) {
1311 1320
        if (it->first == "label") {
1312 1321
          label = it->second;
1313 1322
          break;
1314 1323
        }
1315 1324
      }
1316 1325

	
1317 1326
      *_os << "@nodes";
1318 1327
      if (!_nodes_caption.empty()) {
1319 1328
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1320 1329
      }
1321 1330
      *_os << std::endl;
1322 1331

	
1323 1332
      if (label == 0) {
1324 1333
        *_os << "label" << '\t';
1325 1334
      }
1326 1335
      for (typename NodeMaps::iterator it = _node_maps.begin();
1327 1336
           it != _node_maps.end(); ++it) {
1328 1337
        _writer_bits::writeToken(*_os, it->first) << '\t';
1329 1338
      }
1330 1339
      *_os << std::endl;
1331 1340

	
1332 1341
      std::vector<Node> nodes;
1333 1342
      for (NodeIt n(_graph); n != INVALID; ++n) {
1334 1343
        nodes.push_back(n);
1335 1344
      }
1336 1345

	
1337 1346
      if (label == 0) {
1338 1347
        IdMap<Graph, Node> id_map(_graph);
1339 1348
        _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1340 1349
        std::sort(nodes.begin(), nodes.end(), id_less);
1341 1350
      } else {
1342 1351
        label->sort(nodes);
1343 1352
      }
1344 1353

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

	
1367 1376
    void createNodeIndex() {
1368 1377
      _writer_bits::MapStorageBase<Node>* label = 0;
1369 1378
      for (typename NodeMaps::iterator it = _node_maps.begin();
1370 1379
           it != _node_maps.end(); ++it) {
1371 1380
        if (it->first == "label") {
1372 1381
          label = it->second;
1373 1382
          break;
1374 1383
        }
1375 1384
      }
1376 1385

	
1377 1386
      if (label == 0) {
1378 1387
        for (NodeIt n(_graph); n != INVALID; ++n) {
1379 1388
          std::ostringstream os;
1380 1389
          os << _graph.id(n);
1381 1390
          _node_index.insert(std::make_pair(n, os.str()));
1382 1391
        }
1383 1392
      } else {
1384 1393
        for (NodeIt n(_graph); n != INVALID; ++n) {
1385 1394
          std::string value = label->get(n);
1386 1395
          _node_index.insert(std::make_pair(n, value));
1387 1396
        }
1388 1397
      }
1389 1398
    }
1390 1399

	
1391 1400
    void writeEdges() {
1392 1401
      _writer_bits::MapStorageBase<Edge>* label = 0;
1393 1402
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1394 1403
           it != _edge_maps.end(); ++it) {
1395 1404
        if (it->first == "label") {
1396 1405
          label = it->second;
1397 1406
          break;
1398 1407
        }
1399 1408
      }
1400 1409

	
1401 1410
      *_os << "@edges";
1402 1411
      if (!_edges_caption.empty()) {
1403 1412
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
1404 1413
      }
1405 1414
      *_os << std::endl;
1406 1415

	
1407 1416
      *_os << '\t' << '\t';
1408 1417
      if (label == 0) {
1409 1418
        *_os << "label" << '\t';
1410 1419
      }
1411 1420
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1412 1421
           it != _edge_maps.end(); ++it) {
1413 1422
        _writer_bits::writeToken(*_os, it->first) << '\t';
1414 1423
      }
1415 1424
      *_os << std::endl;
1416 1425

	
1417 1426
      std::vector<Edge> edges;
1418 1427
      for (EdgeIt n(_graph); n != INVALID; ++n) {
1419 1428
        edges.push_back(n);
1420 1429
      }
1421 1430

	
1422 1431
      if (label == 0) {
1423 1432
        IdMap<Graph, Edge> id_map(_graph);
1424 1433
        _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1425 1434
        std::sort(edges.begin(), edges.end(), id_less);
1426 1435
      } else {
1427 1436
        label->sort(edges);
1428 1437
      }
1429 1438

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

	
1458 1467
    void createEdgeIndex() {
1459 1468
      _writer_bits::MapStorageBase<Edge>* label = 0;
1460 1469
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1461 1470
           it != _edge_maps.end(); ++it) {
1462 1471
        if (it->first == "label") {
1463 1472
          label = it->second;
1464 1473
          break;
1465 1474
        }
1466 1475
      }
1467 1476

	
1468 1477
      if (label == 0) {
1469 1478
        for (EdgeIt e(_graph); e != INVALID; ++e) {
1470 1479
          std::ostringstream os;
1471 1480
          os << _graph.id(e);
1472 1481
          _edge_index.insert(std::make_pair(e, os.str()));
1473 1482
        }
1474 1483
      } else {
1475 1484
        for (EdgeIt e(_graph); e != INVALID; ++e) {
1476 1485
          std::string value = label->get(e);
1477 1486
          _edge_index.insert(std::make_pair(e, value));
1478 1487
        }
1479 1488
      }
1480 1489
    }
1481 1490

	
1482 1491
    void writeAttributes() {
1483 1492
      if (_attributes.empty()) return;
1484 1493
      *_os << "@attributes";
1485 1494
      if (!_attributes_caption.empty()) {
1486 1495
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1487 1496
      }
1488 1497
      *_os << std::endl;
1489 1498
      for (typename Attributes::iterator it = _attributes.begin();
1490 1499
           it != _attributes.end(); ++it) {
1491 1500
        _writer_bits::writeToken(*_os, it->first) << ' ';
1492 1501
        _writer_bits::writeToken(*_os, it->second->get());
1493 1502
        *_os << std::endl;
1494 1503
      }
1495 1504
    }
1496 1505

	
1497 1506
  public:
1498 1507

	
1499 1508
    /// \name Execution of the writer
1500 1509
    /// @{
1501 1510

	
1502 1511
    /// \brief Start the batch processing
1503 1512
    ///
1504 1513
    /// This function starts the batch processing.
1505 1514
    void run() {
1506 1515
      if (!_skip_nodes) {
1507 1516
        writeNodes();
1508 1517
      } else {
1509 1518
        createNodeIndex();
1510 1519
      }
1511 1520
      if (!_skip_edges) {
1512 1521
        writeEdges();
1513 1522
      } else {
1514 1523
        createEdgeIndex();
1515 1524
      }
1516 1525
      writeAttributes();
1517 1526
    }
1518 1527

	
1519 1528
    /// \brief Give back the stream of the writer
1520 1529
    ///
1521 1530
    /// Give back the stream of the writer
1522 1531
    std::ostream& ostream() {
1523 1532
      return *_os;
1524 1533
    }
1525 1534

	
1526 1535
    /// @}
1527 1536
  };
1528 1537

	
1529
  /// \brief Return a \ref GraphWriter class
1530
  ///
1531
  /// This function just returns a \ref GraphWriter class.
1532
  /// \relates GraphWriter
1533
  template <typename Graph>
1534
  GraphWriter<Graph> graphWriter(const Graph& graph,
1535
                                 std::ostream& os = std::cout) {
1536
    GraphWriter<Graph> tmp(graph, os);
1537
    return tmp;
1538
  }
1539

	
1540
  /// \brief Return a \ref GraphWriter class
1541
  ///
1542
  /// This function just returns a \ref GraphWriter class.
1543
  /// \relates GraphWriter
1544
  template <typename Graph>
1545
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
1546
    GraphWriter<Graph> tmp(graph, fn);
1547
    return tmp;
1548
  }
1549

	
1550
  /// \brief Return a \ref GraphWriter class
1551
  ///
1552
  /// This function just returns a \ref GraphWriter class.
1553
  /// \relates GraphWriter
1554
  template <typename Graph>
1555
  GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
1556
    GraphWriter<Graph> tmp(graph, fn);
1557
    return tmp;
1558
  }
1559

	
1560 1538
  class SectionWriter;
1561 1539

	
1562 1540
  SectionWriter sectionWriter(std::istream& is);
1563 1541
  SectionWriter sectionWriter(const std::string& fn);
1564 1542
  SectionWriter sectionWriter(const char* fn);
1565 1543

	
1566 1544
  /// \ingroup lemon_io
1567 1545
  ///
1568 1546
  /// \brief Section writer class
1569 1547
  ///
1570 1548
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
1571 1549
  /// which contain any data in arbitrary format. Such sections can be
1572 1550
  /// written with this class. A writing rule can be added to the
1573 1551
  /// class with two different functions. With the \c sectionLines()
1574 1552
  /// function a generator can write the section line-by-line, while
1575 1553
  /// with the \c sectionStream() member the section can be written to
1576 1554
  /// an output stream.
1577 1555
  class SectionWriter {
1578 1556
  private:
1579 1557

	
1580 1558
    std::ostream* _os;
1581 1559
    bool local_os;
1582 1560

	
1583 1561
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1584 1562
    Sections;
1585 1563

	
1586 1564
    Sections _sections;
1587 1565

	
1588 1566
  public:
1589 1567

	
1590 1568
    /// \brief Constructor
1591 1569
    ///
1592 1570
    /// Construct a section writer, which writes to the given output
1593 1571
    /// stream.
1594 1572
    SectionWriter(std::ostream& os)
1595 1573
      : _os(&os), local_os(false) {}
1596 1574

	
1597 1575
    /// \brief Constructor
1598 1576
    ///
1599 1577
    /// Construct a section writer, which writes into the given file.
1600 1578
    SectionWriter(const std::string& fn)
1601 1579
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
1602 1580
      if (!(*_os)) {
1603 1581
        delete _os;
1604 1582
        throw IoError("Cannot write file", fn);
1605 1583
      }
1606 1584
    }
1607 1585

	
1608 1586
    /// \brief Constructor
1609 1587
    ///
1610 1588
    /// Construct a section writer, which writes into the given file.
1611 1589
    SectionWriter(const char* fn)
1612 1590
      : _os(new std::ofstream(fn)), local_os(true) {
1613 1591
      if (!(*_os)) {
1614 1592
        delete _os;
1615 1593
        throw IoError("Cannot write file", fn);
1616 1594
      }
1617 1595
    }
1618 1596

	
1619 1597
    /// \brief Destructor
1620 1598
    ~SectionWriter() {
1621 1599
      for (Sections::iterator it = _sections.begin();
1622 1600
           it != _sections.end(); ++it) {
1623 1601
        delete it->second;
1624 1602
      }
1625 1603

	
1626 1604
      if (local_os) {
1627 1605
        delete _os;
1628 1606
      }
1629 1607

	
1630 1608
    }
1631 1609

	
1632 1610
  private:
1633 1611

	
1634 1612
    friend SectionWriter sectionWriter(std::ostream& os);
1635 1613
    friend SectionWriter sectionWriter(const std::string& fn);
1636 1614
    friend SectionWriter sectionWriter(const char* fn);
1637 1615

	
1638 1616
    SectionWriter(SectionWriter& other)
1639 1617
      : _os(other._os), local_os(other.local_os) {
1640 1618

	
1641 1619
      other._os = 0;
1642 1620
      other.local_os = false;
1643 1621

	
1644 1622
      _sections.swap(other._sections);
1645 1623
    }
1646 1624

	
1647 1625
    SectionWriter& operator=(const SectionWriter&);
1648 1626

	
1649 1627
  public:
1650 1628

	
1651 1629
    /// \name Section writers
1652 1630
    /// @{
1653 1631

	
1654 1632
    /// \brief Add a section writer with line oriented writing
1655 1633
    ///
1656 1634
    /// The first parameter is the type descriptor of the section, the
1657 1635
    /// second is a generator with std::string values. At the writing
1658 1636
    /// process, the returned \c std::string will be written into the
1659 1637
    /// output file until it is an empty string.
1660 1638
    ///
1661 1639
    /// For example, an integer vector is written into a section.
1662 1640
    ///\code
1663 1641
    ///  @numbers
1664 1642
    ///  12 45 23 78
1665 1643
    ///  4 28 38 28
1666 1644
    ///  23 6 16
1667 1645
    ///\endcode
1668 1646
    ///
1669 1647
    /// The generator is implemented as a struct.
1670 1648
    ///\code
1671 1649
    ///  struct NumberSection {
1672 1650
    ///    std::vector<int>::const_iterator _it, _end;
1673 1651
    ///    NumberSection(const std::vector<int>& data)
1674 1652
    ///      : _it(data.begin()), _end(data.end()) {}
1675 1653
    ///    std::string operator()() {
1676 1654
    ///      int rem_in_line = 4;
1677 1655
    ///      std::ostringstream ls;
1678 1656
    ///      while (rem_in_line > 0 && _it != _end) {
1679 1657
    ///        ls << *(_it++) << ' ';
1680 1658
    ///        --rem_in_line;
1681 1659
    ///      }
1682 1660
    ///      return ls.str();
1683 1661
    ///    }
1684 1662
    ///  };
1685 1663
    ///
1686 1664
    ///  // ...
1687 1665
    ///
1688 1666
    ///  writer.sectionLines("numbers", NumberSection(vec));
1689 1667
    ///\endcode
1690 1668
    template <typename Functor>
1691 1669
    SectionWriter& sectionLines(const std::string& type, Functor functor) {
1692 1670
      LEMON_ASSERT(!type.empty(), "Type is empty.");
1693 1671
      _sections.push_back(std::make_pair(type,
1694 1672
        new _writer_bits::LineSection<Functor>(functor)));
1695 1673
      return *this;
1696 1674
    }
1697 1675

	
1698 1676

	
1699 1677
    /// \brief Add a section writer with stream oriented writing
1700 1678
    ///
1701 1679
    /// The first parameter is the type of the section, the second is
1702 1680
    /// a functor, which takes a \c std::ostream& parameter. The
1703 1681
    /// functor writes the section to the output stream.
1704 1682
    /// \warning The last line must be closed with end-line character.
1705 1683
    template <typename Functor>
1706 1684
    SectionWriter& sectionStream(const std::string& type, Functor functor) {
1707 1685
      LEMON_ASSERT(!type.empty(), "Type is empty.");
1708 1686
      _sections.push_back(std::make_pair(type,
1709 1687
         new _writer_bits::StreamSection<Functor>(functor)));
1710 1688
      return *this;
1711 1689
    }
1712 1690

	
1713 1691
    /// @}
1714 1692

	
1715 1693
  public:
1716 1694

	
1717 1695

	
1718 1696
    /// \name Execution of the writer
1719 1697
    /// @{
1720 1698

	
1721 1699
    /// \brief Start the batch processing
1722 1700
    ///
1723 1701
    /// This function starts the batch processing.
1724 1702
    void run() {
1725 1703

	
1726 1704
      LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1727 1705

	
1728 1706
      for (Sections::iterator it = _sections.begin();
1729 1707
           it != _sections.end(); ++it) {
1730 1708
        (*_os) << '@' << it->first << std::endl;
1731 1709
        it->second->process(*_os);
1732 1710
      }
1733 1711
    }
1734 1712

	
1735 1713
    /// \brief Give back the stream of the writer
1736 1714
    ///
1737 1715
    /// Returns the stream of the writer
1738 1716
    std::ostream& ostream() {
1739 1717
      return *_os;
1740 1718
    }
1741 1719

	
1742 1720
    /// @}
1743 1721

	
1744 1722
  };
1745 1723

	
1746 1724
  /// \brief Return a \ref SectionWriter class
1747 1725
  ///
1748 1726
  /// This function just returns a \ref SectionWriter class.
1749 1727
  /// \relates SectionWriter
1750 1728
  inline SectionWriter sectionWriter(std::ostream& os) {
1751 1729
    SectionWriter tmp(os);
1752 1730
    return tmp;
1753 1731
  }
1754 1732

	
1755 1733
  /// \brief Return a \ref SectionWriter class
1756 1734
  ///
1757 1735
  /// This function just returns a \ref SectionWriter class.
1758 1736
  /// \relates SectionWriter
1759 1737
  inline SectionWriter sectionWriter(const std::string& fn) {
1760 1738
    SectionWriter tmp(fn);
1761 1739
    return tmp;
1762 1740
  }
1763 1741

	
1764 1742
  /// \brief Return a \ref SectionWriter class
1765 1743
  ///
1766 1744
  /// This function just returns a \ref SectionWriter class.
1767 1745
  /// \relates SectionWriter
1768 1746
  inline SectionWriter sectionWriter(const char* fn) {
1769 1747
    SectionWriter tmp(fn);
1770 1748
    return tmp;
1771 1749
  }
1772 1750
}
1773 1751

	
1774 1752
#endif
0 comments (0 inline)