gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge
0 2 0
merge default
0 files changed with 56 insertions and 14 deletions:
↑ Collapse diff ↑
Ignore white space 6 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" 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 394
  template <typename Digraph>
395 395
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
396 396
                                       std::istream& is = std::cin);
397 397

	
398 398
  template <typename Digraph>
399 399
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const std::string& fn);
400 400

	
401 401
  template <typename Digraph>
402 402
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const char *fn);
403 403

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

	
458 458
    typedef _Digraph Digraph;
459 459
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
460 460

	
461 461
  private:
462 462

	
463 463

	
464 464
    std::istream* _is;
465 465
    bool local_is;
466 466
    std::string _filename;
467 467

	
468 468
    Digraph& _digraph;
469 469

	
470 470
    std::string _nodes_caption;
471 471
    std::string _arcs_caption;
472 472
    std::string _attributes_caption;
473 473

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

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

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

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

	
491 491
    bool _use_nodes;
492 492
    bool _use_arcs;
493 493

	
494 494
    bool _skip_nodes;
495 495
    bool _skip_arcs;
496 496

	
497 497
    int line_num;
498 498
    std::istringstream line;
499 499

	
500 500
  public:
501 501

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

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

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

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

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

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

	
552 558
      if (local_is) {
553 559
        delete _is;
554 560
      }
555 561

	
556 562
    }
557 563

	
558 564
  private:
559 565

	
560 566
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
561 567
                                                  std::istream& is);
562 568
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
563 569
                                                  const std::string& fn);
564 570
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
565 571
                                                  const char *fn);
566 572

	
567 573
    DigraphReader(DigraphReader& other)
568 574
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
569 575
        _use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
570 576
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
571 577

	
572 578
      other._is = 0;
573 579
      other.local_is = false;
574 580

	
575 581
      _node_index.swap(other._node_index);
576 582
      _arc_index.swap(other._arc_index);
577 583

	
578 584
      _node_maps.swap(other._node_maps);
579 585
      _arc_maps.swap(other._arc_maps);
580 586
      _attributes.swap(other._attributes);
581 587

	
582 588
      _nodes_caption = other._nodes_caption;
583 589
      _arcs_caption = other._arcs_caption;
584 590
      _attributes_caption = other._attributes_caption;
585 591

	
586 592
    }
587 593

	
588 594
    DigraphReader& operator=(const DigraphReader&);
589 595

	
590 596
  public:
591 597

	
592 598
    /// \name Reading rules
593 599
    /// @{
594 600

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

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

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

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

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

	
658 664
    /// \brief Attribute reading rule
659 665
    ///
660 666
    /// Add an attribute reading rule with specialized converter to the
661 667
    /// reader.
662 668
    template <typename Value, typename Converter>
663 669
    DigraphReader& attribute(const std::string& caption, Value& value,
664 670
                             const Converter& converter = Converter()) {
665 671
      _reader_bits::ValueStorageBase* storage =
666 672
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
667 673
      _attributes.insert(std::make_pair(caption, storage));
668 674
      return *this;
669 675
    }
670 676

	
671 677
    /// \brief Node reading rule
672 678
    ///
673 679
    /// Add a node reading rule to reader.
674 680
    DigraphReader& node(const std::string& caption, Node& node) {
675 681
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
676 682
      Converter converter(_node_index);
677 683
      _reader_bits::ValueStorageBase* storage =
678 684
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
679 685
      _attributes.insert(std::make_pair(caption, storage));
680 686
      return *this;
681 687
    }
682 688

	
683 689
    /// \brief Arc reading rule
684 690
    ///
685 691
    /// Add an arc reading rule to reader.
686 692
    DigraphReader& arc(const std::string& caption, Arc& arc) {
687 693
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
688 694
      Converter converter(_arc_index);
689 695
      _reader_bits::ValueStorageBase* storage =
690 696
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
691 697
      _attributes.insert(std::make_pair(caption, storage));
692 698
      return *this;
693 699
    }
694 700

	
695 701
    /// @}
696 702

	
697 703
    /// \name Select section by name
698 704
    /// @{
699 705

	
700 706
    /// \brief Set \c \@nodes section to be read
701 707
    ///
702 708
    /// Set \c \@nodes section to be read
703 709
    DigraphReader& nodes(const std::string& caption) {
704 710
      _nodes_caption = caption;
705 711
      return *this;
706 712
    }
707 713

	
708 714
    /// \brief Set \c \@arcs section to be read
709 715
    ///
710 716
    /// Set \c \@arcs section to be read
711 717
    DigraphReader& arcs(const std::string& caption) {
712 718
      _arcs_caption = caption;
713 719
      return *this;
714 720
    }
715 721

	
716 722
    /// \brief Set \c \@attributes section to be read
717 723
    ///
718 724
    /// Set \c \@attributes section to be read
719 725
    DigraphReader& attributes(const std::string& caption) {
720 726
      _attributes_caption = caption;
721 727
      return *this;
722 728
    }
723 729

	
724 730
    /// @}
725 731

	
726 732
    /// \name Using previously constructed node or arc set
727 733
    /// @{
728 734

	
729 735
    /// \brief Use previously constructed node set
730 736
    ///
731 737
    /// Use previously constructed node set, and specify the node
732 738
    /// label map.
733 739
    template <typename Map>
734 740
    DigraphReader& useNodes(const Map& map) {
735 741
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
736 742
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
737 743
      _use_nodes = true;
738 744
      _writer_bits::DefaultConverter<typename Map::Value> converter;
739 745
      for (NodeIt n(_digraph); n != INVALID; ++n) {
740 746
        _node_index.insert(std::make_pair(converter(map[n]), n));
741 747
      }
742 748
      return *this;
743 749
    }
744 750

	
745 751
    /// \brief Use previously constructed node set
746 752
    ///
747 753
    /// Use previously constructed node set, and specify the node
748 754
    /// label map and a functor which converts the label map values to
749 755
    /// \c std::string.
750 756
    template <typename Map, typename Converter>
751 757
    DigraphReader& useNodes(const Map& map,
752 758
                            const Converter& converter = Converter()) {
753 759
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
754 760
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
755 761
      _use_nodes = true;
756 762
      for (NodeIt n(_digraph); n != INVALID; ++n) {
757 763
        _node_index.insert(std::make_pair(converter(map[n]), n));
758 764
      }
759 765
      return *this;
760 766
    }
761 767

	
762 768
    /// \brief Use previously constructed arc set
763 769
    ///
764 770
    /// Use previously constructed arc set, and specify the arc
765 771
    /// label map.
766 772
    template <typename Map>
767 773
    DigraphReader& useArcs(const Map& map) {
768 774
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
769 775
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
770 776
      _use_arcs = true;
771 777
      _writer_bits::DefaultConverter<typename Map::Value> converter;
772 778
      for (ArcIt a(_digraph); a != INVALID; ++a) {
773 779
        _arc_index.insert(std::make_pair(converter(map[a]), a));
774 780
      }
775 781
      return *this;
776 782
    }
777 783

	
778 784
    /// \brief Use previously constructed arc set
779 785
    ///
780 786
    /// Use previously constructed arc set, and specify the arc
781 787
    /// label map and a functor which converts the label map values to
782 788
    /// \c std::string.
783 789
    template <typename Map, typename Converter>
784 790
    DigraphReader& useArcs(const Map& map,
785 791
                           const Converter& converter = Converter()) {
786 792
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
787 793
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
788 794
      _use_arcs = true;
789 795
      for (ArcIt a(_digraph); a != INVALID; ++a) {
790 796
        _arc_index.insert(std::make_pair(converter(map[a]), a));
791 797
      }
792 798
      return *this;
793 799
    }
794 800

	
795 801
    /// \brief Skips the reading of node section
796 802
    ///
797 803
    /// Omit the reading of the node section. This implies that each node
798 804
    /// map reading rule will be abandoned, and the nodes of the graph
799 805
    /// will not be constructed, which usually cause that the arc set
800 806
    /// could not be read due to lack of node name resolving.
801 807
    /// Therefore \c skipArcs() function should also be used, or
802 808
    /// \c useNodes() should be used to specify the label of the nodes.
803 809
    DigraphReader& skipNodes() {
804 810
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
805 811
      _skip_nodes = true;
806 812
      return *this;
807 813
    }
808 814

	
809 815
    /// \brief Skips the reading of arc section
810 816
    ///
811 817
    /// Omit the reading of the arc section. This implies that each arc
812 818
    /// map reading rule will be abandoned, and the arcs of the graph
813 819
    /// will not be constructed.
814 820
    DigraphReader& skipArcs() {
815 821
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set");
816 822
      _skip_arcs = true;
817 823
      return *this;
818 824
    }
819 825

	
820 826
    /// @}
821 827

	
822 828
  private:
823 829

	
824 830
    bool readLine() {
825 831
      std::string str;
826 832
      while(++line_num, std::getline(*_is, str)) {
827 833
        line.clear(); line.str(str);
828 834
        char c;
829 835
        if (line >> std::ws >> c && c != '#') {
830 836
          line.putback(c);
831 837
          return true;
832 838
        }
833 839
      }
834 840
      return false;
835 841
    }
836 842

	
837 843
    bool readSuccess() {
838 844
      return static_cast<bool>(*_is);
839 845
    }
840 846

	
841 847
    void skipSection() {
842 848
      char c;
843 849
      while (readSuccess() && line >> c && c != '@') {
844 850
        readLine();
845 851
      }
846 852
      line.putback(c);
847 853
    }
848 854

	
849 855
    void readNodes() {
850 856

	
851 857
      std::vector<int> map_index(_node_maps.size());
852 858
      int map_num, label_index;
853 859

	
854 860
      char c;
855 861
      if (!readLine() || !(line >> c) || c == '@') {
856 862
        if (readSuccess() && line) line.putback(c);
857 863
        if (!_node_maps.empty())
858 864
          throw FormatError("Cannot find map names");
859 865
        return;
860 866
      }
861 867
      line.putback(c);
862 868

	
863 869
      {
864 870
        std::map<std::string, int> maps;
865 871

	
866 872
        std::string map;
867 873
        int index = 0;
868 874
        while (_reader_bits::readToken(line, map)) {
869 875
          if (maps.find(map) != maps.end()) {
870 876
            std::ostringstream msg;
871 877
            msg << "Multiple occurence of node map: " << map;
872 878
            throw FormatError(msg.str());
873 879
          }
874 880
          maps.insert(std::make_pair(map, index));
875 881
          ++index;
876 882
        }
877 883

	
878 884
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
879 885
          std::map<std::string, int>::iterator jt =
880 886
            maps.find(_node_maps[i].first);
881 887
          if (jt == maps.end()) {
882 888
            std::ostringstream msg;
883 889
            msg << "Map not found: " << _node_maps[i].first;
884 890
            throw FormatError(msg.str());
885 891
          }
886 892
          map_index[i] = jt->second;
887 893
        }
888 894

	
889 895
        {
890 896
          std::map<std::string, int>::iterator jt = maps.find("label");
891 897
          if (jt != maps.end()) {
892 898
            label_index = jt->second;
893 899
          } else {
894 900
            label_index = -1;
895 901
          }
896 902
        }
897 903
        map_num = maps.size();
898 904
      }
