Changeset 162:33247f6fff16 in lemon-1.2 for lemon/lgf_reader.h
- Timestamp:
- 05/27/08 16:01:20 (17 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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.