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()) {
257 throw DataFormatError("Invalid label error");
262 template <typename _Item, typename _Reader>
263 class SkipReaderInverter : public MapInverterBase<_Item> {
266 typedef _Reader Reader;
267 typedef typename Reader::Value Value;
268 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
272 SkipReaderInverter(const Reader& _reader)
275 virtual ~SkipReaderInverter() {}
277 virtual void read(std::istream& is, const Item& item) {
279 reader.read(is, value);
280 typename Inverse::iterator it = inverse.find(value);
281 if (it == inverse.end()) {
282 inverse.insert(std::make_pair(value, item));
284 throw DataFormatError("Multiple label occurence error");
288 virtual Item read(std::istream& is) const {
290 reader.read(is, value);
291 typename Inverse::const_iterator it = inverse.find(value);
292 if (it != inverse.end()) {
295 throw DataFormatError("Invalid label error");
303 template <typename _Item>
304 class MapReaderBase {
308 MapReaderBase() { _touched = false; }
310 void touch() { _touched = true; }
311 bool touched() const { return _touched; }
313 virtual ~MapReaderBase() {}
315 virtual void read(std::istream& is, const Item& item) = 0;
316 virtual MapInverterBase<_Item>* getInverter() = 0;
323 template <typename _Item, typename _Map, typename _Reader>
324 class MapReader : public MapReaderBase<_Item> {
327 typedef _Reader Reader;
328 typedef typename Reader::Value Value;
331 typename _reader_bits::Ref<Map>::Type map;
334 MapReader(typename _reader_bits::Arg<Map>::Type _map,
335 const Reader& _reader)
336 : map(_map), reader(_reader) {}
338 virtual ~MapReader() {}
340 virtual void read(std::istream& is, const Item& item) {
342 reader.read(is, value);
343 map.set(item, value);
346 virtual MapInverterBase<_Item>* getInverter() {
347 return new MapReaderInverter<Item, Map, Reader>(map, reader);
352 template <typename _Item, typename _Reader>
353 class SkipReader : public MapReaderBase<_Item> {
355 typedef _Reader Reader;
356 typedef typename Reader::Value Value;
360 SkipReader(const Reader& _reader) : reader(_reader) {}
362 virtual ~SkipReader() {}
364 virtual void read(std::istream& is, const Item&) {
366 reader.read(is, value);
369 virtual MapInverterBase<Item>* getInverter() {
370 return new SkipReaderInverter<Item, Reader>(reader);
374 template <typename _Item>
375 class LabelReaderBase {
378 virtual ~LabelReaderBase() {}
379 virtual Item read(std::istream& is) const = 0;
380 virtual bool isLabelReader() const = 0;
383 template <typename _Item, typename _BoxedLabelReader>
384 class LabelReader : public LabelReaderBase<_Item> {
387 typedef _BoxedLabelReader BoxedLabelReader;
389 const BoxedLabelReader& boxedLabelReader;
391 LabelReader(const BoxedLabelReader& _boxedLabelReader)
392 : boxedLabelReader(_boxedLabelReader) {}
394 virtual Item read(std::istream& is) const {
396 boxedLabelReader.readLabel(is, item);
400 virtual bool isLabelReader() const {
401 return boxedLabelReader.isLabelReader();
405 template <typename _Item>
411 ItemStore(Item& _item) : item(&_item) {
415 void touch() { _touched = true; }
416 bool touched() const { return _touched; }
418 void read(const Item& _item) {
427 class ValueReaderBase {
429 virtual void read(std::istream&) {};
430 ValueReaderBase() { _touched = false; }
432 void touch() { _touched = true; }
433 bool touched() const { return _touched; }
435 virtual ~ValueReaderBase() {}
440 template <typename _Value, typename _Reader>
441 class ValueReader : public ValueReaderBase {
443 typedef _Value Value;
444 typedef _Reader Reader;
446 ValueReader(Value& _value, const Reader& _reader)
447 : value(_value), reader(_reader) {}
449 virtual void read(std::istream& is) {
450 reader.read(is, value);
459 /// \ingroup lemon_io
460 /// \brief Lemon Format reader class.
462 /// The Lemon Format contains several sections. We do not want to
463 /// determine what sections are in a lemon file we give only a framework
464 /// to read a section oriented format.
466 /// In the Lemon Format each section starts with a line containing a
467 /// \c \@ character on the first not white space position. This line
468 /// is the header line of the section. Each of the next lines belong
469 /// to this section until a line starting with \c \@ character is
470 /// found. This line can start a new section or it can close the
471 /// file with the \c \@end line. The file format ignores the empty
472 /// and comment lines. The line is comment line if it starts with a
475 /// The framework provides an abstract LemonReader::SectionReader class
476 /// that defines the interface of a SectionReader. The SectionReader
477 /// has the \c header() member function that gets a header line string and
478 /// decides if it wants to process the next section. Several SectionReaders
479 /// can be attached to a LemonReader and the first attached that can
480 /// process the section will be used. Its \c read() member will be called
481 /// with a stream containing the section. From this stream the empty and
482 /// comment lines are filtered out.
484 /// \relates GraphReader
485 /// \relates NodeSetReader
486 /// \relates EdgeSetReader
487 /// \relates NodesReader
488 /// \relates EdgesReader
489 /// \relates AttributeReader
493 class FilterStreamBuf : public std::streambuf {
496 typedef std::streambuf Parent;
497 typedef Parent::char_type char_type;
498 FilterStreamBuf(std::istream& is, int& num)
499 : _is(is), _base(0), _eptr(0),
500 _num(num), skip_state(after_endl) {}
504 enum skip_state_type {
510 char_type small_buf[1];
520 skip_state_type skip_state;
523 char_type* base() { return _base; }
525 char_type* eptr() { return _eptr; }
527 int_type blen() { return _eptr - _base; }
529 void setb(char_type* buf, int_type len) {
534 virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
535 if (base()) return 0;
536 if (buf != 0 && len >= int(sizeof(small_buf))) {
539 setb(small_buf, sizeof(small_buf));
545 bool put_char(char c) {
546 switch (skip_state) {
550 skip_state = after_endl;
562 skip_state = comment_line;
566 skip_state = no_skip;
576 skip_state = after_endl;
585 virtual int_type underflow() {
587 if (_is.read(&c, 1)) {
596 for (ptr = base(); ptr != eptr(); ++ptr) {
597 if (_is.read(&c, 1)) {
598 if (c == '\n') ++_num;
602 if (skip_state == after_endl && c == '@') {
612 setg(base(), base(), ptr);
616 virtual int_type sync() {
622 int line_num() const {
624 for (char_type* p = gptr(); p != egptr(); ++p) {
634 /// \brief Abstract base class for reading a section.
636 /// This class has an \c header() member function what get a
637 /// header line string and decides if it want to process the next
638 /// section. Several SectionReaders can be attached to an LemonReader
639 /// and the first attached what can process the section will be used.
640 /// Its \c read() member will called with a stream contains the section.
641 /// From this stream the empty lines and comments are filtered out.
642 class SectionReader {
643 friend class LemonReader;
645 /// \brief Constructor for SectionReader.
647 /// Constructor for SectionReader. It attach this reader to
648 /// the given LemonReader.
649 SectionReader(LemonReader& reader) {
650 reader.attach(*this);
653 virtual ~SectionReader() {}
655 /// \brief Gives back true when the SectionReader can process
656 /// the section with the given header line.
658 /// It gives back true when the SectionReader can process
659 /// the section with the given header line.
660 virtual bool header(const std::string& line) = 0;
662 /// \brief Reader function of the section.
664 /// It reads the content of the section.
665 virtual void read(std::istream& is) = 0;
667 /// \brief The given section missing in the file.
669 /// The given section missing in the file.
670 virtual void missing() {};
673 /// \brief Constructor for LemonReader.
675 /// Constructor for LemonReader which reads from the given stream.
676 LemonReader(std::istream& _is)
677 : is(&_is), own_is(false) {}
679 /// \brief Constructor for LemonReader.
681 /// Constructor for LemonReader which reads from the given file.
682 LemonReader(const std::string& filename)
683 : is(0), own_is(true) {
684 is = new std::ifstream(filename.c_str());
686 throw FileOpenError(filename);
690 /// \brief Desctructor for LemonReader.
692 /// Desctructor for LemonReader.
700 LemonReader(const LemonReader&);
701 void operator=(const LemonReader&);
703 void attach(SectionReader& reader) {
704 readers.push_back(std::make_pair(&reader, false));
708 /// \brief Executes the LemonReader.
710 /// It executes the LemonReader.
715 SectionReaders::iterator it;
716 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
717 for (it = readers.begin(); it != readers.end(); ++it) {
718 if (it->first->header(line)) {
721 FilterStreamBuf buffer(*is, line_num);
724 buffer.pubsetbuf(buf, sizeof(buf));
725 std::istream ss(&buffer);
728 } catch (DataFormatError& error) {
729 error.line(buffer.line_num());
735 for (it = readers.begin(); it != readers.end(); ++it) {
738 it->first->missing();
739 } catch (DataFormatError& error) {
740 error.line(line_num);
753 typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
754 SectionReaders readers;
758 /// \ingroup section_io
759 /// \brief SectionReader for reading a graph's nodeset.
761 /// The lemon format can store multiple graph nodesets with several
762 /// maps. The nodeset section's header line is \c \@nodeset \c
763 /// nodeset_name, but the \c nodeset_name may be empty.
765 /// The first line of the section contains the names of the maps separated
766 /// with white spaces. Each next lines describes a node in the nodeset, and
767 /// contains the mapped values for each map.
769 /// If the nodeset contains an \c "label" named map then it will be regarded
770 /// as id map. This map should contain only unique values and when the
771 /// \c readLabel() member will read a value from the given stream it will
772 /// give back that node which is mapped to this value.
774 /// \relates LemonReader
775 template <typename _Graph, typename _Traits = DefaultReaderTraits>
776 class NodeSetReader : public LemonReader::SectionReader {
777 typedef LemonReader::SectionReader Parent;
780 typedef _Graph Graph;
781 typedef _Traits Traits;
782 typedef typename Graph::Node Node;
783 typedef typename Traits::Skipper DefaultSkipper;
785 /// \brief Constructor.
787 /// Constructor for NodeSetReader. It creates the NodeSetReader and
788 /// attach it into the given LemonReader. The nodeset reader will
789 /// add the read nodes to the given Graph. The reader will read
790 /// the section when the \c section_name and the \c _name are the same.
791 NodeSetReader(LemonReader& _reader,
793 const std::string& _name = std::string(),
794 const DefaultSkipper& _skipper = DefaultSkipper())
795 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
798 /// \brief Destructor.
800 /// Destructor for NodeSetReader.
801 virtual ~NodeSetReader() {
802 for (typename MapReaders::iterator it = readers.begin();
803 it != readers.end(); ++it) {
809 NodeSetReader(const NodeSetReader&);
810 void operator=(const NodeSetReader&);
814 /// \brief Add a new node map reader command for the reader.
816 /// Add a new node map reader command for the reader.
817 template <typename Map>
818 NodeSetReader& readNodeMap(std::string label, Map& map) {
820 typename Traits::template Reader<typename Map::Value>, Map,
821 typename _reader_bits::Arg<Map>::Type>(label, map);
824 template <typename Map>
825 NodeSetReader& readNodeMap(std::string label, const Map& map) {
827 typename Traits::template Reader<typename Map::Value>, Map,
828 typename _reader_bits::Arg<Map>::Type>(label, map);
831 /// \brief Add a new node map reader command for the reader.
833 /// Add a new node map reader command for the reader.
834 template <typename ItemReader, typename Map>
835 NodeSetReader& readNodeMap(std::string label, Map& map,
836 const ItemReader& ir = ItemReader()) {
837 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
841 template <typename ItemReader, typename Map>
842 NodeSetReader& readNodeMap(std::string label, const Map& map,
843 const ItemReader& ir = ItemReader()) {
844 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
850 template <typename ItemReader, typename Map, typename MapParameter>
851 NodeSetReader& _readMap(std::string label, MapParameter map,
852 const ItemReader& ir = ItemReader()) {
853 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
854 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
855 if (readers.find(label) != readers.end()) {
857 msg << "Multiple read rule for node map: " << label;
858 throw IoParameterError(msg.message());
861 make_pair(label, new _reader_bits::
862 MapReader<Node, Map, ItemReader>(map, ir)));
868 /// \brief Add a new node map skipper command for the reader.
870 /// Add a new node map skipper command for the reader.
871 template <typename ItemReader>
872 NodeSetReader& skipNodeMap(std::string label,
873 const ItemReader& ir = ItemReader()) {
874 if (readers.find(label) != readers.end()) {
876 msg << "Multiple read rule for node map: " << label;
877 throw IoParameterError(msg.message());
879 readers.insert(make_pair(label, new _reader_bits::
880 SkipReader<Node, ItemReader>(ir)));
886 /// \brief Gives back true when the SectionReader can process
887 /// the section with the given header line.
889 /// It gives back true when the header line starts with \c \@nodeset,
890 /// and the header line's name and the nodeset's name are the same.
891 virtual bool header(const std::string& line) {
892 std::istringstream ls(line);
896 return command == "@nodeset" && name == id;
899 /// \brief Reader function of the section.
901 /// It reads the content of the section.
902 virtual void read(std::istream& is) {
903 std::vector<_reader_bits::MapReaderBase<Node>* > index;
908 std::istringstream ls(line);
911 typename MapReaders::iterator it = readers.find(id);
912 if (it != readers.end()) {
914 index.push_back(it->second);
916 index.push_back(&skipper);
919 inverter.reset(index.back()->getInverter());
920 index.back() = inverter.get();
924 for (typename MapReaders::iterator it = readers.begin();
925 it != readers.end(); ++it) {
926 if (!it->second->touched()) {
928 msg << "Map not found in file: " << it->first;
929 throw IoParameterError(msg.message());
932 while (getline(is, line)) {
933 Node node = graph.addNode();
934 std::istringstream ls(line);
935 for (int i = 0; i < int(index.size()); ++i) {
936 index[i]->read(ls, node);
941 virtual void missing() {
942 if (readers.empty()) return;
944 msg << "NodeSet section not found in file: @nodeset " << name;
945 throw IoParameterError(msg.message());
950 /// \brief Returns true if the nodeset can give back the node by its label.
952 /// Returns true if the nodeset can give back the node by its label.
953 /// It is possible only if an "label" named map was read.
954 bool isLabelReader() const {
955 return inverter.get() != 0;
958 /// \brief Gives back the node by its label.
960 /// It reads an id from the stream and gives back which node belongs to
961 /// it. It is possible only if there was read an "label" named map.
962 void readLabel(std::istream& is, Node& node) const {
963 node = inverter->read(is);
968 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
973 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
975 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
978 /// \ingroup section_io
979 /// \brief SectionReader for reading a graph's edgeset.
981 /// The lemon format can store multiple graph edgesets with several maps.
982 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
983 /// \c edgeset_name may be empty.
985 /// The first line of the section contains the names of the maps separated
986 /// with white spaces. Each next lines describes an edge in the edgeset. The
987 /// line contains the source and the target nodes' id and the mapped
988 /// values for each map.
990 /// If the edgeset contains an \c "label" named map then it will be regarded
991 /// as id map. This map should contain only unique values and when the
992 /// \c readLabel() member will read a value from the given stream it will
993 /// give back that edge which is mapped to this value.
995 /// The edgeset reader needs a node id reader to identify which nodes
996 /// have to be connected. If a NodeSetReader reads an "label" named map,
997 /// it will be able to resolve the nodes by ids.
999 /// \relates LemonReader
1000 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1001 class EdgeSetReader : public LemonReader::SectionReader {
1002 typedef LemonReader::SectionReader Parent;
1005 typedef _Graph Graph;
1006 typedef _Traits Traits;
1007 typedef typename Graph::Node Node;
1008 typedef typename Graph::Edge Edge;
1009 typedef typename Traits::Skipper DefaultSkipper;
1011 /// \brief Constructor.
1013 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
1014 /// attach it into the given LemonReader. The edgeset reader will
1015 /// add the read edges to the given Graph. It will use the given
1016 /// node id reader to read the source and target nodes of the edges.
1017 /// The reader will read the section only if the \c _name and the
1018 /// \c edgset_name are the same.
1019 template <typename NodeLabelReader>
1020 EdgeSetReader(LemonReader& _reader,
1022 const NodeLabelReader& _nodeLabelReader,
1023 const std::string& _name = std::string(),
1024 const DefaultSkipper& _skipper = DefaultSkipper())
1025 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1026 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1027 nodeLabelReader.reset(new _reader_bits::
1028 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1030 /// \brief Destructor.
1032 /// Destructor for EdgeSetReader.
1033 virtual ~EdgeSetReader() {
1034 for (typename MapReaders::iterator it = readers.begin();
1035 it != readers.end(); ++it) {
1041 EdgeSetReader(const EdgeSetReader&);
1042 void operator=(const EdgeSetReader&);
1046 /// \brief Add a new edge map reader command for the reader.
1048 /// Add a new edge map reader command for the reader.
1049 template <typename Map>
1050 EdgeSetReader& readEdgeMap(std::string label, Map& map) {
1052 typename Traits::template Reader<typename Map::Value>, Map,
1053 typename _reader_bits::Arg<Map>::Type>(label, map);
1056 template <typename Map>
1057 EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1059 typename Traits::template Reader<typename Map::Value>, Map,
1060 typename _reader_bits::Arg<Map>::Type>(label, map);
1063 /// \brief Add a new edge map reader command for the reader.
1065 /// Add a new edge map reader command for the reader.
1066 template <typename ItemReader, typename Map>
1067 EdgeSetReader& readEdgeMap(std::string label, Map& map,
1068 const ItemReader& ir = ItemReader()) {
1069 return _readMap<ItemReader, Map,
1070 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1073 template <typename ItemReader, typename Map>
1074 EdgeSetReader& readEdgeMap(std::string label, const Map& map,
1075 const ItemReader& ir = ItemReader()) {
1076 return _readMap<ItemReader, Map,
1077 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1082 template <typename ItemReader, typename Map, typename MapParameter>
1083 EdgeSetReader& _readMap(std::string label, MapParameter map,
1084 const ItemReader& ir = ItemReader()) {
1085 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1086 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1087 if (readers.find(label) != readers.end()) {
1089 msg << "Multiple read rule for edge map: " << label;
1090 throw IoParameterError(msg.message());
1093 make_pair(label, new _reader_bits::
1094 MapReader<Edge, Map, ItemReader>(map, ir)));
1100 /// \brief Add a new edge map skipper command for the reader.
1102 /// Add a new edge map skipper command for the reader.
1103 template <typename ItemReader>
1104 EdgeSetReader& skipEdgeMap(std::string label,
1105 const ItemReader& ir = ItemReader()) {
1106 if (readers.find(label) != readers.end()) {
1108 msg << "Multiple read rule for edge map: " << label;
1109 throw IoParameterError(msg.message());
1111 readers.insert(make_pair(label, new _reader_bits::
1112 SkipReader<Edge, ItemReader>(ir)));
1118 /// \brief Gives back true when the SectionReader can process
1119 /// the section with the given header line.
1121 /// It gives back true when the header line starts with \c \@edgeset,
1122 /// and the header line's name and the edgeset's name are the same.
1123 virtual bool header(const std::string& line) {
1124 std::istringstream ls(line);
1125 std::string command;
1127 ls >> command >> id;
1128 return command == "@edgeset" && name == id;
1131 /// \brief Reader function of the section.
1133 /// It reads the content of the section.
1134 virtual void read(std::istream& is) {
1135 if (!nodeLabelReader->isLabelReader()) {
1136 throw DataFormatError("Cannot find nodeset or label map");
1138 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1143 std::istringstream ls(line);
1146 typename MapReaders::iterator it = readers.find(id);
1147 if (it != readers.end()) {
1148 index.push_back(it->second);
1149 it->second->touch();
1151 index.push_back(&skipper);
1153 if (id == "label") {
1154 inverter.reset(index.back()->getInverter());
1155 index.back() = inverter.get();
1159 for (typename MapReaders::iterator it = readers.begin();
1160 it != readers.end(); ++it) {
1161 if (!it->second->touched()) {
1163 msg << "Map not found in file: " << it->first;
1164 throw IoParameterError(msg.message());
1167 while (getline(is, line)) {
1168 std::istringstream ls(line);
1169 Node from = nodeLabelReader->read(ls);
1170 Node to = nodeLabelReader->read(ls);
1171 Edge edge = graph.addEdge(from, to);
1172 for (int i = 0; i < int(index.size()); ++i) {
1173 index[i]->read(ls, edge);
1178 virtual void missing() {
1179 if (readers.empty()) return;
1181 msg << "EdgeSet section not found in file: @edgeset " << name;
1182 throw IoParameterError(msg.message());
1187 /// \brief Returns true if the edgeset can give back the edge by its label.
1189 /// Returns true if the edgeset can give back the edge by its label.
1190 /// It is possible only if an "label" named map was read.
1191 bool isLabelReader() const {
1192 return inverter.get() != 0;
1195 /// \brief Gives back the edge by its label.
1197 /// It reads an id from the stream and gives back which edge belongs to
1198 /// it. It is possible only if there was read an "label" named map.
1199 void readLabel(std::istream& is, Edge& edge) const {
1200 edge = inverter->read(is);
1205 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1212 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1214 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1215 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1218 /// \ingroup section_io
1219 /// \brief SectionReader for reading a undirected graph's edgeset.
1221 /// The lemon format can store multiple undirected edgesets with several
1222 /// maps. The undirected edgeset section's header line is \c \@uedgeset
1223 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1225 /// The first line of the section contains the names of the maps separated
1226 /// with white spaces. Each next lines describes an edge in the edgeset. The
1227 /// line contains the connected nodes' id and the mapped values for each map.
1229 /// The section can handle the directed as a syntactical sugar. Two
1230 /// undirected edge map describes one directed edge map. This two maps
1231 /// are the forward map and the backward map and the names of this map
1232 /// is near the same just with a prefix \c '+' or \c '-' character
1235 /// If the edgeset contains an \c "label" named map then it will be regarded
1236 /// as id map. This map should contain only unique values and when the
1237 /// \c readLabel() member will read a value from the given stream it will
1238 /// give back that uicted edge which is mapped to this value.
1240 /// The undirected edgeset reader needs a node id reader to identify which
1241 /// nodes have to be connected. If a NodeSetReader reads an "label" named
1242 /// map, it will be able to resolve the nodes by ids.
1244 /// \relates LemonReader
1245 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1246 class UEdgeSetReader : public LemonReader::SectionReader {
1247 typedef LemonReader::SectionReader Parent;
1250 typedef _Graph Graph;
1251 typedef _Traits Traits;
1252 typedef typename Graph::Node Node;
1253 typedef typename Graph::Edge Edge;
1254 typedef typename Graph::UEdge UEdge;
1255 typedef typename Traits::Skipper DefaultSkipper;
1257 /// \brief Constructor.
1259 /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1260 /// and attach it into the given LemonReader. The undirected edgeset
1261 /// reader will add the read undirected edges to the given Graph. It
1262 /// will use the given node id reader to read the source and target
1263 /// nodes of the edges. The reader will read the section only if the
1264 /// \c _name and the \c uedgset_name are the same.
1265 template <typename NodeLabelReader>
1266 UEdgeSetReader(LemonReader& _reader,
1268 const NodeLabelReader& _nodeLabelReader,
1269 const std::string& _name = std::string(),
1270 const DefaultSkipper& _skipper = DefaultSkipper())
1271 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1272 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1273 nodeLabelReader.reset(new _reader_bits::
1274 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1276 /// \brief Destructor.
1278 /// Destructor for UEdgeSetReader.
1279 virtual ~UEdgeSetReader() {
1280 for (typename MapReaders::iterator it = readers.begin();
1281 it != readers.end(); ++it) {
1287 UEdgeSetReader(const UEdgeSetReader&);
1288 void operator=(const UEdgeSetReader&);
1292 /// \brief Add a new undirected edge map reader command for the reader.
1294 /// Add a new edge undirected map reader command for the reader.
1295 template <typename Map>
1296 UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
1298 typename Traits::template Reader<typename Map::Value>, Map,
1299 typename _reader_bits::Arg<Map>::Type>(label, map);
1302 template <typename Map>
1303 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
1305 typename Traits::template Reader<typename Map::Value>, Map,
1306 typename _reader_bits::Arg<Map>::Type>(label, map);
1309 /// \brief Add a new undirected edge map reader command for the reader.
1311 /// Add a new edge undirected map reader command for the reader.
1312 template <typename ItemReader, typename Map>
1313 UEdgeSetReader& readUEdgeMap(std::string label, Map& map,
1314 const ItemReader& ir = ItemReader()) {
1315 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1319 template <typename ItemReader, typename Map>
1320 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map,
1321 const ItemReader& ir = ItemReader()) {
1322 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
1328 template <typename ItemReader, typename Map, typename MapParameter>
1329 UEdgeSetReader& _readMap(std::string label, MapParameter map,
1330 const ItemReader& ir = ItemReader()) {
1331 checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1332 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1333 if (readers.find(label) != readers.end()) {
1335 msg << "Multiple read rule for edge map: " << label;
1336 throw IoParameterError(msg.message());
1339 make_pair(label, new _reader_bits::
1340 MapReader<UEdge, Map, ItemReader>(map, ir)));
1346 /// \brief Add a new undirected edge map skipper command for the reader.
1348 /// Add a new undirected edge map skipper command for the reader.
1349 template <typename ItemReader>
1350 UEdgeSetReader& skipUEdgeMap(std::string label,
1351 const ItemReader& ir = ItemReader()) {
1352 if (readers.find(label) != readers.end()) {
1354 msg << "Multiple read rule for node map: " << label;
1355 throw IoParameterError(msg.message());
1357 readers.insert(make_pair(label, new _reader_bits::
1358 SkipReader<UEdge, ItemReader>(ir)));
1362 /// \brief Add a new directed edge map reader command for the reader.
1364 /// Add a new directed edge map reader command for the reader.
1365 template <typename Map>
1366 UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
1368 typename Traits::template Reader<typename Map::Value>, Map,
1369 typename _reader_bits::Arg<Map>::Type>(label, map);
1372 template <typename Map>
1373 UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1375 typename Traits::template Reader<typename Map::Value>, Map,
1376 typename _reader_bits::Arg<Map>::Type>(label, map);
1379 /// \brief Add a new directed edge map reader command for the reader.
1381 /// Add a new directed edge map reader command for the reader.
1382 template <typename ItemReader, typename Map>
1383 UEdgeSetReader& readEdgeMap(std::string label, Map& map,
1384 const ItemReader& ir = ItemReader()) {
1385 return _readDirMap<ItemReader, Map,
1386 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1389 template <typename ItemReader, typename Map>
1390 UEdgeSetReader& readEdgeMap(std::string label, const Map& map,
1391 const ItemReader& ir = ItemReader()) {
1392 return _readDirMap<ItemReader, Map,
1393 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1398 template <typename ItemReader, typename Map, typename MapParameter>
1399 UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
1400 const ItemReader& ir = ItemReader()) {
1401 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1402 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1403 readUEdgeMap("+" + label,
1404 _reader_bits::forwardComposeMap(graph, map), ir);
1405 readUEdgeMap("-" + label,
1406 _reader_bits::backwardComposeMap(graph, map), ir);
1412 /// \brief Add a new directed edge map skipper command for the reader.
1414 /// Add a new directed edge map skipper command for the reader.
1415 template <typename ItemReader>
1416 UEdgeSetReader& skipEdgeMap(std::string label,
1417 const ItemReader& ir = ItemReader()) {
1418 skipUEdgeMap("+" + label, ir);
1419 skipUEdgeMap("-" + label, ir);
1425 /// \brief Gives back true when the SectionReader can process
1426 /// the section with the given header line.
1428 /// It gives back true when the header line starts with \c \@uedgeset,
1429 /// and the header line's name and the edgeset's name are the same.
1430 virtual bool header(const std::string& line) {
1431 std::istringstream ls(line);
1432 std::string command;
1434 ls >> command >> id;
1435 return command == "@uedgeset" && name == id;
1438 /// \brief Reader function of the section.
1440 /// It reads the content of the section.
1441 virtual void read(std::istream& is) {
1442 if (!nodeLabelReader->isLabelReader()) {
1443 throw DataFormatError("Cannot find nodeset or label map");
1445 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1450 std::istringstream ls(line);
1453 typename MapReaders::iterator it = readers.find(id);
1454 if (it != readers.end()) {
1455 index.push_back(it->second);
1456 it->second->touch();
1458 index.push_back(&skipper);
1460 if (id == "label") {
1461 inverter.reset(index.back()->getInverter());
1462 index.back() = inverter.get();
1465 for (typename MapReaders::iterator it = readers.begin();
1466 it != readers.end(); ++it) {
1467 if (!it->second->touched()) {
1469 msg << "Map not found in file: " << it->first;
1470 throw IoParameterError(msg.message());
1474 while (getline(is, line)) {
1475 std::istringstream ls(line);
1476 Node from = nodeLabelReader->read(ls);
1477 Node to = nodeLabelReader->read(ls);
1478 UEdge edge = graph.addEdge(from, to);
1479 for (int i = 0; i < int(index.size()); ++i) {
1480 index[i]->read(ls, edge);
1485 virtual void missing() {
1486 if (readers.empty()) return;
1488 msg << "UEdgeSet section not found in file: @uedgeset " << name;
1489 throw IoParameterError(msg.message());
1494 /// \brief Returns true if the edgeset can give back the edge by its label.
1496 /// Returns true if the edgeset can give back the undirected edge by its
1497 /// id. It is possible only if an "label" named map was read.
1498 bool isLabelReader() const {
1499 return inverter.get() != 0;
1502 /// \brief Gives back the undirected edge by its label.
1504 /// It reads an id from the stream and gives back which undirected edge
1505 /// belongs to it. It is possible only if there was read an "label" named map.
1506 void readLabel(std::istream& is, UEdge& uEdge) const {
1507 uEdge = inverter->read(is);
1510 /// \brief Gives back the directed edge by its label.
1512 /// It reads an id from the stream and gives back which directed edge
1513 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1514 /// and the undirected edge id. It is possible only if there was read
1515 /// an "label" named map.
1516 void readLabel(std::istream& is, Edge& edge) const {
1519 UEdge uEdge = inverter->read(is);
1521 edge = graph.direct(uEdge, true);
1522 } else if (c == '-') {
1523 edge = graph.direct(uEdge, false);
1525 throw DataFormatError("Wrong id format for edge "
1526 "in undirected edgeset");
1532 typedef std::map<std::string,
1533 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1538 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1540 std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1541 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1544 /// \ingroup section_io
1545 /// \brief SectionReader for reading labeled nodes.
1547 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1548 /// \c nodes_name may be empty.
1550 /// Each line in the section contains the name of the node
1551 /// and then the node id.
1553 /// \relates LemonReader
1554 template <typename _Graph>
1555 class NodeReader : public LemonReader::SectionReader {
1556 typedef LemonReader::SectionReader Parent;
1557 typedef _Graph Graph;
1558 typedef typename Graph::Node Node;
1561 /// \brief Constructor.
1563 /// Constructor for NodeReader. It creates the NodeReader and
1564 /// attach it into the given LemonReader. It will use the given
1565 /// node id reader to give back the nodes. The reader will read the
1566 /// section only if the \c _name and the \c nodes_name are the same.
1567 template <typename _LabelReader>
1568 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1569 const std::string& _name = std::string())
1570 : Parent(_reader), name(_name) {
1571 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1572 nodeLabelReader.reset(new _reader_bits::
1573 LabelReader<Node, _LabelReader>(_labelReader));
1576 /// \brief Destructor.
1578 /// Destructor for NodeReader.
1579 virtual ~NodeReader() {}
1582 NodeReader(const NodeReader&);
1583 void operator=(const NodeReader&);
1587 /// \brief Add a node reader command for the NodeReader.
1589 /// Add a node reader command for the NodeReader.
1590 void readNode(std::string label, Node& item) {
1591 if (readers.find(label) != readers.end()) {
1593 msg << "Multiple read rule for node: " << label;
1594 throw IoParameterError(msg.message());
1596 readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
1601 /// \brief Gives back true when the SectionReader can process
1602 /// the section with the given header line.
1604 /// It gives back true when the header line start with \c \@nodes,
1605 /// and the header line's name and the reader's name are the same.
1606 virtual bool header(const std::string& line) {
1607 std::istringstream ls(line);
1608 std::string command;
1610 ls >> command >> id;
1611 return command == "@nodes" && name == id;
1614 /// \brief Reader function of the section.
1616 /// It reads the content of the section.
1617 virtual void read(std::istream& is) {
1618 if (!nodeLabelReader->isLabelReader()) {
1619 throw DataFormatError("Cannot find nodeset or label map");
1622 while (getline(is, line)) {
1623 std::istringstream ls(line);
1626 typename NodeReaders::iterator it = readers.find(id);
1627 if (it != readers.end()) {
1628 it->second.read(nodeLabelReader->read(ls));
1632 for (typename NodeReaders::iterator it = readers.begin();
1633 it != readers.end(); ++it) {
1634 if (!it->second.touched()) {
1636 msg << "Node not found in file: " << it->first;
1637 throw IoParameterError(msg.message());
1642 virtual void missing() {
1643 if (readers.empty()) return;
1645 msg << "Nodes section not found in file: @nodes " << name;
1646 throw IoParameterError(msg.message());
1653 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1654 NodeReaders readers;
1655 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1658 /// \ingroup section_io
1659 /// \brief SectionReader for reading labeled edges.
1661 /// The edges section's header line is \c \@edges \c edges_name, but the
1662 /// \c edges_name may be empty.
1664 /// Each line in the section contains the name of the edge
1665 /// and then the edge id.
1667 /// \relates LemonReader
1668 template <typename _Graph>
1669 class EdgeReader : public LemonReader::SectionReader {
1670 typedef LemonReader::SectionReader Parent;
1671 typedef _Graph Graph;
1672 typedef typename Graph::Edge Edge;
1675 /// \brief Constructor.
1677 /// Constructor for EdgeReader. It creates the EdgeReader and
1678 /// attach it into the given LemonReader. It will use the given
1679 /// edge id reader to give back the edges. The reader will read the
1680 /// section only if the \c _name and the \c edges_name are the same.
1681 template <typename _LabelReader>
1682 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1683 const std::string& _name = std::string())
1684 : Parent(_reader), name(_name) {
1685 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1686 edgeLabelReader.reset(new _reader_bits::
1687 LabelReader<Edge, _LabelReader>(_labelReader));
1690 /// \brief Destructor.
1692 /// Destructor for EdgeReader.
1693 virtual ~EdgeReader() {}
1695 EdgeReader(const EdgeReader&);
1696 void operator=(const EdgeReader&);
1700 /// \brief Add an edge reader command for the EdgeReader.
1702 /// Add an edge reader command for the EdgeReader.
1703 void readEdge(std::string label, Edge& item) {
1704 if (readers.find(label) != readers.end()) {
1706 msg << "Multiple read rule for edge: " << label;
1707 throw IoParameterError(msg.message());
1709 readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1714 /// \brief Gives back true when the SectionReader can process
1715 /// the section with the given header line.
1717 /// It gives back true when the header line start with \c \@edges,
1718 /// and the header line's name and the reader's name are the same.
1719 virtual bool header(const std::string& line) {
1720 std::istringstream ls(line);
1721 std::string command;
1723 ls >> command >> id;
1724 return command == "@edges" && name == id;
1727 /// \brief Reader function of the section.
1729 /// It reads the content of the section.
1730 virtual void read(std::istream& is) {
1731 if (!edgeLabelReader->isLabelReader()) {
1732 throw DataFormatError("Cannot find edgeset or label map");
1735 while (getline(is, line)) {
1736 std::istringstream ls(line);
1739 typename EdgeReaders::iterator it = readers.find(id);
1740 if (it != readers.end()) {
1741 it->second.read(edgeLabelReader->read(ls));
1745 for (typename EdgeReaders::iterator it = readers.begin();
1746 it != readers.end(); ++it) {
1747 if (!it->second.touched()) {
1749 msg << "Edge not found in file: " << it->first;
1750 throw IoParameterError(msg.message());
1755 virtual void missing() {
1756 if (readers.empty()) return;
1758 msg << "Edges section not found in file: @edges " << name;
1759 throw IoParameterError(msg.message());
1766 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1767 EdgeReaders readers;
1768 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1771 /// \ingroup section_io
1772 /// \brief SectionReader for reading labeled undirected edges.
1774 /// The undirected edges section's header line is \c \@uedges
1775 /// \c uedges_name, but the \c uedges_name may be empty.
1777 /// Each line in the section contains the name of the undirected edge
1778 /// and then the undirected edge id.
1780 /// \relates LemonReader
1781 template <typename _Graph>
1782 class UEdgeReader : public LemonReader::SectionReader {
1783 typedef LemonReader::SectionReader Parent;
1784 typedef _Graph Graph;
1785 typedef typename Graph::Edge Edge;
1786 typedef typename Graph::UEdge UEdge;
1789 /// \brief Constructor.
1791 /// Constructor for UEdgeReader. It creates the UEdgeReader and
1792 /// attach it into the given LemonReader. It will use the given
1793 /// undirected edge id reader to give back the edges. The reader will
1794 /// read the section only if the \c _name and the \c uedges_name are
1796 template <typename _LabelReader>
1797 UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1798 const std::string& _name = std::string())
1799 : Parent(_reader), name(_name) {
1800 checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1801 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1802 uEdgeLabelReader.reset(new _reader_bits::
1803 LabelReader<UEdge, _LabelReader>(_labelReader));
1804 edgeLabelReader.reset(new _reader_bits::
1805 LabelReader<Edge, _LabelReader>(_labelReader));
1808 /// \brief Destructor.
1810 /// Destructor for UEdgeReader.
1811 virtual ~UEdgeReader() {}
1813 UEdgeReader(const UEdgeReader&);
1814 void operator=(const UEdgeReader&);
1818 /// \brief Add an undirected edge reader command for the UEdgeReader.
1820 /// Add an undirected edge reader command for the UEdgeReader.
1821 void readUEdge(std::string label, UEdge& item) {
1822 if (uEdgeReaders.find(label) != uEdgeReaders.end()) {
1824 msg << "Multiple read rule for undirected edge: " << label;
1825 throw IoParameterError(msg.message());
1827 uEdgeReaders.insert(make_pair(label, _reader_bits::
1828 ItemStore<UEdge>(item)));
1831 /// \brief Add an edge reader command for the UEdgeReader.
1833 /// Add an edge reader command for the UEdgeReader.
1834 void readEdge(std::string label, Edge& item) {
1835 if (edgeReaders.find(label) != edgeReaders.end()) {
1837 msg << "Multiple read rule for edge: " << label;
1838 throw IoParameterError(msg.message());
1840 edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1845 /// \brief Gives back true when the SectionReader can process
1846 /// the section with the given header line.
1848 /// It gives back true when the header line start with \c \@edges,
1849 /// and the header line's name and the reader's name are the same.
1850 virtual bool header(const std::string& line) {
1851 std::istringstream ls(line);
1852 std::string command;
1854 ls >> command >> id;
1855 return command == "@uedges" && name == id;
1858 /// \brief Reader function of the section.
1860 /// It reads the content of the section.
1861 virtual void read(std::istream& is) {
1862 if (!edgeLabelReader->isLabelReader()) {
1863 throw DataFormatError("Cannot find undirected edgeset or label map");
1865 if (!uEdgeLabelReader->isLabelReader()) {
1866 throw DataFormatError("Cannot find undirected edgeset or label map");
1869 while (getline(is, line)) {
1870 std::istringstream ls(line);
1874 typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1875 if (it != uEdgeReaders.end()) {
1876 it->second.read(uEdgeLabelReader->read(ls));
1881 typename EdgeReaders::iterator it = edgeReaders.find(id);
1882 if (it != edgeReaders.end()) {
1883 it->second.read(edgeLabelReader->read(ls));
1889 for (typename EdgeReaders::iterator it = edgeReaders.begin();
1890 it != edgeReaders.end(); ++it) {
1891 if (!it->second.touched()) {
1893 msg << "Edge not found in file: " << it->first;
1894 throw IoParameterError(msg.message());
1897 for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1898 it != uEdgeReaders.end(); ++it) {
1899 if (!it->second.touched()) {
1901 msg << "UEdge not found in file: " << it->first;
1902 throw IoParameterError(msg.message());
1907 virtual void missing() {
1908 if (edgeReaders.empty() && uEdgeReaders.empty()) return;
1910 msg << "UEdges section not found in file: @uedges " << name;
1911 throw IoParameterError(msg.message());
1918 typedef std::map<std::string,
1919 _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1920 UEdgeReaders uEdgeReaders;
1921 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
1923 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1924 EdgeReaders edgeReaders;
1925 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1928 /// \ingroup section_io
1929 /// \brief SectionReader for attributes.
1931 /// The lemon format can store multiple attribute set. Each set has
1932 /// the header line \c \@attributes \c attributeset_name, but the
1933 /// attributeset_name may be empty.
1935 /// The attributeset section contains several lines. Each of them starts
1936 /// with an attribute and then a the value for the id.
1938 /// \relates LemonReader
1939 template <typename _Traits = DefaultReaderTraits>
1940 class AttributeReader : public LemonReader::SectionReader {
1941 typedef LemonReader::SectionReader Parent;
1942 typedef _Traits Traits;
1944 /// \brief Constructor.
1946 /// Constructor for AttributeReader. It creates the AttributeReader and
1947 /// attach it into the given LemonReader. The reader process a section
1948 /// only if the \c section_name and the \c _name are the same.
1949 AttributeReader(LemonReader& _reader,
1950 const std::string& _name = std::string())
1951 : Parent(_reader), name(_name) {}
1953 /// \brief Destructor.
1955 /// Destructor for AttributeReader.
1956 virtual ~AttributeReader() {
1957 for (typename Readers::iterator it = readers.begin();
1958 it != readers.end(); ++it) {
1964 AttributeReader(const AttributeReader&);
1965 void operator=(AttributeReader&);
1968 /// \brief Add an attribute reader command for the reader.
1970 /// Add an attribute reader command for the reader.
1971 template <typename Value>
1972 AttributeReader& readAttribute(const std::string& label, Value& value) {
1973 return readAttribute<typename Traits::template Reader<Value> >
1977 /// \brief Add an attribute reader command for the reader.
1979 /// Add an attribute reader command for the reader.
1980 template <typename ItemReader, typename Value>
1981 AttributeReader& readAttribute(const std::string& label, Value& value,
1982 const ItemReader& ir = ItemReader()) {
1983 checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
1984 if (readers.find(label) != readers.end()) {
1986 msg << "Multiple read rule for attribute: " << label;
1987 throw IoParameterError(msg.message());
1989 readers.insert(make_pair(label, new _reader_bits::
1990 ValueReader<Value, ItemReader>(value, ir)));
1996 /// \brief Gives back true when the SectionReader can process
1997 /// the section with the given header line.
1999 /// It gives back true when the header line start with \c \@attributes,
2000 /// and the header line's id and the attributeset's id are the same.
2001 bool header(const std::string& line) {
2002 std::istringstream ls(line);
2003 std::string command;
2005 ls >> command >> id;
2006 return command == "@attributes" && name == id;
2009 /// \brief Reader function of the section.
2011 /// It reads the content of the section.
2012 void read(std::istream& is) {
2014 while (getline(is, line)) {
2015 std::istringstream ls(line);
2018 typename Readers::iterator it = readers.find(id);
2019 if (it != readers.end()) {
2020 it->second->read(ls);
2021 it->second->touch();
2024 for (typename Readers::iterator it = readers.begin();
2025 it != readers.end(); ++it) {
2026 if (!it->second->touched()) {
2028 msg << "Attribute not found in file: " << it->first;
2029 throw IoParameterError(msg.message());
2034 virtual void missing() {
2035 if (readers.empty()) return;
2037 msg << "Attribute section not found in file: @attributes " << name;
2038 throw IoParameterError(msg.message());
2044 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2048 /// \ingroup section_io
2049 /// \brief SectionReader for retrieve what is in the file.
2051 /// SectionReader for retrieve what is in the file. If you want
2052 /// to know which sections, maps and items are in the file
2053 /// use the next code:
2055 /// LemonReader reader("input.lgf");
2056 /// ContentReader content(reader);
2059 class ContentReader : public LemonReader::SectionReader {
2060 typedef LemonReader::SectionReader Parent;
2062 /// \brief Constructor.
2065 ContentReader(LemonReader& _reader) : Parent(_reader) {}
2067 /// \brief Desctructor.
2070 virtual ~ContentReader() {}
2072 /// \brief Gives back how many nodesets are in the file.
2074 /// Gives back how many nodesets are in the file.
2075 int nodeSetNum() const {
2076 return nodesets.size();
2079 /// \brief Gives back the name of nodeset on the indiced position.
2081 /// Gives back the name of nodeset on the indiced position.
2082 std::string nodeSetName(int index) const {
2083 return nodesets[index].name;
2086 /// \brief Gives back the map names of nodeset on the indiced position.
2088 /// Gives back the map names of nodeset on the indiced position.
2089 const std::vector<std::string>& nodeSetMaps(int index) const {
2090 return nodesets[index].items;
2093 /// \brief Gives back how many edgesets are in the file.
2095 /// Gives back how many edgesets are in the file.
2096 int edgeSetNum() const {
2097 return edgesets.size();
2100 /// \brief Gives back the name of edgeset on the indiced position.
2102 /// Gives back the name of edgeset on the indiced position.
2103 std::string edgeSetName(int index) const {
2104 return edgesets[index].name;
2107 /// \brief Gives back the map names of edgeset on the indiced position.
2109 /// Gives back the map names of edgeset on the indiced position.
2110 const std::vector<std::string>& edgeSetMaps(int index) const {
2111 return edgesets[index].items;
2114 /// \brief Gives back how many undirected edgesets are in the file.
2116 /// Gives back how many undirected edgesets are in the file.
2117 int uEdgeSetNum() const {
2118 return uedgesets.size();
2121 /// \brief Gives back the name of undirected edgeset on the indiced
2124 /// Gives back the name of undirected edgeset on the indiced position.
2125 std::string uEdgeSetName(int index) const {
2126 return uedgesets[index].name;
2129 /// \brief Gives back the map names of undirected edgeset on the indiced
2132 /// Gives back the map names of undirected edgeset on the indiced position.
2133 const std::vector<std::string>& uEdgeSetMaps(int index) const {
2134 return uedgesets[index].items;
2137 /// \brief Gives back how many labeled nodes section are in the file.
2139 /// Gives back how many labeled nodes section are in the file.
2140 int nodesNum() const {
2141 return nodes.size();
2144 /// \brief Gives back the name of labeled nodes section on the indiced
2147 /// Gives back the name of labeled nodes section on the indiced position.
2148 std::string nodesName(int index) const {
2149 return nodes[index].name;
2152 /// \brief Gives back the names of the labeled nodes in the indiced
2155 /// Gives back the names of the labeled nodes in the indiced section.
2156 const std::vector<std::string>& nodesItems(int index) const {
2157 return nodes[index].items;
2160 /// \brief Gives back how many labeled edges section are in the file.
2162 /// Gives back how many labeled edges section are in the file.
2163 int edgesNum() const {
2164 return edges.size();
2167 /// \brief Gives back the name of labeled edges section on the indiced
2170 /// Gives back the name of labeled edges section on the indiced position.
2171 std::string edgesName(int index) const {
2172 return edges[index].name;
2175 /// \brief Gives back the names of the labeled edges in the indiced
2178 /// Gives back the names of the labeled edges in the indiced section.
2179 const std::vector<std::string>& edgesItems(int index) const {
2180 return edges[index].items;
2183 /// \brief Gives back how many labeled undirected edges section are
2186 /// Gives back how many labeled undirected edges section are in the file.
2187 int uEdgesNum() const {
2188 return uedges.size();
2191 /// \brief Gives back the name of labeled undirected edges section
2192 /// on the indiced position.
2194 /// Gives back the name of labeled undirected edges section on the
2195 /// indiced position.
2196 std::string uEdgesName(int index) const {
2197 return uedges[index].name;
2200 /// \brief Gives back the names of the labeled undirected edges in
2201 /// the indiced section.
2203 /// Gives back the names of the labeled undirected edges in the
2204 /// indiced section.
2205 const std::vector<std::string>& uEdgesItems(int index) const {
2206 return uedges[index].items;
2210 /// \brief Gives back how many attributes section are in the file.
2212 /// Gives back how many attributes section are in the file.
2213 int attributesNum() const {
2214 return attributes.size();
2217 /// \brief Gives back the name of attributes section on the indiced
2220 /// Gives back the name of attributes section on the indiced position.
2221 std::string attributesName(int index) const {
2222 return attributes[index].name;
2225 /// \brief Gives back the names of the attributes in the indiced section.
2227 /// Gives back the names of the attributes in the indiced section.
2228 const std::vector<std::string>& attributesItems(int index) const {
2229 return attributes[index].items;
2232 const std::vector<std::string>& otherSections() const {
2238 /// \brief Gives back true when the SectionReader can process
2239 /// the section with the given header line.
2241 /// It gives back true when the section is common section.
2242 bool header(const std::string& line) {
2243 std::istringstream ls(line);
2244 std::string command, name;
2245 ls >> command >> name;
2246 if (command == "@nodeset") {
2248 nodesets.push_back(SectionInfo(name));
2249 } else if (command == "@edgeset") {
2251 edgesets.push_back(SectionInfo(name));
2252 } else if (command == "@uedgeset") {
2254 uedgesets.push_back(SectionInfo(name));
2255 } else if (command == "@nodes") {
2257 nodes.push_back(SectionInfo(name));
2258 } else if (command == "@edges") {
2260 edges.push_back(SectionInfo(name));
2261 } else if (command == "@uedges") {
2263 uedges.push_back(SectionInfo(name));
2264 } else if (command == "@attributes") {
2266 attributes.push_back(SectionInfo(name));
2268 sections.push_back(line);
2274 /// \brief Retrieve the items from various sections.
2276 /// Retrieve the items from various sections.
2277 void read(std::istream& is) {
2278 if (current == "@nodeset") {
2279 readMapNames(is, nodesets.back().items);
2280 } else if (current == "@edgeset") {
2281 readMapNames(is, edgesets.back().items);
2282 } else if (current == "@uedgeset") {
2283 readMapNames(is, uedgesets.back().items);
2284 } else if (current == "@nodes") {
2285 readItemNames(is, nodes.back().items);
2286 } else if (current == "@edges") {
2287 readItemNames(is, edges.back().items);
2288 } else if (current == "@uedges") {
2289 readItemNames(is, uedges.back().items);
2290 } else if (current == "@attributes") {
2291 readItemNames(is, attributes.back().items);
2297 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2298 std::string line, name;
2299 std::getline(is, line);
2300 std::istringstream ls(line);
2301 while (ls >> name) {
2302 maps.push_back(name);
2304 while (getline(is, line));
2307 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2308 std::string line, name;
2309 while (std::getline(is, line)) {
2310 std::istringstream ls(line);
2312 maps.push_back(name);
2316 struct SectionInfo {
2318 std::vector<std::string> items;
2320 SectionInfo(const std::string& _name) : name(_name) {}
2323 std::vector<SectionInfo> nodesets;
2324 std::vector<SectionInfo> edgesets;
2325 std::vector<SectionInfo> uedgesets;
2327 std::vector<SectionInfo> nodes;
2328 std::vector<SectionInfo> edges;
2329 std::vector<SectionInfo> uedges;
2331 std::vector<SectionInfo> attributes;
2333 std::vector<std::string> sections;
2335 std::string current;