899 905

	
900 906
      while (readLine() && line >> c && c != '@') {
901 907
        line.putback(c);
902 908

	
903 909
        std::vector<std::string> tokens(map_num);
904 910
        for (int i = 0; i < map_num; ++i) {
905 911
          if (!_reader_bits::readToken(line, tokens[i])) {
906 912
            std::ostringstream msg;
907 913
            msg << "Column not found (" << i + 1 << ")";
908 914
            throw FormatError(msg.str());
909 915
          }
910 916
        }
911 917
        if (line >> std::ws >> c)
912 918
          throw FormatError("Extra character at the end of line");
913 919

	
914 920
        Node n;
915 921
        if (!_use_nodes) {
916 922
          n = _digraph.addNode();
917 923
          if (label_index != -1)
918 924
            _node_index.insert(std::make_pair(tokens[label_index], n));
919 925
        } else {
920 926
          if (label_index == -1)
921 927
            throw FormatError("Label map not found");
922 928
          typename std::map<std::string, Node>::iterator it =
923 929
            _node_index.find(tokens[label_index]);
924 930
          if (it == _node_index.end()) {
925 931
            std::ostringstream msg;
926 932
            msg << "Node with label not found: " << tokens[label_index];
927 933
            throw FormatError(msg.str());
928 934
          }
929 935
          n = it->second;
930 936
        }
931 937

	
932 938
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
933 939
          _node_maps[i].second->set(n, tokens[map_index[i]]);
934 940
        }
935 941

	
936 942
      }
937 943
      if (readSuccess()) {
938 944
        line.putback(c);
939 945
      }
940 946
    }
941 947

	
942 948
    void readArcs() {
943 949

	
944 950
      std::vector<int> map_index(_arc_maps.size());
945 951
      int map_num, label_index;
946 952

	
947 953
      char c;
948 954
      if (!readLine() || !(line >> c) || c == '@') {
949 955
        if (readSuccess() && line) line.putback(c);
950 956
        if (!_arc_maps.empty())
951 957
          throw FormatError("Cannot find map names");
952 958
        return;
953 959
      }
954 960
      line.putback(c);
955 961

	
956 962
      {
957 963
        std::map<std::string, int> maps;
958 964

	
959 965
        std::string map;
960 966
        int index = 0;
961 967
        while (_reader_bits::readToken(line, map)) {
962 968
          if (maps.find(map) != maps.end()) {
963 969
            std::ostringstream msg;
964 970
            msg << "Multiple occurence of arc map: " << map;
965 971
            throw FormatError(msg.str());
966 972
          }
967 973
          maps.insert(std::make_pair(map, index));
968 974
          ++index;
969 975
        }
970 976

	
971 977
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
972 978
          std::map<std::string, int>::iterator jt =
973 979
            maps.find(_arc_maps[i].first);
974 980
          if (jt == maps.end()) {
975 981
            std::ostringstream msg;
976 982
            msg << "Map not found: " << _arc_maps[i].first;
977 983
            throw FormatError(msg.str());
978 984
          }
979 985
          map_index[i] = jt->second;
980 986
        }
981 987

	
982 988
        {
983 989
          std::map<std::string, int>::iterator jt = maps.find("label");
984 990
          if (jt != maps.end()) {
985 991
            label_index = jt->second;
986 992
          } else {
987 993
            label_index = -1;
988 994
          }
989 995
        }
990 996
        map_num = maps.size();
991 997
      }
992 998

	
993 999
      while (readLine() && line >> c && c != '@') {
994 1000
        line.putback(c);
995 1001

	
996 1002
        std::string source_token;
997 1003
        std::string target_token;
998 1004

	
999 1005
        if (!_reader_bits::readToken(line, source_token))
1000 1006
          throw FormatError("Source not found");
1001 1007

	
1002 1008
        if (!_reader_bits::readToken(line, target_token))
1003 1009
          throw FormatError("Target not found");
1004 1010

	
1005 1011
        std::vector<std::string> tokens(map_num);
1006 1012
        for (int i = 0; i < map_num; ++i) {
1007 1013
          if (!_reader_bits::readToken(line, tokens[i])) {
1008 1014
            std::ostringstream msg;
1009 1015
            msg << "Column not found (" << i + 1 << ")";
1010 1016
            throw FormatError(msg.str());
1011 1017
          }
1012 1018
        }
1013 1019
        if (line >> std::ws >> c)
1014 1020
          throw FormatError("Extra character at the end of line");
1015 1021

	
1016 1022
        Arc a;
1017 1023
        if (!_use_arcs) {
1018 1024

	
1019 1025
          typename NodeIndex::iterator it;
1020 1026

	
1021 1027
          it = _node_index.find(source_token);
1022 1028
          if (it == _node_index.end()) {
1023 1029
            std::ostringstream msg;
1024 1030
            msg << "Item not found: " << source_token;
1025 1031
            throw FormatError(msg.str());
1026 1032
          }
1027 1033
          Node source = it->second;
1028 1034

	
1029 1035
          it = _node_index.find(target_token);
1030 1036
          if (it == _node_index.end()) {
1031 1037
            std::ostringstream msg;
1032 1038
            msg << "Item not found: " << target_token;
1033 1039
            throw FormatError(msg.str());
1034 1040
          }
1035 1041
          Node target = it->second;
1036 1042

	
1037 1043
          a = _digraph.addArc(source, target);
1038 1044
          if (label_index != -1)
1039 1045
            _arc_index.insert(std::make_pair(tokens[label_index], a));
1040 1046
        } else {
1041 1047
          if (label_index == -1)
1042 1048
            throw FormatError("Label map not found");
1043 1049
          typename std::map<std::string, Arc>::iterator it =
1044 1050
            _arc_index.find(tokens[label_index]);
1045 1051
          if (it == _arc_index.end()) {
1046 1052
            std::ostringstream msg;
1047 1053
            msg << "Arc with label not found: " << tokens[label_index];
1048 1054
            throw FormatError(msg.str());
1049 1055
          }
1050 1056
          a = it->second;
1051 1057
        }
1052 1058

	
1053 1059
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1054 1060
          _arc_maps[i].second->set(a, tokens[map_index[i]]);
1055 1061
        }
1056 1062

	
1057 1063
      }
1058 1064
      if (readSuccess()) {
1059 1065
        line.putback(c);
1060 1066
      }
1061 1067
    }
1062 1068

	
1063 1069
    void readAttributes() {
1064 1070

	
1065 1071
      std::set<std::string> read_attr;
1066 1072

	
1067 1073
      char c;
1068 1074
      while (readLine() && line >> c && c != '@') {
1069 1075
        line.putback(c);
1070 1076

	
1071 1077
        std::string attr, token;
1072 1078
        if (!_reader_bits::readToken(line, attr))
1073 1079
          throw FormatError("Attribute name not found");
1074 1080
        if (!_reader_bits::readToken(line, token))
1075 1081
          throw FormatError("Attribute value not found");
1076 1082
        if (line >> c)
1077 1083
          throw FormatError("Extra character at the end of line");
1078 1084

	
1079 1085
        {
1080 1086
          std::set<std::string>::iterator it = read_attr.find(attr);
1081 1087
          if (it != read_attr.end()) {
1082 1088
            std::ostringstream msg;
1083 1089
            msg << "Multiple occurence of attribute: " << attr;
1084 1090
            throw FormatError(msg.str());
1085 1091
          }
1086 1092
          read_attr.insert(attr);
1087 1093
        }
1088 1094

	
1089 1095
        {
1090 1096
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1091 1097
          while (it != _attributes.end() && it->first == attr) {
1092 1098
            it->second->set(token);
1093 1099
            ++it;
1094 1100
          }
1095 1101
        }
1096 1102

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

	
1111 1117
  public:
1112 1118

	
1113 1119
    /// \name Execution of the reader
1114 1120
    /// @{
1115 1121

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

	
1122 1128
      bool nodes_done = _skip_nodes;
1123 1129
      bool arcs_done = _skip_arcs;
1124 1130
      bool attributes_done = false;
1125 1131

	
1126 1132
      line_num = 0;
1127 1133
      readLine();
1128 1134
      skipSection();
1129 1135

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

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

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

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

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

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

	
1180 1186
    }
1181 1187

	
1182 1188
    /// @}
1183 1189

	
1184 1190
  };
1185 1191

	
1186 1192
  /// \brief Return a \ref DigraphReader class
1187 1193
  ///
1188 1194
  /// This function just returns a \ref DigraphReader class.
1189 1195
  /// \relates DigraphReader
1190 1196
  template <typename Digraph>
1191 1197
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
1192 1198
                                       std::istream& is = std::cin) {
1193 1199
    DigraphReader<Digraph> tmp(digraph, is);
1194 1200
    return tmp;
1195 1201
  }
1196 1202

	
1197 1203
  /// \brief Return a \ref DigraphReader class
1198 1204
  ///
1199 1205
  /// This function just returns a \ref DigraphReader class.
1200 1206
  /// \relates DigraphReader
1201 1207
  template <typename Digraph>
1202 1208
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
1203 1209
                                       const std::string& fn) {
1204 1210
    DigraphReader<Digraph> tmp(digraph, fn);
1205 1211
    return tmp;
1206 1212
  }
1207 1213

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

	
1218 1224
  template <typename Graph>
1219 1225
  class GraphReader;
1220 1226

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

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

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

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

	
1250 1256
    typedef _Graph Graph;
1251 1257
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1252 1258

	
1253 1259
  private:
1254 1260

	
1255 1261
    std::istream* _is;
1256 1262
    bool local_is;
1257 1263
    std::string _filename;
1258 1264

	
1259 1265
    Graph& _graph;
1260 1266

	
1261 1267
    std::string _nodes_caption;
1262 1268
    std::string _edges_caption;
1263 1269
    std::string _attributes_caption;
