Rel.07 NEWS - 3. round
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
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 Lemon Format reader.
24 #ifndef LEMON_LEMON_READER_H
25 #define LEMON_LEMON_READER_H
36 #include <lemon/error.h>
37 #include <lemon/graph_utils.h>
38 #include <lemon/bits/utility.h>
39 #include <lemon/bits/item_reader.h>
41 #include <lemon/dim2.h>
43 #include <lemon/concept_check.h>
44 #include <lemon/concepts/maps.h>
48 namespace _reader_bits {
51 bool operator<(T, T) {
52 throw DataFormatError("Label is not comparable");
57 bool operator()(const T& p, const T& q) const {
62 template <typename Item>
63 class ItemLabelReader {
66 bool isLabelReader() { return true; }
68 void readLabel(std::istream&, Item&) {}
70 template <class _ItemLabelReader>
73 bool b = reader.isLabelReader();
74 ignore_unused_variable_warning(b);
76 reader.readLabel(is, item);
78 _ItemLabelReader& reader;
84 template <typename Item>
87 void read(std::istream&, Item&) {}
89 template <class _ItemReader>
93 reader.read(is, item);
101 template <typename Map>
102 struct Ref { typedef Map& Type; };
103 template <typename Map>
104 struct Arg { typedef Map& Type; };
106 template <typename Graph, typename Map>
107 class ForwardComposeMap {
109 typedef typename Graph::UEdge Key;
110 typedef typename Map::Value Value;
112 ForwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
113 : graph(_graph), map(_map) {}
115 void set(const Key& key, const Value& val) {
116 map.set(graph.direct(key, true), val);
121 typename Ref<Map>::Type map;
124 template <typename Graph, typename Map>
125 ForwardComposeMap<Graph, Map>
126 forwardComposeMap(const Graph& graph, const Map& map) {
127 return ForwardComposeMap<Graph, Map>(graph, map);
130 template <typename Graph, typename Map>
131 ForwardComposeMap<Graph, Map>
132 forwardComposeMap(const Graph& graph, Map& map) {
133 return ForwardComposeMap<Graph, Map>(graph, map);
136 template <typename Graph, typename Map>
137 class BackwardComposeMap {
139 typedef typename Graph::UEdge Key;
140 typedef typename Map::Value Value;
142 BackwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
143 : graph(_graph), map(_map) {}
145 void set(const Key& key, const Value& val) {
146 map.set(graph.direct(key, false), val);
151 typename Ref<Map>::Type map;
155 template <typename Graph, typename Map>
156 BackwardComposeMap<Graph, Map>
157 backwardComposeMap(const Graph& graph, const Map& map) {
158 return BackwardComposeMap<Graph, Map>(graph, map);
161 template <typename Graph, typename Map>
162 BackwardComposeMap<Graph, Map>
163 backwardComposeMap(const Graph& graph, Map& map) {
164 return BackwardComposeMap<Graph, Map>(graph, map);
167 template <typename Graph, typename Map>
168 struct Ref<ForwardComposeMap<Graph, Map> > {
169 typedef ForwardComposeMap<Graph, Map> Type;
171 template <typename Graph, typename Map>
172 struct Arg<ForwardComposeMap<Graph, Map> > {
173 typedef const ForwardComposeMap<Graph, Map>& Type;
176 template <typename Graph, typename Map>
177 struct Ref<BackwardComposeMap<Graph, Map> > {
178 typedef BackwardComposeMap<Graph, Map> Type;
180 template <typename Graph, typename Map>
181 struct Arg<BackwardComposeMap<Graph, Map> > {
182 typedef const BackwardComposeMap<Graph, Map>& Type;
185 template <typename Map>
186 struct Ref<dim2::XMap<Map> > {
187 typedef dim2::XMap<Map> Type;
189 template <typename Map>
190 struct Arg<dim2::XMap<Map> > {
191 typedef const dim2::XMap<Map>& Type;
194 template <typename Map>
195 struct Ref<dim2::YMap<Map> > {
196 typedef dim2::YMap<Map> Type;
198 template <typename Map>
199 struct Arg<dim2::YMap<Map> > {
200 typedef const dim2::YMap<Map>& Type;
204 template <typename _Item>
207 template <typename _Item>
208 class MapInverterBase : public MapReaderBase<_Item> {
211 virtual void read(std::istream&, const Item&) = 0;
212 virtual Item read(std::istream&) const = 0;
214 virtual MapInverterBase<_Item>* getInverter() {
219 template <typename _Item, typename _Map, typename _Reader>
220 class MapReaderInverter : public MapInverterBase<_Item> {
223 typedef _Reader Reader;
224 typedef typename Reader::Value Value;
226 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
228 typename _reader_bits::Ref<Map>::Type map;
232 MapReaderInverter(typename _reader_bits::Arg<Map>::Type _map,
233 const Reader& _reader)
234 : map(_map), reader(_reader) {}
236 virtual ~MapReaderInverter() {}
238 virtual void read(std::istream& is, const Item& item) {
240 reader.read(is, value);
241 map.set(item, value);
242 typename Inverse::iterator it = inverse.find(value);
243 if (it == inverse.end()) {
244 inverse.insert(std::make_pair(value, item));
246 throw DataFormatError("Multiple label occurence");
250 virtual Item read(std::istream& is) const {
252 reader.read(is, value);
253 typename Inverse::const_iterator it = inverse.find(value);
254 if (it != inverse.end()) {
258 msg << "Invalid label error";
259 throw DataFormatError(msg.message());
264 template <typename _Item, typename _Reader>
265 class SkipReaderInverter : public MapInverterBase<_Item> {
268 typedef _Reader Reader;
269 typedef typename Reader::Value Value;
270 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
274 SkipReaderInverter(const Reader& _reader)
277 virtual ~SkipReaderInverter() {}
279 virtual void read(std::istream& is, const Item& item) {
281 reader.read(is, value);
282 typename Inverse::iterator it = inverse.find(value);
283 if (it == inverse.end()) {
284 inverse.insert(std::make_pair(value, item));
286 throw DataFormatError("Multiple label occurence error");
290 virtual Item read(std::istream& is) const {
292 reader.read(is, value);
293 typename Inverse::const_iterator it = inverse.find(value);
294 if (it != inverse.end()) {
298 msg << "Invalid label error: " << value;
299 throw DataFormatError(msg.message());
307 template <typename _Item>
308 class MapReaderBase {
312 MapReaderBase() { _touched = false; }
314 void touch(bool value = true) { _touched = value; }
315 bool touched() const { return _touched; }
317 virtual ~MapReaderBase() {}
319 virtual void read(std::istream& is, const Item& item) = 0;
320 virtual MapInverterBase<_Item>* getInverter() = 0;
327 template <typename _Item, typename _Map, typename _Reader>
328 class MapReader : public MapReaderBase<_Item> {
331 typedef _Reader Reader;
332 typedef typename Reader::Value Value;
335 typename _reader_bits::Ref<Map>::Type map;
338 MapReader(typename _reader_bits::Arg<Map>::Type _map,
339 const Reader& _reader)
340 : map(_map), reader(_reader) {}
342 virtual ~MapReader() {}
344 virtual void read(std::istream& is, const Item& item) {
346 reader.read(is, value);
347 map.set(item, value);
350 virtual MapInverterBase<_Item>* getInverter() {
351 return new MapReaderInverter<Item, Map, Reader>(map, reader);
356 template <typename _Item, typename _Reader>
357 class SkipReader : public MapReaderBase<_Item> {
359 typedef _Reader Reader;
360 typedef typename Reader::Value Value;
364 SkipReader(const Reader& _reader) : reader(_reader) {}
366 virtual ~SkipReader() {}
368 virtual void read(std::istream& is, const Item&) {
370 reader.read(is, value);
373 virtual MapInverterBase<Item>* getInverter() {
374 return new SkipReaderInverter<Item, Reader>(reader);
378 template <typename _Item>
379 class LabelReaderBase {
382 virtual ~LabelReaderBase() {}
383 virtual Item read(std::istream& is) const = 0;
384 virtual bool isLabelReader() const = 0;
385 virtual LabelReaderBase<_Item>* clone() const = 0;
388 template <typename _Item, typename _BoxedLabelReader>
389 class LabelReader : public LabelReaderBase<_Item> {
392 typedef _BoxedLabelReader BoxedLabelReader;
394 const BoxedLabelReader& labelReader;
396 LabelReader(const BoxedLabelReader& _labelReader)
397 : labelReader(_labelReader) {}
399 virtual Item read(std::istream& is) const {
401 labelReader.readLabel(is, item);
405 virtual bool isLabelReader() const {
406 return labelReader.isLabelReader();
409 LabelReader<Item, BoxedLabelReader>* clone() const {
410 return new LabelReader<Item, BoxedLabelReader>(labelReader);
414 template <typename _Item>
420 ItemStore(Item& _item) : item(&_item) {
424 void touch() { _touched = true; }
425 bool touched() const { return _touched; }
427 void read(const Item& _item) {
436 class ValueReaderBase {
438 virtual void read(std::istream&) {};
439 ValueReaderBase() { _touched = false; }
441 void touch() { _touched = true; }
442 bool touched() const { return _touched; }
444 virtual ~ValueReaderBase() {}
449 template <typename _Value, typename _Reader>
450 class ValueReader : public ValueReaderBase {
452 typedef _Value Value;
453 typedef _Reader Reader;
455 ValueReader(Value& _value, const Reader& _reader)
456 : value(_value), reader(_reader) {}
458 virtual void read(std::istream& is) {
459 reader.read(is, value);
468 /// \ingroup lemon_io
469 /// \brief Lemon Format reader class.
471 /// The Lemon Format contains several sections. We do not want to
472 /// determine what sections are in a lemon file we give only a framework
473 /// to read a section oriented format.
475 /// In the Lemon Format each section starts with a line containing a
476 /// \c \@ character on the first not white space position. This line
477 /// is the header line of the section. Each of the next lines belong
478 /// to this section until a line starting with \c \@ character is
479 /// found. This line can start a new section or it can close the
480 /// file with the \c \@end line. The file format ignores the empty
481 /// and comment lines. The line is comment line if it starts with a
484 /// The framework provides an abstract LemonReader::SectionReader class
485 /// that defines the interface of a SectionReader. The SectionReader
486 /// has the \c header() member function that gets a header line string and
487 /// decides if it wants to process the next section. Several SectionReaders
488 /// can be attached to a LemonReader and the first attached that can
489 /// process the section will be used. Its \c read() member will be called
490 /// with a stream containing the section. From this stream the empty and
491 /// comment lines are filtered out.
493 /// \relates GraphReader
494 /// \relates NodeSetReader
495 /// \relates EdgeSetReader
496 /// \relates NodesReader
497 /// \relates EdgesReader
498 /// \relates AttributeReader
502 class FilterStreamBuf : public std::streambuf {
505 typedef std::streambuf Parent;
506 typedef Parent::char_type char_type;
507 FilterStreamBuf(std::istream& is, int& num)
508 : _is(is), _base(0), _eptr(0),
509 _num(num), skip_state(after_endl) {}
513 enum skip_state_type {
519 char_type small_buf[1];
529 skip_state_type skip_state;
532 char_type* base() { return _base; }
534 char_type* eptr() { return _eptr; }
536 int_type blen() { return _eptr - _base; }
538 void setb(char_type* buf, int_type len) {
543 virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
544 if (base()) return 0;
545 if (buf != 0 && len >= int(sizeof(small_buf))) {
548 setb(small_buf, sizeof(small_buf));
554 bool put_char(char c) {
555 switch (skip_state) {
559 skip_state = after_endl;
571 skip_state = comment_line;
575 skip_state = no_skip;
585 skip_state = after_endl;
594 virtual int_type underflow() {
596 if ((c = _is.peek()) != EOF) {
604 for (ptr = base(); ptr != eptr(); ++ptr) {
605 if ((c = _is.get()) != EOF) {
606 if (c == '\n') ++_num;
610 if (skip_state == after_endl && c == '@') {
620 setg(base(), base(), ptr);
624 virtual int_type sync() {
630 int line_num() const {
632 for (char_type* p = gptr(); p != egptr(); ++p) {
640 static void skipPreSection(std::istream& is, int& line_num) {
641 enum skip_state_type { skip, after_endl };
643 skip_state_type skip_state = after_endl;
646 while ((c = is.get()) != EOF) {
647 if (c == '\n') ++line_num;
649 switch (skip_state) {
651 if (c == '\n') skip_state = after_endl;
672 /// \brief Abstract base class for reading a section.
674 /// This class has an \c header() member function what get a
675 /// header line string and decides if it want to process the next
676 /// section. Several SectionReaders can be attached to an LemonReader
677 /// and the first attached what can process the section will be used.
678 /// Its \c read() member will called with a stream contains the section.
679 /// From this stream the empty lines and comments are filtered out.
680 class SectionReader {
681 friend class LemonReader;
683 /// \brief Constructor for SectionReader.
685 /// Constructor for SectionReader. It attach this reader to
686 /// the given LemonReader.
687 SectionReader(LemonReader& reader) {
688 reader.attach(*this);
691 virtual ~SectionReader() {}
693 /// \brief Gives back true when the SectionReader can process
694 /// the section with the given header line.
696 /// It gives back true when the SectionReader can process
697 /// the section with the given header line.
698 virtual bool header(const std::string& line) = 0;
700 /// \brief Reader function of the section.
702 /// It reads the content of the section.
703 virtual void read(std::istream& is) = 0;
705 /// \brief The given section missing in the file.
707 /// The given section missing in the file.
708 virtual void missing() {};
711 /// \brief Constructor for LemonReader.
713 /// Constructor for LemonReader which reads from the given stream.
714 LemonReader(std::istream& _is)
715 : is(&_is), own_is(false) {}
717 /// \brief Constructor for LemonReader.
719 /// Constructor for LemonReader which reads from the given file.
720 LemonReader(const std::string& filename)
721 : is(0), own_is(true) {
722 is = new std::ifstream(filename.c_str());
724 throw FileOpenError(filename);
728 /// \brief Desctructor for LemonReader.
730 /// Desctructor for LemonReader.
738 LemonReader(const LemonReader&);
739 void operator=(const LemonReader&);
741 void attach(SectionReader& reader) {
742 readers.push_back(std::make_pair(&reader, false));
746 /// \brief Executes the LemonReader.
748 /// It executes the LemonReader.
753 SectionReaders::iterator it;
754 skipPreSection(*is, line_num);
755 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
756 for (it = readers.begin(); it != readers.end(); ++it) {
757 if (it->first->header(line)) {
760 FilterStreamBuf buffer(*is, line_num);
762 buffer.pubsetbuf(buf, sizeof(buf));
763 std::istream ss(&buffer);
765 skipPreSection(*is, line_num);
767 } catch (DataFormatError& error) {
768 error.line(buffer.line_num());
774 for (it = readers.begin(); it != readers.end(); ++it) {
777 it->first->missing();
778 } catch (DataFormatError& error) {
779 error.line(line_num);
792 typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
793 SectionReaders readers;
797 /// \ingroup section_io
798 /// \brief SectionReader for reading a graph's nodeset.
800 /// The lemon format can store multiple graph nodesets with several
801 /// maps. The nodeset section's header line is \c \@nodeset \c
802 /// nodeset_name, but the \c nodeset_name may be empty.
804 /// The first line of the section contains the names of the maps separated
805 /// with white spaces. Each next lines describes a node in the nodeset, and
806 /// contains the mapped values for each map.
808 /// If the nodeset contains an \c "label" named map then it will be regarded
809 /// as id map. This map should contain only unique values and when the
810 /// \c readLabel() member will read a value from the given stream it will
811 /// give back that node which is mapped to this value.
813 /// \relates LemonReader
814 template <typename _Graph, typename _Traits = DefaultReaderTraits>
815 class NodeSetReader : public LemonReader::SectionReader {
816 typedef LemonReader::SectionReader Parent;
819 typedef _Graph Graph;
820 typedef _Traits Traits;
821 typedef typename Graph::Node Node;
822 typedef typename Traits::Skipper DefaultSkipper;
824 /// \brief Constructor.
826 /// Constructor for NodeSetReader. It creates the NodeSetReader and
827 /// attach it into the given LemonReader. The nodeset reader will
828 /// add the read nodes to the given Graph. The reader will read
829 /// the section when the \c section_name and the \c _name are the same.
830 NodeSetReader(LemonReader& _reader,
832 const std::string& _name = std::string(),
833 const DefaultSkipper& _skipper = DefaultSkipper())
834 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
837 /// \brief Destructor.
839 /// Destructor for NodeSetReader.
840 virtual ~NodeSetReader() {
841 for (typename MapReaders::iterator it = readers.begin();
842 it != readers.end(); ++it) {
848 NodeSetReader(const NodeSetReader&);
849 void operator=(const NodeSetReader&);
853 /// \brief Add a new node map reader command for the reader.
855 /// Add a new node map reader command for the reader.
856 template <typename Map>
857 NodeSetReader& readNodeMap(std::string label, Map& map) {
859 typename Traits::template Reader<typename Map::Value>, Map,
860 typename _reader_bits::Arg<Map>::Type>(label, map);
863 template <typename Map>
864 NodeSetReader& readNodeMap(std::string label, const Map& map) {
866 typename Traits::template Reader<typename Map::Value>, Map,
867 typename _reader_bits::Arg<Map>::Type>(label, map);
870 /// \brief Add a new node map reader command for the reader.
872 /// Add a new node map reader command for the reader.
873 template <typename ItemReader, typename Map>
874 NodeSetReader& readNodeMap(std::string label, Map& map,
875 const ItemReader& ir = ItemReader()) {
876 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
880 template <typename ItemReader, typename Map>
881 NodeSetReader& readNodeMap(std::string label, const Map& map,
882 const ItemReader& ir = ItemReader()) {
883 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
889 template <typename ItemReader, typename Map, typename MapParameter>
890 NodeSetReader& _readMap(std::string label, MapParameter map,
891 const ItemReader& ir = ItemReader()) {
892 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
893 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
894 if (readers.find(label) != readers.end()) {
896 msg << "Multiple read rule for node map: " << label;
897 throw IoParameterError(msg.message());
900 make_pair(label, new _reader_bits::
901 MapReader<Node, Map, ItemReader>(map, ir)));
907 /// \brief Add a new node map skipper command for the reader.
909 /// Add a new node map skipper command for the reader.
910 template <typename ItemReader>
911 NodeSetReader& skipNodeMap(std::string label,
912 const ItemReader& ir = ItemReader()) {
913 if (readers.find(label) != readers.end()) {
915 msg << "Multiple read rule for node map: " << label;
916 throw IoParameterError(msg.message());
918 readers.insert(make_pair(label, new _reader_bits::
919 SkipReader<Node, ItemReader>(ir)));
925 /// \brief Gives back true when the SectionReader can process
926 /// the section with the given header line.
928 /// It gives back true when the header line starts with \c \@nodeset,
929 /// and the header line's name and the nodeset's name are the same.
930 virtual bool header(const std::string& line) {
931 std::istringstream ls(line);
935 return command == "@nodeset" && name == id;
938 /// \brief Reader function of the section.
940 /// It reads the content of the section.
941 virtual void read(std::istream& is) {
942 std::vector<_reader_bits::MapReaderBase<Node>* > index;
947 std::istringstream ls(line);
950 typename MapReaders::iterator it = readers.find(id);
951 if (it != readers.end()) {
953 index.push_back(it->second);
955 index.push_back(&skipper);
958 inverter.reset(index.back()->getInverter());
959 index.back() = inverter.get();
963 for (typename MapReaders::iterator it = readers.begin();
964 it != readers.end(); ++it) {
965 if (!it->second->touched()) {
967 msg << "Map not found in file: " << it->first;
968 throw IoParameterError(msg.message());
971 while (getline(is, line)) {
972 Node node = graph.addNode();
973 std::istringstream ls(line);
974 for (int i = 0; i < int(index.size()); ++i) {
975 index[i]->read(ls, node);
980 virtual void missing() {
981 if (readers.empty()) return;
983 msg << "NodeSet section not found in file: @nodeset " << name;
984 throw IoParameterError(msg.message());
989 /// \brief Returns true if the nodeset can give back the node by its label.
991 /// Returns true if the nodeset can give back the node by its label.
992 /// It is possible only if an "label" named map was read.
993 bool isLabelReader() const {
994 return inverter.get() != 0;
997 /// \brief Gives back the node by its label.
999 /// It reads an id from the stream and gives back which node belongs to
1000 /// it. It is possible only if there was read an "label" named map.
1001 void readLabel(std::istream& is, Node& node) const {
1002 node = inverter->read(is);
1007 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
1012 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
1014 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
1017 /// \ingroup section_io
1018 /// \brief SectionReader for reading a bipartite graph's nodeset.
1020 /// The lemon format can store multiple bipartite graph nodesets
1021 /// with several maps. The bipartite graph nodeset section's header
1022 /// line is \c \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name
1025 /// The first line of the section contains \c "&anodeset" and the
1026 /// the names of the A-node maps and regular maps separated with
1027 /// white spaces. Each next lines describes an A-node in the anodeset,
1028 /// and contains the mapped values for each map. If one of the line
1029 /// starts with \c "&bnodeset" then this line contains the names of
1030 /// the B-node maps and the regular node maps. And the remaining lines
1031 /// contains the mapped values to the B-nodes.
1033 /// If there is "label" named map then it should be defined in both
1034 /// nodeset, and it will be regarded as id map. This map should
1035 /// contain only unique values and when the \c readLabel() member
1036 /// will read a value from the given stream it will give back that
1037 /// node which is mapped to this value.
1039 /// \relates LemonReader
1040 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1041 class BpNodeSetReader : public LemonReader::SectionReader {
1042 typedef LemonReader::SectionReader Parent;
1045 typedef _Graph Graph;
1046 typedef _Traits Traits;
1047 typedef typename Graph::Node Node;
1048 typedef typename Traits::Skipper DefaultSkipper;
1050 /// \brief Constructor.
1052 /// Constructor for BpNodeSetReader. It creates the BpNodeSetReader and
1053 /// attach it into the given LemonReader. The nodeset reader will
1054 /// add the read nodes to the given Graph. The reader will read
1055 /// the section when the \c section_name and the \c _name are the same.
1056 BpNodeSetReader(LemonReader& _reader,
1058 const std::string& _name = std::string(),
1059 const DefaultSkipper& _skipper = DefaultSkipper())
1060 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
1063 /// \brief Destructor.
1065 /// Destructor for BpNodeSetReader.
1066 virtual ~BpNodeSetReader() {
1067 for (typename MapReaders::iterator it = readers.begin();
1068 it != readers.end(); ++it) {
1074 BpNodeSetReader(const BpNodeSetReader&);
1075 void operator=(const BpNodeSetReader&);
1079 /// \brief Add a new node map reader command for the reader.
1081 /// Add a new node map reader command for the reader.
1082 template <typename Map>
1083 BpNodeSetReader& readNodeMap(std::string label, Map& map) {
1085 typename Traits::template Reader<typename Map::Value>, Map,
1086 typename _reader_bits::Arg<Map>::Type>(label, map);
1089 template <typename Map>
1090 BpNodeSetReader& readNodeMap(std::string label, const Map& map) {
1092 typename Traits::template Reader<typename Map::Value>, Map,
1093 typename _reader_bits::Arg<Map>::Type>(label, map);
1096 /// \brief Add a new node map reader command for the reader.
1098 /// Add a new node map reader command for the reader.
1099 template <typename ItemReader, typename Map>
1100 BpNodeSetReader& readNodeMap(std::string label, Map& map,
1101 const ItemReader& ir = ItemReader()) {
1102 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1106 template <typename ItemReader, typename Map>
1107 BpNodeSetReader& readNodeMap(std::string label, const Map& map,
1108 const ItemReader& ir = ItemReader()) {
1109 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1115 template <typename ItemReader, typename Map, typename MapParameter>
1116 BpNodeSetReader& _readMap(std::string label, MapParameter map,
1117 const ItemReader& ir = ItemReader()) {
1118 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1119 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1120 if (areaders.find(label) != areaders.end() ||
1121 breaders.find(label) != breaders.end() ||
1122 readers.find(label) != readers.end()) {
1124 msg << "Multiple read rule for node map: " << label;
1125 throw IoParameterError(msg.message());
1127 readers.insert(make_pair(label, new _reader_bits::
1128 MapReader<Node, Map, ItemReader>(map, ir)));
1134 /// \brief Add a new A-node map reader command for the reader.
1136 /// Add a new A-node map reader command for the reader.
1137 template <typename Map>
1138 BpNodeSetReader& readANodeMap(std::string label, Map& map) {
1140 typename Traits::template Reader<typename Map::Value>, Map,
1141 typename _reader_bits::Arg<Map>::Type>(label, map);
1144 template <typename Map>
1145 BpNodeSetReader& readANodeMap(std::string label, const Map& map) {
1147 typename Traits::template Reader<typename Map::Value>, Map,
1148 typename _reader_bits::Arg<Map>::Type>(label, map);
1151 /// \brief Add a new A-node map reader command for the reader.
1153 /// Add a new A-node map reader command for the reader.
1154 template <typename ItemReader, typename Map>
1155 BpNodeSetReader& readANodeMap(std::string label, Map& map,
1156 const ItemReader& ir = ItemReader()) {
1157 return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1161 template <typename ItemReader, typename Map>
1162 BpNodeSetReader& readANodeMap(std::string label, const Map& map,
1163 const ItemReader& ir = ItemReader()) {
1164 return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1170 template <typename ItemReader, typename Map, typename MapParameter>
1171 BpNodeSetReader& _readAMap(std::string label, MapParameter map,
1172 const ItemReader& ir = ItemReader()) {
1173 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1174 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1175 if (label == "label") {
1176 throw IoParameterError("Label cannot be A-node map");
1178 if (areaders.find(label) != areaders.end() ||
1179 readers.find(label) != readers.end()) {
1181 msg << "Multiple read rule for A-node map: " << label;
1182 throw IoParameterError(msg.message());
1184 areaders.insert(make_pair(label, new _reader_bits::
1185 MapReader<Node, Map, ItemReader>(map, ir)));
1191 /// \brief Add a new B-node map reader command for the reader.
1193 /// Add a new B-node map reader command for the reader.
1194 template <typename Map>
1195 BpNodeSetReader& readBNodeMap(std::string label, Map& map) {
1197 typename Traits::template Reader<typename Map::Value>, Map,
1198 typename _reader_bits::Arg<Map>::Type>(label, map);
1201 template <typename Map>
1202 BpNodeSetReader& readBNodeMap(std::string label, const Map& map) {
1204 typename Traits::template Reader<typename Map::Value>, Map,
1205 typename _reader_bits::Arg<Map>::Type>(label, map);
1208 /// \brief Add a new B-node map reader command for the reader.
1210 /// Add a new B-node map reader command for the reader.
1211 template <typename ItemReader, typename Map>
1212 BpNodeSetReader& readBNodeMap(std::string label, Map& map,
1213 const ItemReader& ir = ItemReader()) {
1214 return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1218 template <typename ItemReader, typename Map>
1219 BpNodeSetReader& readBNodeMap(std::string label, const Map& map,
1220 const ItemReader& ir = ItemReader()) {
1221 return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1227 template <typename ItemReader, typename Map, typename MapParameter>
1228 BpNodeSetReader& _readBMap(std::string label, MapParameter map,
1229 const ItemReader& ir = ItemReader()) {
1230 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1231 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1232 if (label == "label") {
1233 throw IoParameterError("Label cannot be B-node map");
1235 if (breaders.find(label) != breaders.end() ||
1236 readers.find(label) != readers.end()) {
1238 msg << "Multiple read rule for B-node map: " << label;
1239 throw IoParameterError(msg.message());
1241 breaders.insert(make_pair(label, new _reader_bits::
1242 MapReader<Node, Map, ItemReader>(map, ir)));
1248 /// \brief Add a new node map skipper command for the reader.
1250 /// Add a new node map skipper command for the reader.
1251 template <typename ItemReader>
1252 BpNodeSetReader& skipNodeMap(std::string label,
1253 const ItemReader& ir = ItemReader()) {
1254 if (areaders.find(label) != areaders.end() ||
1255 breaders.find(label) != breaders.end() ||
1256 readers.find(label) != readers.end()) {
1258 msg << "Multiple read rule for node map: " << label;
1259 throw IoParameterError(msg.message());
1261 readers.insert(make_pair(label, new _reader_bits::
1262 SkipReader<Node, ItemReader>(ir)));
1266 /// \brief Add a new A-node map skipper command for the reader.
1268 /// Add a new A-node map skipper command for the reader.
1269 template <typename ItemReader>
1270 BpNodeSetReader& skipANodeMap(std::string label,
1271 const ItemReader& ir = ItemReader()) {
1272 if (label == "label") {
1273 throw IoParameterError("Label cannot be A-node map");
1275 if (areaders.find(label) != areaders.end() ||
1276 readers.find(label) != readers.end()) {
1278 msg << "Multiple read rule for A-node map: " << label;
1279 throw IoParameterError(msg.message());
1281 areaders.insert(make_pair(label, new _reader_bits::
1282 SkipReader<Node, ItemReader>(ir)));
1286 /// \brief Add a new B-node map skipper command for the reader.
1288 /// Add a new B-node map skipper command for the reader.
1289 template <typename ItemReader>
1290 BpNodeSetReader& skipBNodeMap(std::string label,
1291 const ItemReader& ir = ItemReader()) {
1292 if (label == "label") {
1293 throw IoParameterError("Label cannot be B-node map");
1295 if (breaders.find(label) != breaders.end() ||
1296 readers.find(label) != readers.end()) {
1298 msg << "Multiple read rule for B-node map: " << label;
1299 throw IoParameterError(msg.message());
1301 breaders.insert(make_pair(label, new _reader_bits::
1302 SkipReader<Node, ItemReader>(ir)));
1309 /// \brief Gives back true when the SectionReader can process
1310 /// the section with the given header line.
1312 /// It gives back true when the header line starts with \c \@nodeset,
1313 /// and the header line's name and the nodeset's name are the same.
1314 virtual bool header(const std::string& line) {
1315 std::istringstream ls(line);
1316 std::string command;
1318 ls >> command >> id;
1319 return command == "@bpnodeset" && name == id;
1322 /// \brief Reader function of the section.
1324 /// It reads the content of the section.
1325 virtual void read(std::istream& is) {
1328 std::vector<_reader_bits::MapReaderBase<Node>* > index;
1331 std::istringstream ls(line);
1334 if (id != "&anodeset") {
1335 throw IoParameterError("Cannot find &anodeset subsection");
1338 typename MapReaders::iterator it = readers.find(id);
1339 typename MapReaders::iterator ait = areaders.find(id);
1340 if (it != readers.end()) {
1341 it->second->touch();
1342 index.push_back(it->second);
1343 } else if (ait != areaders.end()) {
1344 ait->second->touch();
1345 index.push_back(ait->second);
1347 index.push_back(&skipper);
1349 if (id == "label") {
1350 inverter.reset(index.back()->getInverter());
1351 index.back() = inverter.get();
1355 for (typename MapReaders::iterator it = areaders.begin();
1356 it != areaders.end(); ++it) {
1357 if (!it->second->touched()) {
1359 msg << "Map not found in file: " << it->first;
1360 throw IoParameterError(msg.message());
1363 for (typename MapReaders::iterator it = readers.begin();
1364 it != readers.end(); ++it) {
1365 if (!it->second->touched()) {
1367 msg << "Map not found in file: " << it->first;
1368 throw IoParameterError(msg.message());
1370 it->second->touch(false);
1373 while (getline(is, line)) {
1374 if (line[0] == '&') {
1375 std::istringstream ls(line);
1378 if (id == "&bnodeset") break;
1380 Node node = graph.addANode();
1381 std::istringstream ls(line);
1382 for (int i = 0; i < int(index.size()); ++i) {
1383 index[i]->read(ls, node);
1389 std::vector<_reader_bits::MapReaderBase<Node>* > index;
1391 std::istringstream ls(line);
1394 if (id != "&bnodeset") {
1395 throw IoParameterError("Cannot find &bnodeset subsection");
1398 typename MapReaders::iterator it = readers.find(id);
1399 typename MapReaders::iterator bit = breaders.find(id);
1400 if (it != readers.end()) {
1401 it->second->touch();
1402 index.push_back(it->second);
1403 } else if (bit != breaders.end()) {
1404 bit->second->touch();
1405 index.push_back(bit->second);
1407 index.push_back(&skipper);
1409 if (id == "label" && inverter.get() != 0) {
1410 index.back() = inverter.get();
1414 for (typename MapReaders::iterator it = breaders.begin();
1415 it != breaders.end(); ++it) {
1416 if (!it->second->touched()) {
1418 msg << "Map not found in file: " << it->first;
1419 throw IoParameterError(msg.message());
1422 for (typename MapReaders::iterator it = readers.begin();
1423 it != readers.end(); ++it) {
1424 if (!it->second->touched()) {
1426 msg << "Map not found in file: " << it->first;
1427 throw IoParameterError(msg.message());
1430 while (getline(is, line)) {
1431 Node node = graph.addBNode();
1432 std::istringstream ls(line);
1433 for (int i = 0; i < int(index.size()); ++i) {
1434 index[i]->read(ls, node);
1440 virtual void missing() {
1441 if (readers.empty()) return;
1443 msg << "BpNodeSet section not found in file: @bpnodeset " << name;
1444 throw IoParameterError(msg.message());
1449 /// \brief Returns true if the nodeset can give back the node by its label.
1451 /// Returns true if the nodeset can give back the node by its label.
1452 /// It is possible only if an "label" named map was read.
1453 bool isLabelReader() const {
1454 return inverter.get() != 0;
1457 /// \brief Gives back the node by its label.
1459 /// It reads an id from the stream and gives back which node belongs to
1460 /// it. It is possible only if there was read an "label" named map.
1461 void readLabel(std::istream& is, Node& node) const {
1462 node = inverter->read(is);
1467 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*>
1470 MapReaders areaders, breaders, readers;
1474 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
1476 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
1480 /// \ingroup section_io
1481 /// \brief SectionReader for reading a graph's edgeset.
1483 /// The lemon format can store multiple graph edgesets with several maps.
1484 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
1485 /// \c edgeset_name may be empty.
1487 /// The first line of the section contains the names of the maps separated
1488 /// with white spaces. Each next lines describes an edge in the edgeset. The
1489 /// line contains the source and the target nodes' id and the mapped
1490 /// values for each map.
1492 /// If the edgeset contains an \c "label" named map then it will be regarded
1493 /// as id map. This map should contain only unique values and when the
1494 /// \c readLabel() member will read a value from the given stream it will
1495 /// give back that edge which is mapped to this value.
1497 /// The edgeset reader needs a node id reader to identify which nodes
1498 /// have to be connected. If a NodeSetReader reads an "label" named map,
1499 /// it will be able to resolve the nodes by ids.
1501 /// \relates LemonReader
1502 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1503 class EdgeSetReader : public LemonReader::SectionReader {
1504 typedef LemonReader::SectionReader Parent;
1507 typedef _Graph Graph;
1508 typedef _Traits Traits;
1509 typedef typename Graph::Node Node;
1510 typedef typename Graph::Edge Edge;
1511 typedef typename Traits::Skipper DefaultSkipper;
1513 /// \brief Constructor.
1515 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
1516 /// attach it into the given LemonReader. The edgeset reader will
1517 /// add the read edges to the given Graph. It will use the given
1518 /// node id reader to read the source and target nodes of the edges.
1519 /// The reader will read the section only if the \c _name and the
1520 /// \c edgset_name are the same.
1521 template <typename NodeLabelReader>
1522 EdgeSetReader(LemonReader& _reader,
1524 const NodeLabelReader& _nodeLabelReader,
1525 const std::string& _name = std::string(),
1526 const DefaultSkipper& _skipper = DefaultSkipper())
1527 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1528 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1529 nodeLabelReader.reset(new _reader_bits::
1530 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1532 /// \brief Destructor.
1534 /// Destructor for EdgeSetReader.
1535 virtual ~EdgeSetReader() {
1536 for (typename MapReaders::iterator it = readers.begin();
1537 it != readers.end(); ++it) {
1543 EdgeSetReader(const EdgeSetReader&);
1544 void operator=(const EdgeSetReader&);
1548 /// \brief Add a new edge map reader command for the reader.
1550 /// Add a new edge map reader command for the reader.
1551 template <typename Map>
1552 EdgeSetReader& readEdgeMap(std::string label, Map& map) {
1554 typename Traits::template Reader<typename Map::Value>, Map,
1555 typename _reader_bits::Arg<Map>::Type>(label, map);
1558 template <typename Map>
1559 EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1561 typename Traits::template Reader<typename Map::Value>, Map,
1562 typename _reader_bits::Arg<Map>::Type>(label, map);
1565 /// \brief Add a new edge map reader command for the reader.
1567 /// Add a new edge map reader command for the reader.
1568 template <typename ItemReader, typename Map>
1569 EdgeSetReader& readEdgeMap(std::string label, Map& map,
1570 const ItemReader& ir = ItemReader()) {
1571 return _readMap<ItemReader, Map,
1572 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1575 template <typename ItemReader, typename Map>
1576 EdgeSetReader& readEdgeMap(std::string label, const Map& map,
1577 const ItemReader& ir = ItemReader()) {
1578 return _readMap<ItemReader, Map,
1579 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1584 template <typename ItemReader, typename Map, typename MapParameter>
1585 EdgeSetReader& _readMap(std::string label, MapParameter map,
1586 const ItemReader& ir = ItemReader()) {
1587 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1588 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1589 if (readers.find(label) != readers.end()) {
1591 msg << "Multiple read rule for edge map: " << label;
1592 throw IoParameterError(msg.message());
1595 make_pair(label, new _reader_bits::
1596 MapReader<Edge, Map, ItemReader>(map, ir)));
1602 /// \brief Add a new edge map skipper command for the reader.
1604 /// Add a new edge map skipper command for the reader.
1605 template <typename ItemReader>
1606 EdgeSetReader& skipEdgeMap(std::string label,
1607 const ItemReader& ir = ItemReader()) {
1608 if (readers.find(label) != readers.end()) {
1610 msg << "Multiple read rule for edge map: " << label;
1611 throw IoParameterError(msg.message());
1613 readers.insert(make_pair(label, new _reader_bits::
1614 SkipReader<Edge, ItemReader>(ir)));
1620 /// \brief Gives back true when the SectionReader can process
1621 /// the section with the given header line.
1623 /// It gives back true when the header line starts with \c \@edgeset,
1624 /// and the header line's name and the edgeset's name are the same.
1625 /// The sections with \@uedgeset head line could be read with this
1626 /// section reader too.
1627 virtual bool header(const std::string& line) {
1628 std::istringstream ls(line);
1629 std::string command;
1631 ls >> command >> id;
1632 return (command == "@edgeset" || command == "@uedgeset") && name == id;
1635 /// \brief Reader function of the section.
1637 /// It reads the content of the section.
1638 virtual void read(std::istream& is) {
1639 if (!nodeLabelReader->isLabelReader()) {
1640 throw DataFormatError("Cannot find nodeset or label map");
1642 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1647 std::istringstream ls(line);
1650 typename MapReaders::iterator it = readers.find(id);
1651 if (it != readers.end()) {
1652 index.push_back(it->second);
1653 it->second->touch();
1655 index.push_back(&skipper);
1657 if (id == "label") {
1658 inverter.reset(index.back()->getInverter());
1659 index.back() = inverter.get();
1663 for (typename MapReaders::iterator it = readers.begin();
1664 it != readers.end(); ++it) {
1665 if (!it->second->touched()) {
1667 msg << "Map not found in file: " << it->first;
1668 throw IoParameterError(msg.message());
1671 while (getline(is, line)) {
1672 std::istringstream ls(line);
1673 Node from = nodeLabelReader->read(ls);
1674 Node to = nodeLabelReader->read(ls);
1675 Edge edge = graph.addEdge(from, to);
1676 for (int i = 0; i < int(index.size()); ++i) {
1677 index[i]->read(ls, edge);
1682 virtual void missing() {
1683 if (readers.empty()) return;
1685 msg << "EdgeSet section not found in file: @edgeset " << name;
1686 throw IoParameterError(msg.message());
1691 /// \brief Returns true if the edgeset can give back the edge by its label.
1693 /// Returns true if the edgeset can give back the edge by its label.
1694 /// It is possible only if an "label" named map was read.
1695 bool isLabelReader() const {
1696 return inverter.get() != 0;
1699 /// \brief Gives back the edge by its label.
1701 /// It reads an id from the stream and gives back which edge belongs to
1702 /// it. It is possible only if there was read an "label" named map.
1703 void readLabel(std::istream& is, Edge& edge) const {
1704 edge = inverter->read(is);
1709 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1716 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1718 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1719 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1722 /// \ingroup section_io
1723 /// \brief SectionReader for reading a undirected graph's edgeset.
1725 /// The lemon format can store multiple undirected edgesets with several
1726 /// maps. The undirected edgeset section's header line is \c \@uedgeset
1727 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1729 /// The first line of the section contains the names of the maps separated
1730 /// with white spaces. Each next lines describes an edge in the edgeset. The
1731 /// line contains the connected nodes' id and the mapped values for each map.
1733 /// The section can handle the directed as a syntactical sugar. Two
1734 /// undirected edge map describes one directed edge map. This two maps
1735 /// are the forward map and the backward map and the names of this map
1736 /// is near the same just with a prefix \c '+' or \c '-' character
1739 /// If the edgeset contains an \c "label" named map then it will be regarded
1740 /// as id map. This map should contain only unique values and when the
1741 /// \c readLabel() member will read a value from the given stream it will
1742 /// give back that uicted edge which is mapped to this value.
1744 /// The undirected edgeset reader needs a node id reader to identify which
1745 /// nodes have to be connected. If a NodeSetReader reads an "label" named
1746 /// map, it will be able to resolve the nodes by ids.
1748 /// \relates LemonReader
1749 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1750 class UEdgeSetReader : public LemonReader::SectionReader {
1751 typedef LemonReader::SectionReader Parent;
1754 typedef _Graph Graph;
1755 typedef _Traits Traits;
1756 typedef typename Graph::Node Node;
1757 typedef typename Graph::Edge Edge;
1758 typedef typename Graph::UEdge UEdge;
1759 typedef typename Traits::Skipper DefaultSkipper;
1761 /// \brief Constructor.
1763 /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1764 /// and attach it into the given LemonReader. The undirected edgeset
1765 /// reader will add the read undirected edges to the given Graph. It
1766 /// will use the given node id reader to read the source and target
1767 /// nodes of the edges. The reader will read the section only if the
1768 /// \c _name and the \c uedgset_name are the same.
1769 template <typename NodeLabelReader>
1770 UEdgeSetReader(LemonReader& _reader,
1772 const NodeLabelReader& _nodeLabelReader,
1773 const std::string& _name = std::string(),
1774 const DefaultSkipper& _skipper = DefaultSkipper())
1775 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1776 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1777 nodeLabelReader.reset(new _reader_bits::
1778 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1780 /// \brief Destructor.
1782 /// Destructor for UEdgeSetReader.
1783 virtual ~UEdgeSetReader() {
1784 for (typename MapReaders::iterator it = readers.begin();
1785 it != readers.end(); ++it) {
1791 UEdgeSetReader(const UEdgeSetReader&);
1792 void operator=(const UEdgeSetReader&);
1796 /// \brief Add a new undirected edge map reader command for the reader.
1798 /// Add a new edge undirected map reader command for the reader.
1799 template <typename Map>
1800 UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
1802 typename Traits::template Reader<typename Map::Value>, Map,
1803 typename _reader_bits::Arg<Map>::Type>(label, map);
1806 template <typename Map>
1807 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
1809 typename Traits::template Reader<typename Map::Value>, Map,
1810 typename _reader_bits::Arg<Map>::Type>(label, map);
1813 /// \brief Add a new undirected edge map reader command for the reader.
1815 /// Add a new edge undirected map reader command for the reader.
1816 template <typename ItemReader, typename Map>
1817 UEdgeSetReader& readUEdgeMap(std::string label, Map& map,
1818 const ItemReader& ir = ItemReader()) {
1819 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1823 template <typename ItemReader, typename Map>
1824 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map,
1825 const ItemReader& ir = ItemReader()) {
1826 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
1832 template <typename ItemReader, typename Map, typename MapParameter>
1833 UEdgeSetReader& _readMap(std::string label, MapParameter map,
1834 const ItemReader& ir = ItemReader()) {
1835 checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1836 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1837 if (readers.find(label) != readers.end()) {
1839 msg << "Multiple read rule for edge map: " << label;
1840 throw IoParameterError(msg.message());
1843 make_pair(label, new _reader_bits::
1844 MapReader<UEdge, Map, ItemReader>(map, ir)));
1850 /// \brief Add a new undirected edge map skipper command for the reader.
1852 /// Add a new undirected edge map skipper command for the reader.
1853 template <typename ItemReader>
1854 UEdgeSetReader& skipUEdgeMap(std::string label,
1855 const ItemReader& ir = ItemReader()) {
1856 if (readers.find(label) != readers.end()) {
1858 msg << "Multiple read rule for node map: " << label;
1859 throw IoParameterError(msg.message());
1861 readers.insert(make_pair(label, new _reader_bits::
1862 SkipReader<UEdge, ItemReader>(ir)));
1866 /// \brief Add a new directed edge map reader command for the reader.
1868 /// Add a new directed edge map reader command for the reader.
1869 template <typename Map>
1870 UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
1872 typename Traits::template Reader<typename Map::Value>, Map,
1873 typename _reader_bits::Arg<Map>::Type>(label, map);
1876 template <typename Map>
1877 UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1879 typename Traits::template Reader<typename Map::Value>, Map,
1880 typename _reader_bits::Arg<Map>::Type>(label, map);
1883 /// \brief Add a new directed edge map reader command for the reader.
1885 /// Add a new directed edge map reader command for the reader.
1886 template <typename ItemReader, typename Map>
1887 UEdgeSetReader& readEdgeMap(std::string label, Map& map,
1888 const ItemReader& ir = ItemReader()) {
1889 return _readDirMap<ItemReader, Map,
1890 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1893 template <typename ItemReader, typename Map>
1894 UEdgeSetReader& readEdgeMap(std::string label, const Map& map,
1895 const ItemReader& ir = ItemReader()) {
1896 return _readDirMap<ItemReader, Map,
1897 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1902 template <typename ItemReader, typename Map, typename MapParameter>
1903 UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
1904 const ItemReader& ir = ItemReader()) {
1905 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1906 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1907 readUEdgeMap("+" + label,
1908 _reader_bits::forwardComposeMap(graph, map), ir);
1909 readUEdgeMap("-" + label,
1910 _reader_bits::backwardComposeMap(graph, map), ir);
1916 /// \brief Add a new directed edge map skipper command for the reader.
1918 /// Add a new directed edge map skipper command for the reader.
1919 template <typename ItemReader>
1920 UEdgeSetReader& skipEdgeMap(std::string label,
1921 const ItemReader& ir = ItemReader()) {
1922 skipUEdgeMap("+" + label, ir);
1923 skipUEdgeMap("-" + label, ir);
1929 /// \brief Gives back true when the SectionReader can process
1930 /// the section with the given header line.
1932 /// It gives back true when the header line starts with \c \@uedgeset,
1933 /// and the header line's name and the edgeset's name are the same.
1934 /// The sections with \@edgeset head line could be read with this
1935 /// section reader too.
1936 virtual bool header(const std::string& line) {
1937 std::istringstream ls(line);
1938 std::string command;
1940 ls >> command >> id;
1941 return (command == "@edgeset" || command == "@uedgeset") && name == id;
1944 /// \brief Reader function of the section.
1946 /// It reads the content of the section.
1947 virtual void read(std::istream& is) {
1948 if (!nodeLabelReader->isLabelReader()) {
1949 throw DataFormatError("Cannot find nodeset or label map");
1951 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1956 std::istringstream ls(line);
1959 typename MapReaders::iterator it = readers.find(id);
1960 if (it != readers.end()) {
1961 index.push_back(it->second);
1962 it->second->touch();
1964 index.push_back(&skipper);
1966 if (id == "label") {
1967 inverter.reset(index.back()->getInverter());
1968 index.back() = inverter.get();
1971 for (typename MapReaders::iterator it = readers.begin();
1972 it != readers.end(); ++it) {
1973 if (!it->second->touched()) {
1975 msg << "Map not found in file: " << it->first;
1976 throw IoParameterError(msg.message());
1980 while (getline(is, line)) {
1981 std::istringstream ls(line);
1982 Node from = nodeLabelReader->read(ls);
1983 Node to = nodeLabelReader->read(ls);
1984 UEdge edge = graph.addEdge(from, to);
1985 for (int i = 0; i < int(index.size()); ++i) {
1986 index[i]->read(ls, edge);
1991 virtual void missing() {
1992 if (readers.empty()) return;
1994 msg << "UEdgeSet section not found in file: @uedgeset " << name;
1995 throw IoParameterError(msg.message());
2000 /// \brief Returns true if the edgeset can give back the edge by its label.
2002 /// Returns true if the edgeset can give back the undirected edge by its
2003 /// id. It is possible only if an "label" named map was read.
2004 bool isLabelReader() const {
2005 return inverter.get() != 0;
2008 /// \brief Gives back the undirected edge by its label.
2010 /// It reads an id from the stream and gives back which undirected edge
2011 /// belongs to it. It is possible only if there was read an "label" named map.
2012 void readLabel(std::istream& is, UEdge& uedge) const {
2013 uedge = inverter->read(is);
2016 /// \brief Gives back the directed edge by its label.
2018 /// It reads an id from the stream and gives back which directed edge
2019 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
2020 /// and the undirected edge id. It is possible only if there was read
2021 /// an "label" named map.
2022 void readLabel(std::istream& is, Edge& edge) const {
2025 UEdge uedge = inverter->read(is);
2027 edge = graph.direct(uedge, true);
2028 } else if (c == '-') {
2029 edge = graph.direct(uedge, false);
2031 throw DataFormatError("Wrong id format for edge "
2032 "in undirected edgeset");
2038 typedef std::map<std::string,
2039 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
2044 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
2046 std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
2047 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
2050 /// \ingroup section_io
2051 /// \brief SectionReader for reading labeled nodes.
2053 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
2054 /// \c nodes_name may be empty.
2056 /// Each line in the section contains the name of the node
2057 /// and then the node id.
2059 /// \relates LemonReader
2060 template <typename _Graph>
2061 class NodeReader : public LemonReader::SectionReader {
2062 typedef LemonReader::SectionReader Parent;
2063 typedef _Graph Graph;
2064 typedef typename Graph::Node Node;
2067 /// \brief Constructor.
2069 /// Constructor for NodeReader. It creates the NodeReader and
2070 /// attach it into the given LemonReader. It will use the given
2071 /// node id reader to give back the nodes. The reader will read the
2072 /// section only if the \c _name and the \c nodes_name are the same.
2073 template <typename _LabelReader>
2074 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2075 const std::string& _name = std::string())
2076 : Parent(_reader), name(_name) {
2077 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
2078 nodeLabelReader.reset(new _reader_bits::
2079 LabelReader<Node, _LabelReader>(_labelReader));
2082 /// \brief Destructor.
2084 /// Destructor for NodeReader.
2085 virtual ~NodeReader() {}
2088 NodeReader(const NodeReader&);
2089 void operator=(const NodeReader&);
2093 /// \brief Add a node reader command for the NodeReader.
2095 /// Add a node reader command for the NodeReader.
2096 void readNode(std::string label, Node& item) {
2097 if (readers.find(label) != readers.end()) {
2099 msg << "Multiple read rule for node: " << label;
2100 throw IoParameterError(msg.message());
2102 readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
2107 /// \brief Gives back true when the SectionReader can process
2108 /// the section with the given header line.
2110 /// It gives back true when the header line start with \c \@nodes,
2111 /// and the header line's name and the reader's name are the same.
2112 virtual bool header(const std::string& line) {
2113 std::istringstream ls(line);
2114 std::string command;
2116 ls >> command >> id;
2117 return command == "@nodes" && name == id;
2120 /// \brief Reader function of the section.
2122 /// It reads the content of the section.
2123 virtual void read(std::istream& is) {
2124 if (!nodeLabelReader->isLabelReader()) {
2125 throw DataFormatError("Cannot find nodeset or label map");
2128 while (getline(is, line)) {
2129 std::istringstream ls(line);
2132 typename NodeReaders::iterator it = readers.find(id);
2133 if (it != readers.end()) {
2134 it->second.read(nodeLabelReader->read(ls));
2138 for (typename NodeReaders::iterator it = readers.begin();
2139 it != readers.end(); ++it) {
2140 if (!it->second.touched()) {
2142 msg << "Node not found in file: " << it->first;
2143 throw IoParameterError(msg.message());
2148 virtual void missing() {
2149 if (readers.empty()) return;
2151 msg << "Nodes section not found in file: @nodes " << name;
2152 throw IoParameterError(msg.message());
2159 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
2160 NodeReaders readers;
2161 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
2164 /// \ingroup section_io
2165 /// \brief SectionReader for reading labeled edges.
2167 /// The edges section's header line is \c \@edges \c edges_name, but the
2168 /// \c edges_name may be empty.
2170 /// Each line in the section contains the name of the edge
2171 /// and then the edge id.
2173 /// \relates LemonReader
2174 template <typename _Graph>
2175 class EdgeReader : public LemonReader::SectionReader {
2176 typedef LemonReader::SectionReader Parent;
2177 typedef _Graph Graph;
2178 typedef typename Graph::Edge Edge;
2181 /// \brief Constructor.
2183 /// Constructor for EdgeReader. It creates the EdgeReader and
2184 /// attach it into the given LemonReader. It will use the given
2185 /// edge id reader to give back the edges. The reader will read the
2186 /// section only if the \c _name and the \c edges_name are the same.
2187 template <typename _LabelReader>
2188 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2189 const std::string& _name = std::string())
2190 : Parent(_reader), name(_name) {
2191 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
2192 edgeLabelReader.reset(new _reader_bits::
2193 LabelReader<Edge, _LabelReader>(_labelReader));
2196 /// \brief Destructor.
2198 /// Destructor for EdgeReader.
2199 virtual ~EdgeReader() {}
2201 EdgeReader(const EdgeReader&);
2202 void operator=(const EdgeReader&);
2206 /// \brief Add an edge reader command for the EdgeReader.
2208 /// Add an edge reader command for the EdgeReader.
2209 void readEdge(std::string label, Edge& item) {
2210 if (readers.find(label) != readers.end()) {
2212 msg << "Multiple read rule for edge: " << label;
2213 throw IoParameterError(msg.message());
2215 readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
2220 /// \brief Gives back true when the SectionReader can process
2221 /// the section with the given header line.
2223 /// It gives back true when the header line start with \c \@edges,
2224 /// and the header line's name and the reader's name are the same.
2225 virtual bool header(const std::string& line) {
2226 std::istringstream ls(line);
2227 std::string command;
2229 ls >> command >> id;
2230 return command == "@edges" && name == id;
2233 /// \brief Reader function of the section.
2235 /// It reads the content of the section.
2236 virtual void read(std::istream& is) {
2237 if (!edgeLabelReader->isLabelReader()) {
2238 throw DataFormatError("Cannot find edgeset or label map");
2241 while (getline(is, line)) {
2242 std::istringstream ls(line);
2245 typename EdgeReaders::iterator it = readers.find(id);
2246 if (it != readers.end()) {
2247 it->second.read(edgeLabelReader->read(ls));
2251 for (typename EdgeReaders::iterator it = readers.begin();
2252 it != readers.end(); ++it) {
2253 if (!it->second.touched()) {
2255 msg << "Edge not found in file: " << it->first;
2256 throw IoParameterError(msg.message());
2261 virtual void missing() {
2262 if (readers.empty()) return;
2264 msg << "Edges section not found in file: @edges " << name;
2265 throw IoParameterError(msg.message());
2272 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
2273 EdgeReaders readers;
2274 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
2277 /// \ingroup section_io
2278 /// \brief SectionReader for reading labeled undirected edges.
2280 /// The undirected edges section's header line is \c \@uedges
2281 /// \c uedges_name, but the \c uedges_name may be empty.
2283 /// Each line in the section contains the name of the undirected edge
2284 /// and then the undirected edge id.
2286 /// \relates LemonReader
2287 template <typename _Graph>
2288 class UEdgeReader : public LemonReader::SectionReader {
2289 typedef LemonReader::SectionReader Parent;
2290 typedef _Graph Graph;
2291 typedef typename Graph::Edge Edge;
2292 typedef typename Graph::UEdge UEdge;
2295 /// \brief Constructor.
2297 /// Constructor for UEdgeReader. It creates the UEdgeReader and
2298 /// attach it into the given LemonReader. It will use the given
2299 /// undirected edge id reader to give back the edges. The reader will
2300 /// read the section only if the \c _name and the \c uedges_name are
2302 template <typename _LabelReader>
2303 UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2304 const std::string& _name = std::string())
2305 : Parent(_reader), name(_name) {
2306 checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
2307 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
2308 uedgeLabelReader.reset(new _reader_bits::
2309 LabelReader<UEdge, _LabelReader>(_labelReader));
2310 edgeLabelReader.reset(new _reader_bits::
2311 LabelReader<Edge, _LabelReader>(_labelReader));
2314 /// \brief Destructor.
2316 /// Destructor for UEdgeReader.
2317 virtual ~UEdgeReader() {}
2319 UEdgeReader(const UEdgeReader&);
2320 void operator=(const UEdgeReader&);
2324 /// \brief Add an undirected edge reader command for the UEdgeReader.
2326 /// Add an undirected edge reader command for the UEdgeReader.
2327 void readUEdge(std::string label, UEdge& item) {
2328 if (uedgeReaders.find(label) != uedgeReaders.end()) {
2330 msg << "Multiple read rule for undirected edge: " << label;
2331 throw IoParameterError(msg.message());
2333 uedgeReaders.insert(make_pair(label, _reader_bits::
2334 ItemStore<UEdge>(item)));
2337 /// \brief Add an edge reader command for the UEdgeReader.
2339 /// Add an edge reader command for the UEdgeReader.
2340 void readEdge(std::string label, Edge& item) {
2341 if (edgeReaders.find(label) != edgeReaders.end()) {
2343 msg << "Multiple read rule for edge: " << label;
2344 throw IoParameterError(msg.message());
2346 edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
2351 /// \brief Gives back true when the SectionReader can process
2352 /// the section with the given header line.
2354 /// It gives back true when the header line start with \c \@edges,
2355 /// and the header line's name and the reader's name are the same.
2356 virtual bool header(const std::string& line) {
2357 std::istringstream ls(line);
2358 std::string command;
2360 ls >> command >> id;
2361 return command == "@uedges" && name == id;
2364 /// \brief Reader function of the section.
2366 /// It reads the content of the section.
2367 virtual void read(std::istream& is) {
2368 if (!edgeLabelReader->isLabelReader()) {
2369 throw DataFormatError("Cannot find undirected edgeset or label map");
2371 if (!uedgeLabelReader->isLabelReader()) {
2372 throw DataFormatError("Cannot find undirected edgeset or label map");
2375 while (getline(is, line)) {
2376 std::istringstream ls(line);
2380 typename UEdgeReaders::iterator it = uedgeReaders.find(id);
2381 if (it != uedgeReaders.end()) {
2382 it->second.read(uedgeLabelReader->read(ls));
2387 typename EdgeReaders::iterator it = edgeReaders.find(id);
2388 if (it != edgeReaders.end()) {
2389 it->second.read(edgeLabelReader->read(ls));
2395 for (typename EdgeReaders::iterator it = edgeReaders.begin();
2396 it != edgeReaders.end(); ++it) {
2397 if (!it->second.touched()) {
2399 msg << "Edge not found in file: " << it->first;
2400 throw IoParameterError(msg.message());
2403 for (typename UEdgeReaders::iterator it = uedgeReaders.begin();
2404 it != uedgeReaders.end(); ++it) {
2405 if (!it->second.touched()) {
2407 msg << "UEdge not found in file: " << it->first;
2408 throw IoParameterError(msg.message());
2413 virtual void missing() {
2414 if (edgeReaders.empty() && uedgeReaders.empty()) return;
2416 msg << "UEdges section not found in file: @uedges " << name;
2417 throw IoParameterError(msg.message());
2424 typedef std::map<std::string,
2425 _reader_bits::ItemStore<UEdge> > UEdgeReaders;
2426 UEdgeReaders uedgeReaders;
2427 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uedgeLabelReader;
2429 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
2430 EdgeReaders edgeReaders;
2431 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
2434 /// \ingroup section_io
2435 /// \brief SectionReader for attributes.
2437 /// The lemon format can store multiple attribute set. Each set has
2438 /// the header line \c \@attributes \c attributeset_name, but the
2439 /// attributeset_name may be empty.
2441 /// The attributeset section contains several lines. Each of them starts
2442 /// with an attribute and then a the value for the id.
2444 /// \relates LemonReader
2445 template <typename _Traits = DefaultReaderTraits>
2446 class AttributeReader : public LemonReader::SectionReader {
2447 typedef LemonReader::SectionReader Parent;
2448 typedef _Traits Traits;
2450 /// \brief Constructor.
2452 /// Constructor for AttributeReader. It creates the AttributeReader and
2453 /// attach it into the given LemonReader. The reader process a section
2454 /// only if the \c section_name and the \c _name are the same.
2455 AttributeReader(LemonReader& _reader,
2456 const std::string& _name = std::string())
2457 : Parent(_reader), name(_name) {}
2459 /// \brief Destructor.
2461 /// Destructor for AttributeReader.
2462 virtual ~AttributeReader() {
2463 for (typename Readers::iterator it = readers.begin();
2464 it != readers.end(); ++it) {
2470 AttributeReader(const AttributeReader&);
2471 void operator=(AttributeReader&);
2474 /// \brief Add an attribute reader command for the reader.
2476 /// Add an attribute reader command for the reader.
2477 template <typename Value>
2478 AttributeReader& readAttribute(const std::string& label, Value& value) {
2479 return readAttribute<typename Traits::template Reader<Value> >
2483 /// \brief Add an attribute reader command for the reader.
2485 /// Add an attribute reader command for the reader.
2486 template <typename ItemReader, typename Value>
2487 AttributeReader& readAttribute(const std::string& label, Value& value,
2488 const ItemReader& ir = ItemReader()) {
2489 checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
2490 if (readers.find(label) != readers.end()) {
2492 msg << "Multiple read rule for attribute: " << label;
2493 throw IoParameterError(msg.message());
2495 readers.insert(make_pair(label, new _reader_bits::
2496 ValueReader<Value, ItemReader>(value, ir)));
2502 /// \brief Gives back true when the SectionReader can process
2503 /// the section with the given header line.
2505 /// It gives back true when the header line start with \c \@attributes,
2506 /// and the header line's id and the attributeset's id are the same.
2507 bool header(const std::string& line) {
2508 std::istringstream ls(line);
2509 std::string command;
2511 ls >> command >> id;
2512 return command == "@attributes" && name == id;
2515 /// \brief Reader function of the section.
2517 /// It reads the content of the section.
2518 void read(std::istream& is) {
2520 while (getline(is, line)) {
2521 std::istringstream ls(line);
2524 typename Readers::iterator it = readers.find(id);
2525 if (it != readers.end()) {
2526 it->second->read(ls);
2527 it->second->touch();
2530 for (typename Readers::iterator it = readers.begin();
2531 it != readers.end(); ++it) {
2532 if (!it->second->touched()) {
2534 msg << "Attribute not found in file: " << it->first;
2535 throw IoParameterError(msg.message());
2540 virtual void missing() {
2541 if (readers.empty()) return;
2543 msg << "Attribute section not found in file: @attributes " << name;
2544 throw IoParameterError(msg.message());
2550 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2554 /// \ingroup section_io
2555 /// \brief SectionReader for reading extra node maps.
2557 /// The lemon format can store maps in the nodeset sections. This
2558 /// class let you make distinict section to store maps. The main
2559 /// purpose of this class is a logical separation of some maps. The
2560 /// other useful application could be to store paths in node maps.
2562 /// The first line of the section contains the names of the maps
2563 /// separated with white spaces. Each next line describes an item
2564 /// in the itemset, and contains in the first column the label of
2565 /// the item and then the mapped values for each map.
2567 /// \relates LemonReader
2568 template <typename _Graph, typename _Traits = DefaultReaderTraits>
2569 class NodeMapReader : public LemonReader::SectionReader {
2570 typedef LemonReader::SectionReader Parent;
2573 typedef _Graph Graph;
2574 typedef typename Graph::Node Node;
2575 typedef _Traits Traits;
2576 typedef typename Traits::Skipper DefaultSkipper;
2578 /// \brief Constructor.
2580 /// Constructor for NodeMapReader. It creates the NodeMapReader and
2581 /// attach it into the given LemonReader. The reader will read
2582 /// the section when the \c section_name and the \c _name are the same.
2583 template <typename _LabelReader>
2584 NodeMapReader(LemonReader& _reader,
2585 const Graph& _graph,
2586 const _LabelReader& _labelReader,
2587 const std::string& _name = std::string(),
2588 const DefaultSkipper& _skipper = DefaultSkipper())
2589 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2590 labelReader.reset(new _reader_bits::
2591 LabelReader<Node, _LabelReader>(_labelReader));
2595 /// \brief Destructor.
2597 /// Destructor for NodeMapReader.
2598 virtual ~NodeMapReader() {
2599 for (typename MapReaders::iterator it = readers.begin();
2600 it != readers.end(); ++it) {
2606 NodeMapReader(const NodeMapReader&);
2607 void operator=(const NodeMapReader&);
2611 /// \brief Add a new node map reader command for the reader.
2613 /// Add a new node map reader command for the reader.
2614 template <typename Map>
2615 NodeMapReader& readNodeMap(std::string label, Map& map) {
2617 typename Traits::template Reader<typename Map::Value>, Map,
2618 typename _reader_bits::Arg<Map>::Type>(label, map);
2621 template <typename Map>
2622 NodeMapReader& readNodeMap(std::string label, const Map& map) {
2624 typename Traits::template Reader<typename Map::Value>, Map,
2625 typename _reader_bits::Arg<Map>::Type>(label, map);
2628 /// \brief Add a new node map reader command for the reader.
2630 /// Add a new node map reader command for the reader.
2631 template <typename ItemReader, typename Map>
2632 NodeMapReader& readNodeMap(std::string label, Map& map,
2633 const ItemReader& ir = ItemReader()) {
2634 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2638 template <typename ItemReader, typename Map>
2639 NodeMapReader& readNodeMap(std::string label, const Map& map,
2640 const ItemReader& ir = ItemReader()) {
2641 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2647 template <typename ItemReader, typename Map, typename MapParameter>
2648 NodeMapReader& _readMap(std::string label, MapParameter map,
2649 const ItemReader& ir = ItemReader()) {
2650 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
2651 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2652 if (readers.find(label) != readers.end()) {
2654 msg << "Multiple read rule for map: " << label;
2655 throw IoParameterError(msg.message());
2658 make_pair(label, new _reader_bits::
2659 MapReader<Node, Map, ItemReader>(map, ir)));
2665 /// \brief Add a new node map skipper command for the reader.
2667 /// Add a new node map skipper command for the reader.
2668 template <typename ItemReader>
2669 NodeMapReader& skipNodeMap(std::string label,
2670 const ItemReader& ir = ItemReader()) {
2671 if (readers.find(label) != readers.end()) {
2673 msg << "Multiple read rule for map: " << label;
2674 throw IoParameterError(msg.message());
2676 readers.insert(make_pair(label, new _reader_bits::
2677 SkipReader<Node, ItemReader>(ir)));
2683 /// \brief Gives back true when the SectionReader can process
2684 /// the section with the given header line.
2686 /// It gives back true when the header line starts with \c \@mapset,
2687 /// and the header line's name and the mapset's name are the same.
2688 virtual bool header(const std::string& line) {
2689 std::istringstream ls(line);
2690 std::string command;
2692 ls >> command >> id;
2693 return command == "@nodemaps" && name == id;
2696 /// \brief Reader function of the section.
2698 /// It reads the content of the section.
2699 virtual void read(std::istream& is) {
2700 std::vector<_reader_bits::MapReaderBase<Node>* > index;
2705 std::istringstream ls(line);
2708 typename MapReaders::iterator it = readers.find(id);
2709 if (it != readers.end()) {
2710 it->second->touch();
2711 index.push_back(it->second);
2713 index.push_back(&skipper);
2717 for (typename MapReaders::iterator it = readers.begin();
2718 it != readers.end(); ++it) {
2719 if (!it->second->touched()) {
2721 msg << "Map not found in file: " << it->first;
2722 throw IoParameterError(msg.message());
2725 while (getline(is, line)) {
2726 std::istringstream ls(line);
2727 Node node = labelReader->read(ls);
2728 for (int i = 0; i < int(index.size()); ++i) {
2729 index[i]->read(ls, node);
2734 virtual void missing() {
2735 if (readers.empty()) return;
2737 msg << "NodeMap section not found in file: @nodemaps " << name;
2738 throw IoParameterError(msg.message());
2743 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
2748 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
2749 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > labelReader;
2753 /// \ingroup section_io
2754 /// \brief SectionReader for reading extra edge maps.
2756 /// The lemon format can store maps in the edgeset sections. This
2757 /// class let you make distinict section to store maps. The main
2758 /// purpose of this class is a logical separation of some maps. The
2759 /// other useful application could be to store paths in edge maps.
2761 /// The first line of the section contains the names of the maps
2762 /// separated with white spaces. Each next line describes an item
2763 /// in the itemset, and contains in the first column the label of
2764 /// the item and then the mapped values for each map.
2766 /// \relates LemonReader
2767 template <typename _Graph, typename _Traits = DefaultReaderTraits>
2768 class EdgeMapReader : public LemonReader::SectionReader {
2769 typedef LemonReader::SectionReader Parent;
2772 typedef _Graph Graph;
2773 typedef typename Graph::Edge Edge;
2774 typedef _Traits Traits;
2775 typedef typename Traits::Skipper DefaultSkipper;
2777 /// \brief Constructor.
2779 /// Constructor for EdgeMapReader. It creates the EdgeMapReader and
2780 /// attach it into the given LemonReader. The reader will read
2781 /// the section when the \c section_name and the \c _name are the same.
2782 template <typename _LabelReader>
2783 EdgeMapReader(LemonReader& _reader,
2784 const Graph& _graph,
2785 const _LabelReader& _labelReader,
2786 const std::string& _name = std::string(),
2787 const DefaultSkipper& _skipper = DefaultSkipper())
2788 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2789 labelReader.reset(new _reader_bits::
2790 LabelReader<Edge, _LabelReader>(_labelReader));
2794 /// \brief Destructor.
2796 /// Destructor for EdgeMapReader.
2797 virtual ~EdgeMapReader() {
2798 for (typename MapReaders::iterator it = readers.begin();
2799 it != readers.end(); ++it) {
2805 EdgeMapReader(const EdgeMapReader&);
2806 void operator=(const EdgeMapReader&);
2810 /// \brief Add a new edge map reader command for the reader.
2812 /// Add a new edge map reader command for the reader.
2813 template <typename Map>
2814 EdgeMapReader& readEdgeMap(std::string label, Map& map) {
2816 typename Traits::template Reader<typename Map::Value>, Map,
2817 typename _reader_bits::Arg<Map>::Type>(label, map);
2820 template <typename Map>
2821 EdgeMapReader& readEdgeMap(std::string label, const Map& map) {
2823 typename Traits::template Reader<typename Map::Value>, Map,
2824 typename _reader_bits::Arg<Map>::Type>(label, map);
2827 /// \brief Add a new edge map reader command for the reader.
2829 /// Add a new edge map reader command for the reader.
2830 template <typename ItemReader, typename Map>
2831 EdgeMapReader& readEdgeMap(std::string label, Map& map,
2832 const ItemReader& ir = ItemReader()) {
2833 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2837 template <typename ItemReader, typename Map>
2838 EdgeMapReader& readEdgeMap(std::string label, const Map& map,
2839 const ItemReader& ir = ItemReader()) {
2840 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2846 template <typename ItemReader, typename Map, typename MapParameter>
2847 EdgeMapReader& _readMap(std::string label, MapParameter map,
2848 const ItemReader& ir = ItemReader()) {
2849 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
2850 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2851 if (readers.find(label) != readers.end()) {
2853 msg << "Multiple read rule for map: " << label;
2854 throw IoParameterError(msg.message());
2857 make_pair(label, new _reader_bits::
2858 MapReader<Edge, Map, ItemReader>(map, ir)));
2864 /// \brief Add a new edge map skipper command for the reader.
2866 /// Add a new edge map skipper command for the reader.
2867 template <typename ItemReader>
2868 EdgeMapReader& skipEdgeMap(std::string label,
2869 const ItemReader& ir = ItemReader()) {
2870 if (readers.find(label) != readers.end()) {
2872 msg << "Multiple read rule for map: " << label;
2873 throw IoParameterError(msg.message());
2875 readers.insert(make_pair(label, new _reader_bits::
2876 SkipReader<Edge, ItemReader>(ir)));
2882 /// \brief Gives back true when the SectionReader can process
2883 /// the section with the given header line.
2885 /// It gives back true when the header line starts with \c \@mapset,
2886 /// and the header line's name and the mapset's name are the same.
2887 virtual bool header(const std::string& line) {
2888 std::istringstream ls(line);
2889 std::string command;
2891 ls >> command >> id;
2892 return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
2895 /// \brief Reader function of the section.
2897 /// It reads the content of the section.
2898 virtual void read(std::istream& is) {
2899 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
2904 std::istringstream ls(line);
2907 typename MapReaders::iterator it = readers.find(id);
2908 if (it != readers.end()) {
2909 it->second->touch();
2910 index.push_back(it->second);
2912 index.push_back(&skipper);
2916 for (typename MapReaders::iterator it = readers.begin();
2917 it != readers.end(); ++it) {
2918 if (!it->second->touched()) {
2920 msg << "Map not found in file: " << it->first;
2921 throw IoParameterError(msg.message());
2924 while (getline(is, line)) {
2925 std::istringstream ls(line);
2926 Edge edge = labelReader->read(ls);
2927 for (int i = 0; i < int(index.size()); ++i) {
2928 index[i]->read(ls, edge);
2933 virtual void missing() {
2934 if (readers.empty()) return;
2936 msg << "EdgeMap section not found in file: @edgemaps " << name;
2937 throw IoParameterError(msg.message());
2942 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
2947 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
2948 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > labelReader;
2952 /// \ingroup section_io
2953 /// \brief SectionReader for reading extra undirected edge maps.
2955 /// The lemon format can store maps in the uedgeset sections. This
2956 /// class let you make distinict section to store maps. The main
2957 /// purpose of this class is a logical separation of some maps. The
2958 /// other useful application could be to store paths in undirected
2961 /// The first line of the section contains the names of the maps
2962 /// separated with white spaces. Each next line describes an item
2963 /// in the itemset, and contains in the first column the label of
2964 /// the item and then the mapped values for each map.
2966 /// \relates LemonReader
2967 template <typename _Graph, typename _Traits = DefaultReaderTraits>
2968 class UEdgeMapReader : public LemonReader::SectionReader {
2969 typedef LemonReader::SectionReader Parent;
2972 typedef _Graph Graph;
2973 typedef typename Graph::Edge Edge;
2974 typedef typename Graph::UEdge UEdge;
2975 typedef _Traits Traits;
2976 typedef typename Traits::Skipper DefaultSkipper;
2978 /// \brief Constructor.
2980 /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and
2981 /// attach it into the given LemonReader. The reader will read
2982 /// the section when the \c section_name and the \c _name are the same.
2983 template <typename _LabelReader>
2984 UEdgeMapReader(LemonReader& _reader, const Graph& _graph,
2985 const _LabelReader& _labelReader,
2986 const std::string& _name = std::string(),
2987 const DefaultSkipper& _skipper = DefaultSkipper())
2988 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2989 labelReader.reset(new _reader_bits::
2990 LabelReader<UEdge, _LabelReader>(_labelReader));
2994 /// \brief Destructor.
2996 /// Destructor for UEdgeMapReader.
2997 virtual ~UEdgeMapReader() {
2998 for (typename MapReaders::iterator it = readers.begin();
2999 it != readers.end(); ++it) {
3005 UEdgeMapReader(const UEdgeMapReader&);
3006 void operator=(const UEdgeMapReader&);
3010 /// \brief Add a new undirected edge map reader command for the
3013 /// Add a new undirected edge map reader command for the reader.
3014 template <typename Map>
3015 UEdgeMapReader& readUEdgeMap(std::string label, Map& map) {
3017 typename Traits::template Reader<typename Map::Value>, Map,
3018 typename _reader_bits::Arg<Map>::Type>(label, map);
3021 template <typename Map>
3022 UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) {
3024 typename Traits::template Reader<typename Map::Value>, Map,
3025 typename _reader_bits::Arg<Map>::Type>(label, map);
3028 /// \brief Add a new undirected edge map reader command for the
3031 /// Add a new undirected edge map reader command for the reader.
3032 template <typename ItemReader, typename Map>
3033 UEdgeMapReader& readUEdgeMap(std::string label, Map& map,
3034 const ItemReader& ir = ItemReader()) {
3035 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
3039 template <typename ItemReader, typename Map>
3040 UEdgeMapReader& readUEdgeMap(std::string label, const Map& map,
3041 const ItemReader& ir = ItemReader()) {
3042 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
3048 template <typename ItemReader, typename Map, typename MapParameter>
3049 UEdgeMapReader& _readMap(std::string label, MapParameter map,
3050 const ItemReader& ir = ItemReader()) {
3051 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
3052 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
3053 if (readers.find(label) != readers.end()) {
3055 msg << "Multiple read rule for map: " << label;
3056 throw IoParameterError(msg.message());
3059 make_pair(label, new _reader_bits::
3060 MapReader<UEdge, Map, ItemReader>(map, ir)));
3066 /// \brief Add a new undirected edge map skipper command for the
3069 /// Add a new undirected edge map skipper command for the reader.
3070 template <typename ItemReader>
3071 UEdgeMapReader& skipUEdgeMap(std::string label,
3072 const ItemReader& ir = ItemReader()) {
3073 if (readers.find(label) != readers.end()) {
3075 msg << "Multiple read rule for map: " << label;
3076 throw IoParameterError(msg.message());
3078 readers.insert(make_pair(label, new _reader_bits::
3079 SkipReader<Edge, ItemReader>(ir)));
3083 /// \brief Add a new directed edge map reader command for the reader.
3085 /// Add a new directed edge map reader command for the reader.
3086 template <typename Map>
3087 UEdgeMapReader& readEdgeMap(std::string label, Map& map) {
3089 typename Traits::template Reader<typename Map::Value>, Map,
3090 typename _reader_bits::Arg<Map>::Type>(label, map);
3093 template <typename Map>
3094 UEdgeMapReader& readEdgeMap(std::string label, const Map& map) {
3096 typename Traits::template Reader<typename Map::Value>, Map,
3097 typename _reader_bits::Arg<Map>::Type>(label, map);
3100 /// \brief Add a new directed edge map reader command for the reader.
3102 /// Add a new directed edge map reader command for the reader.
3103 template <typename ItemReader, typename Map>
3104 UEdgeMapReader& readEdgeMap(std::string label, Map& map,
3105 const ItemReader& ir = ItemReader()) {
3106 return _readDirMap<ItemReader, Map,
3107 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
3110 template <typename ItemReader, typename Map>
3111 UEdgeMapReader& readEdgeMap(std::string label, const Map& map,
3112 const ItemReader& ir = ItemReader()) {
3113 return _readDirMap<ItemReader, Map,
3114 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
3119 template <typename ItemReader, typename Map, typename MapParameter>
3120 UEdgeMapReader& _readDirMap(std::string label, MapParameter map,
3121 const ItemReader& ir = ItemReader()) {
3122 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
3123 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
3124 readUEdgeMap("+" + label,
3125 _reader_bits::forwardComposeMap(graph, map), ir);
3126 readUEdgeMap("-" + label,
3127 _reader_bits::backwardComposeMap(graph, map), ir);
3133 /// \brief Add a new directed edge map skipper command for the reader.
3135 /// Add a new directed edge map skipper command for the reader.
3136 template <typename ItemReader>
3137 UEdgeMapReader& skipEdgeMap(std::string label,
3138 const ItemReader& ir = ItemReader()) {
3139 skipUEdgeMap("+" + label, ir);
3140 skipUEdgeMap("-" + label, ir);
3146 /// \brief Gives back true when the SectionReader can process
3147 /// the section with the given header line.
3149 /// It gives back true when the header line starts with \c \@mapset,
3150 /// and the header line's name and the mapset's name are the same.
3151 virtual bool header(const std::string& line) {
3152 std::istringstream ls(line);
3153 std::string command;
3155 ls >> command >> id;
3156 return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
3159 /// \brief Reader function of the section.
3161 /// It reads the content of the section.
3162 virtual void read(std::istream& is) {
3163 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
3168 std::istringstream ls(line);
3171 typename MapReaders::iterator it = readers.find(id);
3172 if (it != readers.end()) {
3173 it->second->touch();
3174 index.push_back(it->second);
3176 index.push_back(&skipper);
3180 for (typename MapReaders::iterator it = readers.begin();
3181 it != readers.end(); ++it) {
3182 if (!it->second->touched()) {
3184 msg << "Map not found in file: " << it->first;
3185 throw IoParameterError(msg.message());
3188 while (getline(is, line)) {
3189 std::istringstream ls(line);
3190 UEdge uedge = labelReader->read(ls);
3191 for (int i = 0; i < int(index.size()); ++i) {
3192 index[i]->read(ls, uedge);
3197 virtual void missing() {
3198 if (readers.empty()) return;
3200 msg << "UEdgeMap section not found in file: @uedgemaps " << name;
3201 throw IoParameterError(msg.message());
3209 typedef std::map<std::string,
3210 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
3213 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
3215 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > labelReader;
3219 /// \ingroup section_io
3220 /// \brief SectionReader for retrieve what is in the file.
3222 /// SectionReader for retrieve what is in the file. If you want
3223 /// to know which sections, maps and items are in the file
3224 /// use the next code:
3226 /// LemonReader reader("input.lgf");
3227 /// ContentReader content(reader);
3230 class ContentReader : public LemonReader::SectionReader {
3231 typedef LemonReader::SectionReader Parent;
3233 /// \brief Constructor.
3236 ContentReader(LemonReader& _reader) : Parent(_reader) {}
3238 /// \brief Desctructor.
3241 virtual ~ContentReader() {}
3243 /// \brief Gives back how many nodesets are in the file.
3245 /// Gives back how many nodesets are in the file.
3246 int nodeSetNum() const {
3247 return nodesets.size();
3250 /// \brief Gives back the name of nodeset on the indiced position.
3252 /// Gives back the name of nodeset on the indiced position.
3253 std::string nodeSetName(int index) const {
3254 return nodesets[index].name;
3257 /// \brief Gives back the map names of nodeset on the indiced position.
3259 /// Gives back the map names of nodeset on the indiced position.
3260 const std::vector<std::string>& nodeSetMaps(int index) const {
3261 return nodesets[index].items;
3264 /// \brief Gives back how many edgesets are in the file.
3266 /// Gives back how many edgesets are in the file.
3267 int edgeSetNum() const {
3268 return edgesets.size();
3271 /// \brief Gives back the name of edgeset on the indiced position.
3273 /// Gives back the name of edgeset on the indiced position.
3274 std::string edgeSetName(int index) const {
3275 return edgesets[index].name;
3278 /// \brief Gives back the map names of edgeset on the indiced position.
3280 /// Gives back the map names of edgeset on the indiced position.
3281 const std::vector<std::string>& edgeSetMaps(int index) const {
3282 return edgesets[index].items;
3285 /// \brief Gives back how many undirected edgesets are in the file.
3287 /// Gives back how many undirected edgesets are in the file.
3288 int uEdgeSetNum() const {
3289 return uedgesets.size();
3292 /// \brief Gives back the name of undirected edgeset on the indiced
3295 /// Gives back the name of undirected edgeset on the indiced position.
3296 std::string uEdgeSetName(int index) const {
3297 return uedgesets[index].name;
3300 /// \brief Gives back the map names of undirected edgeset on the indiced
3303 /// Gives back the map names of undirected edgeset on the indiced position.
3304 const std::vector<std::string>& uEdgeSetMaps(int index) const {
3305 return uedgesets[index].items;
3308 /// \brief Gives back how many labeled nodes section are in the file.
3310 /// Gives back how many labeled nodes section are in the file.
3311 int nodesNum() const {
3312 return nodes.size();
3315 /// \brief Gives back the name of labeled nodes section on the indiced
3318 /// Gives back the name of labeled nodes section on the indiced position.
3319 std::string nodesName(int index) const {
3320 return nodes[index].name;
3323 /// \brief Gives back the names of the labeled nodes in the indiced
3326 /// Gives back the names of the labeled nodes in the indiced section.
3327 const std::vector<std::string>& nodesItems(int index) const {
3328 return nodes[index].items;
3331 /// \brief Gives back how many labeled edges section are in the file.
3333 /// Gives back how many labeled edges section are in the file.
3334 int edgesNum() const {
3335 return edges.size();
3338 /// \brief Gives back the name of labeled edges section on the indiced
3341 /// Gives back the name of labeled edges section on the indiced position.
3342 std::string edgesName(int index) const {
3343 return edges[index].name;
3346 /// \brief Gives back the names of the labeled edges in the indiced
3349 /// Gives back the names of the labeled edges in the indiced section.
3350 const std::vector<std::string>& edgesItems(int index) const {
3351 return edges[index].items;
3354 /// \brief Gives back how many labeled undirected edges section are
3357 /// Gives back how many labeled undirected edges section are in the file.
3358 int uEdgesNum() const {
3359 return uedges.size();
3362 /// \brief Gives back the name of labeled undirected edges section
3363 /// on the indiced position.
3365 /// Gives back the name of labeled undirected edges section on the
3366 /// indiced position.
3367 std::string uEdgesName(int index) const {
3368 return uedges[index].name;
3371 /// \brief Gives back the names of the labeled undirected edges in
3372 /// the indiced section.
3374 /// Gives back the names of the labeled undirected edges in the
3375 /// indiced section.
3376 const std::vector<std::string>& uEdgesItems(int index) const {
3377 return uedges[index].items;
3381 /// \brief Gives back how many attributes section are in the file.
3383 /// Gives back how many attributes section are in the file.
3384 int attributesNum() const {
3385 return attributes.size();
3388 /// \brief Gives back the name of attributes section on the indiced
3391 /// Gives back the name of attributes section on the indiced position.
3392 std::string attributesName(int index) const {
3393 return attributes[index].name;
3396 /// \brief Gives back the names of the attributes in the indiced section.
3398 /// Gives back the names of the attributes in the indiced section.
3399 const std::vector<std::string>& attributesItems(int index) const {
3400 return attributes[index].items;
3403 const std::vector<std::string>& otherSections() const {
3409 /// \brief Gives back true when the SectionReader can process
3410 /// the section with the given header line.
3412 /// It gives back true when the section is common section.
3413 bool header(const std::string& line) {
3414 std::istringstream ls(line);
3415 std::string command, name;
3416 ls >> command >> name;
3417 if (command == "@nodeset") {
3419 nodesets.push_back(SectionInfo(name));
3420 } else if (command == "@edgeset") {
3422 edgesets.push_back(SectionInfo(name));
3423 } else if (command == "@uedgeset") {
3425 uedgesets.push_back(SectionInfo(name));
3426 } else if (command == "@nodes") {
3428 nodes.push_back(SectionInfo(name));
3429 } else if (command == "@edges") {
3431 edges.push_back(SectionInfo(name));
3432 } else if (command == "@uedges") {
3434 uedges.push_back(SectionInfo(name));
3435 } else if (command == "@attributes") {
3437 attributes.push_back(SectionInfo(name));
3439 sections.push_back(line);
3445 /// \brief Retrieve the items from various sections.
3447 /// Retrieve the items from various sections.
3448 void read(std::istream& is) {
3449 if (current == "@nodeset") {
3450 readMapNames(is, nodesets.back().items);
3451 } else if (current == "@edgeset") {
3452 readMapNames(is, edgesets.back().items);
3453 } else if (current == "@uedgeset") {
3454 readMapNames(is, uedgesets.back().items);
3455 } else if (current == "@nodes") {
3456 readItemNames(is, nodes.back().items);
3457 } else if (current == "@edges") {
3458 readItemNames(is, edges.back().items);
3459 } else if (current == "@uedges") {
3460 readItemNames(is, uedges.back().items);
3461 } else if (current == "@attributes") {
3462 readItemNames(is, attributes.back().items);
3468 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
3469 std::string line, name;
3470 std::getline(is, line);
3471 std::istringstream ls(line);
3472 while (ls >> name) {
3473 maps.push_back(name);
3475 while (getline(is, line));
3478 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
3479 std::string line, name;
3480 while (std::getline(is, line)) {
3481 std::istringstream ls(line);
3483 maps.push_back(name);
3487 struct SectionInfo {
3489 std::vector<std::string> items;
3491 SectionInfo(const std::string& _name) : name(_name) {}
3494 std::vector<SectionInfo> nodesets;
3495 std::vector<SectionInfo> edgesets;
3496 std::vector<SectionInfo> uedgesets;
3498 std::vector<SectionInfo> nodes;
3499 std::vector<SectionInfo> edges;
3500 std::vector<SectionInfo> uedges;
3502 std::vector<SectionInfo> attributes;
3504 std::vector<std::string> sections;
3506 std::string current;