gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge bugfix #193
0 1 0
merge 1.0
0 files changed with 12 insertions and 4 deletions:
↑ Collapse diff ↑
Ignore white space 3072 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/core.h>
35 35

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

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

	
41 41
namespace lemon {
42 42

	
43 43
  namespace _reader_bits {
44 44

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

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

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

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

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

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

	
80 80
    };
81 81

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
332 332
      Functor _functor;
333 333

	
334 334
    public:
335 335

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

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

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

	
364 364
      Functor _functor;
365 365

	
366 366
    public:
367 367

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

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

	
388 388
  }
389 389

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

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

	
404 404
  /// \brief Return a \ref DigraphReader class
405 405
  ///
406 406
  /// This function just returns a \ref DigraphReader class.
407 407
  /// \relates DigraphReader
408 408
  template <typename Digraph>
409 409
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
410 410
                                       const std::string& fn) {
411 411
    DigraphReader<Digraph> tmp(digraph, fn);
412 412
    return tmp;
413 413
  }
414 414

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

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

	
479 479
    typedef _Digraph Digraph;
480 480
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
481 481

	
482 482
  private:
483 483

	
484 484

	
485 485
    std::istream* _is;
486 486
    bool local_is;
487 487
    std::string _filename;
488 488

	
489 489
    Digraph& _digraph;
490 490

	
491 491
    std::string _nodes_caption;
492 492
    std::string _arcs_caption;
493 493
    std::string _attributes_caption;
494 494

	
495 495
    typedef std::map<std::string, Node> NodeIndex;
496 496
    NodeIndex _node_index;
497 497
    typedef std::map<std::string, Arc> ArcIndex;
498 498
    ArcIndex _arc_index;
499 499

	
500 500
    typedef std::vector<std::pair<std::string,
501 501
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
502 502
    NodeMaps _node_maps;
503 503

	
504 504
    typedef std::vector<std::pair<std::string,
505 505
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
506 506
    ArcMaps _arc_maps;
507 507

	
508 508
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
509 509
      Attributes;
510 510
    Attributes _attributes;
511 511

	
512 512
    bool _use_nodes;
513 513
    bool _use_arcs;
514 514

	
515 515
    bool _skip_nodes;
516 516
    bool _skip_arcs;
517 517

	
518 518
    int line_num;
519 519
    std::istringstream line;
520 520

	
521 521
  public:
522 522

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

	
532 532
    /// \brief Constructor
533 533
    ///
534 534
    /// Construct a directed graph reader, which reads from the given
535 535
    /// file.
536 536
    DigraphReader(Digraph& digraph, const std::string& fn)
537 537
      : _is(new std::ifstream(fn.c_str())), local_is(true),
538 538
        _filename(fn), _digraph(digraph),
539 539
        _use_nodes(false), _use_arcs(false),
540 540
        _skip_nodes(false), _skip_arcs(false) {
541 541
      if (!(*_is)) {
542 542
        delete _is;
543 543
        throw IoError("Cannot open file", fn);
544 544
      }
545 545
    }
546 546

	
547 547
    /// \brief Constructor
548 548
    ///
549 549
    /// Construct a directed graph reader, which reads from the given
550 550
    /// file.
551 551
    DigraphReader(Digraph& digraph, const char* fn)
552 552
      : _is(new std::ifstream(fn)), local_is(true),
553 553
        _filename(fn), _digraph(digraph),
554 554
        _use_nodes(false), _use_arcs(false),
555 555
        _skip_nodes(false), _skip_arcs(false) {
556 556
      if (!(*_is)) {
557 557
        delete _is;
558 558
        throw IoError("Cannot open file", fn);
559 559
      }
560 560
    }
561 561

	
562 562
    /// \brief Destructor
563 563
    ~DigraphReader() {
564 564
      for (typename NodeMaps::iterator it = _node_maps.begin();
565 565
           it != _node_maps.end(); ++it) {
566 566
        delete it->second;
567 567
      }
568 568

	
569 569
      for (typename ArcMaps::iterator it = _arc_maps.begin();
570 570
           it != _arc_maps.end(); ++it) {
571 571
        delete it->second;
572 572
      }
573 573

	
574 574
      for (typename Attributes::iterator it = _attributes.begin();
575 575
           it != _attributes.end(); ++it) {
576 576
        delete it->second;
577 577
      }
578 578

	
579 579
      if (local_is) {
580 580
        delete _is;
581 581
      }
582 582

	
583 583
    }
584 584

	
585 585
  private:
586 586

	
587 587
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
588 588
                                                  std::istream& is);
589 589
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
590 590
                                                  const std::string& fn);
591 591
    friend DigraphReader<Digraph> digraphReader<>(Digraph& digraph,
592 592
                                                  const char *fn);
593 593

	
594 594
    DigraphReader(DigraphReader& other)
595 595
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
596 596
        _use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
597 597
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
598 598

	
599 599
      other._is = 0;
600 600
      other.local_is = false;
601 601

	
602 602
      _node_index.swap(other._node_index);
603 603
      _arc_index.swap(other._arc_index);
604 604

	
605 605
      _node_maps.swap(other._node_maps);
606 606
      _arc_maps.swap(other._arc_maps);
607 607
      _attributes.swap(other._attributes);
608 608

	
609 609
      _nodes_caption = other._nodes_caption;
610 610
      _arcs_caption = other._arcs_caption;
611 611
      _attributes_caption = other._attributes_caption;
612 612

	
613 613
    }
614 614

	
615 615
    DigraphReader& operator=(const DigraphReader&);
616 616

	
617 617
  public:
618 618

	
619 619
    /// \name Reading rules
620 620
    /// @{
621 621

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

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

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

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

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

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

	
698 698
    /// \brief Node reading rule
699 699
    ///
700 700
    /// Add a node reading rule to reader.
701 701
    DigraphReader& node(const std::string& caption, Node& node) {
702 702
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
703 703
      Converter converter(_node_index);
704 704
      _reader_bits::ValueStorageBase* storage =
705 705
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
706 706
      _attributes.insert(std::make_pair(caption, storage));
707 707
      return *this;
708 708
    }
709 709

	
710 710
    /// \brief Arc reading rule
711 711
    ///
712 712
    /// Add an arc reading rule to reader.
713 713
    DigraphReader& arc(const std::string& caption, Arc& arc) {
714 714
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
715 715
      Converter converter(_arc_index);
716 716
      _reader_bits::ValueStorageBase* storage =
717 717
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
718 718
      _attributes.insert(std::make_pair(caption, storage));
719 719
      return *this;
720 720
    }
721 721

	
722 722
    /// @}
723 723

	
724 724
    /// \name Select section by name
725 725
    /// @{
726 726

	
727 727
    /// \brief Set \c \@nodes section to be read
728 728
    ///
729 729
    /// Set \c \@nodes section to be read