1264 1270

	
1265 1271
    typedef std::map<std::string, Node> NodeIndex;
1266 1272
    NodeIndex _node_index;
1267 1273
    typedef std::map<std::string, Edge> EdgeIndex;
1268 1274
    EdgeIndex _edge_index;
1269 1275

	
1270 1276
    typedef std::vector<std::pair<std::string,
1271 1277
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
1272 1278
    NodeMaps _node_maps;
1273 1279

	
1274 1280
    typedef std::vector<std::pair<std::string,
1275 1281
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1276 1282
    EdgeMaps _edge_maps;
1277 1283

	
1278 1284
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1279 1285
      Attributes;
1280 1286
    Attributes _attributes;
1281 1287

	
1282 1288
    bool _use_nodes;
1283 1289
    bool _use_edges;
1284 1290

	
1285 1291
    bool _skip_nodes;
1286 1292
    bool _skip_edges;
1287 1293

	
1288 1294
    int line_num;
1289 1295
    std::istringstream line;
1290 1296

	
1291 1297
  public:
1292 1298

	
1293 1299
    /// \brief Constructor
1294 1300
    ///
1295 1301
    /// Construct an undirected graph reader, which reads from the given
1296 1302
    /// input stream.
1297 1303
    GraphReader(Graph& graph, std::istream& is = std::cin)
1298 1304
      : _is(&is), local_is(false), _graph(graph),
1299 1305
        _use_nodes(false), _use_edges(false),
1300 1306
        _skip_nodes(false), _skip_edges(false) {}
1301 1307

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

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

	
1326 1338
    /// \brief Destructor
1327 1339
    ~GraphReader() {
1328 1340
      for (typename NodeMaps::iterator it = _node_maps.begin();
1329 1341
           it != _node_maps.end(); ++it) {
1330 1342
        delete it->second;
1331 1343
      }
1332 1344

	
1333 1345
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1334 1346
           it != _edge_maps.end(); ++it) {
1335 1347
        delete it->second;
1336 1348
      }
1337 1349

	
1338 1350
      for (typename Attributes::iterator it = _attributes.begin();
1339 1351
           it != _attributes.end(); ++it) {
1340 1352
        delete it->second;
1341 1353
      }
1342 1354

	
1343 1355
      if (local_is) {
1344 1356
        delete _is;
1345 1357
      }
1346 1358

	
1347 1359
    }
1348 1360

	
1349 1361
  private:
1350 1362
    friend GraphReader<Graph> graphReader<>(Graph& graph, std::istream& is);
1351 1363
    friend GraphReader<Graph> graphReader<>(Graph& graph,
1352 1364
                                            const std::string& fn);
1353 1365
    friend GraphReader<Graph> graphReader<>(Graph& graph, const char *fn);
1354 1366

	
1355 1367
    GraphReader(GraphReader& other)
1356 1368
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1357 1369
        _use_nodes(other._use_nodes), _use_edges(other._use_edges),
1358 1370
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1359 1371

	
1360 1372
      other._is = 0;
1361 1373
      other.local_is = false;
1362 1374

	
1363 1375
      _node_index.swap(other._node_index);
1364 1376
      _edge_index.swap(other._edge_index);
1365 1377

	
1366 1378
      _node_maps.swap(other._node_maps);
1367 1379
      _edge_maps.swap(other._edge_maps);
1368 1380
      _attributes.swap(other._attributes);
1369 1381

	
1370 1382
      _nodes_caption = other._nodes_caption;
1371 1383
      _edges_caption = other._edges_caption;
1372 1384
      _attributes_caption = other._attributes_caption;
1373 1385

	
1374 1386
    }
1375 1387

	
1376 1388
    GraphReader& operator=(const GraphReader&);
1377 1389

	
1378 1390
  public:
1379 1391

	
1380 1392
    /// \name Reading rules
1381 1393
    /// @{
1382 1394

	
1383 1395
    /// \brief Node map reading rule
1384 1396
    ///
1385 1397
    /// Add a node map reading rule to the reader.
1386 1398
    template <typename Map>
1387 1399
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1388 1400
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1389 1401
      _reader_bits::MapStorageBase<Node>* storage =
1390 1402
        new _reader_bits::MapStorage<Node, Map>(map);
1391 1403
      _node_maps.push_back(std::make_pair(caption, storage));
1392 1404
      return *this;
1393 1405
    }
1394 1406

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

	
1409 1421
    /// \brief Edge map reading rule
1410 1422
    ///
1411 1423
    /// Add an edge map reading rule to the reader.
1412 1424
    template <typename Map>
1413 1425
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1414 1426
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1415 1427
      _reader_bits::MapStorageBase<Edge>* storage =
1416 1428
        new _reader_bits::MapStorage<Edge, Map>(map);
1417 1429
      _edge_maps.push_back(std::make_pair(caption, storage));
1418 1430
      return *this;
1419 1431
    }
1420 1432

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

	
1435 1447
    /// \brief Arc map reading rule
1436 1448
    ///
1437 1449
    /// Add an arc map reading rule to the reader.
1438 1450
    template <typename Map>
1439 1451
    GraphReader& arcMap(const std::string& caption, Map& map) {
1440 1452
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1441 1453
      _reader_bits::MapStorageBase<Edge>* forward_storage =
1442 1454
        new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1443 1455
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1444 1456
      _reader_bits::MapStorageBase<Edge>* backward_storage =
1445 1457
        new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1446 1458
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1447 1459
      return *this;
1448 1460
    }
1449 1461

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

	
1469 1481
    /// \brief Attribute reading rule
1470 1482
    ///
1471 1483
    /// Add an attribute reading rule to the reader.
1472 1484
    template <typename Value>
1473 1485
    GraphReader& attribute(const std::string& caption, Value& value) {
1474 1486
      _reader_bits::ValueStorageBase* storage =
1475 1487
        new _reader_bits::ValueStorage<Value>(value);
1476 1488
      _attributes.insert(std::make_pair(caption, storage));
1477 1489
      return *this;
1478 1490
    }
1479 1491

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

	
1493 1505
    /// \brief Node reading rule
1494 1506
    ///
1495 1507
    /// Add a node reading rule to reader.
1496 1508
    GraphReader& node(const std::string& caption, Node& node) {
1497 1509
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1498 1510
      Converter converter(_node_index);
1499 1511
      _reader_bits::ValueStorageBase* storage =
1500 1512
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1501 1513
      _attributes.insert(std::make_pair(caption, storage));
1502 1514
      return *this;
1503 1515
    }
1504 1516

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

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

	
1529 1541
    /// @}
1530 1542

	
1531 1543
    /// \name Select section by name
1532 1544
    /// @{
1533 1545

	
1534 1546
    /// \brief Set \c \@nodes section to be read
1535 1547
    ///
1536 1548
    /// Set \c \@nodes section to be read.
1537 1549
    GraphReader& nodes(const std::string& caption) {
1538 1550
      _nodes_caption = caption;
1539 1551
      return *this;
1540 1552
    }
1541 1553

	
1542 1554
    /// \brief Set \c \@edges section to be read
1543 1555
    ///
1544 1556
    /// Set \c \@edges section to be read.
1545 1557
    GraphReader& edges(const std::string& caption) {
1546 1558
      _edges_caption = caption;
1547 1559
      return *this;
1548 1560
    }
1549 1561

	
1550 1562
    /// \brief Set \c \@attributes section to be read
1551 1563
    ///
1552 1564
    /// Set \c \@attributes section to be read.
1553 1565
    GraphReader& attributes(const std::string& caption) {
1554 1566
      _attributes_caption = caption;
1555 1567
      return *this;
1556 1568
    }
1557 1569

	
1558 1570
    /// @}
1559 1571

	
1560 1572
    /// \name Using previously constructed node or edge set
1561 1573
    /// @{
1562 1574

	
1563 1575
    /// \brief Use previously constructed node set
1564 1576
    ///
1565 1577
    /// Use previously constructed node set, and specify the node
1566 1578
    /// label map.
1567 1579
    template <typename Map>
1568 1580
    GraphReader& useNodes(const Map& map) {
1569 1581
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1570 1582
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1571 1583
      _use_nodes = true;
1572 1584
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1573 1585
      for (NodeIt n(_graph); n != INVALID; ++n) {
1574 1586
        _node_index.insert(std::make_pair(converter(map[n]), n));
1575 1587
      }
1576 1588
      return *this;
1577 1589
    }
1578 1590

	
1579 1591
    /// \brief Use previously constructed node set
1580 1592
    ///
1581 1593
    /// Use previously constructed node set, and specify the node
1582 1594
    /// label map and a functor which converts the label map values to
1583 1595
    /// \c std::string.
1584 1596
    template <typename Map, typename Converter>
1585 1597
    GraphReader& useNodes(const Map& map,
1586 1598
                            const Converter& converter = Converter()) {
1587 1599
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1588 1600
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1589 1601
      _use_nodes = true;
1590 1602
      for (NodeIt n(_graph); n != INVALID; ++n) {
1591 1603
        _node_index.insert(std::make_pair(converter(map[n]), n));
1592 1604
      }
1593 1605
      return *this;
1594 1606
    }
1595 1607

	
1596 1608
    /// \brief Use previously constructed edge set
1597 1609
    ///
1598 1610
    /// Use previously constructed edge set, and specify the edge
1599 1611
    /// label map.
1600 1612
    template <typename Map>
1601 1613
    GraphReader& useEdges(const Map& map) {
1602 1614
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1603 1615
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1604 1616
      _use_edges = true;
1605 1617
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1606 1618
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1607 1619
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1608 1620
      }
1609 1621
      return *this;
1610 1622
    }
1611 1623

	
1612 1624
    /// \brief Use previously constructed edge set
1613 1625
    ///
1614 1626
    /// Use previously constructed edge set, and specify the edge
1615 1627
    /// label map and a functor which converts the label map values to
1616 1628
    /// \c std::string.
1617 1629
    template <typename Map, typename Converter>
1618 1630
    GraphReader& useEdges(const Map& map,
1619 1631
                            const Converter& converter = Converter()) {
1620 1632
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1621 1633
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1622 1634
      _use_edges = true;
1623 1635
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1624 1636
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1625 1637
      }
1626 1638
      return *this;
1627 1639
    }
1628 1640

	
1629 1641
    /// \brief Skip the reading of node section
1630 1642
    ///
1631 1643
    /// Omit the reading of the node section. This implies that each node
1632 1644
    /// map reading rule will be abandoned, and the nodes of the graph
1633 1645
    /// will not be constructed, which usually cause that the edge set
1634 1646
    /// could not be read due to lack of node name
