Slight modifications.
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() {
623 /// \brief Abstract base class for reading a section.
625 /// This class has an \c header() member function what get a
626 /// header line string and decides if it want to process the next
627 /// section. Several SectionReaders can be attached to an LemonReader
628 /// and the first attached what can process the section will be used.
629 /// Its \c read() member will called with a stream contains the section.
630 /// From this stream the empty lines and comments are filtered out.
631 class SectionReader {
632 friend class LemonReader;
634 /// \brief Constructor for SectionReader.
636 /// Constructor for SectionReader. It attach this reader to
637 /// the given LemonReader.
638 SectionReader(LemonReader& reader) {
639 reader.attach(*this);
642 virtual ~SectionReader() {}
644 /// \brief Gives back true when the SectionReader can process
645 /// the section with the given header line.
647 /// It gives back true when the SectionReader can process
648 /// the section with the given header line.
649 virtual bool header(const std::string& line) = 0;
651 /// \brief Reader function of the section.
653 /// It reads the content of the section.
654 virtual void read(std::istream& is) = 0;
656 /// \brief The given section missing in the file.
658 /// The given section missing in the file.
659 virtual void missing() {};
662 /// \brief Constructor for LemonReader.
664 /// Constructor for LemonReader which reads from the given stream.
665 LemonReader(std::istream& _is)
666 : is(&_is), own_is(false) {}
668 /// \brief Constructor for LemonReader.
670 /// Constructor for LemonReader which reads from the given file.
671 LemonReader(const std::string& filename)
672 : is(0), own_is(true) {
673 is = new std::ifstream(filename.c_str());
675 throw FileOpenError(filename);
679 /// \brief Desctructor for LemonReader.
681 /// Desctructor for LemonReader.
689 LemonReader(const LemonReader&);
690 void operator=(const LemonReader&);
692 void attach(SectionReader& reader) {
693 readers.push_back(std::make_pair(&reader, false));
697 /// \brief Executes the LemonReader.
699 /// It executes the LemonReader.
704 SectionReaders::iterator it;
705 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
706 for (it = readers.begin(); it != readers.end(); ++it) {
707 if (it->first->header(line)) {
710 FilterStreamBuf buffer(*is, line_num);
711 buffer.pubsetbuf(buf, sizeof(buf));
712 std::istream ss(&buffer);
718 for (it = readers.begin(); it != readers.end(); ++it) {
720 it->first->missing();
723 } catch (DataFormatError& error) {
724 error.line(line_num);
735 typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
736 SectionReaders readers;
740 /// \ingroup section_io
741 /// \brief SectionReader for reading a graph's nodeset.
743 /// The lemon format can store multiple graph nodesets with several
744 /// maps. The nodeset section's header line is \c \@nodeset \c
745 /// nodeset_name, but the \c nodeset_name may be empty.
747 /// The first line of the section contains the names of the maps separated
748 /// with white spaces. Each next lines describes a node in the nodeset, and
749 /// contains the mapped values for each map.
751 /// If the nodeset contains an \c "label" named map then it will be regarded
752 /// as id map. This map should contain only unique values and when the
753 /// \c readLabel() member will read a value from the given stream it will
754 /// give back that node which is mapped to this value.
756 /// \relates LemonReader
757 template <typename _Graph, typename _Traits = DefaultReaderTraits>
758 class NodeSetReader : public LemonReader::SectionReader {
759 typedef LemonReader::SectionReader Parent;
762 typedef _Graph Graph;
763 typedef _Traits Traits;
764 typedef typename Graph::Node Node;
765 typedef typename Traits::Skipper DefaultSkipper;
767 /// \brief Constructor.
769 /// Constructor for NodeSetReader. It creates the NodeSetReader and
770 /// attach it into the given LemonReader. The nodeset reader will
771 /// add the read nodes to the given Graph. The reader will read
772 /// the section when the \c section_name and the \c _name are the same.
773 NodeSetReader(LemonReader& _reader,
775 const std::string& _name = std::string(),
776 const DefaultSkipper& _skipper = DefaultSkipper())
777 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
780 /// \brief Destructor.
782 /// Destructor for NodeSetReader.
783 virtual ~NodeSetReader() {
784 for (typename MapReaders::iterator it = readers.begin();
785 it != readers.end(); ++it) {
791 NodeSetReader(const NodeSetReader&);
792 void operator=(const NodeSetReader&);
796 /// \brief Add a new node map reader command for the reader.
798 /// Add a new node map reader command for the reader.
799 template <typename Map>
800 NodeSetReader& readNodeMap(std::string label, Map& map) {
802 typename Traits::template Reader<typename Map::Value>, Map,
803 typename _reader_bits::Arg<Map>::Type>(label, map);
806 template <typename Map>
807 NodeSetReader& readNodeMap(std::string label, const Map& map) {
809 typename Traits::template Reader<typename Map::Value>, Map,
810 typename _reader_bits::Arg<Map>::Type>(label, map);
813 /// \brief Add a new node map reader command for the reader.
815 /// Add a new node map reader command for the reader.
816 template <typename ItemReader, typename Map>
817 NodeSetReader& readNodeMap(std::string label, Map& map,
818 const ItemReader& ir = ItemReader()) {
819 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
823 template <typename ItemReader, typename Map>
824 NodeSetReader& readNodeMap(std::string label, const Map& map,
825 const ItemReader& ir = ItemReader()) {
826 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
832 template <typename ItemReader, typename Map, typename MapParameter>
833 NodeSetReader& _readMap(std::string label, MapParameter map,
834 const ItemReader& ir = ItemReader()) {
835 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
836 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
837 if (readers.find(label) != readers.end()) {
839 msg << "Multiple read rule for node map: " << label;
840 throw IoParameterError(msg.message());
843 make_pair(label, new _reader_bits::
844 MapReader<Node, Map, ItemReader>(map, ir)));
850 /// \brief Add a new node map skipper command for the reader.
852 /// Add a new node map skipper command for the reader.
853 template <typename ItemReader>
854 NodeSetReader& skipNodeMap(std::string label,
855 const ItemReader& ir = ItemReader()) {
856 if (readers.find(label) != readers.end()) {
858 msg << "Multiple read rule for node map: " << label;
859 throw IoParameterError(msg.message());
861 readers.insert(make_pair(label, new _reader_bits::
862 SkipReader<Node, ItemReader>(ir)));
868 /// \brief Gives back true when the SectionReader can process
869 /// the section with the given header line.
871 /// It gives back true when the header line starts with \c \@nodeset,
872 /// and the header line's name and the nodeset's name are the same.
873 virtual bool header(const std::string& line) {
874 std::istringstream ls(line);
878 return command == "@nodeset" && name == id;
881 /// \brief Reader function of the section.
883 /// It reads the content of the section.
884 virtual void read(std::istream& is) {
885 std::vector<_reader_bits::MapReaderBase<Node>* > index;
890 std::istringstream ls(line);
893 typename MapReaders::iterator it = readers.find(id);
894 if (it != readers.end()) {
896 index.push_back(it->second);
898 index.push_back(&skipper);
901 inverter.reset(index.back()->getInverter());
902 index.back() = inverter.get();
906 for (typename MapReaders::iterator it = readers.begin();
907 it != readers.end(); ++it) {
908 if (!it->second->touched()) {
910 msg << "Map not found in file: " << it->first;
911 throw IoParameterError(msg.message());
914 while (getline(is, line)) {
915 Node node = graph.addNode();
916 std::istringstream ls(line);
917 for (int i = 0; i < int(index.size()); ++i) {
918 index[i]->read(ls, node);
923 virtual void missing() {
924 if (readers.empty()) return;
926 msg << "NodeSet section not found in file: @nodeset " << name;
927 throw IoParameterError(msg.message());
932 /// \brief Returns true if the nodeset can give back the node by its label.
934 /// Returns true if the nodeset can give back the node by its label.
935 /// It is possible only if an "label" named map was read.
936 bool isLabelReader() const {
937 return inverter.get() != 0;
940 /// \brief Gives back the node by its label.
942 /// It reads an id from the stream and gives back which node belongs to
943 /// it. It is possible only if there was read an "label" named map.
944 void readLabel(std::istream& is, Node& node) const {
945 node = inverter->read(is);
950 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
955 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
957 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
960 /// \ingroup section_io
961 /// \brief SectionReader for reading a graph's edgeset.
963 /// The lemon format can store multiple graph edgesets with several maps.
964 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
965 /// \c edgeset_name may be empty.
967 /// The first line of the section contains the names of the maps separated
968 /// with white spaces. Each next lines describes an edge in the edgeset. The
969 /// line contains the source and the target nodes' id and the mapped
970 /// values for each map.
972 /// If the edgeset contains an \c "label" named map then it will be regarded
973 /// as id map. This map should contain only unique values and when the
974 /// \c readLabel() member will read a value from the given stream it will
975 /// give back that edge which is mapped to this value.
977 /// The edgeset reader needs a node id reader to identify which nodes
978 /// have to be connected. If a NodeSetReader reads an "label" named map,
979 /// it will be able to resolve the nodes by ids.
981 /// \relates LemonReader
982 template <typename _Graph, typename _Traits = DefaultReaderTraits>
983 class EdgeSetReader : public LemonReader::SectionReader {
984 typedef LemonReader::SectionReader Parent;
987 typedef _Graph Graph;
988 typedef _Traits Traits;
989 typedef typename Graph::Node Node;
990 typedef typename Graph::Edge Edge;
991 typedef typename Traits::Skipper DefaultSkipper;
993 /// \brief Constructor.
995 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
996 /// attach it into the given LemonReader. The edgeset reader will
997 /// add the read edges to the given Graph. It will use the given
998 /// node id reader to read the source and target nodes of the edges.
999 /// The reader will read the section only if the \c _name and the
1000 /// \c edgset_name are the same.
1001 template <typename NodeLabelReader>
1002 EdgeSetReader(LemonReader& _reader,
1004 const NodeLabelReader& _nodeLabelReader,
1005 const std::string& _name = std::string(),
1006 const DefaultSkipper& _skipper = DefaultSkipper())
1007 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1008 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1009 nodeLabelReader.reset(new _reader_bits::
1010 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1012 /// \brief Destructor.
1014 /// Destructor for EdgeSetReader.
1015 virtual ~EdgeSetReader() {
1016 for (typename MapReaders::iterator it = readers.begin();
1017 it != readers.end(); ++it) {
1023 EdgeSetReader(const EdgeSetReader&);
1024 void operator=(const EdgeSetReader&);
1028 /// \brief Add a new edge map reader command for the reader.
1030 /// Add a new edge map reader command for the reader.
1031 template <typename Map>
1032 EdgeSetReader& readEdgeMap(std::string label, Map& map) {
1034 typename Traits::template Reader<typename Map::Value>, Map,
1035 typename _reader_bits::Arg<Map>::Type>(label, map);
1038 template <typename Map>
1039 EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1041 typename Traits::template Reader<typename Map::Value>, Map,
1042 typename _reader_bits::Arg<Map>::Type>(label, map);
1045 /// \brief Add a new edge map reader command for the reader.
1047 /// Add a new edge map reader command for the reader.
1048 template <typename ItemReader, typename Map>
1049 EdgeSetReader& readEdgeMap(std::string label, Map& map,
1050 const ItemReader& ir = ItemReader()) {
1051 return _readMap<ItemReader, Map,
1052 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1055 template <typename ItemReader, typename Map>
1056 EdgeSetReader& readEdgeMap(std::string label, const Map& map,
1057 const ItemReader& ir = ItemReader()) {
1058 return _readMap<ItemReader, Map,
1059 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1064 template <typename ItemReader, typename Map, typename MapParameter>
1065 EdgeSetReader& _readMap(std::string label, MapParameter map,
1066 const ItemReader& ir = ItemReader()) {
1067 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1068 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1069 if (readers.find(label) != readers.end()) {
1071 msg << "Multiple read rule for edge map: " << label;
1072 throw IoParameterError(msg.message());
1075 make_pair(label, new _reader_bits::
1076 MapReader<Edge, Map, ItemReader>(map, ir)));
1082 /// \brief Add a new edge map skipper command for the reader.
1084 /// Add a new edge map skipper command for the reader.
1085 template <typename ItemReader>
1086 EdgeSetReader& skipEdgeMap(std::string label,
1087 const ItemReader& ir = ItemReader()) {
1088 if (readers.find(label) != readers.end()) {
1090 msg << "Multiple read rule for edge map: " << label;
1091 throw IoParameterError(msg.message());
1093 readers.insert(make_pair(label, new _reader_bits::
1094 SkipReader<Edge, ItemReader>(ir)));
1100 /// \brief Gives back true when the SectionReader can process
1101 /// the section with the given header line.
1103 /// It gives back true when the header line starts with \c \@edgeset,
1104 /// and the header line's name and the edgeset's name are the same.
1105 virtual bool header(const std::string& line) {
1106 std::istringstream ls(line);
1107 std::string command;
1109 ls >> command >> id;
1110 return command == "@edgeset" && name == id;
1113 /// \brief Reader function of the section.
1115 /// It reads the content of the section.
1116 virtual void read(std::istream& is) {
1117 if (!nodeLabelReader->isLabelReader()) {
1118 throw DataFormatError("Cannot find nodeset or label map");
1120 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1125 std::istringstream ls(line);
1128 typename MapReaders::iterator it = readers.find(id);
1129 if (it != readers.end()) {
1130 index.push_back(it->second);
1131 it->second->touch();
1133 index.push_back(&skipper);
1135 if (id == "label") {
1136 inverter.reset(index.back()->getInverter());
1137 index.back() = inverter.get();
1141 for (typename MapReaders::iterator it = readers.begin();
1142 it != readers.end(); ++it) {
1143 if (!it->second->touched()) {
1145 msg << "Map not found in file: " << it->first;
1146 throw IoParameterError(msg.message());
1149 while (getline(is, line)) {
1150 std::istringstream ls(line);
1151 Node from = nodeLabelReader->read(ls);
1152 Node to = nodeLabelReader->read(ls);
1153 Edge edge = graph.addEdge(from, to);
1154 for (int i = 0; i < int(index.size()); ++i) {
1155 index[i]->read(ls, edge);
1160 virtual void missing() {
1161 if (readers.empty()) return;
1163 msg << "EdgeSet section not found in file: @edgeset " << name;
1164 throw IoParameterError(msg.message());
1169 /// \brief Returns true if the edgeset can give back the edge by its label.
1171 /// Returns true if the edgeset can give back the edge by its label.
1172 /// It is possible only if an "label" named map was read.
1173 bool isLabelReader() const {
1174 return inverter.get() != 0;
1177 /// \brief Gives back the edge by its label.
1179 /// It reads an id from the stream and gives back which edge belongs to
1180 /// it. It is possible only if there was read an "label" named map.
1181 void readLabel(std::istream& is, Edge& edge) const {
1182 edge = inverter->read(is);
1187 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1194 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1196 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1197 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1200 /// \ingroup section_io
1201 /// \brief SectionReader for reading a undirected graph's edgeset.
1203 /// The lemon format can store multiple undirected edgesets with several
1204 /// maps. The undirected edgeset section's header line is \c \@uedgeset
1205 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1207 /// The first line of the section contains the names of the maps separated
1208 /// with white spaces. Each next lines describes an edge in the edgeset. The
1209 /// line contains the connected nodes' id and the mapped values for each map.
1211 /// The section can handle the directed as a syntactical sugar. Two
1212 /// undirected edge map describes one directed edge map. This two maps
1213 /// are the forward map and the backward map and the names of this map
1214 /// is near the same just with a prefix \c '+' or \c '-' character
1217 /// If the edgeset contains an \c "label" named map then it will be regarded
1218 /// as id map. This map should contain only unique values and when the
1219 /// \c readLabel() member will read a value from the given stream it will
1220 /// give back that uicted edge which is mapped to this value.
1222 /// The undirected edgeset reader needs a node id reader to identify which
1223 /// nodes have to be connected. If a NodeSetReader reads an "label" named
1224 /// map, it will be able to resolve the nodes by ids.
1226 /// \relates LemonReader
1227 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1228 class UEdgeSetReader : public LemonReader::SectionReader {
1229 typedef LemonReader::SectionReader Parent;
1232 typedef _Graph Graph;
1233 typedef _Traits Traits;
1234 typedef typename Graph::Node Node;
1235 typedef typename Graph::Edge Edge;
1236 typedef typename Graph::UEdge UEdge;
1237 typedef typename Traits::Skipper DefaultSkipper;
1239 /// \brief Constructor.
1241 /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1242 /// and attach it into the given LemonReader. The undirected edgeset
1243 /// reader will add the read undirected edges to the given Graph. It
1244 /// will use the given node id reader to read the source and target
1245 /// nodes of the edges. The reader will read the section only if the
1246 /// \c _name and the \c uedgset_name are the same.
1247 template <typename NodeLabelReader>
1248 UEdgeSetReader(LemonReader& _reader,
1250 const NodeLabelReader& _nodeLabelReader,
1251 const std::string& _name = std::string(),
1252 const DefaultSkipper& _skipper = DefaultSkipper())
1253 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1254 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1255 nodeLabelReader.reset(new _reader_bits::
1256 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1258 /// \brief Destructor.
1260 /// Destructor for UEdgeSetReader.
1261 virtual ~UEdgeSetReader() {
1262 for (typename MapReaders::iterator it = readers.begin();
1263 it != readers.end(); ++it) {
1269 UEdgeSetReader(const UEdgeSetReader&);
1270 void operator=(const UEdgeSetReader&);
1274 /// \brief Add a new undirected edge map reader command for the reader.
1276 /// Add a new edge undirected map reader command for the reader.
1277 template <typename Map>
1278 UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
1280 typename Traits::template Reader<typename Map::Value>, Map,
1281 typename _reader_bits::Arg<Map>::Type>(label, map);
1284 template <typename Map>
1285 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
1287 typename Traits::template Reader<typename Map::Value>, Map,
1288 typename _reader_bits::Arg<Map>::Type>(label, map);
1291 /// \brief Add a new undirected edge map reader command for the reader.
1293 /// Add a new edge undirected map reader command for the reader.
1294 template <typename ItemReader, typename Map>
1295 UEdgeSetReader& readUEdgeMap(std::string label, Map& map,
1296 const ItemReader& ir = ItemReader()) {
1297 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1301 template <typename ItemReader, typename Map>
1302 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map,
1303 const ItemReader& ir = ItemReader()) {
1304 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
1310 template <typename ItemReader, typename Map, typename MapParameter>
1311 UEdgeSetReader& _readMap(std::string label, MapParameter map,
1312 const ItemReader& ir = ItemReader()) {
1313 checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1314 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1315 if (readers.find(label) != readers.end()) {
1317 msg << "Multiple read rule for edge map: " << label;
1318 throw IoParameterError(msg.message());
1321 make_pair(label, new _reader_bits::
1322 MapReader<UEdge, Map, ItemReader>(map, ir)));
1328 /// \brief Add a new undirected edge map skipper command for the reader.
1330 /// Add a new undirected edge map skipper command for the reader.
1331 template <typename ItemReader>
1332 UEdgeSetReader& skipUEdgeMap(std::string label,
1333 const ItemReader& ir = ItemReader()) {
1334 if (readers.find(label) != readers.end()) {
1336 msg << "Multiple read rule for node map: " << label;
1337 throw IoParameterError(msg.message());
1339 readers.insert(make_pair(label, new _reader_bits::
1340 SkipReader<UEdge, ItemReader>(ir)));
1344 /// \brief Add a new directed edge map reader command for the reader.
1346 /// Add a new directed edge map reader command for the reader.
1347 template <typename Map>
1348 UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
1350 typename Traits::template Reader<typename Map::Value>, Map,
1351 typename _reader_bits::Arg<Map>::Type>(label, map);
1354 template <typename Map>
1355 UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1357 typename Traits::template Reader<typename Map::Value>, Map,
1358 typename _reader_bits::Arg<Map>::Type>(label, map);
1361 /// \brief Add a new directed edge map reader command for the reader.
1363 /// Add a new directed edge map reader command for the reader.
1364 template <typename ItemReader, typename Map>
1365 UEdgeSetReader& readEdgeMap(std::string label, Map& map,
1366 const ItemReader& ir = ItemReader()) {
1367 return _readDirMap<ItemReader, Map,
1368 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1371 template <typename ItemReader, typename Map>
1372 UEdgeSetReader& readEdgeMap(std::string label, const Map& map,
1373 const ItemReader& ir = ItemReader()) {
1374 return _readDirMap<ItemReader, Map,
1375 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1380 template <typename ItemReader, typename Map, typename MapParameter>
1381 UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
1382 const ItemReader& ir = ItemReader()) {
1383 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1384 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1385 readUEdgeMap("+" + label,
1386 _reader_bits::forwardComposeMap(graph, map), ir);
1387 readUEdgeMap("-" + label,
1388 _reader_bits::backwardComposeMap(graph, map), ir);
1394 /// \brief Add a new directed edge map skipper command for the reader.
1396 /// Add a new directed edge map skipper command for the reader.
1397 template <typename ItemReader>
1398 UEdgeSetReader& skipEdgeMap(std::string label,
1399 const ItemReader& ir = ItemReader()) {
1400 skipUEdgeMap("+" + label, ir);
1401 skipUEdgeMap("-" + label, ir);
1407 /// \brief Gives back true when the SectionReader can process
1408 /// the section with the given header line.
1410 /// It gives back true when the header line starts with \c \@uedgeset,
1411 /// and the header line's name and the edgeset's name are the same.
1412 virtual bool header(const std::string& line) {
1413 std::istringstream ls(line);
1414 std::string command;
1416 ls >> command >> id;
1417 return command == "@uedgeset" && name == id;
1420 /// \brief Reader function of the section.
1422 /// It reads the content of the section.
1423 virtual void read(std::istream& is) {
1424 if (!nodeLabelReader->isLabelReader()) {
1425 throw DataFormatError("Cannot find nodeset or label map");
1427 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1432 std::istringstream ls(line);
1435 typename MapReaders::iterator it = readers.find(id);
1436 if (it != readers.end()) {
1437 index.push_back(it->second);
1438 it->second->touch();
1440 index.push_back(&skipper);
1442 if (id == "label") {
1443 inverter.reset(index.back()->getInverter());
1444 index.back() = inverter.get();
1447 for (typename MapReaders::iterator it = readers.begin();
1448 it != readers.end(); ++it) {
1449 if (!it->second->touched()) {
1451 msg << "Map not found in file: " << it->first;
1452 throw IoParameterError(msg.message());
1456 while (getline(is, line)) {
1457 std::istringstream ls(line);
1458 Node from = nodeLabelReader->read(ls);
1459 Node to = nodeLabelReader->read(ls);
1460 UEdge edge = graph.addEdge(from, to);
1461 for (int i = 0; i < int(index.size()); ++i) {
1462 index[i]->read(ls, edge);
1467 virtual void missing() {
1468 if (readers.empty()) return;
1470 msg << "UEdgeSet section not found in file: @uedgeset " << name;
1471 throw IoParameterError(msg.message());
1476 /// \brief Returns true if the edgeset can give back the edge by its label.
1478 /// Returns true if the edgeset can give back the undirected edge by its
1479 /// id. It is possible only if an "label" named map was read.
1480 bool isLabelReader() const {
1481 return inverter.get() != 0;
1484 /// \brief Gives back the undirected edge by its label.
1486 /// It reads an id from the stream and gives back which undirected edge
1487 /// belongs to it. It is possible only if there was read an "label" named map.
1488 void readLabel(std::istream& is, UEdge& uEdge) const {
1489 uEdge = inverter->read(is);
1492 /// \brief Gives back the directed edge by its label.
1494 /// It reads an id from the stream and gives back which directed edge
1495 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1496 /// and the undirected edge id. It is possible only if there was read
1497 /// an "label" named map.
1498 void readLabel(std::istream& is, Edge& edge) const {
1501 UEdge uEdge = inverter->read(is);
1503 edge = graph.direct(uEdge, true);
1504 } else if (c == '-') {
1505 edge = graph.direct(uEdge, false);
1507 throw DataFormatError("Wrong id format for edge "
1508 "in undirected edgeset");
1514 typedef std::map<std::string,
1515 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1520 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1522 std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1523 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1526 /// \ingroup section_io
1527 /// \brief SectionReader for reading labeled nodes.
1529 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1530 /// \c nodes_name may be empty.
1532 /// Each line in the section contains the name of the node
1533 /// and then the node id.
1535 /// \relates LemonReader
1536 template <typename _Graph>
1537 class NodeReader : public LemonReader::SectionReader {
1538 typedef LemonReader::SectionReader Parent;
1539 typedef _Graph Graph;
1540 typedef typename Graph::Node Node;
1543 /// \brief Constructor.
1545 /// Constructor for NodeReader. It creates the NodeReader and
1546 /// attach it into the given LemonReader. It will use the given
1547 /// node id reader to give back the nodes. The reader will read the
1548 /// section only if the \c _name and the \c nodes_name are the same.
1549 template <typename _LabelReader>
1550 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1551 const std::string& _name = std::string())
1552 : Parent(_reader), name(_name) {
1553 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1554 nodeLabelReader.reset(new _reader_bits::
1555 LabelReader<Node, _LabelReader>(_labelReader));
1558 /// \brief Destructor.
1560 /// Destructor for NodeReader.
1561 virtual ~NodeReader() {}
1564 NodeReader(const NodeReader&);
1565 void operator=(const NodeReader&);
1569 /// \brief Add a node reader command for the NodeReader.
1571 /// Add a node reader command for the NodeReader.
1572 void readNode(std::string label, Node& item) {
1573 if (readers.find(label) != readers.end()) {
1575 msg << "Multiple read rule for node: " << label;
1576 throw IoParameterError(msg.message());
1578 readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
1583 /// \brief Gives back true when the SectionReader can process
1584 /// the section with the given header line.
1586 /// It gives back true when the header line start with \c \@nodes,
1587 /// and the header line's name and the reader's name are the same.
1588 virtual bool header(const std::string& line) {
1589 std::istringstream ls(line);
1590 std::string command;
1592 ls >> command >> id;
1593 return command == "@nodes" && name == id;
1596 /// \brief Reader function of the section.
1598 /// It reads the content of the section.
1599 virtual void read(std::istream& is) {
1600 if (!nodeLabelReader->isLabelReader()) {
1601 throw DataFormatError("Cannot find nodeset or label map");
1604 while (getline(is, line)) {
1605 std::istringstream ls(line);
1608 typename NodeReaders::iterator it = readers.find(id);
1609 if (it != readers.end()) {
1610 it->second.read(nodeLabelReader->read(ls));
1614 for (typename NodeReaders::iterator it = readers.begin();
1615 it != readers.end(); ++it) {
1616 if (!it->second.touched()) {
1618 msg << "Node not found in file: " << it->first;
1619 throw IoParameterError(msg.message());
1624 virtual void missing() {
1625 if (readers.empty()) return;
1627 msg << "Nodes section not found in file: @nodes " << name;
1628 throw IoParameterError(msg.message());
1635 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1636 NodeReaders readers;
1637 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1640 /// \ingroup section_io
1641 /// \brief SectionReader for reading labeled edges.
1643 /// The edges section's header line is \c \@edges \c edges_name, but the
1644 /// \c edges_name may be empty.
1646 /// Each line in the section contains the name of the edge
1647 /// and then the edge id.
1649 /// \relates LemonReader
1650 template <typename _Graph>
1651 class EdgeReader : public LemonReader::SectionReader {
1652 typedef LemonReader::SectionReader Parent;
1653 typedef _Graph Graph;
1654 typedef typename Graph::Edge Edge;
1657 /// \brief Constructor.
1659 /// Constructor for EdgeReader. It creates the EdgeReader and
1660 /// attach it into the given LemonReader. It will use the given
1661 /// edge id reader to give back the edges. The reader will read the
1662 /// section only if the \c _name and the \c edges_name are the same.
1663 template <typename _LabelReader>
1664 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1665 const std::string& _name = std::string())
1666 : Parent(_reader), name(_name) {
1667 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1668 edgeLabelReader.reset(new _reader_bits::
1669 LabelReader<Edge, _LabelReader>(_labelReader));
1672 /// \brief Destructor.
1674 /// Destructor for EdgeReader.
1675 virtual ~EdgeReader() {}
1677 EdgeReader(const EdgeReader&);
1678 void operator=(const EdgeReader&);
1682 /// \brief Add an edge reader command for the EdgeReader.
1684 /// Add an edge reader command for the EdgeReader.
1685 void readEdge(std::string label, Edge& item) {
1686 if (readers.find(label) != readers.end()) {
1688 msg << "Multiple read rule for edge: " << label;
1689 throw IoParameterError(msg.message());
1691 readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1696 /// \brief Gives back true when the SectionReader can process
1697 /// the section with the given header line.
1699 /// It gives back true when the header line start with \c \@edges,
1700 /// and the header line's name and the reader's name are the same.
1701 virtual bool header(const std::string& line) {
1702 std::istringstream ls(line);
1703 std::string command;
1705 ls >> command >> id;
1706 return command == "@edges" && name == id;
1709 /// \brief Reader function of the section.
1711 /// It reads the content of the section.
1712 virtual void read(std::istream& is) {
1713 if (!edgeLabelReader->isLabelReader()) {
1714 throw DataFormatError("Cannot find edgeset or label map");
1717 while (getline(is, line)) {
1718 std::istringstream ls(line);
1721 typename EdgeReaders::iterator it = readers.find(id);
1722 if (it != readers.end()) {
1723 it->second.read(edgeLabelReader->read(ls));
1727 for (typename EdgeReaders::iterator it = readers.begin();
1728 it != readers.end(); ++it) {
1729 if (!it->second.touched()) {
1731 msg << "Edge not found in file: " << it->first;
1732 throw IoParameterError(msg.message());
1737 virtual void missing() {
1738 if (readers.empty()) return;
1740 msg << "Edges section not found in file: @edges " << name;
1741 throw IoParameterError(msg.message());
1748 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1749 EdgeReaders readers;
1750 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1753 /// \ingroup section_io
1754 /// \brief SectionReader for reading labeled undirected edges.
1756 /// The undirected edges section's header line is \c \@uedges
1757 /// \c uedges_name, but the \c uedges_name may be empty.
1759 /// Each line in the section contains the name of the undirected edge
1760 /// and then the undirected edge id.
1762 /// \relates LemonReader
1763 template <typename _Graph>
1764 class UEdgeReader : public LemonReader::SectionReader {
1765 typedef LemonReader::SectionReader Parent;
1766 typedef _Graph Graph;
1767 typedef typename Graph::Edge Edge;
1768 typedef typename Graph::UEdge UEdge;
1771 /// \brief Constructor.
1773 /// Constructor for UEdgeReader. It creates the UEdgeReader and
1774 /// attach it into the given LemonReader. It will use the given
1775 /// undirected edge id reader to give back the edges. The reader will
1776 /// read the section only if the \c _name and the \c uedges_name are
1778 template <typename _LabelReader>
1779 UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1780 const std::string& _name = std::string())
1781 : Parent(_reader), name(_name) {
1782 checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1783 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1784 uEdgeLabelReader.reset(new _reader_bits::
1785 LabelReader<UEdge, _LabelReader>(_labelReader));
1786 edgeLabelReader.reset(new _reader_bits::
1787 LabelReader<Edge, _LabelReader>(_labelReader));
1790 /// \brief Destructor.
1792 /// Destructor for UEdgeReader.
1793 virtual ~UEdgeReader() {}
1795 UEdgeReader(const UEdgeReader&);
1796 void operator=(const UEdgeReader&);
1800 /// \brief Add an undirected edge reader command for the UEdgeReader.
1802 /// Add an undirected edge reader command for the UEdgeReader.
1803 void readUEdge(std::string label, UEdge& item) {
1804 if (uEdgeReaders.find(label) != uEdgeReaders.end()) {
1806 msg << "Multiple read rule for undirected edge: " << label;
1807 throw IoParameterError(msg.message());
1809 uEdgeReaders.insert(make_pair(label, _reader_bits::
1810 ItemStore<UEdge>(item)));
1813 /// \brief Add an edge reader command for the UEdgeReader.
1815 /// Add an edge reader command for the UEdgeReader.
1816 void readEdge(std::string label, Edge& item) {
1817 if (edgeReaders.find(label) != edgeReaders.end()) {
1819 msg << "Multiple read rule for edge: " << label;
1820 throw IoParameterError(msg.message());
1822 edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1827 /// \brief Gives back true when the SectionReader can process
1828 /// the section with the given header line.
1830 /// It gives back true when the header line start with \c \@edges,
1831 /// and the header line's name and the reader's name are the same.
1832 virtual bool header(const std::string& line) {
1833 std::istringstream ls(line);
1834 std::string command;
1836 ls >> command >> id;
1837 return command == "@uedges" && name == id;
1840 /// \brief Reader function of the section.
1842 /// It reads the content of the section.
1843 virtual void read(std::istream& is) {
1844 if (!edgeLabelReader->isLabelReader()) {
1845 throw DataFormatError("Cannot find undirected edgeset or label map");
1847 if (!uEdgeLabelReader->isLabelReader()) {
1848 throw DataFormatError("Cannot find undirected edgeset or label map");
1851 while (getline(is, line)) {
1852 std::istringstream ls(line);
1856 typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1857 if (it != uEdgeReaders.end()) {
1858 it->second.read(uEdgeLabelReader->read(ls));
1863 typename EdgeReaders::iterator it = edgeReaders.find(id);
1864 if (it != edgeReaders.end()) {
1865 it->second.read(edgeLabelReader->read(ls));
1871 for (typename EdgeReaders::iterator it = edgeReaders.begin();
1872 it != edgeReaders.end(); ++it) {
1873 if (!it->second.touched()) {
1875 msg << "Edge not found in file: " << it->first;
1876 throw IoParameterError(msg.message());
1879 for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1880 it != uEdgeReaders.end(); ++it) {
1881 if (!it->second.touched()) {
1883 msg << "UEdge not found in file: " << it->first;
1884 throw IoParameterError(msg.message());
1889 virtual void missing() {
1890 if (edgeReaders.empty() && uEdgeReaders.empty()) return;
1892 msg << "UEdges section not found in file: @uedges " << name;
1893 throw IoParameterError(msg.message());
1900 typedef std::map<std::string,
1901 _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1902 UEdgeReaders uEdgeReaders;
1903 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
1905 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1906 EdgeReaders edgeReaders;
1907 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1910 /// \ingroup section_io
1911 /// \brief SectionReader for attributes.
1913 /// The lemon format can store multiple attribute set. Each set has
1914 /// the header line \c \@attributes \c attributeset_name, but the
1915 /// attributeset_name may be empty.
1917 /// The attributeset section contains several lines. Each of them starts
1918 /// with an attribute and then a the value for the id.
1920 /// \relates LemonReader
1921 template <typename _Traits = DefaultReaderTraits>
1922 class AttributeReader : public LemonReader::SectionReader {
1923 typedef LemonReader::SectionReader Parent;
1924 typedef _Traits Traits;
1926 /// \brief Constructor.
1928 /// Constructor for AttributeReader. It creates the AttributeReader and
1929 /// attach it into the given LemonReader. The reader process a section
1930 /// only if the \c section_name and the \c _name are the same.
1931 AttributeReader(LemonReader& _reader,
1932 const std::string& _name = std::string())
1933 : Parent(_reader), name(_name) {}
1935 /// \brief Destructor.
1937 /// Destructor for AttributeReader.
1938 virtual ~AttributeReader() {
1939 for (typename Readers::iterator it = readers.begin();
1940 it != readers.end(); ++it) {
1946 AttributeReader(const AttributeReader&);
1947 void operator=(AttributeReader&);
1950 /// \brief Add an attribute reader command for the reader.
1952 /// Add an attribute reader command for the reader.
1953 template <typename Value>
1954 AttributeReader& readAttribute(const std::string& label, Value& value) {
1955 return readAttribute<typename Traits::template Reader<Value> >
1959 /// \brief Add an attribute reader command for the reader.
1961 /// Add an attribute reader command for the reader.
1962 template <typename ItemReader, typename Value>
1963 AttributeReader& readAttribute(const std::string& label, Value& value,
1964 const ItemReader& ir = ItemReader()) {
1965 checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
1966 if (readers.find(label) != readers.end()) {
1968 msg << "Multiple read rule for attribute: " << label;
1969 throw IoParameterError(msg.message());
1971 readers.insert(make_pair(label, new _reader_bits::
1972 ValueReader<Value, ItemReader>(value, ir)));
1978 /// \brief Gives back true when the SectionReader can process
1979 /// the section with the given header line.
1981 /// It gives back true when the header line start with \c \@attributes,
1982 /// and the header line's id and the attributeset's id are the same.
1983 bool header(const std::string& line) {
1984 std::istringstream ls(line);
1985 std::string command;
1987 ls >> command >> id;
1988 return command == "@attributes" && name == id;
1991 /// \brief Reader function of the section.
1993 /// It reads the content of the section.
1994 void read(std::istream& is) {
1996 while (getline(is, line)) {
1997 std::istringstream ls(line);
2000 typename Readers::iterator it = readers.find(id);
2001 if (it != readers.end()) {
2002 it->second->read(ls);
2003 it->second->touch();
2006 for (typename Readers::iterator it = readers.begin();
2007 it != readers.end(); ++it) {
2008 if (!it->second->touched()) {
2010 msg << "Attribute not found in file: " << it->first;
2011 throw IoParameterError(msg.message());
2016 virtual void missing() {
2017 if (readers.empty()) return;
2019 msg << "Attribute section not found in file: @attributes " << name;
2020 throw IoParameterError(msg.message());
2026 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2030 /// \ingroup section_io
2031 /// \brief SectionReader for retrieve what is in the file.
2033 /// SectionReader for retrieve what is in the file. If you want
2034 /// to know which sections, maps and items are in the file
2035 /// use the next code:
2037 /// LemonReader reader("input.lgf");
2038 /// ContentReader content(reader);
2041 class ContentReader : public LemonReader::SectionReader {
2042 typedef LemonReader::SectionReader Parent;
2044 /// \brief Constructor.
2047 ContentReader(LemonReader& _reader) : Parent(_reader) {}
2049 /// \brief Desctructor.
2052 virtual ~ContentReader() {}
2054 /// \brief Gives back how many nodesets are in the file.
2056 /// Gives back how many nodesets are in the file.
2057 int nodeSetNum() const {
2058 return nodesets.size();
2061 /// \brief Gives back the name of nodeset on the indiced position.
2063 /// Gives back the name of nodeset on the indiced position.
2064 std::string nodeSetName(int index) const {
2065 return nodesets[index].name;
2068 /// \brief Gives back the map names of nodeset on the indiced position.
2070 /// Gives back the map names of nodeset on the indiced position.
2071 const std::vector<std::string>& nodeSetMaps(int index) const {
2072 return nodesets[index].items;
2075 /// \brief Gives back how many edgesets are in the file.
2077 /// Gives back how many edgesets are in the file.
2078 int edgeSetNum() const {
2079 return edgesets.size();
2082 /// \brief Gives back the name of edgeset on the indiced position.
2084 /// Gives back the name of edgeset on the indiced position.
2085 std::string edgeSetName(int index) const {
2086 return edgesets[index].name;
2089 /// \brief Gives back the map names of edgeset on the indiced position.
2091 /// Gives back the map names of edgeset on the indiced position.
2092 const std::vector<std::string>& edgeSetMaps(int index) const {
2093 return edgesets[index].items;
2096 /// \brief Gives back how many undirected edgesets are in the file.
2098 /// Gives back how many undirected edgesets are in the file.
2099 int uEdgeSetNum() const {
2100 return uedgesets.size();
2103 /// \brief Gives back the name of undirected edgeset on the indiced
2106 /// Gives back the name of undirected edgeset on the indiced position.
2107 std::string uEdgeSetName(int index) const {
2108 return uedgesets[index].name;
2111 /// \brief Gives back the map names of undirected edgeset on the indiced
2114 /// Gives back the map names of undirected edgeset on the indiced position.
2115 const std::vector<std::string>& uEdgeSetMaps(int index) const {
2116 return uedgesets[index].items;
2119 /// \brief Gives back how many labeled nodes section are in the file.
2121 /// Gives back how many labeled nodes section are in the file.
2122 int nodesNum() const {
2123 return nodes.size();
2126 /// \brief Gives back the name of labeled nodes section on the indiced
2129 /// Gives back the name of labeled nodes section on the indiced position.
2130 std::string nodesName(int index) const {
2131 return nodes[index].name;
2134 /// \brief Gives back the names of the labeled nodes in the indiced
2137 /// Gives back the names of the labeled nodes in the indiced section.
2138 const std::vector<std::string>& nodesItems(int index) const {
2139 return nodes[index].items;
2142 /// \brief Gives back how many labeled edges section are in the file.
2144 /// Gives back how many labeled edges section are in the file.
2145 int edgesNum() const {
2146 return edges.size();
2149 /// \brief Gives back the name of labeled edges section on the indiced
2152 /// Gives back the name of labeled edges section on the indiced position.
2153 std::string edgesName(int index) const {
2154 return edges[index].name;
2157 /// \brief Gives back the names of the labeled edges in the indiced
2160 /// Gives back the names of the labeled edges in the indiced section.
2161 const std::vector<std::string>& edgesItems(int index) const {
2162 return edges[index].items;
2165 /// \brief Gives back how many labeled undirected edges section are
2168 /// Gives back how many labeled undirected edges section are in the file.
2169 int uEdgesNum() const {
2170 return uedges.size();
2173 /// \brief Gives back the name of labeled undirected edges section
2174 /// on the indiced position.
2176 /// Gives back the name of labeled undirected edges section on the
2177 /// indiced position.
2178 std::string uEdgesName(int index) const {
2179 return uedges[index].name;
2182 /// \brief Gives back the names of the labeled undirected edges in
2183 /// the indiced section.
2185 /// Gives back the names of the labeled undirected edges in the
2186 /// indiced section.
2187 const std::vector<std::string>& uEdgesItems(int index) const {
2188 return uedges[index].items;
2192 /// \brief Gives back how many attributes section are in the file.
2194 /// Gives back how many attributes section are in the file.
2195 int attributesNum() const {
2196 return attributes.size();
2199 /// \brief Gives back the name of attributes section on the indiced
2202 /// Gives back the name of attributes section on the indiced position.
2203 std::string attributesName(int index) const {
2204 return attributes[index].name;
2207 /// \brief Gives back the names of the attributes in the indiced section.
2209 /// Gives back the names of the attributes in the indiced section.
2210 const std::vector<std::string>& attributesItems(int index) const {
2211 return attributes[index].items;
2214 const std::vector<std::string>& otherSections() const {
2220 /// \brief Gives back true when the SectionReader can process
2221 /// the section with the given header line.
2223 /// It gives back true when the section is common section.
2224 bool header(const std::string& line) {
2225 std::istringstream ls(line);
2226 std::string command, name;
2227 ls >> command >> name;
2228 if (command == "@nodeset") {
2230 nodesets.push_back(SectionInfo(name));
2231 } else if (command == "@edgeset") {
2233 edgesets.push_back(SectionInfo(name));
2234 } else if (command == "@uedgeset") {
2236 uedgesets.push_back(SectionInfo(name));
2237 } else if (command == "@nodes") {
2239 nodes.push_back(SectionInfo(name));
2240 } else if (command == "@edges") {
2242 edges.push_back(SectionInfo(name));
2243 } else if (command == "@uedges") {
2245 uedges.push_back(SectionInfo(name));
2246 } else if (command == "@attributes") {
2248 attributes.push_back(SectionInfo(name));
2250 sections.push_back(line);
2256 /// \brief Retrieve the items from various sections.
2258 /// Retrieve the items from various sections.
2259 void read(std::istream& is) {
2260 if (current == "@nodeset") {
2261 readMapNames(is, nodesets.back().items);
2262 } else if (current == "@edgeset") {
2263 readMapNames(is, edgesets.back().items);
2264 } else if (current == "@uedgeset") {
2265 readMapNames(is, uedgesets.back().items);
2266 } else if (current == "@nodes") {
2267 readItemNames(is, nodes.back().items);
2268 } else if (current == "@edges") {
2269 readItemNames(is, edges.back().items);
2270 } else if (current == "@uedges") {
2271 readItemNames(is, uedges.back().items);
2272 } else if (current == "@attributes") {
2273 readItemNames(is, attributes.back().items);
2279 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2280 std::string line, name;
2281 std::getline(is, line);
2282 std::istringstream ls(line);
2283 while (ls >> name) {
2284 maps.push_back(name);
2286 while (getline(is, line));
2289 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2290 std::string line, name;
2291 while (std::getline(is, line)) {
2292 std::istringstream ls(line);
2294 maps.push_back(name);
2298 struct SectionInfo {
2300 std::vector<std::string> items;
2302 SectionInfo(const std::string& _name) : name(_name) {}
2305 std::vector<SectionInfo> nodesets;
2306 std::vector<SectionInfo> edgesets;
2307 std::vector<SectionInfo> uedgesets;
2309 std::vector<SectionInfo> nodes;
2310 std::vector<SectionInfo> edges;
2311 std::vector<SectionInfo> uedges;
2313 std::vector<SectionInfo> attributes;
2315 std::vector<std::string> sections;
2317 std::string current;