730 730
    DigraphReader& nodes(const std::string& caption) {
731 731
      _nodes_caption = caption;
732 732
      return *this;
733 733
    }
734 734

	
735 735
    /// \brief Set \c \@arcs section to be read
736 736
    ///
737 737
    /// Set \c \@arcs section to be read
738 738
    DigraphReader& arcs(const std::string& caption) {
739 739
      _arcs_caption = caption;
740 740
      return *this;
741 741
    }
742 742

	
743 743
    /// \brief Set \c \@attributes section to be read
744 744
    ///
745 745
    /// Set \c \@attributes section to be read
746 746
    DigraphReader& attributes(const std::string& caption) {
747 747
      _attributes_caption = caption;
748 748
      return *this;
749 749
    }
750 750

	
751 751
    /// @}
752 752

	
753 753
    /// \name Using previously constructed node or arc set
754 754
    /// @{
755 755

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

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

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

	
805 805
    /// \brief Use previously constructed arc set
806 806
    ///
807 807
    /// Use previously constructed arc set, and specify the arc
808 808
    /// label map and a functor which converts the label map values to
809 809
    /// \c std::string.
810 810
    template <typename Map, typename Converter>
811 811
    DigraphReader& useArcs(const Map& map,
812 812
                           const Converter& converter = Converter()) {
813 813
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
814 814
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
815 815
      _use_arcs = true;
816 816
      for (ArcIt a(_digraph); a != INVALID; ++a) {
817 817
        _arc_index.insert(std::make_pair(converter(map[a]), a));
818 818
      }
819 819
      return *this;
820 820
    }
821 821

	
822 822
    /// \brief Skips the reading of node section
823 823
    ///
824 824
    /// Omit the reading of the node section. This implies that each node
825 825
    /// map reading rule will be abandoned, and the nodes of the graph
826 826
    /// will not be constructed, which usually cause that the arc set
827 827
    /// could not be read due to lack of node name resolving.
828 828
    /// Therefore \c skipArcs() function should also be used, or
829 829
    /// \c useNodes() should be used to specify the label of the nodes.
830 830
    DigraphReader& skipNodes() {
831 831
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
832 832
      _skip_nodes = true;
833 833
      return *this;
834 834
    }
835 835

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

	
847 847
    /// @}
848 848

	
849 849
  private:
850 850

	
851 851
    bool readLine() {
852 852
      std::string str;
853 853
      while(++line_num, std::getline(*_is, str)) {
854 854
        line.clear(); line.str(str);
855 855
        char c;
856 856
        if (line >> std::ws >> c && c != '#') {
857 857
          line.putback(c);
858 858
          return true;
859 859
        }
860 860
      }
861 861
      return false;
862 862
    }
863 863

	
864 864
    bool readSuccess() {
865 865
      return static_cast<bool>(*_is);
866 866
    }
867 867

	
868 868
    void skipSection() {
869 869
      char c;
870 870
      while (readSuccess() && line >> c && c != '@') {
871 871
        readLine();
872 872
      }
873
      line.putback(c);
873
      if (readSuccess()) {
874
        line.putback(c);
875
      }
874 876
    }
875 877

	
876 878
    void readNodes() {
877 879

	
878 880
      std::vector<int> map_index(_node_maps.size());
879 881
      int map_num, label_index;
880 882

	
881 883
      char c;
882 884
      if (!readLine() || !(line >> c) || c == '@') {
883 885
        if (readSuccess() && line) line.putback(c);
884 886
        if (!_node_maps.empty())
885 887
          throw FormatError("Cannot find map names");
886 888
        return;
887 889
      }
888 890
      line.putback(c);
889 891

	
890 892
      {
891 893
        std::map<std::string, int> maps;
892 894

	
893 895
        std::string map;
894 896
        int index = 0;
895 897
        while (_reader_bits::readToken(line, map)) {
896 898
          if (maps.find(map) != maps.end()) {
897 899
            std::ostringstream msg;
898 900
            msg << "Multiple occurence of node map: " << map;
899 901
            throw FormatError(msg.str());
900 902
          }
901 903
          maps.insert(std::make_pair(map, index));
902 904
          ++index;
903 905
        }
904 906

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

	
916 918
        {
917 919
          std::map<std::string, int>::iterator jt = maps.find("label");
918 920
          if (jt != maps.end()) {
919 921
            label_index = jt->second;
920 922
          } else {
921 923
            label_index = -1;
922 924
          }
923 925
        }
924 926
        map_num = maps.size();
925 927
      }
926 928

	
927 929
      while (readLine() && line >> c && c != '@') {
928 930
        line.putback(c);
929 931

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

	
941 943
        Node n;
942 944
        if (!_use_nodes) {
943 945
          n = _digraph.addNode();
944 946
          if (label_index != -1)
945 947
            _node_index.insert(std::make_pair(tokens[label_index], n));
946 948
        } else {
947 949
          if (label_index == -1)
948 950
            throw FormatError("Label map not found");
949 951
          typename std::map<std::string, Node>::iterator it =
950 952
            _node_index.find(tokens[label_index]);
951 953
          if (it == _node_index.end()) {
952 954
            std::ostringstream msg;
953 955
            msg << "Node with label not found: " << tokens[label_index];
954 956
            throw FormatError(msg.str());
955 957
          }
956 958
          n = it->second;
957 959
        }
958 960

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

	
963 965
      }
964 966
      if (readSuccess()) {
965 967
        line.putback(c);
966 968
      }
967 969
    }