1635 1647
    /// could not be read due to lack of node name resolving.
1636 1648
    /// Therefore \c skipEdges() function should also be used, or
1637 1649
    /// \c useNodes() should be used to specify the label of the nodes.
1638 1650
    GraphReader& skipNodes() {
1639 1651
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
1640 1652
      _skip_nodes = true;
1641 1653
      return *this;
1642 1654
    }
1643 1655

	
1644 1656
    /// \brief Skip the reading of edge section
1645 1657
    ///
1646 1658
    /// Omit the reading of the edge section. This implies that each edge
1647 1659
    /// map reading rule will be abandoned, and the edges of the graph
1648 1660
    /// will not be constructed.
1649 1661
    GraphReader& skipEdges() {
1650 1662
      LEMON_ASSERT(!_skip_edges, "Skip edges already set");
1651 1663
      _skip_edges = true;
1652 1664
      return *this;
1653 1665
    }
1654 1666

	
1655 1667
    /// @}
1656 1668

	
1657 1669
  private:
1658 1670

	
1659 1671
    bool readLine() {
1660 1672
      std::string str;
1661 1673
      while(++line_num, std::getline(*_is, str)) {
1662 1674
        line.clear(); line.str(str);
1663 1675
        char c;
1664 1676
        if (line >> std::ws >> c && c != '#') {
1665 1677
          line.putback(c);
1666 1678
          return true;
1667 1679
        }
1668 1680
      }
1669 1681
      return false;
1670 1682
    }
1671 1683

	
1672 1684
    bool readSuccess() {
1673 1685
      return static_cast<bool>(*_is);
1674 1686
    }
1675 1687

	
1676 1688
    void skipSection() {
1677 1689
      char c;
1678 1690
      while (readSuccess() && line >> c && c != '@') {
1679 1691
        readLine();
1680 1692
      }
1681 1693
      line.putback(c);
1682 1694
    }
1683 1695

	
1684 1696
    void readNodes() {
1685 1697

	
1686 1698
      std::vector<int> map_index(_node_maps.size());
1687 1699
      int map_num, label_index;
1688 1700

	
1689 1701
      char c;
1690 1702
      if (!readLine() || !(line >> c) || c == '@') {
1691 1703
        if (readSuccess() && line) line.putback(c);
1692 1704
        if (!_node_maps.empty())
1693 1705
          throw FormatError("Cannot find map names");
1694 1706
        return;
1695 1707
      }
1696 1708
      line.putback(c);
1697 1709

	
1698 1710
      {
1699 1711
        std::map<std::string, int> maps;
1700 1712

	
1701 1713
        std::string map;
1702 1714
        int index = 0;
1703 1715
        while (_reader_bits::readToken(line, map)) {
1704 1716
          if (maps.find(map) != maps.end()) {
1705 1717
            std::ostringstream msg;
1706 1718
            msg << "Multiple occurence of node map: " << map;
1707 1719
            throw FormatError(msg.str());
1708 1720
          }
1709 1721
          maps.insert(std::make_pair(map, index));
1710 1722
          ++index;
1711 1723
        }
1712 1724

	
1713 1725
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1714 1726
          std::map<std::string, int>::iterator jt =
1715 1727
            maps.find(_node_maps[i].first);
1716 1728
          if (jt == maps.end()) {
1717 1729
            std::ostringstream msg;
1718 1730
            msg << "Map not found: " << _node_maps[i].first;
1719 1731
            throw FormatError(msg.str());
1720 1732
          }
1721 1733
          map_index[i] = jt->second;
1722 1734
        }
1723 1735

	
1724 1736
        {
1725 1737
          std::map<std::string, int>::iterator jt = maps.find("label");
1726 1738
          if (jt != maps.end()) {
1727 1739
            label_index = jt->second;
1728 1740
          } else {
1729 1741
            label_index = -1;
1730 1742
          }
1731 1743
        }
1732 1744
        map_num = maps.size();
1733 1745
      }
1734 1746

	
1735 1747
      while (readLine() && line >> c && c != '@') {
1736 1748
        line.putback(c);
1737 1749

	
1738 1750
        std::vector<std::string> tokens(map_num);
1739 1751
        for (int i = 0; i < map_num; ++i) {
1740 1752
          if (!_reader_bits::readToken(line, tokens[i])) {
1741 1753
            std::ostringstream msg;
1742 1754
            msg << "Column not found (" << i + 1 << ")";
1743 1755
            throw FormatError(msg.str());
1744 1756
          }
1745 1757
        }
1746 1758
        if (line >> std::ws >> c)
1747 1759
          throw FormatError("Extra character at the end of line");
1748 1760

	
1749 1761
        Node n;
1750 1762
        if (!_use_nodes) {
1751 1763
          n = _graph.addNode();
1752 1764
          if (label_index != -1)
1753 1765
            _node_index.insert(std::make_pair(tokens[label_index], n));
1754 1766
        } else {
1755 1767
          if (label_index == -1)
1756 1768
            throw FormatError("Label map not found");
1757 1769
          typename std::map<std::string, Node>::iterator it =
1758 1770
            _node_index.find(tokens[label_index]);
1759 1771
          if (it == _node_index.end()) {
1760 1772
            std::ostringstream msg;
1761 1773
            msg << "Node with label not found: " << tokens[label_index];
1762 1774
            throw FormatError(msg.str());
1763 1775
          }
1764 1776
          n = it->second;
1765 1777
        }
1766 1778

	
1767 1779
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1768 1780
          _node_maps[i].second->set(n, tokens[map_index[i]]);
1769 1781
        }
1770 1782

	
1771 1783
      }
1772 1784
      if (readSuccess()) {
1773 1785
        line.putback(c);
1774 1786
      }
1775 1787
    }
1776 1788

	
1777 1789
    void readEdges() {
1778 1790

	
1779 1791
      std::vector<int> map_index(_edge_maps.size());
1780 1792
      int map_num, label_index;
1781 1793

	
1782 1794
      char c;
1783 1795
      if (!readLine() || !(line >> c) || c == '@') {
1784 1796
        if (readSuccess() && line) line.putback(c);
1785 1797
        if (!_edge_maps.empty())
1786 1798
          throw FormatError("Cannot find map names");
1787 1799
        return;
1788 1800
      }
1789 1801
      line.putback(c);
1790 1802

	
1791 1803
      {
1792 1804
        std::map<std::string, int> maps;
1793 1805

	
1794 1806
        std::string map;
1795 1807
        int index = 0;
1796 1808
        while (_reader_bits::readToken(line, map)) {
1797 1809
          if (maps.find(map) != maps.end()) {
1798 1810
            std::ostringstream msg;
1799 1811
            msg << "Multiple occurence of edge map: " << map;
1800 1812
            throw FormatError(msg.str());
1801 1813
          }
1802 1814
          maps.insert(std::make_pair(map, index));
1803 1815
          ++index;
1804 1816
        }
1805 1817

	
1806 1818
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1807 1819
          std::map<std::string, int>::iterator jt =
1808 1820
            maps.find(_edge_maps[i].first);
1809 1821
          if (jt == maps.end()) {
1810 1822
            std::ostringstream msg;
1811 1823
            msg << "Map not found: " << _edge_maps[i].first;
1812 1824
            throw FormatError(msg.str());
1813 1825
          }
1814 1826
          map_index[i] = jt->second;
1815 1827
        }
1816 1828

	
1817 1829
        {
1818 1830
          std::map<std::string, int>::iterator jt = maps.find("label");
1819 1831
          if (jt != maps.end()) {
1820 1832
            label_index = jt->second;
1821 1833
          } else {
1822 1834
            label_index = -1;
1823 1835
          }
1824 1836
        }
1825 1837
        map_num = maps.size();
1826 1838
      }
1827 1839

	
1828 1840
      while (readLine() && line >> c && c != '@') {
1829 1841
        line.putback(c);
1830 1842

	
1831 1843
        std::string source_token;
1832 1844
        std::string target_token;
1833 1845

	
1834 1846
        if (!_reader_bits::readToken(line, source_token))
1835 1847
          throw FormatError("Node u not found");
1836 1848

	
1837 1849
        if (!_reader_bits::readToken(line, target_token))
1838 1850
          throw FormatError("Node v not found");
1839 1851

	
1840 1852
        std::vector<std::string> tokens(map_num);
1841 1853
        for (int i = 0; i < map_num; ++i) {
1842 1854
          if (!_reader_bits::readToken(line, tokens[i])) {
1843 1855
            std::ostringstream msg;
1844 1856
            msg << "Column not found (" << i + 1 << ")";
1845 1857
            throw FormatError(msg.str());
1846 1858
          }
1847 1859
        }
1848 1860
        if (line >> std::ws >> c)
1849 1861
          throw FormatError("Extra character at the end of line");
1850 1862

	
1851 1863
        Edge e;
1852 1864
        if (!_use_edges) {
1853 1865

	
1854 1866
          typename NodeIndex::iterator it;
1855 1867

	
1856 1868
          it = _node_index.find(source_token);
1857 1869
          if (it == _node_index.end()) {
1858 1870
            std::ostringstream msg;
1859 1871
            msg << "Item not found: " << source_token;
1860 1872
            throw FormatError(msg.str());
1861 1873
          }
1862 1874
          Node source = it->second;
1863 1875

	
1864 1876
          it = _node_index.find(target_token);
1865 1877
          if (it == _node_index.end()) {
1866 1878
            std::ostringstream msg;
1867 1879
            msg << "Item not found: " << target_token;
1868 1880
            throw FormatError(msg.str());
1869 1881
          }
1870 1882
          Node target = it->second;
1871 1883

	
1872 1884
          e = _graph.addEdge(source, target);
1873 1885
          if (label_index != -1)
1874 1886
            _edge_index.insert(std::make_pair(tokens[label_index], e));
1875 1887
        } else {
1876 1888
          if (label_index == -1)
1877 1889
            throw FormatError("Label map not found");
1878 1890
          typename std::map<std::string, Edge>::iterator it =
1879 1891
            _edge_index.find(tokens[label_index]);
1880 1892
          if (it == _edge_index.end()) {
1881 1893
            std::ostringstream msg;
1882 1894
            msg << "Edge with label not found: " << tokens[label_index];
1883 1895
            throw FormatError(msg.str());
1884 1896
          }
1885 1897
          e = it->second;
1886 1898
        }
1887 1899

	
1888 1900
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1889 1901
          _edge_maps[i].second->set(e, tokens[map_index[i]]);
1890 1902
        }
1891 1903

	
1892 1904
      }
