gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Section readers moved to distinct class
0 1 0
default
1 file changed with 248 insertions and 198 deletions:
↑ Collapse diff ↑
Ignore white space 192 line context
... ...
@@ -326,558 +326,470 @@
326 326

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

	
331 331
      Functor _functor;
332 332

	
333 333
    public:
334 334
      
335 335
      LineSection(const Functor& functor) : _functor(functor) {}
336 336
      virtual ~LineSection() {}
337 337

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

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

	
363 363
      Functor _functor;
364 364

	
365 365
    public:
366 366
      
367 367
      StreamSection(const Functor& functor) : _functor(functor) {}
368 368
      virtual ~StreamSection() {} 
369 369

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

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

	
444 442
    typedef _Digraph Digraph;
445 443
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
446 444
    
447 445
  private:
448 446

	
449 447

	
450 448
    std::istream* _is;
451 449
    bool local_is;
452 450

	
453 451
    Digraph& _digraph;
454 452

	
455 453
    std::string _nodes_caption;
456 454
    std::string _arcs_caption;
457 455
    std::string _attributes_caption;
458 456

	
459 457
    typedef std::map<std::string, Node> NodeIndex;
460 458
    NodeIndex _node_index;
461 459
    typedef std::map<std::string, Arc> ArcIndex;
462 460
    ArcIndex _arc_index;
463 461
    
464 462
    typedef std::vector<std::pair<std::string, 
465 463
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
466 464
    NodeMaps _node_maps; 
467 465

	
468 466
    typedef std::vector<std::pair<std::string,
469 467
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
470 468
    ArcMaps _arc_maps;
471 469

	
472 470
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
473 471
      Attributes;
474 472
    Attributes _attributes;
475 473

	
476
    typedef std::map<std::string, _reader_bits::Section*> Sections;
477
    Sections _sections;
478

	
479 474
    bool _use_nodes;
480 475
    bool _use_arcs;
481 476

	
482 477
    bool _skip_nodes;
483 478
    bool _skip_arcs;
484 479

	
485 480
    int line_num;
486 481
    std::istringstream line;
487 482

	
488 483
  public:
489 484

	
490 485
    /// \brief Constructor
491 486
    ///
492 487
    /// Construct a directed graph reader, which reads from the given
493 488
    /// input stream.
494 489
    DigraphReader(std::istream& is, Digraph& digraph) 
495 490
      : _is(&is), local_is(false), _digraph(digraph),
496 491
	_use_nodes(false), _use_arcs(false),
497 492
	_skip_nodes(false), _skip_arcs(false) {}
498 493

	
499 494
    /// \brief Constructor
500 495
    ///
501 496
    /// Construct a directed graph reader, which reads from the given
502 497
    /// file.
503 498
    DigraphReader(const std::string& fn, Digraph& digraph) 
504 499
      : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
505 500
    	_use_nodes(false), _use_arcs(false),
506 501
	_skip_nodes(false), _skip_arcs(false) {}
507 502
    
508 503
    /// \brief Constructor
509 504
    ///
510 505
    /// Construct a directed graph reader, which reads from the given
511 506
    /// file.
512 507
    DigraphReader(const char* fn, Digraph& digraph) 
513 508
      : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
514 509
    	_use_nodes(false), _use_arcs(false),
515 510
	_skip_nodes(false), _skip_arcs(false) {}
516 511

	
517 512
    /// \brief Copy constructor
518 513
    ///
519 514
    /// The copy constructor transfers all data from the other reader,
520 515
    /// therefore the copied reader will not be usable more. 
521 516
    DigraphReader(DigraphReader& other) 
522 517
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
523 518
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
524 519
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
525 520

	
526 521
      other._is = 0;
527 522
      other.local_is = false;
528 523
      
529 524
      _node_index.swap(other._node_index);
530 525
      _arc_index.swap(other._arc_index);
531 526

	
532 527
      _node_maps.swap(other._node_maps);
533 528
      _arc_maps.swap(other._arc_maps);
534 529
      _attributes.swap(other._attributes);
535 530

	
536 531
      _nodes_caption = other._nodes_caption;
537 532
      _arcs_caption = other._arcs_caption;
538 533
      _attributes_caption = other._attributes_caption;
539 534

	
540
      _sections.swap(other._sections);
541 535
    }
542 536

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

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

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

	
560
      for (typename Sections::iterator it = _sections.begin(); 
561
	   it != _sections.end(); ++it) {
562
	delete it->second;
563
      }
564

	
565 554
      if (local_is) {
566 555
	delete _is;
567 556
      }
568 557

	
569 558
    }
570 559

	
571 560
  private:
572 561
    
573 562
    DigraphReader& operator=(const DigraphReader&);
574 563

	
575 564
  public:
576 565

	
577 566
    /// \name Reading rules
578 567
    /// @{
579 568
    
580 569
    /// \brief Node map reading rule
581 570
    ///
582 571
    /// Add a node map reading rule to the reader.
583 572
    template <typename Map>
584 573
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
585 574
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
586 575
      _reader_bits::MapStorageBase<Node>* storage = 
587 576
	new _reader_bits::MapStorage<Node, Map>(map);
588 577
      _node_maps.push_back(std::make_pair(caption, storage));
589 578
      return *this;
590 579
    }
591 580

	
592 581
    /// \brief Node map reading rule
593 582
    ///
594 583
    /// Add a node map reading rule with specialized converter to the
595 584
    /// reader.
596 585
    template <typename Map, typename Converter>
597 586
    DigraphReader& nodeMap(const std::string& caption, Map& map, 
598 587
			   const Converter& converter = Converter()) {
599 588
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
600 589
      _reader_bits::MapStorageBase<Node>* storage = 
601 590
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
602 591
      _node_maps.push_back(std::make_pair(caption, storage));
603 592
      return *this;
604 593
    }
605 594

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

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

	
632 621
    /// \brief Attribute reading rule
633 622
    ///
634 623
    /// Add an attribute reading rule to the reader.
635 624
    template <typename Value>
636 625
    DigraphReader& attribute(const std::string& caption, Value& value) {
637 626
      _reader_bits::ValueStorageBase* storage = 
638 627
	new _reader_bits::ValueStorage<Value>(value);
639 628
      _attributes.insert(std::make_pair(caption, storage));
640 629
      return *this;
641 630
    }
642 631

	
643 632
    /// \brief Attribute reading rule
644 633
    ///
645 634
    /// Add an attribute reading rule with specialized converter to the
646 635
    /// reader.
647 636
    template <typename Value, typename Converter>
648 637
    DigraphReader& attribute(const std::string& caption, Value& value, 
649 638
			     const Converter& converter = Converter()) {
650 639
      _reader_bits::ValueStorageBase* storage = 
651 640
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
652 641
      _attributes.insert(std::make_pair(caption, storage));
653 642
      return *this;
654 643
    }
655 644

	
656 645
    /// \brief Node reading rule
657 646
    ///
658 647
    /// Add a node reading rule to reader.
659 648
    DigraphReader& node(const std::string& caption, Node& node) {
660 649
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
661 650
      Converter converter(_node_index);
662 651
      _reader_bits::ValueStorageBase* storage = 
663 652
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
664 653
      _attributes.insert(std::make_pair(caption, storage));
665 654
      return *this;
666 655
    }
667 656

	
668 657
    /// \brief Arc reading rule
669 658
    ///
670 659
    /// Add an arc reading rule to reader.
671 660
    DigraphReader& arc(const std::string& caption, Arc& arc) {
672 661
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
673 662
      Converter converter(_arc_index);
674 663
      _reader_bits::ValueStorageBase* storage = 
675 664
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
676 665
      _attributes.insert(std::make_pair(caption, storage));
677 666
      return *this;
678 667
    }
679 668

	
680 669
    /// @}
681 670

	
682 671
    /// \name Select section by name
683 672
    /// @{
