... | ... |
@@ -34,12 +34,15 @@ |
34 | 34 |
#include <functional> |
35 | 35 |
|
36 | 36 |
#include <lemon/assert.h> |
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 { |
43 | 46 |
|
44 | 47 |
template <typename Value> |
45 | 48 |
struct DefaultConverter { |
... | ... |
@@ -301,12 +304,51 @@ |
301 | 304 |
} else { |
302 | 305 |
os << str; |
303 | 306 |
} |
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> |
310 | 352 |
class DigraphWriter; |
311 | 353 |
|
312 | 354 |
template <typename Digraph> |
... | ... |
@@ -1489,9 +1531,212 @@ |
1489 | 1531 |
/// \relates GraphWriter |
1490 | 1532 |
template <typename Graph> |
1491 | 1533 |
GraphWriter<Graph> graphWriter(const char* fn, const Graph& graph) { |
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)