gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge
0 1 0
merge default
0 files changed with 12 insertions and 4 deletions:
↑ Collapse diff ↑
Ignore white space 192 line context
... ...
@@ -777,193 +777,195 @@
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() {
... ...
@@ -1606,193 +1608,195 @@
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() {
... ...
@@ -2133,193 +2137,195 @@
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
... ...
@@ -2474,175 +2480,177 @@
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)