684 673

	
685 674
    /// \brief Set \c \@nodes section to be read
686 675
    ///
687 676
    /// Set \c \@nodes section to be read
688 677
    DigraphReader& nodes(const std::string& caption) {
689 678
      _nodes_caption = caption;
690 679
      return *this;
691 680
    }
692 681

	
693 682
    /// \brief Set \c \@arcs section to be read
694 683
    ///
695 684
    /// Set \c \@arcs section to be read
696 685
    DigraphReader& arcs(const std::string& caption) {
697 686
      _arcs_caption = caption;
698 687
      return *this;
699 688
    }
700 689

	
701 690
    /// \brief Set \c \@attributes section to be read
702 691
    ///
703 692
    /// Set \c \@attributes section to be read
704 693
    DigraphReader& attributes(const std::string& caption) {
705 694
      _attributes_caption = caption;
706 695
      return *this;
707 696
    }
708 697

	
709 698
    /// @}
710 699

	
711
    /// \name Section readers
712
    /// @{
713

	
714
    /// \brief Add a section processor with line oriented reading
715
    ///
716
    /// In the \e LGF file extra sections can be placed, which contain
717
    /// any data in arbitrary format. These sections can be read with
718
    /// this function line by line. The first parameter is the type
719
    /// descriptor of the section, the second is a functor, which
720
    /// takes just one \c std::string parameter. At the reading
721
    /// process, each line of the section will be given to the functor
722
    /// object. However, the empty lines and the comment lines are
723
    /// filtered out, and the leading whitespaces are stipped from
724
    /// each processed string.
725
    ///
726
    /// For example let's see a section, which contain several
727
    /// integers, which should be inserted into a vector.
728
    ///\code
729
    ///  @numbers
730
    ///  12 45 23
731
    ///  4
732
    ///  23 6
733
    ///\endcode
734
    ///
735
    /// The functor is implemented as an struct:
736
    ///\code
737
    ///  struct NumberSection {
738
    ///    std::vector<int>& _data;
739
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
740
    ///    void operator()(const std::string& line) {
741
    ///      std::istringstream ls(line);
742
    ///      int value;
743
    ///      while (ls >> value) _data.push_back(value);
744
    ///    }
745
    ///  };
746
    ///
747
    ///  // ...
748
    ///
749
    ///  reader.sectionLines("numbers", NumberSection(vec));  
750
    ///\endcode
751
    template <typename Functor>
752
    DigraphReader& sectionLines(const std::string& type, Functor functor) {
753
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
754
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
755
		   "Multiple reading of section.");
756
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
757
		   type != "attributes", "Multiple reading of section.");
758
      _sections.insert(std::make_pair(type, 
759
        new _reader_bits::LineSection<Functor>(functor)));
760
      return *this;
761
    }
762

	
763

	
764
    /// \brief Add a section processor with stream oriented reading
765
    ///
766
    /// In the \e LGF file extra sections can be placed, which contain
767
    /// any data in arbitrary format. These sections can be read
768
    /// directly with this function. The first parameter is the type
769
    /// of the section, the second is a functor, which takes an \c
770
    /// std::istream& and an int& parameter, the latter regard to the
771
    /// line number of stream. The functor can read the input while
772
    /// the section go on, and the line number should be modified
773
    /// accordingly.
774
    template <typename Functor>
775
    DigraphReader& sectionStream(const std::string& type, Functor functor) {
776
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
777
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
778
		   "Multiple reading of section.");
779
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
780
		   type != "attributes", "Multiple reading of section.");
781
      _sections.insert(std::make_pair(type, 
782
	 new _reader_bits::StreamSection<Functor>(functor)));
783
      return *this;
784
    }    
785
    
786
    /// @}
787

	
788 700
    /// \name Using previously constructed node or arc set
789 701
    /// @{
790 702

	
791 703
    /// \brief Use previously constructed node set
792 704
    ///
793 705
    /// Use previously constructed node set, and specify the node
794 706
    /// label map.
795 707
    template <typename Map>
796 708
    DigraphReader& useNodes(const Map& map) {
797 709
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
798 710
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
799 711
      _use_nodes = true;
800 712
      _writer_bits::DefaultConverter<typename Map::Value> converter;
801 713
      for (NodeIt n(_digraph); n != INVALID; ++n) {
802 714
	_node_index.insert(std::make_pair(converter(map[n]), n));
803 715
      }
804 716
      return *this;
805 717
    }
806 718

	
807 719
    /// \brief Use previously constructed node set
808 720
    ///
809 721
    /// Use previously constructed node set, and specify the node
810 722
    /// label map and a functor which converts the label map values to
811 723
    /// std::string.
812 724
    template <typename Map, typename Converter>
813 725
    DigraphReader& useNodes(const Map& map, 
814 726
			    const Converter& converter = Converter()) {
815 727
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
816 728
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
817 729
      _use_nodes = true;
818 730
      for (NodeIt n(_digraph); n != INVALID; ++n) {
819 731
	_node_index.insert(std::make_pair(converter(map[n]), n));
820 732
      }
821 733
      return *this;
822 734
    }
823 735

	
824 736
    /// \brief Use previously constructed arc set
825 737
    ///
826 738
    /// Use previously constructed arc set, and specify the arc
827 739
    /// label map.
828 740
    template <typename Map>
829 741
    DigraphReader& useArcs(const Map& map) {
830 742
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
831 743
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
832 744
      _use_arcs = true;
833 745
      _writer_bits::DefaultConverter<typename Map::Value> converter;
834 746
      for (ArcIt a(_digraph); a != INVALID; ++a) {
835 747
	_arc_index.insert(std::make_pair(converter(map[a]), a));
836 748
      }
837 749
      return *this;
838 750
    }
839 751

	
840 752
    /// \brief Use previously constructed arc set
841 753
    ///
842 754
    /// Use previously constructed arc set, and specify the arc
843 755
    /// label map and a functor which converts the label map values to
844 756
    /// std::string.
845 757
    template <typename Map, typename Converter>
846 758
    DigraphReader& useArcs(const Map& map, 
847 759
			   const Converter& converter = Converter()) {
848 760
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
849 761
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); 
850 762
      _use_arcs = true;
851 763
      for (ArcIt a(_digraph); a != INVALID; ++a) {
852 764
	_arc_index.insert(std::make_pair(converter(map[a]), a));
853 765
      }
854 766
      return *this;
855 767
    }
856 768

	
857 769
    /// \brief Skips the reading of node section
858 770
    ///
859 771
    /// Omit the reading of the node section. This implies that each node
860 772
    /// map reading rule will be abanoned, and the nodes of the graph
861 773
    /// will not be constructed, which usually cause that the arc set
862 774
    /// could not be read due to lack of node name
863 775
    /// resolving. Therefore, the \c skipArcs() should be used too, or
864 776
    /// the useNodes() member function should be used to specify the
865 777
    /// label of the nodes.
866 778
    DigraphReader& skipNodes() {
867 779
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); 
868 780
      _skip_nodes = true;
869 781
      return *this;
870 782
    }
871 783

	
872 784
    /// \brief Skips the reading of arc section
873 785
    ///
874 786
    /// Omit the reading of the arc section. This implies that each arc
875 787
    /// map reading rule will be abanoned, and the arcs of the graph
876 788
    /// will not be constructed.
877 789
    DigraphReader& skipArcs() {
878 790
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set"); 
879 791
      _skip_arcs = true;
880 792
      return *this;
881 793
    }
882 794

	
883 795
    /// @}
... ...
@@ -1095,684 +1007,586 @@
1095 1007
            msg << "Item not found: " << target_token;
1096 1008
            throw DataFormatError(msg.str().c_str());
1097 1009
          }                                          
1098 1010
          Node target = it->second;                            
1099 1011

	
1100 1012
	  a = _digraph.addArc(source, target);
1101 1013
	  if (label_index != -1) 