1893 1905
      if (readSuccess()) {
1894 1906
        line.putback(c);
1895 1907
      }
1896 1908
    }
1897 1909

	
1898 1910
    void readAttributes() {
1899 1911

	
1900 1912
      std::set<std::string> read_attr;
1901 1913

	
1902 1914
      char c;
1903 1915
      while (readLine() && line >> c && c != '@') {
1904 1916
        line.putback(c);
1905 1917

	
1906 1918
        std::string attr, token;
1907 1919
        if (!_reader_bits::readToken(line, attr))
1908 1920
          throw FormatError("Attribute name not found");
1909 1921
        if (!_reader_bits::readToken(line, token))
1910 1922
          throw FormatError("Attribute value not found");
1911 1923
        if (line >> c)
1912 1924
          throw FormatError("Extra character at the end of line");
1913 1925

	
1914 1926
        {
1915 1927
          std::set<std::string>::iterator it = read_attr.find(attr);
1916 1928
          if (it != read_attr.end()) {
1917 1929
            std::ostringstream msg;
1918 1930
            msg << "Multiple occurence of attribute: " << attr;
1919 1931
            throw FormatError(msg.str());
1920 1932
          }
1921 1933
          read_attr.insert(attr);
1922 1934
        }
1923 1935

	
1924 1936
        {
1925 1937
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1926 1938
          while (it != _attributes.end() && it->first == attr) {
1927 1939
            it->second->set(token);
1928 1940
            ++it;
1929 1941
          }
1930 1942
        }
1931 1943

	
1932 1944
      }
1933 1945
      if (readSuccess()) {
1934 1946
        line.putback(c);
1935 1947
      }
1936 1948
      for (typename Attributes::iterator it = _attributes.begin();
1937 1949
           it != _attributes.end(); ++it) {
1938 1950
        if (read_attr.find(it->first) == read_attr.end()) {
1939 1951
          std::ostringstream msg;
1940 1952
          msg << "Attribute not found: " << it->first;
1941 1953
          throw FormatError(msg.str());
1942 1954
        }
1943 1955
      }
1944 1956
    }
1945 1957

	
1946 1958
  public:
1947 1959

	
1948 1960
    /// \name Execution of the reader
1949 1961
    /// @{
1950 1962

	
1951 1963
    /// \brief Start the batch processing
1952 1964
    ///
1953 1965
    /// This function starts the batch processing
1954 1966
    void run() {
1955 1967

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

	
1958 1970
      bool nodes_done = _skip_nodes;
1959 1971
      bool edges_done = _skip_edges;
1960 1972
      bool attributes_done = false;
1961 1973

	
1962 1974
      line_num = 0;
1963 1975
      readLine();
1964 1976
      skipSection();
1965 1977

	
1966 1978
      while (readSuccess()) {
1967 1979
        try {
1968 1980
          char c;
1969 1981
          std::string section, caption;
1970 1982
          line >> c;
1971 1983
          _reader_bits::readToken(line, section);
1972 1984
          _reader_bits::readToken(line, caption);
1973 1985

	
1974 1986
          if (line >> c)
1975 1987
            throw FormatError("Extra character at the end of line");
1976 1988

	
1977 1989
          if (section == "nodes" && !nodes_done) {
1978 1990
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1979 1991
              readNodes();
1980 1992
              nodes_done = true;
1981 1993
            }
1982 1994
          } else if ((section == "edges" || section == "arcs") &&
1983 1995
                     !edges_done) {
1984 1996
            if (_edges_caption.empty() || _edges_caption == caption) {
1985 1997
              readEdges();
1986 1998
              edges_done = true;
1987 1999
            }
1988 2000
          } else if (section == "attributes" && !attributes_done) {
1989 2001
            if (_attributes_caption.empty() || _attributes_caption == caption) {
1990 2002
              readAttributes();
1991 2003
              attributes_done = true;
1992 2004
            }
1993 2005
          } else {
1994 2006
            readLine();
1995 2007
            skipSection();
1996 2008
          }
1997 2009
        } catch (FormatError& error) {
1998 2010
          error.line(line_num);
1999 2011
          error.file(_filename);
2000 2012
          throw;
2001 2013
        }
2002 2014
      }
2003 2015

	
2004 2016
      if (!nodes_done) {
2005 2017
        throw FormatError("Section @nodes not found");
2006 2018
      }
2007 2019

	
2008 2020
      if (!edges_done) {
2009 2021
        throw FormatError("Section @edges not found");
2010 2022
      }
2011 2023

	
2012 2024
      if (!attributes_done && !_attributes.empty()) {
2013 2025
        throw FormatError("Section @attributes not found");
2014 2026
      }
2015 2027

	
2016 2028
    }
2017 2029

	
2018 2030
    /// @}
2019 2031

	
2020 2032
  };
2021 2033

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

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

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

	
2052 2064
  class SectionReader;
2053 2065

	
2054 2066
  SectionReader sectionReader(std::istream& is);
2055 2067
  SectionReader sectionReader(const std::string& fn);
2056 2068
  SectionReader sectionReader(const char* fn);
2057 2069

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

	
2072 2084
    std::istream* _is;
2073 2085
    bool local_is;
2074 2086
    std::string _filename;
2075 2087

	
2076 2088
    typedef std::map<std::string, _reader_bits::Section*> Sections;
2077 2089
    Sections _sections;
2078 2090

	
2079 2091
    int line_num;
2080 2092
    std::istringstream line;
2081 2093

	
2082 2094
  public:
2083 2095

	
2084 2096
    /// \brief Constructor
2085 2097
    ///
2086 2098
    /// Construct a section reader, which reads from the given input
2087 2099
    /// stream.
2088 2100
    SectionReader(std::istream& is)
2089 2101
      : _is(&is), local_is(false) {}
2090 2102

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

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

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

	
2116 2134
      if (local_is) {
2117 2135
        delete _is;
2118 2136
      }
2119 2137

	
2120 2138
    }
2121 2139

	
2122 2140
  private:
2123 2141

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

	
2128 2146
    SectionReader(SectionReader& other)
2129 2147
      : _is(other._is), local_is(other.local_is) {
2130 2148

	
2131 2149
      other._is = 0;
2132 2150
      other.local_is = false;
2133 2151

	
2134 2152
      _sections.swap(other._sections);
2135 2153
    }
2136 2154

	
2137 2155
    SectionReader& operator=(const SectionReader&);
2138 2156

	
2139 2157
  public:
2140 2158

	
2141 2159
    /// \name Section readers
2142 2160
    /// @{
2143 2161

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

	
2188 2206

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

	
2206 2224
    /// @}
2207 2225

	
2208 2226
  private:
2209 2227

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

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

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

	
2235 2253
  public:
2236 2254

	
2237 2255

	
2238 2256
    /// \name Execution of the reader
2239 2257
    /// @{
2240 2258

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

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

	
2248 2266
      std::set<std::string> extra_sections;
2249 2267

	
2250 2268
      line_num = 0;
2251 2269
      readLine();
2252 2270
      skipSection();
2253 2271

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

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

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

	
2293 2311
    /// @}
2294 2312

	
2295 2313
  };
2296 2314

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

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

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

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

	
2355 2373
    std::istream* _is;
2356 2374
    bool local_is;
2357 2375

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

	
2363 2381
    std::vector<bool> _arc_sections;
2364 2382

	
2365 2383
    std::vector<std::vector<std::string> > _node_maps;
2366 2384
    std::vector<std::vector<std::string> > _edge_maps;
2367 2385

	
2368 2386
    std::vector<std::vector<std::string> > _attributes;
2369 2387

	
2370 2388

	
2371 2389
    int line_num;
2372 2390
    std::istringstream line;
2373 2391

	
2374 2392
  public:
2375 2393

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

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

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

	
2401 2425
    /// \brief Destructor
2402 2426
    ~LgfContents() {
2403 2427
      if (local_is) delete _is;
2404 2428
    }
2405 2429

	
2406 2430
  private:
2407 2431

	
2408 2432
    LgfContents(const LgfContents&);
2409 2433
    LgfContents& operator=(const LgfContents&);
2410 2434

	
2411 2435
  public:
2412 2436

	
2413 2437

	
2414 2438
    /// \name Node sections
2415 2439
    /// @{
2416 2440

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

	
2424 2448
    /// \brief Returns the node section name at the given position.
2425 2449
    ///
2426 2450
    /// Returns the node section name at the given position.
2427 2451
    const std::string& nodeSection(int i) const {
2428 2452
      return _node_sections[i];
2429 2453
    }
2430 2454

	
2431 2455
    /// \brief Gives back the node maps for the given section.
2432 2456
    ///
2433 2457
    /// Gives back the node maps for the given section.
2434 2458
    const std::vector<std::string>& nodeMapNames(int i) const {
2435 2459
      return _node_maps[i];
2436 2460
    }
2437 2461

	
2438 2462
    /// @}
2439 2463

	
2440 2464
    /// \name Arc/Edge sections
2441 2465
    /// @{
2442 2466

	
2443 2467
    /// \brief Gives back the number of arc/edge sections in the file.
2444 2468
    ///
2445 2469
    /// Gives back the number of arc/edge sections in the file.
2446 2470
    /// \note It is synonym of \c edgeSectionNum().
2447 2471
    int arcSectionNum() const {
2448 2472
      return _edge_sections.size();
2449 2473
    }
2450 2474

	
2451 2475
    /// \brief Returns the arc/edge section name at the given position.
2452 2476
    ///
2453 2477
    /// Returns the arc/edge section name at the given position.
2454 2478
    /// \note It is synonym of \c edgeSection().
2455 2479
    const std::string& arcSection(int i) const {
2456 2480
      return _edge_sections[i];
2457 2481
    }
2458 2482

	
2459 2483
    /// \brief Gives back the arc/edge maps for the given section.
2460 2484
    ///
2461 2485
    /// Gives back the arc/edge maps for the given section.
2462 2486
    /// \note It is synonym of \c edgeMapNames().
2463 2487
    const std::vector<std::string>& arcMapNames(int i) const {
2464 2488
      return _edge_maps[i];
2465 2489
    }
2466 2490

	
2467 2491
    /// @}
2468 2492

	
2469 2493
    /// \name Synonyms
2470 2494
    /// @{
2471 2495

	
2472 2496
    /// \brief Gives back the number of arc/edge sections in the file.
2473 2497
    ///
2474 2498
    /// Gives back the number of arc/edge sections in the file.
2475 2499
    /// \note It is synonym of \c arcSectionNum().