968 970

	
969 971
    void readArcs() {
970 972

	
971 973
      std::vector<int> map_index(_arc_maps.size());
972 974
      int map_num, label_index;
973 975

	
974 976
      char c;
975 977
      if (!readLine() || !(line >> c) || c == '@') {
976 978
        if (readSuccess() && line) line.putback(c);
977 979
        if (!_arc_maps.empty())
978 980
          throw FormatError("Cannot find map names");
979 981
        return;
980 982
      }
981 983
      line.putback(c);
982 984

	
983 985
      {
984 986
        std::map<std::string, int> maps;
985 987

	
986 988
        std::string map;
987 989
        int index = 0;
988 990
        while (_reader_bits::readToken(line, map)) {
989 991
          if (maps.find(map) != maps.end()) {
990 992
            std::ostringstream msg;
991 993
            msg << "Multiple occurence of arc map: " << map;
992 994
            throw FormatError(msg.str());
993 995
          }
994 996
          maps.insert(std::make_pair(map, index));
995 997
          ++index;
996 998
        }
997 999

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

	
1009 1011
        {
1010 1012
          std::map<std::string, int>::iterator jt = maps.find("label");
1011 1013
          if (jt != maps.end()) {
1012 1014
            label_index = jt->second;
1013 1015
          } else {
1014 1016
            label_index = -1;
1015 1017
          }
1016 1018
        }
1017 1019
        map_num = maps.size();
1018 1020
      }
1019 1021

	
1020 1022
      while (readLine() && line >> c && c != '@') {
1021 1023
        line.putback(c);
1022 1024

	
1023 1025
        std::string source_token;
1024 1026
        std::string target_token;
1025 1027

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

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

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

	
1043 1045
        Arc a;
1044 1046
        if (!_use_arcs) {
1045 1047

	
1046 1048
          typename NodeIndex::iterator it;
1047 1049

	
1048 1050
          it = _node_index.find(source_token);
1049 1051
          if (it == _node_index.end()) {
1050 1052
            std::ostringstream msg;
1051 1053
            msg << "Item not found: " << source_token;
1052 1054
            throw FormatError(msg.str());
1053 1055
          }
1054 1056
          Node source = it->second;
1055 1057

	
1056 1058
          it = _node_index.find(target_token);
1057 1059
          if (it == _node_index.end()) {
1058 1060
            std::ostringstream msg;
1059 1061
            msg << "Item not found: " << target_token;
1060 1062
            throw FormatError(msg.str());
1061 1063
          }
1062 1064
          Node target = it->second;
1063 1065

	
1064 1066
          a = _digraph.addArc(source, target);
1065 1067
          if (label_index != -1)
1066 1068
            _arc_index.insert(std::make_pair(tokens[label_index], a));
1067 1069
        } else {
1068 1070
          if (label_index == -1)
1069 1071
            throw FormatError("Label map not found");
1070 1072
          typename std::map<std::string, Arc>::iterator it =
1071 1073
            _arc_index.find(tokens[label_index]);
1072 1074
          if (it == _arc_index.end()) {
1073 1075
            std::ostringstream msg;
1074 1076
            msg << "Arc with label not found: " << tokens[label_index];
1075 1077
            throw FormatError(msg.str());
1076 1078
          }
1077 1079
          a = it->second;
1078 1080
        }
1079 1081

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

	
1084 1086
      }
1085 1087
      if (readSuccess()) {
1086 1088
        line.putback(c);
1087 1089
      }
1088 1090
    }
1089 1091

	
1090 1092
    void readAttributes() {
1091 1093

	
1092 1094
      std::set<std::string> read_attr;
1093 1095

	
1094 1096
      char c;
1095 1097
      while (readLine() && line >> c && c != '@') {
1096 1098
        line.putback(c);
1097 1099

	
1098 1100
        std::string attr, token;
1099 1101
        if (!_reader_bits::readToken(line, attr))
1100 1102
          throw FormatError("Attribute name not found");
1101 1103
        if (!_reader_bits::readToken(line, token))
1102 1104
          throw FormatError("Attribute value not found");
1103 1105
        if (line >> c)
1104 1106
          throw FormatError("Extra character at the end of line");
1105 1107

	
1106 1108
        {
1107 1109
          std::set<std::string>::iterator it = read_attr.find(attr);
1108 1110
          if (it != read_attr.end()) {
1109 1111
            std::ostringstream msg;
1110 1112
            msg << "Multiple occurence of attribute: " << attr;
1111 1113
            throw FormatError(msg.str());
1112 1114
          }
1113 1115
          read_attr.insert(attr);
1114 1116
        }
1115 1117

	
1116 1118
        {
1117 1119
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1118 1120
          while (it != _attributes.end() && it->first == attr) {
1119 1121
            it->second->set(token);
1120 1122
            ++it;
1121 1123
          }
1122 1124
        }
1123 1125

	
1124 1126
      }
1125 1127
      if (readSuccess()) {
1126 1128
        line.putback(c);
1127 1129
      }
1128 1130
      for (typename Attributes::iterator it = _attributes.begin();
1129 1131
           it != _attributes.end(); ++it) {
1130 1132
        if (read_attr.find(it->first) == read_attr.end()) {
1131 1133
          std::ostringstream msg;
1132 1134
          msg << "Attribute not found: " << it->first;
1133 1135
          throw FormatError(msg.str());
1134 1136
        }
1135 1137
      }
1136 1138
    }
1137 1139

	
1138 1140
  public:
1139 1141

	
1140 1142
    /// \name Execution of the reader
1141 1143
    /// @{
1142 1144

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

	
1149 1151
      bool nodes_done = _skip_nodes;
1150 1152
      bool arcs_done = _skip_arcs;
1151 1153
      bool attributes_done = false;
1152 1154

	
1153 1155
      line_num = 0;
1154 1156
      readLine();
1155 1157
      skipSection();
1156 1158

	
1157 1159
      while (readSuccess()) {
1158 1160
        try {
1159 1161
          char c;
1160 1162
          std::string section, caption;
1161 1163
          line >> c;
1162 1164
          _reader_bits::readToken(line, section);
1163 1165
          _reader_bits::readToken(line, caption);
1164 1166

	
1165 1167
          if (line >> c)
1166 1168
            throw FormatError("Extra character at the end of line");
1167 1169

	
1168 1170
          if (section == "nodes" && !nodes_done) {
1169 1171
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1170 1172
              readNodes();
1171 1173
              nodes_done = true;
1172 1174
            }
1173 1175
          } else if ((section == "arcs" || section == "edges") &&
1174 1176
                     !arcs_done) {
1175 1177
            if (_arcs_caption.empty() || _arcs_caption == caption) {
1176 1178
              readArcs();
1177 1179
              arcs_done = true;
1178 1180
            }
1179 1181
          } else if (section == "attributes" && !attributes_done) {
1180 1182
            if (_attributes_caption.empty() || _attributes_caption == caption) {
1181 1183
              readAttributes();
1182 1184
              attributes_done = true;
1183 1185
            }
1184 1186
          } else {
1185 1187
            readLine();
1186 1188
            skipSection();
1187 1189
          }
1188 1190
        } catch (FormatError& error) {
1189 1191
          error.line(line_num);
1190 1192
          error.file(_filename);
1191 1193
          throw;
1192 1194
        }
1193 1195
      }
1194 1196

	
1195 1197
      if (!nodes_done) {
1196 1198
        throw FormatError("Section @nodes not found");
1197 1199
      }
1198 1200

	
1199 1201
      if (!arcs_done) {
1200 1202
        throw FormatError("Section @arcs not found");
1201 1203
      }
1202 1204

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

	
1207 1209
    }
1208 1210

	
1209 1211
    /// @}
1210 1212

	
1211 1213
  };
1212 1214

	
1213 1215
  template <typename Graph>
1214 1216
  class GraphReader;
1215 1217

	
1216 1218
  /// \brief Return a \ref GraphReader class
1217 1219
  ///
1218 1220
  /// This function just returns a \ref GraphReader class.
1219 1221
  /// \relates GraphReader
1220 1222
  template <typename Graph>
1221 1223
  GraphReader<Graph> graphReader(Graph& graph, std::istream& is = std::cin) {
1222 1224
    GraphReader<Graph> tmp(graph, is);
1223 1225
    return tmp;
1224 1226
  }