1102 1014
	    _arc_index.insert(std::make_pair(tokens[label_index], a));
1103 1015
	} else {
1104 1016
	  if (label_index == -1) 
1105 1017
	    throw DataFormatError("Label map not found in file");
1106 1018
	  typename std::map<std::string, Arc>::iterator it =
1107 1019
	    _arc_index.find(tokens[label_index]);
1108 1020
	  if (it == _arc_index.end()) {
1109 1021
	    std::ostringstream msg;
1110 1022
	    msg << "Arc with label not found: " << tokens[label_index];
1111 1023
	    throw DataFormatError(msg.str().c_str());	    
1112 1024
	  }
1113 1025
	  a = it->second;
1114 1026
	}
1115 1027

	
1116 1028
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1117 1029
	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
1118 1030
	}
1119 1031

	
1120 1032
      }
1121 1033
      if (readSuccess()) {
1122 1034
	line.putback(c);
1123 1035
      }
1124 1036
    }
1125 1037

	
1126 1038
    void readAttributes() {
1127 1039

	
1128 1040
      std::set<std::string> read_attr;
1129 1041

	
1130 1042
      char c;
1131 1043
      while (readLine() && line >> c && c != '@') {
1132 1044
	line.putback(c);
1133 1045
	
1134 1046
	std::string attr, token;
1135 1047
	if (!_reader_bits::readToken(line, attr))
1136 1048
	  throw DataFormatError("Attribute name not found");
1137 1049
	if (!_reader_bits::readToken(line, token))
1138 1050
	  throw DataFormatError("Attribute value not found");
1139 1051
	if (line >> c)
1140 1052
	  throw DataFormatError("Extra character on the end of line");	  
1141 1053

	
1142 1054
	{
1143 1055
	  std::set<std::string>::iterator it = read_attr.find(attr);
1144 1056
	  if (it != read_attr.end()) {
1145 1057
	    std::ostringstream msg;
1146 1058
	    msg << "Multiple occurence of attribute " << attr;
1147 1059
	    throw DataFormatError(msg.str().c_str());
1148 1060
	  }
1149 1061
	  read_attr.insert(attr);
1150 1062
	}
1151 1063
	
1152 1064
	{
1153 1065
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1154 1066
	  while (it != _attributes.end() && it->first == attr) {
1155 1067
	    it->second->set(token);
1156 1068
	    ++it;
1157 1069
	  }
1158 1070
	}
1159 1071

	
1160 1072
      }
1161 1073
      if (readSuccess()) {
1162 1074
	line.putback(c);
1163 1075
      }
1164 1076
      for (typename Attributes::iterator it = _attributes.begin();
1165 1077
	   it != _attributes.end(); ++it) {
1166 1078
	if (read_attr.find(it->first) == read_attr.end()) {
1167 1079
	  std::ostringstream msg;
1168 1080
	  msg << "Attribute not found in file: " << it->first;
1169 1081
	  throw DataFormatError(msg.str().c_str());
1170 1082
	}	
1171 1083
      }
1172 1084
    }
1173 1085

	
1174 1086
  public:
1175 1087

	
1176 1088
    /// \name Execution of the reader    
1177 1089
    /// @{
1178 1090

	
1179 1091
    /// \brief Start the batch processing
1180 1092
    ///
1181 1093
    /// This function starts the batch processing
1182 1094
    void run() {
1183 1095
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1184 1096
      if (!*_is) {
1185 1097
	throw DataFormatError("Cannot find file");
1186 1098
      }
1187 1099
      
1188 1100
      bool nodes_done = _skip_nodes;
1189 1101
      bool arcs_done = _skip_arcs;
1190 1102
      bool attributes_done = false;
1191
      std::set<std::string> extra_sections;
1192 1103

	
1193 1104
      line_num = 0;      
1194 1105
      readLine();
1195 1106
      skipSection();
1196 1107

	
1197 1108
      while (readSuccess()) {
1198 1109
	try {
1199 1110
	  char c;
1200 1111
	  std::string section, caption;
1201 1112
	  line >> c;
1202 1113
	  _reader_bits::readToken(line, section);
1203 1114
	  _reader_bits::readToken(line, caption);
1204 1115

	
1205 1116
	  if (line >> c) 
1206 1117
	    throw DataFormatError("Extra character on the end of line");
1207 1118

	
1208 1119
	  if (section == "nodes" && !nodes_done) {
1209 1120
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1210 1121
	      readNodes();
1211 1122
	      nodes_done = true;
1212 1123
	    }
1213 1124
	  } else if ((section == "arcs" || section == "edges") && 
1214 1125
		     !arcs_done) {
1215 1126
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
1216 1127
	      readArcs();
1217 1128
	      arcs_done = true;
1218 1129
	    }
1219 1130
	  } else if (section == "attributes" && !attributes_done) {
1220 1131
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
1221 1132
	      readAttributes();
1222 1133
	      attributes_done = true;
1223 1134
	    }
1224 1135
	  } else {
1225
	    if (extra_sections.find(section) != extra_sections.end()) {
1226
	      std::ostringstream msg;
1227
	      msg << "Multiple occurence of section " << section;
1228
	      throw DataFormatError(msg.str().c_str());
1229
	    }
1230
	    Sections::iterator it = _sections.find(section);
1231
	    if (it != _sections.end()) {
1232
	      extra_sections.insert(section);
1233
	      it->second->process(*_is, line_num);
1234
	    }
1235 1136
	    readLine();
1236 1137
	    skipSection();
1237 1138
	  }
1238 1139
	} catch (DataFormatError& error) {
1239 1140
	  error.line(line_num);
1240 1141
	  throw;
1241 1142
	}	
1242 1143
      }
1243 1144

	
1244 1145
      if (!nodes_done) {
1245 1146
	throw DataFormatError("Section @nodes not found");
1246 1147
      }
1247 1148

	
1248 1149
      if (!arcs_done) {
1249 1150
	throw DataFormatError("Section @arcs not found");
1250 1151
      }
1251 1152

	
1252 1153
      if (!attributes_done && !_attributes.empty()) {
1253 1154
	throw DataFormatError("Section @attributes not found");
1254 1155
      }
1255 1156

	
1256 1157
    }
1257 1158

	
1258 1159
    /// @}
1259 1160
    
1260 1161
  };
1261 1162

	
1262 1163
  /// \relates DigraphReader
1263 1164
  template <typename Digraph>
1264 1165
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
1265 1166
    DigraphReader<Digraph> tmp(is, digraph);
1266 1167
    return tmp;
1267 1168
  }
1268 1169

	
1269 1170
  /// \relates DigraphReader
1270 1171
  template <typename Digraph>
1271 1172
  DigraphReader<Digraph> digraphReader(const std::string& fn, 
1272 1173
				       Digraph& digraph) {
1273 1174
    DigraphReader<Digraph> tmp(fn, digraph);
1274 1175
    return tmp;
1275 1176
  }
1276 1177

	
1277 1178
  /// \relates DigraphReader
1278 1179
  template <typename Digraph>
1279 1180
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
1280 1181
    DigraphReader<Digraph> tmp(fn, digraph);
1281 1182
    return tmp;
1282 1183
  }
1283 1184

	
1284 1185
  /// \ingroup lemon_io
1285 1186
  ///  
1286 1187
  /// \brief LGF reader for undirected graphs
1287 1188
  ///
1288 1189
  /// This utility reads an \ref lgf-format "LGF" file.
1289 1190
  template <typename _Graph>
