gravatar
ladanyi@tmit.bme.hu
ladanyi@tmit.bme.hu
Fix compilation with Visual Studio 2005.
0 2 0
default
2 files changed with 94 insertions and 136 deletions:
↑ Collapse diff ↑
Ignore white space 384 line context
... ...
@@ -202,393 +202,415 @@
202 202
        c == '\n' || c == '\r' || c == '\f';
203 203
    }
204 204

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
333 333
      Functor _functor;
334 334

	
335 335
    public:
336 336

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

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

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

	
365 365
      Functor _functor;
366 366

	
367 367
    public:
368 368

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

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

	
389 389
  }
390 390

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

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

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

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

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

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

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

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

	
461 483
  private:
462 484

	
463 485

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

	
468 490
    Digraph& _digraph;
469 491

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

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

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

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

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

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

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

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

	
500 522
  public:
501 523

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

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

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

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

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

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

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

	
562 584
    }
563 585

	
564 586
  private:
565 587

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

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

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

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

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

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

	
592 614
    }
593 615

	
594 616
    DigraphReader& operator=(const DigraphReader&);
... ...
@@ -1000,429 +1022,417 @@
1000 1022
        line.putback(c);
1001 1023

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

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

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

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

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

	
1025 1047
          typename NodeIndex::iterator it;
1026 1048

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

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

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

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

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

	
1069 1091
    void readAttributes() {
1070 1092

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

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

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

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

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

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

	
1117 1139
  public:
1118 1140

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

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

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

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

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

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

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

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

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

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

	
1186 1208
    }
1187 1209

	
1188 1210
    /// @}
1189 1211

	
1190 1212
  };
1191 1213

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

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

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

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

	
1224
  template <typename Graph>
1225
  class GraphReader;
1226

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

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

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

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

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

	
1259 1269
  private:
1260 1270

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

	
1265 1275
    Graph& _graph;
1266 1276

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

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

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

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

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

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

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

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

	
1297 1307
  public:
1298 1308

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

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

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

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

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

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

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

	
1359 1369
    }
1360 1370

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

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

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

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

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

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

	
1386 1396
    }
1387 1397

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

	
1390 1400
  public:
1391 1401

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

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

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

	
1421 1431
    /// \brief Edge map reading rule
1422 1432
    ///
1423 1433
    /// Add an edge map reading rule to the reader.
1424 1434
    template <typename Map>
1425 1435
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1426 1436
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1427 1437
      _reader_bits::MapStorageBase<Edge>* storage =
1428 1438
        new _reader_bits::MapStorage<Edge, Map>(map);
... ...
@@ -1842,414 +1852,384 @@
1842 1852

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

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

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

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

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

	
1866 1876
          typename NodeIndex::iterator it;
1867 1877

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

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

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

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

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

	
1910 1920
    void readAttributes() {
1911 1921

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

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

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

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

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

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

	
1958 1968
  public:
1959 1969

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

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

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

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

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

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

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

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

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

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

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

	
2028 2038
    }
2029 2039

	
2030 2040
    /// @}
2031 2041

	
2032 2042
  };
2033 2043

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

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

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

	
2064 2044
  class SectionReader;
2065 2045

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

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

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

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

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

	
2094 2074
  public:
2095 2075

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

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

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

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

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

	
2138 2118
    }
2139 2119

	
2140 2120
  private:
2141 2121

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

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

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

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

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

	
2157 2137
  public:
2158 2138

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

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

	
2206 2186

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

	
2224 2204
    /// @}
2225 2205

	
2226 2206
  private:
2227 2207

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

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

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

	
2253 2233
  public:
2254 2234

	
2255 2235

	
Ignore white space 6 line context
... ...
@@ -162,395 +162,416 @@
162 162
      virtual void sort(std::vector<Item>& items) {
163 163
        GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
164 164
        std::sort(items.begin(), items.end(), less);
165 165
      }
166 166
    };
167 167

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
320 320
      Functor _functor;
321 321

	
322 322
    public:
323 323

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

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

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

	
337 337
      Functor _functor;
338 338

	
339 339
    public:
340 340

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

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

	
349 349
  }
350 350

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

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

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

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

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

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

	
417 438
  private:
418 439

	
419 440

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

	
423 444
    const Digraph& _digraph;
424 445

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

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

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

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

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

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

	
449 470
  public:
450 471

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

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

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

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

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

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

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

	
507 528
  private:
508 529

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

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

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

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

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

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

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

	
537 558
  public:
538 559

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

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

	
554 575
    /// \brief Node map writing rule
555 576
    ///
556 577
    /// Add a node map writing rule with specialized converter to the
... ...
@@ -724,430 +745,418 @@
724 745
      if (label == 0) {
725 746
        IdMap<Digraph, Node> id_map(_digraph);
726 747
        _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
727 748
        std::sort(nodes.begin(), nodes.end(), id_less);
728 749
      } else {
729 750
        label->sort(nodes);
730 751
      }
731 752

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

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

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

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

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

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

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

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

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

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

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

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

	
884 905
  public:
885 906

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

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

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

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

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

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

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

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

	
949
  template <typename Graph>
950
  class GraphWriter;
951

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

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

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

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

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

	
984 993
  private:
985 994

	
986 995

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

	
990 999
    const Graph& _graph;
991 1000

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

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

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

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

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

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

	
1016 1025
  public:
1017 1026

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

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

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

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

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

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

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

	
1074 1083
  private:
1075 1084

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

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

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

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

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

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

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

	
1104 1113
  public:
1105 1114

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

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

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

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

	
1147 1156
    /// \brief Edge map writing rule
1148 1157
    ///
1149 1158
    /// Add an edge map writing rule with specialized converter to the
1150 1159
    /// writer.
1151 1160
    template <typename Map, typename Converter>
1152 1161
    GraphWriter& edgeMap(const std::string& caption, const Map& map,
1153 1162
                          const Converter& converter = Converter()) {
... ...
@@ -1337,415 +1346,384 @@
1337 1346
      if (label == 0) {
1338 1347
        IdMap<Graph, Node> id_map(_graph);
1339 1348
        _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1340 1349
        std::sort(nodes.begin(), nodes.end(), id_less);
1341 1350
      } else {
1342 1351
        label->sort(nodes);
1343 1352
      }
1344 1353

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

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

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

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

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

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

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

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

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

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

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

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

	
1497 1506
  public:
1498 1507

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

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

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

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

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

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

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

	
1560 1538
  class SectionWriter;
1561 1539

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

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

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

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

	
1586 1564
    Sections _sections;
1587 1565

	
1588 1566
  public:
1589 1567

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

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

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

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

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

	
1630 1608
    }
1631 1609

	
1632 1610
  private:
1633 1611

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

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

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

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

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

	
1649 1627
  public:
1650 1628

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

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

	
1698 1676

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

	
1713 1691
    /// @}
1714 1692

	
1715 1693
  public:
1716 1694

	
1717 1695

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

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

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

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

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

	
1742 1720
    /// @}
1743 1721

	
1744 1722
  };
1745 1723

	
1746 1724
  /// \brief Return a \ref SectionWriter class
1747 1725
  ///
1748 1726
  /// This function just returns a \ref SectionWriter class.
1749 1727
  /// \relates SectionWriter
1750 1728
  inline SectionWriter sectionWriter(std::ostream& os) {
1751 1729
    SectionWriter tmp(os);
0 comments (0 inline)