1225 1227

	
1226 1228
  /// \brief Return a \ref GraphReader class
1227 1229
  ///
1228 1230
  /// This function just returns a \ref GraphReader class.
1229 1231
  /// \relates GraphReader
1230 1232
  template <typename Graph>
1231 1233
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn) {
1232 1234
    GraphReader<Graph> tmp(graph, fn);
1233 1235
    return tmp;
1234 1236
  }
1235 1237

	
1236 1238
  /// \brief Return a \ref GraphReader class
1237 1239
  ///
1238 1240
  /// This function just returns a \ref GraphReader class.
1239 1241
  /// \relates GraphReader
1240 1242
  template <typename Graph>
1241 1243
  GraphReader<Graph> graphReader(Graph& graph, const char* fn) {
1242 1244
    GraphReader<Graph> tmp(graph, fn);
1243 1245
    return tmp;
1244 1246
  }
1245 1247

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

	
1265 1267
    typedef _Graph Graph;
1266 1268
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1267 1269

	
1268 1270
  private:
1269 1271

	
1270 1272
    std::istream* _is;
1271 1273
    bool local_is;
1272 1274
    std::string _filename;
1273 1275

	
1274 1276
    Graph& _graph;
1275 1277

	
1276 1278
    std::string _nodes_caption;
1277 1279
    std::string _edges_caption;
1278 1280
    std::string _attributes_caption;
1279 1281

	
1280 1282
    typedef std::map<std::string, Node> NodeIndex;
1281 1283
    NodeIndex _node_index;
1282 1284
    typedef std::map<std::string, Edge> EdgeIndex;
1283 1285
    EdgeIndex _edge_index;
1284 1286

	
1285 1287
    typedef std::vector<std::pair<std::string,
1286 1288
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
1287 1289
    NodeMaps _node_maps;
1288 1290

	
1289 1291
    typedef std::vector<std::pair<std::string,
1290 1292
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1291 1293
    EdgeMaps _edge_maps;
1292 1294

	
1293 1295
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1294 1296
      Attributes;
1295 1297
    Attributes _attributes;
1296 1298

	
1297 1299
    bool _use_nodes;
1298 1300
    bool _use_edges;
1299 1301

	
1300 1302
    bool _skip_nodes;
1301 1303
    bool _skip_edges;
1302 1304

	
1303 1305
    int line_num;
1304 1306
    std::istringstream line;
1305 1307

	
1306 1308
  public:
1307 1309

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

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

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

	
1347 1349
    /// \brief Destructor
1348 1350
    ~GraphReader() {
1349 1351
      for (typename NodeMaps::iterator it = _node_maps.begin();
1350 1352
           it != _node_maps.end(); ++it) {
1351 1353
        delete it->second;
1352 1354
      }
1353 1355

	
1354 1356
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1355 1357
           it != _edge_maps.end(); ++it) {
1356 1358
        delete it->second;
1357 1359
      }
1358 1360

	
1359 1361
      for (typename Attributes::iterator it = _attributes.begin();
1360 1362
           it != _attributes.end(); ++it) {
1361 1363
        delete it->second;
1362 1364
      }
1363 1365

	
1364 1366
      if (local_is) {
1365 1367
        delete _is;
1366 1368
      }
1367 1369

	
1368 1370
    }
1369 1371

	
1370 1372
  private:
1371 1373
    friend GraphReader<Graph> graphReader<>(Graph& graph, std::istream& is);
1372 1374
    friend GraphReader<Graph> graphReader<>(Graph& graph,
1373 1375
                                            const std::string& fn);
1374 1376
    friend GraphReader<Graph> graphReader<>(Graph& graph, const char *fn);
1375 1377

	
1376 1378
    GraphReader(GraphReader& other)
1377 1379
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1378 1380
        _use_nodes(other._use_nodes), _use_edges(other._use_edges),
1379 1381
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1380 1382

	
1381 1383
      other._is = 0;
1382 1384
      other.local_is = false;
1383 1385

	
1384 1386
      _node_index.swap(other._node_index);
1385 1387
      _edge_index.swap(other._edge_index);
1386 1388

	
1387 1389
      _node_maps.swap(other._node_maps);
1388 1390
      _edge_maps.swap(other._edge_maps);
1389 1391
      _attributes.swap(other._attributes);
1390 1392

	
1391 1393
      _nodes_caption = other._nodes_caption;
1392 1394
      _edges_caption = other._edges_caption;
1393 1395
      _attributes_caption = other._attributes_caption;
1394 1396

	
1395 1397
    }
1396 1398

	
1397 1399
    GraphReader& operator=(const GraphReader&);
1398 1400

	
1399 1401
  public:
1400 1402

	
1401 1403
    /// \name Reading rules
1402 1404
    /// @{
1403 1405

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

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

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

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

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

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

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

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

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

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

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

	
1550 1552
    /// @}
1551 1553

	
1552 1554
    /// \name Select section by name
1553 1555
    /// @{
1554 1556

	
1555 1557
    /// \brief Set \c \@nodes section to be read
1556 1558
    ///
1557 1559
    /// Set \c \@nodes section to be read.
1558 1560
    GraphReader& nodes(const std::string& caption) {
1559 1561
      _nodes_caption = caption;
1560 1562
      return *this;
1561 1563
    }
1562 1564

	
1563 1565
    /// \brief Set \c \@edges section to be read
1564 1566
    ///
1565 1567
    /// Set \c \@edges section to be read.
1566 1568
    GraphReader& edges(const std::string& caption) {
1567 1569
      _edges_caption = caption;
1568 1570
      return *this;
1569 1571
    }
1570 1572

	
1571 1573
    /// \brief Set \c \@attributes section to be read
1572 1574
    ///
1573 1575
    /// Set \c \@attributes section to be read.
1574 1576
    GraphReader& attributes(const std::string& caption) {
1575 1577
      _attributes_caption = caption;
1576 1578
      return *this;
1577 1579
    }
1578 1580

	
1579 1581
    /// @}
1580 1582

	
1581 1583
    /// \name Using previously constructed node or edge set
1582 1584
    /// @{
1583 1585

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

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

	
1617 1619
    /// \brief Use previously constructed edge set
1618 1620
    ///
1619 1621
    /// Use previously constructed edge set, and specify the edge
1620 1622
    /// label map.
1621 1623
    template <typename Map>
1622 1624
    GraphReader& useEdges(const Map& map) {
1623 1625
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1624 1626
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1625 1627
      _use_edges = true;
1626 1628
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1627 1629
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1628 1630
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1629 1631
      }
1630 1632
      return *this;
1631 1633
    }
1632 1634

	
1633 1635
    /// \brief Use previously constructed edge set
1634 1636
    ///
1635 1637
    /// Use previously constructed edge set, and specify the edge
1636 1638
    /// label map and a functor which converts the label map values to
1637 1639
    /// \c std::string.