2476 2500
    int edgeSectionNum() const {
2477 2501
      return _edge_sections.size();
2478 2502
    }
2479 2503

	
2480 2504
    /// \brief Returns the section name at the given position.
2481 2505
    ///
2482 2506
    /// Returns the section name at the given position.
2483 2507
    /// \note It is synonym of \c arcSection().
2484 2508
    const std::string& edgeSection(int i) const {
2485 2509
      return _edge_sections[i];
2486 2510
    }
2487 2511

	
2488 2512
    /// \brief Gives back the edge maps for the given section.
2489 2513
    ///
2490 2514
    /// Gives back the edge maps for the given section.
2491 2515
    /// \note It is synonym of \c arcMapNames().
2492 2516
    const std::vector<std::string>& edgeMapNames(int i) const {
2493 2517
      return _edge_maps[i];
2494 2518
    }
2495 2519

	
2496 2520
    /// @}
2497 2521

	
2498 2522
    /// \name Attribute sections
2499 2523
    /// @{
2500 2524

	
2501 2525
    /// \brief Gives back the number of attribute sections in the file.
2502 2526
    ///
2503 2527
    /// Gives back the number of attribute sections in the file.
2504 2528
    int attributeSectionNum() const {
2505 2529
      return _attribute_sections.size();
2506 2530
    }
2507 2531

	
2508 2532
    /// \brief Returns the attribute section name at the given position.
2509 2533
    ///
2510 2534
    /// Returns the attribute section name at the given position.
2511 2535
    const std::string& attributeSectionNames(int i) const {
2512 2536
      return _attribute_sections[i];
2513 2537
    }
2514 2538

	
2515 2539
    /// \brief Gives back the attributes for the given section.
2516 2540
    ///
2517 2541
    /// Gives back the attributes for the given section.
2518 2542
    const std::vector<std::string>& attributes(int i) const {
2519 2543
      return _attributes[i];
2520 2544
    }
2521 2545

	
2522 2546
    /// @}
2523 2547

	
2524 2548
    /// \name Extra sections
2525 2549
    /// @{
2526 2550

	
2527 2551
    /// \brief Gives back the number of extra sections in the file.
2528 2552
    ///
2529 2553
    /// Gives back the number of extra sections in the file.
2530 2554
    int extraSectionNum() const {
2531 2555
      return _extra_sections.size();
2532 2556
    }
2533 2557

	
2534 2558
    /// \brief Returns the extra section type at the given position.
2535 2559
    ///
2536 2560
    /// Returns the section type at the given position.
2537 2561
    const std::string& extraSection(int i) const {
2538 2562
      return _extra_sections[i];
2539 2563
    }
2540 2564

	
2541 2565
    /// @}
2542 2566

	
2543 2567
  private:
2544 2568

	
2545 2569
    bool readLine() {
2546 2570
      std::string str;
2547 2571
      while(++line_num, std::getline(*_is, str)) {
2548 2572
        line.clear(); line.str(str);
2549 2573
        char c;
2550 2574
        if (line >> std::ws >> c && c != '#') {
2551 2575
          line.putback(c);
2552 2576
          return true;
2553 2577
        }
2554 2578
      }
2555 2579
      return false;
2556 2580
    }
2557 2581

	
2558 2582
    bool readSuccess() {
2559 2583
      return static_cast<bool>(*_is);
2560 2584
    }
2561 2585

	
2562 2586
    void skipSection() {
2563 2587
      char c;
2564 2588
      while (readSuccess() && line >> c && c != '@') {
2565 2589
        readLine();
2566 2590
      }
2567 2591
      line.putback(c);
2568 2592
    }
2569 2593

	
2570 2594
    void readMaps(std::vector<std::string>& maps) {
2571 2595
      char c;
2572 2596
      if (!readLine() || !(line >> c) || c == '@') {
2573 2597
        if (readSuccess() && line) line.putback(c);
2574 2598
        return;
2575 2599
      }
2576 2600
      line.putback(c);
2577 2601
      std::string map;
2578 2602
      while (_reader_bits::readToken(line, map)) {
2579 2603
        maps.push_back(map);
2580 2604
      }
2581 2605
    }
2582 2606

	
2583 2607
    void readAttributes(std::vector<std::string>& attrs) {
2584 2608
      readLine();
2585 2609
      char c;
2586 2610
      while (readSuccess() && line >> c && c != '@') {
2587 2611
        line.putback(c);
2588 2612
        std::string attr;
2589 2613
        _reader_bits::readToken(line, attr);
2590 2614
        attrs.push_back(attr);
2591 2615
        readLine();
2592 2616
      }
2593 2617
      line.putback(c);
2594 2618
    }
2595 2619

	
2596 2620
  public:
2597 2621

	
2598 2622
    /// \name Execution of the contents reader
2599 2623
    /// @{
2600 2624

	
2601 2625
    /// \brief Starts the reading
2602 2626
    ///
2603 2627
    /// This function starts the reading.
2604 2628
    void run() {
2605 2629

	
2606 2630
      readLine();
2607 2631
      skipSection();
2608 2632

	
2609 2633
      while (readSuccess()) {
2610 2634

	
2611 2635
        char c;
2612 2636
        line >> c;
2613 2637

	
2614 2638
        std::string section, caption;
2615 2639
        _reader_bits::readToken(line, section);
2616 2640
        _reader_bits::readToken(line, caption);
2617 2641

	
2618 2642
        if (section == "nodes") {
2619 2643
          _node_sections.push_back(caption);
2620 2644
          _node_maps.push_back(std::vector<std::string>());
2621 2645
          readMaps(_node_maps.back());
2622 2646
          readLine(); skipSection();
2623 2647
        } else if (section == "arcs" || section == "edges") {
2624 2648
          _edge_sections.push_back(caption);
2625 2649
          _arc_sections.push_back(section == "arcs");
2626 2650
          _edge_maps.push_back(std::vector<std::string>());
2627 2651
          readMaps(_edge_maps.back());
2628 2652
          readLine(); skipSection();
2629 2653
        } else if (section == "attributes") {
2630 2654
          _attribute_sections.push_back(caption);
2631 2655
          _attributes.push_back(std::vector<std::string>());
2632 2656
          readAttributes(_attributes.back());
2633 2657
        } else {
2634 2658
          _extra_sections.push_back(section);
2635 2659
          readLine(); skipSection();
2636 2660
        }
2637 2661
      }
2638 2662
    }
2639 2663

	
2640 2664
    /// @}
2641 2665

	
2642 2666
  };
2643 2667
}
2644 2668

	
2645 2669
#endif
Ignore white space 1536 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 354
  template <typename Digraph>
355 355
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
356 356
                                       std::ostream& os = std::cout);
357 357

	
358 358
  template <typename Digraph>
359 359
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
360 360
                                       const std::string& fn);
361 361

	
362 362
  template <typename Digraph>
363 363
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
364 364
                                       const char *fn);
365 365

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

	
414 414
    typedef _Digraph Digraph;
415 415
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
416 416

	
417 417
  private:
418 418

	
419 419

	
420 420
    std::ostream* _os;
421 421
    bool local_os;
422 422

	
423 423
    const Digraph& _digraph;
424 424

	
425 425
    std::string _nodes_caption;
426 426
    std::string _arcs_caption;
427 427
    std::string _attributes_caption;
428 428

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

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

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

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

	
446 446
    bool _skip_nodes;
447 447
    bool _skip_arcs;
448 448

	
449 449
  public:
450 450

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

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

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

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

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

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

	
496 502
      if (local_os) {
497 503
        delete _os;
498 504
      }
499 505
    }
500 506

	
501 507
  private:
502 508

	
503 509
    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
504 510
                                                  std::ostream& os);
505 511
    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
506 512
                                                  const std::string& fn);
507 513
    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
508 514
                                                  const char *fn);
509 515

	
510 516
    DigraphWriter(DigraphWriter& other)
511 517
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
512 518
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
513 519

	
514 520
      other._os = 0;
515 521
      other.local_os = false;
516 522

	
517 523
      _node_index.swap(other._node_index);
518 524
      _arc_index.swap(other._arc_index);
519 525

	
520 526
      _node_maps.swap(other._node_maps);
521 527
      _arc_maps.swap(other._arc_maps);
522 528
      _attributes.swap(other._attributes);
523 529

	
524 530
      _nodes_caption = other._nodes_caption;
525 531
      _arcs_caption = other._arcs_caption;
526 532
      _attributes_caption = other._attributes_caption;
527 533
    }
528 534

	
529 535
    DigraphWriter& operator=(const DigraphWriter&);
530 536

	
531 537
  public:
532 538

	
533 539
    /// \name Writing rules
534 540
    /// @{
535 541

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

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

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

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

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

	
599 605
    /// \brief Attribute writing rule
600 606
    ///
601 607
    /// Add an attribute writing rule with specialized converter to the
602 608
    /// writer.
603 609
    template <typename Value, typename Converter>
604 610
    DigraphWriter& attribute(const std::string& caption, const Value& value,
605 611
                             const Converter& converter = Converter()) {
606 612
      _writer_bits::ValueStorageBase* storage =
607 613
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
608 614
      _attributes.push_back(std::make_pair(caption, storage));
609 615
      return *this;
610 616
    }
611 617

	
612 618
    /// \brief Node writing rule
613 619
    ///
614 620
    /// Add a node writing rule to the writer.
615 621
    DigraphWriter& node(const std::string& caption, const Node& node) {
616 622
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
617 623
      Converter converter(_node_index);
618 624
      _writer_bits::ValueStorageBase* storage =
619 625
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
620 626
      _attributes.push_back(std::make_pair(caption, storage));
621 627
      return *this;
622 628
    }
623 629

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

	
636 642
    /// \name Section captions
637 643
    /// @{
638 644

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

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

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

	
663 669
    /// \name Skipping section
664 670
    /// @{
665 671

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

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

	
684 690
    /// @}
685 691

	
686 692
  private:
687 693

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

	
698 704
      *_os << "@nodes";
699 705
      if (!_nodes_caption.empty()) {
700 706
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
701 707
      }
702 708
      *_os << std::endl;
703 709

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

	
713 719
      std::vector<Node> nodes;
714 720
      for (NodeIt n(_digraph); n != INVALID; ++n) {
715 721
        nodes.push_back(n);
716 722
      }
717 723

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

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

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

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

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

	
782 788
      *_os << "@arcs";
783 789
      if (!_arcs_caption.empty()) {
784 790
        _writer_bits::writeToken(*_os << ' ', _arcs_caption);
785 791
      }
786 792
      *_os << std::endl;
