1.1 --- a/lemon/lgf_writer.h Mon Aug 04 22:00:36 2008 +0200
1.2 +++ b/lemon/lgf_writer.h Sun Aug 17 13:39:04 2008 +0200
1.3 @@ -37,6 +37,9 @@
1.4 #include <lemon/core.h>
1.5 #include <lemon/maps.h>
1.6
1.7 +#include <lemon/concept_check.h>
1.8 +#include <lemon/concepts/maps.h>
1.9 +
1.10 namespace lemon {
1.11
1.12 namespace _writer_bits {
1.13 @@ -304,6 +307,45 @@
1.14 return os;
1.15 }
1.16
1.17 + class Section {
1.18 + public:
1.19 + virtual ~Section() {}
1.20 + virtual void process(std::ostream& os) = 0;
1.21 + };
1.22 +
1.23 + template <typename Functor>
1.24 + class LineSection : public Section {
1.25 + private:
1.26 +
1.27 + Functor _functor;
1.28 +
1.29 + public:
1.30 +
1.31 + LineSection(const Functor& functor) : _functor(functor) {}
1.32 + virtual ~LineSection() {}
1.33 +
1.34 + virtual void process(std::ostream& os) {
1.35 + std::string line;
1.36 + while (!(line = _functor()).empty()) os << line << std::endl;
1.37 + }
1.38 + };
1.39 +
1.40 + template <typename Functor>
1.41 + class StreamSection : public Section {
1.42 + private:
1.43 +
1.44 + Functor _functor;
1.45 +
1.46 + public:
1.47 +
1.48 + StreamSection(const Functor& functor) : _functor(functor) {}
1.49 + virtual ~StreamSection() {}
1.50 +
1.51 + virtual void process(std::ostream& os) {
1.52 + _functor(os);
1.53 + }
1.54 + };
1.55 +
1.56 }
1.57
1.58 template <typename Digraph>
1.59 @@ -1492,6 +1534,209 @@
1.60 GraphWriter<Graph> tmp(fn, graph);
1.61 return tmp;
1.62 }
1.63 +
1.64 + class SectionWriter;
1.65 +
1.66 + SectionWriter sectionWriter(std::istream& is);
1.67 + SectionWriter sectionWriter(const std::string& fn);
1.68 + SectionWriter sectionWriter(const char* fn);
1.69 +
1.70 + /// \ingroup lemon_io
1.71 + ///
1.72 + /// \brief Section writer class
1.73 + ///
1.74 + /// In the \ref lgf-format "LGF" file extra sections can be placed,
1.75 + /// which contain any data in arbitrary format. Such sections can be
1.76 + /// written with this class. A writing rule can be added to the
1.77 + /// class with two different functions. With the \c sectionLines()
1.78 + /// function a generator can write the section line-by-line, while
1.79 + /// with the \c sectionStream() member the section can be written to
1.80 + /// an output stream.
1.81 + class SectionWriter {
1.82 + private:
1.83 +
1.84 + std::ostream* _os;
1.85 + bool local_os;
1.86 +
1.87 + typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1.88 + Sections;
1.89 +
1.90 + Sections _sections;
1.91 +
1.92 + public:
1.93 +
1.94 + /// \brief Constructor
1.95 + ///
1.96 + /// Construct a section writer, which writes to the given output
1.97 + /// stream.
1.98 + SectionWriter(std::ostream& os)
1.99 + : _os(&os), local_os(false) {}
1.100 +
1.101 + /// \brief Constructor
1.102 + ///
1.103 + /// Construct a section writer, which writes into the given file.
1.104 + SectionWriter(const std::string& fn)
1.105 + : _os(new std::ofstream(fn.c_str())), local_os(true) {}
1.106 +
1.107 + /// \brief Constructor
1.108 + ///
1.109 + /// Construct a section writer, which writes into the given file.
1.110 + SectionWriter(const char* fn)
1.111 + : _os(new std::ofstream(fn)), local_os(true) {}
1.112 +
1.113 + /// \brief Destructor
1.114 + ~SectionWriter() {
1.115 + for (Sections::iterator it = _sections.begin();
1.116 + it != _sections.end(); ++it) {
1.117 + delete it->second;
1.118 + }
1.119 +
1.120 + if (local_os) {
1.121 + delete _os;
1.122 + }
1.123 +
1.124 + }
1.125 +
1.126 + private:
1.127 +
1.128 + friend SectionWriter sectionWriter(std::ostream& os);
1.129 + friend SectionWriter sectionWriter(const std::string& fn);
1.130 + friend SectionWriter sectionWriter(const char* fn);
1.131 +
1.132 + SectionWriter(SectionWriter& other)
1.133 + : _os(other._os), local_os(other.local_os) {
1.134 +
1.135 + other._os = 0;
1.136 + other.local_os = false;
1.137 +
1.138 + _sections.swap(other._sections);
1.139 + }
1.140 +
1.141 + SectionWriter& operator=(const SectionWriter&);
1.142 +
1.143 + public:
1.144 +
1.145 + /// \name Section writers
1.146 + /// @{
1.147 +
1.148 + /// \brief Add a section writer with line oriented writing
1.149 + ///
1.150 + /// The first parameter is the type descriptor of the section, the
1.151 + /// second is a generator with std::string values. At the writing
1.152 + /// process, the returned \c std::string will be written into the
1.153 + /// output file until it is an empty string.
1.154 + ///
1.155 + /// For example, an integer vector is written into a section.
1.156 + ///\code
1.157 + /// @numbers
1.158 + /// 12 45 23 78
1.159 + /// 4 28 38 28
1.160 + /// 23 6 16
1.161 + ///\endcode
1.162 + ///
1.163 + /// The generator is implemented as a struct.
1.164 + ///\code
1.165 + /// struct NumberSection {
1.166 + /// std::vector<int>::const_iterator _it, _end;
1.167 + /// NumberSection(const std::vector<int>& data)
1.168 + /// : _it(data.begin()), _end(data.end()) {}
1.169 + /// std::string operator()() {
1.170 + /// int rem_in_line = 4;
1.171 + /// std::ostringstream ls;
1.172 + /// while (rem_in_line > 0 && _it != _end) {
1.173 + /// ls << *(_it++) << ' ';
1.174 + /// --rem_in_line;
1.175 + /// }
1.176 + /// return ls.str();
1.177 + /// }
1.178 + /// };
1.179 + ///
1.180 + /// // ...
1.181 + ///
1.182 + /// writer.sectionLines("numbers", NumberSection(vec));
1.183 + ///\endcode
1.184 + template <typename Functor>
1.185 + SectionWriter& sectionLines(const std::string& type, Functor functor) {
1.186 + LEMON_ASSERT(!type.empty(), "Type is empty.");
1.187 + _sections.push_back(std::make_pair(type,
1.188 + new _writer_bits::LineSection<Functor>(functor)));
1.189 + return *this;
1.190 + }
1.191 +
1.192 +
1.193 + /// \brief Add a section writer with stream oriented writing
1.194 + ///
1.195 + /// The first parameter is the type of the section, the second is
1.196 + /// a functor, which takes a \c std::ostream& parameter. The
1.197 + /// functor writes the section to the output stream.
1.198 + /// \warning The last line must be closed with end-line character.
1.199 + template <typename Functor>
1.200 + SectionWriter& sectionStream(const std::string& type, Functor functor) {
1.201 + LEMON_ASSERT(!type.empty(), "Type is empty.");
1.202 + _sections.push_back(std::make_pair(type,
1.203 + new _writer_bits::StreamSection<Functor>(functor)));
1.204 + return *this;
1.205 + }
1.206 +
1.207 + /// @}
1.208 +
1.209 + public:
1.210 +
1.211 +
1.212 + /// \name Execution of the writer
1.213 + /// @{
1.214 +
1.215 + /// \brief Start the batch processing
1.216 + ///
1.217 + /// This function starts the batch processing.
1.218 + void run() {
1.219 +
1.220 + LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1.221 +
1.222 + for (Sections::iterator it = _sections.begin();
1.223 + it != _sections.end(); ++it) {
1.224 + (*_os) << '@' << it->first << std::endl;
1.225 + it->second->process(*_os);
1.226 + }
1.227 + }
1.228 +
1.229 + /// \brief Give back the stream of the writer
1.230 + ///
1.231 + /// Returns the stream of the writer
1.232 + std::ostream& ostream() {
1.233 + return *_os;
1.234 + }
1.235 +
1.236 + /// @}
1.237 +
1.238 + };
1.239 +
1.240 + /// \brief Return a \ref SectionWriter class
1.241 + ///
1.242 + /// This function just returns a \ref SectionWriter class.
1.243 + /// \relates SectionWriter
1.244 + inline SectionWriter sectionWriter(std::ostream& os) {
1.245 + SectionWriter tmp(os);
1.246 + return tmp;
1.247 + }
1.248 +
1.249 + /// \brief Return a \ref SectionWriter class
1.250 + ///
1.251 + /// This function just returns a \ref SectionWriter class.
1.252 + /// \relates SectionWriter
1.253 + inline SectionWriter sectionWriter(const std::string& fn) {
1.254 + SectionWriter tmp(fn);
1.255 + return tmp;
1.256 + }
1.257 +
1.258 + /// \brief Return a \ref SectionWriter class
1.259 + ///
1.260 + /// This function just returns a \ref SectionWriter class.
1.261 + /// \relates SectionWriter
1.262 + inline SectionWriter sectionWriter(const char* fn) {
1.263 + SectionWriter tmp(fn);
1.264 + return tmp;
1.265 + }
1.266 }
1.267
1.268 #endif