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 virtual bool header(const std::string& line) {
1128 std::istringstream ls(line);
1129 std::string command;
1131 ls >> command >> id;
1132 return command == "@edgeset" && name == id;
1135 /// \brief Reader function of the section.
1137 /// It reads the content of the section.
1138 virtual void read(std::istream& is) {
1139 if (!nodeLabelReader->isLabelReader()) {
1140 throw DataFormatError("Cannot find nodeset or label map");
1142 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1147 std::istringstream ls(line);
1150 typename MapReaders::iterator it = readers.find(id);
1151 if (it != readers.end()) {
1152 index.push_back(it->second);
1153 it->second->touch();
1155 index.push_back(&skipper);
1157 if (id == "label") {
1158 inverter.reset(index.back()->getInverter());
1159 index.back() = inverter.get();
1163 for (typename MapReaders::iterator it = readers.begin();
1164 it != readers.end(); ++it) {
1165 if (!it->second->touched()) {
1167 msg << "Map not found in file: " << it->first;
1168 throw IoParameterError(msg.message());
1171 while (getline(is, line)) {
1172 std::istringstream ls(line);
1173 Node from = nodeLabelReader->read(ls);
1174 Node to = nodeLabelReader->read(ls);
1175 Edge edge = graph.addEdge(from, to);
1176 for (int i = 0; i < int(index.size()); ++i) {
1177 index[i]->read(ls, edge);
1182 virtual void missing() {
1183 if (readers.empty()) return;
1185 msg << "EdgeSet section not found in file: @edgeset " << name;
1186 throw IoParameterError(msg.message());
1191 /// \brief Returns true if the edgeset can give back the edge by its label.
1193 /// Returns true if the edgeset can give back the edge by its label.
1194 /// It is possible only if an "label" named map was read.
1195 bool isLabelReader() const {
1196 return inverter.get() != 0;
1199 /// \brief Gives back the edge by its label.
1201 /// It reads an id from the stream and gives back which edge belongs to
1202 /// it. It is possible only if there was read an "label" named map.
1203 void readLabel(std::istream& is, Edge& edge) const {
1204 edge = inverter->read(is);
1209 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1216 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1218 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1219 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1222 /// \ingroup section_io
1223 /// \brief SectionReader for reading a undirected graph's edgeset.
1225 /// The lemon format can store multiple undirected edgesets with several
1226 /// maps. The undirected edgeset section's header line is \c \@uedgeset
1227 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1229 /// The first line of the section contains the names of the maps separated
1230 /// with white spaces. Each next lines describes an edge in the edgeset. The
1231 /// line contains the connected nodes' id and the mapped values for each map.
1233 /// The section can handle the directed as a syntactical sugar. Two
1234 /// undirected edge map describes one directed edge map. This two maps
1235 /// are the forward map and the backward map and the names of this map
1236 /// is near the same just with a prefix \c '+' or \c '-' character
1239 /// If the edgeset contains an \c "label" named map then it will be regarded
1240 /// as id map. This map should contain only unique values and when the
1241 /// \c readLabel() member will read a value from the given stream it will
1242 /// give back that uicted edge which is mapped to this value.
1244 /// The undirected edgeset reader needs a node id reader to identify which
1245 /// nodes have to be connected. If a NodeSetReader reads an "label" named
1246 /// map, it will be able to resolve the nodes by ids.
1248 /// \relates LemonReader
1249 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1250 class UEdgeSetReader : public LemonReader::SectionReader {
1251 typedef LemonReader::SectionReader Parent;
1254 typedef _Graph Graph;
1255 typedef _Traits Traits;
1256 typedef typename Graph::Node Node;
1257 typedef typename Graph::Edge Edge;
1258 typedef typename Graph::UEdge UEdge;
1259 typedef typename Traits::Skipper DefaultSkipper;
1261 /// \brief Constructor.
1263 /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1264 /// and attach it into the given LemonReader. The undirected edgeset
1265 /// reader will add the read undirected edges to the given Graph. It
1266 /// will use the given node id reader to read the source and target
1267 /// nodes of the edges. The reader will read the section only if the
1268 /// \c _name and the \c uedgset_name are the same.
1269 template <typename NodeLabelReader>
1270 UEdgeSetReader(LemonReader& _reader,
1272 const NodeLabelReader& _nodeLabelReader,
1273 const std::string& _name = std::string(),
1274 const DefaultSkipper& _skipper = DefaultSkipper())
1275 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1276 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1277 nodeLabelReader.reset(new _reader_bits::
1278 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1280 /// \brief Destructor.
1282 /// Destructor for UEdgeSetReader.
1283 virtual ~UEdgeSetReader() {
1284 for (typename MapReaders::iterator it = readers.begin();
1285 it != readers.end(); ++it) {
1291 UEdgeSetReader(const UEdgeSetReader&);
1292 void operator=(const UEdgeSetReader&);
1296 /// \brief Add a new undirected edge map reader command for the reader.
1298 /// Add a new edge undirected map reader command for the reader.
1299 template <typename Map>
1300 UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
1302 typename Traits::template Reader<typename Map::Value>, Map,
1303 typename _reader_bits::Arg<Map>::Type>(label, map);
1306 template <typename Map>
1307 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
1309 typename Traits::template Reader<typename Map::Value>, Map,
1310 typename _reader_bits::Arg<Map>::Type>(label, map);
1313 /// \brief Add a new undirected edge map reader command for the reader.
1315 /// Add a new edge undirected map reader command for the reader.
1316 template <typename ItemReader, typename Map>
1317 UEdgeSetReader& readUEdgeMap(std::string label, Map& map,
1318 const ItemReader& ir = ItemReader()) {
1319 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1323 template <typename ItemReader, typename Map>
1324 UEdgeSetReader& readUEdgeMap(std::string label, const Map& map,
1325 const ItemReader& ir = ItemReader()) {
1326 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
1332 template <typename ItemReader, typename Map, typename MapParameter>
1333 UEdgeSetReader& _readMap(std::string label, MapParameter map,
1334 const ItemReader& ir = ItemReader()) {
1335 checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1336 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1337 if (readers.find(label) != readers.end()) {
1339 msg << "Multiple read rule for edge map: " << label;
1340 throw IoParameterError(msg.message());
1343 make_pair(label, new _reader_bits::
1344 MapReader<UEdge, Map, ItemReader>(map, ir)));
1350 /// \brief Add a new undirected edge map skipper command for the reader.
1352 /// Add a new undirected edge map skipper command for the reader.
1353 template <typename ItemReader>
1354 UEdgeSetReader& skipUEdgeMap(std::string label,
1355 const ItemReader& ir = ItemReader()) {
1356 if (readers.find(label) != readers.end()) {
1358 msg << "Multiple read rule for node map: " << label;
1359 throw IoParameterError(msg.message());
1361 readers.insert(make_pair(label, new _reader_bits::
1362 SkipReader<UEdge, ItemReader>(ir)));
1366 /// \brief Add a new directed edge map reader command for the reader.
1368 /// Add a new directed edge map reader command for the reader.
1369 template <typename Map>
1370 UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
1372 typename Traits::template Reader<typename Map::Value>, Map,
1373 typename _reader_bits::Arg<Map>::Type>(label, map);
1376 template <typename Map>
1377 UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1379 typename Traits::template Reader<typename Map::Value>, Map,
1380 typename _reader_bits::Arg<Map>::Type>(label, map);
1383 /// \brief Add a new directed edge map reader command for the reader.
1385 /// Add a new directed edge map reader command for the reader.
1386 template <typename ItemReader, typename Map>
1387 UEdgeSetReader& readEdgeMap(std::string label, Map& map,
1388 const ItemReader& ir = ItemReader()) {
1389 return _readDirMap<ItemReader, Map,
1390 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1393 template <typename ItemReader, typename Map>
1394 UEdgeSetReader& readEdgeMap(std::string label, const Map& map,
1395 const ItemReader& ir = ItemReader()) {
1396 return _readDirMap<ItemReader, Map,
1397 typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1402 template <typename ItemReader, typename Map, typename MapParameter>
1403 UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
1404 const ItemReader& ir = ItemReader()) {
1405 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1406 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1407 readUEdgeMap("+" + label,
1408 _reader_bits::forwardComposeMap(graph, map), ir);
1409 readUEdgeMap("-" + label,
1410 _reader_bits::backwardComposeMap(graph, map), ir);
1416 /// \brief Add a new directed edge map skipper command for the reader.
1418 /// Add a new directed edge map skipper command for the reader.
1419 template <typename ItemReader>
1420 UEdgeSetReader& skipEdgeMap(std::string label,
1421 const ItemReader& ir = ItemReader()) {
1422 skipUEdgeMap("+" + label, ir);
1423 skipUEdgeMap("-" + label, ir);
1429 /// \brief Gives back true when the SectionReader can process
1430 /// the section with the given header line.
1432 /// It gives back true when the header line starts with \c \@uedgeset,
1433 /// and the header line's name and the edgeset's name are the same.
1434 virtual bool header(const std::string& line) {
1435 std::istringstream ls(line);
1436 std::string command;
1438 ls >> command >> id;
1439 return command == "@uedgeset" && name == id;
1442 /// \brief Reader function of the section.
1444 /// It reads the content of the section.
1445 virtual void read(std::istream& is) {
1446 if (!nodeLabelReader->isLabelReader()) {
1447 throw DataFormatError("Cannot find nodeset or label map");
1449 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1454 std::istringstream ls(line);
1457 typename MapReaders::iterator it = readers.find(id);
1458 if (it != readers.end()) {
1459 index.push_back(it->second);
1460 it->second->touch();
1462 index.push_back(&skipper);
1464 if (id == "label") {
1465 inverter.reset(index.back()->getInverter());
1466 index.back() = inverter.get();
1469 for (typename MapReaders::iterator it = readers.begin();
1470 it != readers.end(); ++it) {
1471 if (!it->second->touched()) {
1473 msg << "Map not found in file: " << it->first;
1474 throw IoParameterError(msg.message());
1478 while (getline(is, line)) {
1479 std::istringstream ls(line);
1480 Node from = nodeLabelReader->read(ls);
1481 Node to = nodeLabelReader->read(ls);
1482 UEdge edge = graph.addEdge(from, to);
1483 for (int i = 0; i < int(index.size()); ++i) {
1484 index[i]->read(ls, edge);
1489 virtual void missing() {
1490 if (readers.empty()) return;
1492 msg << "UEdgeSet section not found in file: @uedgeset " << name;
1493 throw IoParameterError(msg.message());
1498 /// \brief Returns true if the edgeset can give back the edge by its label.
1500 /// Returns true if the edgeset can give back the undirected edge by its
1501 /// id. It is possible only if an "label" named map was read.
1502 bool isLabelReader() const {
1503 return inverter.get() != 0;
1506 /// \brief Gives back the undirected edge by its label.
1508 /// It reads an id from the stream and gives back which undirected edge
1509 /// belongs to it. It is possible only if there was read an "label" named map.
1510 void readLabel(std::istream& is, UEdge& uEdge) const {
1511 uEdge = inverter->read(is);
1514 /// \brief Gives back the directed edge by its label.
1516 /// It reads an id from the stream and gives back which directed edge
1517 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1518 /// and the undirected edge id. It is possible only if there was read
1519 /// an "label" named map.
1520 void readLabel(std::istream& is, Edge& edge) const {
1523 UEdge uEdge = inverter->read(is);
1525 edge = graph.direct(uEdge, true);
1526 } else if (c == '-') {
1527 edge = graph.direct(uEdge, false);
1529 throw DataFormatError("Wrong id format for edge "
1530 "in undirected edgeset");
1536 typedef std::map<std::string,
1537 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1542 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1544 std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1545 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1548 /// \ingroup section_io
1549 /// \brief SectionReader for reading labeled nodes.
1551 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1552 /// \c nodes_name may be empty.
1554 /// Each line in the section contains the name of the node
1555 /// and then the node id.
1557 /// \relates LemonReader
1558 template <typename _Graph>
1559 class NodeReader : public LemonReader::SectionReader {
1560 typedef LemonReader::SectionReader Parent;
1561 typedef _Graph Graph;
1562 typedef typename Graph::Node Node;
1565 /// \brief Constructor.
1567 /// Constructor for NodeReader. It creates the NodeReader and
1568 /// attach it into the given LemonReader. It will use the given
1569 /// node id reader to give back the nodes. The reader will read the
1570 /// section only if the \c _name and the \c nodes_name are the same.
1571 template <typename _LabelReader>
1572 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1573 const std::string& _name = std::string())
1574 : Parent(_reader), name(_name) {
1575 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1576 nodeLabelReader.reset(new _reader_bits::
1577 LabelReader<Node, _LabelReader>(_labelReader));
1580 /// \brief Destructor.
1582 /// Destructor for NodeReader.
1583 virtual ~NodeReader() {}
1586 NodeReader(const NodeReader&);
1587 void operator=(const NodeReader&);
1591 /// \brief Add a node reader command for the NodeReader.
1593 /// Add a node reader command for the NodeReader.
1594 void readNode(std::string label, Node& item) {
1595 if (readers.find(label) != readers.end()) {
1597 msg << "Multiple read rule for node: " << label;
1598 throw IoParameterError(msg.message());
1600 readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
1605 /// \brief Gives back true when the SectionReader can process
1606 /// the section with the given header line.
1608 /// It gives back true when the header line start with \c \@nodes,
1609 /// and the header line's name and the reader's name are the same.
1610 virtual bool header(const std::string& line) {
1611 std::istringstream ls(line);
1612 std::string command;
1614 ls >> command >> id;
1615 return command == "@nodes" && name == id;
1618 /// \brief Reader function of the section.
1620 /// It reads the content of the section.
1621 virtual void read(std::istream& is) {
1622 if (!nodeLabelReader->isLabelReader()) {
1623 throw DataFormatError("Cannot find nodeset or label map");
1626 while (getline(is, line)) {
1627 std::istringstream ls(line);
1630 typename NodeReaders::iterator it = readers.find(id);
1631 if (it != readers.end()) {
1632 it->second.read(nodeLabelReader->read(ls));
1636 for (typename NodeReaders::iterator it = readers.begin();
1637 it != readers.end(); ++it) {
1638 if (!it->second.touched()) {
1640 msg << "Node not found in file: " << it->first;
1641 throw IoParameterError(msg.message());
1646 virtual void missing() {
1647 if (readers.empty()) return;
1649 msg << "Nodes section not found in file: @nodes " << name;
1650 throw IoParameterError(msg.message());
1657 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1658 NodeReaders readers;
1659 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1662 /// \ingroup section_io
1663 /// \brief SectionReader for reading labeled edges.
1665 /// The edges section's header line is \c \@edges \c edges_name, but the
1666 /// \c edges_name may be empty.
1668 /// Each line in the section contains the name of the edge
1669 /// and then the edge id.
1671 /// \relates LemonReader
1672 template <typename _Graph>
1673 class EdgeReader : public LemonReader::SectionReader {
1674 typedef LemonReader::SectionReader Parent;
1675 typedef _Graph Graph;
1676 typedef typename Graph::Edge Edge;
1679 /// \brief Constructor.
1681 /// Constructor for EdgeReader. It creates the EdgeReader and
1682 /// attach it into the given LemonReader. It will use the given
1683 /// edge id reader to give back the edges. The reader will read the
1684 /// section only if the \c _name and the \c edges_name are the same.
1685 template <typename _LabelReader>
1686 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1687 const std::string& _name = std::string())
1688 : Parent(_reader), name(_name) {
1689 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1690 edgeLabelReader.reset(new _reader_bits::
1691 LabelReader<Edge, _LabelReader>(_labelReader));
1694 /// \brief Destructor.
1696 /// Destructor for EdgeReader.
1697 virtual ~EdgeReader() {}
1699 EdgeReader(const EdgeReader&);
1700 void operator=(const EdgeReader&);
1704 /// \brief Add an edge reader command for the EdgeReader.
1706 /// Add an edge reader command for the EdgeReader.
1707 void readEdge(std::string label, Edge& item) {
1708 if (readers.find(label) != readers.end()) {
1710 msg << "Multiple read rule for edge: " << label;
1711 throw IoParameterError(msg.message());
1713 readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1718 /// \brief Gives back true when the SectionReader can process
1719 /// the section with the given header line.
1721 /// It gives back true when the header line start with \c \@edges,
1722 /// and the header line's name and the reader's name are the same.
1723 virtual bool header(const std::string& line) {
1724 std::istringstream ls(line);
1725 std::string command;
1727 ls >> command >> id;
1728 return command == "@edges" && name == id;
1731 /// \brief Reader function of the section.
1733 /// It reads the content of the section.
1734 virtual void read(std::istream& is) {
1735 if (!edgeLabelReader->isLabelReader()) {
1736 throw DataFormatError("Cannot find edgeset or label map");
1739 while (getline(is, line)) {
1740 std::istringstream ls(line);
1743 typename EdgeReaders::iterator it = readers.find(id);
1744 if (it != readers.end()) {
1745 it->second.read(edgeLabelReader->read(ls));
1749 for (typename EdgeReaders::iterator it = readers.begin();
1750 it != readers.end(); ++it) {
1751 if (!it->second.touched()) {
1753 msg << "Edge not found in file: " << it->first;
1754 throw IoParameterError(msg.message());
1759 virtual void missing() {
1760 if (readers.empty()) return;
1762 msg << "Edges section not found in file: @edges " << name;
1763 throw IoParameterError(msg.message());
1770 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1771 EdgeReaders readers;
1772 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1775 /// \ingroup section_io
1776 /// \brief SectionReader for reading labeled undirected edges.
1778 /// The undirected edges section's header line is \c \@uedges
1779 /// \c uedges_name, but the \c uedges_name may be empty.
1781 /// Each line in the section contains the name of the undirected edge
1782 /// and then the undirected edge id.
1784 /// \relates LemonReader
1785 template <typename _Graph>
1786 class UEdgeReader : public LemonReader::SectionReader {
1787 typedef LemonReader::SectionReader Parent;
1788 typedef _Graph Graph;
1789 typedef typename Graph::Edge Edge;
1790 typedef typename Graph::UEdge UEdge;
1793 /// \brief Constructor.
1795 /// Constructor for UEdgeReader. It creates the UEdgeReader and
1796 /// attach it into the given LemonReader. It will use the given
1797 /// undirected edge id reader to give back the edges. The reader will
1798 /// read the section only if the \c _name and the \c uedges_name are
1800 template <typename _LabelReader>
1801 UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1802 const std::string& _name = std::string())
1803 : Parent(_reader), name(_name) {
1804 checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1805 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1806 uEdgeLabelReader.reset(new _reader_bits::
1807 LabelReader<UEdge, _LabelReader>(_labelReader));
1808 edgeLabelReader.reset(new _reader_bits::
1809 LabelReader<Edge, _LabelReader>(_labelReader));
1812 /// \brief Destructor.
1814 /// Destructor for UEdgeReader.
1815 virtual ~UEdgeReader() {}
1817 UEdgeReader(const UEdgeReader&);
1818 void operator=(const UEdgeReader&);
1822 /// \brief Add an undirected edge reader command for the UEdgeReader.
1824 /// Add an undirected edge reader command for the UEdgeReader.
1825 void readUEdge(std::string label, UEdge& item) {
1826 if (uEdgeReaders.find(label) != uEdgeReaders.end()) {
1828 msg << "Multiple read rule for undirected edge: " << label;
1829 throw IoParameterError(msg.message());
1831 uEdgeReaders.insert(make_pair(label, _reader_bits::
1832 ItemStore<UEdge>(item)));
1835 /// \brief Add an edge reader command for the UEdgeReader.
1837 /// Add an edge reader command for the UEdgeReader.
1838 void readEdge(std::string label, Edge& item) {
1839 if (edgeReaders.find(label) != edgeReaders.end()) {
1841 msg << "Multiple read rule for edge: " << label;
1842 throw IoParameterError(msg.message());
1844 edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1849 /// \brief Gives back true when the SectionReader can process
1850 /// the section with the given header line.
1852 /// It gives back true when the header line start with \c \@edges,
1853 /// and the header line's name and the reader's name are the same.
1854 virtual bool header(const std::string& line) {
1855 std::istringstream ls(line);
1856 std::string command;
1858 ls >> command >> id;
1859 return command == "@uedges" && name == id;
1862 /// \brief Reader function of the section.
1864 /// It reads the content of the section.
1865 virtual void read(std::istream& is) {
1866 if (!edgeLabelReader->isLabelReader()) {
1867 throw DataFormatError("Cannot find undirected edgeset or label map");
1869 if (!uEdgeLabelReader->isLabelReader()) {
1870 throw DataFormatError("Cannot find undirected edgeset or label map");
1873 while (getline(is, line)) {
1874 std::istringstream ls(line);
1878 typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1879 if (it != uEdgeReaders.end()) {
1880 it->second.read(uEdgeLabelReader->read(ls));
1885 typename EdgeReaders::iterator it = edgeReaders.find(id);
1886 if (it != edgeReaders.end()) {
1887 it->second.read(edgeLabelReader->read(ls));
1893 for (typename EdgeReaders::iterator it = edgeReaders.begin();
1894 it != edgeReaders.end(); ++it) {
1895 if (!it->second.touched()) {
1897 msg << "Edge not found in file: " << it->first;
1898 throw IoParameterError(msg.message());
1901 for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1902 it != uEdgeReaders.end(); ++it) {
1903 if (!it->second.touched()) {
1905 msg << "UEdge not found in file: " << it->first;
1906 throw IoParameterError(msg.message());
1911 virtual void missing() {
1912 if (edgeReaders.empty() && uEdgeReaders.empty()) return;
1914 msg << "UEdges section not found in file: @uedges " << name;
1915 throw IoParameterError(msg.message());
1922 typedef std::map<std::string,
1923 _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1924 UEdgeReaders uEdgeReaders;
1925 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
1927 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1928 EdgeReaders edgeReaders;
1929 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1932 /// \ingroup section_io
1933 /// \brief SectionReader for attributes.
1935 /// The lemon format can store multiple attribute set. Each set has
1936 /// the header line \c \@attributes \c attributeset_name, but the
1937 /// attributeset_name may be empty.
1939 /// The attributeset section contains several lines. Each of them starts
1940 /// with an attribute and then a the value for the id.
1942 /// \relates LemonReader
1943 template <typename _Traits = DefaultReaderTraits>
1944 class AttributeReader : public LemonReader::SectionReader {
1945 typedef LemonReader::SectionReader Parent;
1946 typedef _Traits Traits;
1948 /// \brief Constructor.
1950 /// Constructor for AttributeReader. It creates the AttributeReader and
1951 /// attach it into the given LemonReader. The reader process a section
1952 /// only if the \c section_name and the \c _name are the same.
1953 AttributeReader(LemonReader& _reader,
1954 const std::string& _name = std::string())
1955 : Parent(_reader), name(_name) {}
1957 /// \brief Destructor.
1959 /// Destructor for AttributeReader.
1960 virtual ~AttributeReader() {
1961 for (typename Readers::iterator it = readers.begin();
1962 it != readers.end(); ++it) {
1968 AttributeReader(const AttributeReader&);
1969 void operator=(AttributeReader&);
1972 /// \brief Add an attribute reader command for the reader.
1974 /// Add an attribute reader command for the reader.
1975 template <typename Value>
1976 AttributeReader& readAttribute(const std::string& label, Value& value) {
1977 return readAttribute<typename Traits::template Reader<Value> >
1981 /// \brief Add an attribute reader command for the reader.
1983 /// Add an attribute reader command for the reader.
1984 template <typename ItemReader, typename Value>
1985 AttributeReader& readAttribute(const std::string& label, Value& value,
1986 const ItemReader& ir = ItemReader()) {
1987 checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
1988 if (readers.find(label) != readers.end()) {
1990 msg << "Multiple read rule for attribute: " << label;
1991 throw IoParameterError(msg.message());
1993 readers.insert(make_pair(label, new _reader_bits::
1994 ValueReader<Value, ItemReader>(value, ir)));
2000 /// \brief Gives back true when the SectionReader can process
2001 /// the section with the given header line.
2003 /// It gives back true when the header line start with \c \@attributes,
2004 /// and the header line's id and the attributeset's id are the same.
2005 bool header(const std::string& line) {
2006 std::istringstream ls(line);
2007 std::string command;
2009 ls >> command >> id;
2010 return command == "@attributes" && name == id;
2013 /// \brief Reader function of the section.
2015 /// It reads the content of the section.
2016 void read(std::istream& is) {
2018 while (getline(is, line)) {
2019 std::istringstream ls(line);
2022 typename Readers::iterator it = readers.find(id);
2023 if (it != readers.end()) {
2024 it->second->read(ls);
2025 it->second->touch();
2028 for (typename Readers::iterator it = readers.begin();
2029 it != readers.end(); ++it) {
2030 if (!it->second->touched()) {
2032 msg << "Attribute not found in file: " << it->first;
2033 throw IoParameterError(msg.message());
2038 virtual void missing() {
2039 if (readers.empty()) return;
2041 msg << "Attribute section not found in file: @attributes " << name;
2042 throw IoParameterError(msg.message());
2048 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2052 /// \ingroup section_io
2053 /// \brief SectionReader for retrieve what is in the file.
2055 /// SectionReader for retrieve what is in the file. If you want
2056 /// to know which sections, maps and items are in the file
2057 /// use the next code:
2059 /// LemonReader reader("input.lgf");
2060 /// ContentReader content(reader);
2063 class ContentReader : public LemonReader::SectionReader {
2064 typedef LemonReader::SectionReader Parent;
2066 /// \brief Constructor.
2069 ContentReader(LemonReader& _reader) : Parent(_reader) {}
2071 /// \brief Desctructor.
2074 virtual ~ContentReader() {}
2076 /// \brief Gives back how many nodesets are in the file.
2078 /// Gives back how many nodesets are in the file.
2079 int nodeSetNum() const {
2080 return nodesets.size();
2083 /// \brief Gives back the name of nodeset on the indiced position.
2085 /// Gives back the name of nodeset on the indiced position.
2086 std::string nodeSetName(int index) const {
2087 return nodesets[index].name;
2090 /// \brief Gives back the map names of nodeset on the indiced position.
2092 /// Gives back the map names of nodeset on the indiced position.
2093 const std::vector<std::string>& nodeSetMaps(int index) const {
2094 return nodesets[index].items;
2097 /// \brief Gives back how many edgesets are in the file.
2099 /// Gives back how many edgesets are in the file.
2100 int edgeSetNum() const {
2101 return edgesets.size();
2104 /// \brief Gives back the name of edgeset on the indiced position.
2106 /// Gives back the name of edgeset on the indiced position.
2107 std::string edgeSetName(int index) const {
2108 return edgesets[index].name;
2111 /// \brief Gives back the map names of edgeset on the indiced position.
2113 /// Gives back the map names of edgeset on the indiced position.
2114 const std::vector<std::string>& edgeSetMaps(int index) const {
2115 return edgesets[index].items;
2118 /// \brief Gives back how many undirected edgesets are in the file.
2120 /// Gives back how many undirected edgesets are in the file.
2121 int uEdgeSetNum() const {
2122 return uedgesets.size();
2125 /// \brief Gives back the name of undirected edgeset on the indiced
2128 /// Gives back the name of undirected edgeset on the indiced position.
2129 std::string uEdgeSetName(int index) const {
2130 return uedgesets[index].name;
2133 /// \brief Gives back the map names of undirected edgeset on the indiced
2136 /// Gives back the map names of undirected edgeset on the indiced position.
2137 const std::vector<std::string>& uEdgeSetMaps(int index) const {
2138 return uedgesets[index].items;
2141 /// \brief Gives back how many labeled nodes section are in the file.
2143 /// Gives back how many labeled nodes section are in the file.
2144 int nodesNum() const {
2145 return nodes.size();
2148 /// \brief Gives back the name of labeled nodes section on the indiced
2151 /// Gives back the name of labeled nodes section on the indiced position.
2152 std::string nodesName(int index) const {
2153 return nodes[index].name;
2156 /// \brief Gives back the names of the labeled nodes in the indiced
2159 /// Gives back the names of the labeled nodes in the indiced section.
2160 const std::vector<std::string>& nodesItems(int index) const {
2161 return nodes[index].items;
2164 /// \brief Gives back how many labeled edges section are in the file.
2166 /// Gives back how many labeled edges section are in the file.
2167 int edgesNum() const {
2168 return edges.size();
2171 /// \brief Gives back the name of labeled edges section on the indiced
2174 /// Gives back the name of labeled edges section on the indiced position.
2175 std::string edgesName(int index) const {
2176 return edges[index].name;
2179 /// \brief Gives back the names of the labeled edges in the indiced
2182 /// Gives back the names of the labeled edges in the indiced section.
2183 const std::vector<std::string>& edgesItems(int index) const {
2184 return edges[index].items;
2187 /// \brief Gives back how many labeled undirected edges section are
2190 /// Gives back how many labeled undirected edges section are in the file.
2191 int uEdgesNum() const {
2192 return uedges.size();
2195 /// \brief Gives back the name of labeled undirected edges section
2196 /// on the indiced position.
2198 /// Gives back the name of labeled undirected edges section on the
2199 /// indiced position.
2200 std::string uEdgesName(int index) const {
2201 return uedges[index].name;
2204 /// \brief Gives back the names of the labeled undirected edges in
2205 /// the indiced section.
2207 /// Gives back the names of the labeled undirected edges in the
2208 /// indiced section.
2209 const std::vector<std::string>& uEdgesItems(int index) const {
2210 return uedges[index].items;
2214 /// \brief Gives back how many attributes section are in the file.
2216 /// Gives back how many attributes section are in the file.
2217 int attributesNum() const {
2218 return attributes.size();
2221 /// \brief Gives back the name of attributes section on the indiced
2224 /// Gives back the name of attributes section on the indiced position.
2225 std::string attributesName(int index) const {
2226 return attributes[index].name;
2229 /// \brief Gives back the names of the attributes in the indiced section.
2231 /// Gives back the names of the attributes in the indiced section.
2232 const std::vector<std::string>& attributesItems(int index) const {
2233 return attributes[index].items;
2236 const std::vector<std::string>& otherSections() const {
2242 /// \brief Gives back true when the SectionReader can process
2243 /// the section with the given header line.
2245 /// It gives back true when the section is common section.
2246 bool header(const std::string& line) {
2247 std::istringstream ls(line);
2248 std::string command, name;
2249 ls >> command >> name;
2250 if (command == "@nodeset") {
2252 nodesets.push_back(SectionInfo(name));
2253 } else if (command == "@edgeset") {
2255 edgesets.push_back(SectionInfo(name));
2256 } else if (command == "@uedgeset") {
2258 uedgesets.push_back(SectionInfo(name));
2259 } else if (command == "@nodes") {
2261 nodes.push_back(SectionInfo(name));
2262 } else if (command == "@edges") {
2264 edges.push_back(SectionInfo(name));
2265 } else if (command == "@uedges") {
2267 uedges.push_back(SectionInfo(name));
2268 } else if (command == "@attributes") {
2270 attributes.push_back(SectionInfo(name));
2272 sections.push_back(line);
2278 /// \brief Retrieve the items from various sections.
2280 /// Retrieve the items from various sections.
2281 void read(std::istream& is) {
2282 if (current == "@nodeset") {
2283 readMapNames(is, nodesets.back().items);
2284 } else if (current == "@edgeset") {
2285 readMapNames(is, edgesets.back().items);
2286 } else if (current == "@uedgeset") {
2287 readMapNames(is, uedgesets.back().items);
2288 } else if (current == "@nodes") {
2289 readItemNames(is, nodes.back().items);
2290 } else if (current == "@edges") {
2291 readItemNames(is, edges.back().items);
2292 } else if (current == "@uedges") {
2293 readItemNames(is, uedges.back().items);
2294 } else if (current == "@attributes") {
2295 readItemNames(is, attributes.back().items);
2301 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2302 std::string line, name;
2303 std::getline(is, line);
2304 std::istringstream ls(line);
2305 while (ls >> name) {
2306 maps.push_back(name);
2308 while (getline(is, line));
2311 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2312 std::string line, name;
2313 while (std::getline(is, line)) {
2314 std::istringstream ls(line);
2316 maps.push_back(name);
2320 struct SectionInfo {
2322 std::vector<std::string> items;
2324 SectionInfo(const std::string& _name) : name(_name) {}
2327 std::vector<SectionInfo> nodesets;
2328 std::vector<SectionInfo> edgesets;
2329 std::vector<SectionInfo> uedgesets;
2331 std::vector<SectionInfo> nodes;
2332 std::vector<SectionInfo> edges;
2333 std::vector<SectionInfo> uedges;
2335 std::vector<SectionInfo> attributes;
2337 std::vector<std::string> sections;
2339 std::string current;