1290 1191
  class GraphReader {
1291 1192
  public:
1292 1193

	
1293 1194
    typedef _Graph Graph;
1294 1195
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1295 1196
    
1296 1197
  private:
1297 1198

	
1298

	
1299 1199
    std::istream* _is;
1300 1200
    bool local_is;
1301 1201

	
1302 1202
    Graph& _graph;
1303 1203

	
1304 1204
    std::string _nodes_caption;
1305 1205
    std::string _edges_caption;
1306 1206
    std::string _attributes_caption;
1307 1207

	
1308 1208
    typedef std::map<std::string, Node> NodeIndex;
1309 1209
    NodeIndex _node_index;
1310 1210
    typedef std::map<std::string, Edge> EdgeIndex;
1311 1211
    EdgeIndex _edge_index;
1312 1212
    
1313 1213
    typedef std::vector<std::pair<std::string, 
1314 1214
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
1315 1215
    NodeMaps _node_maps; 
1316 1216

	
1317 1217
    typedef std::vector<std::pair<std::string,
1318 1218
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1319 1219
    EdgeMaps _edge_maps;
1320 1220

	
1321 1221
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
1322 1222
      Attributes;
1323 1223
    Attributes _attributes;
1324 1224

	
1325
    typedef std::map<std::string, _reader_bits::Section*> Sections;
1326
    Sections _sections;
1327

	
1328 1225
    bool _use_nodes;
1329 1226
    bool _use_edges;
1330 1227

	
1331 1228
    bool _skip_nodes;
1332 1229
    bool _skip_edges;
1333 1230

	
1334 1231
    int line_num;
1335 1232
    std::istringstream line;
1336 1233

	
1337 1234
  public:
1338 1235

	
1339 1236
    /// \brief Constructor
1340 1237
    ///
1341 1238
    /// Construct a undirected graph reader, which reads from the given
1342 1239
    /// input stream.
1343 1240
    GraphReader(std::istream& is, Graph& graph) 
1344 1241
      : _is(&is), local_is(false), _graph(graph),
1345 1242
	_use_nodes(false), _use_edges(false),
1346 1243
	_skip_nodes(false), _skip_edges(false) {}
1347 1244

	
1348 1245
    /// \brief Constructor
1349 1246
    ///
1350 1247
    /// Construct a undirected graph reader, which reads from the given
1351 1248
    /// file.
1352 1249
    GraphReader(const std::string& fn, Graph& graph) 
1353 1250
      : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
1354 1251
    	_use_nodes(false), _use_edges(false),
1355 1252
	_skip_nodes(false), _skip_edges(false) {}
1356 1253
    
1357 1254
    /// \brief Constructor
1358 1255
    ///
1359 1256
    /// Construct a undirected graph reader, which reads from the given
1360 1257
    /// file.
1361 1258
    GraphReader(const char* fn, Graph& graph) 
1362 1259
      : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
1363 1260
    	_use_nodes(false), _use_edges(false),
1364 1261
	_skip_nodes(false), _skip_edges(false) {}
1365 1262

	
1366 1263
    /// \brief Copy constructor
1367 1264
    ///
1368 1265
    /// The copy constructor transfers all data from the other reader,
1369 1266
    /// therefore the copied reader will not be usable more. 
1370 1267
    GraphReader(GraphReader& other) 
1371 1268
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1372 1269
	_use_nodes(other._use_nodes), _use_edges(other._use_edges),
1373 1270
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1374 1271

	
1375 1272
      other._is = 0;
1376 1273
      other.local_is = false;
1377 1274
      
1378 1275
      _node_index.swap(other._node_index);
1379 1276
      _edge_index.swap(other._edge_index);
1380 1277

	
1381 1278
      _node_maps.swap(other._node_maps);
1382 1279
      _edge_maps.swap(other._edge_maps);
1383 1280
      _attributes.swap(other._attributes);
1384 1281

	
1385 1282
      _nodes_caption = other._nodes_caption;
1386 1283
      _edges_caption = other._edges_caption;
1387 1284
      _attributes_caption = other._attributes_caption;
1388 1285

	
1389
      _sections.swap(other._sections);
1390 1286
    }
1391 1287

	
1392 1288
    /// \brief Destructor
1393 1289
    ~GraphReader() {
1394 1290
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
1395 1291
	   it != _node_maps.end(); ++it) {
1396 1292
	delete it->second;
1397 1293
      }
1398 1294

	
1399 1295
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
1400 1296
	   it != _edge_maps.end(); ++it) {
1401 1297
	delete it->second;
1402 1298
      }
1403 1299

	
1404 1300
      for (typename Attributes::iterator it = _attributes.begin(); 
1405 1301
	   it != _attributes.end(); ++it) {
1406 1302
	delete it->second;
1407 1303
      }
1408 1304

	
1409
      for (typename Sections::iterator it = _sections.begin(); 
1410
	   it != _sections.end(); ++it) {
1411
	delete it->second;
1412
      }
1413

	
1414 1305
      if (local_is) {
1415 1306
	delete _is;
1416 1307
      }
1417 1308

	
1418 1309
    }
1419 1310

	
1420 1311
  private:
1421 1312
    
1422 1313
    GraphReader& operator=(const GraphReader&);
1423 1314

	
1424 1315
  public:
1425 1316

	
1426 1317
    /// \name Reading rules
1427 1318
    /// @{
1428 1319
    
1429 1320
    /// \brief Node map reading rule
1430 1321
    ///
1431 1322
    /// Add a node map reading rule to the reader.
1432 1323
    template <typename Map>
1433 1324
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1434 1325
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1435 1326
      _reader_bits::MapStorageBase<Node>* storage = 
1436 1327
	new _reader_bits::MapStorage<Node, Map>(map);
1437 1328
      _node_maps.push_back(std::make_pair(caption, storage));
1438 1329
      return *this;
1439 1330
    }
1440 1331

	
1441 1332
    /// \brief Node map reading rule
1442 1333
    ///
1443 1334
    /// Add a node map reading rule with specialized converter to the
1444 1335
    /// reader.
1445 1336
    template <typename Map, typename Converter>
1446 1337
    GraphReader& nodeMap(const std::string& caption, Map& map, 
1447 1338
			   const Converter& converter = Converter()) {
1448 1339
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1449 1340
      _reader_bits::MapStorageBase<Node>* storage = 
1450 1341
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1451 1342
      _node_maps.push_back(std::make_pair(caption, storage));
1452 1343
      return *this;
1453 1344
    }
1454 1345

	
1455 1346
    /// \brief Edge map reading rule
1456 1347
    ///
1457 1348
    /// Add an edge map reading rule to the reader.
1458 1349
    template <typename Map>
1459 1350
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1460 1351
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1461 1352
      _reader_bits::MapStorageBase<Edge>* storage = 
1462 1353
	new _reader_bits::MapStorage<Edge, Map>(map);
1463 1354
      _edge_maps.push_back(std::make_pair(caption, storage));
1464 1355
      return *this;
1465 1356
    }
1466 1357

	
1467 1358
    /// \brief Edge map reading rule
1468 1359
    ///
1469 1360
    /// Add an edge map reading rule with specialized converter to the
1470 1361
    /// reader.
1471 1362
    template <typename Map, typename Converter>
1472 1363
    GraphReader& edgeMap(const std::string& caption, Map& map, 
1473 1364
			  const Converter& converter = Converter()) {
1474 1365
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1475 1366
      _reader_bits::MapStorageBase<Edge>* storage = 
1476 1367
	new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1477 1368
      _edge_maps.push_back(std::make_pair(caption, storage));
1478 1369
      return *this;
1479 1370
    }
1480 1371

	
1481 1372
    /// \brief Arc map reading rule
1482 1373
    ///
1483 1374
    /// Add an arc map reading rule to the reader.
1484 1375
    template <typename Map>
1485 1376
    GraphReader& arcMap(const std::string& caption, Map& map) {
1486 1377
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1487 1378
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
1488 1379
	new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1489 1380
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1490 1381
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
1491 1382
	new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1492 1383
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1493 1384
      return *this;
1494 1385
    }
1495 1386

	
1496 1387
    /// \brief Arc map reading rule
1497 1388
    ///
1498 1389
    /// Add an arc map reading rule with specialized converter to the
