Section writer class
authorBalazs Dezso <deba@inf.elte.hu>
Sun, 17 Aug 2008 13:39:04 +0200
changeset 2488fada33fc60a
parent 247 f1158744a112
child 249 f0b89f242745
Section writer class
lemon/lgf_writer.h
     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