gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Section writer class
0 1 0
default
1 file changed with 245 insertions and 0 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -37,6 +37,9 @@
37 37
#include <lemon/core.h>
38 38
#include <lemon/maps.h>
39 39

	
40
#include <lemon/concept_check.h>
41
#include <lemon/concepts/maps.h>
42

	
40 43
namespace lemon {
41 44

	
42 45
  namespace _writer_bits {
... ...
@@ -304,6 +307,45 @@
304 307
      return os;
305 308
    }
306 309

	
310
    class Section {
311
    public:
312
      virtual ~Section() {}
313
      virtual void process(std::ostream& os) = 0;
314
    };
315

	
316
    template <typename Functor>
317
    class LineSection : public Section {
318
    private:
319

	
320
      Functor _functor;
321

	
322
    public:
323

	
324
      LineSection(const Functor& functor) : _functor(functor) {}
325
      virtual ~LineSection() {}
326

	
327
      virtual void process(std::ostream& os) {
328
        std::string line;
329
        while (!(line = _functor()).empty()) os << line << std::endl;
330
      }
331
    };
332

	
333
    template <typename Functor>
334
    class StreamSection : public Section {
335
    private:
336

	
337
      Functor _functor;
338

	
339
    public:
340

	
341
      StreamSection(const Functor& functor) : _functor(functor) {}
342
      virtual ~StreamSection() {}
343

	
344
      virtual void process(std::ostream& os) {
345
        _functor(os);
346
      }
347
    };
348

	
307 349
  }
308 350

	
309 351
  template <typename Digraph>
... ...
@@ -1492,6 +1534,209 @@
1492 1534
    GraphWriter<Graph> tmp(fn, graph);
1493 1535
    return tmp;
1494 1536
  }
1537

	
1538
  class SectionWriter;
1539

	
1540
  SectionWriter sectionWriter(std::istream& is);
1541
  SectionWriter sectionWriter(const std::string& fn);
1542
  SectionWriter sectionWriter(const char* fn);
1543

	
1544
  /// \ingroup lemon_io
1545
  ///
1546
  /// \brief Section writer class
1547
  ///
1548
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
1549
  /// which contain any data in arbitrary format. Such sections can be
1550
  /// written with this class. A writing rule can be added to the
1551
  /// class with two different functions. With the \c sectionLines()
1552
  /// function a generator can write the section line-by-line, while
1553
  /// with the \c sectionStream() member the section can be written to
1554
  /// an output stream.