1499 1390
    /// reader.
1500 1391
    template <typename Map, typename Converter>
1501 1392
    GraphReader& arcMap(const std::string& caption, Map& map, 
1502 1393
			  const Converter& converter = Converter()) {
1503 1394
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1504 1395
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
1505 1396
	new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1506 1397
	(_graph, map, converter);
1507 1398
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1508 1399
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
1509 1400
	new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1510 1401
	(_graph, map, converter);
1511 1402
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1512 1403
      return *this;
1513 1404
    }
1514 1405

	
1515 1406
    /// \brief Attribute reading rule
1516 1407
    ///
1517 1408
    /// Add an attribute reading rule to the reader.
1518 1409
    template <typename Value>
1519 1410
    GraphReader& attribute(const std::string& caption, Value& value) {
1520 1411
      _reader_bits::ValueStorageBase* storage = 
1521 1412
	new _reader_bits::ValueStorage<Value>(value);
1522 1413
      _attributes.insert(std::make_pair(caption, storage));
1523 1414
      return *this;
1524 1415
    }
1525 1416

	
1526 1417
    /// \brief Attribute reading rule
1527 1418
    ///
1528 1419
    /// Add an attribute reading rule with specialized converter to the
1529 1420
    /// reader.
1530 1421
    template <typename Value, typename Converter>
1531 1422
    GraphReader& attribute(const std::string& caption, Value& value, 
1532 1423
			     const Converter& converter = Converter()) {
1533 1424
      _reader_bits::ValueStorageBase* storage = 
1534 1425
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1535 1426
      _attributes.insert(std::make_pair(caption, storage));
1536 1427
      return *this;
1537 1428
    }
1538 1429

	
1539 1430
    /// \brief Node reading rule
1540 1431
    ///
1541 1432
    /// Add a node reading rule to reader.
1542 1433
    GraphReader& node(const std::string& caption, Node& node) {
1543 1434
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1544 1435
      Converter converter(_node_index);
1545 1436
      _reader_bits::ValueStorageBase* storage = 
1546 1437
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1547 1438
      _attributes.insert(std::make_pair(caption, storage));
1548 1439
      return *this;
1549 1440
    }
1550 1441

	
1551 1442
    /// \brief Edge reading rule
1552 1443
    ///
1553 1444
    /// Add an edge reading rule to reader.
1554 1445
    GraphReader& edge(const std::string& caption, Edge& edge) {
1555 1446
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1556 1447
      Converter converter(_edge_index);
1557 1448
      _reader_bits::ValueStorageBase* storage = 
1558 1449
	new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1559 1450
      _attributes.insert(std::make_pair(caption, storage));
1560 1451
      return *this;
1561 1452
    }
1562 1453

	
1563 1454
    /// \brief Arc reading rule
1564 1455
    ///
1565 1456
    /// Add an arc reading rule to reader.
1566 1457
    GraphReader& arc(const std::string& caption, Arc& arc) {
1567 1458
      typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
1568 1459
      Converter converter(_graph, _edge_index);
1569 1460
      _reader_bits::ValueStorageBase* storage = 
1570 1461
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1571 1462
      _attributes.insert(std::make_pair(caption, storage));
1572 1463
      return *this;
1573 1464
    }
1574 1465

	
1575 1466
    /// @}
1576 1467

	
1577 1468
    /// \name Select section by name
1578 1469
    /// @{
1579 1470

	
1580 1471
    /// \brief Set \c \@nodes section to be read
1581 1472
    ///
1582 1473
    /// Set \c \@nodes section to be read
1583 1474
    GraphReader& nodes(const std::string& caption) {
1584 1475
      _nodes_caption = caption;
1585 1476
      return *this;
1586 1477
    }
1587 1478

	
1588 1479
    /// \brief Set \c \@edges section to be read
1589 1480
    ///
1590 1481
    /// Set \c \@edges section to be read
1591 1482
    GraphReader& edges(const std::string& caption) {
1592 1483
      _edges_caption = caption;
1593 1484
      return *this;
1594 1485
    }
1595 1486

	
1596 1487
    /// \brief Set \c \@attributes section to be read
1597 1488
    ///
1598 1489
    /// Set \c \@attributes section to be read
1599 1490
    GraphReader& attributes(const std::string& caption) {
1600 1491
      _attributes_caption = caption;
1601 1492
      return *this;
1602 1493
    }
1603 1494

	
1604 1495
    /// @}
1605 1496

	
1606
    /// \name Section readers
1607
    /// @{
1608

	
1609
    /// \brief Add a section processor with line oriented reading
1610
    ///
1611
    /// In the \e LGF file extra sections can be placed, which contain
1612
    /// any data in arbitrary format. These sections can be read with
1613
    /// this function line by line. The first parameter is the type
1614
    /// descriptor of the section, the second is a functor, which
1615
    /// takes just one \c std::string parameter. At the reading
1616
    /// process, each line of the section will be given to the functor
1617
    /// object. However, the empty lines and the comment lines are
1618
    /// filtered out, and the leading whitespaces are stipped from
1619
    /// each processed string.
1620
    ///
1621
    /// For example let's see a section, which contain several
1622
    /// integers, which should be inserted into a vector.
1623
    ///\code
1624
    ///  @numbers
1625
    ///  12 45 23
1626
    ///  4
1627
    ///  23 6
1628
    ///\endcode
1629
    ///
1630
    /// The functor is implemented as an struct:
1631
    ///\code
1632
    ///  struct NumberSection {
1633
    ///    std::vector<int>& _data;
1634
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
1635
    ///    void operator()(const std::string& line) {
1636
    ///      std::istringstream ls(line);
1637
    ///      int value;
1638
    ///      while (ls >> value) _data.push_back(value);
1639
    ///    }
1640
    ///  };
1641
    ///
1642
    ///  // ...
1643
    ///
1644
    ///  reader.sectionLines("numbers", NumberSection(vec));  
1645
    ///\endcode
1646
    template <typename Functor>
1647
    GraphReader& sectionLines(const std::string& type, Functor functor) {
1648
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
1649
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
1650
		   "Multiple reading of section.");
1651
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
1652
		   type != "attributes", "Multiple reading of section.");
1653
      _sections.insert(std::make_pair(type, 
1654
        new _reader_bits::LineSection<Functor>(functor)));
1655
      return *this;
1656
    }
1657

	
1658

	
1659
    /// \brief Add a section processor with stream oriented reading
1660
    ///
1661
    /// In the \e LGF file extra sections can be placed, which contain
1662
    /// any data in arbitrary format. These sections can be read
1663
    /// directly with this function. The first parameter is the type
1664
    /// of the section, the second is a functor, which takes an \c
1665
    /// std::istream& and an int& parameter, the latter regard to the
1666
    /// line number of stream. The functor can read the input while
1667
    /// the section go on, and the line number should be modified
1668
    /// accordingly.
1669
    template <typename Functor>
1670
    GraphReader& sectionStream(const std::string& type, Functor functor) {
1671
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
1672
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
1673
		   "Multiple reading of section.");
1674
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
1675
		   type != "attributes", "Multiple reading of section.");
1676
      _sections.insert(std::make_pair(type, 
1677
	 new _reader_bits::StreamSection<Functor>(functor)));
1678
      return *this;
1679
    }    
1680
    
1681
    /// @}
1682

	
1683 1497
    /// \name Using previously constructed node or edge set
1684 1498
    /// @{
1685 1499

	
1686 1500
    /// \brief Use previously constructed node set
1687 1501
    ///
1688 1502
    /// Use previously constructed node set, and specify the node
1689 1503
    /// label map.
1690 1504
    template <typename Map>
