lemon/lgf_reader.h
changeset 162 33247f6fff16
parent 156 e561aa7675de
child 163 c82fd9568d75
equal deleted inserted replaced
4:7b4f9985079f 5:416bae201451
   266 	}
   266 	}
   267       }
   267       }
   268       str = os.str();
   268       str = os.str();
   269       return is;
   269       return is;
   270     }
   270     }
       
   271 
       
   272     class Section {
       
   273     public:
       
   274       virtual ~Section() {}
       
   275       virtual void process(std::istream& is, int& line_num) = 0;
       
   276     };
       
   277 
       
   278     template <typename Functor>
       
   279     class LineSection : public Section {
       
   280     private:
       
   281 
       
   282       Functor _functor;
       
   283 
       
   284     public:
       
   285       
       
   286       LineSection(const Functor& functor) : _functor(functor) {}
       
   287       virtual ~LineSection() {}
       
   288 
       
   289       virtual void process(std::istream& is, int& line_num) {
       
   290 	char c;
       
   291 	std::string line;
       
   292 	while (is.get(c) && c != '@') {
       
   293 	  if (c == '\n') {
       
   294 	    ++line_num;
       
   295 	  } else if (c == '#') {
       
   296 	    getline(is, line);
       
   297 	    ++line_num;
       
   298 	  } else if (!isWhiteSpace(c)) {
       
   299 	    is.putback(c);
       
   300 	    getline(is, line);
       
   301 	    _functor(line);
       
   302 	    ++line_num;
       
   303 	  }
       
   304 	}
       
   305 	if (is) is.putback(c);
       
   306 	else if (is.eof()) is.clear();
       
   307       }
       
   308     };
       
   309 
       
   310     template <typename Functor>
       
   311     class StreamSection : public Section {
       
   312     private:
       
   313 
       
   314       Functor _functor;
       
   315 
       
   316     public:
       
   317       
       
   318       StreamSection(const Functor& functor) : _functor(functor) {}
       
   319       virtual ~StreamSection() {} 
       
   320 
       
   321       virtual void process(std::istream& is, int& line_num) {
       
   322 	_functor(is, line_num);
       
   323 	char c;
       
   324 	std::string line;
       
   325 	while (is.get(c) && c != '@') {
       
   326 	  if (c == '\n') {
       
   327 	    ++line_num;
       
   328 	  } else if (!isWhiteSpace(c)) {
       
   329 	    getline(is, line);
       
   330 	    ++line_num;
       
   331 	  }
       
   332 	}
       
   333 	if (is) is.putback(c);
       
   334 	else if (is.eof()) is.clear();	
       
   335       }
       
   336     };
   271     
   337     
   272   }
   338   }
   273 
   339 
   274   /// \ingroup lemon_io
   340   /// \ingroup lemon_io
   275   ///  
   341   ///  
   280   /// The reading method does a batch processing. The user creates a
   346   /// The reading method does a batch processing. The user creates a
   281   /// reader object, then various reading rules can be added to the
   347   /// reader object, then various reading rules can be added to the
   282   /// reader, and eventually the reading is executed with the \c run()
   348   /// reader, and eventually the reading is executed with the \c run()
   283   /// member function. A map reading rule can be added to the reader
   349   /// member function. A map reading rule can be added to the reader
   284   /// with the \c nodeMap() or \c arcMap() members. An optional
   350   /// with the \c nodeMap() or \c arcMap() members. An optional
   285   /// converter parameter can also be added as a standard functor converting from
   351   /// converter parameter can also be added as a standard functor
   286   /// std::string to the value type of the map. If it is set, it will
   352   /// converting from std::string to the value type of the map. If it
   287   /// determine how the tokens in the file should be is converted to the map's
   353   /// is set, it will determine how the tokens in the file should be
   288   /// value type. If the functor is not set, then a default conversion
   354   /// is converted to the map's value type. If the functor is not set,
   289   /// will be used. One map can be read into multiple map objects at the
   355   /// then a default conversion will be used. One map can be read into
   290   /// same time. The \c attribute(), \c node() and \c arc() functions
   356   /// multiple map objects at the same time. The \c attribute(), \c
   291   /// are used to add attribute reading rules.
   357   /// node() and \c arc() functions are used to add attribute reading
       
   358   /// rules.
   292   ///
   359   ///
   293   ///\code
   360   ///\code
   294   ///     DigraphReader<Digraph>(std::cin, digraph).
   361   ///     DigraphReader<Digraph>(std::cin, digraph).
   295   ///       nodeMap("coordinates", coord_map).
   362   ///       nodeMap("coordinates", coord_map).
   296   ///       arcMap("capacity", cap_map).
   363   ///       arcMap("capacity", cap_map).
   300   ///       run();
   367   ///       run();
   301   ///\endcode
   368   ///\endcode
   302   ///
   369   ///
   303   /// By default the reader uses the first section in the file of the
   370   /// By default the reader uses the first section in the file of the
   304   /// proper type. If a section has an optional name, then it can be
   371   /// proper type. If a section has an optional name, then it can be
   305   /// selected for reading by giving an optional name parameter to
   372   /// selected for reading by giving an optional name parameter to the
   306   /// the \c nodes(), \c arcs() or \c attributes()
   373   /// \c nodes(), \c arcs() or \c attributes() functions. The readers
   307   /// functions.
   374   /// also can load extra sections with the \c sectionLines() and
       
   375   /// sectionStream() functions.
   308   ///
   376   ///
   309   /// The \c useNodes() and \c useArcs() functions are used to tell the reader
   377   /// The \c useNodes() and \c useArcs() functions are used to tell the reader
   310   /// that the nodes or arcs should not be constructed (added to the
   378   /// that the nodes or arcs should not be constructed (added to the
   311   /// graph) during the reading, but instead the label map of the items
   379   /// graph) during the reading, but instead the label map of the items
   312   /// are given as a parameter of these functions. An
   380   /// are given as a parameter of these functions. An
   354 
   422 
   355     typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
   423     typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
   356       Attributes;
   424       Attributes;
   357     Attributes _attributes;
   425     Attributes _attributes;
   358 
   426 
       
   427     typedef std::map<std::string, _reader_bits::Section*> Sections;
       
   428     Sections _sections;
       
   429 
   359     bool _use_nodes;
   430     bool _use_nodes;
   360     bool _use_arcs;
   431     bool _use_arcs;
   361 
   432 
   362     int line_num;
   433     int line_num;
   363     std::istringstream line;
   434     std::istringstream line;
   407       _attributes.swap(other._attributes);
   478       _attributes.swap(other._attributes);
   408 
   479 
   409       _nodes_caption = other._nodes_caption;
   480       _nodes_caption = other._nodes_caption;
   410       _arcs_caption = other._arcs_caption;
   481       _arcs_caption = other._arcs_caption;
   411       _attributes_caption = other._attributes_caption;
   482       _attributes_caption = other._attributes_caption;
       
   483 
       
   484       _sections.swap(other._sections);
   412     }
   485     }
   413 
   486 
   414     /// \brief Destructor
   487     /// \brief Destructor
   415     ~DigraphReader() {
   488     ~DigraphReader() {
   416       for (typename NodeMaps::iterator it = _node_maps.begin(); 
   489       for (typename NodeMaps::iterator it = _node_maps.begin(); 
   423 	delete it->second;
   496 	delete it->second;
   424       }
   497       }
   425 
   498 
   426       for (typename Attributes::iterator it = _attributes.begin(); 
   499       for (typename Attributes::iterator it = _attributes.begin(); 
   427 	   it != _attributes.end(); ++it) {
   500 	   it != _attributes.end(); ++it) {
       
   501 	delete it->second;
       
   502       }
       
   503 
       
   504       for (typename Sections::iterator it = _sections.begin(); 
       
   505 	   it != _sections.end(); ++it) {
   428 	delete it->second;
   506 	delete it->second;
   429       }
   507       }
   430 
   508 
   431       if (local_is) {
   509       if (local_is) {
   432 	delete _is;
   510 	delete _is;
   570     DigraphReader& attributes(const std::string& caption) {
   648     DigraphReader& attributes(const std::string& caption) {
   571       _attributes_caption = caption;
   649       _attributes_caption = caption;
   572       return *this;
   650       return *this;
   573     }
   651     }
   574 
   652 
       
   653     /// @}
       
   654 
       
   655     /// \name Section readers
       
   656     /// @{
       
   657 
       
   658     /// \brief Add a section processor with line oriented reading
       
   659     ///
       
   660     /// In the \e LGF file extra sections can be placed, which contain
       
   661     /// any data in arbitrary format. These sections can be read with
       
   662     /// this function line by line. The first parameter is the type
       
   663     /// descriptor of the section, the second is a functor, which
       
   664     /// takes just one \c std::string parameter. At the reading
       
   665     /// process, each line of the section will be given to the functor
       
   666     /// object. However, the empty lines and the comment lines are
       
   667     /// filtered out, and the leading whitespaces are stipped from
       
   668     /// each processed string.
       
   669     ///
       
   670     /// For example let's see a section, which contain several
       
   671     /// integers, which should be inserted into a vector.
       
   672     ///\code
       
   673     ///  @numbers
       
   674     ///  12 45 23
       
   675     ///  4
       
   676     ///  23 6
       
   677     ///\endcode
       
   678     ///
       
   679     /// The functor is implemented as an struct:
       
   680     ///\code
       
   681     ///  struct NumberSection {
       
   682     ///    std::vector<int>& _data;
       
   683     ///    NumberSection(std::vector<int>& data) : _data(data) {}
       
   684     ///    void operator()(const std::string& line) {
       
   685     ///      std::istringstream ls(line);
       
   686     ///      int value;
       
   687     ///      while (ls >> value) _data.push_back(value);
       
   688     ///    }
       
   689     ///  };
       
   690     ///
       
   691     ///  // ...
       
   692     ///
       
   693     ///  reader.sectionLines("numbers", NumberSection(vec));  
       
   694     ///\endcode
       
   695     template <typename Functor>
       
   696     DigraphReader& sectionLines(const std::string& type, Functor functor) {
       
   697       LEMON_ASSERT(!type.empty(), "Type is not empty.");
       
   698       LEMON_ASSERT(_sections.find(type) == _sections.end(), 
       
   699 		   "Multiple reading of section.");
       
   700       LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
       
   701 		   type != "attributes", "Multiple reading of section.");
       
   702       _sections.insert(std::make_pair(type, 
       
   703         new _reader_bits::LineSection<Functor>(functor)));
       
   704       return *this;
       
   705     }
       
   706 
       
   707 
       
   708     /// \brief Add a section processor with stream oriented reading
       
   709     ///
       
   710     /// In the \e LGF file extra sections can be placed, which contain
       
   711     /// any data in arbitrary format. These sections can be read
       
   712     /// directly with this function. The first parameter is the type
       
   713     /// of the section, the second is a functor, which takes an \c
       
   714     /// std::istream& and an int& parameter, the latter regard to the
       
   715     /// line number of stream. The functor can read the input while
       
   716     /// the section go on, and the line number should be modified
       
   717     /// accordingly.
       
   718     template <typename Functor>
       
   719     DigraphReader& sectionStream(const std::string& type, Functor functor) {
       
   720       LEMON_ASSERT(!type.empty(), "Type is not empty.");
       
   721       LEMON_ASSERT(_sections.find(type) == _sections.end(), 
       
   722 		   "Multiple reading of section.");
       
   723       LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
       
   724 		   type != "attributes", "Multiple reading of section.");
       
   725       _sections.insert(std::make_pair(type, 
       
   726 	 new _reader_bits::StreamSection<Functor>(functor)));
       
   727       return *this;
       
   728     }    
       
   729     
   575     /// @}
   730     /// @}
   576 
   731 
   577     /// \name Using previously constructed node or arc set
   732     /// \name Using previously constructed node or arc set
   578     /// @{
   733     /// @{
   579 
   734 
   927       LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
  1082       LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
   928       
  1083       
   929       bool nodes_done = false;
  1084       bool nodes_done = false;
   930       bool arcs_done = false;
  1085       bool arcs_done = false;
   931       bool attributes_done = false;
  1086       bool attributes_done = false;
       
  1087       std::set<std::string> extra_sections;
   932 
  1088 
   933       line_num = 0;      
  1089       line_num = 0;      
   934       readLine();
  1090       readLine();
   935 
  1091 
   936       while (readSuccess()) {
  1092       while (readSuccess()) {
   960 	    if (_attributes_caption.empty() || _attributes_caption == caption) {
  1116 	    if (_attributes_caption.empty() || _attributes_caption == caption) {
   961 	      readAttributes();
  1117 	      readAttributes();
   962 	      attributes_done = true;
  1118 	      attributes_done = true;
   963 	    }
  1119 	    }
   964 	  } else {
  1120 	  } else {
   965 	    readLine();
  1121 	    if (extra_sections.find(section) != extra_sections.end()) {
   966 	    skipSection();
  1122 	      std::ostringstream msg;
       
  1123 	      msg << "Multiple occurence of section " << section;
       
  1124 	      throw DataFormatError(msg.str().c_str());
       
  1125 	    }
       
  1126 	    Sections::iterator it = _sections.find(section);
       
  1127 	    if (it != _sections.end()) {
       
  1128 	      extra_sections.insert(section);
       
  1129 	      it->second->process(*_is, line_num);
       
  1130 	      readLine();
       
  1131 	    } else {
       
  1132 	      readLine();
       
  1133 	      skipSection();
       
  1134 	    }
   967 	  }
  1135 	  }
   968 	} catch (DataFormatError& error) {
  1136 	} catch (DataFormatError& error) {
   969 	  error.line(line_num);
  1137 	  error.line(line_num);
   970 	  throw;
  1138 	  throw;
   971 	}	
  1139 	}