lemon/lgf_writer.h
changeset 278 931190050520
parent 240 bea328c5a8d3
child 290 f6899946c1ac
child 293 47fbc814aa31
equal deleted inserted replaced
17:a4d4bf19e1db 18:60d9653f7d1e
    34 #include <functional>
    34 #include <functional>
    35 
    35 
    36 #include <lemon/assert.h>
    36 #include <lemon/assert.h>
    37 #include <lemon/core.h>
    37 #include <lemon/core.h>
    38 #include <lemon/maps.h>
    38 #include <lemon/maps.h>
       
    39 
       
    40 #include <lemon/concept_check.h>
       
    41 #include <lemon/concepts/maps.h>
    39 
    42 
    40 namespace lemon {
    43 namespace lemon {
    41 
    44 
    42   namespace _writer_bits {
    45   namespace _writer_bits {
    43 
    46 
   302         os << str;
   305         os << str;
   303       }
   306       }
   304       return os;
   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   template <typename Digraph>
   351   template <typename Digraph>
   310   class DigraphWriter;
   352   class DigraphWriter;
   311 
   353 
  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