1691 1505
    GraphReader& useNodes(const Map& map) {
1692 1506
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1693 1507
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
1694 1508
      _use_nodes = true;
1695 1509
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1696 1510
      for (NodeIt n(_graph); n != INVALID; ++n) {
1697 1511
	_node_index.insert(std::make_pair(converter(map[n]), n));
1698 1512
      }
1699 1513
      return *this;
1700 1514
    }
1701 1515

	
1702 1516
    /// \brief Use previously constructed node set
1703 1517
    ///
1704 1518
    /// Use previously constructed node set, and specify the node
1705 1519
    /// label map and a functor which converts the label map values to
1706 1520
    /// std::string.
1707 1521
    template <typename Map, typename Converter>
1708 1522
    GraphReader& useNodes(const Map& map, 
1709 1523
			    const Converter& converter = Converter()) {
1710 1524
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1711 1525
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
1712 1526
      _use_nodes = true;
1713 1527
      for (NodeIt n(_graph); n != INVALID; ++n) {
1714 1528
	_node_index.insert(std::make_pair(converter(map[n]), n));
1715 1529
      }
1716 1530
      return *this;
1717 1531
    }
1718 1532

	
1719 1533
    /// \brief Use previously constructed edge set
1720 1534
    ///
1721 1535
    /// Use previously constructed edge set, and specify the edge
1722 1536
    /// label map.
1723 1537
    template <typename Map>
1724 1538
    GraphReader& useEdges(const Map& map) {
1725 1539
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1726 1540
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1727 1541
      _use_edges = true;
1728 1542
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1729 1543
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1730 1544
	_edge_index.insert(std::make_pair(converter(map[a]), a));
1731 1545
      }
1732 1546
      return *this;
1733 1547
    }
1734 1548

	
1735 1549
    /// \brief Use previously constructed edge set
1736 1550
    ///
1737 1551
    /// Use previously constructed edge set, and specify the edge
1738 1552
    /// label map and a functor which converts the label map values to
1739 1553
    /// std::string.
1740 1554
    template <typename Map, typename Converter>
1741 1555
    GraphReader& useEdges(const Map& map, 
1742 1556
			    const Converter& converter = Converter()) {
1743 1557
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1744 1558
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member"); 
1745 1559
      _use_edges = true;
1746 1560
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1747 1561
	_edge_index.insert(std::make_pair(converter(map[a]), a));
1748 1562
      }
1749 1563
      return *this;
1750 1564
    }
1751 1565

	
1752 1566
    /// \brief Skips the reading of node section
1753 1567
    ///
1754 1568
    /// Omit the reading of the node section. This implies that each node
1755 1569
    /// map reading rule will be abanoned, and the nodes of the graph
1756 1570
    /// will not be constructed, which usually cause that the edge set
1757 1571
    /// could not be read due to lack of node name
1758 1572
    /// resolving. Therefore, the \c skipEdges() should be used too, or
1759 1573
    /// the useNodes() member function should be used to specify the
1760 1574
    /// label of the nodes.
1761 1575
    GraphReader& skipNodes() {
1762 1576
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); 
1763 1577
      _skip_nodes = true;
1764 1578
      return *this;
1765 1579
    }
1766 1580

	
1767 1581
    /// \brief Skips the reading of edge section
1768 1582
    ///
1769 1583
    /// Omit the reading of the edge section. This implies that each edge
1770 1584
    /// map reading rule will be abanoned, and the edges of the graph
1771 1585
    /// will not be constructed.
1772 1586
    GraphReader& skipEdges() {
1773 1587
      LEMON_ASSERT(!_skip_edges, "Skip edges already set"); 
1774 1588
      _skip_edges = true;
1775 1589
      return *this;
1776 1590
    }
1777 1591

	
1778 1592
    /// @}
... ...
@@ -1988,285 +1802,521 @@
1988 1802
          if (it == _node_index.end()) {       
1989 1803
            std::ostringstream msg;            
1990 1804
            msg << "Item not found: " << target_token;
1991 1805
            throw DataFormatError(msg.str().c_str());
1992 1806
          }                                          
1993 1807
          Node target = it->second;                            
1994 1808

	
1995 1809
	  e = _graph.addEdge(source, target);
1996 1810
	  if (label_index != -1) 
1997 1811
	    _edge_index.insert(std::make_pair(tokens[label_index], e));
1998 1812
	} else {
1999 1813
	  if (label_index == -1) 
2000 1814
	    throw DataFormatError("Label map not found in file");
2001 1815
	  typename std::map<std::string, Edge>::iterator it =
2002 1816
	    _edge_index.find(tokens[label_index]);
2003 1817
	  if (it == _edge_index.end()) {
2004 1818
	    std::ostringstream msg;
2005 1819
	    msg << "Edge with label not found: " << tokens[label_index];
2006 1820
	    throw DataFormatError(msg.str().c_str());	    
2007 1821
	  }
2008 1822
	  e = it->second;
2009 1823
	}
2010 1824

	
2011 1825
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
2012 1826
	  _edge_maps[i].second->set(e, tokens[map_index[i]]);
2013 1827
	}
2014 1828

	
2015 1829
      }
2016 1830
      if (readSuccess()) {
2017 1831
	line.putback(c);
2018 1832
      }
2019 1833
    }
2020 1834

	
2021 1835
    void readAttributes() {
2022 1836

	
2023 1837
      std::set<std::string> read_attr;
2024 1838

	
2025 1839
      char c;
2026 1840
      while (readLine() && line >> c && c != '@') {
2027 1841
	line.putback(c);
2028 1842
	
2029 1843
	std::string attr, token;
2030 1844
	if (!_reader_bits::readToken(line, attr))
2031 1845
	  throw DataFormatError("Attribute name not found");
2032 1846
	if (!_reader_bits::readToken(line, token))
2033 1847
	  throw DataFormatError("Attribute value not found");
2034 1848
	if (line >> c)
2035 1849
	  throw DataFormatError("Extra character on the end of line");	  
2036 1850

	
2037 1851
	{
2038 1852
	  std::set<std::string>::iterator it = read_attr.find(attr);
2039 1853
	  if (it != read_attr.end()) {
2040 1854
	    std::ostringstream msg;
2041 1855
	    msg << "Multiple occurence of attribute " << attr;
2042 1856
	    throw DataFormatError(msg.str().c_str());
2043 1857
	  }
2044 1858
	  read_attr.insert(attr);
2045 1859
	}
2046 1860
	
2047 1861
	{
2048 1862
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
2049 1863
	  while (it != _attributes.end() && it->first == attr) {
2050 1864
	    it->second->set(token);
2051 1865
	    ++it;
2052 1866
	  }
2053 1867
	}
2054 1868

	
2055 1869
      }
2056 1870
      if (readSuccess()) {
2057 1871
	line.putback(c);
2058 1872
      }
2059 1873
      for (typename Attributes::iterator it = _attributes.begin();
2060 1874
	   it != _attributes.end(); ++it) {
2061 1875
	if (read_attr.find(it->first) == read_attr.end()) {
2062 1876
	  std::ostringstream msg;
2063 1877
	  msg << "Attribute not found in file: " << it->first;
2064 1878
	  throw DataFormatError(msg.str().c_str());
2065 1879
	}	
2066 1880
      }
2067 1881
    }
2068 1882

	
2069 1883
  public:
2070 1884

	
2071 1885
    /// \name Execution of the reader    
2072 1886
    /// @{
2073 1887

	
2074 1888
    /// \brief Start the batch processing
2075 1889
    ///
2076 1890
    /// This function starts the batch processing
