3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2007
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 if (id == "label") {
1348 inverter.reset(index.back()->getInverter());
1349 index.back() = inverter.get();
1353 for (typename MapReaders::iterator it = areaders.begin();
1354 it != areaders.end(); ++it) {
1355 if (!it->second->touched()) {
1357 msg << "Map not found in file: " << it->first;
1358 throw IoParameterError(msg.message());
1361 for (typename MapReaders::iterator it = readers.begin();
1362 it != readers.end(); ++it) {
1363 if (!it->second->touched()) {
1365 msg << "Map not found in file: " << it->first;
1366 throw IoParameterError(msg.message());
1368 it->second->touch(false);
1371 while (getline(is, line)) {
1372 if (line[0] == '&') {
1373 std::istringstream ls(line);
1376 if (id == "&bnodeset") break;
1378 Node node = graph.addANode();
1379 std::istringstream ls(line);
1380 for (int i = 0; i < int(index.size()); ++i) {
1381 index[i]->read(ls, node);
1387 std::vector<_reader_bits::MapReaderBase<Node>* > index;
1389 std::istringstream ls(line);
1392 if (id != "&bnodeset") {
1393 throw IoParameterError("Cannot find &bnodeset subsection");
1396 typename MapReaders::iterator it = readers.find(id);
1397 typename MapReaders::iterator bit = breaders.find(id);
1398 if (it != readers.end()) {
1399 it->second->touch();
1400 index.push_back(it->second);
1401 } else if (bit != breaders.end()) {
1402 bit->second->touch();
1403 index.push_back(bit->second);
1405 if (id == "label" && inverter.get() != 0) {
1406 index.back() = inverter.get();
1410 for (typename MapReaders::iterator it = breaders.begin();
1411 it != breaders.end(); ++it) {
1412 if (!it->second->touched()) {
1414 msg << "Map not found in file: " << it->first;
1415 throw IoParameterError(msg.message());
1418 for (typename MapReaders::iterator it = readers.begin();
1419 it != readers.end(); ++it) {
1420 if (!it->second->touched()) {
1422 msg << "Map not found in file: " << it->first;
1423 throw IoParameterError(msg.message());
1426 while (getline(is, line)) {
1427 Node node = graph.addBNode();
1428 std::istringstream ls(line);
1429 for (int i = 0; i < int(index.size()); ++i) {
1430 index[i]->read(ls, node);
1436 virtual void missing() {
1437 if (readers.empty()) return;
1439 msg << "BpNodeSet section not found in file: @bpnodeset " << name;
1440 throw IoParameterError(msg.message());
1445 /// \brief Returns true if the nodeset can give back the node by its label.
1447 /// Returns true if the nodeset can give back the node by its label.
1448 /// It is possible only if an "label" named map was read.
1449 bool isLabelReader() const {
1450 return inverter.get() != 0;
1453 /// \brief Gives back the node by its label.
1455 /// It reads an id from the stream and gives back which node belongs to
1456 /// it. It is possible only if there was read an "label" named map.
1457 void readLabel(std::istream& is, Node& node) const {
1458 node = inverter->read(is);
1463 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*>
1466 MapReaders areaders, breaders, readers;
1470 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
1472 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
1476 /// \ingroup section_io
1477 /// \brief SectionReader for reading a graph's edgeset.
1479 /// The lemon format can store multiple graph edgesets with several maps.
1480 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
1481 /// \c edgeset_name may be empty.
1483 /// The first line of the section contains the names of the maps separated
1484 /// with white spaces. Each next lines describes an edge in the edgeset. The
1485 /// line contains the source and the target nodes' id and the mapped
1486 /// values for each map.
1488 /// If the edgeset contains an \c "label" named map then it will be regarded
1489 /// as id map. This map should contain only unique values and when the
1490 /// \c readLabel() member will read a value from the given stream it will
1491 /// give back that edge which is mapped to this value.
1493 /// The edgeset reader needs a node id reader to identify which nodes
1494 /// have to be connected. If a NodeSetReader reads an "label" named map,
1495 /// it will be able to resolve the nodes by ids.
1497 /// \relates LemonReader
1498 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1499 class EdgeSetReader : public LemonReader::SectionReader {
1500 typedef LemonReader::SectionReader Parent;
1503 typedef _Graph Graph;
1504 typedef _Traits Traits;
1505 typedef typename Graph::Node Node;
1506 typedef typename Graph::Edge Edge;
1507 typedef typename Traits::Skipper DefaultSkipper;
1509 /// \brief Constructor.
1511 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
1512 /// attach it into the given LemonReader. The edgeset reader will
1513 /// add the read edges to the given Graph. It will use the given
1514 /// node id reader to read the source and target nodes of the edges.
1515 /// The reader will read the section only if the \c _name and the
1516 /// \c edgset_name are the same.
1517 template <typename NodeLabelReader>
1518 EdgeSetReader(LemonReader& _reader,
1520 const NodeLabelReader& _nodeLabelReader,
1521 const std::string& _name = std::string(),
1522 const DefaultSkipper& _skipper = DefaultSkipper())
1523 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1524 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1525 nodeLabelReader.reset(new _reader_bits::
1526 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1528 /// \brief Destructor.
1530 /// Destructor for EdgeSetReader.
1531 virtual ~EdgeSetReader() {
1532 for (typename MapReaders::iterator it = readers.begin();
1533 it != readers.end(); ++it) {
1539 EdgeSetReader(const EdgeSetReader&);
1540 void operator=(const EdgeSetReader&);
1544 /// \brief Add a new edge map reader command for the reader.
1546 /// Add a new edge map reader command for the reader.
1547 template <typename Map>
1548 EdgeSetReader& readEdgeMap(std::string label, Map& map) {
1550 typename Traits::template Reader<typename Map::Value>, Map,
1551 typename _reader_bits::Arg<Map>::Type>(label, map);
1554 template <typename Map>
1555 EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1557 typename Traits::template Reader<typename Map::Value>, Map,
1558 typename _reader_bits::Arg<Map>::Type>(label, map);
1561 /// \brief Add a new edge map reader command for the reader.
1563 /// Add a new edge map reader command for the reader.
1564 template <typename ItemReader, typename Map>
1565 EdgeSetReader& readEdgeMap(std::string label, Map& map,
1566 const ItemReader& ir = ItemReader()) {
1567 return _readMap<ItemReader, Map,
1568 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1571 template <typename ItemReader, typename Map>
1572 EdgeSetReader& readEdgeMap(std::string label, const Map& map,
1573 const ItemReader& ir = ItemReader()) {
1574 return _readMap<ItemReader, Map,
1575 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1580 template <typename ItemReader, typename Map, typename MapParameter>
1581 EdgeSetReader& _readMap(std::string label, MapParameter map,
1582 const ItemReader& ir = ItemReader()) {
1583 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1584 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1585 if (readers.find(label) != readers.end()) {
1587 msg << "Multiple read rule for edge map: " << label;
1588 throw IoParameterError(msg.message());
1591 make_pair(label, new _reader_bits::
1592 MapReader<Edge, Map, ItemReader>(map, ir)));
1598 /// \brief Add a new edge map skipper command for the reader.
1600 /// Add a new edge map skipper command for the reader.
1601 template <typename ItemReader>
1602 EdgeSetReader& skipEdgeMap(std::string label,
1603 const ItemReader& ir = ItemReader()) {
1604 if (readers.find(label) != readers.end()) {
1606 msg << "Multiple read rule for edge map: " << label;
1607 throw IoParameterError(msg.message());
1609 readers.insert(make_pair(label, new _reader_bits::
1610 SkipReader<Edge, ItemReader>(ir)));
1616 /// \brief Gives back true when the SectionReader can process
1617 /// the section with the given header line.
1619 /// It gives back true when the header line starts with \c \@edgeset,
1620 /// and the header line's name and the edgeset's name are the same.
1621 /// The sections with \@uedgeset head line could be read with this
1622 /// section reader too.
1623 virtual bool header(const std::string& line) {
1624 std::istringstream ls(line);
1625 std::string command;
1627 ls >> command >> id;
1628 return (command == "@edgeset" || command == "@uedgeset") && name == id;
1631 /// \brief Reader function of the section.
1633 /// It reads the content of the section.
1634 virtual void read(std::istream& is) {
1635 if (!nodeLabelReader->isLabelReader()) {
1636 throw DataFormatError("Cannot find nodeset or label map");
1638 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1643 std::istringstream ls(line);
1646 typename MapReaders::iterator it = readers.find(id);
1647 if (it != readers.end()) {
1648 index.push_back(it->second);
1649 it->second->touch();
1651 index.push_back(&skipper);
1653 if (id == "label") {
1654 inverter.reset(index.back()->getInverter());
1655 index.back() = inverter.get();
1659 for (typename MapReaders::iterator it = readers.begin();
1660 it != readers.end(); ++it) {
1661 if (!it->second->touched()) {
1663 msg << "Map not found in file: " << it->first;
1664 throw IoParameterError(msg.message());
1667 while (getline(is, line)) {
1668 std::istringstream ls(line);
1669 Node from = nodeLabelReader->read(ls);
1670 Node to = nodeLabelReader->read(ls);
1671 Edge edge = graph.addEdge(from, to);
1672 for (int i = 0; i < int(index.size()); ++i) {
1673 index[i]->read(ls, edge);
1678 virtual void missing() {
1679 if (readers.empty()) return;
1681 msg << "EdgeSet section not found in file: @edgeset " << name;
1682 throw IoParameterError(msg.message());
1687 /// \brief Returns true if the edgeset can give back the edge by its label.
1689 /// Returns true if the edgeset can give back the edge by its label.
1690 /// It is possible only if an "label" named map was read.
1691 bool isLabelReader() const {
1692 return inverter.get() != 0;
1695 /// \brief Gives back the edge by its label.
1697 /// It reads an id from the stream and gives back which edge belongs to
1698 /// it. It is possible only if there was read an "label" named map.
1699 void readLabel(std::istream& is, Edge& edge) const {
1700 edge = inverter->read(is);
1705 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1712 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1714 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1715 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1718 /// \ingroup section_io
1719 /// \brief SectionReader for reading a undirected graph's edgeset.
1721 /// The lemon format can store multiple undirected edgesets with several
1722 /// maps. The undirected edgeset section's header line is \c \@uedgeset
1723 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1725 /// The first line of the section contains the names of the maps separated
1726 /// with white spaces. Each next lines describes an edge in the edgeset. The
1727 /// line contains the connected nodes' id and the mapped values for each map.
1729 /// The section can handle the directed as a syntactical sugar. Two
1730 /// undirected edge map describes one directed edge map. This two maps
1731 /// are the forward map and the backward map and the names of this map
1732 /// is near the same just with a prefix \c '+' or \c '-' character
1735 /// If the edgeset contains an \c "label" named map then it will be regarded
1736 /// as id map. This map should contain only unique values and when the
1737 /// \c readLabel() member will read a value from the given stream it will
1738 /// give back that uicted edge which is mapped to this value.
1740 /// The undirected edgeset reader needs a node id reader to identify which
1741 /// nodes have to be connected. If a NodeSetReader reads an "label" named
1742 /// map, it will be able to resolve the nodes by ids.
1744 /// \relates LemonReader
1745 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1746 class UEdgeSetReader : public LemonReader::SectionReader {
1747 typedef LemonReader::SectionReader Parent;
1750 typedef _Graph Graph;
1751 typedef _Traits Traits;
1752 typedef typename Graph::Node Node;
1753 typedef typename Graph::Edge Edge;
1754 typedef typename Graph::UEdge UEdge;
1755 typedef typename Traits::Skipper DefaultSkipper;
1757 /// \brief Constructor.
1759 /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1760 /// and attach it into the given LemonReader. The undirected edgeset
1761 /// reader will add the read undirected edges to the given Graph. It
1762 /// will use the given node id reader to read the source and target
1763 /// nodes of the edges. The reader will read the section only if the
1764 /// \c _name and the \c uedgset_name are the same.
1765 template <typename NodeLabelReader>
1766 UEdgeSetReader(LemonReader& _reader,
1768 const NodeLabelReader& _nodeLabelReader,
1769 const std::string& _name = std::string(),
1770 const DefaultSkipper& _skipper = DefaultSkipper())
1771 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1772 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1773 nodeLabelReader.reset(new _reader_bits::
1774 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1776 /// \brief Destructor.
1778 /// Destructor for UEdgeSetReader.
1779 virtual ~UEdgeSetReader() {
1780 for (typename MapReaders::iterator it = readers.begin();
1781 it != readers.end(); ++it) {
1787 UEdgeSetReader(const UEdgeSetReader&);
1788 void operator=(const UEdgeSetReader&);
1792 /// \brief Add a new undirected edge map reader command for the reader.
1794 /// Add a new edge undirected map reader command for the reader.
1795 template <typename Map>
1796 UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
1798 typename Traits::template Reader<typename Map::Value>, Map,
1799 typename _reader_bits::Arg<Map>::Type>(label, map);
1802 template <typename Map>
1803 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
1805 typename Traits::template Reader<typename Map::Value>, Map,
1806 typename _reader_bits::Arg<Map>::Type>(label, map);
1809 /// \brief Add a new undirected edge map reader command for the reader.
1811 /// Add a new edge undirected map reader command for the reader.
1812 template <typename ItemReader, typename Map>
1813 UEdgeSetReader& readUEdgeMap(std::string label, Map& map,
1814 const ItemReader& ir = ItemReader()) {
1815 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1819 template <typename ItemReader, typename Map>
1820 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map,
1821 const ItemReader& ir = ItemReader()) {
1822 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
1828 template <typename ItemReader, typename Map, typename MapParameter>
1829 UEdgeSetReader& _readMap(std::string label, MapParameter map,
1830 const ItemReader& ir = ItemReader()) {
1831 checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1832 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1833 if (readers.find(label) != readers.end()) {
1835 msg << "Multiple read rule for edge map: " << label;
1836 throw IoParameterError(msg.message());
1839 make_pair(label, new _reader_bits::
1840 MapReader<UEdge, Map, ItemReader>(map, ir)));
1846 /// \brief Add a new undirected edge map skipper command for the reader.
1848 /// Add a new undirected edge map skipper command for the reader.
1849 template <typename ItemReader>
1850 UEdgeSetReader& skipUEdgeMap(std::string label,
1851 const ItemReader& ir = ItemReader()) {
1852 if (readers.find(label) != readers.end()) {
1854 msg << "Multiple read rule for node map: " << label;
1855 throw IoParameterError(msg.message());
1857 readers.insert(make_pair(label, new _reader_bits::
1858 SkipReader<UEdge, ItemReader>(ir)));
1862 /// \brief Add a new directed edge map reader command for the reader.
1864 /// Add a new directed edge map reader command for the reader.
1865 template <typename Map>
1866 UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
1868 typename Traits::template Reader<typename Map::Value>, Map,
1869 typename _reader_bits::Arg<Map>::Type>(label, map);
1872 template <typename Map>
1873 UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1875 typename Traits::template Reader<typename Map::Value>, Map,
1876 typename _reader_bits::Arg<Map>::Type>(label, map);
1879 /// \brief Add a new directed edge map reader command for the reader.
1881 /// Add a new directed edge map reader command for the reader.
1882 template <typename ItemReader, typename Map>
1883 UEdgeSetReader& readEdgeMap(std::string label, Map& map,
1884 const ItemReader& ir = ItemReader()) {
1885 return _readDirMap<ItemReader, Map,
1886 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1889 template <typename ItemReader, typename Map>
1890 UEdgeSetReader& readEdgeMap(std::string label, const Map& map,
1891 const ItemReader& ir = ItemReader()) {
1892 return _readDirMap<ItemReader, Map,
1893 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1898 template <typename ItemReader, typename Map, typename MapParameter>
1899 UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
1900 const ItemReader& ir = ItemReader()) {
1901 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1902 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1903 readUEdgeMap("+" + label,
1904 _reader_bits::forwardComposeMap(graph, map), ir);
1905 readUEdgeMap("-" + label,
1906 _reader_bits::backwardComposeMap(graph, map), ir);
1912 /// \brief Add a new directed edge map skipper command for the reader.
1914 /// Add a new directed edge map skipper command for the reader.
1915 template <typename ItemReader>
1916 UEdgeSetReader& skipEdgeMap(std::string label,
1917 const ItemReader& ir = ItemReader()) {
1918 skipUEdgeMap("+" + label, ir);
1919 skipUEdgeMap("-" + label, ir);
1925 /// \brief Gives back true when the SectionReader can process
1926 /// the section with the given header line.
1928 /// It gives back true when the header line starts with \c \@uedgeset,
1929 /// and the header line's name and the edgeset's name are the same.
1930 /// The sections with \@edgeset head line could be read with this
1931 /// section reader too.
1932 virtual bool header(const std::string& line) {
1933 std::istringstream ls(line);
1934 std::string command;
1936 ls >> command >> id;
1937 return (command == "@edgeset" || command == "@uedgeset") && name == id;
1940 /// \brief Reader function of the section.
1942 /// It reads the content of the section.
1943 virtual void read(std::istream& is) {
1944 if (!nodeLabelReader->isLabelReader()) {
1945 throw DataFormatError("Cannot find nodeset or label map");
1947 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1952 std::istringstream ls(line);
1955 typename MapReaders::iterator it = readers.find(id);
1956 if (it != readers.end()) {
1957 index.push_back(it->second);
1958 it->second->touch();
1960 index.push_back(&skipper);
1962 if (id == "label") {
1963 inverter.reset(index.back()->getInverter());
1964 index.back() = inverter.get();
1967 for (typename MapReaders::iterator it = readers.begin();
1968 it != readers.end(); ++it) {
1969 if (!it->second->touched()) {
1971 msg << "Map not found in file: " << it->first;
1972 throw IoParameterError(msg.message());
1976 while (getline(is, line)) {
1977 std::istringstream ls(line);
1978 Node from = nodeLabelReader->read(ls);
1979 Node to = nodeLabelReader->read(ls);
1980 UEdge edge = graph.addEdge(from, to);
1981 for (int i = 0; i < int(index.size()); ++i) {
1982 index[i]->read(ls, edge);
1987 virtual void missing() {
1988 if (readers.empty()) return;
1990 msg << "UEdgeSet section not found in file: @uedgeset " << name;
1991 throw IoParameterError(msg.message());
1996 /// \brief Returns true if the edgeset can give back the edge by its label.
1998 /// Returns true if the edgeset can give back the undirected edge by its
1999 /// id. It is possible only if an "label" named map was read.
2000 bool isLabelReader() const {
2001 return inverter.get() != 0;
2004 /// \brief Gives back the undirected edge by its label.
2006 /// It reads an id from the stream and gives back which undirected edge
2007 /// belongs to it. It is possible only if there was read an "label" named map.
2008 void readLabel(std::istream& is, UEdge& uedge) const {
2009 uedge = inverter->read(is);
2012 /// \brief Gives back the directed edge by its label.
2014 /// It reads an id from the stream and gives back which directed edge
2015 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
2016 /// and the undirected edge id. It is possible only if there was read
2017 /// an "label" named map.
2018 void readLabel(std::istream& is, Edge& edge) const {
2021 UEdge uedge = inverter->read(is);
2023 edge = graph.direct(uedge, true);
2024 } else if (c == '-') {
2025 edge = graph.direct(uedge, false);
2027 throw DataFormatError("Wrong id format for edge "
2028 "in undirected edgeset");
2034 typedef std::map<std::string,
2035 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
2040 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
2042 std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
2043 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
2046 /// \ingroup section_io
2047 /// \brief SectionReader for reading labeled nodes.
2049 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
2050 /// \c nodes_name may be empty.
2052 /// Each line in the section contains the name of the node
2053 /// and then the node id.
2055 /// \relates LemonReader
2056 template <typename _Graph>
2057 class NodeReader : public LemonReader::SectionReader {
2058 typedef LemonReader::SectionReader Parent;
2059 typedef _Graph Graph;
2060 typedef typename Graph::Node Node;
2063 /// \brief Constructor.
2065 /// Constructor for NodeReader. It creates the NodeReader and
2066 /// attach it into the given LemonReader. It will use the given
2067 /// node id reader to give back the nodes. The reader will read the
2068 /// section only if the \c _name and the \c nodes_name are the same.
2069 template <typename _LabelReader>
2070 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2071 const std::string& _name = std::string())
2072 : Parent(_reader), name(_name) {
2073 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
2074 nodeLabelReader.reset(new _reader_bits::
2075 LabelReader<Node, _LabelReader>(_labelReader));
2078 /// \brief Destructor.
2080 /// Destructor for NodeReader.
2081 virtual ~NodeReader() {}
2084 NodeReader(const NodeReader&);
2085 void operator=(const NodeReader&);
2089 /// \brief Add a node reader command for the NodeReader.
2091 /// Add a node reader command for the NodeReader.
2092 void readNode(std::string label, Node& item) {
2093 if (readers.find(label) != readers.end()) {
2095 msg << "Multiple read rule for node: " << label;
2096 throw IoParameterError(msg.message());
2098 readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
2103 /// \brief Gives back true when the SectionReader can process
2104 /// the section with the given header line.
2106 /// It gives back true when the header line start with \c \@nodes,
2107 /// and the header line's name and the reader's name are the same.
2108 virtual bool header(const std::string& line) {
2109 std::istringstream ls(line);
2110 std::string command;
2112 ls >> command >> id;
2113 return command == "@nodes" && name == id;
2116 /// \brief Reader function of the section.
2118 /// It reads the content of the section.
2119 virtual void read(std::istream& is) {
2120 if (!nodeLabelReader->isLabelReader()) {
2121 throw DataFormatError("Cannot find nodeset or label map");
2124 while (getline(is, line)) {
2125 std::istringstream ls(line);
2128 typename NodeReaders::iterator it = readers.find(id);
2129 if (it != readers.end()) {
2130 it->second.read(nodeLabelReader->read(ls));
2134 for (typename NodeReaders::iterator it = readers.begin();
2135 it != readers.end(); ++it) {
2136 if (!it->second.touched()) {
2138 msg << "Node not found in file: " << it->first;
2139 throw IoParameterError(msg.message());
2144 virtual void missing() {
2145 if (readers.empty()) return;
2147 msg << "Nodes section not found in file: @nodes " << name;
2148 throw IoParameterError(msg.message());
2155 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
2156 NodeReaders readers;
2157 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
2160 /// \ingroup section_io
2161 /// \brief SectionReader for reading labeled edges.
2163 /// The edges section's header line is \c \@edges \c edges_name, but the
2164 /// \c edges_name may be empty.
2166 /// Each line in the section contains the name of the edge
2167 /// and then the edge id.
2169 /// \relates LemonReader
2170 template <typename _Graph>
2171 class EdgeReader : public LemonReader::SectionReader {
2172 typedef LemonReader::SectionReader Parent;
2173 typedef _Graph Graph;
2174 typedef typename Graph::Edge Edge;
2177 /// \brief Constructor.
2179 /// Constructor for EdgeReader. It creates the EdgeReader and
2180 /// attach it into the given LemonReader. It will use the given
2181 /// edge id reader to give back the edges. The reader will read the
2182 /// section only if the \c _name and the \c edges_name are the same.
2183 template <typename _LabelReader>
2184 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2185 const std::string& _name = std::string())
2186 : Parent(_reader), name(_name) {
2187 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
2188 edgeLabelReader.reset(new _reader_bits::
2189 LabelReader<Edge, _LabelReader>(_labelReader));
2192 /// \brief Destructor.
2194 /// Destructor for EdgeReader.
2195 virtual ~EdgeReader() {}
2197 EdgeReader(const EdgeReader&);
2198 void operator=(const EdgeReader&);
2202 /// \brief Add an edge reader command for the EdgeReader.
2204 /// Add an edge reader command for the EdgeReader.
2205 void readEdge(std::string label, Edge& item) {
2206 if (readers.find(label) != readers.end()) {
2208 msg << "Multiple read rule for edge: " << label;
2209 throw IoParameterError(msg.message());
2211 readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
2216 /// \brief Gives back true when the SectionReader can process
2217 /// the section with the given header line.
2219 /// It gives back true when the header line start with \c \@edges,
2220 /// and the header line's name and the reader's name are the same.
2221 virtual bool header(const std::string& line) {
2222 std::istringstream ls(line);
2223 std::string command;
2225 ls >> command >> id;
2226 return command == "@edges" && name == id;
2229 /// \brief Reader function of the section.
2231 /// It reads the content of the section.
2232 virtual void read(std::istream& is) {
2233 if (!edgeLabelReader->isLabelReader()) {
2234 throw DataFormatError("Cannot find edgeset or label map");
2237 while (getline(is, line)) {
2238 std::istringstream ls(line);
2241 typename EdgeReaders::iterator it = readers.find(id);
2242 if (it != readers.end()) {
2243 it->second.read(edgeLabelReader->read(ls));
2247 for (typename EdgeReaders::iterator it = readers.begin();
2248 it != readers.end(); ++it) {
2249 if (!it->second.touched()) {
2251 msg << "Edge not found in file: " << it->first;
2252 throw IoParameterError(msg.message());
2257 virtual void missing() {
2258 if (readers.empty()) return;
2260 msg << "Edges section not found in file: @edges " << name;
2261 throw IoParameterError(msg.message());
2268 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
2269 EdgeReaders readers;
2270 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
2273 /// \ingroup section_io
2274 /// \brief SectionReader for reading labeled undirected edges.
2276 /// The undirected edges section's header line is \c \@uedges
2277 /// \c uedges_name, but the \c uedges_name may be empty.
2279 /// Each line in the section contains the name of the undirected edge
2280 /// and then the undirected edge id.
2282 /// \relates LemonReader
2283 template <typename _Graph>
2284 class UEdgeReader : public LemonReader::SectionReader {
2285 typedef LemonReader::SectionReader Parent;
2286 typedef _Graph Graph;
2287 typedef typename Graph::Edge Edge;
2288 typedef typename Graph::UEdge UEdge;
2291 /// \brief Constructor.
2293 /// Constructor for UEdgeReader. It creates the UEdgeReader and
2294 /// attach it into the given LemonReader. It will use the given
2295 /// undirected edge id reader to give back the edges. The reader will
2296 /// read the section only if the \c _name and the \c uedges_name are
2298 template <typename _LabelReader>
2299 UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2300 const std::string& _name = std::string())
2301 : Parent(_reader), name(_name) {
2302 checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
2303 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
2304 uedgeLabelReader.reset(new _reader_bits::
2305 LabelReader<UEdge, _LabelReader>(_labelReader));
2306 edgeLabelReader.reset(new _reader_bits::
2307 LabelReader<Edge, _LabelReader>(_labelReader));
2310 /// \brief Destructor.
2312 /// Destructor for UEdgeReader.
2313 virtual ~UEdgeReader() {}
2315 UEdgeReader(const UEdgeReader&);
2316 void operator=(const UEdgeReader&);
2320 /// \brief Add an undirected edge reader command for the UEdgeReader.
2322 /// Add an undirected edge reader command for the UEdgeReader.
2323 void readUEdge(std::string label, UEdge& item) {
2324 if (uedgeReaders.find(label) != uedgeReaders.end()) {
2326 msg << "Multiple read rule for undirected edge: " << label;
2327 throw IoParameterError(msg.message());
2329 uedgeReaders.insert(make_pair(label, _reader_bits::
2330 ItemStore<UEdge>(item)));
2333 /// \brief Add an edge reader command for the UEdgeReader.
2335 /// Add an edge reader command for the UEdgeReader.
2336 void readEdge(std::string label, Edge& item) {
2337 if (edgeReaders.find(label) != edgeReaders.end()) {
2339 msg << "Multiple read rule for edge: " << label;
2340 throw IoParameterError(msg.message());
2342 edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
2347 /// \brief Gives back true when the SectionReader can process
2348 /// the section with the given header line.
2350 /// It gives back true when the header line start with \c \@edges,
2351 /// and the header line's name and the reader's name are the same.
2352 virtual bool header(const std::string& line) {
2353 std::istringstream ls(line);
2354 std::string command;
2356 ls >> command >> id;
2357 return command == "@uedges" && name == id;
2360 /// \brief Reader function of the section.
2362 /// It reads the content of the section.
2363 virtual void read(std::istream& is) {
2364 if (!edgeLabelReader->isLabelReader()) {
2365 throw DataFormatError("Cannot find undirected edgeset or label map");
2367 if (!uedgeLabelReader->isLabelReader()) {
2368 throw DataFormatError("Cannot find undirected edgeset or label map");
2371 while (getline(is, line)) {
2372 std::istringstream ls(line);
2376 typename UEdgeReaders::iterator it = uedgeReaders.find(id);
2377 if (it != uedgeReaders.end()) {
2378 it->second.read(uedgeLabelReader->read(ls));
2383 typename EdgeReaders::iterator it = edgeReaders.find(id);
2384 if (it != edgeReaders.end()) {
2385 it->second.read(edgeLabelReader->read(ls));
2391 for (typename EdgeReaders::iterator it = edgeReaders.begin();
2392 it != edgeReaders.end(); ++it) {
2393 if (!it->second.touched()) {
2395 msg << "Edge not found in file: " << it->first;
2396 throw IoParameterError(msg.message());
2399 for (typename UEdgeReaders::iterator it = uedgeReaders.begin();
2400 it != uedgeReaders.end(); ++it) {
2401 if (!it->second.touched()) {
2403 msg << "UEdge not found in file: " << it->first;
2404 throw IoParameterError(msg.message());
2409 virtual void missing() {
2410 if (edgeReaders.empty() && uedgeReaders.empty()) return;
2412 msg << "UEdges section not found in file: @uedges " << name;
2413 throw IoParameterError(msg.message());
2420 typedef std::map<std::string,
2421 _reader_bits::ItemStore<UEdge> > UEdgeReaders;
2422 UEdgeReaders uedgeReaders;
2423 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uedgeLabelReader;
2425 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
2426 EdgeReaders edgeReaders;
2427 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
2430 /// \ingroup section_io
2431 /// \brief SectionReader for attributes.
2433 /// The lemon format can store multiple attribute set. Each set has
2434 /// the header line \c \@attributes \c attributeset_name, but the
2435 /// attributeset_name may be empty.
2437 /// The attributeset section contains several lines. Each of them starts
2438 /// with an attribute and then a the value for the id.
2440 /// \relates LemonReader
2441 template <typename _Traits = DefaultReaderTraits>
2442 class AttributeReader : public LemonReader::SectionReader {
2443 typedef LemonReader::SectionReader Parent;
2444 typedef _Traits Traits;
2446 /// \brief Constructor.
2448 /// Constructor for AttributeReader. It creates the AttributeReader and
2449 /// attach it into the given LemonReader. The reader process a section
2450 /// only if the \c section_name and the \c _name are the same.
2451 AttributeReader(LemonReader& _reader,
2452 const std::string& _name = std::string())
2453 : Parent(_reader), name(_name) {}
2455 /// \brief Destructor.
2457 /// Destructor for AttributeReader.
2458 virtual ~AttributeReader() {
2459 for (typename Readers::iterator it = readers.begin();
2460 it != readers.end(); ++it) {
2466 AttributeReader(const AttributeReader&);
2467 void operator=(AttributeReader&);
2470 /// \brief Add an attribute reader command for the reader.
2472 /// Add an attribute reader command for the reader.
2473 template <typename Value>
2474 AttributeReader& readAttribute(const std::string& label, Value& value) {
2475 return readAttribute<typename Traits::template Reader<Value> >
2479 /// \brief Add an attribute reader command for the reader.
2481 /// Add an attribute reader command for the reader.
2482 template <typename ItemReader, typename Value>
2483 AttributeReader& readAttribute(const std::string& label, Value& value,
2484 const ItemReader& ir = ItemReader()) {
2485 checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
2486 if (readers.find(label) != readers.end()) {
2488 msg << "Multiple read rule for attribute: " << label;
2489 throw IoParameterError(msg.message());
2491 readers.insert(make_pair(label, new _reader_bits::
2492 ValueReader<Value, ItemReader>(value, ir)));
2498 /// \brief Gives back true when the SectionReader can process
2499 /// the section with the given header line.
2501 /// It gives back true when the header line start with \c \@attributes,
2502 /// and the header line's id and the attributeset's id are the same.
2503 bool header(const std::string& line) {
2504 std::istringstream ls(line);
2505 std::string command;
2507 ls >> command >> id;
2508 return command == "@attributes" && name == id;
2511 /// \brief Reader function of the section.
2513 /// It reads the content of the section.
2514 void read(std::istream& is) {
2516 while (getline(is, line)) {
2517 std::istringstream ls(line);
2520 typename Readers::iterator it = readers.find(id);
2521 if (it != readers.end()) {
2522 it->second->read(ls);
2523 it->second->touch();
2526 for (typename Readers::iterator it = readers.begin();
2527 it != readers.end(); ++it) {
2528 if (!it->second->touched()) {
2530 msg << "Attribute not found in file: " << it->first;
2531 throw IoParameterError(msg.message());
2536 virtual void missing() {
2537 if (readers.empty()) return;
2539 msg << "Attribute section not found in file: @attributes " << name;
2540 throw IoParameterError(msg.message());
2546 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2550 /// \ingroup section_io
2551 /// \brief SectionReader for reading extra node maps.
2553 /// The lemon format can store maps in the nodeset sections. This
2554 /// class let you make distinict section to store maps. The main
2555 /// purpose of this class is a logical separation of some maps. The
2556 /// other useful application could be to store paths in node maps.
2558 /// The first line of the section contains the names of the maps
2559 /// separated with white spaces. Each next line describes an item
2560 /// in the itemset, and contains in the first column the label of
2561 /// the item and then the mapped values for each map.
2563 /// \relates LemonReader
2564 template <typename _Graph, typename _Traits = DefaultReaderTraits>
2565 class NodeMapReader : public LemonReader::SectionReader {
2566 typedef LemonReader::SectionReader Parent;
2569 typedef _Graph Graph;
2570 typedef typename Graph::Node Node;
2571 typedef _Traits Traits;
2572 typedef typename Traits::Skipper DefaultSkipper;
2574 /// \brief Constructor.
2576 /// Constructor for NodeMapReader. It creates the NodeMapReader and
2577 /// attach it into the given LemonReader. The reader will read
2578 /// the section when the \c section_name and the \c _name are the same.
2579 template <typename _LabelReader>
2580 NodeMapReader(LemonReader& _reader,
2581 const Graph& _graph,
2582 const _LabelReader& _labelReader,
2583 const std::string& _name = std::string(),
2584 const DefaultSkipper& _skipper = DefaultSkipper())
2585 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2586 labelReader.reset(new _reader_bits::
2587 LabelReader<Node, _LabelReader>(_labelReader));
2591 /// \brief Destructor.
2593 /// Destructor for NodeMapReader.
2594 virtual ~NodeMapReader() {
2595 for (typename MapReaders::iterator it = readers.begin();
2596 it != readers.end(); ++it) {
2602 NodeMapReader(const NodeMapReader&);
2603 void operator=(const NodeMapReader&);
2607 /// \brief Add a new node map reader command for the reader.
2609 /// Add a new node map reader command for the reader.
2610 template <typename Map>
2611 NodeMapReader& readNodeMap(std::string label, Map& map) {
2613 typename Traits::template Reader<typename Map::Value>, Map,
2614 typename _reader_bits::Arg<Map>::Type>(label, map);
2617 template <typename Map>
2618 NodeMapReader& readNodeMap(std::string label, const Map& map) {
2620 typename Traits::template Reader<typename Map::Value>, Map,
2621 typename _reader_bits::Arg<Map>::Type>(label, map);
2624 /// \brief Add a new node map reader command for the reader.
2626 /// Add a new node map reader command for the reader.
2627 template <typename ItemReader, typename Map>
2628 NodeMapReader& readNodeMap(std::string label, Map& map,
2629 const ItemReader& ir = ItemReader()) {
2630 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2634 template <typename ItemReader, typename Map>
2635 NodeMapReader& readNodeMap(std::string label, const Map& map,
2636 const ItemReader& ir = ItemReader()) {
2637 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2643 template <typename ItemReader, typename Map, typename MapParameter>
2644 NodeMapReader& _readMap(std::string label, MapParameter map,
2645 const ItemReader& ir = ItemReader()) {
2646 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
2647 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2648 if (readers.find(label) != readers.end()) {
2650 msg << "Multiple read rule for map: " << label;
2651 throw IoParameterError(msg.message());
2654 make_pair(label, new _reader_bits::
2655 MapReader<Node, Map, ItemReader>(map, ir)));
2661 /// \brief Add a new node map skipper command for the reader.
2663 /// Add a new node map skipper command for the reader.
2664 template <typename ItemReader>
2665 NodeMapReader& skipNodeMap(std::string label,
2666 const ItemReader& ir = ItemReader()) {
2667 if (readers.find(label) != readers.end()) {
2669 msg << "Multiple read rule for map: " << label;
2670 throw IoParameterError(msg.message());
2672 readers.insert(make_pair(label, new _reader_bits::
2673 SkipReader<Node, ItemReader>(ir)));
2679 /// \brief Gives back true when the SectionReader can process
2680 /// the section with the given header line.
2682 /// It gives back true when the header line starts with \c \@mapset,
2683 /// and the header line's name and the mapset's name are the same.
2684 virtual bool header(const std::string& line) {
2685 std::istringstream ls(line);
2686 std::string command;
2688 ls >> command >> id;
2689 return command == "@nodemaps" && name == id;
2692 /// \brief Reader function of the section.
2694 /// It reads the content of the section.
2695 virtual void read(std::istream& is) {
2696 std::vector<_reader_bits::MapReaderBase<Node>* > index;
2701 std::istringstream ls(line);
2704 typename MapReaders::iterator it = readers.find(id);
2705 if (it != readers.end()) {
2706 it->second->touch();
2707 index.push_back(it->second);
2709 index.push_back(&skipper);
2713 for (typename MapReaders::iterator it = readers.begin();
2714 it != readers.end(); ++it) {
2715 if (!it->second->touched()) {
2717 msg << "Map not found in file: " << it->first;
2718 throw IoParameterError(msg.message());
2721 while (getline(is, line)) {
2722 std::istringstream ls(line);
2723 Node node = labelReader->read(ls);
2724 for (int i = 0; i < int(index.size()); ++i) {
2725 index[i]->read(ls, node);
2730 virtual void missing() {
2731 if (readers.empty()) return;
2733 msg << "NodeMap section not found in file: @nodemaps " << name;
2734 throw IoParameterError(msg.message());
2739 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
2744 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
2745 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > labelReader;
2749 /// \ingroup section_io
2750 /// \brief SectionReader for reading extra edge maps.
2752 /// The lemon format can store maps in the edgeset sections. This
2753 /// class let you make distinict section to store maps. The main
2754 /// purpose of this class is a logical separation of some maps. The
2755 /// other useful application could be to store paths in edge maps.
2757 /// The first line of the section contains the names of the maps
2758 /// separated with white spaces. Each next line describes an item
2759 /// in the itemset, and contains in the first column the label of
2760 /// the item and then the mapped values for each map.
2762 /// \relates LemonReader
2763 template <typename _Graph, typename _Traits = DefaultReaderTraits>
2764 class EdgeMapReader : public LemonReader::SectionReader {
2765 typedef LemonReader::SectionReader Parent;
2768 typedef _Graph Graph;
2769 typedef typename Graph::Edge Edge;
2770 typedef _Traits Traits;
2771 typedef typename Traits::Skipper DefaultSkipper;
2773 /// \brief Constructor.
2775 /// Constructor for EdgeMapReader. It creates the EdgeMapReader and
2776 /// attach it into the given LemonReader. The reader will read
2777 /// the section when the \c section_name and the \c _name are the same.
2778 template <typename _LabelReader>
2779 EdgeMapReader(LemonReader& _reader,
2780 const Graph& _graph,
2781 const _LabelReader& _labelReader,
2782 const std::string& _name = std::string(),
2783 const DefaultSkipper& _skipper = DefaultSkipper())
2784 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2785 labelReader.reset(new _reader_bits::
2786 LabelReader<Edge, _LabelReader>(_labelReader));
2790 /// \brief Destructor.
2792 /// Destructor for EdgeMapReader.
2793 virtual ~EdgeMapReader() {
2794 for (typename MapReaders::iterator it = readers.begin();
2795 it != readers.end(); ++it) {
2801 EdgeMapReader(const EdgeMapReader&);
2802 void operator=(const EdgeMapReader&);
2806 /// \brief Add a new edge map reader command for the reader.
2808 /// Add a new edge map reader command for the reader.
2809 template <typename Map>
2810 EdgeMapReader& readEdgeMap(std::string label, Map& map) {
2812 typename Traits::template Reader<typename Map::Value>, Map,
2813 typename _reader_bits::Arg<Map>::Type>(label, map);
2816 template <typename Map>
2817 EdgeMapReader& readEdgeMap(std::string label, const Map& map) {
2819 typename Traits::template Reader<typename Map::Value>, Map,
2820 typename _reader_bits::Arg<Map>::Type>(label, map);
2823 /// \brief Add a new edge map reader command for the reader.
2825 /// Add a new edge map reader command for the reader.
2826 template <typename ItemReader, typename Map>
2827 EdgeMapReader& readEdgeMap(std::string label, Map& map,
2828 const ItemReader& ir = ItemReader()) {
2829 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2833 template <typename ItemReader, typename Map>
2834 EdgeMapReader& readEdgeMap(std::string label, const Map& map,
2835 const ItemReader& ir = ItemReader()) {
2836 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2842 template <typename ItemReader, typename Map, typename MapParameter>
2843 EdgeMapReader& _readMap(std::string label, MapParameter map,
2844 const ItemReader& ir = ItemReader()) {
2845 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
2846 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2847 if (readers.find(label) != readers.end()) {
2849 msg << "Multiple read rule for map: " << label;
2850 throw IoParameterError(msg.message());
2853 make_pair(label, new _reader_bits::
2854 MapReader<Edge, Map, ItemReader>(map, ir)));
2860 /// \brief Add a new edge map skipper command for the reader.
2862 /// Add a new edge map skipper command for the reader.
2863 template <typename ItemReader>
2864 EdgeMapReader& skipEdgeMap(std::string label,
2865 const ItemReader& ir = ItemReader()) {
2866 if (readers.find(label) != readers.end()) {
2868 msg << "Multiple read rule for map: " << label;
2869 throw IoParameterError(msg.message());
2871 readers.insert(make_pair(label, new _reader_bits::
2872 SkipReader<Edge, ItemReader>(ir)));
2878 /// \brief Gives back true when the SectionReader can process
2879 /// the section with the given header line.
2881 /// It gives back true when the header line starts with \c \@mapset,
2882 /// and the header line's name and the mapset's name are the same.
2883 virtual bool header(const std::string& line) {
2884 std::istringstream ls(line);
2885 std::string command;
2887 ls >> command >> id;
2888 return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
2891 /// \brief Reader function of the section.
2893 /// It reads the content of the section.
2894 virtual void read(std::istream& is) {
2895 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
2900 std::istringstream ls(line);
2903 typename MapReaders::iterator it = readers.find(id);
2904 if (it != readers.end()) {
2905 it->second->touch();
2906 index.push_back(it->second);
2908 index.push_back(&skipper);
2912 for (typename MapReaders::iterator it = readers.begin();
2913 it != readers.end(); ++it) {
2914 if (!it->second->touched()) {
2916 msg << "Map not found in file: " << it->first;
2917 throw IoParameterError(msg.message());
2920 while (getline(is, line)) {
2921 std::istringstream ls(line);
2922 Edge edge = labelReader->read(ls);
2923 for (int i = 0; i < int(index.size()); ++i) {
2924 index[i]->read(ls, edge);
2929 virtual void missing() {
2930 if (readers.empty()) return;
2932 msg << "EdgeMap section not found in file: @edgemaps " << name;
2933 throw IoParameterError(msg.message());
2938 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
2943 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
2944 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > labelReader;
2948 /// \ingroup section_io
2949 /// \brief SectionReader for reading extra undirected edge maps.
2951 /// The lemon format can store maps in the uedgeset sections. This
2952 /// class let you make distinict section to store maps. The main
2953 /// purpose of this class is a logical separation of some maps. The
2954 /// other useful application could be to store paths in undirected
2957 /// The first line of the section contains the names of the maps
2958 /// separated with white spaces. Each next line describes an item
2959 /// in the itemset, and contains in the first column the label of
2960 /// the item and then the mapped values for each map.
2962 /// \relates LemonReader
2963 template <typename _Graph, typename _Traits = DefaultReaderTraits>
2964 class UEdgeMapReader : public LemonReader::SectionReader {
2965 typedef LemonReader::SectionReader Parent;
2968 typedef _Graph Graph;
2969 typedef typename Graph::Edge Edge;
2970 typedef typename Graph::UEdge UEdge;
2971 typedef _Traits Traits;
2972 typedef typename Traits::Skipper DefaultSkipper;
2974 /// \brief Constructor.
2976 /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and
2977 /// attach it into the given LemonReader. The reader will read
2978 /// the section when the \c section_name and the \c _name are the same.
2979 template <typename _LabelReader>
2980 UEdgeMapReader(LemonReader& _reader, const Graph& _graph,
2981 const _LabelReader& _labelReader,
2982 const std::string& _name = std::string(),
2983 const DefaultSkipper& _skipper = DefaultSkipper())
2984 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2985 labelReader.reset(new _reader_bits::
2986 LabelReader<UEdge, _LabelReader>(_labelReader));
2990 /// \brief Destructor.
2992 /// Destructor for UEdgeMapReader.
2993 virtual ~UEdgeMapReader() {
2994 for (typename MapReaders::iterator it = readers.begin();
2995 it != readers.end(); ++it) {
3001 UEdgeMapReader(const UEdgeMapReader&);
3002 void operator=(const UEdgeMapReader&);
3006 /// \brief Add a new undirected edge map reader command for the
3009 /// Add a new undirected edge map reader command for the reader.
3010 template <typename Map>
3011 UEdgeMapReader& readUEdgeMap(std::string label, Map& map) {
3013 typename Traits::template Reader<typename Map::Value>, Map,
3014 typename _reader_bits::Arg<Map>::Type>(label, map);
3017 template <typename Map>
3018 UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) {
3020 typename Traits::template Reader<typename Map::Value>, Map,
3021 typename _reader_bits::Arg<Map>::Type>(label, map);
3024 /// \brief Add a new undirected edge map reader command for the
3027 /// Add a new undirected edge map reader command for the reader.
3028 template <typename ItemReader, typename Map>
3029 UEdgeMapReader& readUEdgeMap(std::string label, Map& map,
3030 const ItemReader& ir = ItemReader()) {
3031 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
3035 template <typename ItemReader, typename Map>
3036 UEdgeMapReader& readUEdgeMap(std::string label, const Map& map,
3037 const ItemReader& ir = ItemReader()) {
3038 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
3044 template <typename ItemReader, typename Map, typename MapParameter>
3045 UEdgeMapReader& _readMap(std::string label, MapParameter map,
3046 const ItemReader& ir = ItemReader()) {
3047 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
3048 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
3049 if (readers.find(label) != readers.end()) {
3051 msg << "Multiple read rule for map: " << label;
3052 throw IoParameterError(msg.message());
3055 make_pair(label, new _reader_bits::
3056 MapReader<UEdge, Map, ItemReader>(map, ir)));
3062 /// \brief Add a new undirected edge map skipper command for the
3065 /// Add a new undirected edge map skipper command for the reader.
3066 template <typename ItemReader>
3067 UEdgeMapReader& skipUEdgeMap(std::string label,
3068 const ItemReader& ir = ItemReader()) {
3069 if (readers.find(label) != readers.end()) {
3071 msg << "Multiple read rule for map: " << label;
3072 throw IoParameterError(msg.message());
3074 readers.insert(make_pair(label, new _reader_bits::
3075 SkipReader<Edge, ItemReader>(ir)));
3079 /// \brief Add a new directed edge map reader command for the reader.
3081 /// Add a new directed edge map reader command for the reader.
3082 template <typename Map>
3083 UEdgeMapReader& readEdgeMap(std::string label, Map& map) {
3085 typename Traits::template Reader<typename Map::Value>, Map,
3086 typename _reader_bits::Arg<Map>::Type>(label, map);
3089 template <typename Map>
3090 UEdgeMapReader& readEdgeMap(std::string label, const Map& map) {
3092 typename Traits::template Reader<typename Map::Value>, Map,
3093 typename _reader_bits::Arg<Map>::Type>(label, map);
3096 /// \brief Add a new directed edge map reader command for the reader.
3098 /// Add a new directed edge map reader command for the reader.
3099 template <typename ItemReader, typename Map>
3100 UEdgeMapReader& readEdgeMap(std::string label, Map& map,
3101 const ItemReader& ir = ItemReader()) {
3102 return _readDirMap<ItemReader, Map,
3103 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
3106 template <typename ItemReader, typename Map>
3107 UEdgeMapReader& readEdgeMap(std::string label, const Map& map,
3108 const ItemReader& ir = ItemReader()) {
3109 return _readDirMap<ItemReader, Map,
3110 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
3115 template <typename ItemReader, typename Map, typename MapParameter>
3116 UEdgeMapReader& _readDirMap(std::string label, MapParameter map,
3117 const ItemReader& ir = ItemReader()) {
3118 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
3119 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
3120 readUEdgeMap("+" + label,
3121 _reader_bits::forwardComposeMap(graph, map), ir);
3122 readUEdgeMap("-" + label,
3123 _reader_bits::backwardComposeMap(graph, map), ir);
3129 /// \brief Add a new directed edge map skipper command for the reader.
3131 /// Add a new directed edge map skipper command for the reader.
3132 template <typename ItemReader>
3133 UEdgeMapReader& skipEdgeMap(std::string label,
3134 const ItemReader& ir = ItemReader()) {
3135 skipUEdgeMap("+" + label, ir);
3136 skipUEdgeMap("-" + label, ir);
3142 /// \brief Gives back true when the SectionReader can process
3143 /// the section with the given header line.
3145 /// It gives back true when the header line starts with \c \@mapset,
3146 /// and the header line's name and the mapset's name are the same.
3147 virtual bool header(const std::string& line) {
3148 std::istringstream ls(line);
3149 std::string command;
3151 ls >> command >> id;
3152 return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
3155 /// \brief Reader function of the section.
3157 /// It reads the content of the section.
3158 virtual void read(std::istream& is) {
3159 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
3164 std::istringstream ls(line);
3167 typename MapReaders::iterator it = readers.find(id);
3168 if (it != readers.end()) {
3169 it->second->touch();
3170 index.push_back(it->second);
3172 index.push_back(&skipper);
3176 for (typename MapReaders::iterator it = readers.begin();
3177 it != readers.end(); ++it) {
3178 if (!it->second->touched()) {
3180 msg << "Map not found in file: " << it->first;
3181 throw IoParameterError(msg.message());
3184 while (getline(is, line)) {
3185 std::istringstream ls(line);
3186 UEdge uedge = labelReader->read(ls);
3187 for (int i = 0; i < int(index.size()); ++i) {
3188 index[i]->read(ls, uedge);
3193 virtual void missing() {
3194 if (readers.empty()) return;
3196 msg << "UEdgeMap section not found in file: @uedgemaps " << name;
3197 throw IoParameterError(msg.message());
3205 typedef std::map<std::string,
3206 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
3209 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
3211 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > labelReader;
3215 /// \ingroup section_io
3216 /// \brief SectionReader for retrieve what is in the file.
3218 /// SectionReader for retrieve what is in the file. If you want
3219 /// to know which sections, maps and items are in the file
3220 /// use the next code:
3222 /// LemonReader reader("input.lgf");
3223 /// ContentReader content(reader);
3226 class ContentReader : public LemonReader::SectionReader {
3227 typedef LemonReader::SectionReader Parent;
3229 /// \brief Constructor.
3232 ContentReader(LemonReader& _reader) : Parent(_reader) {}
3234 /// \brief Desctructor.
3237 virtual ~ContentReader() {}
3239 /// \brief Gives back how many nodesets are in the file.
3241 /// Gives back how many nodesets are in the file.
3242 int nodeSetNum() const {
3243 return nodesets.size();
3246 /// \brief Gives back the name of nodeset on the indiced position.
3248 /// Gives back the name of nodeset on the indiced position.
3249 std::string nodeSetName(int index) const {
3250 return nodesets[index].name;
3253 /// \brief Gives back the map names of nodeset on the indiced position.
3255 /// Gives back the map names of nodeset on the indiced position.
3256 const std::vector<std::string>& nodeSetMaps(int index) const {
3257 return nodesets[index].items;
3260 /// \brief Gives back how many edgesets are in the file.
3262 /// Gives back how many edgesets are in the file.
3263 int edgeSetNum() const {
3264 return edgesets.size();
3267 /// \brief Gives back the name of edgeset on the indiced position.
3269 /// Gives back the name of edgeset on the indiced position.
3270 std::string edgeSetName(int index) const {
3271 return edgesets[index].name;
3274 /// \brief Gives back the map names of edgeset on the indiced position.
3276 /// Gives back the map names of edgeset on the indiced position.
3277 const std::vector<std::string>& edgeSetMaps(int index) const {
3278 return edgesets[index].items;
3281 /// \brief Gives back how many undirected edgesets are in the file.
3283 /// Gives back how many undirected edgesets are in the file.
3284 int uEdgeSetNum() const {
3285 return uedgesets.size();
3288 /// \brief Gives back the name of undirected edgeset on the indiced
3291 /// Gives back the name of undirected edgeset on the indiced position.
3292 std::string uEdgeSetName(int index) const {
3293 return uedgesets[index].name;
3296 /// \brief Gives back the map names of undirected edgeset on the indiced
3299 /// Gives back the map names of undirected edgeset on the indiced position.
3300 const std::vector<std::string>& uEdgeSetMaps(int index) const {
3301 return uedgesets[index].items;
3304 /// \brief Gives back how many labeled nodes section are in the file.
3306 /// Gives back how many labeled nodes section are in the file.
3307 int nodesNum() const {
3308 return nodes.size();
3311 /// \brief Gives back the name of labeled nodes section on the indiced
3314 /// Gives back the name of labeled nodes section on the indiced position.
3315 std::string nodesName(int index) const {
3316 return nodes[index].name;
3319 /// \brief Gives back the names of the labeled nodes in the indiced
3322 /// Gives back the names of the labeled nodes in the indiced section.
3323 const std::vector<std::string>& nodesItems(int index) const {
3324 return nodes[index].items;
3327 /// \brief Gives back how many labeled edges section are in the file.
3329 /// Gives back how many labeled edges section are in the file.
3330 int edgesNum() const {
3331 return edges.size();
3334 /// \brief Gives back the name of labeled edges section on the indiced
3337 /// Gives back the name of labeled edges section on the indiced position.
3338 std::string edgesName(int index) const {
3339 return edges[index].name;
3342 /// \brief Gives back the names of the labeled edges in the indiced
3345 /// Gives back the names of the labeled edges in the indiced section.
3346 const std::vector<std::string>& edgesItems(int index) const {
3347 return edges[index].items;
3350 /// \brief Gives back how many labeled undirected edges section are
3353 /// Gives back how many labeled undirected edges section are in the file.
3354 int uEdgesNum() const {
3355 return uedges.size();
3358 /// \brief Gives back the name of labeled undirected edges section
3359 /// on the indiced position.
3361 /// Gives back the name of labeled undirected edges section on the
3362 /// indiced position.
3363 std::string uEdgesName(int index) const {
3364 return uedges[index].name;
3367 /// \brief Gives back the names of the labeled undirected edges in
3368 /// the indiced section.
3370 /// Gives back the names of the labeled undirected edges in the
3371 /// indiced section.
3372 const std::vector<std::string>& uEdgesItems(int index) const {
3373 return uedges[index].items;
3377 /// \brief Gives back how many attributes section are in the file.
3379 /// Gives back how many attributes section are in the file.
3380 int attributesNum() const {
3381 return attributes.size();
3384 /// \brief Gives back the name of attributes section on the indiced
3387 /// Gives back the name of attributes section on the indiced position.
3388 std::string attributesName(int index) const {
3389 return attributes[index].name;
3392 /// \brief Gives back the names of the attributes in the indiced section.
3394 /// Gives back the names of the attributes in the indiced section.
3395 const std::vector<std::string>& attributesItems(int index) const {
3396 return attributes[index].items;
3399 const std::vector<std::string>& otherSections() const {
3405 /// \brief Gives back true when the SectionReader can process
3406 /// the section with the given header line.
3408 /// It gives back true when the section is common section.
3409 bool header(const std::string& line) {
3410 std::istringstream ls(line);
3411 std::string command, name;
3412 ls >> command >> name;
3413 if (command == "@nodeset") {
3415 nodesets.push_back(SectionInfo(name));
3416 } else if (command == "@edgeset") {
3418 edgesets.push_back(SectionInfo(name));
3419 } else if (command == "@uedgeset") {
3421 uedgesets.push_back(SectionInfo(name));
3422 } else if (command == "@nodes") {
3424 nodes.push_back(SectionInfo(name));
3425 } else if (command == "@edges") {
3427 edges.push_back(SectionInfo(name));
3428 } else if (command == "@uedges") {
3430 uedges.push_back(SectionInfo(name));
3431 } else if (command == "@attributes") {
3433 attributes.push_back(SectionInfo(name));
3435 sections.push_back(line);
3441 /// \brief Retrieve the items from various sections.
3443 /// Retrieve the items from various sections.
3444 void read(std::istream& is) {
3445 if (current == "@nodeset") {
3446 readMapNames(is, nodesets.back().items);
3447 } else if (current == "@edgeset") {
3448 readMapNames(is, edgesets.back().items);
3449 } else if (current == "@uedgeset") {
3450 readMapNames(is, uedgesets.back().items);
3451 } else if (current == "@nodes") {
3452 readItemNames(is, nodes.back().items);
3453 } else if (current == "@edges") {
3454 readItemNames(is, edges.back().items);
3455 } else if (current == "@uedges") {
3456 readItemNames(is, uedges.back().items);
3457 } else if (current == "@attributes") {
3458 readItemNames(is, attributes.back().items);
3464 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
3465 std::string line, name;
3466 std::getline(is, line);
3467 std::istringstream ls(line);
3468 while (ls >> name) {
3469 maps.push_back(name);
3471 while (getline(is, line));
3474 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
3475 std::string line, name;
3476 while (std::getline(is, line)) {
3477 std::istringstream ls(line);
3479 maps.push_back(name);
3483 struct SectionInfo {
3485 std::vector<std::string> items;
3487 SectionInfo(const std::string& _name) : name(_name) {}
3490 std::vector<SectionInfo> nodesets;
3491 std::vector<SectionInfo> edgesets;
3492 std::vector<SectionInfo> uedgesets;
3494 std::vector<SectionInfo> nodes;
3495 std::vector<SectionInfo> edges;
3496 std::vector<SectionInfo> uedges;
3498 std::vector<SectionInfo> attributes;
3500 std::vector<std::string> sections;
3502 std::string current;