src/lemon/lemon_reader.h
changeset 1411 5d161e08bda8
parent 1408 892c29484414
child 1421 7a21e1414c38
equal deleted inserted replaced
0:c2499068d11d 1:eebb67bff1d6
    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) {
   262     typedef std::vector<SectionReader*> SectionReaders;
   309     typedef std::vector<SectionReader*> SectionReaders;
   263     SectionReaders readers;
   310     SectionReaders readers;
   264 
   311 
   265   };
   312   };
   266 
   313 
   267 
   314   /// \brief Helper class for implementing the common SectionReaders.
   268   /// \e
   315   ///
       
   316   /// Helper class for implementing the common SectionReaders.
   269   class CommonSectionReaderBase : public LemonReader::SectionReader {
   317   class CommonSectionReaderBase : public LemonReader::SectionReader {
       
   318     typedef LemonReader::SectionReader Parent;
   270   protected:
   319   protected:
       
   320     
       
   321     /// \brief Constructor for CommonSectionReaderBase.
       
   322     ///
       
   323     /// Constructor for CommonSectionReaderBase. It attach this reader to
       
   324     /// the given LemonReader.
       
   325     CommonSectionReaderBase(LemonReader& _reader) 
       
   326       : Parent(_reader) {}
       
   327 
   271     template <typename _Item>
   328     template <typename _Item>
   272     class ReaderBase;
   329     class ReaderBase;
   273     
   330     
   274     template <typename _Item>
   331     template <typename _Item>
   275     class InverterBase : public ReaderBase<_Item> {
   332     class InverterBase : public ReaderBase<_Item> {
   431 	return new SkipReaderInverter<Item, Reader>(reader);
   488 	return new SkipReaderInverter<Item, Reader>(reader);
   432       }
   489       }
   433     };
   490     };
   434 
   491 
   435     template <typename _Item>
   492     template <typename _Item>
   436     class ResolverReaderBase {
   493     class IdReaderBase {
   437     public:
   494     public:
   438       typedef _Item Item;
   495       typedef _Item Item;
   439       virtual Item resolve(std::istream& is) const = 0;
   496       virtual Item read(std::istream& is) const = 0;
   440     };
   497     };
   441 
   498 
   442     template <typename _Item, typename _Resolver>
   499     template <typename _Item, typename _BoxedIdReader>
   443     class ResolverReader : public ResolverReaderBase<_Item> {
   500     class IdReader : public IdReaderBase<_Item> {
   444     public:
   501     public:
   445       typedef _Item Item;
   502       typedef _Item Item;
   446       typedef _Resolver Resolver;
   503       typedef _BoxedIdReader BoxedIdReader;
   447 
   504       
   448       const Resolver& resolver;
   505       const BoxedIdReader& boxedIdReader;
   449 
   506 
   450       ResolverReader(const Resolver& _resolver) 
   507       IdReader(const BoxedIdReader& _boxedIdReader) 
   451 	: resolver(_resolver) {}
   508 	: boxedIdReader(_boxedIdReader) {}
   452 
   509 
   453       virtual Item resolve(std::istream& is) const {
   510       virtual Item read(std::istream& is) const {
   454 	return resolver.resolve(is);
   511 	return boxedIdReader.readId(is);
   455       }
   512       }
   456     };
   513     };
   457 
   514 
   458     class ValueReaderBase {
   515     class ValueReaderBase {
   459     public:
   516     public:
   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       }
   548       }
   629       }
   549       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   630       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   550       return *this;
   631       return *this;
   551     }
   632     }
   552 
   633 
   553     /// \e
   634   protected:
       
   635 
       
   636     /// \brief Gives back true when the SectionReader can process 
       
   637     /// the section with the given header line.
       
   638     ///
       
   639     /// It gives back true when the header line starts with \c @nodeset,
       
   640     /// and the header line's id and the nodeset's id are the same.
   554     virtual bool header(const std::string& line) {
   641     virtual bool header(const std::string& line) {
   555       std::istringstream ls(line);
   642       std::istringstream ls(line);
   556       std::string command;
   643       std::string command;
   557       std::string name;
   644       std::string name;
   558       ls >> command >> name;
   645       ls >> command >> name;
   559       return command == "@nodeset" && name == id;
   646       return command == "@nodeset" && name == id;
   560     }
   647     }
   561 
   648 
   562     /// \e
   649     /// \brief Reader function of the section.
       
   650     ///
       
   651     /// It reads the content of the section.
   563     virtual void read(std::istream& is) {
   652     virtual void read(std::istream& is) {
   564       std::vector<ReaderBase<Item>* > index;
   653       std::vector<ReaderBase<Item>* > index;
   565       std::string line;
   654       std::string line;
   566 
   655 
   567       getline(is, line);
   656       getline(is, line);
   585 	  index[i]->read(ls, node);
   674 	  index[i]->read(ls, node);
   586 	}
   675 	}
   587       }
   676       }
   588     }
   677     }
   589 
   678 
   590     bool isResolver() const {
   679   public:
       
   680 
       
   681     /// \brief Returns true if the nodeset can give back the node by its id.
       
   682     ///
       
   683     /// Returns true if the nodeset can give back the node by its id.
       
   684     /// It is possible only if an "id" named map was read.
       
   685     bool isIdReader() const {
   591       return inverter.get() != 0;
   686       return inverter.get() != 0;
   592     }
   687     }
   593 
   688 
   594     typename Graph::Node resolve(std::istream& is) const {
   689     /// \brief Gives back the node by its id.
       
   690     ///
       
   691     /// It reads an id from the stream and gives back which node belongs to
       
   692     /// it. It is possible only if there was read an "id" named map.
       
   693     typename Graph::Node readId(std::istream& is) const {
   595       return inverter->read(is);
   694       return inverter->read(is);
   596     } 
   695     } 
   597 
   696 
   598   private:
   697   private:
   599 
   698 
   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;
   667       readers.insert(
   793       readers.insert(
   668 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   794 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   669       return *this;
   795       return *this;
   670     }
   796     }
   671 
   797 
   672     /// \brief Add a new node map skipper command for the reader.
   798     /// \brief Add a new edge map skipper command for the reader.
   673     ///
   799     ///
   674     /// Add a new node map skipper command for the reader.
   800     /// Add a new edge map skipper command for the reader.
   675     template <typename Reader>
   801     template <typename Reader>
   676     EdgeSetReader& skipMap(std::string name, 
   802     EdgeSetReader& skipMap(std::string name, 
   677 			   const Reader& reader = Reader()) {
   803 			   const Reader& reader = Reader()) {
   678       if (readers.find(name) != readers.end()) {
   804       if (readers.find(name) != readers.end()) {
   679 	ErrorMessage msg;
   805 	ErrorMessage msg;
   682       }
   808       }
   683       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   809       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   684       return *this;
   810       return *this;
   685     }
   811     }
   686 
   812 
   687     /// \e
   813   protected:
       
   814 
       
   815     /// \brief Gives back true when the SectionReader can process 
       
   816     /// the section with the given header line.
       
   817     ///
       
   818     /// It gives back true when the header line starts with \c @edgeset,
       
   819     /// and the header line's id and the edgeset's id are the same.
   688     virtual bool header(const std::string& line) {
   820     virtual bool header(const std::string& line) {
   689       std::istringstream ls(line);
   821       std::istringstream ls(line);
   690       std::string command;
   822       std::string command;
   691       std::string name;
   823       std::string name;
   692       ls >> command >> name;
   824       ls >> command >> name;
   693       return command == "@edgeset" && name == id;
   825       return command == "@edgeset" && name == id;
   694     }
   826     }
   695 
   827 
   696     /// \e
   828     /// \brief Reader function of the section.
       
   829     ///
       
   830     /// It reads the content of the section.
   697     virtual void read(std::istream& is) {
   831     virtual void read(std::istream& is) {
   698       std::vector<ReaderBase<Item>* > index;
   832       std::vector<ReaderBase<Item>* > index;
   699       std::string line;
   833       std::string line;
   700 
   834 
   701       getline(is, line);
   835       getline(is, line);
   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       }
   768   private:
  1109   private:
   769     AttributeReader(const AttributeReader&);
  1110     AttributeReader(const AttributeReader&);
   770     void operator=(AttributeReader&);
  1111     void operator=(AttributeReader&);
   771 
  1112 
   772   public:
  1113   public:
   773     /// \e
  1114     /// \brief Add an attribute reader command for the reader.
       
  1115     ///
       
  1116     /// Add an attribute reader command for the reader.
   774     template <typename Value>
  1117     template <typename Value>
   775     AttributeReader& readAttribute(const std::string& id, Value& value) {
  1118     AttributeReader& readAttribute(const std::string& id, Value& value) {
   776       return readAttribute<typename Traits::template Reader<Value> >
  1119       return readAttribute<typename Traits::template Reader<Value> >
   777 	(id, value);
  1120 	(id, value);
   778     }
  1121     }
   779 
  1122 
   780     /// \e
  1123     /// \brief Add an attribute reader command for the reader.
       
  1124     ///
       
  1125     /// Add an attribute reader command for the reader.
   781     template <typename Reader, typename Value>
  1126     template <typename Reader, typename Value>
   782     AttributeReader& readAttribute(const std::string& name, Value& value,
  1127     AttributeReader& readAttribute(const std::string& name, Value& value,
   783 				   const Reader& reader = Reader()) {
  1128 				   const Reader& reader = Reader()) {
   784       if (readers.find(name) != readers.end()) {
  1129       if (readers.find(name) != readers.end()) {
   785 	ErrorMessage msg;
  1130 	ErrorMessage msg;
   789       readers.insert(make_pair(name, new ValueReader<Value, Reader>
  1134       readers.insert(make_pair(name, new ValueReader<Value, Reader>
   790       			       (value, reader)));
  1135       			       (value, reader)));
   791       return *this;
  1136       return *this;
   792     }
  1137     }
   793 
  1138 
   794     /// \e
  1139   protected:
       
  1140 
       
  1141     /// \brief Gives back true when the SectionReader can process 
       
  1142     /// the section with the given header line.
       
  1143     ///
       
  1144     /// It gives back true when the header line start with \c @attributes,
       
  1145     /// and the header line's id and the attributeset's id are the same.
   795     bool header(const std::string& line) {
  1146     bool header(const std::string& line) {
   796       std::istringstream ls(line);
  1147       std::istringstream ls(line);
   797       std::string command;
  1148       std::string command;
   798       std::string name;
  1149       std::string name;
   799       ls >> command >> name;
  1150       ls >> command >> name;
   800       return command == "@attributes" && name == id;
  1151       return command == "@attributes" && name == id;
   801     }
  1152     }
   802 
  1153 
   803     /// \e
  1154     /// \brief Reader function of the section.
       
  1155     ///
       
  1156     /// It reads the content of the section.
   804     void read(std::istream& is) {
  1157     void read(std::istream& is) {
   805       std::string line;
  1158       std::string line;
   806       while (getline(is, line)) {
  1159       while (getline(is, line)) {
   807 	std::istringstream ls(line);
  1160 	std::istringstream ls(line);
   808 	std::string id;
  1161 	std::string id;
   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