2077 1891
    void run() {
2078 1892
      
2079 1893
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2080 1894
      
2081 1895
      bool nodes_done = _skip_nodes;
2082 1896
      bool edges_done = _skip_edges;
2083 1897
      bool attributes_done = false;
2084
      std::set<std::string> extra_sections;
2085 1898

	
2086 1899
      line_num = 0;      
2087 1900
      readLine();
2088 1901
      skipSection();
2089 1902

	
2090 1903
      while (readSuccess()) {
2091 1904
	try {
2092 1905
	  char c;
2093 1906
	  std::string section, caption;
2094 1907
	  line >> c;
2095 1908
	  _reader_bits::readToken(line, section);
2096 1909
	  _reader_bits::readToken(line, caption);
2097 1910

	
2098 1911
	  if (line >> c) 
2099 1912
	    throw DataFormatError("Extra character on the end of line");
2100 1913

	
2101 1914
	  if (section == "nodes" && !nodes_done) {
2102 1915
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
2103 1916
	      readNodes();
2104 1917
	      nodes_done = true;
2105 1918
	    }
2106 1919
	  } else if ((section == "edges" || section == "arcs") && 
2107 1920
		     !edges_done) {
2108 1921
	    if (_edges_caption.empty() || _edges_caption == caption) {
2109 1922
	      readEdges();
2110 1923
	      edges_done = true;
2111 1924
	    }
2112 1925
	  } else if (section == "attributes" && !attributes_done) {
2113 1926
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
2114 1927
	      readAttributes();
2115 1928
	      attributes_done = true;
2116 1929
	    }
2117 1930
	  } else {
2118
	    if (extra_sections.find(section) != extra_sections.end()) {
2119
	      std::ostringstream msg;
2120
	      msg << "Multiple occurence of section " << section;
2121
	      throw DataFormatError(msg.str().c_str());
2122
	    }
2123
	    Sections::iterator it = _sections.find(section);
2124
	    if (it != _sections.end()) {
2125
	      extra_sections.insert(section);
2126
	      it->second->process(*_is, line_num);
2127
	    }
2128 1931
	    readLine();
2129 1932
	    skipSection();
2130 1933
	  }
2131 1934
	} catch (DataFormatError& error) {
2132 1935
	  error.line(line_num);
2133 1936
	  throw;
2134 1937
	}	
2135 1938
      }
2136 1939

	
2137 1940
      if (!nodes_done) {
2138 1941
	throw DataFormatError("Section @nodes not found");
2139 1942
      }
2140 1943

	
2141 1944
      if (!edges_done) {
2142 1945
	throw DataFormatError("Section @edges not found");
2143 1946
      }
2144 1947

	
2145 1948
      if (!attributes_done && !_attributes.empty()) {
2146 1949
	throw DataFormatError("Section @attributes not found");
2147 1950
      }
2148 1951

	
2149 1952
    }
2150 1953

	
2151 1954
    /// @}
2152 1955
    
2153 1956
  };
2154 1957

	
2155 1958
  /// \relates GraphReader
2156 1959
  template <typename Graph>
2157 1960
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
2158 1961
    GraphReader<Graph> tmp(is, graph);
2159 1962
    return tmp;
2160 1963
  }
2161 1964

	
2162 1965
  /// \relates GraphReader
2163 1966
  template <typename Graph>
2164 1967
  GraphReader<Graph> graphReader(const std::string& fn, 
2165 1968
				       Graph& graph) {
2166 1969
    GraphReader<Graph> tmp(fn, graph);
2167 1970
    return tmp;
2168 1971
  }
2169 1972

	
2170 1973
  /// \relates GraphReader
2171 1974
  template <typename Graph>
2172 1975
  GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
2173 1976
    GraphReader<Graph> tmp(fn, graph);
2174 1977
    return tmp;
2175 1978
  }
2176 1979

	
1980
  /// \brief Section reader class
1981
  ///
1982
  /// In the \e LGF file extra sections can be placed, which contain
1983
  /// any data in arbitrary format. Such sections can be read with
1984
  /// this class. A reading rule can be added with two different
1985
  /// functions, with the \c sectionLines() function a functor can
1986
  /// process the section line-by-line. While with the \c
1987
  /// sectionStream() member the section can be read from an input
1988
  /// stream.
1989
  class SectionReader {
1990
  private:
1991
    
1992
    std::istream* _is;
1993
    bool local_is;
1994

	
1995
    typedef std::map<std::string, _reader_bits::Section*> Sections;
1996
    Sections _sections;
1997

	
1998
    int line_num;
1999
    std::istringstream line;
2000

	
2001
  public:
2002

	
2003
    /// \brief Constructor
2004
    ///
2005
    /// Construct a section reader, which reads from the given input
2006
    /// stream.
2007
    SectionReader(std::istream& is) 
2008
      : _is(&is), local_is(false) {}
2009

	
2010
    /// \brief Constructor
2011
    ///
2012
    /// Construct a section reader, which reads from the given file.
2013
    SectionReader(const std::string& fn) 
2014
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2015
    
2016
    /// \brief Constructor
2017
    ///
2018
    /// Construct a section reader, which reads from the given file.
2019
    SectionReader(const char* fn) 
2020
      : _is(new std::ifstream(fn)), local_is(true) {}
2021

	
2022
    /// \brief Copy constructor
2023
    ///
2024
    /// The copy constructor transfers all data from the other reader,
2025
    /// therefore the copied reader will not be usable more. 
2026
    SectionReader(SectionReader& other) 
2027
      : _is(other._is), local_is(other.local_is) {
2028

	
2029
      other._is = 0;
2030
      other.local_is = false;
2031
      
2032
      _sections.swap(other._sections);
2033
    }
2034

	
2035
    /// \brief Destructor
2036
    ~SectionReader() {
2037
      for (Sections::iterator it = _sections.begin(); 
2038
	   it != _sections.end(); ++it) {
2039
	delete it->second;
2040
      }
2041

	
2042
      if (local_is) {
2043
	delete _is;
2044
      }
2045

	
2046
    }
2047

	
2048
  private:
2049
    
2050
    SectionReader& operator=(const SectionReader&);
2051

	
2052
  public:
2053

	
2054
    /// \name Section readers
2055
    /// @{
2056

	
2057
    /// \brief Add a section processor with line oriented reading
2058
    ///
2059
    /// The first parameter is the type descriptor of the section, the
2060
    /// second is a functor, which takes just one \c std::string
2061
    /// parameter. At the reading process, each line of the section
2062
    /// will be given to the functor object. However, the empty lines
2063
    /// and the comment lines are filtered out, and the leading
2064
    /// whitespaces are trimmed from each processed string.
2065
    ///
2066
    /// For example let's see a section, which contain several
2067
    /// integers, which should be inserted into a vector.
2068
    ///\code
2069
    ///  @numbers
2070
    ///  12 45 23
2071
    ///  4
2072
    ///  23 6
2073
    ///\endcode
2074
    ///
2075
    /// The functor is implemented as an struct:
2076
    ///\code
2077
    ///  struct NumberSection {
2078
    ///    std::vector<int>& _data;
2079
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
2080
    ///    void operator()(const std::string& line) {
2081
    ///      std::istringstream ls(line);
2082
    ///      int value;
2083
    ///      while (ls >> value) _data.push_back(value);
2084
    ///    }
2085
    ///  };
2086
    ///
2087
    ///  // ...
2088
    ///
2089
    ///  reader.sectionLines("numbers", NumberSection(vec));  
2090
    ///\endcode
2091
    template <typename Functor>
2092
    SectionReader& sectionLines(const std::string& type, Functor functor) {
2093
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
2094
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
2095
		   "Multiple reading of section.");
2096
      _sections.insert(std::make_pair(type, 
2097
        new _reader_bits::LineSection<Functor>(functor)));
2098
      return *this;
2099
    }
2100

	
2101

	
2102
    /// \brief Add a section processor with stream oriented reading
2103
    ///
2104
    /// The first parameter is the type of the section, the second is
2105
    /// a functor, which takes an \c std::istream& and an int&
2106
    /// parameter, the latter regard to the line number of stream. The
2107
    /// functor can read the input while the section go on, and the
2108
    /// line number should be modified accordingly.
2109
    template <typename Functor>
2110
    SectionReader& sectionStream(const std::string& type, Functor functor) {
2111
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
2112
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
2113
		   "Multiple reading of section.");