1638 1640
    template <typename Map, typename Converter>
1639 1641
    GraphReader& useEdges(const Map& map,
1640 1642
                            const Converter& converter = Converter()) {
1641 1643
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1642 1644
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1643 1645
      _use_edges = true;
1644 1646
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1645 1647
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1646 1648
      }
1647 1649
      return *this;
1648 1650
    }
1649 1651

	
1650 1652
    /// \brief Skip the reading of node section
1651 1653
    ///
1652 1654
    /// Omit the reading of the node section. This implies that each node
1653 1655
    /// map reading rule will be abandoned, and the nodes of the graph
1654 1656
    /// will not be constructed, which usually cause that the edge set
1655 1657
    /// could not be read due to lack of node name
1656 1658
    /// could not be read due to lack of node name resolving.
1657 1659
    /// Therefore \c skipEdges() function should also be used, or
1658 1660
    /// \c useNodes() should be used to specify the label of the nodes.
1659 1661
    GraphReader& skipNodes() {
1660 1662
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
1661 1663
      _skip_nodes = true;
1662 1664
      return *this;
1663 1665
    }
1664 1666

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

	
1676 1678
    /// @}
1677 1679

	
1678 1680
  private:
1679 1681

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

	
1693 1695
    bool readSuccess() {
1694 1696
      return static_cast<bool>(*_is);
1695 1697
    }
1696 1698

	
1697 1699
    void skipSection() {
1698 1700
      char c;
1699 1701
      while (readSuccess() && line >> c && c != '@') {
1700 1702
        readLine();
1701 1703
      }
1702
      line.putback(c);
1704
      if (readSuccess()) {
1705
        line.putback(c);
1706
      }
1703 1707
    }
1704 1708

	
1705 1709
    void readNodes() {
1706 1710

	
1707 1711
      std::vector<int> map_index(_node_maps.size());
1708 1712
      int map_num, label_index;
1709 1713

	
1710 1714
      char c;
1711 1715
      if (!readLine() || !(line >> c) || c == '@') {
1712 1716
        if (readSuccess() && line) line.putback(c);
1713 1717
        if (!_node_maps.empty())
1714 1718
          throw FormatError("Cannot find map names");
1715 1719
        return;
1716 1720
      }
1717 1721
      line.putback(c);
1718 1722

	
1719 1723
      {
1720 1724
        std::map<std::string, int> maps;
1721 1725

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

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

	
1745 1749
        {
1746 1750
          std::map<std::string, int>::iterator jt = maps.find("label");
1747 1751
          if (jt != maps.end()) {
1748 1752
            label_index = jt->second;
1749 1753
          } else {
1750 1754
            label_index = -1;
1751 1755
          }
1752 1756
        }
1753 1757
        map_num = maps.size();
1754 1758
      }
1755 1759

	
1756 1760
      while (readLine() && line >> c && c != '@') {
1757 1761
        line.putback(c);
1758 1762

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

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

	
1788 1792
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1789 1793
          _node_maps[i].second->set(n, tokens[map_index[i]]);
1790 1794
        }
1791 1795

	
1792 1796
      }
1793 1797
      if (readSuccess()) {
1794 1798
        line.putback(c);
1795 1799
      }
1796 1800
    }
1797 1801

	
1798 1802
    void readEdges() {
1799 1803

	
1800 1804
      std::vector<int> map_index(_edge_maps.size());
1801 1805
      int map_num, label_index;
1802 1806

	
1803 1807
      char c;
1804 1808
      if (!readLine() || !(line >> c) || c == '@') {
1805 1809
        if (readSuccess() && line) line.putback(c);
1806 1810
        if (!_edge_maps.empty())
1807 1811
          throw FormatError("Cannot find map names");
1808 1812
        return;
1809 1813
      }
1810 1814
      line.putback(c);
1811 1815

	
1812 1816
      {
1813 1817
        std::map<std::string, int> maps;
1814 1818

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

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

	
1838 1842
        {
1839 1843
          std::map<std::string, int>::iterator jt = maps.find("label");
1840 1844
          if (jt != maps.end()) {
1841 1845
            label_index = jt->second;
1842 1846
          } else {
1843 1847
            label_index = -1;
1844 1848
          }
1845 1849
        }
1846 1850
        map_num = maps.size();
1847 1851
      }
1848 1852

	
1849 1853
      while (readLine() && line >> c && c != '@') {
1850 1854
        line.putback(c);
1851 1855

	
1852 1856
        std::string source_token;
1853 1857
        std::string target_token;
1854 1858

	
1855 1859
        if (!_reader_bits::readToken(line, source_token))
1856 1860
          throw FormatError("Node u not found");
1857 1861

	
1858 1862
        if (!_reader_bits::readToken(line, target_token))
1859 1863
          throw FormatError("Node v not found");
1860 1864

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

	
1872 1876
        Edge e;
1873 1877
        if (!_use_edges) {
1874 1878

	
1875 1879
          typename NodeIndex::iterator it;
1876 1880

	
1877 1881
          it = _node_index.find(source_token);
1878 1882
          if (it == _node_index.end()) {
1879 1883
            std::ostringstream msg;
1880 1884
            msg << "Item not found: " << source_token;
1881 1885
            throw FormatError(msg.str());
1882 1886
          }
1883 1887
          Node source = it->second;
1884 1888

	
1885 1889
          it = _node_index.find(target_token);
1886 1890
          if (it == _node_index.end()) {
1887 1891
            std::ostringstream msg;
1888 1892
            msg << "Item not found: " << target_token;
1889 1893
            throw FormatError(msg.str());
1890 1894
          }
1891 1895
          Node target = it->second;
1892 1896

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

	
1909 1913
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1910 1914
          _edge_maps[i].second->set(e, tokens[map_index[i]]);
1911 1915
        }
1912 1916

	
1913 1917
      }
1914 1918
      if (readSuccess()) {
1915 1919
        line.putback(c);
1916 1920
      }
1917 1921
    }