1555
  class SectionWriter {
1556
  private:
1557

	
1558
    std::ostream* _os;
1559
    bool local_os;
1560

	
1561
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1562
    Sections;
1563

	
1564
    Sections _sections;
1565

	
1566
  public:
1567

	
1568
    /// \brief Constructor
1569
    ///
1570
    /// Construct a section writer, which writes to the given output
1571
    /// stream.
1572
    SectionWriter(std::ostream& os)
1573
      : _os(&os), local_os(false) {}
1574

	
1575
    /// \brief Constructor
1576
    ///
1577
    /// Construct a section writer, which writes into the given file.
1578
    SectionWriter(const std::string& fn)
1579
      : _os(new std::ofstream(fn.c_str())), local_os(true) {}
1580

	
1581
    /// \brief Constructor
1582
    ///
1583
    /// Construct a section writer, which writes into the given file.
1584
    SectionWriter(const char* fn)
1585
      : _os(new std::ofstream(fn)), local_os(true) {}
1586

	
1587
    /// \brief Destructor
1588
    ~SectionWriter() {
1589
      for (Sections::iterator it = _sections.begin();
1590
           it != _sections.end(); ++it) {
1591
        delete it->second;
1592
      }
1593

	
1594
      if (local_os) {
1595
        delete _os;
1596
      }
1597

	
1598
    }
1599

	
1600
  private:
1601

	
1602
    friend SectionWriter sectionWriter(std::ostream& os);
1603
    friend SectionWriter sectionWriter(const std::string& fn);
1604
    friend SectionWriter sectionWriter(const char* fn);
1605

	
1606
    SectionWriter(SectionWriter& other)
1607
      : _os(other._os), local_os(other.local_os) {
1608

	
1609
      other._os = 0;
1610
      other.local_os = false;
1611

	
1612
      _sections.swap(other._sections);
1613
    }
1614

	
1615
    SectionWriter& operator=(const SectionWriter&);
1616

	
1617
  public:
1618

	
1619
    /// \name Section writers
1620
    /// @{
1621

	
1622
    /// \brief Add a section writer with line oriented writing
1623
    ///
1624
    /// The first parameter is the type descriptor of the section, the
1625
    /// second is a generator with std::string values. At the writing
1626
    /// process, the returned \c std::string will be written into the
1627
    /// output file until it is an empty string.
1628
    ///
1629
    /// For example, an integer vector is written into a section.
1630
    ///\code
1631
    ///  @numbers
1632
    ///  12 45 23 78
1633
    ///  4 28 38 28
1634
    ///  23 6 16
1635
    ///\endcode
1636
    ///
1637
    /// The generator is implemented as a struct.
1638
    ///\code
1639
    ///  struct NumberSection {
1640
    ///    std::vector<int>::const_iterator _it, _end;
1641
    ///    NumberSection(const std::vector<int>& data)
1642
    ///      : _it(data.begin()), _end(data.end()) {}
1643
    ///    std::string operator()() {
1644
    ///      int rem_in_line = 4;
1645
    ///      std::ostringstream ls;
1646
    ///      while (rem_in_line > 0 && _it != _end) {
1647
    ///        ls << *(_it++) << ' ';
1648
    ///        --rem_in_line;
1649
    ///      }
1650
    ///      return ls.str();
1651
    ///    }
1652
    ///  };
1653
    ///
1654
    ///  // ...
1655
    ///
1656
    ///  writer.sectionLines("numbers", NumberSection(vec));
1657
    ///\endcode
1658
    template <typename Functor>
1659
    SectionWriter& sectionLines(const std::string& type, Functor functor) {
1660
      LEMON_ASSERT(!type.empty(), "Type is empty.");
1661
      _sections.push_back(std::make_pair(type,
1662
        new _writer_bits::LineSection<Functor>(functor)));
1663
      return *this;
1664
    }
1665

	
1666

	
1667
    /// \brief Add a section writer with stream oriented writing
1668
    ///
1669
    /// The first parameter is the type of the section, the second is
1670
    /// a functor, which takes a \c std::ostream& parameter. The
1671
    /// functor writes the section to the output stream.
1672
    /// \warning The last line must be closed with end-line character.
1673
    template <typename Functor>
1674
    SectionWriter& sectionStream(const std::string& type, Functor functor) {
1675
      LEMON_ASSERT(!type.empty(), "Type is empty.");
1676
      _sections.push_back(std::make_pair(type,
1677
         new _writer_bits::StreamSection<Functor>(functor)));
1678
      return *this;
1679
    }
1680

	
1681
    /// @}
1682

	
1683
  public:
1684

	
1685

	
1686
    /// \name Execution of the writer
1687
    /// @{
1688

	
1689
    /// \brief Start the batch processing
1690
    ///
1691
    /// This function starts the batch processing.
1692
    void run() {
1693

	
1694
      LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1695

	
1696
      for (Sections::iterator it = _sections.begin();
1697
           it != _sections.end(); ++it) {
1698
        (*_os) << '@' << it->first << std::endl;
1699
        it->second->process(*_os);
1700
      }
1701
    }
1702

	
1703
    /// \brief Give back the stream of the writer
1704
    ///
1705
    /// Returns the stream of the writer
1706
    std::ostream& ostream() {
1707
      return *_os;
1708
    }
1709

	
1710
    /// @}
1711

	
1712
  };
1713

	
1714
  /// \brief Return a \ref SectionWriter class
1715
  ///
1716
  /// This function just returns a \ref SectionWriter class.
1717
  /// \relates SectionWriter
1718
  inline SectionWriter sectionWriter(std::ostream& os) {
1719
    SectionWriter tmp(os);
1720
    return tmp;
1721
  }
1722

	
1723
  /// \brief Return a \ref SectionWriter class
1724
  ///
1725
  /// This function just returns a \ref SectionWriter class.
1726
  /// \relates SectionWriter
1727
  inline SectionWriter sectionWriter(const std::string& fn) {
1728
    SectionWriter tmp(fn);
1729
    return tmp;
1730
  }
1731

	
1732
  /// \brief Return a \ref SectionWriter class
1733
  ///
1734
  /// This function just returns a \ref SectionWriter class.
1735
  /// \relates SectionWriter
1736
  inline SectionWriter sectionWriter(const char* fn) {
1737
    SectionWriter tmp(fn);
1738
    return tmp;
1739
  }
1495 1740
}
1496 1741

	
1497 1742
#endif
0 comments (0 inline)