|  | 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 | }; | 
            
                      
                        | 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. | 
            
                  
                          |  | 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 |  |