1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2013
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
21 ///\brief \ref lgf-format "LEMON Graph Format" reader.
24 #ifndef LEMON_LGF_READER_H
25 #define LEMON_LGF_READER_H
34 #include <lemon/core.h>
36 #include <lemon/lgf_writer.h>
38 #include <lemon/concept_check.h>
39 #include <lemon/concepts/maps.h>
43 namespace _reader_bits {
45 template <typename Value>
46 struct DefaultConverter {
47 Value operator()(const std::string& str) {
48 std::istringstream is(str);
51 throw FormatError("Cannot read token");
55 if (is >> std::ws >> c) {
56 throw FormatError("Remaining characters in token");
63 struct DefaultConverter<std::string> {
64 std::string operator()(const std::string& str) {
69 template <typename _Item>
70 class MapStorageBase {
76 virtual ~MapStorageBase() {}
78 virtual void set(const Item& item, const std::string& value) = 0;
82 template <typename _Item, typename _Map,
83 typename _Converter = DefaultConverter<typename _Map::Value> >
84 class MapStorage : public MapStorageBase<_Item> {
87 typedef _Converter Converter;
95 MapStorage(Map& map, const Converter& converter = Converter())
96 : _map(map), _converter(converter) {}
97 virtual ~MapStorage() {}
99 virtual void set(const Item& item ,const std::string& value) {
100 _map.set(item, _converter(value));
104 template <typename _GR, bool _dir, typename _Map,
105 typename _Converter = DefaultConverter<typename _Map::Value> >
106 class GraphArcMapStorage : public MapStorageBase<typename _GR::Edge> {
109 typedef _Converter Converter;
111 typedef typename GR::Edge Item;
112 static const bool dir = _dir;
117 Converter _converter;
120 GraphArcMapStorage(const GR& graph, Map& map,
121 const Converter& converter = Converter())
122 : _graph(graph), _map(map), _converter(converter) {}
123 virtual ~GraphArcMapStorage() {}
125 virtual void set(const Item& item ,const std::string& value) {
126 _map.set(_graph.direct(item, dir), _converter(value));
130 class ValueStorageBase {
132 ValueStorageBase() {}
133 virtual ~ValueStorageBase() {}
135 virtual void set(const std::string&) = 0;
138 template <typename _Value, typename _Converter = DefaultConverter<_Value> >
139 class ValueStorage : public ValueStorageBase {
141 typedef _Value Value;
142 typedef _Converter Converter;
146 Converter _converter;
149 ValueStorage(Value& value, const Converter& converter = Converter())
150 : _value(value), _converter(converter) {}
152 virtual void set(const std::string& value) {
153 _value = _converter(value);
157 template <typename Value,
158 typename Map = std::map<std::string, Value> >
159 struct MapLookUpConverter {
162 MapLookUpConverter(const Map& map)
165 Value operator()(const std::string& str) {
166 typename Map::const_iterator it = _map.find(str);
167 if (it == _map.end()) {
168 std::ostringstream msg;
169 msg << "Item not found: " << str;
170 throw FormatError(msg.str());
176 template <typename Value,
177 typename Map1 = std::map<std::string, Value>,
178 typename Map2 = std::map<std::string, Value> >
179 struct DoubleMapLookUpConverter {
183 DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
184 : _map1(map1), _map2(map2) {}
186 Value operator()(const std::string& str) {
187 typename Map1::const_iterator it1 = _map1.find(str);
188 typename Map2::const_iterator it2 = _map2.find(str);
189 if (it1 == _map1.end()) {
190 if (it2 == _map2.end()) {
191 std::ostringstream msg;
192 msg << "Item not found: " << str;
193 throw FormatError(msg.str());
198 if (it2 == _map2.end()) {
201 std::ostringstream msg;
202 msg << "Item is ambigous: " << str;
203 throw FormatError(msg.str());
209 template <typename GR>
210 struct GraphArcLookUpConverter {
212 const std::map<std::string, typename GR::Edge>& _map;
214 GraphArcLookUpConverter(const GR& graph,
215 const std::map<std::string,
216 typename GR::Edge>& map)
217 : _graph(graph), _map(map) {}
219 typename GR::Arc operator()(const std::string& str) {
220 if (str.empty() || (str[0] != '+' && str[0] != '-')) {
221 throw FormatError("Item must start with '+' or '-'");
223 typename std::map<std::string, typename GR::Edge>
224 ::const_iterator it = _map.find(str.substr(1));
225 if (it == _map.end()) {
226 throw FormatError("Item not found");
228 return _graph.direct(it->second, str[0] == '+');
232 inline bool isWhiteSpace(char c) {
233 return c == ' ' || c == '\t' || c == '\v' ||
234 c == '\n' || c == '\r' || c == '\f';
237 inline bool isOct(char c) {
238 return '0' <= c && c <='7';
241 inline int valueOct(char c) {
242 LEMON_ASSERT(isOct(c), "The character is not octal.");
246 inline bool isHex(char c) {
247 return ('0' <= c && c <= '9') ||
248 ('a' <= c && c <= 'z') ||
249 ('A' <= c && c <= 'Z');
252 inline int valueHex(char c) {
253 LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
254 if ('0' <= c && c <= '9') return c - '0';
255 if ('a' <= c && c <= 'z') return c - 'a' + 10;
259 inline bool isIdentifierFirstChar(char c) {
260 return ('a' <= c && c <= 'z') ||
261 ('A' <= c && c <= 'Z') || c == '_';
264 inline bool isIdentifierChar(char c) {
265 return isIdentifierFirstChar(c) ||
266 ('0' <= c && c <= '9');
269 inline char readEscape(std::istream& is) {
272 throw FormatError("Escape format error");
300 if (!is.get(c) || !isHex(c))
301 throw FormatError("Escape format error");
302 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
303 else code = code * 16 + valueHex(c);
310 throw FormatError("Escape format error");
311 else if (code = valueOct(c), !is.get(c) || !isOct(c))
313 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
315 else code = code * 8 + valueOct(c);
321 inline std::istream& readToken(std::istream& is, std::string& str) {
322 std::ostringstream os;
331 while (is.get(c) && c != '\"') {
337 throw FormatError("Quoted format error");
340 while (is.get(c) && !isWhiteSpace(c)) {
357 virtual ~Section() {}
358 virtual void process(std::istream& is, int& line_num) = 0;
361 template <typename Functor>
362 class LineSection : public Section {
369 LineSection(const Functor& functor) : _functor(functor) {}
370 virtual ~LineSection() {}
372 virtual void process(std::istream& is, int& line_num) {
375 while (is.get(c) && c != '@') {
378 } else if (c == '#') {
381 } else if (!isWhiteSpace(c)) {
388 if (is) is.putback(c);
389 else if (is.eof()) is.clear();
393 template <typename Functor>
394 class StreamSection : public Section {
401 StreamSection(const Functor& functor) : _functor(functor) {}
402 virtual ~StreamSection() {}
404 virtual void process(std::istream& is, int& line_num) {
405 _functor(is, line_num);
408 while (is.get(c) && c != '@') {
411 } else if (!isWhiteSpace(c)) {
416 if (is) is.putback(c);
417 else if (is.eof()) is.clear();
423 template <typename DGR>
426 template <typename TDGR>
427 DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is = std::cin);
428 template <typename TDGR>
429 DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn);
430 template <typename TDGR>
431 DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
433 /// \ingroup lemon_io
435 /// \brief \ref lgf-format "LGF" reader for directed graphs
437 /// This utility reads an \ref lgf-format "LGF" file.
439 /// The reading method does a batch processing. The user creates a
440 /// reader object, then various reading rules can be added to the
441 /// reader, and eventually the reading is executed with the \c run()
442 /// member function. A map reading rule can be added to the reader
443 /// with the \c nodeMap() or \c arcMap() members. An optional
444 /// converter parameter can also be added as a standard functor
445 /// converting from \c std::string to the value type of the map. If it
446 /// is set, it will determine how the tokens in the file should be
447 /// converted to the value type of the map. If the functor is not set,
448 /// then a default conversion will be used. One map can be read into
449 /// multiple map objects at the same time. The \c attribute(), \c
450 /// node() and \c arc() functions are used to add attribute reading
454 /// DigraphReader<DGR>(digraph, std::cin).
455 /// nodeMap("coordinates", coord_map).
456 /// arcMap("capacity", cap_map).
457 /// node("source", src).
458 /// node("target", trg).
459 /// attribute("caption", caption).
463 /// By default, the reader uses the first section in the file of the
464 /// proper type. If a section has an optional name, then it can be
465 /// selected for reading by giving an optional name parameter to the
466 /// \c nodes(), \c arcs() or \c attributes() functions.
468 /// The \c useNodes() and \c useArcs() functions are used to tell the reader
469 /// that the nodes or arcs should not be constructed (added to the
470 /// graph) during the reading, but instead the label map of the items
471 /// are given as a parameter of these functions. An
472 /// application of these functions is multipass reading, which is
473 /// important if two \c \@arcs sections must be read from the
474 /// file. In this case the first phase would read the node set and one
475 /// of the arc sets, while the second phase would read the second arc
476 /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
477 /// The previously read label node map should be passed to the \c
478 /// useNodes() functions. Another application of multipass reading when
479 /// paths are given as a node map or an arc map.
480 /// It is impossible to read this in
481 /// a single pass, because the arcs are not constructed when the node
483 template <typename DGR>
484 class DigraphReader {
491 TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
495 std::string _filename;
499 std::string _nodes_caption;
500 std::string _arcs_caption;
501 std::string _attributes_caption;
503 typedef std::map<std::string, Node> NodeIndex;
504 NodeIndex _node_index;
505 typedef std::map<std::string, Arc> ArcIndex;
508 typedef std::vector<std::pair<std::string,
509 _reader_bits::MapStorageBase<Node>*> > NodeMaps;
512 typedef std::vector<std::pair<std::string,
513 _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
516 typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
518 Attributes _attributes;
527 std::istringstream line;
531 /// \brief Constructor
533 /// Construct a directed graph reader, which reads from the given
535 DigraphReader(DGR& digraph, std::istream& is = std::cin)
536 : _is(&is), local_is(false), _digraph(digraph),
537 _use_nodes(false), _use_arcs(false),
538 _skip_nodes(false), _skip_arcs(false) {}
540 /// \brief Constructor
542 /// Construct a directed graph reader, which reads from the given
544 DigraphReader(DGR& digraph, const std::string& fn)
545 : _is(new std::ifstream(fn.c_str())), local_is(true),
546 _filename(fn), _digraph(digraph),
547 _use_nodes(false), _use_arcs(false),
548 _skip_nodes(false), _skip_arcs(false) {
551 throw IoError("Cannot open file", fn);
555 /// \brief Constructor
557 /// Construct a directed graph reader, which reads from the given
559 DigraphReader(DGR& digraph, const char* fn)
560 : _is(new std::ifstream(fn)), local_is(true),
561 _filename(fn), _digraph(digraph),
562 _use_nodes(false), _use_arcs(false),
563 _skip_nodes(false), _skip_arcs(false) {
566 throw IoError("Cannot open file", fn);
570 /// \brief Destructor
572 for (typename NodeMaps::iterator it = _node_maps.begin();
573 it != _node_maps.end(); ++it) {
577 for (typename ArcMaps::iterator it = _arc_maps.begin();
578 it != _arc_maps.end(); ++it) {
582 for (typename Attributes::iterator it = _attributes.begin();
583 it != _attributes.end(); ++it) {
595 template <typename TDGR>
596 friend DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is);
597 template <typename TDGR>
598 friend DigraphReader<TDGR> digraphReader(TDGR& digraph,
599 const std::string& fn);
600 template <typename TDGR>
601 friend DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
603 DigraphReader(DigraphReader& other)
604 : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
605 _use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
606 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
609 other.local_is = false;
611 _node_index.swap(other._node_index);
612 _arc_index.swap(other._arc_index);
614 _node_maps.swap(other._node_maps);
615 _arc_maps.swap(other._arc_maps);
616 _attributes.swap(other._attributes);
618 _nodes_caption = other._nodes_caption;
619 _arcs_caption = other._arcs_caption;
620 _attributes_caption = other._attributes_caption;
624 DigraphReader& operator=(const DigraphReader&);
628 /// \name Reading Rules
631 /// \brief Node map reading rule
633 /// Add a node map reading rule to the reader.
634 template <typename Map>
635 DigraphReader& nodeMap(const std::string& caption, Map& map) {
636 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
637 _reader_bits::MapStorageBase<Node>* storage =
638 new _reader_bits::MapStorage<Node, Map>(map);
639 _node_maps.push_back(std::make_pair(caption, storage));
643 /// \brief Node map reading rule
645 /// Add a node map reading rule with specialized converter to the
647 template <typename Map, typename Converter>
648 DigraphReader& nodeMap(const std::string& caption, Map& map,
649 const Converter& converter = Converter()) {
650 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
651 _reader_bits::MapStorageBase<Node>* storage =
652 new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
653 _node_maps.push_back(std::make_pair(caption, storage));
657 /// \brief Arc map reading rule
659 /// Add an arc map reading rule to the reader.
660 template <typename Map>
661 DigraphReader& arcMap(const std::string& caption, Map& map) {
662 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
663 _reader_bits::MapStorageBase<Arc>* storage =
664 new _reader_bits::MapStorage<Arc, Map>(map);
665 _arc_maps.push_back(std::make_pair(caption, storage));
669 /// \brief Arc map reading rule
671 /// Add an arc map reading rule with specialized converter to the
673 template <typename Map, typename Converter>
674 DigraphReader& arcMap(const std::string& caption, Map& map,
675 const Converter& converter = Converter()) {
676 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
677 _reader_bits::MapStorageBase<Arc>* storage =
678 new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
679 _arc_maps.push_back(std::make_pair(caption, storage));
683 /// \brief Attribute reading rule
685 /// Add an attribute reading rule to the reader.
686 template <typename Value>
687 DigraphReader& attribute(const std::string& caption, Value& value) {
688 _reader_bits::ValueStorageBase* storage =
689 new _reader_bits::ValueStorage<Value>(value);
690 _attributes.insert(std::make_pair(caption, storage));
694 /// \brief Attribute reading rule
696 /// Add an attribute reading rule with specialized converter to the
698 template <typename Value, typename Converter>
699 DigraphReader& attribute(const std::string& caption, Value& value,
700 const Converter& converter = Converter()) {
701 _reader_bits::ValueStorageBase* storage =
702 new _reader_bits::ValueStorage<Value, Converter>(value, converter);
703 _attributes.insert(std::make_pair(caption, storage));
707 /// \brief Node reading rule
709 /// Add a node reading rule to reader.
710 DigraphReader& node(const std::string& caption, Node& node) {
711 typedef _reader_bits::MapLookUpConverter<Node> Converter;
712 Converter converter(_node_index);
713 _reader_bits::ValueStorageBase* storage =
714 new _reader_bits::ValueStorage<Node, Converter>(node, converter);
715 _attributes.insert(std::make_pair(caption, storage));
719 /// \brief Arc reading rule
721 /// Add an arc reading rule to reader.
722 DigraphReader& arc(const std::string& caption, Arc& arc) {
723 typedef _reader_bits::MapLookUpConverter<Arc> Converter;
724 Converter converter(_arc_index);
725 _reader_bits::ValueStorageBase* storage =
726 new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
727 _attributes.insert(std::make_pair(caption, storage));
733 /// \name Select Section by Name
736 /// \brief Set \c \@nodes section to be read
738 /// Set \c \@nodes section to be read
739 DigraphReader& nodes(const std::string& caption) {
740 _nodes_caption = caption;
744 /// \brief Set \c \@arcs section to be read
746 /// Set \c \@arcs section to be read
747 DigraphReader& arcs(const std::string& caption) {
748 _arcs_caption = caption;
752 /// \brief Set \c \@attributes section to be read
754 /// Set \c \@attributes section to be read
755 DigraphReader& attributes(const std::string& caption) {
756 _attributes_caption = caption;
762 /// \name Using Previously Constructed Node or Arc Set
765 /// \brief Use previously constructed node set
767 /// Use previously constructed node set, and specify the node
769 template <typename Map>
770 DigraphReader& useNodes(const Map& map) {
771 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
772 LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
774 _writer_bits::DefaultConverter<typename Map::Value> converter;
775 for (NodeIt n(_digraph); n != INVALID; ++n) {
776 _node_index.insert(std::make_pair(converter(map[n]), n));
781 /// \brief Use previously constructed node set
783 /// Use previously constructed node set, and specify the node
784 /// label map and a functor which converts the label map values to
786 template <typename Map, typename Converter>
787 DigraphReader& useNodes(const Map& map,
788 const Converter& converter = Converter()) {
789 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
790 LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
792 for (NodeIt n(_digraph); n != INVALID; ++n) {
793 _node_index.insert(std::make_pair(converter(map[n]), n));
798 /// \brief Use previously constructed arc set
800 /// Use previously constructed arc set, and specify the arc
802 template <typename Map>
803 DigraphReader& useArcs(const Map& map) {
804 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
805 LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
807 _writer_bits::DefaultConverter<typename Map::Value> converter;
808 for (ArcIt a(_digraph); a != INVALID; ++a) {
809 _arc_index.insert(std::make_pair(converter(map[a]), a));
814 /// \brief Use previously constructed arc set
816 /// Use previously constructed arc set, and specify the arc
817 /// label map and a functor which converts the label map values to
819 template <typename Map, typename Converter>
820 DigraphReader& useArcs(const Map& map,
821 const Converter& converter = Converter()) {
822 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
823 LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
825 for (ArcIt a(_digraph); a != INVALID; ++a) {
826 _arc_index.insert(std::make_pair(converter(map[a]), a));
831 /// \brief Skips the reading of node section
833 /// Omit the reading of the node section. This implies that each node
834 /// map reading rule will be abandoned, and the nodes of the graph
835 /// will not be constructed, which usually cause that the arc set
836 /// could not be read due to lack of node name resolving.
837 /// Therefore \c skipArcs() function should also be used, or
838 /// \c useNodes() should be used to specify the label of the nodes.
839 DigraphReader& skipNodes() {
840 LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
845 /// \brief Skips the reading of arc section
847 /// Omit the reading of the arc section. This implies that each arc
848 /// map reading rule will be abandoned, and the arcs of the graph
849 /// will not be constructed.
850 DigraphReader& skipArcs() {
851 LEMON_ASSERT(!_skip_arcs, "Skip arcs already set");
862 while(++line_num, std::getline(*_is, str)) {
863 line.clear(); line.str(str);
865 if (line >> std::ws >> c && c != '#') {
874 return static_cast<bool>(*_is);
879 while (readSuccess() && line >> c && c != '@') {
889 std::vector<int> map_index(_node_maps.size());
890 int map_num, label_index;
893 if (!readLine() || !(line >> c) || c == '@') {
894 if (readSuccess() && line) line.putback(c);
895 if (!_node_maps.empty())
896 throw FormatError("Cannot find map names");
902 std::map<std::string, int> maps;
906 while (_reader_bits::readToken(line, map)) {
907 if (maps.find(map) != maps.end()) {
908 std::ostringstream msg;
909 msg << "Multiple occurence of node map: " << map;
910 throw FormatError(msg.str());
912 maps.insert(std::make_pair(map, index));
916 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
917 std::map<std::string, int>::iterator jt =
918 maps.find(_node_maps[i].first);
919 if (jt == maps.end()) {
920 std::ostringstream msg;
921 msg << "Map not found: " << _node_maps[i].first;
922 throw FormatError(msg.str());
924 map_index[i] = jt->second;
928 std::map<std::string, int>::iterator jt = maps.find("label");
929 if (jt != maps.end()) {
930 label_index = jt->second;
935 map_num = maps.size();
938 while (readLine() && line >> c && c != '@') {
941 std::vector<std::string> tokens(map_num);
942 for (int i = 0; i < map_num; ++i) {
943 if (!_reader_bits::readToken(line, tokens[i])) {
944 std::ostringstream msg;
945 msg << "Column not found (" << i + 1 << ")";
946 throw FormatError(msg.str());
949 if (line >> std::ws >> c)
950 throw FormatError("Extra character at the end of line");
954 n = _digraph.addNode();
955 if (label_index != -1)
956 _node_index.insert(std::make_pair(tokens[label_index], n));
958 if (label_index == -1)
959 throw FormatError("Label map not found");
960 typename std::map<std::string, Node>::iterator it =
961 _node_index.find(tokens[label_index]);
962 if (it == _node_index.end()) {
963 std::ostringstream msg;
964 msg << "Node with label not found: " << tokens[label_index];
965 throw FormatError(msg.str());
970 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
971 _node_maps[i].second->set(n, tokens[map_index[i]]);
982 std::vector<int> map_index(_arc_maps.size());
983 int map_num, label_index;
986 if (!readLine() || !(line >> c) || c == '@') {
987 if (readSuccess() && line) line.putback(c);
988 if (!_arc_maps.empty())
989 throw FormatError("Cannot find map names");
995 std::map<std::string, int> maps;
999 while (_reader_bits::readToken(line, map)) {
1002 throw FormatError("'-' is not allowed as a map name");
1003 else if (line >> std::ws >> c)
1004 throw FormatError("Extra character at the end of line");
1007 if (maps.find(map) != maps.end()) {
1008 std::ostringstream msg;
1009 msg << "Multiple occurence of arc map: " << map;
1010 throw FormatError(msg.str());
1012 maps.insert(std::make_pair(map, index));
1016 for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1017 std::map<std::string, int>::iterator jt =
1018 maps.find(_arc_maps[i].first);
1019 if (jt == maps.end()) {
1020 std::ostringstream msg;
1021 msg << "Map not found: " << _arc_maps[i].first;
1022 throw FormatError(msg.str());
1024 map_index[i] = jt->second;
1028 std::map<std::string, int>::iterator jt = maps.find("label");
1029 if (jt != maps.end()) {
1030 label_index = jt->second;
1035 map_num = maps.size();
1038 while (readLine() && line >> c && c != '@') {
1041 std::string source_token;
1042 std::string target_token;
1044 if (!_reader_bits::readToken(line, source_token))
1045 throw FormatError("Source not found");
1047 if (!_reader_bits::readToken(line, target_token))
1048 throw FormatError("Target not found");
1050 std::vector<std::string> tokens(map_num);
1051 for (int i = 0; i < map_num; ++i) {
1052 if (!_reader_bits::readToken(line, tokens[i])) {
1053 std::ostringstream msg;
1054 msg << "Column not found (" << i + 1 << ")";
1055 throw FormatError(msg.str());
1058 if (line >> std::ws >> c)
1059 throw FormatError("Extra character at the end of line");
1064 typename NodeIndex::iterator it;
1066 it = _node_index.find(source_token);
1067 if (it == _node_index.end()) {
1068 std::ostringstream msg;
1069 msg << "Item not found: " << source_token;
1070 throw FormatError(msg.str());
1072 Node source = it->second;
1074 it = _node_index.find(target_token);
1075 if (it == _node_index.end()) {
1076 std::ostringstream msg;
1077 msg << "Item not found: " << target_token;
1078 throw FormatError(msg.str());
1080 Node target = it->second;
1082 a = _digraph.addArc(source, target);
1083 if (label_index != -1)
1084 _arc_index.insert(std::make_pair(tokens[label_index], a));
1086 if (label_index == -1)
1087 throw FormatError("Label map not found");
1088 typename std::map<std::string, Arc>::iterator it =
1089 _arc_index.find(tokens[label_index]);
1090 if (it == _arc_index.end()) {
1091 std::ostringstream msg;
1092 msg << "Arc with label not found: " << tokens[label_index];
1093 throw FormatError(msg.str());
1098 for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1099 _arc_maps[i].second->set(a, tokens[map_index[i]]);
1103 if (readSuccess()) {
1108 void readAttributes() {
1110 std::set<std::string> read_attr;
1113 while (readLine() && line >> c && c != '@') {
1116 std::string attr, token;
1117 if (!_reader_bits::readToken(line, attr))
1118 throw FormatError("Attribute name not found");
1119 if (!_reader_bits::readToken(line, token))
1120 throw FormatError("Attribute value not found");
1122 throw FormatError("Extra character at the end of line");
1125 std::set<std::string>::iterator it = read_attr.find(attr);
1126 if (it != read_attr.end()) {
1127 std::ostringstream msg;
1128 msg << "Multiple occurence of attribute: " << attr;
1129 throw FormatError(msg.str());
1131 read_attr.insert(attr);
1135 typename Attributes::iterator it = _attributes.lower_bound(attr);
1136 while (it != _attributes.end() && it->first == attr) {
1137 it->second->set(token);
1143 if (readSuccess()) {
1146 for (typename Attributes::iterator it = _attributes.begin();
1147 it != _attributes.end(); ++it) {
1148 if (read_attr.find(it->first) == read_attr.end()) {
1149 std::ostringstream msg;
1150 msg << "Attribute not found: " << it->first;
1151 throw FormatError(msg.str());
1158 /// \name Execution of the Reader
1161 /// \brief Start the batch processing
1163 /// This function starts the batch processing
1165 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1167 bool nodes_done = _skip_nodes;
1168 bool arcs_done = _skip_arcs;
1169 bool attributes_done = false;
1175 while (readSuccess()) {
1178 std::string section, caption;
1180 _reader_bits::readToken(line, section);
1181 _reader_bits::readToken(line, caption);
1184 throw FormatError("Extra character at the end of line");
1186 if (section == "nodes" && !nodes_done) {
1187 if (_nodes_caption.empty() || _nodes_caption == caption) {
1191 } else if ((section == "arcs" || section == "edges") &&
1193 if (_arcs_caption.empty() || _arcs_caption == caption) {
1197 } else if (section == "attributes" && !attributes_done) {
1198 if (_attributes_caption.empty() || _attributes_caption == caption) {
1200 attributes_done = true;
1206 } catch (FormatError& error) {
1207 error.line(line_num);
1208 error.file(_filename);
1214 throw FormatError("Section @nodes not found");
1218 throw FormatError("Section @arcs not found");
1221 if (!attributes_done && !_attributes.empty()) {
1222 throw FormatError("Section @attributes not found");
1231 /// \ingroup lemon_io
1233 /// \brief Return a \ref lemon::DigraphReader "DigraphReader" class
1235 /// This function just returns a \ref lemon::DigraphReader
1236 /// "DigraphReader" class.
1238 /// With this function a digraph can be read from an
1239 /// \ref lgf-format "LGF" file or input stream with several maps and
1240 /// attributes. For example, there is network flow problem on a
1241 /// digraph, i.e. a digraph with a \e capacity map on the arcs and
1242 /// \e source and \e target nodes. This digraph can be read with the
1246 ///ListDigraph digraph;
1247 ///ListDigraph::ArcMap<int> cm(digraph);
1248 ///ListDigraph::Node src, trg;
1249 ///digraphReader(digraph, std::cin).
1250 /// arcMap("capacity", cap).
1251 /// node("source", src).
1252 /// node("target", trg).
1256 /// For a complete documentation, please see the
1257 /// \ref lemon::DigraphReader "DigraphReader"
1258 /// class documentation.
1259 /// \warning Don't forget to put the \ref lemon::DigraphReader::run() "run()"
1260 /// to the end of the parameter list.
1261 /// \relates DigraphReader
1262 /// \sa digraphReader(TDGR& digraph, const std::string& fn)
1263 /// \sa digraphReader(TDGR& digraph, const char* fn)
1264 template <typename TDGR>
1265 DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is) {
1266 DigraphReader<TDGR> tmp(digraph, is);
1270 /// \brief Return a \ref DigraphReader class
1272 /// This function just returns a \ref DigraphReader class.
1273 /// \relates DigraphReader
1274 /// \sa digraphReader(TDGR& digraph, std::istream& is)
1275 template <typename TDGR>
1276 DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn) {
1277 DigraphReader<TDGR> tmp(digraph, fn);
1281 /// \brief Return a \ref DigraphReader class
1283 /// This function just returns a \ref DigraphReader class.
1284 /// \relates DigraphReader
1285 /// \sa digraphReader(TDGR& digraph, std::istream& is)
1286 template <typename TDGR>
1287 DigraphReader<TDGR> digraphReader(TDGR& digraph, const char* fn) {
1288 DigraphReader<TDGR> tmp(digraph, fn);
1292 template <typename GR>
1295 template <typename TGR>
1296 GraphReader<TGR> graphReader(TGR& graph, std::istream& is = std::cin);
1297 template <typename TGR>
1298 GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
1299 template <typename TGR>
1300 GraphReader<TGR> graphReader(TGR& graph, const char *fn);
1302 /// \ingroup lemon_io
1304 /// \brief \ref lgf-format "LGF" reader for undirected graphs
1306 /// This utility reads an \ref lgf-format "LGF" file.
1308 /// It can be used almost the same way as \c DigraphReader.
1309 /// The only difference is that this class can handle edges and
1310 /// edge maps as well as arcs and arc maps.
1312 /// The columns in the \c \@edges (or \c \@arcs) section are the
1313 /// edge maps. However, if there are two maps with the same name
1314 /// prefixed with \c '+' and \c '-', then these can be read into an
1315 /// arc map. Similarly, an attribute can be read into an arc, if
1316 /// it's value is an edge label prefixed with \c '+' or \c '-'.
1317 template <typename GR>
1325 TEMPLATE_GRAPH_TYPEDEFS(GR);
1329 std::string _filename;
1333 std::string _nodes_caption;
1334 std::string _edges_caption;
1335 std::string _attributes_caption;
1337 typedef std::map<std::string, Node> NodeIndex;
1338 NodeIndex _node_index;
1339 typedef std::map<std::string, Edge> EdgeIndex;
1340 EdgeIndex _edge_index;
1342 typedef std::vector<std::pair<std::string,
1343 _reader_bits::MapStorageBase<Node>*> > NodeMaps;
1344 NodeMaps _node_maps;
1346 typedef std::vector<std::pair<std::string,
1347 _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1348 EdgeMaps _edge_maps;
1350 typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1352 Attributes _attributes;
1361 std::istringstream line;
1365 /// \brief Constructor
1367 /// Construct an undirected graph reader, which reads from the given
1369 GraphReader(GR& graph, std::istream& is = std::cin)
1370 : _is(&is), local_is(false), _graph(graph),
1371 _use_nodes(false), _use_edges(false),
1372 _skip_nodes(false), _skip_edges(false) {}
1374 /// \brief Constructor
1376 /// Construct an undirected graph reader, which reads from the given
1378 GraphReader(GR& graph, const std::string& fn)
1379 : _is(new std::ifstream(fn.c_str())), local_is(true),
1380 _filename(fn), _graph(graph),
1381 _use_nodes(false), _use_edges(false),
1382 _skip_nodes(false), _skip_edges(false) {
1385 throw IoError("Cannot open file", fn);
1389 /// \brief Constructor
1391 /// Construct an undirected graph reader, which reads from the given
1393 GraphReader(GR& graph, const char* fn)
1394 : _is(new std::ifstream(fn)), local_is(true),
1395 _filename(fn), _graph(graph),
1396 _use_nodes(false), _use_edges(false),
1397 _skip_nodes(false), _skip_edges(false) {
1400 throw IoError("Cannot open file", fn);
1404 /// \brief Destructor
1406 for (typename NodeMaps::iterator it = _node_maps.begin();
1407 it != _node_maps.end(); ++it) {
1411 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1412 it != _edge_maps.end(); ++it) {
1416 for (typename Attributes::iterator it = _attributes.begin();
1417 it != _attributes.end(); ++it) {
1428 template <typename TGR>
1429 friend GraphReader<TGR> graphReader(TGR& graph, std::istream& is);
1430 template <typename TGR>
1431 friend GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
1432 template <typename TGR>
1433 friend GraphReader<TGR> graphReader(TGR& graph, const char *fn);
1435 GraphReader(GraphReader& other)
1436 : _is(other._is), local_is(other.local_is), _graph(other._graph),
1437 _use_nodes(other._use_nodes), _use_edges(other._use_edges),
1438 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1441 other.local_is = false;
1443 _node_index.swap(other._node_index);
1444 _edge_index.swap(other._edge_index);
1446 _node_maps.swap(other._node_maps);
1447 _edge_maps.swap(other._edge_maps);
1448 _attributes.swap(other._attributes);
1450 _nodes_caption = other._nodes_caption;
1451 _edges_caption = other._edges_caption;
1452 _attributes_caption = other._attributes_caption;
1456 GraphReader& operator=(const GraphReader&);
1460 /// \name Reading Rules
1463 /// \brief Node map reading rule
1465 /// Add a node map reading rule to the reader.
1466 template <typename Map>
1467 GraphReader& nodeMap(const std::string& caption, Map& map) {
1468 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1469 _reader_bits::MapStorageBase<Node>* storage =
1470 new _reader_bits::MapStorage<Node, Map>(map);
1471 _node_maps.push_back(std::make_pair(caption, storage));
1475 /// \brief Node map reading rule
1477 /// Add a node map reading rule with specialized converter to the
1479 template <typename Map, typename Converter>
1480 GraphReader& nodeMap(const std::string& caption, Map& map,
1481 const Converter& converter = Converter()) {
1482 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1483 _reader_bits::MapStorageBase<Node>* storage =
1484 new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1485 _node_maps.push_back(std::make_pair(caption, storage));
1489 /// \brief Edge map reading rule
1491 /// Add an edge map reading rule to the reader.
1492 template <typename Map>
1493 GraphReader& edgeMap(const std::string& caption, Map& map) {
1494 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1495 _reader_bits::MapStorageBase<Edge>* storage =
1496 new _reader_bits::MapStorage<Edge, Map>(map);
1497 _edge_maps.push_back(std::make_pair(caption, storage));
1501 /// \brief Edge map reading rule
1503 /// Add an edge map reading rule with specialized converter to the
1505 template <typename Map, typename Converter>
1506 GraphReader& edgeMap(const std::string& caption, Map& map,
1507 const Converter& converter = Converter()) {
1508 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1509 _reader_bits::MapStorageBase<Edge>* storage =
1510 new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1511 _edge_maps.push_back(std::make_pair(caption, storage));
1515 /// \brief Arc map reading rule
1517 /// Add an arc map reading rule to the reader.
1518 template <typename Map>
1519 GraphReader& arcMap(const std::string& caption, Map& map) {
1520 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1521 _reader_bits::MapStorageBase<Edge>* forward_storage =
1522 new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1523 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1524 _reader_bits::MapStorageBase<Edge>* backward_storage =
1525 new _reader_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
1526 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1530 /// \brief Arc map reading rule
1532 /// Add an arc map reading rule with specialized converter to the
1534 template <typename Map, typename Converter>
1535 GraphReader& arcMap(const std::string& caption, Map& map,
1536 const Converter& converter = Converter()) {
1537 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1538 _reader_bits::MapStorageBase<Edge>* forward_storage =
1539 new _reader_bits::GraphArcMapStorage<GR, true, Map, Converter>
1540 (_graph, map, converter);
1541 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1542 _reader_bits::MapStorageBase<Edge>* backward_storage =
1543 new _reader_bits::GraphArcMapStorage<GR, false, Map, Converter>
1544 (_graph, map, converter);
1545 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1549 /// \brief Attribute reading rule
1551 /// Add an attribute reading rule to the reader.
1552 template <typename Value>
1553 GraphReader& attribute(const std::string& caption, Value& value) {
1554 _reader_bits::ValueStorageBase* storage =
1555 new _reader_bits::ValueStorage<Value>(value);
1556 _attributes.insert(std::make_pair(caption, storage));
1560 /// \brief Attribute reading rule
1562 /// Add an attribute reading rule with specialized converter to the
1564 template <typename Value, typename Converter>
1565 GraphReader& attribute(const std::string& caption, Value& value,
1566 const Converter& converter = Converter()) {
1567 _reader_bits::ValueStorageBase* storage =
1568 new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1569 _attributes.insert(std::make_pair(caption, storage));
1573 /// \brief Node reading rule
1575 /// Add a node reading rule to reader.
1576 GraphReader& node(const std::string& caption, Node& node) {
1577 typedef _reader_bits::MapLookUpConverter<Node> Converter;
1578 Converter converter(_node_index);
1579 _reader_bits::ValueStorageBase* storage =
1580 new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1581 _attributes.insert(std::make_pair(caption, storage));
1585 /// \brief Edge reading rule
1587 /// Add an edge reading rule to reader.
1588 GraphReader& edge(const std::string& caption, Edge& edge) {
1589 typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1590 Converter converter(_edge_index);
1591 _reader_bits::ValueStorageBase* storage =
1592 new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1593 _attributes.insert(std::make_pair(caption, storage));
1597 /// \brief Arc reading rule
1599 /// Add an arc reading rule to reader.
1600 GraphReader& arc(const std::string& caption, Arc& arc) {
1601 typedef _reader_bits::GraphArcLookUpConverter<GR> Converter;
1602 Converter converter(_graph, _edge_index);
1603 _reader_bits::ValueStorageBase* storage =
1604 new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1605 _attributes.insert(std::make_pair(caption, storage));
1611 /// \name Select Section by Name
1614 /// \brief Set \c \@nodes section to be read
1616 /// Set \c \@nodes section to be read.
1617 GraphReader& nodes(const std::string& caption) {
1618 _nodes_caption = caption;
1622 /// \brief Set \c \@edges section to be read
1624 /// Set \c \@edges section to be read.
1625 GraphReader& edges(const std::string& caption) {
1626 _edges_caption = caption;
1630 /// \brief Set \c \@attributes section to be read
1632 /// Set \c \@attributes section to be read.
1633 GraphReader& attributes(const std::string& caption) {
1634 _attributes_caption = caption;
1640 /// \name Using Previously Constructed Node or Edge Set
1643 /// \brief Use previously constructed node set
1645 /// Use previously constructed node set, and specify the node
1647 template <typename Map>
1648 GraphReader& useNodes(const Map& map) {
1649 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1650 LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1652 _writer_bits::DefaultConverter<typename Map::Value> converter;
1653 for (NodeIt n(_graph); n != INVALID; ++n) {
1654 _node_index.insert(std::make_pair(converter(map[n]), n));
1659 /// \brief Use previously constructed node set
1661 /// Use previously constructed node set, and specify the node
1662 /// label map and a functor which converts the label map values to
1664 template <typename Map, typename Converter>
1665 GraphReader& useNodes(const Map& map,
1666 const Converter& converter = Converter()) {
1667 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1668 LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1670 for (NodeIt n(_graph); n != INVALID; ++n) {
1671 _node_index.insert(std::make_pair(converter(map[n]), n));
1676 /// \brief Use previously constructed edge set
1678 /// Use previously constructed edge set, and specify the edge
1680 template <typename Map>
1681 GraphReader& useEdges(const Map& map) {
1682 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1683 LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1685 _writer_bits::DefaultConverter<typename Map::Value> converter;
1686 for (EdgeIt a(_graph); a != INVALID; ++a) {
1687 _edge_index.insert(std::make_pair(converter(map[a]), a));
1692 /// \brief Use previously constructed edge set
1694 /// Use previously constructed edge set, and specify the edge
1695 /// label map and a functor which converts the label map values to
1697 template <typename Map, typename Converter>
1698 GraphReader& useEdges(const Map& map,
1699 const Converter& converter = Converter()) {
1700 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1701 LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1703 for (EdgeIt a(_graph); a != INVALID; ++a) {
1704 _edge_index.insert(std::make_pair(converter(map[a]), a));
1709 /// \brief Skip the reading of node section
1711 /// Omit the reading of the node section. This implies that each node
1712 /// map reading rule will be abandoned, and the nodes of the graph
1713 /// will not be constructed, which usually cause that the edge set
1714 /// could not be read due to lack of node name
1715 /// could not be read due to lack of node name resolving.
1716 /// Therefore \c skipEdges() function should also be used, or
1717 /// \c useNodes() should be used to specify the label of the nodes.
1718 GraphReader& skipNodes() {
1719 LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
1724 /// \brief Skip the reading of edge section
1726 /// Omit the reading of the edge section. This implies that each edge
1727 /// map reading rule will be abandoned, and the edges of the graph
1728 /// will not be constructed.
1729 GraphReader& skipEdges() {
1730 LEMON_ASSERT(!_skip_edges, "Skip edges already set");
1741 while(++line_num, std::getline(*_is, str)) {
1742 line.clear(); line.str(str);
1744 if (line >> std::ws >> c && c != '#') {
1752 bool readSuccess() {
1753 return static_cast<bool>(*_is);
1756 void skipSection() {
1758 while (readSuccess() && line >> c && c != '@') {
1761 if (readSuccess()) {
1768 std::vector<int> map_index(_node_maps.size());
1769 int map_num, label_index;
1772 if (!readLine() || !(line >> c) || c == '@') {
1773 if (readSuccess() && line) line.putback(c);
1774 if (!_node_maps.empty())
1775 throw FormatError("Cannot find map names");
1781 std::map<std::string, int> maps;
1785 while (_reader_bits::readToken(line, map)) {
1786 if (maps.find(map) != maps.end()) {
1787 std::ostringstream msg;
1788 msg << "Multiple occurence of node map: " << map;
1789 throw FormatError(msg.str());
1791 maps.insert(std::make_pair(map, index));
1795 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1796 std::map<std::string, int>::iterator jt =
1797 maps.find(_node_maps[i].first);
1798 if (jt == maps.end()) {
1799 std::ostringstream msg;
1800 msg << "Map not found: " << _node_maps[i].first;
1801 throw FormatError(msg.str());
1803 map_index[i] = jt->second;
1807 std::map<std::string, int>::iterator jt = maps.find("label");
1808 if (jt != maps.end()) {
1809 label_index = jt->second;
1814 map_num = maps.size();
1817 while (readLine() && line >> c && c != '@') {
1820 std::vector<std::string> tokens(map_num);
1821 for (int i = 0; i < map_num; ++i) {
1822 if (!_reader_bits::readToken(line, tokens[i])) {
1823 std::ostringstream msg;
1824 msg << "Column not found (" << i + 1 << ")";
1825 throw FormatError(msg.str());
1828 if (line >> std::ws >> c)
1829 throw FormatError("Extra character at the end of line");
1833 n = _graph.addNode();
1834 if (label_index != -1)
1835 _node_index.insert(std::make_pair(tokens[label_index], n));
1837 if (label_index == -1)
1838 throw FormatError("Label map not found");
1839 typename std::map<std::string, Node>::iterator it =
1840 _node_index.find(tokens[label_index]);
1841 if (it == _node_index.end()) {
1842 std::ostringstream msg;
1843 msg << "Node with label not found: " << tokens[label_index];
1844 throw FormatError(msg.str());
1849 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1850 _node_maps[i].second->set(n, tokens[map_index[i]]);
1854 if (readSuccess()) {
1861 std::vector<int> map_index(_edge_maps.size());
1862 int map_num, label_index;
1865 if (!readLine() || !(line >> c) || c == '@') {
1866 if (readSuccess() && line) line.putback(c);
1867 if (!_edge_maps.empty())
1868 throw FormatError("Cannot find map names");
1874 std::map<std::string, int> maps;
1878 while (_reader_bits::readToken(line, map)) {
1881 throw FormatError("'-' is not allowed as a map name");
1882 else if (line >> std::ws >> c)
1883 throw FormatError("Extra character at the end of line");
1886 if (maps.find(map) != maps.end()) {
1887 std::ostringstream msg;
1888 msg << "Multiple occurence of edge map: " << map;
1889 throw FormatError(msg.str());
1891 maps.insert(std::make_pair(map, index));
1895 for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1896 std::map<std::string, int>::iterator jt =
1897 maps.find(_edge_maps[i].first);
1898 if (jt == maps.end()) {
1899 std::ostringstream msg;
1900 msg << "Map not found: " << _edge_maps[i].first;
1901 throw FormatError(msg.str());
1903 map_index[i] = jt->second;
1907 std::map<std::string, int>::iterator jt = maps.find("label");
1908 if (jt != maps.end()) {
1909 label_index = jt->second;
1914 map_num = maps.size();
1917 while (readLine() && line >> c && c != '@') {
1920 std::string source_token;
1921 std::string target_token;
1923 if (!_reader_bits::readToken(line, source_token))
1924 throw FormatError("Node u not found");
1926 if (!_reader_bits::readToken(line, target_token))
1927 throw FormatError("Node v not found");
1929 std::vector<std::string> tokens(map_num);
1930 for (int i = 0; i < map_num; ++i) {
1931 if (!_reader_bits::readToken(line, tokens[i])) {
1932 std::ostringstream msg;
1933 msg << "Column not found (" << i + 1 << ")";
1934 throw FormatError(msg.str());
1937 if (line >> std::ws >> c)
1938 throw FormatError("Extra character at the end of line");
1943 typename NodeIndex::iterator it;
1945 it = _node_index.find(source_token);
1946 if (it == _node_index.end()) {
1947 std::ostringstream msg;
1948 msg << "Item not found: " << source_token;
1949 throw FormatError(msg.str());
1951 Node source = it->second;
1953 it = _node_index.find(target_token);
1954 if (it == _node_index.end()) {
1955 std::ostringstream msg;
1956 msg << "Item not found: " << target_token;
1957 throw FormatError(msg.str());
1959 Node target = it->second;
1961 e = _graph.addEdge(source, target);
1962 if (label_index != -1)
1963 _edge_index.insert(std::make_pair(tokens[label_index], e));
1965 if (label_index == -1)
1966 throw FormatError("Label map not found");
1967 typename std::map<std::string, Edge>::iterator it =
1968 _edge_index.find(tokens[label_index]);
1969 if (it == _edge_index.end()) {
1970 std::ostringstream msg;
1971 msg << "Edge with label not found: " << tokens[label_index];
1972 throw FormatError(msg.str());
1977 for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1978 _edge_maps[i].second->set(e, tokens[map_index[i]]);
1982 if (readSuccess()) {
1987 void readAttributes() {
1989 std::set<std::string> read_attr;
1992 while (readLine() && line >> c && c != '@') {
1995 std::string attr, token;
1996 if (!_reader_bits::readToken(line, attr))
1997 throw FormatError("Attribute name not found");
1998 if (!_reader_bits::readToken(line, token))
1999 throw FormatError("Attribute value not found");
2001 throw FormatError("Extra character at the end of line");
2004 std::set<std::string>::iterator it = read_attr.find(attr);
2005 if (it != read_attr.end()) {
2006 std::ostringstream msg;
2007 msg << "Multiple occurence of attribute: " << attr;
2008 throw FormatError(msg.str());
2010 read_attr.insert(attr);
2014 typename Attributes::iterator it = _attributes.lower_bound(attr);
2015 while (it != _attributes.end() && it->first == attr) {
2016 it->second->set(token);
2022 if (readSuccess()) {
2025 for (typename Attributes::iterator it = _attributes.begin();
2026 it != _attributes.end(); ++it) {
2027 if (read_attr.find(it->first) == read_attr.end()) {
2028 std::ostringstream msg;
2029 msg << "Attribute not found: " << it->first;
2030 throw FormatError(msg.str());
2037 /// \name Execution of the Reader
2040 /// \brief Start the batch processing
2042 /// This function starts the batch processing
2045 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2047 bool nodes_done = _skip_nodes;
2048 bool edges_done = _skip_edges;
2049 bool attributes_done = false;
2055 while (readSuccess()) {
2058 std::string section, caption;
2060 _reader_bits::readToken(line, section);
2061 _reader_bits::readToken(line, caption);
2064 throw FormatError("Extra character at the end of line");
2066 if (section == "nodes" && !nodes_done) {
2067 if (_nodes_caption.empty() || _nodes_caption == caption) {
2071 } else if ((section == "edges" || section == "arcs") &&
2073 if (_edges_caption.empty() || _edges_caption == caption) {
2077 } else if (section == "attributes" && !attributes_done) {
2078 if (_attributes_caption.empty() || _attributes_caption == caption) {
2080 attributes_done = true;
2086 } catch (FormatError& error) {
2087 error.line(line_num);
2088 error.file(_filename);
2094 throw FormatError("Section @nodes not found");
2098 throw FormatError("Section @edges not found");
2101 if (!attributes_done && !_attributes.empty()) {
2102 throw FormatError("Section @attributes not found");
2111 /// \ingroup lemon_io
2113 /// \brief Return a \ref lemon::GraphReader "GraphReader" class
2115 /// This function just returns a \ref lemon::GraphReader "GraphReader" class.
2117 /// With this function a graph can be read from an
2118 /// \ref lgf-format "LGF" file or input stream with several maps and
2119 /// attributes. For example, there is weighted matching problem on a
2120 /// graph, i.e. a graph with a \e weight map on the edges. This
2121 /// graph can be read with the following code:
2125 ///ListGraph::EdgeMap<int> weight(graph);
2126 ///graphReader(graph, std::cin).
2127 /// edgeMap("weight", weight).
2131 /// For a complete documentation, please see the
2132 /// \ref lemon::GraphReader "GraphReader"
2133 /// class documentation.
2134 /// \warning Don't forget to put the \ref lemon::GraphReader::run() "run()"
2135 /// to the end of the parameter list.
2136 /// \relates GraphReader
2137 /// \sa graphReader(TGR& graph, const std::string& fn)
2138 /// \sa graphReader(TGR& graph, const char* fn)
2139 template <typename TGR>
2140 GraphReader<TGR> graphReader(TGR& graph, std::istream& is) {
2141 GraphReader<TGR> tmp(graph, is);
2145 /// \brief Return a \ref GraphReader class
2147 /// This function just returns a \ref GraphReader class.
2148 /// \relates GraphReader
2149 /// \sa graphReader(TGR& graph, std::istream& is)
2150 template <typename TGR>
2151 GraphReader<TGR> graphReader(TGR& graph, const std::string& fn) {
2152 GraphReader<TGR> tmp(graph, fn);
2156 /// \brief Return a \ref GraphReader class
2158 /// This function just returns a \ref GraphReader class.
2159 /// \relates GraphReader
2160 /// \sa graphReader(TGR& graph, std::istream& is)
2161 template <typename TGR>
2162 GraphReader<TGR> graphReader(TGR& graph, const char* fn) {
2163 GraphReader<TGR> tmp(graph, fn);
2167 template <typename BGR>
2168 class BpGraphReader;
2170 template <typename TBGR>
2171 BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is = std::cin);
2172 template <typename TBGR>
2173 BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn);
2174 template <typename TBGR>
2175 BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
2177 /// \ingroup lemon_io
2179 /// \brief \ref lgf-format "LGF" reader for bipartite graphs
2181 /// This utility reads an \ref lgf-format "LGF" file.
2183 /// It can be used almost the same way as \c GraphReader, but it
2184 /// reads the red and blue nodes from separate sections, and these
2185 /// sections can contain different set of maps.
2187 /// The red and blue node maps are read from the corresponding
2188 /// sections. If a map is defined with the same name in both of
2189 /// these sections, then it can be read as a node map.
2190 template <typename BGR>
2191 class BpGraphReader {
2198 TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
2202 std::string _filename;
2206 std::string _nodes_caption;
2207 std::string _edges_caption;
2208 std::string _attributes_caption;
2210 typedef std::map<std::string, RedNode> RedNodeIndex;
2211 RedNodeIndex _red_node_index;
2212 typedef std::map<std::string, BlueNode> BlueNodeIndex;
2213 BlueNodeIndex _blue_node_index;
2214 typedef std::map<std::string, Edge> EdgeIndex;
2215 EdgeIndex _edge_index;
2217 typedef std::vector<std::pair<std::string,
2218 _reader_bits::MapStorageBase<RedNode>*> > RedNodeMaps;
2219 RedNodeMaps _red_node_maps;
2220 typedef std::vector<std::pair<std::string,
2221 _reader_bits::MapStorageBase<BlueNode>*> > BlueNodeMaps;
2222 BlueNodeMaps _blue_node_maps;
2224 typedef std::vector<std::pair<std::string,
2225 _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
2226 EdgeMaps _edge_maps;
2228 typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
2230 Attributes _attributes;
2239 std::istringstream line;
2243 /// \brief Constructor
2245 /// Construct an undirected graph reader, which reads from the given
2247 BpGraphReader(BGR& graph, std::istream& is = std::cin)
2248 : _is(&is), local_is(false), _graph(graph),
2249 _use_nodes(false), _use_edges(false),
2250 _skip_nodes(false), _skip_edges(false) {}
2252 /// \brief Constructor
2254 /// Construct an undirected graph reader, which reads from the given
2256 BpGraphReader(BGR& graph, const std::string& fn)
2257 : _is(new std::ifstream(fn.c_str())), local_is(true),
2258 _filename(fn), _graph(graph),
2259 _use_nodes(false), _use_edges(false),
2260 _skip_nodes(false), _skip_edges(false) {
2263 throw IoError("Cannot open file", fn);
2267 /// \brief Constructor
2269 /// Construct an undirected graph reader, which reads from the given
2271 BpGraphReader(BGR& graph, const char* fn)
2272 : _is(new std::ifstream(fn)), local_is(true),
2273 _filename(fn), _graph(graph),
2274 _use_nodes(false), _use_edges(false),
2275 _skip_nodes(false), _skip_edges(false) {
2278 throw IoError("Cannot open file", fn);
2282 /// \brief Destructor
2284 for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
2285 it != _red_node_maps.end(); ++it) {
2289 for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
2290 it != _blue_node_maps.end(); ++it) {
2294 for (typename EdgeMaps::iterator it = _edge_maps.begin();
2295 it != _edge_maps.end(); ++it) {
2299 for (typename Attributes::iterator it = _attributes.begin();
2300 it != _attributes.end(); ++it) {
2311 template <typename TBGR>
2312 friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is);
2313 template <typename TBGR>
2314 friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph,
2315 const std::string& fn);
2316 template <typename TBGR>
2317 friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
2319 BpGraphReader(BpGraphReader& other)
2320 : _is(other._is), local_is(other.local_is), _graph(other._graph),
2321 _use_nodes(other._use_nodes), _use_edges(other._use_edges),
2322 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
2325 other.local_is = false;
2327 _red_node_index.swap(other._red_node_index);
2328 _blue_node_index.swap(other._blue_node_index);
2329 _edge_index.swap(other._edge_index);
2331 _red_node_maps.swap(other._red_node_maps);
2332 _blue_node_maps.swap(other._blue_node_maps);
2333 _edge_maps.swap(other._edge_maps);
2334 _attributes.swap(other._attributes);
2336 _nodes_caption = other._nodes_caption;
2337 _edges_caption = other._edges_caption;
2338 _attributes_caption = other._attributes_caption;
2342 BpGraphReader& operator=(const BpGraphReader&);
2346 /// \name Reading Rules
2349 /// \brief Node map reading rule
2351 /// Add a node map reading rule to the reader.
2352 template <typename Map>
2353 BpGraphReader& nodeMap(const std::string& caption, Map& map) {
2354 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
2355 _reader_bits::MapStorageBase<RedNode>* red_storage =
2356 new _reader_bits::MapStorage<RedNode, Map>(map);
2357 _red_node_maps.push_back(std::make_pair(caption, red_storage));
2358 _reader_bits::MapStorageBase<BlueNode>* blue_storage =
2359 new _reader_bits::MapStorage<BlueNode, Map>(map);
2360 _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
2364 /// \brief Node map reading rule
2366 /// Add a node map reading rule with specialized converter to the
2368 template <typename Map, typename Converter>
2369 BpGraphReader& nodeMap(const std::string& caption, Map& map,
2370 const Converter& converter = Converter()) {
2371 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
2372 _reader_bits::MapStorageBase<RedNode>* red_storage =
2373 new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
2374 _red_node_maps.push_back(std::make_pair(caption, red_storage));
2375 _reader_bits::MapStorageBase<BlueNode>* blue_storage =
2376 new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
2377 _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
2381 /// Add a red node map reading rule to the reader.
2382 template <typename Map>
2383 BpGraphReader& redNodeMap(const std::string& caption, Map& map) {
2384 checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
2385 _reader_bits::MapStorageBase<RedNode>* storage =
2386 new _reader_bits::MapStorage<RedNode, Map>(map);
2387 _red_node_maps.push_back(std::make_pair(caption, storage));
2391 /// \brief Red node map reading rule
2393 /// Add a red node map node reading rule with specialized converter to
2395 template <typename Map, typename Converter>
2396 BpGraphReader& redNodeMap(const std::string& caption, Map& map,
2397 const Converter& converter = Converter()) {
2398 checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
2399 _reader_bits::MapStorageBase<RedNode>* storage =
2400 new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
2401 _red_node_maps.push_back(std::make_pair(caption, storage));
2405 /// Add a blue node map reading rule to the reader.
2406 template <typename Map>
2407 BpGraphReader& blueNodeMap(const std::string& caption, Map& map) {
2408 checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
2409 _reader_bits::MapStorageBase<BlueNode>* storage =
2410 new _reader_bits::MapStorage<BlueNode, Map>(map);
2411 _blue_node_maps.push_back(std::make_pair(caption, storage));
2415 /// \brief Blue node map reading rule
2417 /// Add a blue node map reading rule with specialized converter to
2419 template <typename Map, typename Converter>
2420 BpGraphReader& blueNodeMap(const std::string& caption, Map& map,
2421 const Converter& converter = Converter()) {
2422 checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
2423 _reader_bits::MapStorageBase<BlueNode>* storage =
2424 new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
2425 _blue_node_maps.push_back(std::make_pair(caption, storage));
2429 /// \brief Edge map reading rule
2431 /// Add an edge map reading rule to the reader.
2432 template <typename Map>
2433 BpGraphReader& edgeMap(const std::string& caption, Map& map) {
2434 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
2435 _reader_bits::MapStorageBase<Edge>* storage =
2436 new _reader_bits::MapStorage<Edge, Map>(map);
2437 _edge_maps.push_back(std::make_pair(caption, storage));
2441 /// \brief Edge map reading rule
2443 /// Add an edge map reading rule with specialized converter to the
2445 template <typename Map, typename Converter>
2446 BpGraphReader& edgeMap(const std::string& caption, Map& map,
2447 const Converter& converter = Converter()) {
2448 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
2449 _reader_bits::MapStorageBase<Edge>* storage =
2450 new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
2451 _edge_maps.push_back(std::make_pair(caption, storage));
2455 /// \brief Arc map reading rule
2457 /// Add an arc map reading rule to the reader.
2458 template <typename Map>
2459 BpGraphReader& arcMap(const std::string& caption, Map& map) {
2460 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
2461 _reader_bits::MapStorageBase<Edge>* forward_storage =
2462 new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
2463 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
2464 _reader_bits::MapStorageBase<Edge>* backward_storage =
2465 new _reader_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
2466 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
2470 /// \brief Arc map reading rule
2472 /// Add an arc map reading rule with specialized converter to the
2474 template <typename Map, typename Converter>
2475 BpGraphReader& arcMap(const std::string& caption, Map& map,
2476 const Converter& converter = Converter()) {
2477 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
2478 _reader_bits::MapStorageBase<Edge>* forward_storage =
2479 new _reader_bits::GraphArcMapStorage<BGR, true, Map, Converter>
2480 (_graph, map, converter);
2481 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
2482 _reader_bits::MapStorageBase<Edge>* backward_storage =
2483 new _reader_bits::GraphArcMapStorage<BGR, false, Map, Converter>
2484 (_graph, map, converter);
2485 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
2489 /// \brief Attribute reading rule
2491 /// Add an attribute reading rule to the reader.
2492 template <typename Value>
2493 BpGraphReader& attribute(const std::string& caption, Value& value) {
2494 _reader_bits::ValueStorageBase* storage =
2495 new _reader_bits::ValueStorage<Value>(value);
2496 _attributes.insert(std::make_pair(caption, storage));
2500 /// \brief Attribute reading rule
2502 /// Add an attribute reading rule with specialized converter to the
2504 template <typename Value, typename Converter>
2505 BpGraphReader& attribute(const std::string& caption, Value& value,
2506 const Converter& converter = Converter()) {
2507 _reader_bits::ValueStorageBase* storage =
2508 new _reader_bits::ValueStorage<Value, Converter>(value, converter);
2509 _attributes.insert(std::make_pair(caption, storage));
2513 /// \brief Node reading rule
2515 /// Add a node reading rule to reader.
2516 BpGraphReader& node(const std::string& caption, Node& node) {
2517 typedef _reader_bits::DoubleMapLookUpConverter<
2518 Node, RedNodeIndex, BlueNodeIndex> Converter;
2519 Converter converter(_red_node_index, _blue_node_index);
2520 _reader_bits::ValueStorageBase* storage =
2521 new _reader_bits::ValueStorage<Node, Converter>(node, converter);
2522 _attributes.insert(std::make_pair(caption, storage));
2526 /// \brief Red node reading rule
2528 /// Add a red node reading rule to reader.
2529 BpGraphReader& redNode(const std::string& caption, RedNode& node) {
2530 typedef _reader_bits::MapLookUpConverter<RedNode> Converter;
2531 Converter converter(_red_node_index);
2532 _reader_bits::ValueStorageBase* storage =
2533 new _reader_bits::ValueStorage<RedNode, Converter>(node, converter);
2534 _attributes.insert(std::make_pair(caption, storage));
2538 /// \brief Blue node reading rule
2540 /// Add a blue node reading rule to reader.
2541 BpGraphReader& blueNode(const std::string& caption, BlueNode& node) {
2542 typedef _reader_bits::MapLookUpConverter<BlueNode> Converter;
2543 Converter converter(_blue_node_index);
2544 _reader_bits::ValueStorageBase* storage =
2545 new _reader_bits::ValueStorage<BlueNode, Converter>(node, converter);
2546 _attributes.insert(std::make_pair(caption, storage));
2550 /// \brief Edge reading rule
2552 /// Add an edge reading rule to reader.
2553 BpGraphReader& edge(const std::string& caption, Edge& edge) {
2554 typedef _reader_bits::MapLookUpConverter<Edge> Converter;
2555 Converter converter(_edge_index);
2556 _reader_bits::ValueStorageBase* storage =
2557 new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
2558 _attributes.insert(std::make_pair(caption, storage));
2562 /// \brief Arc reading rule
2564 /// Add an arc reading rule to reader.
2565 BpGraphReader& arc(const std::string& caption, Arc& arc) {
2566 typedef _reader_bits::GraphArcLookUpConverter<BGR> Converter;
2567 Converter converter(_graph, _edge_index);
2568 _reader_bits::ValueStorageBase* storage =
2569 new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
2570 _attributes.insert(std::make_pair(caption, storage));
2576 /// \name Select Section by Name
2579 /// \brief Set \c \@nodes section to be read
2581 /// Set \c \@nodes section to be read.
2582 BpGraphReader& nodes(const std::string& caption) {
2583 _nodes_caption = caption;
2587 /// \brief Set \c \@edges section to be read
2589 /// Set \c \@edges section to be read.
2590 BpGraphReader& edges(const std::string& caption) {
2591 _edges_caption = caption;
2595 /// \brief Set \c \@attributes section to be read
2597 /// Set \c \@attributes section to be read.
2598 BpGraphReader& attributes(const std::string& caption) {
2599 _attributes_caption = caption;
2605 /// \name Using Previously Constructed Node or Edge Set
2608 /// \brief Use previously constructed node set
2610 /// Use previously constructed node set, and specify the node
2612 template <typename Map>
2613 BpGraphReader& useNodes(const Map& map) {
2614 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
2615 LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
2617 _writer_bits::DefaultConverter<typename Map::Value> converter;
2618 for (RedNodeIt n(_graph); n != INVALID; ++n) {
2619 _red_node_index.insert(std::make_pair(converter(map[n]), n));
2621 for (BlueNodeIt n(_graph); n != INVALID; ++n) {
2622 _blue_node_index.insert(std::make_pair(converter(map[n]), n));
2627 /// \brief Use previously constructed node set
2629 /// Use previously constructed node set, and specify the node
2630 /// label map and a functor which converts the label map values to
2632 template <typename Map, typename Converter>
2633 BpGraphReader& useNodes(const Map& map,
2634 const Converter& converter = Converter()) {
2635 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
2636 LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
2638 for (RedNodeIt n(_graph); n != INVALID; ++n) {
2639 _red_node_index.insert(std::make_pair(converter(map[n]), n));
2641 for (BlueNodeIt n(_graph); n != INVALID; ++n) {
2642 _blue_node_index.insert(std::make_pair(converter(map[n]), n));
2647 /// \brief Use previously constructed edge set
2649 /// Use previously constructed edge set, and specify the edge
2651 template <typename Map>
2652 BpGraphReader& useEdges(const Map& map) {
2653 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
2654 LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
2656 _writer_bits::DefaultConverter<typename Map::Value> converter;
2657 for (EdgeIt a(_graph); a != INVALID; ++a) {
2658 _edge_index.insert(std::make_pair(converter(map[a]), a));
2663 /// \brief Use previously constructed edge set
2665 /// Use previously constructed edge set, and specify the edge
2666 /// label map and a functor which converts the label map values to
2668 template <typename Map, typename Converter>
2669 BpGraphReader& useEdges(const Map& map,
2670 const Converter& converter = Converter()) {
2671 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
2672 LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
2674 for (EdgeIt a(_graph); a != INVALID; ++a) {
2675 _edge_index.insert(std::make_pair(converter(map[a]), a));
2680 /// \brief Skip the reading of node section
2682 /// Omit the reading of the node section. This implies that each node
2683 /// map reading rule will be abandoned, and the nodes of the graph
2684 /// will not be constructed, which usually cause that the edge set
2685 /// could not be read due to lack of node name
2686 /// could not be read due to lack of node name resolving.
2687 /// Therefore \c skipEdges() function should also be used, or
2688 /// \c useNodes() should be used to specify the label of the nodes.
2689 BpGraphReader& skipNodes() {
2690 LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
2695 /// \brief Skip the reading of edge section
2697 /// Omit the reading of the edge section. This implies that each edge
2698 /// map reading rule will be abandoned, and the edges of the graph
2699 /// will not be constructed.
2700 BpGraphReader& skipEdges() {
2701 LEMON_ASSERT(!_skip_edges, "Skip edges already set");
2712 while(++line_num, std::getline(*_is, str)) {
2713 line.clear(); line.str(str);
2715 if (line >> std::ws >> c && c != '#') {
2723 bool readSuccess() {
2724 return static_cast<bool>(*_is);
2727 void skipSection() {
2729 while (readSuccess() && line >> c && c != '@') {
2732 if (readSuccess()) {
2737 void readRedNodes() {
2739 std::vector<int> map_index(_red_node_maps.size());
2740 int map_num, label_index;
2743 if (!readLine() || !(line >> c) || c == '@') {
2744 if (readSuccess() && line) line.putback(c);
2745 if (!_red_node_maps.empty())
2746 throw FormatError("Cannot find map names");
2752 std::map<std::string, int> maps;
2756 while (_reader_bits::readToken(line, map)) {
2757 if (maps.find(map) != maps.end()) {
2758 std::ostringstream msg;
2759 msg << "Multiple occurence of red node map: " << map;
2760 throw FormatError(msg.str());
2762 maps.insert(std::make_pair(map, index));
2766 for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
2767 std::map<std::string, int>::iterator jt =
2768 maps.find(_red_node_maps[i].first);
2769 if (jt == maps.end()) {
2770 std::ostringstream msg;
2771 msg << "Map not found: " << _red_node_maps[i].first;
2772 throw FormatError(msg.str());
2774 map_index[i] = jt->second;
2778 std::map<std::string, int>::iterator jt = maps.find("label");
2779 if (jt != maps.end()) {
2780 label_index = jt->second;
2785 map_num = maps.size();
2788 while (readLine() && line >> c && c != '@') {
2791 std::vector<std::string> tokens(map_num);
2792 for (int i = 0; i < map_num; ++i) {
2793 if (!_reader_bits::readToken(line, tokens[i])) {
2794 std::ostringstream msg;
2795 msg << "Column not found (" << i + 1 << ")";
2796 throw FormatError(msg.str());
2799 if (line >> std::ws >> c)
2800 throw FormatError("Extra character at the end of line");
2804 n = _graph.addRedNode();
2805 if (label_index != -1)
2806 _red_node_index.insert(std::make_pair(tokens[label_index], n));
2808 if (label_index == -1)
2809 throw FormatError("Label map not found");
2810 typename std::map<std::string, RedNode>::iterator it =
2811 _red_node_index.find(tokens[label_index]);
2812 if (it == _red_node_index.end()) {
2813 std::ostringstream msg;
2814 msg << "Node with label not found: " << tokens[label_index];
2815 throw FormatError(msg.str());
2820 for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
2821 _red_node_maps[i].second->set(n, tokens[map_index[i]]);
2825 if (readSuccess()) {
2830 void readBlueNodes() {
2832 std::vector<int> map_index(_blue_node_maps.size());
2833 int map_num, label_index;
2836 if (!readLine() || !(line >> c) || c == '@') {
2837 if (readSuccess() && line) line.putback(c);
2838 if (!_blue_node_maps.empty())
2839 throw FormatError("Cannot find map names");
2845 std::map<std::string, int> maps;
2849 while (_reader_bits::readToken(line, map)) {
2850 if (maps.find(map) != maps.end()) {
2851 std::ostringstream msg;
2852 msg << "Multiple occurence of blue node map: " << map;
2853 throw FormatError(msg.str());
2855 maps.insert(std::make_pair(map, index));
2859 for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
2860 std::map<std::string, int>::iterator jt =
2861 maps.find(_blue_node_maps[i].first);
2862 if (jt == maps.end()) {
2863 std::ostringstream msg;
2864 msg << "Map not found: " << _blue_node_maps[i].first;
2865 throw FormatError(msg.str());
2867 map_index[i] = jt->second;
2871 std::map<std::string, int>::iterator jt = maps.find("label");
2872 if (jt != maps.end()) {
2873 label_index = jt->second;
2878 map_num = maps.size();
2881 while (readLine() && line >> c && c != '@') {
2884 std::vector<std::string> tokens(map_num);
2885 for (int i = 0; i < map_num; ++i) {
2886 if (!_reader_bits::readToken(line, tokens[i])) {
2887 std::ostringstream msg;
2888 msg << "Column not found (" << i + 1 << ")";
2889 throw FormatError(msg.str());
2892 if (line >> std::ws >> c)
2893 throw FormatError("Extra character at the end of line");
2897 n = _graph.addBlueNode();
2898 if (label_index != -1)
2899 _blue_node_index.insert(std::make_pair(tokens[label_index], n));
2901 if (label_index == -1)
2902 throw FormatError("Label map not found");
2903 typename std::map<std::string, BlueNode>::iterator it =
2904 _blue_node_index.find(tokens[label_index]);
2905 if (it == _blue_node_index.end()) {
2906 std::ostringstream msg;
2907 msg << "Node with label not found: " << tokens[label_index];
2908 throw FormatError(msg.str());
2913 for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
2914 _blue_node_maps[i].second->set(n, tokens[map_index[i]]);
2918 if (readSuccess()) {
2925 std::vector<int> map_index(_edge_maps.size());
2926 int map_num, label_index;
2929 if (!readLine() || !(line >> c) || c == '@') {
2930 if (readSuccess() && line) line.putback(c);
2931 if (!_edge_maps.empty())
2932 throw FormatError("Cannot find map names");
2938 std::map<std::string, int> maps;
2942 while (_reader_bits::readToken(line, map)) {
2943 if (maps.find(map) != maps.end()) {
2944 std::ostringstream msg;
2945 msg << "Multiple occurence of edge map: " << map;
2946 throw FormatError(msg.str());
2948 maps.insert(std::make_pair(map, index));
2952 for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
2953 std::map<std::string, int>::iterator jt =
2954 maps.find(_edge_maps[i].first);
2955 if (jt == maps.end()) {
2956 std::ostringstream msg;
2957 msg << "Map not found: " << _edge_maps[i].first;
2958 throw FormatError(msg.str());
2960 map_index[i] = jt->second;
2964 std::map<std::string, int>::iterator jt = maps.find("label");
2965 if (jt != maps.end()) {
2966 label_index = jt->second;
2971 map_num = maps.size();
2974 while (readLine() && line >> c && c != '@') {
2977 std::string source_token;
2978 std::string target_token;
2980 if (!_reader_bits::readToken(line, source_token))
2981 throw FormatError("Red node not found");
2983 if (!_reader_bits::readToken(line, target_token))
2984 throw FormatError("Blue node not found");
2986 std::vector<std::string> tokens(map_num);
2987 for (int i = 0; i < map_num; ++i) {
2988 if (!_reader_bits::readToken(line, tokens[i])) {
2989 std::ostringstream msg;
2990 msg << "Column not found (" << i + 1 << ")";
2991 throw FormatError(msg.str());
2994 if (line >> std::ws >> c)
2995 throw FormatError("Extra character at the end of line");
2999 typename RedNodeIndex::iterator rit =
3000 _red_node_index.find(source_token);
3001 if (rit == _red_node_index.end()) {
3002 std::ostringstream msg;
3003 msg << "Item not found: " << source_token;
3004 throw FormatError(msg.str());
3006 RedNode source = rit->second;
3007 typename BlueNodeIndex::iterator it =
3008 _blue_node_index.find(target_token);
3009 if (it == _blue_node_index.end()) {
3010 std::ostringstream msg;
3011 msg << "Item not found: " << target_token;
3012 throw FormatError(msg.str());
3014 BlueNode target = it->second;
3016 // It is checked that source is red and
3017 // target is blue, so this should be safe:
3018 e = _graph.addEdge(source, target);
3019 if (label_index != -1)
3020 _edge_index.insert(std::make_pair(tokens[label_index], e));
3022 if (label_index == -1)
3023 throw FormatError("Label map not found");
3024 typename std::map<std::string, Edge>::iterator it =
3025 _edge_index.find(tokens[label_index]);
3026 if (it == _edge_index.end()) {
3027 std::ostringstream msg;
3028 msg << "Edge with label not found: " << tokens[label_index];
3029 throw FormatError(msg.str());
3034 for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
3035 _edge_maps[i].second->set(e, tokens[map_index[i]]);
3039 if (readSuccess()) {
3044 void readAttributes() {
3046 std::set<std::string> read_attr;
3049 while (readLine() && line >> c && c != '@') {
3052 std::string attr, token;
3053 if (!_reader_bits::readToken(line, attr))
3054 throw FormatError("Attribute name not found");
3055 if (!_reader_bits::readToken(line, token))
3056 throw FormatError("Attribute value not found");
3058 throw FormatError("Extra character at the end of line");
3061 std::set<std::string>::iterator it = read_attr.find(attr);
3062 if (it != read_attr.end()) {
3063 std::ostringstream msg;
3064 msg << "Multiple occurence of attribute: " << attr;
3065 throw FormatError(msg.str());
3067 read_attr.insert(attr);
3071 typename Attributes::iterator it = _attributes.lower_bound(attr);
3072 while (it != _attributes.end() && it->first == attr) {
3073 it->second->set(token);
3079 if (readSuccess()) {
3082 for (typename Attributes::iterator it = _attributes.begin();
3083 it != _attributes.end(); ++it) {
3084 if (read_attr.find(it->first) == read_attr.end()) {
3085 std::ostringstream msg;
3086 msg << "Attribute not found: " << it->first;
3087 throw FormatError(msg.str());
3094 /// \name Execution of the Reader
3097 /// \brief Start the batch processing
3099 /// This function starts the batch processing
3102 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
3104 bool red_nodes_done = _skip_nodes;
3105 bool blue_nodes_done = _skip_nodes;
3106 bool edges_done = _skip_edges;
3107 bool attributes_done = false;
3113 while (readSuccess()) {
3116 std::string section, caption;
3118 _reader_bits::readToken(line, section);
3119 _reader_bits::readToken(line, caption);
3122 throw FormatError("Extra character at the end of line");
3124 if (section == "red_nodes" && !red_nodes_done) {
3125 if (_nodes_caption.empty() || _nodes_caption == caption) {
3127 red_nodes_done = true;
3129 } else if (section == "blue_nodes" && !blue_nodes_done) {
3130 if (_nodes_caption.empty() || _nodes_caption == caption) {
3132 blue_nodes_done = true;
3134 } else if ((section == "edges" || section == "arcs") &&
3136 if (_edges_caption.empty() || _edges_caption == caption) {
3140 } else if (section == "attributes" && !attributes_done) {
3141 if (_attributes_caption.empty() || _attributes_caption == caption) {
3143 attributes_done = true;
3149 } catch (FormatError& error) {
3150 error.line(line_num);
3151 error.file(_filename);
3156 if (!red_nodes_done) {
3157 throw FormatError("Section @red_nodes not found");
3160 if (!blue_nodes_done) {
3161 throw FormatError("Section @blue_nodes not found");
3165 throw FormatError("Section @edges not found");
3168 if (!attributes_done && !_attributes.empty()) {
3169 throw FormatError("Section @attributes not found");
3178 /// \ingroup lemon_io
3180 /// \brief Return a \ref lemon::BpGraphReader "BpGraphReader" class
3182 /// This function just returns a \ref lemon::BpGraphReader
3183 /// "BpGraphReader" class.
3185 /// With this function a graph can be read from an
3186 /// \ref lgf-format "LGF" file or input stream with several maps and
3187 /// attributes. For example, there is bipartite weighted matching problem
3188 /// on a graph, i.e. a graph with a \e weight map on the edges. This
3189 /// graph can be read with the following code:
3192 ///ListBpGraph graph;
3193 ///ListBpGraph::EdgeMap<int> weight(graph);
3194 ///bpGraphReader(graph, std::cin).
3195 /// edgeMap("weight", weight).
3199 /// For a complete documentation, please see the
3200 /// \ref lemon::BpGraphReader "BpGraphReader"
3201 /// class documentation.
3202 /// \warning Don't forget to put the \ref lemon::BpGraphReader::run() "run()"
3203 /// to the end of the parameter list.
3204 /// \relates BpGraphReader
3205 /// \sa bpGraphReader(TBGR& graph, const std::string& fn)
3206 /// \sa bpGraphReader(TBGR& graph, const char* fn)
3207 template <typename TBGR>
3208 BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is) {
3209 BpGraphReader<TBGR> tmp(graph, is);
3213 /// \brief Return a \ref BpGraphReader class
3215 /// This function just returns a \ref BpGraphReader class.
3216 /// \relates BpGraphReader
3217 /// \sa bpGraphReader(TBGR& graph, std::istream& is)
3218 template <typename TBGR>
3219 BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn) {
3220 BpGraphReader<TBGR> tmp(graph, fn);
3224 /// \brief Return a \ref BpGraphReader class
3226 /// This function just returns a \ref BpGraphReader class.
3227 /// \relates BpGraphReader
3228 /// \sa bpGraphReader(TBGR& graph, std::istream& is)
3229 template <typename TBGR>
3230 BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char* fn) {
3231 BpGraphReader<TBGR> tmp(graph, fn);
3235 class SectionReader;
3237 SectionReader sectionReader(std::istream& is);
3238 SectionReader sectionReader(const std::string& fn);
3239 SectionReader sectionReader(const char* fn);
3241 /// \ingroup lemon_io
3243 /// \brief Section reader class
3245 /// In the \ref lgf-format "LGF" file extra sections can be placed,
3246 /// which contain any data in arbitrary format. Such sections can be
3247 /// read with this class. A reading rule can be added to the class
3248 /// with two different functions. With the \c sectionLines() function a
3249 /// functor can process the section line-by-line, while with the \c
3250 /// sectionStream() member the section can be read from an input
3252 class SectionReader {
3257 std::string _filename;
3259 typedef std::map<std::string, _reader_bits::Section*> Sections;
3263 std::istringstream line;
3267 /// \brief Constructor
3269 /// Construct a section reader, which reads from the given input
3271 SectionReader(std::istream& is)
3272 : _is(&is), local_is(false) {}
3274 /// \brief Constructor
3276 /// Construct a section reader, which reads from the given file.
3277 SectionReader(const std::string& fn)
3278 : _is(new std::ifstream(fn.c_str())), local_is(true),
3282 throw IoError("Cannot open file", fn);
3286 /// \brief Constructor
3288 /// Construct a section reader, which reads from the given file.
3289 SectionReader(const char* fn)
3290 : _is(new std::ifstream(fn)), local_is(true),
3294 throw IoError("Cannot open file", fn);
3298 /// \brief Destructor
3300 for (Sections::iterator it = _sections.begin();
3301 it != _sections.end(); ++it) {
3313 friend SectionReader sectionReader(std::istream& is);
3314 friend SectionReader sectionReader(const std::string& fn);
3315 friend SectionReader sectionReader(const char* fn);
3317 SectionReader(SectionReader& other)
3318 : _is(other._is), local_is(other.local_is) {
3321 other.local_is = false;
3323 _sections.swap(other._sections);
3326 SectionReader& operator=(const SectionReader&);
3330 /// \name Section Readers
3333 /// \brief Add a section processor with line oriented reading
3335 /// The first parameter is the type descriptor of the section, the
3336 /// second is a functor, which takes just one \c std::string
3337 /// parameter. At the reading process, each line of the section
3338 /// will be given to the functor object. However, the empty lines
3339 /// and the comment lines are filtered out, and the leading
3340 /// whitespaces are trimmed from each processed string.
3342 /// For example, let's see a section, which contain several
3343 /// integers, which should be inserted into a vector.
3351 /// The functor is implemented as a struct:
3353 /// struct NumberSection {
3354 /// std::vector<int>& _data;
3355 /// NumberSection(std::vector<int>& data) : _data(data) {}
3356 /// void operator()(const std::string& line) {
3357 /// std::istringstream ls(line);
3359 /// while (ls >> value) _data.push_back(value);
3365 /// reader.sectionLines("numbers", NumberSection(vec));
3367 template <typename Functor>
3368 SectionReader& sectionLines(const std::string& type, Functor functor) {
3369 LEMON_ASSERT(!type.empty(), "Type is empty.");
3370 LEMON_ASSERT(_sections.find(type) == _sections.end(),
3371 "Multiple reading of section.");
3372 _sections.insert(std::make_pair(type,
3373 new _reader_bits::LineSection<Functor>(functor)));
3378 /// \brief Add a section processor with stream oriented reading
3380 /// The first parameter is the type of the section, the second is
3381 /// a functor, which takes an \c std::istream& and an \c int&
3382 /// parameter, the latter regard to the line number of stream. The
3383 /// functor can read the input while the section go on, and the
3384 /// line number should be modified accordingly.
3385 template <typename Functor>
3386 SectionReader& sectionStream(const std::string& type, Functor functor) {
3387 LEMON_ASSERT(!type.empty(), "Type is empty.");
3388 LEMON_ASSERT(_sections.find(type) == _sections.end(),
3389 "Multiple reading of section.");
3390 _sections.insert(std::make_pair(type,
3391 new _reader_bits::StreamSection<Functor>(functor)));
3401 while(++line_num, std::getline(*_is, str)) {
3402 line.clear(); line.str(str);
3404 if (line >> std::ws >> c && c != '#') {
3412 bool readSuccess() {
3413 return static_cast<bool>(*_is);
3416 void skipSection() {
3418 while (readSuccess() && line >> c && c != '@') {
3421 if (readSuccess()) {
3429 /// \name Execution of the Reader
3432 /// \brief Start the batch processing
3434 /// This function starts the batch processing.
3437 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
3439 std::set<std::string> extra_sections;
3445 while (readSuccess()) {
3448 std::string section, caption;
3450 _reader_bits::readToken(line, section);
3451 _reader_bits::readToken(line, caption);
3454 throw FormatError("Extra character at the end of line");
3456 if (extra_sections.find(section) != extra_sections.end()) {
3457 std::ostringstream msg;
3458 msg << "Multiple occurence of section: " << section;
3459 throw FormatError(msg.str());
3461 Sections::iterator it = _sections.find(section);
3462 if (it != _sections.end()) {
3463 extra_sections.insert(section);
3464 it->second->process(*_is, line_num);
3468 } catch (FormatError& error) {
3469 error.line(line_num);
3470 error.file(_filename);
3474 for (Sections::iterator it = _sections.begin();
3475 it != _sections.end(); ++it) {
3476 if (extra_sections.find(it->first) == extra_sections.end()) {
3477 std::ostringstream os;
3478 os << "Cannot find section: " << it->first;
3479 throw FormatError(os.str());
3488 /// \ingroup lemon_io
3490 /// \brief Return a \ref SectionReader class
3492 /// This function just returns a \ref SectionReader class.
3494 /// Please see SectionReader documentation about the custom section
3497 /// \relates SectionReader
3498 /// \sa sectionReader(const std::string& fn)
3499 /// \sa sectionReader(const char *fn)
3500 inline SectionReader sectionReader(std::istream& is) {
3501 SectionReader tmp(is);
3505 /// \brief Return a \ref SectionReader class
3507 /// This function just returns a \ref SectionReader class.
3508 /// \relates SectionReader
3509 /// \sa sectionReader(std::istream& is)
3510 inline SectionReader sectionReader(const std::string& fn) {
3511 SectionReader tmp(fn);
3515 /// \brief Return a \ref SectionReader class
3517 /// This function just returns a \ref SectionReader class.
3518 /// \relates SectionReader
3519 /// \sa sectionReader(std::istream& is)
3520 inline SectionReader sectionReader(const char* fn) {
3521 SectionReader tmp(fn);
3525 /// \ingroup lemon_io
3527 /// \brief Reader for the contents of the \ref lgf-format "LGF" file
3529 /// This class can be used to read the sections, the map names and
3530 /// the attributes from a file. Usually, the LEMON programs know
3531 /// that, which type of graph, which maps and which attributes
3532 /// should be read from a file, but in general tools (like glemon)
3533 /// the contents of an LGF file should be guessed somehow. This class
3534 /// reads the graph and stores the appropriate information for
3535 /// reading the graph.
3538 /// LgfContents contents("graph.lgf");
3541 /// // Does it contain any node section and arc section?
3542 /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
3543 /// std::cerr << "Failure, cannot find graph." << std::endl;
3546 /// std::cout << "The name of the default node section: "
3547 /// << contents.nodeSection(0) << std::endl;
3548 /// std::cout << "The number of the arc maps: "
3549 /// << contents.arcMaps(0).size() << std::endl;
3550 /// std::cout << "The name of second arc map: "
3551 /// << contents.arcMaps(0)[1] << std::endl;
3559 std::vector<std::string> _node_sections;
3560 std::vector<std::string> _edge_sections;
3561 std::vector<std::string> _attribute_sections;
3562 std::vector<std::string> _extra_sections;
3564 std::vector<bool> _arc_sections;
3566 std::vector<std::vector<std::string> > _node_maps;
3567 std::vector<std::vector<std::string> > _edge_maps;
3569 std::vector<std::vector<std::string> > _attributes;
3573 std::istringstream line;
3577 /// \brief Constructor
3579 /// Construct an \e LGF contents reader, which reads from the given
3581 LgfContents(std::istream& is)
3582 : _is(&is), local_is(false) {}
3584 /// \brief Constructor
3586 /// Construct an \e LGF contents reader, which reads from the given
3588 LgfContents(const std::string& fn)
3589 : _is(new std::ifstream(fn.c_str())), local_is(true) {
3592 throw IoError("Cannot open file", fn);
3596 /// \brief Constructor
3598 /// Construct an \e LGF contents reader, which reads from the given
3600 LgfContents(const char* fn)
3601 : _is(new std::ifstream(fn)), local_is(true) {
3604 throw IoError("Cannot open file", fn);
3608 /// \brief Destructor
3610 if (local_is) delete _is;
3615 LgfContents(const LgfContents&);
3616 LgfContents& operator=(const LgfContents&);
3621 /// \name Node Sections
3624 /// \brief Gives back the number of node sections in the file.
3626 /// Gives back the number of node sections in the file.
3627 int nodeSectionNum() const {
3628 return _node_sections.size();
3631 /// \brief Returns the node section name at the given position.
3633 /// Returns the node section name at the given position.
3634 const std::string& nodeSection(int i) const {
3635 return _node_sections[i];
3638 /// \brief Gives back the node maps for the given section.
3640 /// Gives back the node maps for the given section.
3641 const std::vector<std::string>& nodeMapNames(int i) const {
3642 return _node_maps[i];
3647 /// \name Arc/Edge Sections
3650 /// \brief Gives back the number of arc/edge sections in the file.
3652 /// Gives back the number of arc/edge sections in the file.
3653 /// \note It is synonym of \c edgeSectionNum().
3654 int arcSectionNum() const {
3655 return _edge_sections.size();
3658 /// \brief Returns the arc/edge section name at the given position.
3660 /// Returns the arc/edge section name at the given position.
3661 /// \note It is synonym of \c edgeSection().
3662 const std::string& arcSection(int i) const {
3663 return _edge_sections[i];
3666 /// \brief Gives back the arc/edge maps for the given section.
3668 /// Gives back the arc/edge maps for the given section.
3669 /// \note It is synonym of \c edgeMapNames().
3670 const std::vector<std::string>& arcMapNames(int i) const {
3671 return _edge_maps[i];
3679 /// \brief Gives back the number of arc/edge sections in the file.
3681 /// Gives back the number of arc/edge sections in the file.
3682 /// \note It is synonym of \c arcSectionNum().
3683 int edgeSectionNum() const {
3684 return _edge_sections.size();
3687 /// \brief Returns the section name at the given position.
3689 /// Returns the section name at the given position.
3690 /// \note It is synonym of \c arcSection().
3691 const std::string& edgeSection(int i) const {
3692 return _edge_sections[i];
3695 /// \brief Gives back the edge maps for the given section.
3697 /// Gives back the edge maps for the given section.
3698 /// \note It is synonym of \c arcMapNames().
3699 const std::vector<std::string>& edgeMapNames(int i) const {
3700 return _edge_maps[i];
3705 /// \name Attribute Sections
3708 /// \brief Gives back the number of attribute sections in the file.
3710 /// Gives back the number of attribute sections in the file.
3711 int attributeSectionNum() const {
3712 return _attribute_sections.size();
3715 /// \brief Returns the attribute section name at the given position.
3717 /// Returns the attribute section name at the given position.
3718 const std::string& attributeSectionNames(int i) const {
3719 return _attribute_sections[i];
3722 /// \brief Gives back the attributes for the given section.
3724 /// Gives back the attributes for the given section.
3725 const std::vector<std::string>& attributes(int i) const {
3726 return _attributes[i];
3731 /// \name Extra Sections
3734 /// \brief Gives back the number of extra sections in the file.
3736 /// Gives back the number of extra sections in the file.
3737 int extraSectionNum() const {
3738 return _extra_sections.size();
3741 /// \brief Returns the extra section type at the given position.
3743 /// Returns the section type at the given position.
3744 const std::string& extraSection(int i) const {
3745 return _extra_sections[i];
3754 while(++line_num, std::getline(*_is, str)) {
3755 line.clear(); line.str(str);
3757 if (line >> std::ws >> c && c != '#') {
3765 bool readSuccess() {
3766 return static_cast<bool>(*_is);
3769 void skipSection() {
3771 while (readSuccess() && line >> c && c != '@') {
3774 if (readSuccess()) {
3779 void readMaps(std::vector<std::string>& maps) {
3781 if (!readLine() || !(line >> c) || c == '@') {
3782 if (readSuccess() && line) line.putback(c);
3787 while (_reader_bits::readToken(line, map)) {
3788 maps.push_back(map);
3792 void readAttributes(std::vector<std::string>& attrs) {
3795 while (readSuccess() && line >> c && c != '@') {
3798 _reader_bits::readToken(line, attr);
3799 attrs.push_back(attr);
3807 /// \name Execution of the Contents Reader
3810 /// \brief Starts the reading
3812 /// This function starts the reading.
3818 while (readSuccess()) {
3823 std::string section, caption;
3824 _reader_bits::readToken(line, section);
3825 _reader_bits::readToken(line, caption);
3827 if (section == "nodes") {
3828 _node_sections.push_back(caption);
3829 _node_maps.push_back(std::vector<std::string>());
3830 readMaps(_node_maps.back());
3831 readLine(); skipSection();
3832 } else if (section == "arcs" || section == "edges") {
3833 _edge_sections.push_back(caption);
3834 _arc_sections.push_back(section == "arcs");
3835 _edge_maps.push_back(std::vector<std::string>());
3836 readMaps(_edge_maps.back());
3837 readLine(); skipSection();
3838 } else if (section == "attributes") {
3839 _attribute_sections.push_back(caption);
3840 _attributes.push_back(std::vector<std::string>());
3841 readAttributes(_attributes.back());
3843 _extra_sections.push_back(section);
3844 readLine(); skipSection();