gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Section reader for DigraphReader
0 2 0
default
2 files changed with 183 insertions and 12 deletions:
↑ Collapse diff ↑
Show white space 6 line context
... ...
@@ -92,2 +92,5 @@
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
*/
Ignore white space 6 line context
... ...
@@ -270,2 +270,68 @@
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
    
... ...
@@ -284,9 +350,10 @@
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
  ///
... ...
@@ -304,5 +371,6 @@
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
  ///
... ...
@@ -358,2 +426,5 @@
358 426

	
427
    typedef std::map<std::string, _reader_bits::Section*> Sections;
428
    Sections _sections;
429

	
359 430
    bool _use_nodes;
... ...
@@ -411,2 +482,4 @@
411 482
      _attributes_caption = other._attributes_caption;
483

	
484
      _sections.swap(other._sections);
412 485
    }
... ...
@@ -430,2 +503,7 @@
430 503

	
504
      for (typename Sections::iterator it = _sections.begin(); 
505
	   it != _sections.end(); ++it) {
506
	delete it->second;
507
      }
508

	
431 509
      if (local_is) {
... ...
@@ -576,2 +654,79 @@
576 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
    
730
    /// @}
731

	
577 732
    /// \name Using previously constructed node or arc set
... ...
@@ -931,2 +1086,3 @@
931 1086
      bool attributes_done = false;
1087
      std::set<std::string> extra_sections;
932 1088

	
... ...
@@ -964,4 +1120,16 @@
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
	  }
0 comments (0 inline)