787 793

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

	
798 804
      std::vector<Arc> arcs;
799 805
      for (ArcIt n(_digraph); n != INVALID; ++n) {
800 806
        arcs.push_back(n);
801 807
      }
802 808

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

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

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

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

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

	
878 884
  public:
879 885

	
880 886
    /// \name Execution of the writer
881 887
    /// @{
882 888

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

	
900 906
    /// \brief Give back the stream of the writer
901 907
    ///
902 908
    /// Give back the stream of the writer.
903 909
    std::ostream& ostream() {
904 910
      return *_os;
905 911
    }
906 912

	
907 913
    /// @}
908 914
  };
909 915

	
910 916
  /// \brief Return a \ref DigraphWriter class
911 917
  ///
912 918
  /// This function just returns a \ref DigraphWriter class.
913 919
  /// \relates DigraphWriter
914 920
  template <typename Digraph>
915 921
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
916 922
                                       std::ostream& os = std::cout) {
917 923
    DigraphWriter<Digraph> tmp(digraph, os);
918 924
    return tmp;
919 925
  }
920 926

	
921 927
  /// \brief Return a \ref DigraphWriter class
922 928
  ///
923 929
  /// This function just returns a \ref DigraphWriter class.
924 930
  /// \relates DigraphWriter
925 931
  template <typename Digraph>
926 932
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
927 933
                                       const std::string& fn) {
928 934
    DigraphWriter<Digraph> tmp(digraph, fn);
929 935
    return tmp;
930 936
  }
931 937

	
932 938
  /// \brief Return a \ref DigraphWriter class
933 939
  ///
934 940
  /// This function just returns a \ref DigraphWriter class.
935 941
  /// \relates DigraphWriter
936 942
  template <typename Digraph>
937 943
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
938 944
                                       const char* fn) {
939 945
    DigraphWriter<Digraph> tmp(digraph, fn);
940 946
    return tmp;
941 947
  }
942 948

	
943 949
  template <typename Graph>
944 950
  class GraphWriter;
945 951

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

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

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

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

	
975 981
    typedef _Graph Graph;
976 982
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
977 983

	
978 984
  private:
979 985

	
980 986

	
981 987
    std::ostream* _os;
982 988
    bool local_os;
983 989

	
984 990
    const Graph& _graph;
985 991

	
986 992
    std::string _nodes_caption;
987 993
    std::string _edges_caption;
988 994
    std::string _attributes_caption;
989 995

	
990 996
    typedef std::map<Node, std::string> NodeIndex;
991 997
    NodeIndex _node_index;
992 998
    typedef std::map<Edge, std::string> EdgeIndex;
993 999
    EdgeIndex _edge_index;
994 1000

	
995 1001
    typedef std::vector<std::pair<std::string,
996 1002
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
997 1003
    NodeMaps _node_maps;
998 1004

	
999 1005
    typedef std::vector<std::pair<std::string,
1000 1006
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1001 1007
    EdgeMaps _edge_maps;
1002 1008

	
1003 1009
    typedef std::vector<std::pair<std::string,
1004 1010
      _writer_bits::ValueStorageBase*> > Attributes;
1005 1011
    Attributes _attributes;
1006 1012

	
1007 1013
    bool _skip_nodes;
1008 1014
    bool _skip_edges;
1009 1015

	
1010 1016
  public:
1011 1017

	
1012 1018
    /// \brief Constructor
1013 1019
    ///
1014 1020
    /// Construct a directed graph writer, which writes to the given
1015 1021
    /// output stream.
1016 1022
    GraphWriter(const Graph& graph, std::ostream& os = std::cout)
1017 1023
      : _os(&os), local_os(false), _graph(graph),
1018 1024
        _skip_nodes(false), _skip_edges(false) {}
1019 1025

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

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

	
1040 1052
    /// \brief Destructor
1041 1053
    ~GraphWriter() {
1042 1054
      for (typename NodeMaps::iterator it = _node_maps.begin();
1043 1055
           it != _node_maps.end(); ++it) {
1044 1056
        delete it->second;
1045 1057
      }
1046 1058

	
1047 1059
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1048 1060
           it != _edge_maps.end(); ++it) {
1049 1061
        delete it->second;
1050 1062
      }
1051 1063

	
1052 1064
      for (typename Attributes::iterator it = _attributes.begin();
1053 1065
           it != _attributes.end(); ++it) {
1054 1066
        delete it->second;
1055 1067
      }
1056 1068

	
1057 1069
      if (local_os) {
1058 1070
        delete _os;
1059 1071
      }
1060 1072
    }
1061 1073

	
1062 1074
  private:
1063 1075

	
1064 1076
    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1065 1077
                                            std::ostream& os);
1066 1078
    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1067 1079
                                            const std::string& fn);
1068 1080
    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1069 1081
                                            const char *fn);
1070 1082

	
1071 1083
    GraphWriter(GraphWriter& other)
1072 1084
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
1073 1085
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1074 1086

	
1075 1087
      other._os = 0;
1076 1088
      other.local_os = false;
1077 1089

	
1078 1090
      _node_index.swap(other._node_index);
1079 1091
      _edge_index.swap(other._edge_index);
1080 1092

	
1081 1093
      _node_maps.swap(other._node_maps);
1082 1094
      _edge_maps.swap(other._edge_maps);
1083 1095
      _attributes.swap(other._attributes);
1084 1096

	
1085 1097
      _nodes_caption = other._nodes_caption;
1086 1098
      _edges_caption = other._edges_caption;
1087 1099
      _attributes_caption = other._attributes_caption;
1088 1100
    }
1089 1101

	
1090 1102
    GraphWriter& operator=(const GraphWriter&);
1091 1103

	
1092 1104
  public:
1093 1105

	
1094 1106
    /// \name Writing rules
1095 1107
    /// @{
1096 1108

	
1097 1109
    /// \brief Node map writing rule
1098 1110
    ///
1099 1111
    /// Add a node map writing rule to the writer.
1100 1112
    template <typename Map>
1101 1113
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1102 1114
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1103 1115
      _writer_bits::MapStorageBase<Node>* storage =
1104 1116
        new _writer_bits::MapStorage<Node, Map>(map);
1105 1117
      _node_maps.push_back(std::make_pair(caption, storage));
1106 1118
      return *this;
1107 1119
    }
1108 1120

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

	
1123 1135
    /// \brief Edge map writing rule
1124 1136
    ///
1125 1137
    /// Add an edge map writing rule to the writer.
1126 1138
    template <typename Map>
1127 1139
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1128 1140
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1129 1141
      _writer_bits::MapStorageBase<Edge>* storage =
1130 1142
        new _writer_bits::MapStorage<Edge, Map>(map);
1131 1143
      _edge_maps.push_back(std::make_pair(caption, storage));
1132 1144
      return *this;
1133 1145
    }
1134 1146

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

	
1149 1161
    /// \brief Arc map writing rule
1150 1162
    ///
1151 1163
    /// Add an arc map writing rule to the writer.
1152 1164
    template <typename Map>
1153 1165
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
1154 1166
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1155 1167
      _writer_bits::MapStorageBase<Edge>* forward_storage =
1156 1168
        new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1157 1169
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1158 1170
      _writer_bits::MapStorageBase<Edge>* backward_storage =
1159 1171
        new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1160 1172
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1161 1173
      return *this;
1162 1174
    }
1163 1175

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

	
1183 1195
    /// \brief Attribute writing rule
1184 1196
    ///
1185 1197
    /// Add an attribute writing rule to the writer.
1186 1198
    template <typename Value>
1187 1199
    GraphWriter& attribute(const std::string& caption, const Value& value) {
1188 1200
      _writer_bits::ValueStorageBase* storage =
1189 1201
        new _writer_bits::ValueStorage<Value>(value);
1190 1202
      _attributes.push_back(std::make_pair(caption, storage));
1191 1203
      return *this;
1192 1204
    }
1193 1205

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

	
1207 1219
    /// \brief Node writing rule
1208 1220
    ///
1209 1221
    /// Add a node writing rule to the writer.
1210 1222
    GraphWriter& node(const std::string& caption, const Node& node) {
1211 1223
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
1212 1224
      Converter converter(_node_index);
1213 1225
      _writer_bits::ValueStorageBase* storage =
1214 1226
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1215 1227
      _attributes.push_back(std::make_pair(caption, storage));
1216 1228
      return *this;
1217 1229
    }
1218 1230

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

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

	
1243 1255
    /// \name Section captions
1244 1256
    /// @{
1245 1257

	
1246 1258
    /// \brief Add an additional caption to the \c \@nodes section
1247 1259
    ///
1248 1260
    /// Add an additional caption to the \c \@nodes section.
1249 1261
    GraphWriter& nodes(const std::string& caption) {
1250 1262
      _nodes_caption = caption;
1251 1263
      return *this;
1252 1264
    }
1253 1265

	
1254 1266
    /// \brief Add an additional caption to the \c \@arcs section
1255 1267
    ///
1256 1268
    /// Add an additional caption to the \c \@arcs section.
1257 1269
    GraphWriter& edges(const std::string& caption) {
1258 1270
      _edges_caption = caption;
1259 1271
      return *this;
1260 1272
    }
1261 1273

	
1262 1274
    /// \brief Add an additional caption to the \c \@attributes section
1263 1275
    ///
1264 1276
    /// Add an additional caption to the \c \@attributes section.
1265 1277
    GraphWriter& attributes(const std::string& caption) {
1266 1278
      _attributes_caption = caption;
1267 1279
      return *this;
1268 1280
    }
1269 1281

	
1270 1282
    /// \name Skipping section
1271 1283
    /// @{
1272 1284

	
1273 1285
    /// \brief Skip writing the node set
1274 1286
    ///
1275 1287
    /// The \c \@nodes section will not be written to the stream.
1276 1288
    GraphWriter& skipNodes() {
1277 1289
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1278 1290
      _skip_nodes = true;
1279 1291
      return *this;
1280 1292
    }
1281 1293

	
1282 1294
    /// \brief Skip writing edge set
1283 1295
    ///
1284 1296
    /// The \c \@edges section will not be written to the stream.
1285 1297
    GraphWriter& skipEdges() {
1286 1298
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1287 1299
      _skip_edges = true;
1288 1300
      return *this;
1289 1301
    }
1290 1302

	
1291 1303
    /// @}
1292 1304

	
1293 1305
  private:
