COIN-OR::LEMON - Graph Library

Ticket #131: 5b77a093fd62.patch

File 5b77a093fd62.patch, 7.5 KB (added by Balazs Dezso, 11 years ago)
  • lemon/lgf_writer.h

    # HG changeset patch
    # User Balazs Dezso <deba@inf.elte.hu>
    # Date 1216994067 -7200
    # Node ID 5b77a093fd62e83e8812e2845d55ec637da13cc9
    # Parent  9ce7a01a95c7e5faa01c80e6697dad0e2d863291
    Section writer class
    
    diff -r 9ce7a01a95c7 -r 5b77a093fd62 lemon/lgf_writer.h
    a b  
    3636#include <lemon/assert.h>
    3737#include <lemon/core.h>
    3838#include <lemon/maps.h>
     39
     40#include <lemon/concept_check.h>
     41#include <lemon/concepts/maps.h>
    3942
    4043namespace lemon {
    4144
     
    303306      }
    304307      return os;
    305308    }
     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 (_functor(line)) 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    };
    306348
    307349  }
    308350
     
    14921534    GraphWriter<Graph> tmp(fn, graph);
    14931535    return tmp;
    14941536  }
     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  /// write with this class. A writing rule can be added to the class
     1551  /// with two different functions. With the \c sectionLines() function a
     1552  /// functor can write the section line-by-line, while with the \c
     1553  /// sectionStream() member the section can be written to an output
     1554  /// 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 to 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 to 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 functor, which takes just one \c std::string
     1626    /// reference parameter and returns a bool value. At the writing
     1627    /// process, while the functor gives back true, the \c std::string
     1628    /// parameter will be written to the output file. If the output is
     1629    /// done, the functor should be give back false.
     1630    ///
     1631    /// For example let's see that the content of an integer vector
     1632    /// should be written to a section.
     1633    ///
     1634    ///\code
     1635    ///  @numbers
     1636    ///  12 45 23 78
     1637    ///  4 28 38 28
     1638    ///  23 6 16
     1639    ///\endcode
     1640    ///
     1641    /// The functor is implemented as a struct:
     1642    ///\code
     1643    ///  struct NumberSection {
     1644    ///    std::vector<int>::const_iterator _it, _end;
     1645    ///    NumberSection(const std::vector<int>& data)
     1646    ///      : _it(data.begin()), _end(data.end()) {}
     1647    ///    bool operator()(const std::string& line) {
     1648    ///      if (_it == _end) return false;
     1649    ///      int rem_in_line = 4;
     1650    ///      std::ostringstream ls;
     1651    ///      while (rem_in_line > 0 && _it != _end) {
     1652    ///        ls << *_it;
     1653    ///        ++_it; --rem_in_line;
     1654    ///      }
     1655    ///      line = ls.str();
     1656    ///      return true;
     1657    ///    }
     1658    ///  };
     1659    ///
     1660    ///  // ...
     1661    ///
     1662    ///  writer.sectionLines("numbers", NumberSection(vec));
     1663    ///\endcode
     1664    template <typename Functor>
     1665    SectionWriter& sectionLines(const std::string& type, Functor functor) {
     1666      LEMON_ASSERT(!type.empty(), "Type is empty.");
     1667      _sections.push_back(std::make_pair(type,
     1668        new _writer_bits::LineSection<Functor>(functor)));
     1669      return *this;
     1670    }
     1671
     1672
     1673    /// \brief Add a section writer with stream oriented writing
     1674    ///
     1675    /// The first parameter is the type of the section, the second is
     1676    /// a functor, which takes an \c std::ostream& parameter. The
     1677    /// functor writes the section to the output stream. The last line
     1678    /// must closed with end-line.
     1679    template <typename Functor>
     1680    SectionWriter& sectionStream(const std::string& type, Functor functor) {
     1681      LEMON_ASSERT(!type.empty(), "Type is empty.");
     1682      _sections.push_back(std::make_pair(type,
     1683         new _writer_bits::StreamSection<Functor>(functor)));
     1684      return *this;
     1685    }
     1686
     1687    /// @}
     1688
     1689  public:
     1690
     1691
     1692    /// \name Execution of the writer
     1693    /// @{
     1694
     1695    /// \brief Start the batch processing
     1696    ///
     1697    /// This function starts the batch processing.
     1698    void run() {
     1699
     1700      LEMON_ASSERT(_os != 0, "This writer assigned to an other writer");
     1701
     1702      for (Sections::iterator it = _sections.begin();
     1703           it != _sections.end(); ++it) {
     1704        (*_os) << '@' << it->first << std::endl;
     1705        it->second->process(*_os);
     1706      }
     1707    }
     1708
     1709    /// \brief Give back the stream of the writer
     1710    ///
     1711    /// Give back the stream of the writer
     1712    std::ostream& ostream() {
     1713      return *_os;
     1714    }
     1715
     1716    /// @}
     1717
     1718  };
     1719
     1720  /// \brief Return a \ref SectionWriter class
     1721  ///
     1722  /// This function just returns a \ref SectionWriter class.
     1723  /// \relates SectionWriter
     1724  inline SectionWriter sectionWriter(std::ostream& os) {
     1725    SectionWriter tmp(os);
     1726    return tmp;
     1727  }
     1728
     1729  /// \brief Return a \ref SectionWriter class
     1730  ///
     1731  /// This function just returns a \ref SectionWriter class.
     1732  /// \relates SectionWriter
     1733  inline SectionWriter sectionWriter(const std::string& fn) {
     1734    SectionWriter tmp(fn);
     1735    return tmp;
     1736  }
     1737
     1738  /// \brief Return a \ref SectionWriter class
     1739  ///
     1740  /// This function just returns a \ref SectionWriter class.
     1741  /// \relates SectionWriter
     1742  inline SectionWriter sectionWriter(const char* fn) {
     1743    SectionWriter tmp(fn);
     1744    return tmp;
     1745  }
    14951746}
    14961747
    14971748#endif