28 #include <algorithm> |
28 #include <algorithm> |
29 #include <map> |
29 #include <map> |
30 #include <memory> |
30 #include <memory> |
31 |
31 |
32 #include <lemon/error.h> |
32 #include <lemon/error.h> |
33 #include "item_reader.h" |
33 #include <lemon/bits/item_reader.h> |
34 |
34 |
35 |
35 |
36 namespace lemon { |
36 namespace lemon { |
37 |
37 |
38 /// \addtogroup io_group |
38 /// \ingroup io_group |
39 /// @{ |
|
40 |
|
41 /// \brief Lemon Format reader class. |
39 /// \brief Lemon Format reader class. |
42 /// |
40 /// |
|
41 /// The Lemon Format contains several sections. We do not want to |
|
42 /// determine what sections are in a lemon file we give only a framework |
|
43 /// to read a section oriented format. |
|
44 /// |
|
45 /// In the Lemon Format each section starts with a line contains a \c \@ |
|
46 /// character on the first not white space position. This line is the |
|
47 /// header line of the section. Each next lines belong to this section |
|
48 /// while it does not starts with \c \@ character. This line can start a |
|
49 /// new section or if it can close the file with the \c \@end line. |
|
50 /// The file format ignore the empty lines and it may contain comments |
|
51 /// started with a \c # character to the end of the line. |
|
52 /// |
|
53 /// The framework provides an abstract LemonReader::SectionReader class |
|
54 /// what defines the interface of a SectionReader. The SectionReader |
|
55 /// has the \c header() member function what get a header line string and |
|
56 /// decides if it want to process the next section. Several SectionReaders |
|
57 /// can be attached to an LemonReader and the first attached what can |
|
58 /// process the section will be used. Its \c read() member will called |
|
59 /// with a stream contains the section. From this stream the empty lines |
|
60 /// and comments are filtered out. |
|
61 /// |
|
62 /// \relates GraphReader |
|
63 /// \relates NodeSetReader |
|
64 /// \relates EdgeSetReader |
|
65 /// \relates NodesReader |
|
66 /// \relates EdgesReader |
|
67 /// \relates AttributeReader |
43 class LemonReader { |
68 class LemonReader { |
44 private: |
69 private: |
45 |
70 |
46 class FilterStreamBuf : public std::streambuf { |
71 class FilterStreamBuf : public std::streambuf { |
47 public: |
72 public: |
183 } |
208 } |
184 }; |
209 }; |
185 |
210 |
186 public: |
211 public: |
187 |
212 |
|
213 /// \brief Abstract base class for reading a section. |
|
214 /// |
|
215 /// This class has an \c header() member function what get a |
|
216 /// header line string and decides if it want to process the next |
|
217 /// section. Several SectionReaders can be attached to an LemonReader |
|
218 /// and the first attached what can process the section will be used. |
|
219 /// Its \c read() member will called with a stream contains the section. |
|
220 /// From this stream the empty lines and comments are filtered out. |
188 class SectionReader { |
221 class SectionReader { |
189 public: |
222 friend class LemonReader; |
190 /// \e |
223 protected: |
|
224 /// \brief Constructor for SectionReader. |
|
225 /// |
|
226 /// Constructor for SectionReader. It attach this reader to |
|
227 /// the given LemonReader. |
|
228 SectionReader(LemonReader& reader) { |
|
229 reader.attach(*this); |
|
230 } |
|
231 |
|
232 /// \brief Gives back true when the SectionReader can process |
|
233 /// the section with the given header line. |
|
234 /// |
|
235 /// It gives back true when the SectionReader can process |
|
236 /// the section with the given header line. |
191 virtual bool header(const std::string& line) = 0; |
237 virtual bool header(const std::string& line) = 0; |
192 /// \e |
238 |
|
239 /// \brief Reader function of the section. |
|
240 /// |
|
241 /// It reads the content of the section. |
193 virtual void read(std::istream& is) = 0; |
242 virtual void read(std::istream& is) = 0; |
194 }; |
243 }; |
195 |
244 |
196 /// \e |
245 /// \brief Constructor for LemonReader. |
|
246 /// |
|
247 /// Constructor for LemonReader which reads from the given stream. |
197 LemonReader(std::istream& _is) |
248 LemonReader(std::istream& _is) |
198 : is(&_is), own_is(false) {} |
249 : is(&_is), own_is(false) {} |
199 |
250 |
|
251 /// \brief Constructor for LemonReader. |
|
252 /// |
|
253 /// Constructor for LemonReader which reads from the given file. |
200 LemonReader(const std::string& filename) |
254 LemonReader(const std::string& filename) |
201 : is(0), own_is(true) { |
255 : is(0), own_is(true) { |
202 is = new std::ifstream(filename.c_str()); |
256 is = new std::ifstream(filename.c_str()); |
203 } |
257 } |
204 |
258 |
205 |
259 /// \brief Desctructor for LemonReader. |
|
260 /// |
|
261 /// Desctructor for LemonReader. |
206 ~LemonReader() { |
262 ~LemonReader() { |
207 if (own_is) { |
263 if (own_is) { |
208 delete is; |
264 delete is; |
209 } |
265 } |
210 } |
266 } |
211 |
267 |
212 private: |
268 private: |
213 LemonReader(const LemonReader&); |
269 LemonReader(const LemonReader&); |
214 void operator=(const LemonReader&); |
270 void operator=(const LemonReader&); |
215 |
271 |
216 public: |
|
217 |
|
218 /// \e |
|
219 void attach(SectionReader& reader) { |
272 void attach(SectionReader& reader) { |
220 readers.push_back(&reader); |
273 readers.push_back(&reader); |
221 } |
274 } |
222 |
275 |
223 /// \e |
276 public: |
224 void detach(SectionReader& reader) { |
277 /// \brief Executes the LemonReader. |
225 std::vector<SectionReader*>::iterator it = |
278 /// |
226 std::find(readers.begin(), readers.end(), &reader); |
279 /// It executes the LemonReader. |
227 if (it != readers.end()) { |
|
228 readers.erase(it); |
|
229 } |
|
230 } |
|
231 |
|
232 /// \e |
|
233 void run() { |
280 void run() { |
234 int line_num = 0; |
281 int line_num = 0; |
235 std::string line; |
282 std::string line; |
236 try { |
283 try { |
237 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) { |
284 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) { |
477 Reader reader; |
534 Reader reader; |
478 }; |
535 }; |
479 |
536 |
480 }; |
537 }; |
481 |
538 |
482 |
539 /// \ingroup io_group |
|
540 /// \brief SectionReader for reading a graph's nodeset. |
|
541 /// |
|
542 /// The lemon format can store multiple graph nodesets with several maps. |
|
543 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the |
|
544 /// \c nodeset_id may be empty. |
|
545 /// |
|
546 /// The first line of the section contains the names of the maps separated |
|
547 /// with white spaces. Each next lines describes a node in the nodeset, and |
|
548 /// contains the mapped values for each map. |
|
549 /// |
|
550 /// If the nodeset contains an \c "id" named map then it will be regarded |
|
551 /// as id map. This map should contain only unique values and when the |
|
552 /// \c readId() member will read a value from the given stream it will |
|
553 /// give back that node which is mapped to this value. |
|
554 /// |
|
555 /// \relates LemonReader |
483 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
556 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
484 class NodeSetReader : public CommonSectionReaderBase { |
557 class NodeSetReader : public CommonSectionReaderBase { |
485 typedef CommonSectionReaderBase Parent; |
558 typedef CommonSectionReaderBase Parent; |
486 public: |
559 public: |
487 |
560 |
488 typedef _Graph Graph; |
561 typedef _Graph Graph; |
489 typedef _Traits Traits; |
562 typedef _Traits Traits; |
490 typedef typename Graph::Node Item; |
563 typedef typename Graph::Node Item; |
491 typedef typename Traits::Skipper DefaultSkipper; |
564 typedef typename Traits::Skipper DefaultSkipper; |
492 |
565 |
|
566 /// \brief Constructor. |
|
567 /// |
|
568 /// Constructor for NodeSetReader. It creates the NodeSetReader and |
|
569 /// attach it into the given LemonReader. The nodeset reader will |
|
570 /// add the readed nodes to the given Graph. The reader will read |
|
571 /// the section when the \c section_id and the \c _id are the same. |
493 NodeSetReader(LemonReader& _reader, Graph& _graph, |
572 NodeSetReader(LemonReader& _reader, Graph& _graph, |
494 const std::string& _id = std::string(), |
573 const std::string& _id = std::string(), |
495 const DefaultSkipper& _defreader = DefaultSkipper()) |
574 const DefaultSkipper& _skipper = DefaultSkipper()) |
496 : graph(_graph), id(_id), skipper(_defreader) { |
575 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} |
497 _reader.attach(*this); |
576 |
498 } |
577 |
499 |
578 /// \brief Destructor. |
|
579 /// |
|
580 /// Destructor for NodeSetReader. |
500 virtual ~NodeSetReader() { |
581 virtual ~NodeSetReader() { |
501 for (typename MapReaders::iterator it = readers.begin(); |
582 for (typename MapReaders::iterator it = readers.begin(); |
502 it != readers.end(); ++it) { |
583 it != readers.end(); ++it) { |
503 delete it->second; |
584 delete it->second; |
504 } |
585 } |
605 SkipReader<Item, DefaultSkipper> skipper; |
704 SkipReader<Item, DefaultSkipper> skipper; |
606 |
705 |
607 std::auto_ptr<InverterBase<Item> > inverter; |
706 std::auto_ptr<InverterBase<Item> > inverter; |
608 }; |
707 }; |
609 |
708 |
610 |
709 /// \ingroup io_group |
611 |
710 /// \brief SectionReader for reading a graph's edgeset. |
612 /// \e |
711 /// |
|
712 /// The lemon format can store multiple graph edgesets with several maps. |
|
713 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the |
|
714 /// \c edgeset_id may be empty. |
|
715 /// |
|
716 /// The first line of the section contains the names of the maps separated |
|
717 /// with white spaces. Each next lines describes a node in the nodeset. The |
|
718 /// line contains the two nodes' id and the mapped values for each map. |
|
719 /// |
|
720 /// If the edgeset contains an \c "id" named map then it will be regarded |
|
721 /// as id map. This map should contain only unique values and when the |
|
722 /// \c readId() member will read a value from the given stream it will |
|
723 /// give back that edge which is mapped to this value. |
|
724 /// |
|
725 /// The edgeset reader needs a node id reader to identify which nodes |
|
726 /// have to be connected. If a NodeSetReader reads an "id" named map, |
|
727 /// it will be able to resolve the nodes by ids. |
|
728 /// |
|
729 /// \relates LemonReader |
613 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
730 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
614 class EdgeSetReader : public CommonSectionReaderBase { |
731 class EdgeSetReader : public CommonSectionReaderBase { |
615 typedef CommonSectionReaderBase Parent; |
732 typedef CommonSectionReaderBase Parent; |
616 public: |
733 public: |
617 |
734 |
618 typedef _Graph Graph; |
735 typedef _Graph Graph; |
619 typedef _Traits Traits; |
736 typedef _Traits Traits; |
620 typedef typename Graph::Edge Item; |
737 typedef typename Graph::Edge Item; |
621 typedef typename Traits::Skipper DefaultSkipper; |
738 typedef typename Traits::Skipper DefaultSkipper; |
622 |
739 |
623 template <typename Resolver> |
740 /// \brief Constructor. |
|
741 /// |
|
742 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and |
|
743 /// attach it into the given LemonReader. The edgeset reader will |
|
744 /// add the readed edges to the given Graph. It will use the given |
|
745 /// node id reader to read the source and target nodes of the edges. |
|
746 /// The reader will read the section only if the \c _id and the |
|
747 /// \c edgset_id are the same. |
|
748 template <typename NodeIdReader> |
624 EdgeSetReader(LemonReader& _reader, Graph& _graph, |
749 EdgeSetReader(LemonReader& _reader, Graph& _graph, |
625 const Resolver& _nodeResolver, |
750 const NodeIdReader& _nodeIdReader, |
626 const std::string& _id = std::string(), |
751 const std::string& _id = std::string(), |
627 const DefaultSkipper& _defreader = DefaultSkipper()) |
752 const DefaultSkipper& _skipper = DefaultSkipper()) |
628 : graph(_graph), id(_id), skipper(_defreader), |
753 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper), |
629 nodeResolver(new ResolverReader<typename Graph::Node, Resolver> |
754 nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader> |
630 (_nodeResolver)) { |
755 (_nodeIdReader)) {} |
631 _reader.attach(*this); |
756 |
632 } |
757 /// \brief Destructor. |
633 |
758 /// |
|
759 /// Destructor for EdgeSetReader. |
634 virtual ~EdgeSetReader() { |
760 virtual ~EdgeSetReader() { |
635 for (typename MapReaders::iterator it = readers.begin(); |
761 for (typename MapReaders::iterator it = readers.begin(); |
636 it != readers.end(); ++it) { |
762 it != readers.end(); ++it) { |
637 delete it->second; |
763 delete it->second; |
638 } |
764 } |
642 EdgeSetReader(const EdgeSetReader&); |
768 EdgeSetReader(const EdgeSetReader&); |
643 void operator=(const EdgeSetReader&); |
769 void operator=(const EdgeSetReader&); |
644 |
770 |
645 public: |
771 public: |
646 |
772 |
647 /// \brief Add a new node map reader command for the reader. |
773 /// \brief Add a new edge map reader command for the reader. |
648 /// |
774 /// |
649 /// Add a new node map reader command for the reader. |
775 /// Add a new edge map reader command for the reader. |
650 template <typename Map> |
776 template <typename Map> |
651 EdgeSetReader& readMap(std::string name, Map& map) { |
777 EdgeSetReader& readMap(std::string name, Map& map) { |
652 return readMap<typename Traits:: |
778 return readMap<typename Traits:: |
653 template Reader<typename Map::Value>, Map>(name, map); |
779 template Reader<typename Map::Value>, Map>(name, map); |
654 } |
780 } |
655 |
781 |
656 /// \brief Add a new node map reader command for the reader. |
782 /// \brief Add a new edge map reader command for the reader. |
657 /// |
783 /// |
658 /// Add a new node map reader command for the reader. |
784 /// Add a new edge map reader command for the reader. |
659 template <typename Reader, typename Map> |
785 template <typename Reader, typename Map> |
660 EdgeSetReader& readMap(std::string name, Map& map, |
786 EdgeSetReader& readMap(std::string name, Map& map, |
661 const Reader& reader = Reader()) { |
787 const Reader& reader = Reader()) { |
662 if (readers.find(name) != readers.end()) { |
788 if (readers.find(name) != readers.end()) { |
663 ErrorMessage msg; |
789 ErrorMessage msg; |
712 index.back() = inverter.get(); |
846 index.back() = inverter.get(); |
713 } |
847 } |
714 } |
848 } |
715 while (getline(is, line)) { |
849 while (getline(is, line)) { |
716 std::istringstream ls(line); |
850 std::istringstream ls(line); |
717 typename Graph::Node from = nodeResolver->resolve(ls); |
851 typename Graph::Node from = nodeIdReader->read(ls); |
718 typename Graph::Node to = nodeResolver->resolve(ls); |
852 typename Graph::Node to = nodeIdReader->read(ls); |
719 typename Graph::Edge edge = graph.addEdge(from, to); |
853 typename Graph::Edge edge = graph.addEdge(from, to); |
720 for (int i = 0; i < (int)index.size(); ++i) { |
854 for (int i = 0; i < (int)index.size(); ++i) { |
721 index[i]->read(ls, edge); |
855 index[i]->read(ls, edge); |
722 } |
856 } |
723 } |
857 } |
724 } |
858 } |
725 |
859 |
726 bool isResolver() const { |
860 public: |
|
861 |
|
862 /// \brief Returns true if the edgeset can give back the edge by its id. |
|
863 /// |
|
864 /// Returns true if the edgeset can give back the edge by its id. |
|
865 /// It is possible only if an "id" named map was read. |
|
866 bool isIdReader() const { |
727 return inverter.get() != 0; |
867 return inverter.get() != 0; |
728 } |
868 } |
729 |
869 |
730 typename Graph::Edge resolve(std::istream& is) { |
870 /// \brief Gives back the edge by its id. |
|
871 /// |
|
872 /// It reads an id from the stream and gives back which edge belongs to |
|
873 /// it. It is possible only if there was read an "id" named map. |
|
874 typename Graph::Edge readId(std::istream& is) const { |
731 return inverter->read(is); |
875 return inverter->read(is); |
732 } |
876 } |
733 |
877 |
734 private: |
878 private: |
735 |
879 |
739 Graph& graph; |
883 Graph& graph; |
740 std::string id; |
884 std::string id; |
741 SkipReader<Item, DefaultSkipper> skipper; |
885 SkipReader<Item, DefaultSkipper> skipper; |
742 |
886 |
743 std::auto_ptr<InverterBase<Item> > inverter; |
887 std::auto_ptr<InverterBase<Item> > inverter; |
744 std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver; |
888 std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader; |
745 }; |
889 }; |
746 |
890 |
747 |
891 /// \ingroup io_group |
748 /// \e |
892 /// \brief SectionReader for reading labeled nodes. |
|
893 /// |
|
894 /// The nodes section's header line is \c \@nodes \c nodes_id, but the |
|
895 /// \c nodes_id may be empty. |
|
896 /// |
|
897 /// Each line in the section contains the name of the node |
|
898 /// and then the node id. |
|
899 /// |
|
900 /// \relates LemonReader |
|
901 template <typename _Graph> |
|
902 class NodeReader : public CommonSectionReaderBase { |
|
903 typedef CommonSectionReaderBase Parent; |
|
904 typedef _Graph Graph; |
|
905 typedef typename Graph::Node Item; |
|
906 public: |
|
907 |
|
908 /// \brief Constructor. |
|
909 /// |
|
910 /// Constructor for NodeReader. It creates the NodeReader and |
|
911 /// attach it into the given LemonReader. It will use the given |
|
912 /// node id reader to give back the nodes. The reader will read the |
|
913 /// section only if the \c _id and the \c nodes_id are the same. |
|
914 template <typename _IdReader> |
|
915 NodeReader(LemonReader& _reader, const _IdReader& _idReader, |
|
916 const std::string& _id = std::string()) |
|
917 : Parent(_reader), id(_id), |
|
918 idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} |
|
919 |
|
920 /// \brief Destructor. |
|
921 /// |
|
922 /// Destructor for NodeReader. |
|
923 virtual ~NodeReader() {} |
|
924 |
|
925 private: |
|
926 NodeReader(const NodeReader&); |
|
927 void operator=(const NodeReader&); |
|
928 |
|
929 public: |
|
930 |
|
931 /// \brief Add a node reader command for the NodeReader. |
|
932 /// |
|
933 /// Add a node reader command for the NodeReader. |
|
934 void readNode(const std::string& name, Item& item) { |
|
935 if (readers.find(name) != readers.end()) { |
|
936 ErrorMessage msg; |
|
937 msg << "Multiple read rule for node: " << name; |
|
938 throw IOParameterError(msg.message()); |
|
939 } |
|
940 readers.insert(make_pair(name, &item)); |
|
941 } |
|
942 |
|
943 protected: |
|
944 |
|
945 /// \brief Gives back true when the SectionReader can process |
|
946 /// the section with the given header line. |
|
947 /// |
|
948 /// It gives back true when the header line start with \c @nodes, |
|
949 /// and the header line's id and the reader's id are the same. |
|
950 virtual bool header(const std::string& line) { |
|
951 std::istringstream ls(line); |
|
952 std::string command; |
|
953 std::string name; |
|
954 ls >> command >> name; |
|
955 return command == "@nodes" && name == id; |
|
956 } |
|
957 |
|
958 /// \brief Reader function of the section. |
|
959 /// |
|
960 /// It reads the content of the section. |
|
961 virtual void read(std::istream& is) { |
|
962 std::string line; |
|
963 while (getline(is, line)) { |
|
964 std::istringstream ls(line); |
|
965 std::string id; |
|
966 ls >> id; |
|
967 typename ItemReaders::iterator it = readers.find(id); |
|
968 if (it != readers.end()) { |
|
969 *(it->second) = idReader->read(ls); |
|
970 } |
|
971 } |
|
972 } |
|
973 |
|
974 private: |
|
975 |
|
976 std::string id; |
|
977 |
|
978 typedef std::map<std::string, Item*> ItemReaders; |
|
979 ItemReaders readers; |
|
980 std::auto_ptr<IdReaderBase<Item> > idReader; |
|
981 }; |
|
982 |
|
983 /// \ingroup io_group |
|
984 /// \brief SectionReader for reading labeled edges. |
|
985 /// |
|
986 /// The edges section's header line is \c \@edges \c edges_id, but the |
|
987 /// \c edges_id may be empty. |
|
988 /// |
|
989 /// Each line in the section contains the name of the edge |
|
990 /// and then the edge id. |
|
991 /// |
|
992 /// \relates LemonReader |
|
993 template <typename _Graph> |
|
994 class EdgeReader : public CommonSectionReaderBase { |
|
995 typedef CommonSectionReaderBase Parent; |
|
996 typedef _Graph Graph; |
|
997 typedef typename Graph::Edge Item; |
|
998 public: |
|
999 |
|
1000 /// \brief Constructor. |
|
1001 /// |
|
1002 /// Constructor for EdgeReader. It creates the EdgeReader and |
|
1003 /// attach it into the given LemonReader. It will use the given |
|
1004 /// edge id reader to give back the edges. The reader will read the |
|
1005 /// section only if the \c _id and the \c nodes_id are the same. |
|
1006 template <typename _IdReader> |
|
1007 EdgeReader(LemonReader& _reader, const _IdReader& _idReader, |
|
1008 const std::string& _id = std::string()) |
|
1009 : Parent(_reader), id(_id), |
|
1010 idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} |
|
1011 |
|
1012 /// \brief Destructor. |
|
1013 /// |
|
1014 /// Destructor for EdgeReader. |
|
1015 virtual ~EdgeReader() {} |
|
1016 private: |
|
1017 EdgeReader(const EdgeReader&); |
|
1018 void operator=(const EdgeReader&); |
|
1019 |
|
1020 public: |
|
1021 |
|
1022 /// \brief Add an edge reader command for the EdgeReader. |
|
1023 /// |
|
1024 /// Add an edge reader command for the EdgeReader. |
|
1025 void readEdge(const std::string& name, Item& item) { |
|
1026 if (readers.find(name) != readers.end()) { |
|
1027 ErrorMessage msg; |
|
1028 msg << "Multiple read rule for edge: " << name; |
|
1029 throw IOParameterError(msg.message()); |
|
1030 } |
|
1031 readers.insert(make_pair(name, &item)); |
|
1032 } |
|
1033 |
|
1034 protected: |
|
1035 |
|
1036 /// \brief Gives back true when the SectionReader can process |
|
1037 /// the section with the given header line. |
|
1038 /// |
|
1039 /// It gives back true when the header line start with \c @edges, |
|
1040 /// and the header line's id and the reader's id are the same. |
|
1041 virtual bool header(const std::string& line) { |
|
1042 std::istringstream ls(line); |
|
1043 std::string command; |
|
1044 std::string name; |
|
1045 ls >> command >> name; |
|
1046 return command == "@edges" && name == id; |
|
1047 } |
|
1048 |
|
1049 /// \brief Reader function of the section. |
|
1050 /// |
|
1051 /// It reads the content of the section. |
|
1052 virtual void read(std::istream& is) { |
|
1053 std::string line; |
|
1054 while (getline(is, line)) { |
|
1055 std::istringstream ls(line); |
|
1056 std::string id; |
|
1057 ls >> id; |
|
1058 typename ItemReaders::iterator it = readers.find(id); |
|
1059 if (it != readers.end()) { |
|
1060 *(it->second) = idReader->read(ls); |
|
1061 } |
|
1062 } |
|
1063 } |
|
1064 |
|
1065 private: |
|
1066 |
|
1067 std::string id; |
|
1068 |
|
1069 typedef std::map<std::string, Item*> ItemReaders; |
|
1070 ItemReaders readers; |
|
1071 std::auto_ptr<IdReaderBase<Item> > idReader; |
|
1072 }; |
|
1073 |
|
1074 /// \ingroup io_group |
|
1075 /// \brief SectionReader for attributes. |
|
1076 /// |
|
1077 /// The lemon format can store multiple attribute set. Each set has |
|
1078 /// the header line \c \@attributes \c attributeset_id, but the |
|
1079 /// attributeset_id may be empty. |
|
1080 /// |
|
1081 /// The attributeset section contains several lines. Each of them starts |
|
1082 /// with an attribute and then a the value for the id. |
|
1083 /// |
|
1084 /// \relates LemonReader |
749 template <typename _Traits = DefaultReaderTraits> |
1085 template <typename _Traits = DefaultReaderTraits> |
750 class AttributeReader : public CommonSectionReaderBase { |
1086 class AttributeReader : public CommonSectionReaderBase { |
751 typedef CommonSectionReaderBase Parent; |
1087 typedef CommonSectionReaderBase Parent; |
752 typedef _Traits Traits; |
1088 typedef _Traits Traits; |
753 public: |
1089 public: |
754 /// \e |
1090 /// \brief Constructor. |
|
1091 /// |
|
1092 /// Constructor for AttributeReader. It creates the AttributeReader and |
|
1093 /// attach it into the given LemonReader. The reader process a section |
|
1094 /// only if the \c section_id and the \c _id are the same. |
755 AttributeReader(LemonReader& _reader, |
1095 AttributeReader(LemonReader& _reader, |
756 const std::string& _id = std::string()) : id(_id) { |
1096 const std::string& _id = std::string()) |
757 _reader.attach(*this); |
1097 : Parent(_reader), id(_id) {} |
758 } |
1098 |
759 |
1099 /// \brief Destructor. |
760 /// \e |
1100 /// |
|
1101 /// Destructor for AttributeReader. |
761 virtual ~AttributeReader() { |
1102 virtual ~AttributeReader() { |
762 for (typename Readers::iterator it = readers.begin(); |
1103 for (typename Readers::iterator it = readers.begin(); |
763 it != readers.end(); ++it) { |
1104 it != readers.end(); ++it) { |
764 delete it->second; |
1105 delete it->second; |
765 } |
1106 } |
816 |
1169 |
817 private: |
1170 private: |
818 std::string id; |
1171 std::string id; |
819 |
1172 |
820 typedef std::map<std::string, ValueReaderBase*> Readers; |
1173 typedef std::map<std::string, ValueReaderBase*> Readers; |
821 Readers readers; |
1174 Readers readers; |
822 |
|
823 }; |
1175 }; |
824 |
1176 |
825 template <typename _Graph> |
1177 |
826 class NodeReader : public CommonSectionReaderBase { |
|
827 typedef CommonSectionReaderBase Parent; |
|
828 typedef _Graph Graph; |
|
829 typedef typename Graph::Node Item; |
|
830 public: |
|
831 |
|
832 template <typename Resolver> |
|
833 NodeReader(LemonReader& _reader, const Resolver& _resolver, |
|
834 const std::string& _id = std::string()) |
|
835 : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver> |
|
836 (_resolver)) { |
|
837 _reader.attach(*this); |
|
838 } |
|
839 |
|
840 virtual ~NodeReader() {} |
|
841 |
|
842 private: |
|
843 NodeReader(const NodeReader&); |
|
844 void operator=(const NodeReader&); |
|
845 |
|
846 public: |
|
847 |
|
848 void readNode(const std::string& name, Item& item) { |
|
849 if (readers.find(name) != readers.end()) { |
|
850 ErrorMessage msg; |
|
851 msg << "Multiple read rule for node: " << name; |
|
852 throw IOParameterError(msg.message()); |
|
853 } |
|
854 readers.insert(make_pair(name, &item)); |
|
855 } |
|
856 |
|
857 virtual bool header(const std::string& line) { |
|
858 std::istringstream ls(line); |
|
859 std::string command; |
|
860 std::string name; |
|
861 ls >> command >> name; |
|
862 return command == "@nodes" && name == id; |
|
863 } |
|
864 |
|
865 virtual void read(std::istream& is) { |
|
866 std::string line; |
|
867 while (getline(is, line)) { |
|
868 std::istringstream ls(line); |
|
869 std::string id; |
|
870 ls >> id; |
|
871 typename ItemReaders::iterator it = readers.find(id); |
|
872 if (it != readers.end()) { |
|
873 *(it->second) = resolver->resolve(ls); |
|
874 } |
|
875 } |
|
876 } |
|
877 |
|
878 private: |
|
879 |
|
880 std::string id; |
|
881 |
|
882 typedef std::map<std::string, Item*> ItemReaders; |
|
883 ItemReaders readers; |
|
884 std::auto_ptr<ResolverReaderBase<Item> > resolver; |
|
885 }; |
|
886 |
|
887 template <typename _Graph> |
|
888 class EdgeReader : public CommonSectionReaderBase { |
|
889 typedef CommonSectionReaderBase Parent; |
|
890 typedef _Graph Graph; |
|
891 typedef typename Graph::Edge Item; |
|
892 public: |
|
893 |
|
894 template <typename Resolver> |
|
895 EdgeReader(LemonReader& _reader, const Resolver& _resolver, |
|
896 const std::string& _id = std::string()) |
|
897 : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver> |
|
898 (_resolver)) { |
|
899 _reader.attach(*this); |
|
900 } |
|
901 |
|
902 virtual ~EdgeReader() {} |
|
903 private: |
|
904 EdgeReader(const EdgeReader&); |
|
905 void operator=(const EdgeReader&); |
|
906 |
|
907 public: |
|
908 |
|
909 void readEdge(const std::string& name, Item& item) { |
|
910 if (readers.find(name) != readers.end()) { |
|
911 ErrorMessage msg; |
|
912 msg << "Multiple read rule for edge: " << name; |
|
913 throw IOParameterError(msg.message()); |
|
914 } |
|
915 readers.insert(make_pair(name, &item)); |
|
916 } |
|
917 |
|
918 |
|
919 virtual bool header(const std::string& line) { |
|
920 std::istringstream ls(line); |
|
921 std::string command; |
|
922 std::string name; |
|
923 ls >> command >> name; |
|
924 return command == "@nodes" && name == id; |
|
925 } |
|
926 |
|
927 virtual void read(std::istream& is) { |
|
928 std::string line; |
|
929 while (getline(is, line)) { |
|
930 std::istringstream ls(line); |
|
931 std::string id; |
|
932 ls >> id; |
|
933 typename ItemReaders::iterator it = readers.find(id); |
|
934 if (it != readers.end()) { |
|
935 *(it->second) = resolver->resolve(ls); |
|
936 } |
|
937 } |
|
938 } |
|
939 |
|
940 private: |
|
941 |
|
942 std::string id; |
|
943 |
|
944 typedef std::map<std::string, Item*> ItemReaders; |
|
945 ItemReaders readers; |
|
946 std::auto_ptr<ResolverReaderBase<Item> > resolver; |
|
947 }; |
|
948 |
|
949 /// \e |
|
950 class PrintReader : public LemonReader::SectionReader { |
|
951 typedef LemonReader::SectionReader Parent; |
|
952 public: |
|
953 |
|
954 /// \e |
|
955 PrintReader(LemonReader& reader) { |
|
956 reader.attach(*this); |
|
957 } |
|
958 |
|
959 /// \e |
|
960 bool header(const std::string& line) { |
|
961 std::cout << "Asked header: " << line << std::endl; |
|
962 return true; |
|
963 } |
|
964 |
|
965 /// \e |
|
966 void read(std::istream& is) { |
|
967 std::string line; |
|
968 while (std::getline(is, line)) { |
|
969 std::cout << line << std::endl; |
|
970 } |
|
971 } |
|
972 |
|
973 }; |
|
974 |
|
975 /// @} |
|
976 } |
1178 } |
977 #endif |
1179 #endif |