1490 template <typename Graph> |
1532 template <typename Graph> |
1491 GraphWriter<Graph> graphWriter(const char* fn, const Graph& graph) { |
1533 GraphWriter<Graph> graphWriter(const char* fn, const Graph& graph) { |
1492 GraphWriter<Graph> tmp(fn, graph); |
1534 GraphWriter<Graph> tmp(fn, graph); |
1493 return tmp; |
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 #endif |
1742 #endif |