1918 1922

	
1919 1923
    void readAttributes() {
1920 1924

	
1921 1925
      std::set<std::string> read_attr;
1922 1926

	
1923 1927
      char c;
1924 1928
      while (readLine() && line >> c && c != '@') {
1925 1929
        line.putback(c);
1926 1930

	
1927 1931
        std::string attr, token;
1928 1932
        if (!_reader_bits::readToken(line, attr))
1929 1933
          throw FormatError("Attribute name not found");
1930 1934
        if (!_reader_bits::readToken(line, token))
1931 1935
          throw FormatError("Attribute value not found");
1932 1936
        if (line >> c)
1933 1937
          throw FormatError("Extra character at the end of line");
1934 1938

	
1935 1939
        {
1936 1940
          std::set<std::string>::iterator it = read_attr.find(attr);
1937 1941
          if (it != read_attr.end()) {
1938 1942
            std::ostringstream msg;
1939 1943
            msg << "Multiple occurence of attribute: " << attr;
1940 1944
            throw FormatError(msg.str());
1941 1945
          }
1942 1946
          read_attr.insert(attr);
1943 1947
        }
1944 1948

	
1945 1949
        {
1946 1950
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1947 1951
          while (it != _attributes.end() && it->first == attr) {
1948 1952
            it->second->set(token);
1949 1953
            ++it;
1950 1954
          }
1951 1955
        }
1952 1956

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

	
1967 1971
  public:
1968 1972

	
1969 1973
    /// \name Execution of the reader
1970 1974
    /// @{
1971 1975

	
1972 1976
    /// \brief Start the batch processing
1973 1977
    ///
1974 1978
    /// This function starts the batch processing
1975 1979
    void run() {
1976 1980

	
1977 1981
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1978 1982

	
1979 1983
      bool nodes_done = _skip_nodes;
1980 1984
      bool edges_done = _skip_edges;
1981 1985
      bool attributes_done = false;
1982 1986

	
1983 1987
      line_num = 0;
1984 1988
      readLine();
1985 1989
      skipSection();
1986 1990

	
1987 1991
      while (readSuccess()) {
1988 1992
        try {
1989 1993
          char c;
1990 1994
          std::string section, caption;
1991 1995
          line >> c;
1992 1996
          _reader_bits::readToken(line, section);
1993 1997
          _reader_bits::readToken(line, caption);
1994 1998

	
1995 1999
          if (line >> c)
1996 2000
            throw FormatError("Extra character at the end of line");
1997 2001

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

	
2025 2029
      if (!nodes_done) {
2026 2030
        throw FormatError("Section @nodes not found");
2027 2031
      }
2028 2032

	
2029 2033
      if (!edges_done) {
2030 2034
        throw FormatError("Section @edges not found");
2031 2035
      }
2032 2036

	
2033 2037
      if (!attributes_done && !_attributes.empty()) {
2034 2038
        throw FormatError("Section @attributes not found");
2035 2039
      }
2036 2040

	
2037 2041
    }
2038 2042

	
2039 2043
    /// @}
2040 2044

	
2041 2045
  };
2042 2046

	
2043 2047
  class SectionReader;
2044 2048

	
2045 2049
  SectionReader sectionReader(std::istream& is);
2046 2050
  SectionReader sectionReader(const std::string& fn);
2047 2051
  SectionReader sectionReader(const char* fn);
2048 2052

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

	
2063 2067
    std::istream* _is;
2064 2068
    bool local_is;
2065 2069
    std::string _filename;
2066 2070

	
2067 2071
    typedef std::map<std::string, _reader_bits::Section*> Sections;
2068 2072
    Sections _sections;
2069 2073

	
2070 2074
    int line_num;
2071 2075
    std::istringstream line;
2072 2076

	
2073 2077
  public:
2074 2078

	
2075 2079
    /// \brief Constructor
2076 2080
    ///
2077 2081
    /// Construct a section reader, which reads from the given input
2078 2082
    /// stream.
2079 2083
    SectionReader(std::istream& is)
2080 2084
      : _is(&is), local_is(false) {}
2081 2085

	
2082 2086
    /// \brief Constructor
2083 2087
    ///
2084 2088
    /// Construct a section reader, which reads from the given file.
2085 2089
    SectionReader(const std::string& fn)
2086 2090
      : _is(new std::ifstream(fn.c_str())), local_is(true),
2087 2091
        _filename(fn) {
2088 2092
      if (!(*_is)) {
2089 2093
        delete _is;
2090 2094
        throw IoError("Cannot open file", fn);
2091 2095
      }
2092 2096
    }
2093 2097

	
2094 2098
    /// \brief Constructor
2095 2099
    ///
2096 2100
    /// Construct a section reader, which reads from the given file.
2097 2101
    SectionReader(const char* fn)
2098 2102
      : _is(new std::ifstream(fn)), local_is(true),
2099 2103
        _filename(fn) {
2100 2104
      if (!(*_is)) {
2101 2105
        delete _is;
2102 2106
        throw IoError("Cannot open file", fn);
2103 2107
      }
2104 2108
    }
2105 2109

	
2106 2110
    /// \brief Destructor
2107 2111
    ~SectionReader() {
2108 2112
      for (Sections::iterator it = _sections.begin();
2109 2113
           it != _sections.end(); ++it) {
2110 2114
        delete it->second;
2111 2115
      }
2112 2116

	
2113 2117
      if (local_is) {
2114 2118
        delete _is;
2115 2119
      }
2116 2120

	
2117 2121
    }
2118 2122

	
2119 2123
  private:
2120 2124

	
2121 2125
    friend SectionReader sectionReader(std::istream& is);
2122 2126
    friend SectionReader sectionReader(const std::string& fn);
2123 2127
    friend SectionReader sectionReader(const char* fn);
2124 2128

	
2125 2129
    SectionReader(SectionReader& other)
2126 2130
      : _is(other._is), local_is(other.local_is) {
2127 2131

	
2128 2132
      other._is = 0;
2129 2133
      other.local_is = false;
2130 2134

	
2131 2135
      _sections.swap(other._sections);
2132 2136
    }
2133 2137

	
2134 2138
    SectionReader& operator=(const SectionReader&);
2135 2139

	
2136 2140
  public:
2137 2141

	
2138 2142
    /// \name Section readers
2139 2143
    /// @{
2140 2144

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

	
2185 2189

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

	
2203 2207
    /// @}
2204 2208

	
2205 2209
  private:
2206 2210

	
2207 2211
    bool readLine() {
2208 2212
      std::string str;
2209 2213
      while(++line_num, std::getline(*_is, str)) {
2210 2214
        line.clear(); line.str(str);
2211 2215
        char c;
2212 2216
        if (line >> std::ws >> c && c != '#') {
2213 2217
          line.putback(c);
2214 2218
          return true;
2215 2219
        }
2216 2220
      }
2217 2221
      return false;
2218 2222
    }
2219 2223

	
2220 2224
    bool readSuccess() {
2221 2225
      return static_cast<bool>(*_is);
2222 2226
    }
2223 2227

	
2224 2228
    void skipSection() {
2225 2229
      char c;
2226 2230
      while (readSuccess() && line >> c && c != '@') {
2227 2231
        readLine();
2228 2232
      }
2229
      line.putback(c);
2233
      if (readSuccess()) {
2234
        line.putback(c);
2235
      }
2230 2236
    }
2231 2237

	
2232 2238
  public:
2233 2239

	
2234 2240

	
2235 2241
    /// \name Execution of the reader
2236 2242
    /// @{
2237 2243

	
2238 2244
    /// \brief Start the batch processing
2239 2245
    ///
2240 2246
    /// This function starts the batch processing.
2241 2247
    void run() {
2242 2248

	
2243 2249
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2244 2250

	
2245 2251
      std::set<std::string> extra_sections;
2246 2252

	
2247 2253
      line_num = 0;
2248 2254
      readLine();
2249 2255
      skipSection();
2250 2256

	
2251 2257
      while (readSuccess()) {
2252 2258
        try {
2253 2259
          char c;
2254 2260
          std::string section, caption;
2255 2261
          line >> c;
2256 2262
          _reader_bits::readToken(line, section);
2257 2263
          _reader_bits::readToken(line, caption);
2258 2264

	
2259 2265
          if (line >> c)
2260 2266
            throw FormatError("Extra character at the end of line");
2261 2267

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

	
2290 2296
    /// @}
2291 2297

	
2292 2298
  };
2293 2299

	
2294 2300
  /// \brief Return a \ref SectionReader class
2295 2301
  ///
2296 2302
  /// This function just returns a \ref SectionReader class.
2297 2303
  /// \relates SectionReader
2298 2304
  inline SectionReader sectionReader(std::istream& is) {
2299 2305
    SectionReader tmp(is);
2300 2306
    return tmp;
2301 2307
  }
2302 2308

	
2303 2309
  /// \brief Return a \ref SectionReader class
2304 2310
  ///
2305 2311
  /// This function just returns a \ref SectionReader class.
2306 2312
  /// \relates SectionReader
2307 2313
  inline SectionReader sectionReader(const std::string& fn) {
2308 2314
    SectionReader tmp(fn);
2309 2315
    return tmp;
2310 2316
  }
2311 2317

	
2312 2318
  /// \brief Return a \ref SectionReader class
2313 2319
  ///
2314 2320
  /// This function just returns a \ref SectionReader class.
2315 2321
  /// \relates SectionReader
2316 2322
  inline SectionReader sectionReader(const char* fn) {
2317 2323
    SectionReader tmp(fn);
2318 2324
    return tmp;
2319 2325
  }
2320 2326

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

	
2352 2358
    std::istream* _is;
2353 2359
    bool local_is;
2354 2360

	
2355 2361
    std::vector<std::string> _node_sections;
2356 2362
    std::vector<std::string> _edge_sections;
2357 2363
    std::vector<std::string> _attribute_sections;
2358 2364
    std::vector<std::string> _extra_sections;
2359 2365

	
2360 2366
    std::vector<bool> _arc_sections;
2361 2367

	
2362 2368
    std::vector<std::vector<std::string> > _node_maps;
2363 2369
    std::vector<std::vector<std::string> > _edge_maps;
2364 2370

	
2365 2371
    std::vector<std::vector<std::string> > _attributes;
2366 2372

	
2367 2373

	
2368 2374
    int line_num;
2369 2375
    std::istringstream line;
2370 2376

	
2371 2377
  public:
2372 2378

	
2373 2379
    /// \brief Constructor
2374 2380
    ///
2375 2381
    /// Construct an \e LGF contents reader, which reads from the given
2376 2382
    /// input stream.
2377 2383
    LgfContents(std::istream& is)
2378 2384
      : _is(&is), local_is(false) {}
2379 2385

	
2380 2386
    /// \brief Constructor
2381 2387
    ///
2382 2388
    /// Construct an \e LGF contents reader, which reads from the given
2383 2389
    /// file.
2384 2390
    LgfContents(const std::string& fn)
2385 2391
      : _is(new std::ifstream(fn.c_str())), local_is(true) {
2386 2392
      if (!(*_is)) {
2387 2393
        delete _is;
2388 2394
        throw IoError("Cannot open file", fn);
2389 2395
      }
2390 2396
    }
2391 2397

	
2392 2398
    /// \brief Constructor
2393 2399
    ///
2394 2400
    /// Construct an \e LGF contents reader, which reads from the given
2395 2401
    /// file.
2396 2402
    LgfContents(const char* fn)
2397 2403
      : _is(new std::ifstream(fn)), local_is(true) {
2398 2404
      if (!(*_is)) {
2399 2405
        delete _is;
2400 2406
        throw IoError("Cannot open file", fn);
2401 2407
      }
2402 2408
    }
2403 2409

	
2404 2410
    /// \brief Destructor
2405 2411
    ~LgfContents() {
2406 2412
      if (local_is) delete _is;
2407 2413
    }
2408 2414

	
2409 2415
  private:
2410 2416

	
2411 2417
    LgfContents(const LgfContents&);
2412 2418
    LgfContents& operator=(const LgfContents&);
2413 2419

	
2414 2420
  public:
2415 2421

	
2416 2422

	
2417 2423
    /// \name Node sections
2418 2424
    /// @{
2419 2425

	
2420 2426
    /// \brief Gives back the number of node sections in the file.
2421 2427
    ///
2422 2428
    /// Gives back the number of node sections in the file.
2423 2429
    int nodeSectionNum() const {
2424 2430
      return _node_sections.size();
2425 2431
    }
2426 2432

	
2427 2433
    /// \brief Returns the node section name at the given position.
2428 2434
    ///
2429 2435
    /// Returns the node section name at the given position.
2430 2436
    const std::string& nodeSection(int i) const {
2431 2437
      return _node_sections[i];
2432 2438
    }
2433 2439

	
2434 2440
    /// \brief Gives back the node maps for the given section.
2435 2441
    ///
2436 2442
    /// Gives back the node maps for the given section.
2437 2443
    const std::vector<std::string>& nodeMapNames(int i) const {
2438 2444
      return _node_maps[i];
2439 2445
    }
2440 2446

	
2441 2447
    /// @}
2442 2448

	
2443 2449
    /// \name Arc/Edge sections
2444 2450
    /// @{
2445 2451

	
2446 2452
    /// \brief Gives back the number of arc/edge sections in the file.
2447 2453
    ///
2448 2454
    /// Gives back the number of arc/edge sections in the file.
2449 2455
    /// \note It is synonym of \c edgeSectionNum().
2450 2456
    int arcSectionNum() const {
2451 2457
      return _edge_sections.size();
2452 2458
    }
2453 2459

	
2454 2460
    /// \brief Returns the arc/edge section name at the given position.
2455 2461
    ///
2456 2462
    /// Returns the arc/edge section name at the given position.
2457 2463
    /// \note It is synonym of \c edgeSection().
2458 2464
    const std::string& arcSection(int i) const {
2459 2465
      return _edge_sections[i];
2460 2466
    }
2461 2467

	
2462 2468
    /// \brief Gives back the arc/edge maps for the given section.
2463 2469
    ///
2464 2470
    /// Gives back the arc/edge maps for the given section.
2465 2471
    /// \note It is synonym of \c edgeMapNames().
2466 2472
    const std::vector<std::string>& arcMapNames(int i) const {
2467 2473
      return _edge_maps[i];
2468 2474
    }
2469 2475

	
2470 2476
    /// @}
2471 2477

	
2472 2478
    /// \name Synonyms
2473 2479
    /// @{
2474 2480

	
2475 2481
    /// \brief Gives back the number of arc/edge sections in the file.
2476 2482
    ///
2477 2483
    /// Gives back the number of arc/edge sections in the file.
2478 2484
    /// \note It is synonym of \c arcSectionNum().
2479 2485
    int edgeSectionNum() const {
2480 2486
      return _edge_sections.size();
2481 2487
    }
2482 2488

	
2483 2489
    /// \brief Returns the section name at the given position.
2484 2490
    ///
2485 2491
    /// Returns the section name at the given position.
2486 2492
    /// \note It is synonym of \c arcSection().
2487 2493
    const std::string& edgeSection(int i) const {
2488 2494
      return _edge_sections[i];
2489 2495
    }
2490 2496

	
2491 2497
    /// \brief Gives back the edge maps for the given section.
2492 2498
    ///
2493 2499
    /// Gives back the edge maps for the given section.
2494 2500
    /// \note It is synonym of \c arcMapNames().
2495 2501
    const std::vector<std::string>& edgeMapNames(int i) const {
2496 2502
      return _edge_maps[i];
2497 2503
    }
2498 2504

	
2499 2505
    /// @}
2500 2506

	
2501 2507
    /// \name Attribute sections
2502 2508
    /// @{
2503 2509

	
2504 2510
    /// \brief Gives back the number of attribute sections in the file.
2505 2511
    ///
2506 2512
    /// Gives back the number of attribute sections in the file.
2507 2513
    int attributeSectionNum() const {
2508 2514
      return _attribute_sections.size();
2509 2515
    }
2510 2516

	
2511 2517
    /// \brief Returns the attribute section name at the given position.
2512 2518
    ///
2513 2519
    /// Returns the attribute section name at the given position.
2514 2520
    const std::string& attributeSectionNames(int i) const {
2515 2521
      return _attribute_sections[i];
2516 2522
    }
2517 2523

	
2518 2524
    /// \brief Gives back the attributes for the given section.
2519 2525
    ///
2520 2526
    /// Gives back the attributes for the given section.
2521 2527
    const std::vector<std::string>& attributes(int i) const {
2522 2528
      return _attributes[i];
2523 2529
    }
2524 2530

	
2525 2531
    /// @}
2526 2532

	
2527 2533
    /// \name Extra sections
2528 2534
    /// @{
2529 2535

	
2530 2536
    /// \brief Gives back the number of extra sections in the file.
2531 2537
    ///
2532 2538
    /// Gives back the number of extra sections in the file.
2533 2539
    int extraSectionNum() const {
2534 2540
      return _extra_sections.size();
2535 2541
    }
2536 2542

	
2537 2543
    /// \brief Returns the extra section type at the given position.
2538 2544
    ///
2539 2545
    /// Returns the section type at the given position.
2540 2546
    const std::string& extraSection(int i) const {
2541 2547
      return _extra_sections[i];
2542 2548
    }
2543 2549

	
2544 2550
    /// @}
2545 2551

	
2546 2552
  private:
2547 2553

	
2548 2554
    bool readLine() {
2549 2555
      std::string str;
2550 2556
      while(++line_num, std::getline(*_is, str)) {
2551 2557
        line.clear(); line.str(str);
2552 2558
        char c;
2553 2559
        if (line >> std::ws >> c && c != '#') {
2554 2560
          line.putback(c);
2555 2561
          return true;
2556 2562
        }
2557 2563
      }
2558 2564
      return false;
2559 2565
    }
2560 2566

	
2561 2567
    bool readSuccess() {
2562 2568
      return static_cast<bool>(*_is);
2563 2569
    }
2564 2570

	
2565 2571
    void skipSection() {
2566 2572
      char c;
2567 2573
      while (readSuccess() && line >> c && c != '@') {
2568 2574
        readLine();
2569 2575
      }
2570
      line.putback(c);
2576
      if (readSuccess()) {
2577
        line.putback(c);
2578
      }
2571 2579
    }
2572 2580

	
2573 2581
    void readMaps(std::vector<std::string>& maps) {
2574 2582
      char c;
2575 2583
      if (!readLine() || !(line >> c) || c == '@') {
2576 2584
        if (readSuccess() && line) line.putback(c);
2577 2585
        return;
2578 2586
      }
2579 2587
      line.putback(c);
2580 2588
      std::string map;
2581 2589
      while (_reader_bits::readToken(line, map)) {
2582 2590
        maps.push_back(map);
2583 2591
      }
2584 2592
    }
2585 2593

	
2586 2594
    void readAttributes(std::vector<std::string>& attrs) {
2587 2595
      readLine();
2588 2596
      char c;
2589 2597
      while (readSuccess() && line >> c && c != '@') {
2590 2598
        line.putback(c);
2591 2599
        std::string attr;
2592 2600
        _reader_bits::readToken(line, attr);
2593 2601
        attrs.push_back(attr);
2594 2602
        readLine();
2595 2603
      }
2596 2604
      line.putback(c);
2597 2605
    }
2598 2606

	
2599 2607
  public:
2600 2608

	
2601 2609
    /// \name Execution of the contents reader
2602 2610
    /// @{
2603 2611

	
2604 2612
    /// \brief Starts the reading
2605 2613
    ///
2606 2614
    /// This function starts the reading.
2607 2615
    void run() {
2608 2616

	
2609 2617
      readLine();
2610 2618
      skipSection();
2611 2619

	
2612 2620
      while (readSuccess()) {
2613 2621

	
2614 2622
        char c;
2615 2623
        line >> c;
2616 2624

	
2617 2625
        std::string section, caption;
2618 2626
        _reader_bits::readToken(line, section);
2619 2627
        _reader_bits::readToken(line, caption);
2620 2628

	
2621 2629
        if (section == "nodes") {
2622 2630
          _node_sections.push_back(caption);
2623 2631
          _node_maps.push_back(std::vector<std::string>());
2624 2632
          readMaps(_node_maps.back());
2625 2633
          readLine(); skipSection();
2626 2634
        } else if (section == "arcs" || section == "edges") {
2627 2635
          _edge_sections.push_back(caption);
2628 2636
          _arc_sections.push_back(section == "arcs");
2629 2637
          _edge_maps.push_back(std::vector<std::string>());
2630 2638
          readMaps(_edge_maps.back());
2631 2639
          readLine(); skipSection();
2632 2640
        } else if (section == "attributes") {
2633 2641
          _attribute_sections.push_back(caption);
2634 2642
          _attributes.push_back(std::vector<std::string>());
2635 2643
          readAttributes(_attributes.back());
2636 2644
        } else {
2637 2645
          _extra_sections.push_back(section);
2638 2646
          readLine(); skipSection();
2639 2647
        }
2640 2648
      }
2641 2649
    }
2642 2650

	
2643 2651
    /// @}
2644 2652

	
2645 2653
  };
2646 2654
}
2647 2655

	
2648 2656
#endif
0 comments (0 inline)