3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2007
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
21 ///\brief Lemon Format reader.
24 #ifndef LEMON_LEMON_READER_H
25 #define LEMON_LEMON_READER_H
36 #include <lemon/error.h>
37 #include <lemon/graph_utils.h>
38 #include <lemon/bits/utility.h>
39 #include <lemon/bits/item_reader.h>
41 #include <lemon/dim2.h>
43 #include <lemon/concept_check.h>
44 #include <lemon/concepts/maps.h>
48 namespace _reader_bits {
51 bool operator<(T, T) {
52 throw DataFormatError("Label is not comparable");
57 bool operator()(const T& p, const T& q) const {
62 template <typename Item>
63 class ItemLabelReader {
66 bool isLabelReader() { return true; }
68 void readLabel(std::istream&, Item&) {}
70 template <class _ItemLabelReader>
73 bool b = reader.isLabelReader();
74 ignore_unused_variable_warning(b);
76 reader.readLabel(is, item);
78 _ItemLabelReader& reader;
84 template <typename Item>
87 void read(std::istream&, Item&) {}
89 template <class _ItemReader>
93 reader.read(is, item);
101 template <typename Map>
102 struct Ref { typedef Map& Type; };
103 template <typename Map>
104 struct Arg { typedef Map& Type; };
106 template <typename Graph, typename Map>
107 class ForwardComposeMap {
109 typedef typename Graph::UEdge Key;
110 typedef typename Map::Value Value;
112 ForwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
113 : graph(_graph), map(_map) {}
115 void set(const Key& key, const Value& val) {
116 map.set(graph.direct(key, true), val);
121 typename Ref<Map>::Type map;
124 template <typename Graph, typename Map>
125 ForwardComposeMap<Graph, Map>
126 forwardComposeMap(const Graph& graph, const Map& map) {
127 return ForwardComposeMap<Graph, Map>(graph, map);
130 template <typename Graph, typename Map>
131 ForwardComposeMap<Graph, Map>
132 forwardComposeMap(const Graph& graph, Map& map) {
133 return ForwardComposeMap<Graph, Map>(graph, map);
136 template <typename Graph, typename Map>
137 class BackwardComposeMap {
139 typedef typename Graph::UEdge Key;
140 typedef typename Map::Value Value;
142 BackwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
143 : graph(_graph), map(_map) {}
145 void set(const Key& key, const Value& val) {
146 map.set(graph.direct(key, false), val);
151 typename Ref<Map>::Type map;
155 template <typename Graph, typename Map>
156 BackwardComposeMap<Graph, Map>
157 backwardComposeMap(const Graph& graph, const Map& map) {
158 return BackwardComposeMap<Graph, Map>(graph, map);
161 template <typename Graph, typename Map>
162 BackwardComposeMap<Graph, Map>
163 backwardComposeMap(const Graph& graph, Map& map) {
164 return BackwardComposeMap<Graph, Map>(graph, map);
167 template <typename Graph, typename Map>
168 struct Ref<ForwardComposeMap<Graph, Map> > {
169 typedef ForwardComposeMap<Graph, Map> Type;
171 template <typename Graph, typename Map>
172 struct Arg<ForwardComposeMap<Graph, Map> > {
173 typedef const ForwardComposeMap<Graph, Map>& Type;
176 template <typename Graph, typename Map>
177 struct Ref<BackwardComposeMap<Graph, Map> > {
178 typedef BackwardComposeMap<Graph, Map> Type;
180 template <typename Graph, typename Map>
181 struct Arg<BackwardComposeMap<Graph, Map> > {
182 typedef const BackwardComposeMap<Graph, Map>& Type;
185 template <typename Map>
186 struct Ref<dim2::XMap<Map> > {
187 typedef dim2::XMap<Map> Type;
189 template <typename Map>
190 struct Arg<dim2::XMap<Map> > {
191 typedef const dim2::XMap<Map>& Type;
194 template <typename Map>
195 struct Ref<dim2::YMap<Map> > {
196 typedef dim2::YMap<Map> Type;
198 template <typename Map>
199 struct Arg<dim2::YMap<Map> > {
200 typedef const dim2::YMap<Map>& Type;
204 template <typename _Item>
207 template <typename _Item>
208 class MapInverterBase : public MapReaderBase<_Item> {
211 virtual void read(std::istream&, const Item&) = 0;
212 virtual Item read(std::istream&) const = 0;
214 virtual MapInverterBase<_Item>* getInverter() {
219 template <typename _Item, typename _Map, typename _Reader>
220 class MapReaderInverter : public MapInverterBase<_Item> {
223 typedef _Reader Reader;
224 typedef typename Reader::Value Value;
226 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
228 typename _reader_bits::Ref<Map>::Type map;
232 MapReaderInverter(typename _reader_bits::Arg<Map>::Type _map,
233 const Reader& _reader)
234 : map(_map), reader(_reader) {}
236 virtual ~MapReaderInverter() {}
238 virtual void read(std::istream& is, const Item& item) {
240 reader.read(is, value);
241 map.set(item, value);
242 typename Inverse::iterator it = inverse.find(value);
243 if (it == inverse.end()) {
244 inverse.insert(std::make_pair(value, item));
246 throw DataFormatError("Multiple label occurence");
250 virtual Item read(std::istream& is) const {
252 reader.read(is, value);
253 typename Inverse::const_iterator it = inverse.find(value);
254 if (it != inverse.end()) {
258 msg << "Invalid label error: " << value;
259 throw DataFormatError(msg.message());
264 template <typename _Item, typename _Reader>
265 class SkipReaderInverter : public MapInverterBase<_Item> {
268 typedef _Reader Reader;
269 typedef typename Reader::Value Value;
270 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
274 SkipReaderInverter(const Reader& _reader)
277 virtual ~SkipReaderInverter() {}
279 virtual void read(std::istream& is, const Item& item) {
281 reader.read(is, value);
282 typename Inverse::iterator it = inverse.find(value);
283 if (it == inverse.end()) {
284 inverse.insert(std::make_pair(value, item));
286 throw DataFormatError("Multiple label occurence error");
290 virtual Item read(std::istream& is) const {
292 reader.read(is, value);
293 typename Inverse::const_iterator it = inverse.find(value);
294 if (it != inverse.end()) {
298 msg << "Invalid label error: " << value;
299 throw DataFormatError(msg.message());
307 template <typename _Item>
308 class MapReaderBase {
312 MapReaderBase() { _touched = false; }
314 void touch() { _touched = true; }
315 bool touched() const { return _touched; }
317 virtual ~MapReaderBase() {}
319 virtual void read(std::istream& is, const Item& item) = 0;
320 virtual MapInverterBase<_Item>* getInverter() = 0;
327 template <typename _Item, typename _Map, typename _Reader>
328 class MapReader : public MapReaderBase<_Item> {
331 typedef _Reader Reader;
332 typedef typename Reader::Value Value;
335 typename _reader_bits::Ref<Map>::Type map;
338 MapReader(typename _reader_bits::Arg<Map>::Type _map,
339 const Reader& _reader)
340 : map(_map), reader(_reader) {}
342 virtual ~MapReader() {}
344 virtual void read(std::istream& is, const Item& item) {
346 reader.read(is, value);
347 map.set(item, value);
350 virtual MapInverterBase<_Item>* getInverter() {
351 return new MapReaderInverter<Item, Map, Reader>(map, reader);
356 template <typename _Item, typename _Reader>
357 class SkipReader : public MapReaderBase<_Item> {
359 typedef _Reader Reader;
360 typedef typename Reader::Value Value;
364 SkipReader(const Reader& _reader) : reader(_reader) {}
366 virtual ~SkipReader() {}
368 virtual void read(std::istream& is, const Item&) {
370 reader.read(is, value);
373 virtual MapInverterBase<Item>* getInverter() {
374 return new SkipReaderInverter<Item, Reader>(reader);
378 template <typename _Item>
379 class LabelReaderBase {
382 virtual ~LabelReaderBase() {}
383 virtual Item read(std::istream& is) const = 0;
384 virtual bool isLabelReader() const = 0;
387 template <typename _Item, typename _BoxedLabelReader>
388 class LabelReader : public LabelReaderBase<_Item> {
391 typedef _BoxedLabelReader BoxedLabelReader;
393 const BoxedLabelReader& boxedLabelReader;
395 LabelReader(const BoxedLabelReader& _boxedLabelReader)
396 : boxedLabelReader(_boxedLabelReader) {}
398 virtual Item read(std::istream& is) const {
400 boxedLabelReader.readLabel(is, item);
404 virtual bool isLabelReader() const {
405 return boxedLabelReader.isLabelReader();
409 template <typename _Item>
415 ItemStore(Item& _item) : item(&_item) {
419 void touch() { _touched = true; }
420 bool touched() const { return _touched; }
422 void read(const Item& _item) {
431 class ValueReaderBase {
433 virtual void read(std::istream&) {};
434 ValueReaderBase() { _touched = false; }
436 void touch() { _touched = true; }
437 bool touched() const { return _touched; }
439 virtual ~ValueReaderBase() {}
444 template <typename _Value, typename _Reader>
445 class ValueReader : public ValueReaderBase {
447 typedef _Value Value;
448 typedef _Reader Reader;
450 ValueReader(Value& _value, const Reader& _reader)
451 : value(_value), reader(_reader) {}
453 virtual void read(std::istream& is) {
454 reader.read(is, value);
463 /// \ingroup lemon_io
464 /// \brief Lemon Format reader class.
466 /// The Lemon Format contains several sections. We do not want to
467 /// determine what sections are in a lemon file we give only a framework
468 /// to read a section oriented format.
470 /// In the Lemon Format each section starts with a line containing a
471 /// \c \@ character on the first not white space position. This line
472 /// is the header line of the section. Each of the next lines belong
473 /// to this section until a line starting with \c \@ character is
474 /// found. This line can start a new section or it can close the
475 /// file with the \c \@end line. The file format ignores the empty
476 /// and comment lines. The line is comment line if it starts with a
479 /// The framework provides an abstract LemonReader::SectionReader class
480 /// that defines the interface of a SectionReader. The SectionReader
481 /// has the \c header() member function that gets a header line string and
482 /// decides if it wants to process the next section. Several SectionReaders
483 /// can be attached to a LemonReader and the first attached that can
484 /// process the section will be used. Its \c read() member will be called
485 /// with a stream containing the section. From this stream the empty and
486 /// comment lines are filtered out.
488 /// \relates GraphReader
489 /// \relates NodeSetReader
490 /// \relates EdgeSetReader
491 /// \relates NodesReader
492 /// \relates EdgesReader
493 /// \relates AttributeReader
497 class FilterStreamBuf : public std::streambuf {
500 typedef std::streambuf Parent;
501 typedef Parent::char_type char_type;
502 FilterStreamBuf(std::istream& is, int& num)
503 : _is(is), _base(0), _eptr(0),
504 _num(num), skip_state(after_endl) {}
508 enum skip_state_type {
514 char_type small_buf[1];
524 skip_state_type skip_state;
527 char_type* base() { return _base; }
529 char_type* eptr() { return _eptr; }
531 int_type blen() { return _eptr - _base; }
533 void setb(char_type* buf, int_type len) {
538 virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
539 if (base()) return 0;
540 if (buf != 0 && len >= int(sizeof(small_buf))) {
543 setb(small_buf, sizeof(small_buf));
549 bool put_char(char c) {
550 switch (skip_state) {
554 skip_state = after_endl;
566 skip_state = comment_line;
570 skip_state = no_skip;
580 skip_state = after_endl;
589 virtual int_type underflow() {
591 if (_is.read(&c, 1)) {
600 for (ptr = base(); ptr != eptr(); ++ptr) {
601 if (_is.read(&c, 1)) {
602 if (c == '\n') ++_num;
606 if (skip_state == after_endl && c == '@') {
616 setg(base(), base(), ptr);
620 virtual int_type sync() {
626 int line_num() const {
628 for (char_type* p = gptr(); p != egptr(); ++p) {
638 /// \brief Abstract base class for reading a section.
640 /// This class has an \c header() member function what get a
641 /// header line string and decides if it want to process the next
642 /// section. Several SectionReaders can be attached to an LemonReader
643 /// and the first attached what can process the section will be used.
644 /// Its \c read() member will called with a stream contains the section.
645 /// From this stream the empty lines and comments are filtered out.
646 class SectionReader {
647 friend class LemonReader;
649 /// \brief Constructor for SectionReader.
651 /// Constructor for SectionReader. It attach this reader to
652 /// the given LemonReader.
653 SectionReader(LemonReader& reader) {
654 reader.attach(*this);
657 virtual ~SectionReader() {}
659 /// \brief Gives back true when the SectionReader can process
660 /// the section with the given header line.
662 /// It gives back true when the SectionReader can process
663 /// the section with the given header line.
664 virtual bool header(const std::string& line) = 0;
666 /// \brief Reader function of the section.
668 /// It reads the content of the section.
669 virtual void read(std::istream& is) = 0;
671 /// \brief The given section missing in the file.
673 /// The given section missing in the file.
674 virtual void missing() {};
677 /// \brief Constructor for LemonReader.
679 /// Constructor for LemonReader which reads from the given stream.
680 LemonReader(std::istream& _is)
681 : is(&_is), own_is(false) {}
683 /// \brief Constructor for LemonReader.
685 /// Constructor for LemonReader which reads from the given file.
686 LemonReader(const std::string& filename)
687 : is(0), own_is(true) {
688 is = new std::ifstream(filename.c_str());
690 throw FileOpenError(filename);
694 /// \brief Desctructor for LemonReader.
696 /// Desctructor for LemonReader.
704 LemonReader(const LemonReader&);
705 void operator=(const LemonReader&);
707 void attach(SectionReader& reader) {
708 readers.push_back(std::make_pair(&reader, false));
712 /// \brief Executes the LemonReader.
714 /// It executes the LemonReader.
719 SectionReaders::iterator it;
720 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
721 for (it = readers.begin(); it != readers.end(); ++it) {
722 if (it->first->header(line)) {
725 FilterStreamBuf buffer(*is, line_num);
728 buffer.pubsetbuf(buf, sizeof(buf));
729 std::istream ss(&buffer);
732 } catch (DataFormatError& error) {
733 error.line(buffer.line_num());
739 for (it = readers.begin(); it != readers.end(); ++it) {
742 it->first->missing();
743 } catch (DataFormatError& error) {
744 error.line(line_num);
757 typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
758 SectionReaders readers;
762 /// \ingroup section_io
763 /// \brief SectionReader for reading a graph's nodeset.
765 /// The lemon format can store multiple graph nodesets with several
766 /// maps. The nodeset section's header line is \c \@nodeset \c
767 /// nodeset_name, but the \c nodeset_name may be empty.
769 /// The first line of the section contains the names of the maps separated
770 /// with white spaces. Each next lines describes a node in the nodeset, and
771 /// contains the mapped values for each map.
773 /// If the nodeset contains an \c "label" named map then it will be regarded
774 /// as id map. This map should contain only unique values and when the
775 /// \c readLabel() member will read a value from the given stream it will
776 /// give back that node which is mapped to this value.
778 /// \relates LemonReader
779 template <typename _Graph, typename _Traits = DefaultReaderTraits>
780 class NodeSetReader : public LemonReader::SectionReader {
781 typedef LemonReader::SectionReader Parent;
784 typedef _Graph Graph;
785 typedef _Traits Traits;
786 typedef typename Graph::Node Node;
787 typedef typename Traits::Skipper DefaultSkipper;
789 /// \brief Constructor.
791 /// Constructor for NodeSetReader. It creates the NodeSetReader and
792 /// attach it into the given LemonReader. The nodeset reader will
793 /// add the read nodes to the given Graph. The reader will read
794 /// the section when the \c section_name and the \c _name are the same.
795 NodeSetReader(LemonReader& _reader,
797 const std::string& _name = std::string(),
798 const DefaultSkipper& _skipper = DefaultSkipper())
799 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
802 /// \brief Destructor.
804 /// Destructor for NodeSetReader.
805 virtual ~NodeSetReader() {
806 for (typename MapReaders::iterator it = readers.begin();
807 it != readers.end(); ++it) {
813 NodeSetReader(const NodeSetReader&);
814 void operator=(const NodeSetReader&);
818 /// \brief Add a new node map reader command for the reader.
820 /// Add a new node map reader command for the reader.
821 template <typename Map>
822 NodeSetReader& readNodeMap(std::string label, Map& map) {
824 typename Traits::template Reader<typename Map::Value>, Map,
825 typename _reader_bits::Arg<Map>::Type>(label, map);
828 template <typename Map>
829 NodeSetReader& readNodeMap(std::string label, const Map& map) {
831 typename Traits::template Reader<typename Map::Value>, Map,
832 typename _reader_bits::Arg<Map>::Type>(label, map);
835 /// \brief Add a new node map reader command for the reader.
837 /// Add a new node map reader command for the reader.
838 template <typename ItemReader, typename Map>
839 NodeSetReader& readNodeMap(std::string label, Map& map,
840 const ItemReader& ir = ItemReader()) {
841 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
845 template <typename ItemReader, typename Map>
846 NodeSetReader& readNodeMap(std::string label, const Map& map,
847 const ItemReader& ir = ItemReader()) {
848 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
854 template <typename ItemReader, typename Map, typename MapParameter>
855 NodeSetReader& _readMap(std::string label, MapParameter map,
856 const ItemReader& ir = ItemReader()) {
857 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
858 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
859 if (readers.find(label) != readers.end()) {
861 msg << "Multiple read rule for node map: " << label;
862 throw IoParameterError(msg.message());
865 make_pair(label, new _reader_bits::
866 MapReader<Node, Map, ItemReader>(map, ir)));
872 /// \brief Add a new node map skipper command for the reader.
874 /// Add a new node map skipper command for the reader.
875 template <typename ItemReader>
876 NodeSetReader& skipNodeMap(std::string label,
877 const ItemReader& ir = ItemReader()) {
878 if (readers.find(label) != readers.end()) {
880 msg << "Multiple read rule for node map: " << label;
881 throw IoParameterError(msg.message());
883 readers.insert(make_pair(label, new _reader_bits::
884 SkipReader<Node, ItemReader>(ir)));
890 /// \brief Gives back true when the SectionReader can process
891 /// the section with the given header line.
893 /// It gives back true when the header line starts with \c \@nodeset,
894 /// and the header line's name and the nodeset's name are the same.
895 virtual bool header(const std::string& line) {
896 std::istringstream ls(line);
900 return command == "@nodeset" && name == id;
903 /// \brief Reader function of the section.
905 /// It reads the content of the section.
906 virtual void read(std::istream& is) {
907 std::vector<_reader_bits::MapReaderBase<Node>* > index;
912 std::istringstream ls(line);
915 typename MapReaders::iterator it = readers.find(id);
916 if (it != readers.end()) {
918 index.push_back(it->second);
920 index.push_back(&skipper);
923 inverter.reset(index.back()->getInverter());
924 index.back() = inverter.get();
928 for (typename MapReaders::iterator it = readers.begin();
929 it != readers.end(); ++it) {
930 if (!it->second->touched()) {
932 msg << "Map not found in file: " << it->first;
933 throw IoParameterError(msg.message());
936 while (getline(is, line)) {
937 Node node = graph.addNode();
938 std::istringstream ls(line);
939 for (int i = 0; i < int(index.size()); ++i) {
940 index[i]->read(ls, node);
945 virtual void missing() {
946 if (readers.empty()) return;
948 msg << "NodeSet section not found in file: @nodeset " << name;
949 throw IoParameterError(msg.message());
954 /// \brief Returns true if the nodeset can give back the node by its label.
956 /// Returns true if the nodeset can give back the node by its label.
957 /// It is possible only if an "label" named map was read.
958 bool isLabelReader() const {
959 return inverter.get() != 0;
962 /// \brief Gives back the node by its label.
964 /// It reads an id from the stream and gives back which node belongs to
965 /// it. It is possible only if there was read an "label" named map.
966 void readLabel(std::istream& is, Node& node) const {
967 node = inverter->read(is);
972 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
977 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
979 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
982 /// \ingroup section_io
983 /// \brief SectionReader for reading a graph's edgeset.
985 /// The lemon format can store multiple graph edgesets with several maps.
986 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
987 /// \c edgeset_name may be empty.
989 /// The first line of the section contains the names of the maps separated
990 /// with white spaces. Each next lines describes an edge in the edgeset. The
991 /// line contains the source and the target nodes' id and the mapped
992 /// values for each map.
994 /// If the edgeset contains an \c "label" named map then it will be regarded
995 /// as id map. This map should contain only unique values and when the
996 /// \c readLabel() member will read a value from the given stream it will
997 /// give back that edge which is mapped to this value.
999 /// The edgeset reader needs a node id reader to identify which nodes
1000 /// have to be connected. If a NodeSetReader reads an "label" named map,
1001 /// it will be able to resolve the nodes by ids.
1003 /// \relates LemonReader
1004 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1005 class EdgeSetReader : public LemonReader::SectionReader {
1006 typedef LemonReader::SectionReader Parent;
1009 typedef _Graph Graph;
1010 typedef _Traits Traits;
1011 typedef typename Graph::Node Node;
1012 typedef typename Graph::Edge Edge;
1013 typedef typename Traits::Skipper DefaultSkipper;
1015 /// \brief Constructor.
1017 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
1018 /// attach it into the given LemonReader. The edgeset reader will
1019 /// add the read edges to the given Graph. It will use the given
1020 /// node id reader to read the source and target nodes of the edges.
1021 /// The reader will read the section only if the \c _name and the
1022 /// \c edgset_name are the same.
1023 template <typename NodeLabelReader>
1024 EdgeSetReader(LemonReader& _reader,
1026 const NodeLabelReader& _nodeLabelReader,
1027 const std::string& _name = std::string(),
1028 const DefaultSkipper& _skipper = DefaultSkipper())
1029 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1030 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1031 nodeLabelReader.reset(new _reader_bits::
1032 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1034 /// \brief Destructor.
1036 /// Destructor for EdgeSetReader.
1037 virtual ~EdgeSetReader() {
1038 for (typename MapReaders::iterator it = readers.begin();
1039 it != readers.end(); ++it) {
1045 EdgeSetReader(const EdgeSetReader&);
1046 void operator=(const EdgeSetReader&);
1050 /// \brief Add a new edge map reader command for the reader.
1052 /// Add a new edge map reader command for the reader.
1053 template <typename Map>
1054 EdgeSetReader& readEdgeMap(std::string label, Map& map) {
1056 typename Traits::template Reader<typename Map::Value>, Map,
1057 typename _reader_bits::Arg<Map>::Type>(label, map);
1060 template <typename Map>
1061 EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1063 typename Traits::template Reader<typename Map::Value>, Map,
1064 typename _reader_bits::Arg<Map>::Type>(label, map);
1067 /// \brief Add a new edge map reader command for the reader.
1069 /// Add a new edge map reader command for the reader.
1070 template <typename ItemReader, typename Map>
1071 EdgeSetReader& readEdgeMap(std::string label, Map& map,
1072 const ItemReader& ir = ItemReader()) {
1073 return _readMap<ItemReader, Map,
1074 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1077 template <typename ItemReader, typename Map>
1078 EdgeSetReader& readEdgeMap(std::string label, const Map& map,
1079 const ItemReader& ir = ItemReader()) {
1080 return _readMap<ItemReader, Map,
1081 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1086 template <typename ItemReader, typename Map, typename MapParameter>
1087 EdgeSetReader& _readMap(std::string label, MapParameter map,
1088 const ItemReader& ir = ItemReader()) {
1089 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1090 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1091 if (readers.find(label) != readers.end()) {
1093 msg << "Multiple read rule for edge map: " << label;
1094 throw IoParameterError(msg.message());
1097 make_pair(label, new _reader_bits::
1098 MapReader<Edge, Map, ItemReader>(map, ir)));
1104 /// \brief Add a new edge map skipper command for the reader.
1106 /// Add a new edge map skipper command for the reader.
1107 template <typename ItemReader>
1108 EdgeSetReader& skipEdgeMap(std::string label,
1109 const ItemReader& ir = ItemReader()) {
1110 if (readers.find(label) != readers.end()) {
1112 msg << "Multiple read rule for edge map: " << label;
1113 throw IoParameterError(msg.message());
1115 readers.insert(make_pair(label, new _reader_bits::
1116 SkipReader<Edge, ItemReader>(ir)));
1122 /// \brief Gives back true when the SectionReader can process
1123 /// the section with the given header line.
1125 /// It gives back true when the header line starts with \c \@edgeset,
1126 /// and the header line's name and the edgeset's name are the same.
1127 /// The sections with @uedgeset head line could be read with this
1128 /// section reader too.
1129 virtual bool header(const std::string& line) {
1130 std::istringstream ls(line);
1131 std::string command;
1133 ls >> command >> id;
1134 return (command == "@edgeset" || command == "@uedgeset") && name == id;
1137 /// \brief Reader function of the section.
1139 /// It reads the content of the section.
1140 virtual void read(std::istream& is) {
1141 if (!nodeLabelReader->isLabelReader()) {
1142 throw DataFormatError("Cannot find nodeset or label map");
1144 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1149 std::istringstream ls(line);
1152 typename MapReaders::iterator it = readers.find(id);
1153 if (it != readers.end()) {
1154 index.push_back(it->second);
1155 it->second->touch();
1157 index.push_back(&skipper);
1159 if (id == "label") {
1160 inverter.reset(index.back()->getInverter());
1161 index.back() = inverter.get();
1165 for (typename MapReaders::iterator it = readers.begin();
1166 it != readers.end(); ++it) {
1167 if (!it->second->touched()) {
1169 msg << "Map not found in file: " << it->first;
1170 throw IoParameterError(msg.message());
1173 while (getline(is, line)) {
1174 std::istringstream ls(line);
1175 Node from = nodeLabelReader->read(ls);
1176 Node to = nodeLabelReader->read(ls);
1177 Edge edge = graph.addEdge(from, to);
1178 for (int i = 0; i < int(index.size()); ++i) {
1179 index[i]->read(ls, edge);
1184 virtual void missing() {
1185 if (readers.empty()) return;
1187 msg << "EdgeSet section not found in file: @edgeset " << name;
1188 throw IoParameterError(msg.message());
1193 /// \brief Returns true if the edgeset can give back the edge by its label.
1195 /// Returns true if the edgeset can give back the edge by its label.
1196 /// It is possible only if an "label" named map was read.
1197 bool isLabelReader() const {
1198 return inverter.get() != 0;
1201 /// \brief Gives back the edge by its label.
1203 /// It reads an id from the stream and gives back which edge belongs to
1204 /// it. It is possible only if there was read an "label" named map.
1205 void readLabel(std::istream& is, Edge& edge) const {
1206 edge = inverter->read(is);
1211 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1218 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1220 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1221 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1224 /// \ingroup section_io
1225 /// \brief SectionReader for reading a undirected graph's edgeset.
1227 /// The lemon format can store multiple undirected edgesets with several
1228 /// maps. The undirected edgeset section's header line is \c \@uedgeset
1229 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1231 /// The first line of the section contains the names of the maps separated
1232 /// with white spaces. Each next lines describes an edge in the edgeset. The
1233 /// line contains the connected nodes' id and the mapped values for each map.
1235 /// The section can handle the directed as a syntactical sugar. Two
1236 /// undirected edge map describes one directed edge map. This two maps
1237 /// are the forward map and the backward map and the names of this map
1238 /// is near the same just with a prefix \c '+' or \c '-' character
1241 /// If the edgeset contains an \c "label" named map then it will be regarded
1242 /// as id map. This map should contain only unique values and when the
1243 /// \c readLabel() member will read a value from the given stream it will
1244 /// give back that uicted edge which is mapped to this value.
1246 /// The undirected edgeset reader needs a node id reader to identify which
1247 /// nodes have to be connected. If a NodeSetReader reads an "label" named
1248 /// map, it will be able to resolve the nodes by ids.
1250 /// \relates LemonReader
1251 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1252 class UEdgeSetReader : public LemonReader::SectionReader {
1253 typedef LemonReader::SectionReader Parent;
1256 typedef _Graph Graph;
1257 typedef _Traits Traits;
1258 typedef typename Graph::Node Node;
1259 typedef typename Graph::Edge Edge;
1260 typedef typename Graph::UEdge UEdge;
1261 typedef typename Traits::Skipper DefaultSkipper;
1263 /// \brief Constructor.
1265 /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1266 /// and attach it into the given LemonReader. The undirected edgeset
1267 /// reader will add the read undirected edges to the given Graph. It
1268 /// will use the given node id reader to read the source and target
1269 /// nodes of the edges. The reader will read the section only if the
1270 /// \c _name and the \c uedgset_name are the same.
1271 template <typename NodeLabelReader>
1272 UEdgeSetReader(LemonReader& _reader,
1274 const NodeLabelReader& _nodeLabelReader,
1275 const std::string& _name = std::string(),
1276 const DefaultSkipper& _skipper = DefaultSkipper())
1277 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1278 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1279 nodeLabelReader.reset(new _reader_bits::
1280 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1282 /// \brief Destructor.
1284 /// Destructor for UEdgeSetReader.
1285 virtual ~UEdgeSetReader() {
1286 for (typename MapReaders::iterator it = readers.begin();
1287 it != readers.end(); ++it) {
1293 UEdgeSetReader(const UEdgeSetReader&);
1294 void operator=(const UEdgeSetReader&);
1298 /// \brief Add a new undirected edge map reader command for the reader.
1300 /// Add a new edge undirected map reader command for the reader.
1301 template <typename Map>
1302 UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
1304 typename Traits::template Reader<typename Map::Value>, Map,
1305 typename _reader_bits::Arg<Map>::Type>(label, map);
1308 template <typename Map>
1309 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
1311 typename Traits::template Reader<typename Map::Value>, Map,
1312 typename _reader_bits::Arg<Map>::Type>(label, map);
1315 /// \brief Add a new undirected edge map reader command for the reader.
1317 /// Add a new edge undirected map reader command for the reader.
1318 template <typename ItemReader, typename Map>
1319 UEdgeSetReader& readUEdgeMap(std::string label, Map& map,
1320 const ItemReader& ir = ItemReader()) {
1321 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1325 template <typename ItemReader, typename Map>
1326 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map,
1327 const ItemReader& ir = ItemReader()) {
1328 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
1334 template <typename ItemReader, typename Map, typename MapParameter>
1335 UEdgeSetReader& _readMap(std::string label, MapParameter map,
1336 const ItemReader& ir = ItemReader()) {
1337 checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1338 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1339 if (readers.find(label) != readers.end()) {
1341 msg << "Multiple read rule for edge map: " << label;
1342 throw IoParameterError(msg.message());
1345 make_pair(label, new _reader_bits::
1346 MapReader<UEdge, Map, ItemReader>(map, ir)));
1352 /// \brief Add a new undirected edge map skipper command for the reader.
1354 /// Add a new undirected edge map skipper command for the reader.
1355 template <typename ItemReader>
1356 UEdgeSetReader& skipUEdgeMap(std::string label,
1357 const ItemReader& ir = ItemReader()) {
1358 if (readers.find(label) != readers.end()) {
1360 msg << "Multiple read rule for node map: " << label;
1361 throw IoParameterError(msg.message());
1363 readers.insert(make_pair(label, new _reader_bits::
1364 SkipReader<UEdge, ItemReader>(ir)));
1368 /// \brief Add a new directed edge map reader command for the reader.
1370 /// Add a new directed edge map reader command for the reader.
1371 template <typename Map>
1372 UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
1374 typename Traits::template Reader<typename Map::Value>, Map,
1375 typename _reader_bits::Arg<Map>::Type>(label, map);
1378 template <typename Map>
1379 UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1381 typename Traits::template Reader<typename Map::Value>, Map,
1382 typename _reader_bits::Arg<Map>::Type>(label, map);
1385 /// \brief Add a new directed edge map reader command for the reader.
1387 /// Add a new directed edge map reader command for the reader.
1388 template <typename ItemReader, typename Map>
1389 UEdgeSetReader& readEdgeMap(std::string label, Map& map,
1390 const ItemReader& ir = ItemReader()) {
1391 return _readDirMap<ItemReader, Map,
1392 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1395 template <typename ItemReader, typename Map>
1396 UEdgeSetReader& readEdgeMap(std::string label, const Map& map,
1397 const ItemReader& ir = ItemReader()) {
1398 return _readDirMap<ItemReader, Map,
1399 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1404 template <typename ItemReader, typename Map, typename MapParameter>
1405 UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
1406 const ItemReader& ir = ItemReader()) {
1407 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1408 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1409 readUEdgeMap("+" + label,
1410 _reader_bits::forwardComposeMap(graph, map), ir);
1411 readUEdgeMap("-" + label,
1412 _reader_bits::backwardComposeMap(graph, map), ir);
1418 /// \brief Add a new directed edge map skipper command for the reader.
1420 /// Add a new directed edge map skipper command for the reader.
1421 template <typename ItemReader>
1422 UEdgeSetReader& skipEdgeMap(std::string label,
1423 const ItemReader& ir = ItemReader()) {
1424 skipUEdgeMap("+" + label, ir);
1425 skipUEdgeMap("-" + label, ir);
1431 /// \brief Gives back true when the SectionReader can process
1432 /// the section with the given header line.
1434 /// It gives back true when the header line starts with \c \@uedgeset,
1435 /// and the header line's name and the edgeset's name are the same.
1436 /// The sections with @edgeset head line could be read with this
1437 /// section reader too.
1438 virtual bool header(const std::string& line) {
1439 std::istringstream ls(line);
1440 std::string command;
1442 ls >> command >> id;
1443 return (command == "@edgeset" || command == "@uedgeset") && name == id;
1446 /// \brief Reader function of the section.
1448 /// It reads the content of the section.
1449 virtual void read(std::istream& is) {
1450 if (!nodeLabelReader->isLabelReader()) {
1451 throw DataFormatError("Cannot find nodeset or label map");
1453 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1458 std::istringstream ls(line);
1461 typename MapReaders::iterator it = readers.find(id);
1462 if (it != readers.end()) {
1463 index.push_back(it->second);
1464 it->second->touch();
1466 index.push_back(&skipper);
1468 if (id == "label") {
1469 inverter.reset(index.back()->getInverter());
1470 index.back() = inverter.get();
1473 for (typename MapReaders::iterator it = readers.begin();
1474 it != readers.end(); ++it) {
1475 if (!it->second->touched()) {
1477 msg << "Map not found in file: " << it->first;
1478 throw IoParameterError(msg.message());
1482 while (getline(is, line)) {
1483 std::istringstream ls(line);
1484 Node from = nodeLabelReader->read(ls);
1485 Node to = nodeLabelReader->read(ls);
1486 UEdge edge = graph.addEdge(from, to);
1487 for (int i = 0; i < int(index.size()); ++i) {
1488 index[i]->read(ls, edge);
1493 virtual void missing() {
1494 if (readers.empty()) return;
1496 msg << "UEdgeSet section not found in file: @uedgeset " << name;
1497 throw IoParameterError(msg.message());
1502 /// \brief Returns true if the edgeset can give back the edge by its label.
1504 /// Returns true if the edgeset can give back the undirected edge by its
1505 /// id. It is possible only if an "label" named map was read.
1506 bool isLabelReader() const {
1507 return inverter.get() != 0;
1510 /// \brief Gives back the undirected edge by its label.
1512 /// It reads an id from the stream and gives back which undirected edge
1513 /// belongs to it. It is possible only if there was read an "label" named map.
1514 void readLabel(std::istream& is, UEdge& uEdge) const {
1515 uEdge = inverter->read(is);
1518 /// \brief Gives back the directed edge by its label.
1520 /// It reads an id from the stream and gives back which directed edge
1521 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1522 /// and the undirected edge id. It is possible only if there was read
1523 /// an "label" named map.
1524 void readLabel(std::istream& is, Edge& edge) const {
1527 UEdge uEdge = inverter->read(is);
1529 edge = graph.direct(uEdge, true);
1530 } else if (c == '-') {
1531 edge = graph.direct(uEdge, false);
1533 throw DataFormatError("Wrong id format for edge "
1534 "in undirected edgeset");
1540 typedef std::map<std::string,
1541 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1546 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1548 std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1549 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1552 /// \ingroup section_io
1553 /// \brief SectionReader for reading labeled nodes.
1555 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1556 /// \c nodes_name may be empty.
1558 /// Each line in the section contains the name of the node
1559 /// and then the node id.
1561 /// \relates LemonReader
1562 template <typename _Graph>
1563 class NodeReader : public LemonReader::SectionReader {
1564 typedef LemonReader::SectionReader Parent;
1565 typedef _Graph Graph;
1566 typedef typename Graph::Node Node;
1569 /// \brief Constructor.
1571 /// Constructor for NodeReader. It creates the NodeReader and
1572 /// attach it into the given LemonReader. It will use the given
1573 /// node id reader to give back the nodes. The reader will read the
1574 /// section only if the \c _name and the \c nodes_name are the same.
1575 template <typename _LabelReader>
1576 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1577 const std::string& _name = std::string())
1578 : Parent(_reader), name(_name) {
1579 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1580 nodeLabelReader.reset(new _reader_bits::
1581 LabelReader<Node, _LabelReader>(_labelReader));
1584 /// \brief Destructor.
1586 /// Destructor for NodeReader.
1587 virtual ~NodeReader() {}
1590 NodeReader(const NodeReader&);
1591 void operator=(const NodeReader&);
1595 /// \brief Add a node reader command for the NodeReader.
1597 /// Add a node reader command for the NodeReader.
1598 void readNode(std::string label, Node& item) {
1599 if (readers.find(label) != readers.end()) {
1601 msg << "Multiple read rule for node: " << label;
1602 throw IoParameterError(msg.message());
1604 readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
1609 /// \brief Gives back true when the SectionReader can process
1610 /// the section with the given header line.
1612 /// It gives back true when the header line start with \c \@nodes,
1613 /// and the header line's name and the reader's name are the same.
1614 virtual bool header(const std::string& line) {
1615 std::istringstream ls(line);
1616 std::string command;
1618 ls >> command >> id;
1619 return command == "@nodes" && name == id;
1622 /// \brief Reader function of the section.
1624 /// It reads the content of the section.
1625 virtual void read(std::istream& is) {
1626 if (!nodeLabelReader->isLabelReader()) {
1627 throw DataFormatError("Cannot find nodeset or label map");
1630 while (getline(is, line)) {
1631 std::istringstream ls(line);
1634 typename NodeReaders::iterator it = readers.find(id);
1635 if (it != readers.end()) {
1636 it->second.read(nodeLabelReader->read(ls));
1640 for (typename NodeReaders::iterator it = readers.begin();
1641 it != readers.end(); ++it) {
1642 if (!it->second.touched()) {
1644 msg << "Node not found in file: " << it->first;
1645 throw IoParameterError(msg.message());
1650 virtual void missing() {
1651 if (readers.empty()) return;
1653 msg << "Nodes section not found in file: @nodes " << name;
1654 throw IoParameterError(msg.message());
1661 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1662 NodeReaders readers;
1663 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1666 /// \ingroup section_io
1667 /// \brief SectionReader for reading labeled edges.
1669 /// The edges section's header line is \c \@edges \c edges_name, but the
1670 /// \c edges_name may be empty.
1672 /// Each line in the section contains the name of the edge
1673 /// and then the edge id.
1675 /// \relates LemonReader
1676 template <typename _Graph>
1677 class EdgeReader : public LemonReader::SectionReader {
1678 typedef LemonReader::SectionReader Parent;
1679 typedef _Graph Graph;
1680 typedef typename Graph::Edge Edge;
1683 /// \brief Constructor.
1685 /// Constructor for EdgeReader. It creates the EdgeReader and
1686 /// attach it into the given LemonReader. It will use the given
1687 /// edge id reader to give back the edges. The reader will read the
1688 /// section only if the \c _name and the \c edges_name are the same.
1689 template <typename _LabelReader>
1690 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1691 const std::string& _name = std::string())
1692 : Parent(_reader), name(_name) {
1693 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1694 edgeLabelReader.reset(new _reader_bits::
1695 LabelReader<Edge, _LabelReader>(_labelReader));
1698 /// \brief Destructor.
1700 /// Destructor for EdgeReader.
1701 virtual ~EdgeReader() {}
1703 EdgeReader(const EdgeReader&);
1704 void operator=(const EdgeReader&);
1708 /// \brief Add an edge reader command for the EdgeReader.
1710 /// Add an edge reader command for the EdgeReader.
1711 void readEdge(std::string label, Edge& item) {
1712 if (readers.find(label) != readers.end()) {
1714 msg << "Multiple read rule for edge: " << label;
1715 throw IoParameterError(msg.message());
1717 readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1722 /// \brief Gives back true when the SectionReader can process
1723 /// the section with the given header line.
1725 /// It gives back true when the header line start with \c \@edges,
1726 /// and the header line's name and the reader's name are the same.
1727 virtual bool header(const std::string& line) {
1728 std::istringstream ls(line);
1729 std::string command;
1731 ls >> command >> id;
1732 return command == "@edges" && name == id;
1735 /// \brief Reader function of the section.
1737 /// It reads the content of the section.
1738 virtual void read(std::istream& is) {
1739 if (!edgeLabelReader->isLabelReader()) {
1740 throw DataFormatError("Cannot find edgeset or label map");
1743 while (getline(is, line)) {
1744 std::istringstream ls(line);
1747 typename EdgeReaders::iterator it = readers.find(id);
1748 if (it != readers.end()) {
1749 it->second.read(edgeLabelReader->read(ls));
1753 for (typename EdgeReaders::iterator it = readers.begin();
1754 it != readers.end(); ++it) {
1755 if (!it->second.touched()) {
1757 msg << "Edge not found in file: " << it->first;
1758 throw IoParameterError(msg.message());
1763 virtual void missing() {
1764 if (readers.empty()) return;
1766 msg << "Edges section not found in file: @edges " << name;
1767 throw IoParameterError(msg.message());
1774 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1775 EdgeReaders readers;
1776 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1779 /// \ingroup section_io
1780 /// \brief SectionReader for reading labeled undirected edges.
1782 /// The undirected edges section's header line is \c \@uedges
1783 /// \c uedges_name, but the \c uedges_name may be empty.
1785 /// Each line in the section contains the name of the undirected edge
1786 /// and then the undirected edge id.
1788 /// \relates LemonReader
1789 template <typename _Graph>
1790 class UEdgeReader : public LemonReader::SectionReader {
1791 typedef LemonReader::SectionReader Parent;
1792 typedef _Graph Graph;
1793 typedef typename Graph::Edge Edge;
1794 typedef typename Graph::UEdge UEdge;
1797 /// \brief Constructor.
1799 /// Constructor for UEdgeReader. It creates the UEdgeReader and
1800 /// attach it into the given LemonReader. It will use the given
1801 /// undirected edge id reader to give back the edges. The reader will
1802 /// read the section only if the \c _name and the \c uedges_name are
1804 template <typename _LabelReader>
1805 UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1806 const std::string& _name = std::string())
1807 : Parent(_reader), name(_name) {
1808 checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1809 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1810 uEdgeLabelReader.reset(new _reader_bits::
1811 LabelReader<UEdge, _LabelReader>(_labelReader));
1812 edgeLabelReader.reset(new _reader_bits::
1813 LabelReader<Edge, _LabelReader>(_labelReader));
1816 /// \brief Destructor.
1818 /// Destructor for UEdgeReader.
1819 virtual ~UEdgeReader() {}
1821 UEdgeReader(const UEdgeReader&);
1822 void operator=(const UEdgeReader&);
1826 /// \brief Add an undirected edge reader command for the UEdgeReader.
1828 /// Add an undirected edge reader command for the UEdgeReader.
1829 void readUEdge(std::string label, UEdge& item) {
1830 if (uEdgeReaders.find(label) != uEdgeReaders.end()) {
1832 msg << "Multiple read rule for undirected edge: " << label;
1833 throw IoParameterError(msg.message());
1835 uEdgeReaders.insert(make_pair(label, _reader_bits::
1836 ItemStore<UEdge>(item)));
1839 /// \brief Add an edge reader command for the UEdgeReader.
1841 /// Add an edge reader command for the UEdgeReader.
1842 void readEdge(std::string label, Edge& item) {
1843 if (edgeReaders.find(label) != edgeReaders.end()) {
1845 msg << "Multiple read rule for edge: " << label;
1846 throw IoParameterError(msg.message());
1848 edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1853 /// \brief Gives back true when the SectionReader can process
1854 /// the section with the given header line.
1856 /// It gives back true when the header line start with \c \@edges,
1857 /// and the header line's name and the reader's name are the same.
1858 virtual bool header(const std::string& line) {
1859 std::istringstream ls(line);
1860 std::string command;
1862 ls >> command >> id;
1863 return command == "@uedges" && name == id;
1866 /// \brief Reader function of the section.
1868 /// It reads the content of the section.
1869 virtual void read(std::istream& is) {
1870 if (!edgeLabelReader->isLabelReader()) {
1871 throw DataFormatError("Cannot find undirected edgeset or label map");
1873 if (!uEdgeLabelReader->isLabelReader()) {
1874 throw DataFormatError("Cannot find undirected edgeset or label map");
1877 while (getline(is, line)) {
1878 std::istringstream ls(line);
1882 typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1883 if (it != uEdgeReaders.end()) {
1884 it->second.read(uEdgeLabelReader->read(ls));
1889 typename EdgeReaders::iterator it = edgeReaders.find(id);
1890 if (it != edgeReaders.end()) {
1891 it->second.read(edgeLabelReader->read(ls));
1897 for (typename EdgeReaders::iterator it = edgeReaders.begin();
1898 it != edgeReaders.end(); ++it) {
1899 if (!it->second.touched()) {
1901 msg << "Edge not found in file: " << it->first;
1902 throw IoParameterError(msg.message());
1905 for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1906 it != uEdgeReaders.end(); ++it) {
1907 if (!it->second.touched()) {
1909 msg << "UEdge not found in file: " << it->first;
1910 throw IoParameterError(msg.message());
1915 virtual void missing() {
1916 if (edgeReaders.empty() && uEdgeReaders.empty()) return;
1918 msg << "UEdges section not found in file: @uedges " << name;
1919 throw IoParameterError(msg.message());
1926 typedef std::map<std::string,
1927 _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1928 UEdgeReaders uEdgeReaders;
1929 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
1931 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1932 EdgeReaders edgeReaders;
1933 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1936 /// \ingroup section_io
1937 /// \brief SectionReader for attributes.
1939 /// The lemon format can store multiple attribute set. Each set has
1940 /// the header line \c \@attributes \c attributeset_name, but the
1941 /// attributeset_name may be empty.
1943 /// The attributeset section contains several lines. Each of them starts
1944 /// with an attribute and then a the value for the id.
1946 /// \relates LemonReader
1947 template <typename _Traits = DefaultReaderTraits>
1948 class AttributeReader : public LemonReader::SectionReader {
1949 typedef LemonReader::SectionReader Parent;
1950 typedef _Traits Traits;
1952 /// \brief Constructor.
1954 /// Constructor for AttributeReader. It creates the AttributeReader and
1955 /// attach it into the given LemonReader. The reader process a section
1956 /// only if the \c section_name and the \c _name are the same.
1957 AttributeReader(LemonReader& _reader,
1958 const std::string& _name = std::string())
1959 : Parent(_reader), name(_name) {}
1961 /// \brief Destructor.
1963 /// Destructor for AttributeReader.
1964 virtual ~AttributeReader() {
1965 for (typename Readers::iterator it = readers.begin();
1966 it != readers.end(); ++it) {
1972 AttributeReader(const AttributeReader&);
1973 void operator=(AttributeReader&);
1976 /// \brief Add an attribute reader command for the reader.
1978 /// Add an attribute reader command for the reader.
1979 template <typename Value>
1980 AttributeReader& readAttribute(const std::string& label, Value& value) {
1981 return readAttribute<typename Traits::template Reader<Value> >
1985 /// \brief Add an attribute reader command for the reader.
1987 /// Add an attribute reader command for the reader.
1988 template <typename ItemReader, typename Value>
1989 AttributeReader& readAttribute(const std::string& label, Value& value,
1990 const ItemReader& ir = ItemReader()) {
1991 checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
1992 if (readers.find(label) != readers.end()) {
1994 msg << "Multiple read rule for attribute: " << label;
1995 throw IoParameterError(msg.message());
1997 readers.insert(make_pair(label, new _reader_bits::
1998 ValueReader<Value, ItemReader>(value, ir)));
2004 /// \brief Gives back true when the SectionReader can process
2005 /// the section with the given header line.
2007 /// It gives back true when the header line start with \c \@attributes,
2008 /// and the header line's id and the attributeset's id are the same.
2009 bool header(const std::string& line) {
2010 std::istringstream ls(line);
2011 std::string command;
2013 ls >> command >> id;
2014 return command == "@attributes" && name == id;
2017 /// \brief Reader function of the section.
2019 /// It reads the content of the section.
2020 void read(std::istream& is) {
2022 while (getline(is, line)) {
2023 std::istringstream ls(line);
2026 typename Readers::iterator it = readers.find(id);
2027 if (it != readers.end()) {
2028 it->second->read(ls);
2029 it->second->touch();
2032 for (typename Readers::iterator it = readers.begin();
2033 it != readers.end(); ++it) {
2034 if (!it->second->touched()) {
2036 msg << "Attribute not found in file: " << it->first;
2037 throw IoParameterError(msg.message());
2042 virtual void missing() {
2043 if (readers.empty()) return;
2045 msg << "Attribute section not found in file: @attributes " << name;
2046 throw IoParameterError(msg.message());
2052 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2056 /// \ingroup section_io
2057 /// \brief SectionReader for retrieve what is in the file.
2059 /// SectionReader for retrieve what is in the file. If you want
2060 /// to know which sections, maps and items are in the file
2061 /// use the next code:
2063 /// LemonReader reader("input.lgf");
2064 /// ContentReader content(reader);
2067 class ContentReader : public LemonReader::SectionReader {
2068 typedef LemonReader::SectionReader Parent;
2070 /// \brief Constructor.
2073 ContentReader(LemonReader& _reader) : Parent(_reader) {}
2075 /// \brief Desctructor.
2078 virtual ~ContentReader() {}
2080 /// \brief Gives back how many nodesets are in the file.
2082 /// Gives back how many nodesets are in the file.
2083 int nodeSetNum() const {
2084 return nodesets.size();
2087 /// \brief Gives back the name of nodeset on the indiced position.
2089 /// Gives back the name of nodeset on the indiced position.
2090 std::string nodeSetName(int index) const {
2091 return nodesets[index].name;
2094 /// \brief Gives back the map names of nodeset on the indiced position.
2096 /// Gives back the map names of nodeset on the indiced position.
2097 const std::vector<std::string>& nodeSetMaps(int index) const {
2098 return nodesets[index].items;
2101 /// \brief Gives back how many edgesets are in the file.
2103 /// Gives back how many edgesets are in the file.
2104 int edgeSetNum() const {
2105 return edgesets.size();
2108 /// \brief Gives back the name of edgeset on the indiced position.
2110 /// Gives back the name of edgeset on the indiced position.
2111 std::string edgeSetName(int index) const {
2112 return edgesets[index].name;
2115 /// \brief Gives back the map names of edgeset on the indiced position.
2117 /// Gives back the map names of edgeset on the indiced position.
2118 const std::vector<std::string>& edgeSetMaps(int index) const {
2119 return edgesets[index].items;
2122 /// \brief Gives back how many undirected edgesets are in the file.
2124 /// Gives back how many undirected edgesets are in the file.
2125 int uEdgeSetNum() const {
2126 return uedgesets.size();
2129 /// \brief Gives back the name of undirected edgeset on the indiced
2132 /// Gives back the name of undirected edgeset on the indiced position.
2133 std::string uEdgeSetName(int index) const {
2134 return uedgesets[index].name;
2137 /// \brief Gives back the map names of undirected edgeset on the indiced
2140 /// Gives back the map names of undirected edgeset on the indiced position.
2141 const std::vector<std::string>& uEdgeSetMaps(int index) const {
2142 return uedgesets[index].items;
2145 /// \brief Gives back how many labeled nodes section are in the file.
2147 /// Gives back how many labeled nodes section are in the file.
2148 int nodesNum() const {
2149 return nodes.size();
2152 /// \brief Gives back the name of labeled nodes section on the indiced
2155 /// Gives back the name of labeled nodes section on the indiced position.
2156 std::string nodesName(int index) const {
2157 return nodes[index].name;
2160 /// \brief Gives back the names of the labeled nodes in the indiced
2163 /// Gives back the names of the labeled nodes in the indiced section.
2164 const std::vector<std::string>& nodesItems(int index) const {
2165 return nodes[index].items;
2168 /// \brief Gives back how many labeled edges section are in the file.
2170 /// Gives back how many labeled edges section are in the file.
2171 int edgesNum() const {
2172 return edges.size();
2175 /// \brief Gives back the name of labeled edges section on the indiced
2178 /// Gives back the name of labeled edges section on the indiced position.
2179 std::string edgesName(int index) const {
2180 return edges[index].name;
2183 /// \brief Gives back the names of the labeled edges in the indiced
2186 /// Gives back the names of the labeled edges in the indiced section.
2187 const std::vector<std::string>& edgesItems(int index) const {
2188 return edges[index].items;
2191 /// \brief Gives back how many labeled undirected edges section are
2194 /// Gives back how many labeled undirected edges section are in the file.
2195 int uEdgesNum() const {
2196 return uedges.size();
2199 /// \brief Gives back the name of labeled undirected edges section
2200 /// on the indiced position.
2202 /// Gives back the name of labeled undirected edges section on the
2203 /// indiced position.
2204 std::string uEdgesName(int index) const {
2205 return uedges[index].name;
2208 /// \brief Gives back the names of the labeled undirected edges in
2209 /// the indiced section.
2211 /// Gives back the names of the labeled undirected edges in the
2212 /// indiced section.
2213 const std::vector<std::string>& uEdgesItems(int index) const {
2214 return uedges[index].items;
2218 /// \brief Gives back how many attributes section are in the file.
2220 /// Gives back how many attributes section are in the file.
2221 int attributesNum() const {
2222 return attributes.size();
2225 /// \brief Gives back the name of attributes section on the indiced
2228 /// Gives back the name of attributes section on the indiced position.
2229 std::string attributesName(int index) const {
2230 return attributes[index].name;
2233 /// \brief Gives back the names of the attributes in the indiced section.
2235 /// Gives back the names of the attributes in the indiced section.
2236 const std::vector<std::string>& attributesItems(int index) const {
2237 return attributes[index].items;
2240 const std::vector<std::string>& otherSections() const {
2246 /// \brief Gives back true when the SectionReader can process
2247 /// the section with the given header line.
2249 /// It gives back true when the section is common section.
2250 bool header(const std::string& line) {
2251 std::istringstream ls(line);
2252 std::string command, name;
2253 ls >> command >> name;
2254 if (command == "@nodeset") {
2256 nodesets.push_back(SectionInfo(name));
2257 } else if (command == "@edgeset") {
2259 edgesets.push_back(SectionInfo(name));
2260 } else if (command == "@uedgeset") {
2262 uedgesets.push_back(SectionInfo(name));
2263 } else if (command == "@nodes") {
2265 nodes.push_back(SectionInfo(name));
2266 } else if (command == "@edges") {
2268 edges.push_back(SectionInfo(name));
2269 } else if (command == "@uedges") {
2271 uedges.push_back(SectionInfo(name));
2272 } else if (command == "@attributes") {
2274 attributes.push_back(SectionInfo(name));
2276 sections.push_back(line);
2282 /// \brief Retrieve the items from various sections.
2284 /// Retrieve the items from various sections.
2285 void read(std::istream& is) {
2286 if (current == "@nodeset") {
2287 readMapNames(is, nodesets.back().items);
2288 } else if (current == "@edgeset") {
2289 readMapNames(is, edgesets.back().items);
2290 } else if (current == "@uedgeset") {
2291 readMapNames(is, uedgesets.back().items);
2292 } else if (current == "@nodes") {
2293 readItemNames(is, nodes.back().items);
2294 } else if (current == "@edges") {
2295 readItemNames(is, edges.back().items);
2296 } else if (current == "@uedges") {
2297 readItemNames(is, uedges.back().items);
2298 } else if (current == "@attributes") {
2299 readItemNames(is, attributes.back().items);
2305 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2306 std::string line, name;
2307 std::getline(is, line);
2308 std::istringstream ls(line);
2309 while (ls >> name) {
2310 maps.push_back(name);
2312 while (getline(is, line));
2315 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2316 std::string line, name;
2317 while (std::getline(is, line)) {
2318 std::istringstream ls(line);
2320 maps.push_back(name);
2324 struct SectionInfo {
2326 std::vector<std::string> items;
2328 SectionInfo(const std::string& _name) : name(_name) {}
2331 std::vector<SectionInfo> nodesets;
2332 std::vector<SectionInfo> edgesets;
2333 std::vector<SectionInfo> uedgesets;
2335 std::vector<SectionInfo> nodes;
2336 std::vector<SectionInfo> edges;
2337 std::vector<SectionInfo> uedges;
2339 std::vector<SectionInfo> attributes;
2341 std::vector<std::string> sections;
2343 std::string current;