2114
      _sections.insert(std::make_pair(type, 
2115
	 new _reader_bits::StreamSection<Functor>(functor)));
2116
      return *this;
2117
    }    
2118
    
2119
    /// @}
2120

	
2121
  private:
2122

	
2123
    bool readLine() {
2124
      std::string str;
2125
      while(++line_num, std::getline(*_is, str)) {
2126
	line.clear(); line.str(str);
2127
	char c;
2128
	if (line >> std::ws >> c && c != '#') {
2129
	  line.putback(c);
2130
	  return true;
2131
	}
2132
      }
2133
      return false;
2134
    }
2135

	
2136
    bool readSuccess() {
2137
      return static_cast<bool>(*_is);
2138
    }
2139
    
2140
    void skipSection() {
2141
      char c;
2142
      while (readSuccess() && line >> c && c != '@') {
2143
	readLine();
2144
      }
2145
      line.putback(c);
2146
    }
2147

	
2148
  public:
2149

	
2150

	
2151
    /// \name Execution of the reader    
2152
    /// @{
2153

	
2154
    /// \brief Start the batch processing
2155
    ///
2156
    /// This function starts the batch processing
2157
    void run() {
2158
      
2159
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2160
      
2161
      std::set<std::string> extra_sections;
2162

	
2163
      line_num = 0;      
2164
      readLine();
2165
      skipSection();
2166

	
2167
      while (readSuccess()) {
2168
	try {
2169
	  char c;
2170
	  std::string section, caption;
2171
	  line >> c;
2172
	  _reader_bits::readToken(line, section);
2173
	  _reader_bits::readToken(line, caption);
2174

	
2175
	  if (line >> c) 
2176
	    throw DataFormatError("Extra character on the end of line");
2177

	
2178
	  if (extra_sections.find(section) != extra_sections.end()) {
2179
	    std::ostringstream msg;
2180
	    msg << "Multiple occurence of section " << section;
2181
	    throw DataFormatError(msg.str().c_str());
2182
	  }
2183
	  Sections::iterator it = _sections.find(section);
2184
	  if (it != _sections.end()) {
2185
	    extra_sections.insert(section);
2186
	    it->second->process(*_is, line_num);
2187
	  }
2188
	  readLine();
2189
	  skipSection();
2190
	} catch (DataFormatError& error) {
2191
	  error.line(line_num);
2192
	  throw;
2193
	}	
2194
      }
2195
      for (Sections::iterator it = _sections.begin();
2196
	   it != _sections.end(); ++it) {
2197
	if (extra_sections.find(it->first) == extra_sections.end()) {
2198
	  std::ostringstream os;
2199
	  os << "Cannot find section: " << it->first;
2200
	  throw DataFormatError(os.str().c_str());
2201
	}
2202
      }
2203
    }
2204

	
2205
    /// @}
2206
        
2207
  };
2208

	
2209
  /// \relates SectionReader
2210
  inline SectionReader sectionReader(std::istream& is) {
2211
    SectionReader tmp(is);
2212
    return tmp;
2213
  }
2214

	
2215
  /// \relates SectionReader
2216
  inline SectionReader sectionReader(const std::string& fn) {
2217
    SectionReader tmp(fn);
2218
    return tmp;
2219
  }
2220

	
2221
  /// \relates SectionReader
2222
  inline SectionReader sectionReader(const char* fn) {
2223
    SectionReader tmp(fn);
2224
    return tmp;
2225
  }
2226

	
2177 2227
  /// \ingroup lemon_io
2178 2228
  ///
2179 2229
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file 
2180 2230
  ///
2181 2231
  /// This class can be used to read the sections, the map names and
2182 2232
  /// the attributes from a file. Usually, the Lemon programs know
2183 2233
  /// that, which type of graph, which maps and which attributes
2184 2234
  /// should be read from a file, but in general tools (like glemon)
2185 2235
  /// the contents of an LGF file should be guessed somehow. This class
2186 2236
  /// reads the graph and stores the appropriate information for
2187 2237
  /// reading the graph.
2188 2238
  ///
2189 2239
  ///\code LgfContents contents("graph.lgf"); 
2190 2240
  /// contents.run();
2191 2241
  ///
2192 2242
  /// // does it contain any node section and arc section
2193 2243
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
2194 2244
  ///   std::cerr << "Failure, cannot find graph" << std::endl;
2195 2245
  ///   return -1;
2196 2246
  /// }
2197 2247
  /// std::cout << "The name of the default node section : " 
2198 2248
  ///           << contents.nodeSection(0) << std::endl;
2199 2249
  /// std::cout << "The number of the arc maps : " 
2200 2250
  ///           << contents.arcMaps(0).size() << std::endl;
2201 2251
  /// std::cout << "The name of second arc map : " 
2202 2252
  ///           << contents.arcMaps(0)[1] << std::endl;
2203 2253
  ///\endcode
2204 2254
  class LgfContents {    
2205 2255
  private:
2206 2256

	
2207 2257
    std::istream* _is;
2208 2258
    bool local_is;
2209 2259

	
2210 2260
    std::vector<std::string> _node_sections;
2211 2261
    std::vector<std::string> _edge_sections;
2212 2262
    std::vector<std::string> _attribute_sections;
2213 2263
    std::vector<std::string> _extra_sections;
2214 2264

	
2215 2265
    std::vector<bool> _arc_sections;
2216 2266

	
2217 2267
    std::vector<std::vector<std::string> > _node_maps;
2218 2268
    std::vector<std::vector<std::string> > _edge_maps;
2219 2269

	
2220 2270
    std::vector<std::vector<std::string> > _attributes;
2221 2271

	
2222 2272

	
2223 2273
    int line_num;
2224 2274
    std::istringstream line;
2225 2275
    
2226 2276
  public:
2227 2277

	
2228 2278
    /// \brief Constructor
2229 2279
    ///
2230 2280
    /// Construct an \e LGF contents reader, which reads from the given
2231 2281
    /// input stream.
2232 2282
    LgfContents(std::istream& is) 
2233 2283
      : _is(&is), local_is(false) {}
2234 2284

	
2235 2285
    /// \brief Constructor
2236 2286
    ///
2237 2287
    /// Construct an \e LGF contents reader, which reads from the given
2238 2288
    /// file.
2239 2289
    LgfContents(const std::string& fn) 
2240 2290
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2241 2291

	
2242 2292
    /// \brief Constructor
2243 2293
    ///
2244 2294
    /// Construct an \e LGF contents reader, which reads from the given
2245 2295
    /// file.
2246 2296
    LgfContents(const char* fn)
2247 2297
      : _is(new std::ifstream(fn)), local_is(true) {}
2248 2298

	
2249 2299
    /// \brief Copy constructor
2250 2300
    ///
2251 2301
    /// The copy constructor transfers all data from the other reader,
2252 2302
    /// therefore the copied reader will not be usable more. 
2253 2303
    LgfContents(LgfContents& other)
2254 2304
      : _is(other._is), local_is(other.local_is) {
2255 2305
      
2256 2306
      other._is = 0;
2257 2307
      other.local_is = false;
2258 2308
      
2259 2309
      _node_sections.swap(other._node_sections);
2260 2310
      _edge_sections.swap(other._edge_sections);
2261 2311
      _attribute_sections.swap(other._attribute_sections);
2262 2312
      _extra_sections.swap(other._extra_sections);
2263 2313

	
2264 2314
      _arc_sections.swap(other._arc_sections);
2265 2315

	
2266 2316
      _node_maps.swap(other._node_maps);
2267 2317
      _edge_maps.swap(other._edge_maps);
2268 2318
      _attributes.swap(other._attributes);
2269 2319
    }
2270 2320
    
2271 2321
    /// \brief Destructor
2272 2322
    ~LgfContents() {
0 comments (0 inline)