1294 1306

	
1295 1307
    void writeNodes() {
1296 1308
      _writer_bits::MapStorageBase<Node>* label = 0;
1297 1309
      for (typename NodeMaps::iterator it = _node_maps.begin();
1298 1310
           it != _node_maps.end(); ++it) {
1299 1311
        if (it->first == "label") {
1300 1312
          label = it->second;
1301 1313
          break;
1302 1314
        }
1303 1315
      }
1304 1316

	
1305 1317
      *_os << "@nodes";
1306 1318
      if (!_nodes_caption.empty()) {
1307 1319
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1308 1320
      }
1309 1321
      *_os << std::endl;
1310 1322

	
1311 1323
      if (label == 0) {
1312 1324
        *_os << "label" << '\t';
1313 1325
      }
1314 1326
      for (typename NodeMaps::iterator it = _node_maps.begin();
1315 1327
           it != _node_maps.end(); ++it) {
1316 1328
        _writer_bits::writeToken(*_os, it->first) << '\t';
1317 1329
      }
1318 1330
      *_os << std::endl;
1319 1331

	
1320 1332
      std::vector<Node> nodes;
1321 1333
      for (NodeIt n(_graph); n != INVALID; ++n) {
1322 1334
        nodes.push_back(n);
1323 1335
      }
1324 1336

	
1325 1337
      if (label == 0) {
1326 1338
        IdMap<Graph, Node> id_map(_graph);
1327 1339
        _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1328 1340
        std::sort(nodes.begin(), nodes.end(), id_less);
1329 1341
      } else {
1330 1342
        label->sort(nodes);
1331 1343
      }
1332 1344

	
1333 1345
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1334 1346
        Node n = nodes[i];
1335 1347
        if (label == 0) {
1336 1348
          std::ostringstream os;
1337 1349
          os << _graph.id(n);
1338 1350
          _writer_bits::writeToken(*_os, os.str());
1339 1351
          *_os << '\t';
1340 1352
          _node_index.insert(std::make_pair(n, os.str()));
1341 1353
        }
1342 1354
        for (typename NodeMaps::iterator it = _node_maps.begin();
1343 1355
             it != _node_maps.end(); ++it) {
1344 1356
          std::string value = it->second->get(n);
1345 1357
          _writer_bits::writeToken(*_os, value);
1346 1358
          if (it->first == "label") {
1347 1359
            _node_index.insert(std::make_pair(n, value));
1348 1360
          }
1349 1361
          *_os << '\t';
1350 1362
        }
1351 1363
        *_os << std::endl;
1352 1364
      }
1353 1365
    }
1354 1366

	
1355 1367
    void createNodeIndex() {
1356 1368
      _writer_bits::MapStorageBase<Node>* label = 0;
1357 1369
      for (typename NodeMaps::iterator it = _node_maps.begin();
1358 1370
           it != _node_maps.end(); ++it) {
1359 1371
        if (it->first == "label") {
1360 1372
          label = it->second;
1361 1373
          break;
1362 1374
        }
1363 1375
      }
1364 1376

	
1365 1377
      if (label == 0) {
1366 1378
        for (NodeIt n(_graph); n != INVALID; ++n) {
1367 1379
          std::ostringstream os;
1368 1380
          os << _graph.id(n);
1369 1381
          _node_index.insert(std::make_pair(n, os.str()));
1370 1382
        }
1371 1383
      } else {
1372 1384
        for (NodeIt n(_graph); n != INVALID; ++n) {
1373 1385
          std::string value = label->get(n);
1374 1386
          _node_index.insert(std::make_pair(n, value));
1375 1387
        }
1376 1388
      }
1377 1389
    }
1378 1390

	
1379 1391
    void writeEdges() {
1380 1392
      _writer_bits::MapStorageBase<Edge>* label = 0;
1381 1393
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1382 1394
           it != _edge_maps.end(); ++it) {
1383 1395
        if (it->first == "label") {
1384 1396
          label = it->second;
1385 1397
          break;
1386 1398
        }
1387 1399
      }
1388 1400

	
1389 1401
      *_os << "@edges";
1390 1402
      if (!_edges_caption.empty()) {
1391 1403
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
1392 1404
      }
1393 1405
      *_os << std::endl;
1394 1406

	
1395 1407
      *_os << '\t' << '\t';
1396 1408
      if (label == 0) {
1397 1409
        *_os << "label" << '\t';
1398 1410
      }
1399 1411
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1400 1412
           it != _edge_maps.end(); ++it) {
1401 1413
        _writer_bits::writeToken(*_os, it->first) << '\t';
1402 1414
      }
1403 1415
      *_os << std::endl;
1404 1416

	
1405 1417
      std::vector<Edge> edges;
1406 1418
      for (EdgeIt n(_graph); n != INVALID; ++n) {
1407 1419
        edges.push_back(n);
1408 1420
      }
1409 1421

	
1410 1422
      if (label == 0) {
1411 1423
        IdMap<Graph, Edge> id_map(_graph);
1412 1424
        _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1413 1425
        std::sort(edges.begin(), edges.end(), id_less);
1414 1426
      } else {
1415 1427
        label->sort(edges);
1416 1428
      }
1417 1429

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

	
1446 1458
    void createEdgeIndex() {
1447 1459
      _writer_bits::MapStorageBase<Edge>* label = 0;
1448 1460
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1449 1461
           it != _edge_maps.end(); ++it) {
1450 1462
        if (it->first == "label") {
1451 1463
          label = it->second;
1452 1464
          break;
1453 1465
        }
1454 1466
      }
1455 1467

	
1456 1468
      if (label == 0) {
1457 1469
        for (EdgeIt e(_graph); e != INVALID; ++e) {
1458 1470
          std::ostringstream os;
1459 1471
          os << _graph.id(e);
1460 1472
          _edge_index.insert(std::make_pair(e, os.str()));
1461 1473
        }
1462 1474
      } else {
1463 1475
        for (EdgeIt e(_graph); e != INVALID; ++e) {
1464 1476
          std::string value = label->get(e);
1465 1477
          _edge_index.insert(std::make_pair(e, value));
1466 1478
        }
1467 1479
      }
1468 1480
    }
1469 1481

	
1470 1482
    void writeAttributes() {
1471 1483
      if (_attributes.empty()) return;
1472 1484
      *_os << "@attributes";
1473 1485
      if (!_attributes_caption.empty()) {
1474 1486
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1475 1487
      }
1476 1488
      *_os << std::endl;
1477 1489
      for (typename Attributes::iterator it = _attributes.begin();
1478 1490
           it != _attributes.end(); ++it) {
1479 1491
        _writer_bits::writeToken(*_os, it->first) << ' ';
1480 1492
        _writer_bits::writeToken(*_os, it->second->get());
1481 1493
        *_os << std::endl;
1482 1494
      }
1483 1495
    }
1484 1496

	
1485 1497
  public:
1486 1498

	
1487 1499
    /// \name Execution of the writer
1488 1500
    /// @{
1489 1501

	
1490 1502
    /// \brief Start the batch processing
1491 1503
    ///
1492 1504
    /// This function starts the batch processing.
1493 1505
    void run() {
1494 1506
      if (!_skip_nodes) {
1495 1507
        writeNodes();
1496 1508
      } else {
1497 1509
        createNodeIndex();
1498 1510
      }
1499 1511
      if (!_skip_edges) {
1500 1512
        writeEdges();
1501 1513
      } else {
1502 1514
        createEdgeIndex();
1503 1515
      }
1504 1516
      writeAttributes();
1505 1517
    }
1506 1518

	
1507 1519
    /// \brief Give back the stream of the writer
1508 1520
    ///
1509 1521
    /// Give back the stream of the writer
1510 1522
    std::ostream& ostream() {
1511 1523
      return *_os;
1512 1524
    }
1513 1525

	
1514 1526
    /// @}
1515 1527
  };
1516 1528

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

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

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

	
1548 1560
  class SectionWriter;
1549 1561

	
1550 1562
  SectionWriter sectionWriter(std::istream& is);
1551 1563
  SectionWriter sectionWriter(const std::string& fn);
1552 1564
  SectionWriter sectionWriter(const char* fn);
1553 1565

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

	
1568 1580
    std::ostream* _os;
1569 1581
    bool local_os;
1570 1582

	
1571 1583
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1572 1584
    Sections;
1573 1585

	
1574 1586
    Sections _sections;
1575 1587

	
1576 1588
  public:
1577 1589

	
1578 1590
    /// \brief Constructor
1579 1591
    ///
1580 1592
    /// Construct a section writer, which writes to the given output
1581 1593
    /// stream.
1582 1594
    SectionWriter(std::ostream& os)
1583 1595
      : _os(&os), local_os(false) {}
1584 1596

	
1585 1597
    /// \brief Constructor
1586 1598
    ///
1587 1599
    /// Construct a section writer, which writes into the given file.
1588 1600
    SectionWriter(const std::string& fn)
1589 1601
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
1590
      if (!(*_os)) throw IoError("Cannot write file", fn);
1602
      if (!(*_os)) {
1603
        delete _os;
1604
        throw IoError("Cannot write file", fn);
1605
      }
1591 1606
    }
1592 1607

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

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

	
1608 1626
      if (local_os) {
1609 1627
        delete _os;
1610 1628
      }
1611 1629

	
1612 1630
    }
1613 1631

	
1614 1632
  private:
1615 1633

	
1616 1634
    friend SectionWriter sectionWriter(std::ostream& os);
1617 1635
    friend SectionWriter sectionWriter(const std::string& fn);
1618 1636
    friend SectionWriter sectionWriter(const char* fn);
1619 1637

	
1620 1638
    SectionWriter(SectionWriter& other)
1621 1639
      : _os(other._os), local_os(other.local_os) {
1622 1640

	
1623 1641
      other._os = 0;
1624 1642
      other.local_os = false;
1625 1643

	
1626 1644
      _sections.swap(other._sections);
1627 1645
    }
1628 1646

	
1629 1647
    SectionWriter& operator=(const SectionWriter&);
1630 1648

	
1631 1649
  public:
1632 1650

	
1633 1651
    /// \name Section writers
1634 1652
    /// @{
1635 1653

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

	
1680 1698

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

	
1695 1713
    /// @}
1696 1714

	
1697 1715
  public:
1698 1716

	
1699 1717

	
1700 1718
    /// \name Execution of the writer
1701 1719
    /// @{
1702 1720

	
1703 1721
    /// \brief Start the batch processing
1704 1722
    ///
1705 1723
    /// This function starts the batch processing.
1706 1724
    void run() {
1707 1725

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

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

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

	
1724 1742
    /// @}
1725 1743

	
1726 1744
  };
1727 1745

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

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

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

	
1756 1774
#endif
0 comments (0 inline)