gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge bugfix #193
0 1 0
merge 1.0
0 files changed with 12 insertions and 4 deletions:
↑ Collapse diff ↑
Ignore white space 384 line context
... ...
@@ -681,385 +681,387 @@
681 681
      _attributes.insert(std::make_pair(caption, storage));
682 682
      return *this;
683 683
    }
684 684

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

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

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

	
722 722
    /// @}
723 723

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

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

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

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

	
751 751
    /// @}
752 752

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

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

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

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

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

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

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

	
847 847
    /// @}
848 848

	
849 849
  private:
850 850

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

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

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

	
876 878
    void readNodes() {
877 879

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

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

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

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

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

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

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

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

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

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

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

	
969 971
    void readArcs() {
970 972

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

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

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

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

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

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

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

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

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

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

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

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

	
1046 1048
          typename NodeIndex::iterator it;
1047 1049

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

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

	
1064 1066
          a = _digraph.addArc(source, target);
1065 1067
          if (label_index != -1)
... ...
@@ -1510,385 +1512,387 @@
1510 1512
      _attributes.insert(std::make_pair(caption, storage));
1511 1513
      return *this;
1512 1514
    }
1513 1515

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

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

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

	
1550 1552
    /// @}
1551 1553

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

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

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

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

	
1579 1581
    /// @}
1580 1582

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

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

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

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

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

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

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

	
1676 1678
    /// @}
1677 1679

	
1678 1680
  private:
1679 1681

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

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

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

	
1705 1709
    void readNodes() {
1706 1710

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

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

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

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

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

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

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

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

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

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

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

	
1798 1802
    void readEdges() {
1799 1803

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

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

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

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

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

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

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

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

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

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

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

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

	
1875 1879
          typename NodeIndex::iterator it;
1876 1880

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

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

	
1893 1897
          e = _graph.addEdge(source, target);
1894 1898
          if (label_index != -1)
... ...
@@ -2037,612 +2041,616 @@
2037 2041
    }
2038 2042

	
2039 2043
    /// @}
2040 2044

	
2041 2045
  };
2042 2046

	
2043 2047
  class SectionReader;
2044 2048

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

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

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

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

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

	
2073 2077
  public:
2074 2078

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

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

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

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

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

	
2117 2121
    }
2118 2122

	
2119 2123
  private:
2120 2124

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

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

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

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

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

	
2136 2140
  public:
2137 2141

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

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

	
2185 2189

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

	
2203 2207
    /// @}
2204 2208

	
2205 2209
  private:
2206 2210

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

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

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

	
2232 2238
  public:
2233 2239

	
2234 2240

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

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

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

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

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

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

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

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

	
2290 2296
    /// @}
2291 2297

	
2292 2298
  };
2293 2299

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

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

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

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

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

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

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

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

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

	
2367 2373

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

	
2371 2377
  public:
2372 2378

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

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

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

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

	
2409 2415
  private:
2410 2416

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

	
2414 2420
  public:
2415 2421

	
2416 2422

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

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

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

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

	
2441 2447
    /// @}
2442 2448

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

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

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

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

	
2470 2476
    /// @}
2471 2477

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

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

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

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

	
2499 2505
    /// @}
2500 2506

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

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

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

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

	
2525 2531
    /// @}
2526 2532

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

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

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

	
2544 2550
    /// @}
2545 2551

	
2546 2552
  private:
2547 2553

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

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

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

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

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

	
2599 2607
  public:
2600 2608

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

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

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

	
2612 2620
      while (readSuccess()) {
2613 2621

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

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

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

	
2643 2651
    /// @}
2644 2652

	
2645 2653
  };
2646 2654
}
2647 2655

	
2648 2656
#endif
0 comments (0 inline)