Changeset 162:33247f6fff16 in lemon-main
- Timestamp:
- 05/27/08 16:01:20 (16 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/lgf.dox
r156 r162 91 91 \endcode 92 92 93 The \e LGF can contain extra sections, but there is no restriction on 94 the format of such sections. 95 93 96 */ 94 97 } -
lemon/lgf_reader.h
r156 r162 269 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 } … … 283 349 /// member function. A map reading rule can be added to the reader 284 350 /// with the \c nodeMap() or \c arcMap() members. An optional 285 /// converter parameter can also be added as a standard functor converting from 286 /// std::string to the value type of the map. If it is set, it will 287 /// determine how the tokens in the file should be is converted to the map's 288 /// value type. If the functor is not set, then a default conversion 289 /// will be used. One map can be read into multiple map objects at the 290 /// same time. The \c attribute(), \c node() and \c arc() functions 291 /// are used to add attribute reading rules. 351 /// converter parameter can also be added as a standard functor 352 /// converting from std::string to the value type of the map. If it 353 /// is set, it will determine how the tokens in the file should be 354 /// is converted to the map's value type. If the functor is not set, 355 /// then a default conversion will be used. One map can be read into 356 /// multiple map objects at the same time. The \c attribute(), \c 357 /// node() and \c arc() functions are used to add attribute reading 358 /// rules. 292 359 /// 293 360 ///\code … … 303 370 /// By default the reader uses the first section in the file of the 304 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 306 /// the \c nodes(), \c arcs() or \c attributes() 307 /// functions. 372 /// selected for reading by giving an optional name parameter to the 373 /// \c nodes(), \c arcs() or \c attributes() functions. The readers 374 /// also can load extra sections with the \c sectionLines() and 375 /// sectionStream() functions. 308 376 /// 309 377 /// The \c useNodes() and \c useArcs() functions are used to tell the reader … … 357 425 Attributes _attributes; 358 426 427 typedef std::map<std::string, _reader_bits::Section*> Sections; 428 Sections _sections; 429 359 430 bool _use_nodes; 360 431 bool _use_arcs; … … 410 481 _arcs_caption = other._arcs_caption; 411 482 _attributes_caption = other._attributes_caption; 483 484 _sections.swap(other._sections); 412 485 } 413 486 … … 426 499 for (typename Attributes::iterator it = _attributes.begin(); 427 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 506 delete it->second; 429 507 } … … 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 … … 930 1085 bool arcs_done = false; 931 1086 bool attributes_done = false; 1087 std::set<std::string> extra_sections; 932 1088 933 1089 line_num = 0; … … 963 1119 } 964 1120 } else { 965 readLine(); 966 skipSection(); 1121 if (extra_sections.find(section) != extra_sections.end()) { 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 1136 } catch (DataFormatError& error) {
Note: See TracChangeset
for help on using the changeset viewer.