gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Changing parameter order in exception classes + improvements
0 4 0
default
4 files changed with 82 insertions and 85 deletions:
↑ Collapse diff ↑
Ignore white space 131072 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_ERROR_H
20 20
#define LEMON_ERROR_H
21 21

	
22 22
/// \ingroup exceptions
23 23
/// \file
24 24
/// \brief Basic exception classes and error handling.
25 25

	
26 26
#include <exception>
27 27
#include <string>
28 28
#include <sstream>
29 29
#include <iostream>
30 30
#include <cstdlib>
31 31
#include <memory>
32 32

	
33 33
namespace lemon {
34 34

	
35 35
  /// \addtogroup exceptions
36 36
  /// @{
37 37

	
38 38
  /// \brief Generic exception class.
39 39
  ///
40 40
  /// Base class for exceptions used in LEMON.
41 41
  ///
42 42
  class Exception : public std::exception {
43 43
  public:
44
    ///\e Constructor
45
    Exception() {}
46
    ///\e Virtual destructor
44
    ///Constructor
45
    Exception() throw() {}
46
    ///Virtual destructor
47 47
    virtual ~Exception() throw() {}
48
    ///\e A short description of the exception
48
    ///A short description of the exception
49 49
    virtual const char* what() const throw() {
50 50
      return "lemon::Exception";
51 51
    }
52 52
  };
53 53

	
54 54
  /// \brief Input-Output error
55 55
  ///
56 56
  /// This exception is thrown when a file operation cannot be
57 57
  /// succeeded.
58 58
  class IoError : public Exception {
59 59
  protected:
60 60
    std::string _message;
61 61
    std::string _file;
62 62

	
63 63
    mutable std::string _what;
64 64
  public:
65 65

	
66 66
    /// Copy constructor
67
    IoError(const IoError &error) {
67
    IoError(const IoError &error) throw() : Exception() {
68 68
      message(error._message);
69 69
      file(error._file);
70 70
    }
71 71

	
72 72
    /// Constructor
73
    explicit IoError(const char *message) {
73
    explicit IoError(const char *message) throw() {
74 74
      IoError::message(message);
75 75
    }
76 76

	
77 77
    /// Constructor
78
    explicit IoError(const std::string &message) {
78
    explicit IoError(const std::string &message) throw() {
79 79
      IoError::message(message);
80 80
    }
81 81

	
82 82
    /// Constructor
83
    IoError(const std::string &file, const char *message) {
83
    explicit IoError(const char *message,
84
                     const std::string &file) throw() {
84 85
      IoError::message(message);
85 86
      IoError::file(file);
86 87
    }
87 88

	
88 89
    /// Constructor
89
    IoError(const std::string &file, const std::string &message) {
90
    explicit IoError(const std::string &message,
91
                     const std::string &file) throw() {
90 92
      IoError::message(message);
91 93
      IoError::file(file);
92 94
    }
93 95

	
94 96
    /// Virtual destructor
95 97
    virtual ~IoError() throw() {}
96 98

	
97 99
    /// Set the error message
98
    void message(const char *message) {
100
    void message(const char *message) throw() {
99 101
      try {
100 102
        _message = message;
101 103
      } catch (...) {}
102 104
    }
103 105

	
104 106
    /// Set the error message
105
    void message(const std::string& message) {
107
    void message(const std::string& message) throw() {
106 108
      try {
107 109
        _message = message;
108 110
      } catch (...) {}
109 111
    }
110 112

	
111 113
    /// Set the file name
112
    void file(const std::string &file) {
114
    void file(const std::string &file) throw() {
113 115
      try {
114 116
        _file = file;
115 117
      } catch (...) {}
116 118
    }
117 119

	
118 120
    /// Returns the error message
119
    const std::string& message() const {
121
    const std::string& message() const throw() {
120 122
      return _message;
121 123
    }
122 124

	
123 125
    /// \brief Returns the filename
124 126
    ///
125
    /// Returns the filename or empty string if the filename was not
126
    /// specified.
127
    const std::string& file() const {
127
    /// Returns the filename or an empty string if it was not specified.
128
    const std::string& file() const throw() {
128 129
      return _file;
129 130
    }
130 131

	
131 132
    /// \brief Returns a short error message
132 133
    ///
133
    /// Returns a short error message which contains the message, the
134
    /// file name and the line number.
134
    /// Returns a short error message which contains the message and the
135
    /// file name.
135 136
    virtual const char* what() const throw() {
136 137
      try {
137 138
        _what.clear();
138 139
        std::ostringstream oss;
139 140
        oss << "lemon:IoError" << ": ";
140
        oss << message();
141
        if (!file().empty()) {
142
          oss << " (";
143
          if (!file().empty()) oss << "with file '" << file() << "'";
144
          oss << ")";
141
        oss << _message;
142
        if (!_file.empty()) {
143
          oss << " ('" << _file << "')";
145 144
        }
146 145
        _what = oss.str();
147 146
      }
148 147
      catch (...) {}
149 148
      if (!_what.empty()) return _what.c_str();
150 149
      else return "lemon:IoError";
151 150
    }
152 151

	
153 152
  };
154 153

	
155 154
  /// \brief Format error
156 155
  ///
157
  /// This class is used to indicate if an input file has wrong
158
  /// formatting, or a data representation is not legal.
156
  /// This exception is thrown when an input file has wrong
157
  /// format or a data representation is not legal.
159 158
  class FormatError : public Exception {
160 159
  protected:
161 160
    std::string _message;
162 161
    std::string _file;
163 162
    int _line;
164 163

	
165 164
    mutable std::string _what;
166 165
  public:
167 166

	
168 167
    /// Copy constructor
169
    FormatError(const FormatError &error) {
168
    FormatError(const FormatError &error) throw() : Exception() {
170 169
      message(error._message);
171 170
      file(error._file);
172 171
      line(error._line);
173 172
    }
174 173

	
175 174
    /// Constructor
176
    explicit FormatError(const char *message) {
175
    explicit FormatError(const char *message) throw() {
177 176
      FormatError::message(message);
178 177
      _line = 0;
179 178
    }
180 179

	
181 180
    /// Constructor
182
    explicit FormatError(const std::string &message) {
181
    explicit FormatError(const std::string &message) throw() {
183 182
      FormatError::message(message);
184 183
      _line = 0;
185 184
    }
186 185

	
187 186
    /// Constructor
188
    FormatError(const std::string &file, int line, const char *message) {
187
    explicit FormatError(const char *message,
188
                         const std::string &file, int line = 0) throw() {
189 189
      FormatError::message(message);
190 190
      FormatError::file(file);
191 191
      FormatError::line(line);
192 192
    }
193 193

	
194 194
    /// Constructor
195
    FormatError(const std::string &file, int line, const std::string &message) {
195
    explicit FormatError(const std::string &message,
196
                         const std::string &file, int line = 0) throw() {
196 197
      FormatError::message(message);
197 198
      FormatError::file(file);
198 199
      FormatError::line(line);
199 200
    }
200 201

	
201 202
    /// Virtual destructor
202 203
    virtual ~FormatError() throw() {}
203 204

	
204 205
    /// Set the line number
205
    void line(int line) { _line = line; }
206
    void line(int line) throw() { _line = line; }
206 207

	
207 208
    /// Set the error message
208
    void message(const char *message) {
209
    void message(const char *message) throw() {
209 210
      try {
210 211
        _message = message;
211 212
      } catch (...) {}
212 213
    }
213 214

	
214 215
    /// Set the error message
215
    void message(const std::string& message) {
216
    void message(const std::string& message) throw() {
216 217
      try {
217 218
        _message = message;
218 219
      } catch (...) {}
219 220
    }
220 221

	
221 222
    /// Set the file name
222
    void file(const std::string &file) {
223
    void file(const std::string &file) throw() {
223 224
      try {
224 225
        _file = file;
225 226
      } catch (...) {}
226 227
    }
227 228

	
228 229
    /// \brief Returns the line number
229 230
    ///
230 231
    /// Returns the line number or zero if it was not specified.
231
    int line() const { return _line; }
232
    int line() const throw() { return _line; }
232 233

	
233 234
    /// Returns the error message
234
    const std::string& message() const {
235
    const std::string& message() const throw() {
235 236
      return _message;
236 237
    }
237 238

	
238 239
    /// \brief Returns the filename
239 240
    ///
240
    /// Returns the filename or empty string if the filename was not
241
    /// specified.
242
    const std::string& file() const {
241
    /// Returns the filename or an empty string if it was not specified.
242
    const std::string& file() const throw() {
243 243
      return _file;
244 244
    }
245 245

	
246 246
    /// \brief Returns a short error message
247 247
    ///
248 248
    /// Returns a short error message which contains the message, the
249 249
    /// file name and the line number.
250 250
    virtual const char* what() const throw() {
251 251
      try {
252 252
        _what.clear();
253 253
        std::ostringstream oss;
254 254
        oss << "lemon:FormatError" << ": ";
255
        oss << message();
256
        if (!file().empty() || line() != 0) {
255
        oss << _message;
256
        if (!_file.empty() || _line != 0) {
257 257
          oss << " (";
258
          if (!file().empty()) oss << "in file '" << file() << "'";
259
          if (!file().empty() && line() != 0) oss << " ";
260
          if (line() != 0) oss << "at line " << line();
258
          if (!_file.empty()) oss << "in file '" << _file << "'";
259
          if (!_file.empty() && _line != 0) oss << " ";
260
          if (_line != 0) oss << "at line " << _line;
261 261
          oss << ")";
262 262
        }
263 263
        _what = oss.str();
264 264
      }
265 265
      catch (...) {}
266 266
      if (!_what.empty()) return _what.c_str();
267 267
      else return "lemon:FormatError";
268 268
    }
269 269

	
270 270
  };
271 271

	
272 272
  /// @}
273 273

	
274 274
}
275 275

	
276 276
#endif // LEMON_ERROR_H
Ignore white space 131072 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_GRAPH_TO_EPS_H
20 20
#define LEMON_GRAPH_TO_EPS_H
21 21

	
22 22
#include<iostream>
23 23
#include<fstream>
24 24
#include<sstream>
25 25
#include<algorithm>
26 26
#include<vector>
27 27

	
28 28
#ifndef WIN32
29 29
#include<sys/time.h>
30 30
#include<ctime>
31 31
#else
32 32
#define WIN32_LEAN_AND_MEAN
33 33
#define NOMINMAX
34 34
#include<windows.h>
35 35
#endif
36 36

	
37 37
#include<lemon/math.h>
38 38
#include<lemon/core.h>
39 39
#include<lemon/dim2.h>
40 40
#include<lemon/maps.h>
41 41
#include<lemon/color.h>
42 42
#include<lemon/bits/bezier.h>
43 43
#include<lemon/error.h>
44 44

	
45 45

	
46 46
///\ingroup eps_io
47 47
///\file
48 48
///\brief A well configurable tool for visualizing graphs
49 49

	
50 50
namespace lemon {
51 51

	
52 52
  namespace _graph_to_eps_bits {
53 53
    template<class MT>
54 54
    class _NegY {
55 55
    public:
56 56
      typedef typename MT::Key Key;
57 57
      typedef typename MT::Value Value;
58 58
      const MT &map;
59 59
      int yscale;
60 60
      _NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
61 61
      Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
62 62
    };
63 63
  }
64 64

	
65 65
///Default traits class of \ref GraphToEps
66 66

	
67 67
///Default traits class of \ref GraphToEps.
68 68
///
69 69
///\c G is the type of the underlying graph.
70 70
template<class G>
71 71
struct DefaultGraphToEpsTraits
72 72
{
73 73
  typedef G Graph;
74 74
  typedef typename Graph::Node Node;
75 75
  typedef typename Graph::NodeIt NodeIt;
76 76
  typedef typename Graph::Arc Arc;
77 77
  typedef typename Graph::ArcIt ArcIt;
78 78
  typedef typename Graph::InArcIt InArcIt;
79 79
  typedef typename Graph::OutArcIt OutArcIt;
80 80

	
81 81

	
82 82
  const Graph &g;
83 83

	
84 84
  std::ostream& os;
85 85

	
86 86
  typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType;
87 87
  CoordsMapType _coords;
88 88
  ConstMap<typename Graph::Node,double > _nodeSizes;
89 89
  ConstMap<typename Graph::Node,int > _nodeShapes;
90 90

	
91 91
  ConstMap<typename Graph::Node,Color > _nodeColors;
92 92
  ConstMap<typename Graph::Arc,Color > _arcColors;
93 93

	
94 94
  ConstMap<typename Graph::Arc,double > _arcWidths;
95 95

	
96 96
  double _arcWidthScale;
97 97

	
98 98
  double _nodeScale;
99 99
  double _xBorder, _yBorder;
100 100
  double _scale;
101 101
  double _nodeBorderQuotient;
102 102

	
103 103
  bool _drawArrows;
104 104
  double _arrowLength, _arrowWidth;
105 105

	
106 106
  bool _showNodes, _showArcs;
107 107

	
108 108
  bool _enableParallel;
109 109
  double _parArcDist;
110 110

	
111 111
  bool _showNodeText;
112 112
  ConstMap<typename Graph::Node,bool > _nodeTexts;
113 113
  double _nodeTextSize;
114 114

	
115 115
  bool _showNodePsText;
116 116
  ConstMap<typename Graph::Node,bool > _nodePsTexts;
117 117
  char *_nodePsTextsPreamble;
118 118

	
119 119
  bool _undirected;
120 120

	
121 121
  bool _pleaseRemoveOsStream;
122 122

	
123 123
  bool _scaleToA4;
124 124

	
125 125
  std::string _title;
126 126
  std::string _copyright;
127 127

	
128 128
  enum NodeTextColorType
129 129
    { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
130 130
  ConstMap<typename Graph::Node,Color > _nodeTextColors;
131 131

	
132 132
  bool _autoNodeScale;
133 133
  bool _autoArcWidthScale;
134 134

	
135 135
  bool _absoluteNodeSizes;
136 136
  bool _absoluteArcWidths;
137 137

	
138 138
  bool _negY;
139 139

	
140 140
  bool _preScale;
141 141
  ///Constructor
142 142

	
143 143
  ///Constructor
144 144
  ///\param _g  Reference to the graph to be printed.
145 145
  ///\param _os Reference to the output stream.
146 146
  ///\param _os Reference to the output stream.
147 147
  ///By default it is <tt>std::cout</tt>.
148 148
  ///\param _pros If it is \c true, then the \c ostream referenced by \c _os
149 149
  ///will be explicitly deallocated by the destructor.
150 150
  DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
151 151
                          bool _pros=false) :
152 152
    g(_g), os(_os),
153 153
    _coords(dim2::Point<double>(1,1)), _nodeSizes(1), _nodeShapes(0),
154 154
    _nodeColors(WHITE), _arcColors(BLACK),
155 155
    _arcWidths(1.0), _arcWidthScale(0.003),
156 156
    _nodeScale(.01), _xBorder(10), _yBorder(10), _scale(1.0),
157 157
    _nodeBorderQuotient(.1),
158 158
    _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
159 159
    _showNodes(true), _showArcs(true),
160 160
    _enableParallel(false), _parArcDist(1),
161 161
    _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
162 162
    _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
163 163
    _undirected(lemon::UndirectedTagIndicator<G>::value),
164 164
    _pleaseRemoveOsStream(_pros), _scaleToA4(false),
165 165
    _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
166 166
    _autoNodeScale(false),
167 167
    _autoArcWidthScale(false),
168 168
    _absoluteNodeSizes(false),
169 169
    _absoluteArcWidths(false),
170 170
    _negY(false),
171 171
    _preScale(true)
172 172
  {}
173 173
};
174 174

	
175 175
///Auxiliary class to implement the named parameters of \ref graphToEps()
176 176

	
177 177
///Auxiliary class to implement the named parameters of \ref graphToEps().
178 178
///
179 179
///For detailed examples see the \ref graph_to_eps_demo.cc demo file.
180 180
template<class T> class GraphToEps : public T
181 181
{
182 182
  // Can't believe it is required by the C++ standard
183 183
  using T::g;
184 184
  using T::os;
185 185

	
186 186
  using T::_coords;
187 187
  using T::_nodeSizes;
188 188
  using T::_nodeShapes;
189 189
  using T::_nodeColors;
190 190
  using T::_arcColors;
191 191
  using T::_arcWidths;
192 192

	
193 193
  using T::_arcWidthScale;
194 194
  using T::_nodeScale;
195 195
  using T::_xBorder;
196 196
  using T::_yBorder;
197 197
  using T::_scale;
198 198
  using T::_nodeBorderQuotient;
199 199

	
200 200
  using T::_drawArrows;
201 201
  using T::_arrowLength;
202 202
  using T::_arrowWidth;
203 203

	
204 204
  using T::_showNodes;
205 205
  using T::_showArcs;
206 206

	
207 207
  using T::_enableParallel;
208 208
  using T::_parArcDist;
209 209

	
210 210
  using T::_showNodeText;
211 211
  using T::_nodeTexts;
212 212
  using T::_nodeTextSize;
213 213

	
214 214
  using T::_showNodePsText;
215 215
  using T::_nodePsTexts;
216 216
  using T::_nodePsTextsPreamble;
217 217

	
218 218
  using T::_undirected;
219 219

	
220 220
  using T::_pleaseRemoveOsStream;
221 221

	
222 222
  using T::_scaleToA4;
223 223

	
224 224
  using T::_title;
225 225
  using T::_copyright;
226 226

	
227 227
  using T::NodeTextColorType;
228 228
  using T::CUST_COL;
229 229
  using T::DIST_COL;
230 230
  using T::DIST_BW;
231 231
  using T::_nodeTextColorType;
232 232
  using T::_nodeTextColors;
233 233

	
234 234
  using T::_autoNodeScale;
235 235
  using T::_autoArcWidthScale;
236 236

	
237 237
  using T::_absoluteNodeSizes;
238 238
  using T::_absoluteArcWidths;
239 239

	
240 240

	
241 241
  using T::_negY;
242 242
  using T::_preScale;
243 243

	
244 244
  // dradnats ++C eht yb deriuqer si ti eveileb t'naC
245 245

	
246 246
  typedef typename T::Graph Graph;
247 247
  typedef typename Graph::Node Node;
248 248
  typedef typename Graph::NodeIt NodeIt;
249 249
  typedef typename Graph::Arc Arc;
250 250
  typedef typename Graph::ArcIt ArcIt;
251 251
  typedef typename Graph::InArcIt InArcIt;
252 252
  typedef typename Graph::OutArcIt OutArcIt;
253 253

	
254 254
  static const int INTERPOL_PREC;
255 255
  static const double A4HEIGHT;
256 256
  static const double A4WIDTH;
257 257
  static const double A4BORDER;
258 258

	
259 259
  bool dontPrint;
260 260

	
261 261
public:
262 262
  ///Node shapes
263 263

	
264 264
  ///Node shapes.
265 265
  ///
266 266
  enum NodeShapes {
267 267
    /// = 0
268 268
    ///\image html nodeshape_0.png
269 269
    ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm
270 270
    CIRCLE=0,
271 271
    /// = 1
272 272
    ///\image html nodeshape_1.png
273 273
    ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm
274 274
    ///
275 275
    SQUARE=1,
276 276
    /// = 2
277 277
    ///\image html nodeshape_2.png
278 278
    ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm
279 279
    ///
280 280
    DIAMOND=2,
281 281
    /// = 3
282 282
    ///\image html nodeshape_3.png
283 283
    ///\image latex nodeshape_2.eps "MALE shape (4)" width=2cm
284 284
    ///
285 285
    MALE=3,
286 286
    /// = 4
287 287
    ///\image html nodeshape_4.png
288 288
    ///\image latex nodeshape_2.eps "FEMALE shape (4)" width=2cm
289 289
    ///
290 290
    FEMALE=4
291 291
  };
292 292

	
293 293
private:
294 294
  class arcLess {
295 295
    const Graph &g;
296 296
  public:
297 297
    arcLess(const Graph &_g) : g(_g) {}
298 298
    bool operator()(Arc a,Arc b) const
299 299
    {
300 300
      Node ai=std::min(g.source(a),g.target(a));
301 301
      Node aa=std::max(g.source(a),g.target(a));
302 302
      Node bi=std::min(g.source(b),g.target(b));
303 303
      Node ba=std::max(g.source(b),g.target(b));
304 304
      return ai<bi ||
305 305
        (ai==bi && (aa < ba ||
306 306
                    (aa==ba && ai==g.source(a) && bi==g.target(b))));
307 307
    }
308 308
  };
309 309
  bool isParallel(Arc e,Arc f) const
310 310
  {
311 311
    return (g.source(e)==g.source(f)&&
312 312
            g.target(e)==g.target(f)) ||
313 313
      (g.source(e)==g.target(f)&&
314 314
       g.target(e)==g.source(f));
315 315
  }
316 316
  template<class TT>
317 317
  static std::string psOut(const dim2::Point<TT> &p)
318 318
    {
319 319
      std::ostringstream os;
320 320
      os << p.x << ' ' << p.y;
321 321
      return os.str();
322 322
    }
323 323
  static std::string psOut(const Color &c)
324 324
    {
325 325
      std::ostringstream os;
326 326
      os << c.red() << ' ' << c.green() << ' ' << c.blue();
327 327
      return os.str();
328 328
    }
329 329

	
330 330
public:
331 331
  GraphToEps(const T &t) : T(t), dontPrint(false) {};
332 332

	
333 333
  template<class X> struct CoordsTraits : public T {
334 334
  typedef X CoordsMapType;
335 335
    const X &_coords;
336 336
    CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
337 337
  };
338 338
  ///Sets the map of the node coordinates
339 339

	
340 340
  ///Sets the map of the node coordinates.
341 341
  ///\param x must be a node map with \ref dim2::Point "dim2::Point<double>" or
342 342
  ///\ref dim2::Point "dim2::Point<int>" values.
343 343
  template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
344 344
    dontPrint=true;
345 345
    return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
346 346
  }
347 347
  template<class X> struct NodeSizesTraits : public T {
348 348
    const X &_nodeSizes;
349 349
    NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
350 350
  };
351 351
  ///Sets the map of the node sizes
352 352

	
353 353
  ///Sets the map of the node sizes.
354 354
  ///\param x must be a node map with \c double (or convertible) values.
355 355
  template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
356 356
  {
357 357
    dontPrint=true;
358 358
    return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
359 359
  }
360 360
  template<class X> struct NodeShapesTraits : public T {
361 361
    const X &_nodeShapes;
362 362
    NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
363 363
  };
364 364
  ///Sets the map of the node shapes
365 365

	
366 366
  ///Sets the map of the node shapes.
367 367
  ///The available shape values
368 368
  ///can be found in \ref NodeShapes "enum NodeShapes".
369 369
  ///\param x must be a node map with \c int (or convertible) values.
370 370
  ///\sa NodeShapes
371 371
  template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
372 372
  {
373 373
    dontPrint=true;
374 374
    return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
375 375
  }
376 376
  template<class X> struct NodeTextsTraits : public T {
377 377
    const X &_nodeTexts;
378 378
    NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
379 379
  };
380 380
  ///Sets the text printed on the nodes
381 381

	
382 382
  ///Sets the text printed on the nodes.
383 383
  ///\param x must be a node map with type that can be pushed to a standard
384 384
  ///\c ostream.
385 385
  template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
386 386
  {
387 387
    dontPrint=true;
388 388
    _showNodeText=true;
389 389
    return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
390 390
  }
391 391
  template<class X> struct NodePsTextsTraits : public T {
392 392
    const X &_nodePsTexts;
393 393
    NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
394 394
  };
395 395
  ///Inserts a PostScript block to the nodes
396 396

	
397 397
  ///With this command it is possible to insert a verbatim PostScript
398 398
  ///block to the nodes.
399 399
  ///The PS current point will be moved to the center of the node before
400 400
  ///the PostScript block inserted.
401 401
  ///
402 402
  ///Before and after the block a newline character is inserted so you
403 403
  ///don't have to bother with the separators.
404 404
  ///
405 405
  ///\param x must be a node map with type that can be pushed to a standard
406 406
  ///\c ostream.
407 407
  ///
408 408
  ///\sa nodePsTextsPreamble()
409 409
  template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
410 410
  {
411 411
    dontPrint=true;
412 412
    _showNodePsText=true;
413 413
    return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
414 414
  }
415 415
  template<class X> struct ArcWidthsTraits : public T {
416 416
    const X &_arcWidths;
417 417
    ArcWidthsTraits(const T &t,const X &x) : T(t), _arcWidths(x) {}
418 418
  };
419 419
  ///Sets the map of the arc widths
420 420

	
421 421
  ///Sets the map of the arc widths.
422 422
  ///\param x must be an arc map with \c double (or convertible) values.
423 423
  template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x)
424 424
  {
425 425
    dontPrint=true;
426 426
    return GraphToEps<ArcWidthsTraits<X> >(ArcWidthsTraits<X>(*this,x));
427 427
  }
428 428

	
429 429
  template<class X> struct NodeColorsTraits : public T {
430 430
    const X &_nodeColors;
431 431
    NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
432 432
  };
433 433
  ///Sets the map of the node colors
434 434

	
435 435
  ///Sets the map of the node colors.
436 436
  ///\param x must be a node map with \ref Color values.
437 437
  ///
438 438
  ///\sa Palette
439 439
  template<class X> GraphToEps<NodeColorsTraits<X> >
440 440
  nodeColors(const X &x)
441 441
  {
442 442
    dontPrint=true;
443 443
    return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
444 444
  }
445 445
  template<class X> struct NodeTextColorsTraits : public T {
446 446
    const X &_nodeTextColors;
447 447
    NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
448 448
  };
449 449
  ///Sets the map of the node text colors
450 450

	
451 451
  ///Sets the map of the node text colors.
452 452
  ///\param x must be a node map with \ref Color values.
453 453
  ///
454 454
  ///\sa Palette
455 455
  template<class X> GraphToEps<NodeTextColorsTraits<X> >
456 456
  nodeTextColors(const X &x)
457 457
  {
458 458
    dontPrint=true;
459 459
    _nodeTextColorType=CUST_COL;
460 460
    return GraphToEps<NodeTextColorsTraits<X> >
461 461
      (NodeTextColorsTraits<X>(*this,x));
462 462
  }
463 463
  template<class X> struct ArcColorsTraits : public T {
464 464
    const X &_arcColors;
465 465
    ArcColorsTraits(const T &t,const X &x) : T(t), _arcColors(x) {}
466 466
  };
467 467
  ///Sets the map of the arc colors
468 468

	
469 469
  ///Sets the map of the arc colors.
470 470
  ///\param x must be an arc map with \ref Color values.
471 471
  ///
472 472
  ///\sa Palette
473 473
  template<class X> GraphToEps<ArcColorsTraits<X> >
474 474
  arcColors(const X &x)
475 475
  {
476 476
    dontPrint=true;
477 477
    return GraphToEps<ArcColorsTraits<X> >(ArcColorsTraits<X>(*this,x));
478 478
  }
479 479
  ///Sets a global scale factor for node sizes
480 480

	
481 481
  ///Sets a global scale factor for node sizes.
482 482
  ///
483 483
  /// If nodeSizes() is not given, this function simply sets the node
484 484
  /// sizes to \c d.  If nodeSizes() is given, but
485 485
  /// autoNodeScale() is not, then the node size given by
486 486
  /// nodeSizes() will be multiplied by the value \c d.
487 487
  /// If both nodeSizes() and autoNodeScale() are used, then the
488 488
  /// node sizes will be scaled in such a way that the greatest size will be
489 489
  /// equal to \c d.
490 490
  /// \sa nodeSizes()
491 491
  /// \sa autoNodeScale()
492 492
  GraphToEps<T> &nodeScale(double d=.01) {_nodeScale=d;return *this;}
493 493
  ///Turns on/off the automatic node size scaling.
494 494

	
495 495
  ///Turns on/off the automatic node size scaling.
496 496
  ///
497 497
  ///\sa nodeScale()
498 498
  ///
499 499
  GraphToEps<T> &autoNodeScale(bool b=true) {
500 500
    _autoNodeScale=b;return *this;
501 501
  }
502 502

	
503 503
  ///Turns on/off the absolutematic node size scaling.
504 504

	
505 505
  ///Turns on/off the absolutematic node size scaling.
506 506
  ///
507 507
  ///\sa nodeScale()
508 508
  ///
509 509
  GraphToEps<T> &absoluteNodeSizes(bool b=true) {
510 510
    _absoluteNodeSizes=b;return *this;
511 511
  }
512 512

	
513 513
  ///Negates the Y coordinates.
514 514
  GraphToEps<T> &negateY(bool b=true) {
515 515
    _negY=b;return *this;
516 516
  }
517 517

	
518 518
  ///Turn on/off pre-scaling
519 519

	
520 520
  ///By default graphToEps() rescales the whole image in order to avoid
521 521
  ///very big or very small bounding boxes.
522 522
  ///
523 523
  ///This (p)rescaling can be turned off with this function.
524 524
  ///
525 525
  GraphToEps<T> &preScale(bool b=true) {
526 526
    _preScale=b;return *this;
527 527
  }
528 528

	
529 529
  ///Sets a global scale factor for arc widths
530 530

	
531 531
  /// Sets a global scale factor for arc widths.
532 532
  ///
533 533
  /// If arcWidths() is not given, this function simply sets the arc
534 534
  /// widths to \c d.  If arcWidths() is given, but
535 535
  /// autoArcWidthScale() is not, then the arc withs given by
536 536
  /// arcWidths() will be multiplied by the value \c d.
537 537
  /// If both arcWidths() and autoArcWidthScale() are used, then the
538 538
  /// arc withs will be scaled in such a way that the greatest width will be
539 539
  /// equal to \c d.
540 540
  GraphToEps<T> &arcWidthScale(double d=.003) {_arcWidthScale=d;return *this;}
541 541
  ///Turns on/off the automatic arc width scaling.
542 542

	
543 543
  ///Turns on/off the automatic arc width scaling.
544 544
  ///
545 545
  ///\sa arcWidthScale()
546 546
  ///
547 547
  GraphToEps<T> &autoArcWidthScale(bool b=true) {
548 548
    _autoArcWidthScale=b;return *this;
549 549
  }
550 550
  ///Turns on/off the absolutematic arc width scaling.
551 551

	
552 552
  ///Turns on/off the absolutematic arc width scaling.
553 553
  ///
554 554
  ///\sa arcWidthScale()
555 555
  ///
556 556
  GraphToEps<T> &absoluteArcWidths(bool b=true) {
557 557
    _absoluteArcWidths=b;return *this;
558 558
  }
559 559
  ///Sets a global scale factor for the whole picture
560 560
  GraphToEps<T> &scale(double d) {_scale=d;return *this;}
561 561
  ///Sets the width of the border around the picture
562 562
  GraphToEps<T> &border(double b=10) {_xBorder=_yBorder=b;return *this;}
563 563
  ///Sets the width of the border around the picture
564 564
  GraphToEps<T> &border(double x, double y) {
565 565
    _xBorder=x;_yBorder=y;return *this;
566 566
  }
567 567
  ///Sets whether to draw arrows
568 568
  GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
569 569
  ///Sets the length of the arrowheads
570 570
  GraphToEps<T> &arrowLength(double d=1.0) {_arrowLength*=d;return *this;}
571 571
  ///Sets the width of the arrowheads
572 572
  GraphToEps<T> &arrowWidth(double d=.3) {_arrowWidth*=d;return *this;}
573 573

	
574 574
  ///Scales the drawing to fit to A4 page
575 575
  GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
576 576

	
577 577
  ///Enables parallel arcs
578 578
  GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
579 579

	
580 580
  ///Sets the distance between parallel arcs
581 581
  GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
582 582

	
583 583
  ///Hides the arcs
584 584
  GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
585 585
  ///Hides the nodes
586 586
  GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
587 587

	
588 588
  ///Sets the size of the node texts
589 589
  GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
590 590

	
591 591
  ///Sets the color of the node texts to be different from the node color
592 592

	
593 593
  ///Sets the color of the node texts to be as different from the node color
594 594
  ///as it is possible.
595 595
  GraphToEps<T> &distantColorNodeTexts()
596 596
  {_nodeTextColorType=DIST_COL;return *this;}
597 597
  ///Sets the color of the node texts to be black or white and always visible.
598 598

	
599 599
  ///Sets the color of the node texts to be black or white according to
600 600
  ///which is more different from the node color.
601 601
  GraphToEps<T> &distantBWNodeTexts()
602 602
  {_nodeTextColorType=DIST_BW;return *this;}
603 603

	
604 604
  ///Gives a preamble block for node Postscript block.
605 605

	
606 606
  ///Gives a preamble block for node Postscript block.
607 607
  ///
608 608
  ///\sa nodePsTexts()
609 609
  GraphToEps<T> & nodePsTextsPreamble(const char *str) {
610 610
    _nodePsTextsPreamble=str ;return *this;
611 611
  }
612 612
  ///Sets whether the graph is undirected
613 613

	
614 614
  ///Sets whether the graph is undirected.
615 615
  ///
616 616
  ///This setting is the default for undirected graphs.
617 617
  ///
618 618
  ///\sa directed()
619 619
   GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
620 620

	
621 621
  ///Sets whether the graph is directed
622 622

	
623 623
  ///Sets whether the graph is directed.
624 624
  ///Use it to show the edges as a pair of directed ones.
625 625
  ///
626 626
  ///This setting is the default for digraphs.
627 627
  ///
628 628
  ///\sa undirected()
629 629
  GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;}
630 630

	
631 631
  ///Sets the title.
632 632

	
633 633
  ///Sets the title of the generated image,
634 634
  ///namely it inserts a <tt>%%Title:</tt> DSC field to the header of
635 635
  ///the EPS file.
636 636
  GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
637 637
  ///Sets the copyright statement.
638 638

	
639 639
  ///Sets the copyright statement of the generated image,
640 640
  ///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of
641 641
  ///the EPS file.
642 642
  GraphToEps<T> &copyright(const std::string &t) {_copyright=t;return *this;}
643 643

	
644 644
protected:
645 645
  bool isInsideNode(dim2::Point<double> p, double r,int t)
646 646
  {
647 647
    switch(t) {
648 648
    case CIRCLE:
649 649
    case MALE:
650 650
    case FEMALE:
651 651
      return p.normSquare()<=r*r;
652 652
    case SQUARE:
653 653
      return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
654 654
    case DIAMOND:
655 655
      return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
656 656
    }
657 657
    return false;
658 658
  }
659 659

	
660 660
public:
661 661
  ~GraphToEps() { }
662 662

	
663 663
  ///Draws the graph.
664 664

	
665 665
  ///Like other functions using
666 666
  ///\ref named-templ-func-param "named template parameters",
667 667
  ///this function calls the algorithm itself, i.e. in this case
668 668
  ///it draws the graph.
669 669
  void run() {
670 670
    const double EPSILON=1e-9;
671 671
    if(dontPrint) return;
672 672

	
673 673
    _graph_to_eps_bits::_NegY<typename T::CoordsMapType>
674 674
      mycoords(_coords,_negY);
675 675

	
676 676
    os << "%!PS-Adobe-2.0 EPSF-2.0\n";
677 677
    if(_title.size()>0) os << "%%Title: " << _title << '\n';
678 678
     if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
679 679
    os << "%%Creator: LEMON, graphToEps()\n";
680 680

	
681 681
    {
682 682
#ifndef WIN32
683 683
      timeval tv;
684 684
      gettimeofday(&tv, 0);
685 685

	
686 686
      char cbuf[26];
687 687
      ctime_r(&tv.tv_sec,cbuf);
688 688
      os << "%%CreationDate: " << cbuf;
689 689
#else
690 690
      SYSTEMTIME time;
691 691
      char buf1[11], buf2[9], buf3[5];
692 692

	
693 693
      GetSystemTime(&time);
694 694
      if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
695 695
                        "ddd MMM dd", buf1, 11) &&
696 696
          GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time,
697 697
                        "HH':'mm':'ss", buf2, 9) &&
698 698
          GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
699 699
                                "yyyy", buf3, 5)) {
700 700
        os << "%%CreationDate: " << buf1 << ' '
701 701
           << buf2 << ' ' << buf3 << std::endl;
702 702
      }
703 703
#endif
704 704
    }
705 705

	
706 706
    if (_autoArcWidthScale) {
707 707
      double max_w=0;
708 708
      for(ArcIt e(g);e!=INVALID;++e)
709 709
        max_w=std::max(double(_arcWidths[e]),max_w);
710 710
      if(max_w>EPSILON) {
711 711
        _arcWidthScale/=max_w;
712 712
      }
713 713
    }
714 714

	
715 715
    if (_autoNodeScale) {
716 716
      double max_s=0;
717 717
      for(NodeIt n(g);n!=INVALID;++n)
718 718
        max_s=std::max(double(_nodeSizes[n]),max_s);
719 719
      if(max_s>EPSILON) {
720 720
        _nodeScale/=max_s;
721 721
      }
722 722
    }
723 723

	
724 724
    double diag_len = 1;
725 725
    if(!(_absoluteNodeSizes&&_absoluteArcWidths)) {
726 726
      dim2::Box<double> bb;
727 727
      for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
728 728
      if (bb.empty()) {
729 729
        bb = dim2::Box<double>(dim2::Point<double>(0,0));
730 730
      }
731 731
      diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
732 732
      if(diag_len<EPSILON) diag_len = 1;
733 733
      if(!_absoluteNodeSizes) _nodeScale*=diag_len;
734 734
      if(!_absoluteArcWidths) _arcWidthScale*=diag_len;
735 735
    }
736 736

	
737 737
    dim2::Box<double> bb;
738 738
    for(NodeIt n(g);n!=INVALID;++n) {
739 739
      double ns=_nodeSizes[n]*_nodeScale;
740 740
      dim2::Point<double> p(ns,ns);
741 741
      switch(_nodeShapes[n]) {
742 742
      case CIRCLE:
743 743
      case SQUARE:
744 744
      case DIAMOND:
745 745
        bb.add(p+mycoords[n]);
746 746
        bb.add(-p+mycoords[n]);
747 747
        break;
748 748
      case MALE:
749 749
        bb.add(-p+mycoords[n]);
750 750
        bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
751 751
        break;
752 752
      case FEMALE:
753 753
        bb.add(p+mycoords[n]);
754 754
        bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
755 755
        break;
756 756
      }
757 757
    }
758 758
    if (bb.empty()) {
759 759
      bb = dim2::Box<double>(dim2::Point<double>(0,0));
760 760
    }
761 761

	
762 762
    if(_scaleToA4)
763 763
      os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
764 764
    else {
765 765
      if(_preScale) {
766 766
        //Rescale so that BoundingBox won't be neither to big nor too small.
767 767
        while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
768 768
        while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
769 769
      }
770 770

	
771 771
      os << "%%BoundingBox: "
772 772
         << int(floor(bb.left()   * _scale - _xBorder)) << ' '
773 773
         << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
774 774
         << int(ceil(bb.right()  * _scale + _xBorder)) << ' '
775 775
         << int(ceil(bb.top()    * _scale + _yBorder)) << '\n';
776 776
    }
777 777

	
778 778
    os << "%%EndComments\n";
779 779

	
780 780
    //x1 y1 x2 y2 x3 y3 cr cg cb w
781 781
    os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
782 782
       << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
783 783
    os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke }"
784 784
       << " bind def\n";
785 785
    //x y r
786 786
    os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath }"
787 787
       << " bind def\n";
788 788
    //x y r
789 789
    os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
790 790
       << "      2 index 1 index sub 2 index 2 index add lineto\n"
791 791
       << "      2 index 1 index sub 2 index 2 index sub lineto\n"
792 792
       << "      2 index 1 index add 2 index 2 index sub lineto\n"
793 793
       << "      closepath pop pop pop} bind def\n";
794 794
    //x y r
795 795
    os << "/di { newpath 2 index 1 index add 2 index moveto\n"
796 796
       << "      2 index             2 index 2 index add lineto\n"
797 797
       << "      2 index 1 index sub 2 index             lineto\n"
798 798
       << "      2 index             2 index 2 index sub lineto\n"
799 799
       << "      closepath pop pop pop} bind def\n";
800 800
    // x y r cr cg cb
801 801
    os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n"
802 802
       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
803 803
       << "   } bind def\n";
804 804
    os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n"
805 805
       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n"
806 806
       << "   } bind def\n";
807 807
    os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n"
808 808
       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n"
809 809
       << "   } bind def\n";
810 810
    os << "/nfemale { 0 0 0 setrgbcolor 3 index "
811 811
       << _nodeBorderQuotient/(1+_nodeBorderQuotient)
812 812
       << " 1.5 mul mul setlinewidth\n"
813 813
       << "  newpath 5 index 5 index moveto "
814 814
       << "5 index 5 index 5 index 3.01 mul sub\n"
815 815
       << "  lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub"
816 816
       << " moveto\n"
817 817
       << "  5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto "
818 818
       << "stroke\n"
819 819
       << "  5 index 5 index 5 index c fill\n"
820 820
       << "  setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
821 821
       << "  } bind def\n";
822 822
    os << "/nmale {\n"
823 823
       << "  0 0 0 setrgbcolor 3 index "
824 824
       << _nodeBorderQuotient/(1+_nodeBorderQuotient)
825 825
       <<" 1.5 mul mul setlinewidth\n"
826 826
       << "  newpath 5 index 5 index moveto\n"
827 827
       << "  5 index 4 index 1 mul 1.5 mul add\n"
828 828
       << "  5 index 5 index 3 sqrt 1.5 mul mul add\n"
829 829
       << "  1 index 1 index lineto\n"
830 830
       << "  1 index 1 index 7 index sub moveto\n"
831 831
       << "  1 index 1 index lineto\n"
832 832
       << "  exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub"
833 833
       << " lineto\n"
834 834
       << "  stroke\n"
835 835
       << "  5 index 5 index 5 index c fill\n"
836 836
       << "  setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
837 837
       << "  } bind def\n";
838 838

	
839 839

	
840 840
    os << "/arrl " << _arrowLength << " def\n";
841 841
    os << "/arrw " << _arrowWidth << " def\n";
842 842
    // l dx_norm dy_norm
843 843
    os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
844 844
    //len w dx_norm dy_norm x1 y1 cr cg cb
845 845
    os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx "
846 846
       << "exch def\n"
847 847
       << "       /w exch def /len exch def\n"
848 848
      //<< "0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
849 849
       << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
850 850
       << "       len w sub arrl sub dx dy lrl\n"
851 851
       << "       arrw dy dx neg lrl\n"
852 852
       << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
853 853
       << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
854 854
       << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
855 855
       << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
856 856
       << "       arrw dy dx neg lrl\n"
857 857
       << "       len w sub arrl sub neg dx dy lrl\n"
858 858
       << "       closepath fill } bind def\n";
859 859
    os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
860 860
       << "         neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
861 861

	
862 862
    os << "\ngsave\n";
863 863
    if(_scaleToA4)
864 864
      if(bb.height()>bb.width()) {
865 865
        double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),
866 866
                  (A4WIDTH-2*A4BORDER)/bb.width());
867 867
        os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
868 868
           << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER
869 869
           << " translate\n"
870 870
           << sc << " dup scale\n"
871 871
           << -bb.left() << ' ' << -bb.bottom() << " translate\n";
872 872
      }
873 873
      else {
874 874
        double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),
875 875
                  (A4WIDTH-2*A4BORDER)/bb.height());
876 876
        os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
877 877
           << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER
878 878
           << " translate\n"
879 879
           << sc << " dup scale\n90 rotate\n"
880 880
           << -bb.left() << ' ' << -bb.top() << " translate\n";
881 881
        }
882 882
    else if(_scale!=1.0) os << _scale << " dup scale\n";
883 883

	
884 884
    if(_showArcs) {
885 885
      os << "%Arcs:\ngsave\n";
886 886
      if(_enableParallel) {
887 887
        std::vector<Arc> el;
888 888
        for(ArcIt e(g);e!=INVALID;++e)
889 889
          if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
890 890
             &&g.source(e)!=g.target(e))
891 891
            el.push_back(e);
892 892
        std::sort(el.begin(),el.end(),arcLess(g));
893 893

	
894 894
        typename std::vector<Arc>::iterator j;
895 895
        for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
896 896
          for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
897 897

	
898 898
          double sw=0;
899 899
          for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
900 900
            sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
901 901
          sw-=_parArcDist;
902 902
          sw/=-2.0;
903 903
          dim2::Point<double>
904 904
            dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
905 905
          double l=std::sqrt(dvec.normSquare());
906 906
          dim2::Point<double> d(dvec/std::max(l,EPSILON));
907 907
          dim2::Point<double> m;
908 908
//           m=dim2::Point<double>(mycoords[g.target(*i)]+
909 909
//                                 mycoords[g.source(*i)])/2.0;
910 910

	
911 911
//            m=dim2::Point<double>(mycoords[g.source(*i)])+
912 912
//             dvec*(double(_nodeSizes[g.source(*i)])/
913 913
//                (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
914 914

	
915 915
          m=dim2::Point<double>(mycoords[g.source(*i)])+
916 916
            d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
917 917

	
918 918
          for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
919 919
            sw+=_arcWidths[*e]*_arcWidthScale/2.0;
920 920
            dim2::Point<double> mm=m+rot90(d)*sw/.75;
921 921
            if(_drawArrows) {
922 922
              int node_shape;
923 923
              dim2::Point<double> s=mycoords[g.source(*e)];
924 924
              dim2::Point<double> t=mycoords[g.target(*e)];
925 925
              double rn=_nodeSizes[g.target(*e)]*_nodeScale;
926 926
              node_shape=_nodeShapes[g.target(*e)];
927 927
              dim2::Bezier3 bez(s,mm,mm,t);
928 928
              double t1=0,t2=1;
929 929
              for(int ii=0;ii<INTERPOL_PREC;++ii)
930 930
                if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
931 931
                else t1=(t1+t2)/2;
932 932
              dim2::Point<double> apoint=bez((t1+t2)/2);
933 933
              rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;
934 934
              rn*=rn;
935 935
              t2=(t1+t2)/2;t1=0;
936 936
              for(int ii=0;ii<INTERPOL_PREC;++ii)
937 937
                if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
938 938
                else t2=(t1+t2)/2;
939 939
              dim2::Point<double> linend=bez((t1+t2)/2);
940 940
              bez=bez.before((t1+t2)/2);
941 941
//               rn=_nodeSizes[g.source(*e)]*_nodeScale;
942 942
//               node_shape=_nodeShapes[g.source(*e)];
943 943
//               t1=0;t2=1;
944 944
//               for(int i=0;i<INTERPOL_PREC;++i)
945 945
//                 if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape))
946 946
//                   t1=(t1+t2)/2;
947 947
//                 else t2=(t1+t2)/2;
948 948
//               bez=bez.after((t1+t2)/2);
949 949
              os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "
950 950
                 << _arcColors[*e].red() << ' '
951 951
                 << _arcColors[*e].green() << ' '
952 952
                 << _arcColors[*e].blue() << " setrgbcolor newpath\n"
953 953
                 << bez.p1.x << ' ' <<  bez.p1.y << " moveto\n"
954 954
                 << bez.p2.x << ' ' << bez.p2.y << ' '
955 955
                 << bez.p3.x << ' ' << bez.p3.y << ' '
956 956
                 << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
957 957
              dim2::Point<double> dd(rot90(linend-apoint));
958 958
              dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/
959 959
                std::sqrt(dd.normSquare());
960 960
              os << "newpath " << psOut(apoint) << " moveto "
961 961
                 << psOut(linend+dd) << " lineto "
962 962
                 << psOut(linend-dd) << " lineto closepath fill\n";
963 963
            }
964 964
            else {
965 965
              os << mycoords[g.source(*e)].x << ' '
966 966
                 << mycoords[g.source(*e)].y << ' '
967 967
                 << mm.x << ' ' << mm.y << ' '
968 968
                 << mycoords[g.target(*e)].x << ' '
969 969
                 << mycoords[g.target(*e)].y << ' '
970 970
                 << _arcColors[*e].red() << ' '
971 971
                 << _arcColors[*e].green() << ' '
972 972
                 << _arcColors[*e].blue() << ' '
973 973
                 << _arcWidths[*e]*_arcWidthScale << " lb\n";
974 974
            }
975 975
            sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;
976 976
          }
977 977
        }
978 978
      }
979 979
      else for(ArcIt e(g);e!=INVALID;++e)
980 980
        if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
981 981
           &&g.source(e)!=g.target(e)) {
982 982
          if(_drawArrows) {
983 983
            dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);
984 984
            double rn=_nodeSizes[g.target(e)]*_nodeScale;
985 985
            int node_shape=_nodeShapes[g.target(e)];
986 986
            double t1=0,t2=1;
987 987
            for(int i=0;i<INTERPOL_PREC;++i)
988 988
              if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
989 989
              else t2=(t1+t2)/2;
990 990
            double l=std::sqrt(d.normSquare());
991 991
            d/=l;
992 992

	
993 993
            os << l*(1-(t1+t2)/2) << ' '
994 994
               << _arcWidths[e]*_arcWidthScale << ' '
995 995
               << d.x << ' ' << d.y << ' '
996 996
               << mycoords[g.source(e)].x << ' '
997 997
               << mycoords[g.source(e)].y << ' '
998 998
               << _arcColors[e].red() << ' '
999 999
               << _arcColors[e].green() << ' '
1000 1000
               << _arcColors[e].blue() << " arr\n";
1001 1001
          }
1002 1002
          else os << mycoords[g.source(e)].x << ' '
1003 1003
                  << mycoords[g.source(e)].y << ' '
1004 1004
                  << mycoords[g.target(e)].x << ' '
1005 1005
                  << mycoords[g.target(e)].y << ' '
1006 1006
                  << _arcColors[e].red() << ' '
1007 1007
                  << _arcColors[e].green() << ' '
1008 1008
                  << _arcColors[e].blue() << ' '
1009 1009
                  << _arcWidths[e]*_arcWidthScale << " l\n";
1010 1010
        }
1011 1011
      os << "grestore\n";
1012 1012
    }
1013 1013
    if(_showNodes) {
1014 1014
      os << "%Nodes:\ngsave\n";
1015 1015
      for(NodeIt n(g);n!=INVALID;++n) {
1016 1016
        os << mycoords[n].x << ' ' << mycoords[n].y << ' '
1017 1017
           << _nodeSizes[n]*_nodeScale << ' '
1018 1018
           << _nodeColors[n].red() << ' '
1019 1019
           << _nodeColors[n].green() << ' '
1020 1020
           << _nodeColors[n].blue() << ' ';
1021 1021
        switch(_nodeShapes[n]) {
1022 1022
        case CIRCLE:
1023 1023
          os<< "nc";break;
1024 1024
        case SQUARE:
1025 1025
          os<< "nsq";break;
1026 1026
        case DIAMOND:
1027 1027
          os<< "ndi";break;
1028 1028
        case MALE:
1029 1029
          os<< "nmale";break;
1030 1030
        case FEMALE:
1031 1031
          os<< "nfemale";break;
1032 1032
        }
1033 1033
        os<<'\n';
1034 1034
      }
1035 1035
      os << "grestore\n";
1036 1036
    }
1037 1037
    if(_showNodeText) {
1038 1038
      os << "%Node texts:\ngsave\n";
1039 1039
      os << "/fosi " << _nodeTextSize << " def\n";
1040 1040
      os << "(Helvetica) findfont fosi scalefont setfont\n";
1041 1041
      for(NodeIt n(g);n!=INVALID;++n) {
1042 1042
        switch(_nodeTextColorType) {
1043 1043
        case DIST_COL:
1044 1044
          os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
1045 1045
          break;
1046 1046
        case DIST_BW:
1047 1047
          os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
1048 1048
          break;
1049 1049
        case CUST_COL:
1050 1050
          os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
1051 1051
          break;
1052 1052
        default:
1053 1053
          os << "0 0 0 setrgbcolor\n";
1054 1054
        }
1055 1055
        os << mycoords[n].x << ' ' << mycoords[n].y
1056 1056
           << " (" << _nodeTexts[n] << ") cshow\n";
1057 1057
      }
1058 1058
      os << "grestore\n";
1059 1059
    }
1060 1060
    if(_showNodePsText) {
1061 1061
      os << "%Node PS blocks:\ngsave\n";
1062 1062
      for(NodeIt n(g);n!=INVALID;++n)
1063 1063
        os << mycoords[n].x << ' ' << mycoords[n].y
1064 1064
           << " moveto\n" << _nodePsTexts[n] << "\n";
1065 1065
      os << "grestore\n";
1066 1066
    }
1067 1067

	
1068 1068
    os << "grestore\nshowpage\n";
1069 1069

	
1070 1070
    //CleanUp:
1071 1071
    if(_pleaseRemoveOsStream) {delete &os;}
1072 1072
  }
1073 1073

	
1074 1074
  ///\name Aliases
1075 1075
  ///These are just some aliases to other parameter setting functions.
1076 1076

	
1077 1077
  ///@{
1078 1078

	
1079 1079
  ///An alias for arcWidths()
1080 1080
  template<class X> GraphToEps<ArcWidthsTraits<X> > edgeWidths(const X &x)
1081 1081
  {
1082 1082
    return arcWidths(x);
1083 1083
  }
1084 1084

	
1085 1085
  ///An alias for arcColors()
1086 1086
  template<class X> GraphToEps<ArcColorsTraits<X> >
1087 1087
  edgeColors(const X &x)
1088 1088
  {
1089 1089
    return arcColors(x);
1090 1090
  }
1091 1091

	
1092 1092
  ///An alias for arcWidthScale()
1093 1093
  GraphToEps<T> &edgeWidthScale(double d) {return arcWidthScale(d);}
1094 1094

	
1095 1095
  ///An alias for autoArcWidthScale()
1096 1096
  GraphToEps<T> &autoEdgeWidthScale(bool b=true)
1097 1097
  {
1098 1098
    return autoArcWidthScale(b);
1099 1099
  }
1100 1100

	
1101 1101
  ///An alias for absoluteArcWidths()
1102 1102
  GraphToEps<T> &absoluteEdgeWidths(bool b=true)
1103 1103
  {
1104 1104
    return absoluteArcWidths(b);
1105 1105
  }
1106 1106

	
1107 1107
  ///An alias for parArcDist()
1108 1108
  GraphToEps<T> &parEdgeDist(double d) {return parArcDist(d);}
1109 1109

	
1110 1110
  ///An alias for hideArcs()
1111 1111
  GraphToEps<T> &hideEdges(bool b=true) {return hideArcs(b);}
1112 1112

	
1113 1113
  ///@}
1114 1114
};
1115 1115

	
1116 1116
template<class T>
1117 1117
const int GraphToEps<T>::INTERPOL_PREC = 20;
1118 1118
template<class T>
1119 1119
const double GraphToEps<T>::A4HEIGHT = 841.8897637795276;
1120 1120
template<class T>
1121 1121
const double GraphToEps<T>::A4WIDTH  = 595.275590551181;
1122 1122
template<class T>
1123 1123
const double GraphToEps<T>::A4BORDER = 15;
1124 1124

	
1125 1125

	
1126 1126
///Generates an EPS file from a graph
1127 1127

	
1128 1128
///\ingroup eps_io
1129 1129
///Generates an EPS file from a graph.
1130 1130
///\param g Reference to the graph to be printed.
1131 1131
///\param os Reference to the output stream.
1132 1132
///By default it is <tt>std::cout</tt>.
1133 1133
///
1134 1134
///This function also has a lot of
1135 1135
///\ref named-templ-func-param "named parameters",
1136 1136
///they are declared as the members of class \ref GraphToEps. The following
1137 1137
///example shows how to use these parameters.
1138 1138
///\code
1139 1139
/// graphToEps(g,os).scale(10).coords(coords)
1140 1140
///              .nodeScale(2).nodeSizes(sizes)
1141 1141
///              .arcWidthScale(.4).run();
1142 1142
///\endcode
1143 1143
///
1144 1144
///For more detailed examples see the \ref graph_to_eps_demo.cc demo file.
1145 1145
///
1146 1146
///\warning Don't forget to put the \ref GraphToEps::run() "run()"
1147 1147
///to the end of the parameter list.
1148 1148
///\sa GraphToEps
1149 1149
///\sa graphToEps(G &g, const char *file_name)
1150 1150
template<class G>
1151 1151
GraphToEps<DefaultGraphToEpsTraits<G> >
1152 1152
graphToEps(G &g, std::ostream& os=std::cout)
1153 1153
{
1154 1154
  return
1155 1155
    GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
1156 1156
}
1157 1157

	
1158 1158
///Generates an EPS file from a graph
1159 1159

	
1160 1160
///\ingroup eps_io
1161 1161
///This function does the same as
1162 1162
///\ref graphToEps(G &g,std::ostream& os)
1163 1163
///but it writes its output into the file \c file_name
1164 1164
///instead of a stream.
1165 1165
///\sa graphToEps(G &g, std::ostream& os)
1166 1166
template<class G>
1167 1167
GraphToEps<DefaultGraphToEpsTraits<G> >
1168 1168
graphToEps(G &g,const char *file_name)
1169 1169
{
1170 1170
  std::ostream* os = new std::ofstream(file_name);
1171 1171
  if (!(*os)) {
1172 1172
    delete os;
1173
    throw IoError(file_name, "Cannot write file");
1173
    throw IoError("Cannot write file", file_name);
1174 1174
  }
1175 1175
  return GraphToEps<DefaultGraphToEpsTraits<G> >
1176 1176
    (DefaultGraphToEpsTraits<G>(g,*os,true));
1177 1177
}
1178 1178

	
1179 1179
///Generates an EPS file from a graph
1180 1180

	
1181 1181
///\ingroup eps_io
1182 1182
///This function does the same as
1183 1183
///\ref graphToEps(G &g,std::ostream& os)
1184 1184
///but it writes its output into the file \c file_name
1185 1185
///instead of a stream.
1186 1186
///\sa graphToEps(G &g, std::ostream& os)
1187 1187
template<class G>
1188 1188
GraphToEps<DefaultGraphToEpsTraits<G> >
1189 1189
graphToEps(G &g,const std::string& file_name)
1190 1190
{
1191 1191
  std::ostream* os = new std::ofstream(file_name.c_str());
1192 1192
  if (!(*os)) {
1193 1193
    delete os;
1194
    throw IoError(file_name, "Cannot write file");
1194
    throw IoError("Cannot write file", file_name);
1195 1195
  }
1196 1196
  return GraphToEps<DefaultGraphToEpsTraits<G> >
1197 1197
    (DefaultGraphToEpsTraits<G>(g,*os,true));
1198 1198
}
1199 1199

	
1200 1200
} //END OF NAMESPACE LEMON
1201 1201

	
1202 1202
#endif // LEMON_GRAPH_TO_EPS_H
Ignore white space 131072 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
///\ingroup lemon_io
20 20
///\file
21 21
///\brief \ref lgf-format "LEMON Graph Format" reader.
22 22

	
23 23

	
24 24
#ifndef LEMON_LGF_READER_H
25 25
#define LEMON_LGF_READER_H
26 26

	
27 27
#include <iostream>
28 28
#include <fstream>
29 29
#include <sstream>
30 30

	
31 31
#include <set>
32 32
#include <map>
33 33

	
34 34
#include <lemon/assert.h>
35 35
#include <lemon/core.h>
36 36

	
37 37
#include <lemon/lgf_writer.h>
38 38

	
39 39
#include <lemon/concept_check.h>
40 40
#include <lemon/concepts/maps.h>
41 41

	
42 42
namespace lemon {
43 43

	
44 44
  namespace _reader_bits {
45 45

	
46 46
    template <typename Value>
47 47
    struct DefaultConverter {
48 48
      Value operator()(const std::string& str) {
49 49
        std::istringstream is(str);
50 50
        Value value;
51 51
        if (!(is >> value)) {
52 52
          throw FormatError("Cannot read token");
53 53
        }
54 54

	
55 55
        char c;
56 56
        if (is >> std::ws >> c) {
57 57
          throw FormatError("Remaining characters in token");
58 58
        }
59 59
        return value;
60 60
      }
61 61
    };
62 62

	
63 63
    template <>
64 64
    struct DefaultConverter<std::string> {
65 65
      std::string operator()(const std::string& str) {
66 66
        return str;
67 67
      }
68 68
    };
69 69

	
70 70
    template <typename _Item>
71 71
    class MapStorageBase {
72 72
    public:
73 73
      typedef _Item Item;
74 74

	
75 75
    public:
76 76
      MapStorageBase() {}
77 77
      virtual ~MapStorageBase() {}
78 78

	
79 79
      virtual void set(const Item& item, const std::string& value) = 0;
80 80

	
81 81
    };
82 82

	
83 83
    template <typename _Item, typename _Map,
84 84
              typename _Converter = DefaultConverter<typename _Map::Value> >
85 85
    class MapStorage : public MapStorageBase<_Item> {
86 86
    public:
87 87
      typedef _Map Map;
88 88
      typedef _Converter Converter;
89 89
      typedef _Item Item;
90 90

	
91 91
    private:
92 92
      Map& _map;
93 93
      Converter _converter;
94 94

	
95 95
    public:
96 96
      MapStorage(Map& map, const Converter& converter = Converter())
97 97
        : _map(map), _converter(converter) {}
98 98
      virtual ~MapStorage() {}
99 99

	
100 100
      virtual void set(const Item& item ,const std::string& value) {
101 101
        _map.set(item, _converter(value));
102 102
      }
103 103
    };
104 104

	
105 105
    template <typename _Graph, bool _dir, typename _Map,
106 106
              typename _Converter = DefaultConverter<typename _Map::Value> >
107 107
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
108 108
    public:
109 109
      typedef _Map Map;
110 110
      typedef _Converter Converter;
111 111
      typedef _Graph Graph;
112 112
      typedef typename Graph::Edge Item;
113 113
      static const bool dir = _dir;
114 114

	
115 115
    private:
116 116
      const Graph& _graph;
117 117
      Map& _map;
118 118
      Converter _converter;
119 119

	
120 120
    public:
121 121
      GraphArcMapStorage(const Graph& graph, Map& map,
122 122
                         const Converter& converter = Converter())
123 123
        : _graph(graph), _map(map), _converter(converter) {}
124 124
      virtual ~GraphArcMapStorage() {}
125 125

	
126 126
      virtual void set(const Item& item ,const std::string& value) {
127 127
        _map.set(_graph.direct(item, dir), _converter(value));
128 128
      }
129 129
    };
130 130

	
131 131
    class ValueStorageBase {
132 132
    public:
133 133
      ValueStorageBase() {}
134 134
      virtual ~ValueStorageBase() {}
135 135

	
136 136
      virtual void set(const std::string&) = 0;
137 137
    };
138 138

	
139 139
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
140 140
    class ValueStorage : public ValueStorageBase {
141 141
    public:
142 142
      typedef _Value Value;
143 143
      typedef _Converter Converter;
144 144

	
145 145
    private:
146 146
      Value& _value;
147 147
      Converter _converter;
148 148

	
149 149
    public:
150 150
      ValueStorage(Value& value, const Converter& converter = Converter())
151 151
        : _value(value), _converter(converter) {}
152 152

	
153 153
      virtual void set(const std::string& value) {
154 154
        _value = _converter(value);
155 155
      }
156 156
    };
157 157

	
158 158
    template <typename Value>
159 159
    struct MapLookUpConverter {
160 160
      const std::map<std::string, Value>& _map;
161 161

	
162 162
      MapLookUpConverter(const std::map<std::string, Value>& map)
163 163
        : _map(map) {}
164 164

	
165 165
      Value operator()(const std::string& str) {
166 166
        typename std::map<std::string, Value>::const_iterator it =
167 167
          _map.find(str);
168 168
        if (it == _map.end()) {
169 169
          std::ostringstream msg;
170 170
          msg << "Item not found: " << str;
171 171
          throw FormatError(msg.str());
172 172
        }
173 173
        return it->second;
174 174
      }
175 175
    };
176 176

	
177 177
    template <typename Graph>
178 178
    struct GraphArcLookUpConverter {
179 179
      const Graph& _graph;
180 180
      const std::map<std::string, typename Graph::Edge>& _map;
181 181

	
182 182
      GraphArcLookUpConverter(const Graph& graph,
183 183
                              const std::map<std::string,
184 184
                                             typename Graph::Edge>& map)
185 185
        : _graph(graph), _map(map) {}
186 186

	
187 187
      typename Graph::Arc operator()(const std::string& str) {
188 188
        if (str.empty() || (str[0] != '+' && str[0] != '-')) {
189 189
          throw FormatError("Item must start with '+' or '-'");
190 190
        }
191 191
        typename std::map<std::string, typename Graph::Edge>
192 192
          ::const_iterator it = _map.find(str.substr(1));
193 193
        if (it == _map.end()) {
194 194
          throw FormatError("Item not found");
195 195
        }
196 196
        return _graph.direct(it->second, str[0] == '+');
197 197
      }
198 198
    };
199 199

	
200 200
    inline bool isWhiteSpace(char c) {
201 201
      return c == ' ' || c == '\t' || c == '\v' ||
202 202
        c == '\n' || c == '\r' || c == '\f';
203 203
    }
204 204

	
205 205
    inline bool isOct(char c) {
206 206
      return '0' <= c && c <='7';
207 207
    }
208 208

	
209 209
    inline int valueOct(char c) {
210 210
      LEMON_ASSERT(isOct(c), "The character is not octal.");
211 211
      return c - '0';
212 212
    }
213 213

	
214 214
    inline bool isHex(char c) {
215 215
      return ('0' <= c && c <= '9') ||
216 216
        ('a' <= c && c <= 'z') ||
217 217
        ('A' <= c && c <= 'Z');
218 218
    }
219 219

	
220 220
    inline int valueHex(char c) {
221 221
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
222 222
      if ('0' <= c && c <= '9') return c - '0';
223 223
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
224 224
      return c - 'A' + 10;
225 225
    }
226 226

	
227 227
    inline bool isIdentifierFirstChar(char c) {
228 228
      return ('a' <= c && c <= 'z') ||
229 229
        ('A' <= c && c <= 'Z') || c == '_';
230 230
    }
231 231

	
232 232
    inline bool isIdentifierChar(char c) {
233 233
      return isIdentifierFirstChar(c) ||
234 234
        ('0' <= c && c <= '9');
235 235
    }
236 236

	
237 237
    inline char readEscape(std::istream& is) {
238 238
      char c;
239 239
      if (!is.get(c))
240 240
        throw FormatError("Escape format error");
241 241

	
242 242
      switch (c) {
243 243
      case '\\':
244 244
        return '\\';
245 245
      case '\"':
246 246
        return '\"';
247 247
      case '\'':
248 248
        return '\'';
249 249
      case '\?':
250 250
        return '\?';
251 251
      case 'a':
252 252
        return '\a';
253 253
      case 'b':
254 254
        return '\b';
255 255
      case 'f':
256 256
        return '\f';
257 257
      case 'n':
258 258
        return '\n';
259 259
      case 'r':
260 260
        return '\r';
261 261
      case 't':
262 262
        return '\t';
263 263
      case 'v':
264 264
        return '\v';
265 265
      case 'x':
266 266
        {
267 267
          int code;
268 268
          if (!is.get(c) || !isHex(c))
269 269
            throw FormatError("Escape format error");
270 270
          else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
271 271
          else code = code * 16 + valueHex(c);
272 272
          return code;
273 273
        }
274 274
      default:
275 275
        {
276 276
          int code;
277 277
          if (!isOct(c))
278 278
            throw FormatError("Escape format error");
279 279
          else if (code = valueOct(c), !is.get(c) || !isOct(c))
280 280
            is.putback(c);
281 281
          else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
282 282
            is.putback(c);
283 283
          else code = code * 8 + valueOct(c);
284 284
          return code;
285 285
        }
286 286
      }
287 287
    }
288 288

	
289 289
    inline std::istream& readToken(std::istream& is, std::string& str) {
290 290
      std::ostringstream os;
291 291

	
292 292
      char c;
293 293
      is >> std::ws;
294 294

	
295 295
      if (!is.get(c))
296 296
        return is;
297 297

	
298 298
      if (c == '\"') {
299 299
        while (is.get(c) && c != '\"') {
300 300
          if (c == '\\')
301 301
            c = readEscape(is);
302 302
          os << c;
303 303
        }
304 304
        if (!is)
305 305
          throw FormatError("Quoted format error");
306 306
      } else {
307 307
        is.putback(c);
308 308
        while (is.get(c) && !isWhiteSpace(c)) {
309 309
          if (c == '\\')
310 310
            c = readEscape(is);
311 311
          os << c;
312 312
        }
313 313
        if (!is) {
314 314
          is.clear();
315 315
        } else {
316 316
          is.putback(c);
317 317
        }
318 318
      }
319 319
      str = os.str();
320 320
      return is;
321 321
    }
322 322

	
323 323
    class Section {
324 324
    public:
325 325
      virtual ~Section() {}
326 326
      virtual void process(std::istream& is, int& line_num) = 0;
327 327
    };
328 328

	
329 329
    template <typename Functor>
330 330
    class LineSection : public Section {
331 331
    private:
332 332

	
333 333
      Functor _functor;
334 334

	
335 335
    public:
336 336

	
337 337
      LineSection(const Functor& functor) : _functor(functor) {}
338 338
      virtual ~LineSection() {}
339 339

	
340 340
      virtual void process(std::istream& is, int& line_num) {
341 341
        char c;
342 342
        std::string line;
343 343
        while (is.get(c) && c != '@') {
344 344
          if (c == '\n') {
345 345
            ++line_num;
346 346
          } else if (c == '#') {
347 347
            getline(is, line);
348 348
            ++line_num;
349 349
          } else if (!isWhiteSpace(c)) {
350 350
            is.putback(c);
351 351
            getline(is, line);
352 352
            _functor(line);
353 353
            ++line_num;
354 354
          }
355 355
        }
356 356
        if (is) is.putback(c);
357 357
        else if (is.eof()) is.clear();
358 358
      }
359 359
    };
360 360

	
361 361
    template <typename Functor>
362 362
    class StreamSection : public Section {
363 363
    private:
364 364

	
365 365
      Functor _functor;
366 366

	
367 367
    public:
368 368

	
369 369
      StreamSection(const Functor& functor) : _functor(functor) {}
370 370
      virtual ~StreamSection() {}
371 371

	
372 372
      virtual void process(std::istream& is, int& line_num) {
373 373
        _functor(is, line_num);
374 374
        char c;
375 375
        std::string line;
376 376
        while (is.get(c) && c != '@') {
377 377
          if (c == '\n') {
378 378
            ++line_num;
379 379
          } else if (!isWhiteSpace(c)) {
380 380
            getline(is, line);
381 381
            ++line_num;
382 382
          }
383 383
        }
384 384
        if (is) is.putback(c);
385 385
        else if (is.eof()) is.clear();
386 386
      }
387 387
    };
388 388

	
389 389
  }
390 390

	
391 391
  template <typename Digraph>
392 392
  class DigraphReader;
393 393

	
394 394
  template <typename Digraph>
395 395
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph);
396 396

	
397 397
  template <typename Digraph>
398 398
  DigraphReader<Digraph> digraphReader(const std::string& fn, Digraph& digraph);
399 399

	
400 400
  template <typename Digraph>
401 401
  DigraphReader<Digraph> digraphReader(const char *fn, Digraph& digraph);
402 402

	
403 403
  /// \ingroup lemon_io
404 404
  ///
405 405
  /// \brief \ref lgf-format "LGF" reader for directed graphs
406 406
  ///
407 407
  /// This utility reads an \ref lgf-format "LGF" file.
408 408
  ///
409 409
  /// The reading method does a batch processing. The user creates a
410 410
  /// reader object, then various reading rules can be added to the
411 411
  /// reader, and eventually the reading is executed with the \c run()
412 412
  /// member function. A map reading rule can be added to the reader
413 413
  /// with the \c nodeMap() or \c arcMap() members. An optional
414 414
  /// converter parameter can also be added as a standard functor
415 415
  /// converting from \c std::string to the value type of the map. If it
416 416
  /// is set, it will determine how the tokens in the file should be
417 417
  /// converted to the value type of the map. If the functor is not set,
418 418
  /// then a default conversion will be used. One map can be read into
419 419
  /// multiple map objects at the same time. The \c attribute(), \c
420 420
  /// node() and \c arc() functions are used to add attribute reading
421 421
  /// rules.
422 422
  ///
423 423
  ///\code
424 424
  /// DigraphReader<Digraph>(std::cin, digraph).
425 425
  ///   nodeMap("coordinates", coord_map).
426 426
  ///   arcMap("capacity", cap_map).
427 427
  ///   node("source", src).
428 428
  ///   node("target", trg).
429 429
  ///   attribute("caption", caption).
430 430
  ///   run();
431 431
  ///\endcode
432 432
  ///
433 433
  /// By default the reader uses the first section in the file of the
434 434
  /// proper type. If a section has an optional name, then it can be
435 435
  /// selected for reading by giving an optional name parameter to the
436 436
  /// \c nodes(), \c arcs() or \c attributes() functions.
437 437
  ///
438 438
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
439 439
  /// that the nodes or arcs should not be constructed (added to the
440 440
  /// graph) during the reading, but instead the label map of the items
441 441
  /// are given as a parameter of these functions. An
442 442
  /// application of these functions is multipass reading, which is
443 443
  /// important if two \c \@arcs sections must be read from the
444 444
  /// file. In this case the first phase would read the node set and one
445 445
  /// of the arc sets, while the second phase would read the second arc
446 446
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
447 447
  /// The previously read label node map should be passed to the \c
448 448
  /// useNodes() functions. Another application of multipass reading when
449 449
  /// paths are given as a node map or an arc map.
450 450
  /// It is impossible to read this in
451 451
  /// a single pass, because the arcs are not constructed when the node
452 452
  /// maps are read.
453 453
  template <typename _Digraph>
454 454
  class DigraphReader {
455 455
  public:
456 456

	
457 457
    typedef _Digraph Digraph;
458 458
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
459 459

	
460 460
  private:
461 461

	
462 462

	
463 463
    std::istream* _is;
464 464
    bool local_is;
465 465
    std::string _filename;
466 466

	
467 467
    Digraph& _digraph;
468 468

	
469 469
    std::string _nodes_caption;
470 470
    std::string _arcs_caption;
471 471
    std::string _attributes_caption;
472 472

	
473 473
    typedef std::map<std::string, Node> NodeIndex;
474 474
    NodeIndex _node_index;
475 475
    typedef std::map<std::string, Arc> ArcIndex;
476 476
    ArcIndex _arc_index;
477 477

	
478 478
    typedef std::vector<std::pair<std::string,
479 479
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
480 480
    NodeMaps _node_maps;
481 481

	
482 482
    typedef std::vector<std::pair<std::string,
483 483
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
484 484
    ArcMaps _arc_maps;
485 485

	
486 486
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
487 487
      Attributes;
488 488
    Attributes _attributes;
489 489

	
490 490
    bool _use_nodes;
491 491
    bool _use_arcs;
492 492

	
493 493
    bool _skip_nodes;
494 494
    bool _skip_arcs;
495 495

	
496 496
    int line_num;
497 497
    std::istringstream line;
498 498

	
499 499
  public:
500 500

	
501 501
    /// \brief Constructor
502 502
    ///
503 503
    /// Construct a directed graph reader, which reads from the given
504 504
    /// input stream.
505 505
    DigraphReader(std::istream& is, Digraph& digraph)
506 506
      : _is(&is), local_is(false), _digraph(digraph),
507 507
        _use_nodes(false), _use_arcs(false),
508 508
        _skip_nodes(false), _skip_arcs(false) {}
509 509

	
510 510
    /// \brief Constructor
511 511
    ///
512 512
    /// Construct a directed graph reader, which reads from the given
513 513
    /// file.
514 514
    DigraphReader(const std::string& fn, Digraph& digraph)
515 515
      : _is(new std::ifstream(fn.c_str())), local_is(true),
516 516
        _filename(fn), _digraph(digraph),
517 517
        _use_nodes(false), _use_arcs(false),
518 518
        _skip_nodes(false), _skip_arcs(false) {
519
      if (!(*_is)) throw IoError(fn, "Cannot open file");
519
      if (!(*_is)) throw IoError("Cannot open file", fn);
520 520
    }
521 521

	
522 522
    /// \brief Constructor
523 523
    ///
524 524
    /// Construct a directed graph reader, which reads from the given
525 525
    /// file.
526 526
    DigraphReader(const char* fn, Digraph& digraph)
527 527
      : _is(new std::ifstream(fn)), local_is(true),
528 528
        _filename(fn), _digraph(digraph),
529 529
        _use_nodes(false), _use_arcs(false),
530 530
        _skip_nodes(false), _skip_arcs(false) {
531
      if (!(*_is)) throw IoError(fn, "Cannot open file");
531
      if (!(*_is)) throw IoError("Cannot open file", fn);
532 532
    }
533 533

	
534 534
    /// \brief Destructor
535 535
    ~DigraphReader() {
536 536
      for (typename NodeMaps::iterator it = _node_maps.begin();
537 537
           it != _node_maps.end(); ++it) {
538 538
        delete it->second;
539 539
      }
540 540

	
541 541
      for (typename ArcMaps::iterator it = _arc_maps.begin();
542 542
           it != _arc_maps.end(); ++it) {
543 543
        delete it->second;
544 544
      }
545 545

	
546 546
      for (typename Attributes::iterator it = _attributes.begin();
547 547
           it != _attributes.end(); ++it) {
548 548
        delete it->second;
549 549
      }
550 550

	
551 551
      if (local_is) {
552 552
        delete _is;
553 553
      }
554 554

	
555 555
    }
556 556

	
557 557
  private:
558 558

	
559 559
    friend DigraphReader<Digraph> digraphReader<>(std::istream& is,
560 560
                                                  Digraph& digraph);
561 561
    friend DigraphReader<Digraph> digraphReader<>(const std::string& fn,
562 562
                                                  Digraph& digraph);
563 563
    friend DigraphReader<Digraph> digraphReader<>(const char *fn,
564 564
                                                  Digraph& digraph);
565 565

	
566 566
    DigraphReader(DigraphReader& other)
567 567
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
568 568
        _use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
569 569
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
570 570

	
571 571
      other._is = 0;
572 572
      other.local_is = false;
573 573

	
574 574
      _node_index.swap(other._node_index);
575 575
      _arc_index.swap(other._arc_index);
576 576

	
577 577
      _node_maps.swap(other._node_maps);
578 578
      _arc_maps.swap(other._arc_maps);
579 579
      _attributes.swap(other._attributes);
580 580

	
581 581
      _nodes_caption = other._nodes_caption;
582 582
      _arcs_caption = other._arcs_caption;
583 583
      _attributes_caption = other._attributes_caption;
584 584

	
585 585
    }
586 586

	
587 587
    DigraphReader& operator=(const DigraphReader&);
588 588

	
589 589
  public:
590 590

	
591 591
    /// \name Reading rules
592 592
    /// @{
593 593

	
594 594
    /// \brief Node map reading rule
595 595
    ///
596 596
    /// Add a node map reading rule to the reader.
597 597
    template <typename Map>
598 598
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
599 599
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
600 600
      _reader_bits::MapStorageBase<Node>* storage =
601 601
        new _reader_bits::MapStorage<Node, Map>(map);
602 602
      _node_maps.push_back(std::make_pair(caption, storage));
603 603
      return *this;
604 604
    }
605 605

	
606 606
    /// \brief Node map reading rule
607 607
    ///
608 608
    /// Add a node map reading rule with specialized converter to the
609 609
    /// reader.
610 610
    template <typename Map, typename Converter>
611 611
    DigraphReader& nodeMap(const std::string& caption, Map& map,
612 612
                           const Converter& converter = Converter()) {
613 613
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
614 614
      _reader_bits::MapStorageBase<Node>* storage =
615 615
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
616 616
      _node_maps.push_back(std::make_pair(caption, storage));
617 617
      return *this;
618 618
    }
619 619

	
620 620
    /// \brief Arc map reading rule
621 621
    ///
622 622
    /// Add an arc map reading rule to the reader.
623 623
    template <typename Map>
624 624
    DigraphReader& arcMap(const std::string& caption, Map& map) {
625 625
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
626 626
      _reader_bits::MapStorageBase<Arc>* storage =
627 627
        new _reader_bits::MapStorage<Arc, Map>(map);
628 628
      _arc_maps.push_back(std::make_pair(caption, storage));
629 629
      return *this;
630 630
    }
631 631

	
632 632
    /// \brief Arc map reading rule
633 633
    ///
634 634
    /// Add an arc map reading rule with specialized converter to the
635 635
    /// reader.
636 636
    template <typename Map, typename Converter>
637 637
    DigraphReader& arcMap(const std::string& caption, Map& map,
638 638
                          const Converter& converter = Converter()) {
639 639
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
640 640
      _reader_bits::MapStorageBase<Arc>* storage =
641 641
        new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
642 642
      _arc_maps.push_back(std::make_pair(caption, storage));
643 643
      return *this;
644 644
    }
645 645

	
646 646
    /// \brief Attribute reading rule
647 647
    ///
648 648
    /// Add an attribute reading rule to the reader.
649 649
    template <typename Value>
650 650
    DigraphReader& attribute(const std::string& caption, Value& value) {
651 651
      _reader_bits::ValueStorageBase* storage =
652 652
        new _reader_bits::ValueStorage<Value>(value);
653 653
      _attributes.insert(std::make_pair(caption, storage));
654 654
      return *this;
655 655
    }
656 656

	
657 657
    /// \brief Attribute reading rule
658 658
    ///
659 659
    /// Add an attribute reading rule with specialized converter to the
660 660
    /// reader.
661 661
    template <typename Value, typename Converter>
662 662
    DigraphReader& attribute(const std::string& caption, Value& value,
663 663
                             const Converter& converter = Converter()) {
664 664
      _reader_bits::ValueStorageBase* storage =
665 665
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
666 666
      _attributes.insert(std::make_pair(caption, storage));
667 667
      return *this;
668 668
    }
669 669

	
670 670
    /// \brief Node reading rule
671 671
    ///
672 672
    /// Add a node reading rule to reader.
673 673
    DigraphReader& node(const std::string& caption, Node& node) {
674 674
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
675 675
      Converter converter(_node_index);
676 676
      _reader_bits::ValueStorageBase* storage =
677 677
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
678 678
      _attributes.insert(std::make_pair(caption, storage));
679 679
      return *this;
680 680
    }
681 681

	
682 682
    /// \brief Arc reading rule
683 683
    ///
684 684
    /// Add an arc reading rule to reader.
685 685
    DigraphReader& arc(const std::string& caption, Arc& arc) {
686 686
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
687 687
      Converter converter(_arc_index);
688 688
      _reader_bits::ValueStorageBase* storage =
689 689
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
690 690
      _attributes.insert(std::make_pair(caption, storage));
691 691
      return *this;
692 692
    }
693 693

	
694 694
    /// @}
695 695

	
696 696
    /// \name Select section by name
697 697
    /// @{
698 698

	
699 699
    /// \brief Set \c \@nodes section to be read
700 700
    ///
701 701
    /// Set \c \@nodes section to be read
702 702
    DigraphReader& nodes(const std::string& caption) {
703 703
      _nodes_caption = caption;
704 704
      return *this;
705 705
    }
706 706

	
707 707
    /// \brief Set \c \@arcs section to be read
708 708
    ///
709 709
    /// Set \c \@arcs section to be read
710 710
    DigraphReader& arcs(const std::string& caption) {
711 711
      _arcs_caption = caption;
712 712
      return *this;
713 713
    }
714 714

	
715 715
    /// \brief Set \c \@attributes section to be read
716 716
    ///
717 717
    /// Set \c \@attributes section to be read
718 718
    DigraphReader& attributes(const std::string& caption) {
719 719
      _attributes_caption = caption;
720 720
      return *this;
721 721
    }
722 722

	
723 723
    /// @}
724 724

	
725 725
    /// \name Using previously constructed node or arc set
726 726
    /// @{
727 727

	
728 728
    /// \brief Use previously constructed node set
729 729
    ///
730 730
    /// Use previously constructed node set, and specify the node
731 731
    /// label map.
732 732
    template <typename Map>
733 733
    DigraphReader& useNodes(const Map& map) {
734 734
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
735 735
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
736 736
      _use_nodes = true;
737 737
      _writer_bits::DefaultConverter<typename Map::Value> converter;
738 738
      for (NodeIt n(_digraph); n != INVALID; ++n) {
739 739
        _node_index.insert(std::make_pair(converter(map[n]), n));
740 740
      }
741 741
      return *this;
742 742
    }
743 743

	
744 744
    /// \brief Use previously constructed node set
745 745
    ///
746 746
    /// Use previously constructed node set, and specify the node
747 747
    /// label map and a functor which converts the label map values to
748 748
    /// \c std::string.
749 749
    template <typename Map, typename Converter>
750 750
    DigraphReader& useNodes(const Map& map,
751 751
                            const Converter& converter = Converter()) {
752 752
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
753 753
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
754 754
      _use_nodes = true;
755 755
      for (NodeIt n(_digraph); n != INVALID; ++n) {
756 756
        _node_index.insert(std::make_pair(converter(map[n]), n));
757 757
      }
758 758
      return *this;
759 759
    }
760 760

	
761 761
    /// \brief Use previously constructed arc set
762 762
    ///
763 763
    /// Use previously constructed arc set, and specify the arc
764 764
    /// label map.
765 765
    template <typename Map>
766 766
    DigraphReader& useArcs(const Map& map) {
767 767
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
768 768
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
769 769
      _use_arcs = true;
770 770
      _writer_bits::DefaultConverter<typename Map::Value> converter;
771 771
      for (ArcIt a(_digraph); a != INVALID; ++a) {
772 772
        _arc_index.insert(std::make_pair(converter(map[a]), a));
773 773
      }
774 774
      return *this;
775 775
    }
776 776

	
777 777
    /// \brief Use previously constructed arc set
778 778
    ///
779 779
    /// Use previously constructed arc set, and specify the arc
780 780
    /// label map and a functor which converts the label map values to
781 781
    /// \c std::string.
782 782
    template <typename Map, typename Converter>
783 783
    DigraphReader& useArcs(const Map& map,
784 784
                           const Converter& converter = Converter()) {
785 785
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
786 786
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
787 787
      _use_arcs = true;
788 788
      for (ArcIt a(_digraph); a != INVALID; ++a) {
789 789
        _arc_index.insert(std::make_pair(converter(map[a]), a));
790 790
      }
791 791
      return *this;
792 792
    }
793 793

	
794 794
    /// \brief Skips the reading of node section
795 795
    ///
796 796
    /// Omit the reading of the node section. This implies that each node
797 797
    /// map reading rule will be abandoned, and the nodes of the graph
798 798
    /// will not be constructed, which usually cause that the arc set
799 799
    /// could not be read due to lack of node name resolving.
800 800
    /// Therefore \c skipArcs() function should also be used, or
801 801
    /// \c useNodes() should be used to specify the label of the nodes.
802 802
    DigraphReader& skipNodes() {
803 803
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
804 804
      _skip_nodes = true;
805 805
      return *this;
806 806
    }
807 807

	
808 808
    /// \brief Skips the reading of arc section
809 809
    ///
810 810
    /// Omit the reading of the arc section. This implies that each arc
811 811
    /// map reading rule will be abandoned, and the arcs of the graph
812 812
    /// will not be constructed.
813 813
    DigraphReader& skipArcs() {
814 814
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set");
815 815
      _skip_arcs = true;
816 816
      return *this;
817 817
    }
818 818

	
819 819
    /// @}
820 820

	
821 821
  private:
822 822

	
823 823
    bool readLine() {
824 824
      std::string str;
825 825
      while(++line_num, std::getline(*_is, str)) {
826 826
        line.clear(); line.str(str);
827 827
        char c;
828 828
        if (line >> std::ws >> c && c != '#') {
829 829
          line.putback(c);
830 830
          return true;
831 831
        }
832 832
      }
833 833
      return false;
834 834
    }
835 835

	
836 836
    bool readSuccess() {
837 837
      return static_cast<bool>(*_is);
838 838
    }
839 839

	
840 840
    void skipSection() {
841 841
      char c;
842 842
      while (readSuccess() && line >> c && c != '@') {
843 843
        readLine();
844 844
      }
845 845
      line.putback(c);
846 846
    }
847 847

	
848 848
    void readNodes() {
849 849

	
850 850
      std::vector<int> map_index(_node_maps.size());
851 851
      int map_num, label_index;
852 852

	
853 853
      char c;
854 854
      if (!readLine() || !(line >> c) || c == '@') {
855 855
        if (readSuccess() && line) line.putback(c);
856 856
        if (!_node_maps.empty())
857 857
          throw FormatError("Cannot find map names");
858 858
        return;
859 859
      }
860 860
      line.putback(c);
861 861

	
862 862
      {
863 863
        std::map<std::string, int> maps;
864 864

	
865 865
        std::string map;
866 866
        int index = 0;
867 867
        while (_reader_bits::readToken(line, map)) {
868 868
          if (maps.find(map) != maps.end()) {
869 869
            std::ostringstream msg;
870 870
            msg << "Multiple occurence of node map: " << map;
871 871
            throw FormatError(msg.str());
872 872
          }
873 873
          maps.insert(std::make_pair(map, index));
874 874
          ++index;
875 875
        }
876 876

	
877 877
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
878 878
          std::map<std::string, int>::iterator jt =
879 879
            maps.find(_node_maps[i].first);
880 880
          if (jt == maps.end()) {
881 881
            std::ostringstream msg;
882
            msg << "Map not found in file: " << _node_maps[i].first;
882
            msg << "Map not found: " << _node_maps[i].first;
883 883
            throw FormatError(msg.str());
884 884
          }
885 885
          map_index[i] = jt->second;
886 886
        }
887 887

	
888 888
        {
889 889
          std::map<std::string, int>::iterator jt = maps.find("label");
890 890
          if (jt != maps.end()) {
891 891
            label_index = jt->second;
892 892
          } else {
893 893
            label_index = -1;
894 894
          }
895 895
        }
896 896
        map_num = maps.size();
897 897
      }
898 898

	
899 899
      while (readLine() && line >> c && c != '@') {
900 900
        line.putback(c);
901 901

	
902 902
        std::vector<std::string> tokens(map_num);
903 903
        for (int i = 0; i < map_num; ++i) {
904 904
          if (!_reader_bits::readToken(line, tokens[i])) {
905 905
            std::ostringstream msg;
906 906
            msg << "Column not found (" << i + 1 << ")";
907 907
            throw FormatError(msg.str());
908 908
          }
909 909
        }
910 910
        if (line >> std::ws >> c)
911
          throw FormatError("Extra character on the end of line");
911
          throw FormatError("Extra character at the end of line");
912 912

	
913 913
        Node n;
914 914
        if (!_use_nodes) {
915 915
          n = _digraph.addNode();
916 916
          if (label_index != -1)
917 917
            _node_index.insert(std::make_pair(tokens[label_index], n));
918 918
        } else {
919 919
          if (label_index == -1)
920
            throw FormatError("Label map not found in file");
920
            throw FormatError("Label map not found");
921 921
          typename std::map<std::string, Node>::iterator it =
922 922
            _node_index.find(tokens[label_index]);
923 923
          if (it == _node_index.end()) {
924 924
            std::ostringstream msg;
925 925
            msg << "Node with label not found: " << tokens[label_index];
926 926
            throw FormatError(msg.str());
927 927
          }
928 928
          n = it->second;
929 929
        }
930 930

	
931 931
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
932 932
          _node_maps[i].second->set(n, tokens[map_index[i]]);
933 933
        }
934 934

	
935 935
      }
936 936
      if (readSuccess()) {
937 937
        line.putback(c);
938 938
      }
939 939
    }
940 940

	
941 941
    void readArcs() {
942 942

	
943 943
      std::vector<int> map_index(_arc_maps.size());
944 944
      int map_num, label_index;
945 945

	
946 946
      char c;
947 947
      if (!readLine() || !(line >> c) || c == '@') {
948 948
        if (readSuccess() && line) line.putback(c);
949 949
        if (!_arc_maps.empty())
950 950
          throw FormatError("Cannot find map names");
951 951
        return;
952 952
      }
953 953
      line.putback(c);
954 954

	
955 955
      {
956 956
        std::map<std::string, int> maps;
957 957

	
958 958
        std::string map;
959 959
        int index = 0;
960 960
        while (_reader_bits::readToken(line, map)) {
961 961
          if (maps.find(map) != maps.end()) {
962 962
            std::ostringstream msg;
963 963
            msg << "Multiple occurence of arc map: " << map;
964 964
            throw FormatError(msg.str());
965 965
          }
966 966
          maps.insert(std::make_pair(map, index));
967 967
          ++index;
968 968
        }
969 969

	
970 970
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
971 971
          std::map<std::string, int>::iterator jt =
972 972
            maps.find(_arc_maps[i].first);
973 973
          if (jt == maps.end()) {
974 974
            std::ostringstream msg;
975
            msg << "Map not found in file: " << _arc_maps[i].first;
975
            msg << "Map not found: " << _arc_maps[i].first;
976 976
            throw FormatError(msg.str());
977 977
          }
978 978
          map_index[i] = jt->second;
979 979
        }
980 980

	
981 981
        {
982 982
          std::map<std::string, int>::iterator jt = maps.find("label");
983 983
          if (jt != maps.end()) {
984 984
            label_index = jt->second;
985 985
          } else {
986 986
            label_index = -1;
987 987
          }
988 988
        }
989 989
        map_num = maps.size();
990 990
      }
991 991

	
992 992
      while (readLine() && line >> c && c != '@') {
993 993
        line.putback(c);
994 994

	
995 995
        std::string source_token;
996 996
        std::string target_token;
997 997

	
998 998
        if (!_reader_bits::readToken(line, source_token))
999 999
          throw FormatError("Source not found");
1000 1000

	
1001 1001
        if (!_reader_bits::readToken(line, target_token))
1002 1002
          throw FormatError("Target not found");
1003 1003

	
1004 1004
        std::vector<std::string> tokens(map_num);
1005 1005
        for (int i = 0; i < map_num; ++i) {
1006 1006
          if (!_reader_bits::readToken(line, tokens[i])) {
1007 1007
            std::ostringstream msg;
1008 1008
            msg << "Column not found (" << i + 1 << ")";
1009 1009
            throw FormatError(msg.str());
1010 1010
          }
1011 1011
        }
1012 1012
        if (line >> std::ws >> c)
1013
          throw FormatError("Extra character on the end of line");
1013
          throw FormatError("Extra character at the end of line");
1014 1014

	
1015 1015
        Arc a;
1016 1016
        if (!_use_arcs) {
1017 1017

	
1018 1018
          typename NodeIndex::iterator it;
1019 1019

	
1020 1020
          it = _node_index.find(source_token);
1021 1021
          if (it == _node_index.end()) {
1022 1022
            std::ostringstream msg;
1023 1023
            msg << "Item not found: " << source_token;
1024 1024
            throw FormatError(msg.str());
1025 1025
          }
1026 1026
          Node source = it->second;
1027 1027

	
1028 1028
          it = _node_index.find(target_token);
1029 1029
          if (it == _node_index.end()) {
1030 1030
            std::ostringstream msg;
1031 1031
            msg << "Item not found: " << target_token;
1032 1032
            throw FormatError(msg.str());
1033 1033
          }
1034 1034
          Node target = it->second;
1035 1035

	
1036 1036
          a = _digraph.addArc(source, target);
1037 1037
          if (label_index != -1)
1038 1038
            _arc_index.insert(std::make_pair(tokens[label_index], a));
1039 1039
        } else {
1040 1040
          if (label_index == -1)
1041
            throw FormatError("Label map not found in file");
1041
            throw FormatError("Label map not found");
1042 1042
          typename std::map<std::string, Arc>::iterator it =
1043 1043
            _arc_index.find(tokens[label_index]);
1044 1044
          if (it == _arc_index.end()) {
1045 1045
            std::ostringstream msg;
1046 1046
            msg << "Arc with label not found: " << tokens[label_index];
1047 1047
            throw FormatError(msg.str());
1048 1048
          }
1049 1049
          a = it->second;
1050 1050
        }
1051 1051

	
1052 1052
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1053 1053
          _arc_maps[i].second->set(a, tokens[map_index[i]]);
1054 1054
        }
1055 1055

	
1056 1056
      }
1057 1057
      if (readSuccess()) {
1058 1058
        line.putback(c);
1059 1059
      }
1060 1060
    }
1061 1061

	
1062 1062
    void readAttributes() {
1063 1063

	
1064 1064
      std::set<std::string> read_attr;
1065 1065

	
1066 1066
      char c;
1067 1067
      while (readLine() && line >> c && c != '@') {
1068 1068
        line.putback(c);
1069 1069

	
1070 1070
        std::string attr, token;
1071 1071
        if (!_reader_bits::readToken(line, attr))
1072 1072
          throw FormatError("Attribute name not found");
1073 1073
        if (!_reader_bits::readToken(line, token))
1074 1074
          throw FormatError("Attribute value not found");
1075 1075
        if (line >> c)
1076
          throw FormatError("Extra character on the end of line");
1076
          throw FormatError("Extra character at the end of line");
1077 1077

	
1078 1078
        {
1079 1079
          std::set<std::string>::iterator it = read_attr.find(attr);
1080 1080
          if (it != read_attr.end()) {
1081 1081
            std::ostringstream msg;
1082
            msg << "Multiple occurence of attribute " << attr;
1082
            msg << "Multiple occurence of attribute: " << attr;
1083 1083
            throw FormatError(msg.str());
1084 1084
          }
1085 1085
          read_attr.insert(attr);
1086 1086
        }
1087 1087

	
1088 1088
        {
1089 1089
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1090 1090
          while (it != _attributes.end() && it->first == attr) {
1091 1091
            it->second->set(token);
1092 1092
            ++it;
1093 1093
          }
1094 1094
        }
1095 1095

	
1096 1096
      }
1097 1097
      if (readSuccess()) {
1098 1098
        line.putback(c);
1099 1099
      }
1100 1100
      for (typename Attributes::iterator it = _attributes.begin();
1101 1101
           it != _attributes.end(); ++it) {
1102 1102
        if (read_attr.find(it->first) == read_attr.end()) {
1103 1103
          std::ostringstream msg;
1104
          msg << "Attribute not found in file: " << it->first;
1104
          msg << "Attribute not found: " << it->first;
1105 1105
          throw FormatError(msg.str());
1106 1106
        }
1107 1107
      }
1108 1108
    }
1109 1109

	
1110 1110
  public:
1111 1111

	
1112 1112
    /// \name Execution of the reader
1113 1113
    /// @{
1114 1114

	
1115 1115
    /// \brief Start the batch processing
1116 1116
    ///
1117 1117
    /// This function starts the batch processing
1118 1118
    void run() {
1119 1119
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1120
      if (!*_is) {
1121
        throw FormatError("Cannot find file");
1122
      }
1123 1120

	
1124 1121
      bool nodes_done = _skip_nodes;
1125 1122
      bool arcs_done = _skip_arcs;
1126 1123
      bool attributes_done = false;
1127 1124

	
1128 1125
      line_num = 0;
1129 1126
      readLine();
1130 1127
      skipSection();
1131 1128

	
1132 1129
      while (readSuccess()) {
1133 1130
        try {
1134 1131
          char c;
1135 1132
          std::string section, caption;
1136 1133
          line >> c;
1137 1134
          _reader_bits::readToken(line, section);
1138 1135
          _reader_bits::readToken(line, caption);
1139 1136

	
1140 1137
          if (line >> c)
1141
            throw FormatError("Extra character on the end of line");
1138
            throw FormatError("Extra character at the end of line");
1142 1139

	
1143 1140
          if (section == "nodes" && !nodes_done) {
1144 1141
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1145 1142
              readNodes();
1146 1143
              nodes_done = true;
1147 1144
            }
1148 1145
          } else if ((section == "arcs" || section == "edges") &&
1149 1146
                     !arcs_done) {
1150 1147
            if (_arcs_caption.empty() || _arcs_caption == caption) {
1151 1148
              readArcs();
1152 1149
              arcs_done = true;
1153 1150
            }
1154 1151
          } else if (section == "attributes" && !attributes_done) {
1155 1152
            if (_attributes_caption.empty() || _attributes_caption == caption) {
1156 1153
              readAttributes();
1157 1154
              attributes_done = true;
1158 1155
            }
1159 1156
          } else {
1160 1157
            readLine();
1161 1158
            skipSection();
1162 1159
          }
1163 1160
        } catch (FormatError& error) {
1164 1161
          error.line(line_num);
1165 1162
          error.file(_filename);
1166 1163
          throw;
1167 1164
        }
1168 1165
      }
1169 1166

	
1170 1167
      if (!nodes_done) {
1171 1168
        throw FormatError("Section @nodes not found");
1172 1169
      }
1173 1170

	
1174 1171
      if (!arcs_done) {
1175 1172
        throw FormatError("Section @arcs not found");
1176 1173
      }
1177 1174

	
1178 1175
      if (!attributes_done && !_attributes.empty()) {
1179 1176
        throw FormatError("Section @attributes not found");
1180 1177
      }
1181 1178

	
1182 1179
    }
1183 1180

	
1184 1181
    /// @}
1185 1182

	
1186 1183
  };
1187 1184

	
1188 1185
  /// \brief Return a \ref DigraphReader class
1189 1186
  ///
1190 1187
  /// This function just returns a \ref DigraphReader class.
1191 1188
  /// \relates DigraphReader
1192 1189
  template <typename Digraph>
1193 1190
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
1194 1191
    DigraphReader<Digraph> tmp(is, digraph);
1195 1192
    return tmp;
1196 1193
  }
1197 1194

	
1198 1195
  /// \brief Return a \ref DigraphReader class
1199 1196
  ///
1200 1197
  /// This function just returns a \ref DigraphReader class.
1201 1198
  /// \relates DigraphReader
1202 1199
  template <typename Digraph>
1203 1200
  DigraphReader<Digraph> digraphReader(const std::string& fn,
1204 1201
                                       Digraph& digraph) {
1205 1202
    DigraphReader<Digraph> tmp(fn, digraph);
1206 1203
    return tmp;
1207 1204
  }
1208 1205

	
1209 1206
  /// \brief Return a \ref DigraphReader class
1210 1207
  ///
1211 1208
  /// This function just returns a \ref DigraphReader class.
1212 1209
  /// \relates DigraphReader
1213 1210
  template <typename Digraph>
1214 1211
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
1215 1212
    DigraphReader<Digraph> tmp(fn, digraph);
1216 1213
    return tmp;
1217 1214
  }
1218 1215

	
1219 1216
  template <typename Graph>
1220 1217
  class GraphReader;
1221 1218

	
1222 1219
  template <typename Graph>
1223 1220
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph);
1224 1221

	
1225 1222
  template <typename Graph>
1226 1223
  GraphReader<Graph> graphReader(const std::string& fn, Graph& graph);
1227 1224

	
1228 1225
  template <typename Graph>
1229 1226
  GraphReader<Graph> graphReader(const char *fn, Graph& graph);
1230 1227

	
1231 1228
  /// \ingroup lemon_io
1232 1229
  ///
1233 1230
  /// \brief \ref lgf-format "LGF" reader for undirected graphs
1234 1231
  ///
1235 1232
  /// This utility reads an \ref lgf-format "LGF" file.
1236 1233
  ///
1237 1234
  /// It can be used almost the same way as \c DigraphReader.
1238 1235
  /// The only difference is that this class can handle edges and
1239 1236
  /// edge maps as well as arcs and arc maps.
1240 1237
  ///
1241 1238
  /// The columns in the \c \@edges (or \c \@arcs) section are the
1242 1239
  /// edge maps. However, if there are two maps with the same name
1243 1240
  /// prefixed with \c '+' and \c '-', then these can be read into an
1244 1241
  /// arc map.  Similarly, an attribute can be read into an arc, if
1245 1242
  /// it's value is an edge label prefixed with \c '+' or \c '-'.
1246 1243
  template <typename _Graph>
1247 1244
  class GraphReader {
1248 1245
  public:
1249 1246

	
1250 1247
    typedef _Graph Graph;
1251 1248
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1252 1249

	
1253 1250
  private:
1254 1251

	
1255 1252
    std::istream* _is;
1256 1253
    bool local_is;
1257 1254
    std::string _filename;
1258 1255

	
1259 1256
    Graph& _graph;
1260 1257

	
1261 1258
    std::string _nodes_caption;
1262 1259
    std::string _edges_caption;
1263 1260
    std::string _attributes_caption;
1264 1261

	
1265 1262
    typedef std::map<std::string, Node> NodeIndex;
1266 1263
    NodeIndex _node_index;
1267 1264
    typedef std::map<std::string, Edge> EdgeIndex;
1268 1265
    EdgeIndex _edge_index;
1269 1266

	
1270 1267
    typedef std::vector<std::pair<std::string,
1271 1268
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
1272 1269
    NodeMaps _node_maps;
1273 1270

	
1274 1271
    typedef std::vector<std::pair<std::string,
1275 1272
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1276 1273
    EdgeMaps _edge_maps;
1277 1274

	
1278 1275
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1279 1276
      Attributes;
1280 1277
    Attributes _attributes;
1281 1278

	
1282 1279
    bool _use_nodes;
1283 1280
    bool _use_edges;
1284 1281

	
1285 1282
    bool _skip_nodes;
1286 1283
    bool _skip_edges;
1287 1284

	
1288 1285
    int line_num;
1289 1286
    std::istringstream line;
1290 1287

	
1291 1288
  public:
1292 1289

	
1293 1290
    /// \brief Constructor
1294 1291
    ///
1295 1292
    /// Construct an undirected graph reader, which reads from the given
1296 1293
    /// input stream.
1297 1294
    GraphReader(std::istream& is, Graph& graph)
1298 1295
      : _is(&is), local_is(false), _graph(graph),
1299 1296
        _use_nodes(false), _use_edges(false),
1300 1297
        _skip_nodes(false), _skip_edges(false) {}
1301 1298

	
1302 1299
    /// \brief Constructor
1303 1300
    ///
1304 1301
    /// Construct an undirected graph reader, which reads from the given
1305 1302
    /// file.
1306 1303
    GraphReader(const std::string& fn, Graph& graph)
1307 1304
      : _is(new std::ifstream(fn.c_str())), local_is(true),
1308 1305
        _filename(fn), _graph(graph),
1309 1306
        _use_nodes(false), _use_edges(false),
1310 1307
        _skip_nodes(false), _skip_edges(false) {
1311
      if (!(*_is)) throw IoError(fn, "Cannot open file");
1308
      if (!(*_is)) throw IoError("Cannot open file", fn);
1312 1309
    }
1313 1310

	
1314 1311
    /// \brief Constructor
1315 1312
    ///
1316 1313
    /// Construct an undirected graph reader, which reads from the given
1317 1314
    /// file.
1318 1315
    GraphReader(const char* fn, Graph& graph)
1319 1316
      : _is(new std::ifstream(fn)), local_is(true),
1320 1317
        _filename(fn), _graph(graph),
1321 1318
        _use_nodes(false), _use_edges(false),
1322 1319
        _skip_nodes(false), _skip_edges(false) {
1323
      if (!(*_is)) throw IoError(fn, "Cannot open file");
1320
      if (!(*_is)) throw IoError("Cannot open file", fn);
1324 1321
    }
1325 1322

	
1326 1323
    /// \brief Destructor
1327 1324
    ~GraphReader() {
1328 1325
      for (typename NodeMaps::iterator it = _node_maps.begin();
1329 1326
           it != _node_maps.end(); ++it) {
1330 1327
        delete it->second;
1331 1328
      }
1332 1329

	
1333 1330
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1334 1331
           it != _edge_maps.end(); ++it) {
1335 1332
        delete it->second;
1336 1333
      }
1337 1334

	
1338 1335
      for (typename Attributes::iterator it = _attributes.begin();
1339 1336
           it != _attributes.end(); ++it) {
1340 1337
        delete it->second;
1341 1338
      }
1342 1339

	
1343 1340
      if (local_is) {
1344 1341
        delete _is;
1345 1342
      }
1346 1343

	
1347 1344
    }
1348 1345

	
1349 1346
  private:
1350 1347
    friend GraphReader<Graph> graphReader<>(std::istream& is, Graph& graph);
1351 1348
    friend GraphReader<Graph> graphReader<>(const std::string& fn,
1352 1349
                                            Graph& graph);
1353 1350
    friend GraphReader<Graph> graphReader<>(const char *fn, Graph& graph);
1354 1351

	
1355 1352
    GraphReader(GraphReader& other)
1356 1353
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1357 1354
        _use_nodes(other._use_nodes), _use_edges(other._use_edges),
1358 1355
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1359 1356

	
1360 1357
      other._is = 0;
1361 1358
      other.local_is = false;
1362 1359

	
1363 1360
      _node_index.swap(other._node_index);
1364 1361
      _edge_index.swap(other._edge_index);
1365 1362

	
1366 1363
      _node_maps.swap(other._node_maps);
1367 1364
      _edge_maps.swap(other._edge_maps);
1368 1365
      _attributes.swap(other._attributes);
1369 1366

	
1370 1367
      _nodes_caption = other._nodes_caption;
1371 1368
      _edges_caption = other._edges_caption;
1372 1369
      _attributes_caption = other._attributes_caption;
1373 1370

	
1374 1371
    }
1375 1372

	
1376 1373
    GraphReader& operator=(const GraphReader&);
1377 1374

	
1378 1375
  public:
1379 1376

	
1380 1377
    /// \name Reading rules
1381 1378
    /// @{
1382 1379

	
1383 1380
    /// \brief Node map reading rule
1384 1381
    ///
1385 1382
    /// Add a node map reading rule to the reader.
1386 1383
    template <typename Map>
1387 1384
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1388 1385
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1389 1386
      _reader_bits::MapStorageBase<Node>* storage =
1390 1387
        new _reader_bits::MapStorage<Node, Map>(map);
1391 1388
      _node_maps.push_back(std::make_pair(caption, storage));
1392 1389
      return *this;
1393 1390
    }
1394 1391

	
1395 1392
    /// \brief Node map reading rule
1396 1393
    ///
1397 1394
    /// Add a node map reading rule with specialized converter to the
1398 1395
    /// reader.
1399 1396
    template <typename Map, typename Converter>
1400 1397
    GraphReader& nodeMap(const std::string& caption, Map& map,
1401 1398
                           const Converter& converter = Converter()) {
1402 1399
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1403 1400
      _reader_bits::MapStorageBase<Node>* storage =
1404 1401
        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1405 1402
      _node_maps.push_back(std::make_pair(caption, storage));
1406 1403
      return *this;
1407 1404
    }
1408 1405

	
1409 1406
    /// \brief Edge map reading rule
1410 1407
    ///
1411 1408
    /// Add an edge map reading rule to the reader.
1412 1409
    template <typename Map>
1413 1410
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1414 1411
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1415 1412
      _reader_bits::MapStorageBase<Edge>* storage =
1416 1413
        new _reader_bits::MapStorage<Edge, Map>(map);
1417 1414
      _edge_maps.push_back(std::make_pair(caption, storage));
1418 1415
      return *this;
1419 1416
    }
1420 1417

	
1421 1418
    /// \brief Edge map reading rule
1422 1419
    ///
1423 1420
    /// Add an edge map reading rule with specialized converter to the
1424 1421
    /// reader.
1425 1422
    template <typename Map, typename Converter>
1426 1423
    GraphReader& edgeMap(const std::string& caption, Map& map,
1427 1424
                          const Converter& converter = Converter()) {
1428 1425
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1429 1426
      _reader_bits::MapStorageBase<Edge>* storage =
1430 1427
        new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1431 1428
      _edge_maps.push_back(std::make_pair(caption, storage));
1432 1429
      return *this;
1433 1430
    }
1434 1431

	
1435 1432
    /// \brief Arc map reading rule
1436 1433
    ///
1437 1434
    /// Add an arc map reading rule to the reader.
1438 1435
    template <typename Map>
1439 1436
    GraphReader& arcMap(const std::string& caption, Map& map) {
1440 1437
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1441 1438
      _reader_bits::MapStorageBase<Edge>* forward_storage =
1442 1439
        new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1443 1440
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1444 1441
      _reader_bits::MapStorageBase<Edge>* backward_storage =
1445 1442
        new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1446 1443
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1447 1444
      return *this;
1448 1445
    }
1449 1446

	
1450 1447
    /// \brief Arc map reading rule
1451 1448
    ///
1452 1449
    /// Add an arc map reading rule with specialized converter to the
1453 1450
    /// reader.
1454 1451
    template <typename Map, typename Converter>
1455 1452
    GraphReader& arcMap(const std::string& caption, Map& map,
1456 1453
                          const Converter& converter = Converter()) {
1457 1454
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1458 1455
      _reader_bits::MapStorageBase<Edge>* forward_storage =
1459 1456
        new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1460 1457
        (_graph, map, converter);
1461 1458
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1462 1459
      _reader_bits::MapStorageBase<Edge>* backward_storage =
1463 1460
        new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1464 1461
        (_graph, map, converter);
1465 1462
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1466 1463
      return *this;
1467 1464
    }
1468 1465

	
1469 1466
    /// \brief Attribute reading rule
1470 1467
    ///
1471 1468
    /// Add an attribute reading rule to the reader.
1472 1469
    template <typename Value>
1473 1470
    GraphReader& attribute(const std::string& caption, Value& value) {
1474 1471
      _reader_bits::ValueStorageBase* storage =
1475 1472
        new _reader_bits::ValueStorage<Value>(value);
1476 1473
      _attributes.insert(std::make_pair(caption, storage));
1477 1474
      return *this;
1478 1475
    }
1479 1476

	
1480 1477
    /// \brief Attribute reading rule
1481 1478
    ///
1482 1479
    /// Add an attribute reading rule with specialized converter to the
1483 1480
    /// reader.
1484 1481
    template <typename Value, typename Converter>
1485 1482
    GraphReader& attribute(const std::string& caption, Value& value,
1486 1483
                             const Converter& converter = Converter()) {
1487 1484
      _reader_bits::ValueStorageBase* storage =
1488 1485
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1489 1486
      _attributes.insert(std::make_pair(caption, storage));
1490 1487
      return *this;
1491 1488
    }
1492 1489

	
1493 1490
    /// \brief Node reading rule
1494 1491
    ///
1495 1492
    /// Add a node reading rule to reader.
1496 1493
    GraphReader& node(const std::string& caption, Node& node) {
1497 1494
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1498 1495
      Converter converter(_node_index);
1499 1496
      _reader_bits::ValueStorageBase* storage =
1500 1497
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1501 1498
      _attributes.insert(std::make_pair(caption, storage));
1502 1499
      return *this;
1503 1500
    }
1504 1501

	
1505 1502
    /// \brief Edge reading rule
1506 1503
    ///
1507 1504
    /// Add an edge reading rule to reader.
1508 1505
    GraphReader& edge(const std::string& caption, Edge& edge) {
1509 1506
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1510 1507
      Converter converter(_edge_index);
1511 1508
      _reader_bits::ValueStorageBase* storage =
1512 1509
        new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1513 1510
      _attributes.insert(std::make_pair(caption, storage));
1514 1511
      return *this;
1515 1512
    }
1516 1513

	
1517 1514
    /// \brief Arc reading rule
1518 1515
    ///
1519 1516
    /// Add an arc reading rule to reader.
1520 1517
    GraphReader& arc(const std::string& caption, Arc& arc) {
1521 1518
      typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
1522 1519
      Converter converter(_graph, _edge_index);
1523 1520
      _reader_bits::ValueStorageBase* storage =
1524 1521
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1525 1522
      _attributes.insert(std::make_pair(caption, storage));
1526 1523
      return *this;
1527 1524
    }
1528 1525

	
1529 1526
    /// @}
1530 1527

	
1531 1528
    /// \name Select section by name
1532 1529
    /// @{
1533 1530

	
1534 1531
    /// \brief Set \c \@nodes section to be read
1535 1532
    ///
1536 1533
    /// Set \c \@nodes section to be read.
1537 1534
    GraphReader& nodes(const std::string& caption) {
1538 1535
      _nodes_caption = caption;
1539 1536
      return *this;
1540 1537
    }
1541 1538

	
1542 1539
    /// \brief Set \c \@edges section to be read
1543 1540
    ///
1544 1541
    /// Set \c \@edges section to be read.
1545 1542
    GraphReader& edges(const std::string& caption) {
1546 1543
      _edges_caption = caption;
1547 1544
      return *this;
1548 1545
    }
1549 1546

	
1550 1547
    /// \brief Set \c \@attributes section to be read
1551 1548
    ///
1552 1549
    /// Set \c \@attributes section to be read.
1553 1550
    GraphReader& attributes(const std::string& caption) {
1554 1551
      _attributes_caption = caption;
1555 1552
      return *this;
1556 1553
    }
1557 1554

	
1558 1555
    /// @}
1559 1556

	
1560 1557
    /// \name Using previously constructed node or edge set
1561 1558
    /// @{
1562 1559

	
1563 1560
    /// \brief Use previously constructed node set
1564 1561
    ///
1565 1562
    /// Use previously constructed node set, and specify the node
1566 1563
    /// label map.
1567 1564
    template <typename Map>
1568 1565
    GraphReader& useNodes(const Map& map) {
1569 1566
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1570 1567
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1571 1568
      _use_nodes = true;
1572 1569
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1573 1570
      for (NodeIt n(_graph); n != INVALID; ++n) {
1574 1571
        _node_index.insert(std::make_pair(converter(map[n]), n));
1575 1572
      }
1576 1573
      return *this;
1577 1574
    }
1578 1575

	
1579 1576
    /// \brief Use previously constructed node set
1580 1577
    ///
1581 1578
    /// Use previously constructed node set, and specify the node
1582 1579
    /// label map and a functor which converts the label map values to
1583 1580
    /// \c std::string.
1584 1581
    template <typename Map, typename Converter>
1585 1582
    GraphReader& useNodes(const Map& map,
1586 1583
                            const Converter& converter = Converter()) {
1587 1584
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1588 1585
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1589 1586
      _use_nodes = true;
1590 1587
      for (NodeIt n(_graph); n != INVALID; ++n) {
1591 1588
        _node_index.insert(std::make_pair(converter(map[n]), n));
1592 1589
      }
1593 1590
      return *this;
1594 1591
    }
1595 1592

	
1596 1593
    /// \brief Use previously constructed edge set
1597 1594
    ///
1598 1595
    /// Use previously constructed edge set, and specify the edge
1599 1596
    /// label map.
1600 1597
    template <typename Map>
1601 1598
    GraphReader& useEdges(const Map& map) {
1602 1599
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1603 1600
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1604 1601
      _use_edges = true;
1605 1602
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1606 1603
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1607 1604
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1608 1605
      }
1609 1606
      return *this;
1610 1607
    }
1611 1608

	
1612 1609
    /// \brief Use previously constructed edge set
1613 1610
    ///
1614 1611
    /// Use previously constructed edge set, and specify the edge
1615 1612
    /// label map and a functor which converts the label map values to
1616 1613
    /// \c std::string.
1617 1614
    template <typename Map, typename Converter>
1618 1615
    GraphReader& useEdges(const Map& map,
1619 1616
                            const Converter& converter = Converter()) {
1620 1617
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1621 1618
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1622 1619
      _use_edges = true;
1623 1620
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1624 1621
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1625 1622
      }
1626 1623
      return *this;
1627 1624
    }
1628 1625

	
1629 1626
    /// \brief Skip the reading of node section
1630 1627
    ///
1631 1628
    /// Omit the reading of the node section. This implies that each node
1632 1629
    /// map reading rule will be abandoned, and the nodes of the graph
1633 1630
    /// will not be constructed, which usually cause that the edge set
1634 1631
    /// could not be read due to lack of node name
1635 1632
    /// could not be read due to lack of node name resolving.
1636 1633
    /// Therefore \c skipEdges() function should also be used, or
1637 1634
    /// \c useNodes() should be used to specify the label of the nodes.
1638 1635
    GraphReader& skipNodes() {
1639 1636
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
1640 1637
      _skip_nodes = true;
1641 1638
      return *this;
1642 1639
    }
1643 1640

	
1644 1641
    /// \brief Skip the reading of edge section
1645 1642
    ///
1646 1643
    /// Omit the reading of the edge section. This implies that each edge
1647 1644
    /// map reading rule will be abandoned, and the edges of the graph
1648 1645
    /// will not be constructed.
1649 1646
    GraphReader& skipEdges() {
1650 1647
      LEMON_ASSERT(!_skip_edges, "Skip edges already set");
1651 1648
      _skip_edges = true;
1652 1649
      return *this;
1653 1650
    }
1654 1651

	
1655 1652
    /// @}
1656 1653

	
1657 1654
  private:
1658 1655

	
1659 1656
    bool readLine() {
1660 1657
      std::string str;
1661 1658
      while(++line_num, std::getline(*_is, str)) {
1662 1659
        line.clear(); line.str(str);
1663 1660
        char c;
1664 1661
        if (line >> std::ws >> c && c != '#') {
1665 1662
          line.putback(c);
1666 1663
          return true;
1667 1664
        }
1668 1665
      }
1669 1666
      return false;
1670 1667
    }
1671 1668

	
1672 1669
    bool readSuccess() {
1673 1670
      return static_cast<bool>(*_is);
1674 1671
    }
1675 1672

	
1676 1673
    void skipSection() {
1677 1674
      char c;
1678 1675
      while (readSuccess() && line >> c && c != '@') {
1679 1676
        readLine();
1680 1677
      }
1681 1678
      line.putback(c);
1682 1679
    }
1683 1680

	
1684 1681
    void readNodes() {
1685 1682

	
1686 1683
      std::vector<int> map_index(_node_maps.size());
1687 1684
      int map_num, label_index;
1688 1685

	
1689 1686
      char c;
1690 1687
      if (!readLine() || !(line >> c) || c == '@') {
1691 1688
        if (readSuccess() && line) line.putback(c);
1692 1689
        if (!_node_maps.empty())
1693 1690
          throw FormatError("Cannot find map names");
1694 1691
        return;
1695 1692
      }
1696 1693
      line.putback(c);
1697 1694

	
1698 1695
      {
1699 1696
        std::map<std::string, int> maps;
1700 1697

	
1701 1698
        std::string map;
1702 1699
        int index = 0;
1703 1700
        while (_reader_bits::readToken(line, map)) {
1704 1701
          if (maps.find(map) != maps.end()) {
1705 1702
            std::ostringstream msg;
1706 1703
            msg << "Multiple occurence of node map: " << map;
1707 1704
            throw FormatError(msg.str());
1708 1705
          }
1709 1706
          maps.insert(std::make_pair(map, index));
1710 1707
          ++index;
1711 1708
        }
1712 1709

	
1713 1710
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1714 1711
          std::map<std::string, int>::iterator jt =
1715 1712
            maps.find(_node_maps[i].first);
1716 1713
          if (jt == maps.end()) {
1717 1714
            std::ostringstream msg;
1718
            msg << "Map not found in file: " << _node_maps[i].first;
1715
            msg << "Map not found: " << _node_maps[i].first;
1719 1716
            throw FormatError(msg.str());
1720 1717
          }
1721 1718
          map_index[i] = jt->second;
1722 1719
        }
1723 1720

	
1724 1721
        {
1725 1722
          std::map<std::string, int>::iterator jt = maps.find("label");
1726 1723
          if (jt != maps.end()) {
1727 1724
            label_index = jt->second;
1728 1725
          } else {
1729 1726
            label_index = -1;
1730 1727
          }
1731 1728
        }
1732 1729
        map_num = maps.size();
1733 1730
      }
1734 1731

	
1735 1732
      while (readLine() && line >> c && c != '@') {
1736 1733
        line.putback(c);
1737 1734

	
1738 1735
        std::vector<std::string> tokens(map_num);
1739 1736
        for (int i = 0; i < map_num; ++i) {
1740 1737
          if (!_reader_bits::readToken(line, tokens[i])) {
1741 1738
            std::ostringstream msg;
1742 1739
            msg << "Column not found (" << i + 1 << ")";
1743 1740
            throw FormatError(msg.str());
1744 1741
          }
1745 1742
        }
1746 1743
        if (line >> std::ws >> c)
1747
          throw FormatError("Extra character on the end of line");
1744
          throw FormatError("Extra character at the end of line");
1748 1745

	
1749 1746
        Node n;
1750 1747
        if (!_use_nodes) {
1751 1748
          n = _graph.addNode();
1752 1749
          if (label_index != -1)
1753 1750
            _node_index.insert(std::make_pair(tokens[label_index], n));
1754 1751
        } else {
1755 1752
          if (label_index == -1)
1756
            throw FormatError("Label map not found in file");
1753
            throw FormatError("Label map not found");
1757 1754
          typename std::map<std::string, Node>::iterator it =
1758 1755
            _node_index.find(tokens[label_index]);
1759 1756
          if (it == _node_index.end()) {
1760 1757
            std::ostringstream msg;
1761 1758
            msg << "Node with label not found: " << tokens[label_index];
1762 1759
            throw FormatError(msg.str());
1763 1760
          }
1764 1761
          n = it->second;
1765 1762
        }
1766 1763

	
1767 1764
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1768 1765
          _node_maps[i].second->set(n, tokens[map_index[i]]);
1769 1766
        }
1770 1767

	
1771 1768
      }
1772 1769
      if (readSuccess()) {
1773 1770
        line.putback(c);
1774 1771
      }
1775 1772
    }
1776 1773

	
1777 1774
    void readEdges() {
1778 1775

	
1779 1776
      std::vector<int> map_index(_edge_maps.size());
1780 1777
      int map_num, label_index;
1781 1778

	
1782 1779
      char c;
1783 1780
      if (!readLine() || !(line >> c) || c == '@') {
1784 1781
        if (readSuccess() && line) line.putback(c);
1785 1782
        if (!_edge_maps.empty())
1786 1783
          throw FormatError("Cannot find map names");
1787 1784
        return;
1788 1785
      }
1789 1786
      line.putback(c);
1790 1787

	
1791 1788
      {
1792 1789
        std::map<std::string, int> maps;
1793 1790

	
1794 1791
        std::string map;
1795 1792
        int index = 0;
1796 1793
        while (_reader_bits::readToken(line, map)) {
1797 1794
          if (maps.find(map) != maps.end()) {
1798 1795
            std::ostringstream msg;
1799 1796
            msg << "Multiple occurence of edge map: " << map;
1800 1797
            throw FormatError(msg.str());
1801 1798
          }
1802 1799
          maps.insert(std::make_pair(map, index));
1803 1800
          ++index;
1804 1801
        }
1805 1802

	
1806 1803
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1807 1804
          std::map<std::string, int>::iterator jt =
1808 1805
            maps.find(_edge_maps[i].first);
1809 1806
          if (jt == maps.end()) {
1810 1807
            std::ostringstream msg;
1811
            msg << "Map not found in file: " << _edge_maps[i].first;
1808
            msg << "Map not found: " << _edge_maps[i].first;
1812 1809
            throw FormatError(msg.str());
1813 1810
          }
1814 1811
          map_index[i] = jt->second;
1815 1812
        }
1816 1813

	
1817 1814
        {
1818 1815
          std::map<std::string, int>::iterator jt = maps.find("label");
1819 1816
          if (jt != maps.end()) {
1820 1817
            label_index = jt->second;
1821 1818
          } else {
1822 1819
            label_index = -1;
1823 1820
          }
1824 1821
        }
1825 1822
        map_num = maps.size();
1826 1823
      }
1827 1824

	
1828 1825
      while (readLine() && line >> c && c != '@') {
1829 1826
        line.putback(c);
1830 1827

	
1831 1828
        std::string source_token;
1832 1829
        std::string target_token;
1833 1830

	
1834 1831
        if (!_reader_bits::readToken(line, source_token))
1835 1832
          throw FormatError("Node u not found");
1836 1833

	
1837 1834
        if (!_reader_bits::readToken(line, target_token))
1838 1835
          throw FormatError("Node v not found");
1839 1836

	
1840 1837
        std::vector<std::string> tokens(map_num);
1841 1838
        for (int i = 0; i < map_num; ++i) {
1842 1839
          if (!_reader_bits::readToken(line, tokens[i])) {
1843 1840
            std::ostringstream msg;
1844 1841
            msg << "Column not found (" << i + 1 << ")";
1845 1842
            throw FormatError(msg.str());
1846 1843
          }
1847 1844
        }
1848 1845
        if (line >> std::ws >> c)
1849
          throw FormatError("Extra character on the end of line");
1846
          throw FormatError("Extra character at the end of line");
1850 1847

	
1851 1848
        Edge e;
1852 1849
        if (!_use_edges) {
1853 1850

	
1854 1851
          typename NodeIndex::iterator it;
1855 1852

	
1856 1853
          it = _node_index.find(source_token);
1857 1854
          if (it == _node_index.end()) {
1858 1855
            std::ostringstream msg;
1859 1856
            msg << "Item not found: " << source_token;
1860 1857
            throw FormatError(msg.str());
1861 1858
          }
1862 1859
          Node source = it->second;
1863 1860

	
1864 1861
          it = _node_index.find(target_token);
1865 1862
          if (it == _node_index.end()) {
1866 1863
            std::ostringstream msg;
1867 1864
            msg << "Item not found: " << target_token;
1868 1865
            throw FormatError(msg.str());
1869 1866
          }
1870 1867
          Node target = it->second;
1871 1868

	
1872 1869
          e = _graph.addEdge(source, target);
1873 1870
          if (label_index != -1)
1874 1871
            _edge_index.insert(std::make_pair(tokens[label_index], e));
1875 1872
        } else {
1876 1873
          if (label_index == -1)
1877
            throw FormatError("Label map not found in file");
1874
            throw FormatError("Label map not found");
1878 1875
          typename std::map<std::string, Edge>::iterator it =
1879 1876
            _edge_index.find(tokens[label_index]);
1880 1877
          if (it == _edge_index.end()) {
1881 1878
            std::ostringstream msg;
1882 1879
            msg << "Edge with label not found: " << tokens[label_index];
1883 1880
            throw FormatError(msg.str());
1884 1881
          }
1885 1882
          e = it->second;
1886 1883
        }
1887 1884

	
1888 1885
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1889 1886
          _edge_maps[i].second->set(e, tokens[map_index[i]]);
1890 1887
        }
1891 1888

	
1892 1889
      }
1893 1890
      if (readSuccess()) {
1894 1891
        line.putback(c);
1895 1892
      }
1896 1893
    }
1897 1894

	
1898 1895
    void readAttributes() {
1899 1896

	
1900 1897
      std::set<std::string> read_attr;
1901 1898

	
1902 1899
      char c;
1903 1900
      while (readLine() && line >> c && c != '@') {
1904 1901
        line.putback(c);
1905 1902

	
1906 1903
        std::string attr, token;
1907 1904
        if (!_reader_bits::readToken(line, attr))
1908 1905
          throw FormatError("Attribute name not found");
1909 1906
        if (!_reader_bits::readToken(line, token))
1910 1907
          throw FormatError("Attribute value not found");
1911 1908
        if (line >> c)
1912
          throw FormatError("Extra character on the end of line");
1909
          throw FormatError("Extra character at the end of line");
1913 1910

	
1914 1911
        {
1915 1912
          std::set<std::string>::iterator it = read_attr.find(attr);
1916 1913
          if (it != read_attr.end()) {
1917 1914
            std::ostringstream msg;
1918
            msg << "Multiple occurence of attribute " << attr;
1915
            msg << "Multiple occurence of attribute: " << attr;
1919 1916
            throw FormatError(msg.str());
1920 1917
          }
1921 1918
          read_attr.insert(attr);
1922 1919
        }
1923 1920

	
1924 1921
        {
1925 1922
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1926 1923
          while (it != _attributes.end() && it->first == attr) {
1927 1924
            it->second->set(token);
1928 1925
            ++it;
1929 1926
          }
1930 1927
        }
1931 1928

	
1932 1929
      }
1933 1930
      if (readSuccess()) {
1934 1931
        line.putback(c);
1935 1932
      }
1936 1933
      for (typename Attributes::iterator it = _attributes.begin();
1937 1934
           it != _attributes.end(); ++it) {
1938 1935
        if (read_attr.find(it->first) == read_attr.end()) {
1939 1936
          std::ostringstream msg;
1940
          msg << "Attribute not found in file: " << it->first;
1937
          msg << "Attribute not found: " << it->first;
1941 1938
          throw FormatError(msg.str());
1942 1939
        }
1943 1940
      }
1944 1941
    }
1945 1942

	
1946 1943
  public:
1947 1944

	
1948 1945
    /// \name Execution of the reader
1949 1946
    /// @{
1950 1947

	
1951 1948
    /// \brief Start the batch processing
1952 1949
    ///
1953 1950
    /// This function starts the batch processing
1954 1951
    void run() {
1955 1952

	
1956 1953
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1957 1954

	
1958 1955
      bool nodes_done = _skip_nodes;
1959 1956
      bool edges_done = _skip_edges;
1960 1957
      bool attributes_done = false;
1961 1958

	
1962 1959
      line_num = 0;
1963 1960
      readLine();
1964 1961
      skipSection();
1965 1962

	
1966 1963
      while (readSuccess()) {
1967 1964
        try {
1968 1965
          char c;
1969 1966
          std::string section, caption;
1970 1967
          line >> c;
1971 1968
          _reader_bits::readToken(line, section);
1972 1969
          _reader_bits::readToken(line, caption);
1973 1970

	
1974 1971
          if (line >> c)
1975
            throw FormatError("Extra character on the end of line");
1972
            throw FormatError("Extra character at the end of line");
1976 1973

	
1977 1974
          if (section == "nodes" && !nodes_done) {
1978 1975
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1979 1976
              readNodes();
1980 1977
              nodes_done = true;
1981 1978
            }
1982 1979
          } else if ((section == "edges" || section == "arcs") &&
1983 1980
                     !edges_done) {
1984 1981
            if (_edges_caption.empty() || _edges_caption == caption) {
1985 1982
              readEdges();
1986 1983
              edges_done = true;
1987 1984
            }
1988 1985
          } else if (section == "attributes" && !attributes_done) {
1989 1986
            if (_attributes_caption.empty() || _attributes_caption == caption) {
1990 1987
              readAttributes();
1991 1988
              attributes_done = true;
1992 1989
            }
1993 1990
          } else {
1994 1991
            readLine();
1995 1992
            skipSection();
1996 1993
          }
1997 1994
        } catch (FormatError& error) {
1998 1995
          error.line(line_num);
1999 1996
          error.file(_filename);
2000 1997
          throw;
2001 1998
        }
2002 1999
      }
2003 2000

	
2004 2001
      if (!nodes_done) {
2005 2002
        throw FormatError("Section @nodes not found");
2006 2003
      }
2007 2004

	
2008 2005
      if (!edges_done) {
2009 2006
        throw FormatError("Section @edges not found");
2010 2007
      }
2011 2008

	
2012 2009
      if (!attributes_done && !_attributes.empty()) {
2013 2010
        throw FormatError("Section @attributes not found");
2014 2011
      }
2015 2012

	
2016 2013
    }
2017 2014

	
2018 2015
    /// @}
2019 2016

	
2020 2017
  };
2021 2018

	
2022 2019
  /// \brief Return a \ref GraphReader class
2023 2020
  ///
2024 2021
  /// This function just returns a \ref GraphReader class.
2025 2022
  /// \relates GraphReader
2026 2023
  template <typename Graph>
2027 2024
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
2028 2025
    GraphReader<Graph> tmp(is, graph);
2029 2026
    return tmp;
2030 2027
  }
2031 2028

	
2032 2029
  /// \brief Return a \ref GraphReader class
2033 2030
  ///
2034 2031
  /// This function just returns a \ref GraphReader class.
2035 2032
  /// \relates GraphReader
2036 2033
  template <typename Graph>
2037 2034
  GraphReader<Graph> graphReader(const std::string& fn,
2038 2035
                                       Graph& graph) {
2039 2036
    GraphReader<Graph> tmp(fn, graph);
2040 2037
    return tmp;
2041 2038
  }
2042 2039

	
2043 2040
  /// \brief Return a \ref GraphReader class
2044 2041
  ///
2045 2042
  /// This function just returns a \ref GraphReader class.
2046 2043
  /// \relates GraphReader
2047 2044
  template <typename Graph>
2048 2045
  GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
2049 2046
    GraphReader<Graph> tmp(fn, graph);
2050 2047
    return tmp;
2051 2048
  }
2052 2049

	
2053 2050
  class SectionReader;
2054 2051

	
2055 2052
  SectionReader sectionReader(std::istream& is);
2056 2053
  SectionReader sectionReader(const std::string& fn);
2057 2054
  SectionReader sectionReader(const char* fn);
2058 2055

	
2059 2056
  /// \ingroup lemon_io
2060 2057
  ///
2061 2058
  /// \brief Section reader class
2062 2059
  ///
2063 2060
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
2064 2061
  /// which contain any data in arbitrary format. Such sections can be
2065 2062
  /// read with this class. A reading rule can be added to the class
2066 2063
  /// with two different functions. With the \c sectionLines() function a
2067 2064
  /// functor can process the section line-by-line, while with the \c
2068 2065
  /// sectionStream() member the section can be read from an input
2069 2066
  /// stream.
2070 2067
  class SectionReader {
2071 2068
  private:
2072 2069

	
2073 2070
    std::istream* _is;
2074 2071
    bool local_is;
2075 2072
    std::string _filename;
2076 2073

	
2077 2074
    typedef std::map<std::string, _reader_bits::Section*> Sections;
2078 2075
    Sections _sections;
2079 2076

	
2080 2077
    int line_num;
2081 2078
    std::istringstream line;
2082 2079

	
2083 2080
  public:
2084 2081

	
2085 2082
    /// \brief Constructor
2086 2083
    ///
2087 2084
    /// Construct a section reader, which reads from the given input
2088 2085
    /// stream.
2089 2086
    SectionReader(std::istream& is)
2090 2087
      : _is(&is), local_is(false) {}
2091 2088

	
2092 2089
    /// \brief Constructor
2093 2090
    ///
2094 2091
    /// Construct a section reader, which reads from the given file.
2095 2092
    SectionReader(const std::string& fn)
2096 2093
      : _is(new std::ifstream(fn.c_str())), local_is(true),
2097 2094
        _filename(fn) {
2098
      if (!(*_is)) throw IoError(fn, "Cannot open file");
2095
      if (!(*_is)) throw IoError("Cannot open file", fn);
2099 2096
    }
2100 2097

	
2101 2098
    /// \brief Constructor
2102 2099
    ///
2103 2100
    /// Construct a section reader, which reads from the given file.
2104 2101
    SectionReader(const char* fn)
2105 2102
      : _is(new std::ifstream(fn)), local_is(true),
2106 2103
        _filename(fn) {
2107
      if (!(*_is)) throw IoError(fn, "Cannot open file");
2104
      if (!(*_is)) throw IoError("Cannot open file", fn);
2108 2105
    }
2109 2106

	
2110 2107
    /// \brief Destructor
2111 2108
    ~SectionReader() {
2112 2109
      for (Sections::iterator it = _sections.begin();
2113 2110
           it != _sections.end(); ++it) {
2114 2111
        delete it->second;
2115 2112
      }
2116 2113

	
2117 2114
      if (local_is) {
2118 2115
        delete _is;
2119 2116
      }
2120 2117

	
2121 2118
    }
2122 2119

	
2123 2120
  private:
2124 2121

	
2125 2122
    friend SectionReader sectionReader(std::istream& is);
2126 2123
    friend SectionReader sectionReader(const std::string& fn);
2127 2124
    friend SectionReader sectionReader(const char* fn);
2128 2125

	
2129 2126
    SectionReader(SectionReader& other)
2130 2127
      : _is(other._is), local_is(other.local_is) {
2131 2128

	
2132 2129
      other._is = 0;
2133 2130
      other.local_is = false;
2134 2131

	
2135 2132
      _sections.swap(other._sections);
2136 2133
    }
2137 2134

	
2138 2135
    SectionReader& operator=(const SectionReader&);
2139 2136

	
2140 2137
  public:
2141 2138

	
2142 2139
    /// \name Section readers
2143 2140
    /// @{
2144 2141

	
2145 2142
    /// \brief Add a section processor with line oriented reading
2146 2143
    ///
2147 2144
    /// The first parameter is the type descriptor of the section, the
2148 2145
    /// second is a functor, which takes just one \c std::string
2149 2146
    /// parameter. At the reading process, each line of the section
2150 2147
    /// will be given to the functor object. However, the empty lines
2151 2148
    /// and the comment lines are filtered out, and the leading
2152 2149
    /// whitespaces are trimmed from each processed string.
2153 2150
    ///
2154 2151
    /// For example let's see a section, which contain several
2155 2152
    /// integers, which should be inserted into a vector.
2156 2153
    ///\code
2157 2154
    ///  @numbers
2158 2155
    ///  12 45 23
2159 2156
    ///  4
2160 2157
    ///  23 6
2161 2158
    ///\endcode
2162 2159
    ///
2163 2160
    /// The functor is implemented as a struct:
2164 2161
    ///\code
2165 2162
    ///  struct NumberSection {
2166 2163
    ///    std::vector<int>& _data;
2167 2164
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
2168 2165
    ///    void operator()(const std::string& line) {
2169 2166
    ///      std::istringstream ls(line);
2170 2167
    ///      int value;
2171 2168
    ///      while (ls >> value) _data.push_back(value);
2172 2169
    ///    }
2173 2170
    ///  };
2174 2171
    ///
2175 2172
    ///  // ...
2176 2173
    ///
2177 2174
    ///  reader.sectionLines("numbers", NumberSection(vec));
2178 2175
    ///\endcode
2179 2176
    template <typename Functor>
2180 2177
    SectionReader& sectionLines(const std::string& type, Functor functor) {
2181 2178
      LEMON_ASSERT(!type.empty(), "Type is empty.");
2182 2179
      LEMON_ASSERT(_sections.find(type) == _sections.end(),
2183 2180
                   "Multiple reading of section.");
2184 2181
      _sections.insert(std::make_pair(type,
2185 2182
        new _reader_bits::LineSection<Functor>(functor)));
2186 2183
      return *this;
2187 2184
    }
2188 2185

	
2189 2186

	
2190 2187
    /// \brief Add a section processor with stream oriented reading
2191 2188
    ///
2192 2189
    /// The first parameter is the type of the section, the second is
2193 2190
    /// a functor, which takes an \c std::istream& and an \c int&
2194 2191
    /// parameter, the latter regard to the line number of stream. The
2195 2192
    /// functor can read the input while the section go on, and the
2196 2193
    /// line number should be modified accordingly.
2197 2194
    template <typename Functor>
2198 2195
    SectionReader& sectionStream(const std::string& type, Functor functor) {
2199 2196
      LEMON_ASSERT(!type.empty(), "Type is empty.");
2200 2197
      LEMON_ASSERT(_sections.find(type) == _sections.end(),
2201 2198
                   "Multiple reading of section.");
2202 2199
      _sections.insert(std::make_pair(type,
2203 2200
         new _reader_bits::StreamSection<Functor>(functor)));
2204 2201
      return *this;
2205 2202
    }
2206 2203

	
2207 2204
    /// @}
2208 2205

	
2209 2206
  private:
2210 2207

	
2211 2208
    bool readLine() {
2212 2209
      std::string str;
2213 2210
      while(++line_num, std::getline(*_is, str)) {
2214 2211
        line.clear(); line.str(str);
2215 2212
        char c;
2216 2213
        if (line >> std::ws >> c && c != '#') {
2217 2214
          line.putback(c);
2218 2215
          return true;
2219 2216
        }
2220 2217
      }
2221 2218
      return false;
2222 2219
    }
2223 2220

	
2224 2221
    bool readSuccess() {
2225 2222
      return static_cast<bool>(*_is);
2226 2223
    }
2227 2224

	
2228 2225
    void skipSection() {
2229 2226
      char c;
2230 2227
      while (readSuccess() && line >> c && c != '@') {
2231 2228
        readLine();
2232 2229
      }
2233 2230
      line.putback(c);
2234 2231
    }
2235 2232

	
2236 2233
  public:
2237 2234

	
2238 2235

	
2239 2236
    /// \name Execution of the reader
2240 2237
    /// @{
2241 2238

	
2242 2239
    /// \brief Start the batch processing
2243 2240
    ///
2244 2241
    /// This function starts the batch processing.
2245 2242
    void run() {
2246 2243

	
2247 2244
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2248 2245

	
2249 2246
      std::set<std::string> extra_sections;
2250 2247

	
2251 2248
      line_num = 0;
2252 2249
      readLine();
2253 2250
      skipSection();
2254 2251

	
2255 2252
      while (readSuccess()) {
2256 2253
        try {
2257 2254
          char c;
2258 2255
          std::string section, caption;
2259 2256
          line >> c;
2260 2257
          _reader_bits::readToken(line, section);
2261 2258
          _reader_bits::readToken(line, caption);
2262 2259

	
2263 2260
          if (line >> c)
2264
            throw FormatError("Extra character on the end of line");
2261
            throw FormatError("Extra character at the end of line");
2265 2262

	
2266 2263
          if (extra_sections.find(section) != extra_sections.end()) {
2267 2264
            std::ostringstream msg;
2268
            msg << "Multiple occurence of section " << section;
2265
            msg << "Multiple occurence of section: " << section;
2269 2266
            throw FormatError(msg.str());
2270 2267
          }
2271 2268
          Sections::iterator it = _sections.find(section);
2272 2269
          if (it != _sections.end()) {
2273 2270
            extra_sections.insert(section);
2274 2271
            it->second->process(*_is, line_num);
2275 2272
          }
2276 2273
          readLine();
2277 2274
          skipSection();
2278 2275
        } catch (FormatError& error) {
2279 2276
          error.line(line_num);
2280 2277
          error.file(_filename);
2281 2278
          throw;
2282 2279
        }
2283 2280
      }
2284 2281
      for (Sections::iterator it = _sections.begin();
2285 2282
           it != _sections.end(); ++it) {
2286 2283
        if (extra_sections.find(it->first) == extra_sections.end()) {
2287 2284
          std::ostringstream os;
2288 2285
          os << "Cannot find section: " << it->first;
2289 2286
          throw FormatError(os.str());
2290 2287
        }
2291 2288
      }
2292 2289
    }
2293 2290

	
2294 2291
    /// @}
2295 2292

	
2296 2293
  };
2297 2294

	
2298 2295
  /// \brief Return a \ref SectionReader class
2299 2296
  ///
2300 2297
  /// This function just returns a \ref SectionReader class.
2301 2298
  /// \relates SectionReader
2302 2299
  inline SectionReader sectionReader(std::istream& is) {
2303 2300
    SectionReader tmp(is);
2304 2301
    return tmp;
2305 2302
  }
2306 2303

	
2307 2304
  /// \brief Return a \ref SectionReader class
2308 2305
  ///
2309 2306
  /// This function just returns a \ref SectionReader class.
2310 2307
  /// \relates SectionReader
2311 2308
  inline SectionReader sectionReader(const std::string& fn) {
2312 2309
    SectionReader tmp(fn);
2313 2310
    return tmp;
2314 2311
  }
2315 2312

	
2316 2313
  /// \brief Return a \ref SectionReader class
2317 2314
  ///
2318 2315
  /// This function just returns a \ref SectionReader class.
2319 2316
  /// \relates SectionReader
2320 2317
  inline SectionReader sectionReader(const char* fn) {
2321 2318
    SectionReader tmp(fn);
2322 2319
    return tmp;
2323 2320
  }
2324 2321

	
2325 2322
  /// \ingroup lemon_io
2326 2323
  ///
2327 2324
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file
2328 2325
  ///
2329 2326
  /// This class can be used to read the sections, the map names and
2330 2327
  /// the attributes from a file. Usually, the LEMON programs know
2331 2328
  /// that, which type of graph, which maps and which attributes
2332 2329
  /// should be read from a file, but in general tools (like glemon)
2333 2330
  /// the contents of an LGF file should be guessed somehow. This class
2334 2331
  /// reads the graph and stores the appropriate information for
2335 2332
  /// reading the graph.
2336 2333
  ///
2337 2334
  ///\code
2338 2335
  /// LgfContents contents("graph.lgf");
2339 2336
  /// contents.run();
2340 2337
  ///
2341 2338
  /// // Does it contain any node section and arc section?
2342 2339
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
2343 2340
  ///   std::cerr << "Failure, cannot find graph." << std::endl;
2344 2341
  ///   return -1;
2345 2342
  /// }
2346 2343
  /// std::cout << "The name of the default node section: "
2347 2344
  ///           << contents.nodeSection(0) << std::endl;
2348 2345
  /// std::cout << "The number of the arc maps: "
2349 2346
  ///           << contents.arcMaps(0).size() << std::endl;
2350 2347
  /// std::cout << "The name of second arc map: "
2351 2348
  ///           << contents.arcMaps(0)[1] << std::endl;
2352 2349
  ///\endcode
2353 2350
  class LgfContents {
2354 2351
  private:
2355 2352

	
2356 2353
    std::istream* _is;
2357 2354
    bool local_is;
2358 2355

	
2359 2356
    std::vector<std::string> _node_sections;
2360 2357
    std::vector<std::string> _edge_sections;
2361 2358
    std::vector<std::string> _attribute_sections;
2362 2359
    std::vector<std::string> _extra_sections;
2363 2360

	
2364 2361
    std::vector<bool> _arc_sections;
2365 2362

	
2366 2363
    std::vector<std::vector<std::string> > _node_maps;
2367 2364
    std::vector<std::vector<std::string> > _edge_maps;
2368 2365

	
2369 2366
    std::vector<std::vector<std::string> > _attributes;
2370 2367

	
2371 2368

	
2372 2369
    int line_num;
2373 2370
    std::istringstream line;
2374 2371

	
2375 2372
  public:
2376 2373

	
2377 2374
    /// \brief Constructor
2378 2375
    ///
2379 2376
    /// Construct an \e LGF contents reader, which reads from the given
2380 2377
    /// input stream.
2381 2378
    LgfContents(std::istream& is)
2382 2379
      : _is(&is), local_is(false) {}
2383 2380

	
2384 2381
    /// \brief Constructor
2385 2382
    ///
2386 2383
    /// Construct an \e LGF contents reader, which reads from the given
2387 2384
    /// file.
2388 2385
    LgfContents(const std::string& fn)
2389 2386
      : _is(new std::ifstream(fn.c_str())), local_is(true) {
2390
      if (!(*_is)) throw IoError(fn, "Cannot open file");
2387
      if (!(*_is)) throw IoError("Cannot open file", fn);
2391 2388
    }
2392 2389

	
2393 2390
    /// \brief Constructor
2394 2391
    ///
2395 2392
    /// Construct an \e LGF contents reader, which reads from the given
2396 2393
    /// file.
2397 2394
    LgfContents(const char* fn)
2398 2395
      : _is(new std::ifstream(fn)), local_is(true) {
2399
      if (!(*_is)) throw IoError(fn, "Cannot open file");
2396
      if (!(*_is)) throw IoError("Cannot open file", fn);
2400 2397
    }
2401 2398

	
2402 2399
    /// \brief Destructor
2403 2400
    ~LgfContents() {
2404 2401
      if (local_is) delete _is;
2405 2402
    }
2406 2403

	
2407 2404
  private:
2408 2405

	
2409 2406
    LgfContents(const LgfContents&);
2410 2407
    LgfContents& operator=(const LgfContents&);
2411 2408

	
2412 2409
  public:
2413 2410

	
2414 2411

	
2415 2412
    /// \name Node sections
2416 2413
    /// @{
2417 2414

	
2418 2415
    /// \brief Gives back the number of node sections in the file.
2419 2416
    ///
2420 2417
    /// Gives back the number of node sections in the file.
2421 2418
    int nodeSectionNum() const {
2422 2419
      return _node_sections.size();
2423 2420
    }
2424 2421

	
2425 2422
    /// \brief Returns the node section name at the given position.
2426 2423
    ///
2427 2424
    /// Returns the node section name at the given position.
2428 2425
    const std::string& nodeSection(int i) const {
2429 2426
      return _node_sections[i];
2430 2427
    }
2431 2428

	
2432 2429
    /// \brief Gives back the node maps for the given section.
2433 2430
    ///
2434 2431
    /// Gives back the node maps for the given section.
2435 2432
    const std::vector<std::string>& nodeMapNames(int i) const {
2436 2433
      return _node_maps[i];
2437 2434
    }
2438 2435

	
2439 2436
    /// @}
2440 2437

	
2441 2438
    /// \name Arc/Edge sections
2442 2439
    /// @{
2443 2440

	
2444 2441
    /// \brief Gives back the number of arc/edge sections in the file.
2445 2442
    ///
2446 2443
    /// Gives back the number of arc/edge sections in the file.
2447 2444
    /// \note It is synonym of \c edgeSectionNum().
2448 2445
    int arcSectionNum() const {
2449 2446
      return _edge_sections.size();
2450 2447
    }
2451 2448

	
2452 2449
    /// \brief Returns the arc/edge section name at the given position.
2453 2450
    ///
2454 2451
    /// Returns the arc/edge section name at the given position.
2455 2452
    /// \note It is synonym of \c edgeSection().
2456 2453
    const std::string& arcSection(int i) const {
2457 2454
      return _edge_sections[i];
2458 2455
    }
2459 2456

	
2460 2457
    /// \brief Gives back the arc/edge maps for the given section.
2461 2458
    ///
2462 2459
    /// Gives back the arc/edge maps for the given section.
2463 2460
    /// \note It is synonym of \c edgeMapNames().
2464 2461
    const std::vector<std::string>& arcMapNames(int i) const {
2465 2462
      return _edge_maps[i];
2466 2463
    }
2467 2464

	
2468 2465
    /// @}
2469 2466

	
2470 2467
    /// \name Synonyms
2471 2468
    /// @{
2472 2469

	
2473 2470
    /// \brief Gives back the number of arc/edge sections in the file.
2474 2471
    ///
2475 2472
    /// Gives back the number of arc/edge sections in the file.
2476 2473
    /// \note It is synonym of \c arcSectionNum().
2477 2474
    int edgeSectionNum() const {
2478 2475
      return _edge_sections.size();
2479 2476
    }
2480 2477

	
2481 2478
    /// \brief Returns the section name at the given position.
2482 2479
    ///
2483 2480
    /// Returns the section name at the given position.
2484 2481
    /// \note It is synonym of \c arcSection().
2485 2482
    const std::string& edgeSection(int i) const {
2486 2483
      return _edge_sections[i];
2487 2484
    }
2488 2485

	
2489 2486
    /// \brief Gives back the edge maps for the given section.
2490 2487
    ///
2491 2488
    /// Gives back the edge maps for the given section.
2492 2489
    /// \note It is synonym of \c arcMapNames().
2493 2490
    const std::vector<std::string>& edgeMapNames(int i) const {
2494 2491
      return _edge_maps[i];
2495 2492
    }
2496 2493

	
2497 2494
    /// @}
2498 2495

	
2499 2496
    /// \name Attribute sections
2500 2497
    /// @{
2501 2498

	
2502 2499
    /// \brief Gives back the number of attribute sections in the file.
2503 2500
    ///
2504 2501
    /// Gives back the number of attribute sections in the file.
2505 2502
    int attributeSectionNum() const {
2506 2503
      return _attribute_sections.size();
2507 2504
    }
2508 2505

	
2509 2506
    /// \brief Returns the attribute section name at the given position.
2510 2507
    ///
2511 2508
    /// Returns the attribute section name at the given position.
2512 2509
    const std::string& attributeSectionNames(int i) const {
2513 2510
      return _attribute_sections[i];
2514 2511
    }
2515 2512

	
2516 2513
    /// \brief Gives back the attributes for the given section.
2517 2514
    ///
2518 2515
    /// Gives back the attributes for the given section.
2519 2516
    const std::vector<std::string>& attributes(int i) const {
2520 2517
      return _attributes[i];
2521 2518
    }
2522 2519

	
2523 2520
    /// @}
2524 2521

	
2525 2522
    /// \name Extra sections
2526 2523
    /// @{
2527 2524

	
2528 2525
    /// \brief Gives back the number of extra sections in the file.
2529 2526
    ///
2530 2527
    /// Gives back the number of extra sections in the file.
2531 2528
    int extraSectionNum() const {
2532 2529
      return _extra_sections.size();
2533 2530
    }
2534 2531

	
2535 2532
    /// \brief Returns the extra section type at the given position.
2536 2533
    ///
2537 2534
    /// Returns the section type at the given position.
2538 2535
    const std::string& extraSection(int i) const {
2539 2536
      return _extra_sections[i];
2540 2537
    }
2541 2538

	
2542 2539
    /// @}
2543 2540

	
2544 2541
  private:
2545 2542

	
2546 2543
    bool readLine() {
2547 2544
      std::string str;
2548 2545
      while(++line_num, std::getline(*_is, str)) {
2549 2546
        line.clear(); line.str(str);
2550 2547
        char c;
2551 2548
        if (line >> std::ws >> c && c != '#') {
2552 2549
          line.putback(c);
2553 2550
          return true;
2554 2551
        }
2555 2552
      }
2556 2553
      return false;
2557 2554
    }
2558 2555

	
2559 2556
    bool readSuccess() {
2560 2557
      return static_cast<bool>(*_is);
2561 2558
    }
2562 2559

	
2563 2560
    void skipSection() {
2564 2561
      char c;
2565 2562
      while (readSuccess() && line >> c && c != '@') {
2566 2563
        readLine();
2567 2564
      }
2568 2565
      line.putback(c);
2569 2566
    }
2570 2567

	
2571 2568
    void readMaps(std::vector<std::string>& maps) {
2572 2569
      char c;
2573 2570
      if (!readLine() || !(line >> c) || c == '@') {
2574 2571
        if (readSuccess() && line) line.putback(c);
2575 2572
        return;
2576 2573
      }
2577 2574
      line.putback(c);
2578 2575
      std::string map;
2579 2576
      while (_reader_bits::readToken(line, map)) {
2580 2577
        maps.push_back(map);
2581 2578
      }
2582 2579
    }
2583 2580

	
2584 2581
    void readAttributes(std::vector<std::string>& attrs) {
2585 2582
      readLine();
2586 2583
      char c;
2587 2584
      while (readSuccess() && line >> c && c != '@') {
2588 2585
        line.putback(c);
2589 2586
        std::string attr;
2590 2587
        _reader_bits::readToken(line, attr);
2591 2588
        attrs.push_back(attr);
2592 2589
        readLine();
2593 2590
      }
2594 2591
      line.putback(c);
2595 2592
    }
2596 2593

	
2597 2594
  public:
2598 2595

	
2599 2596
    /// \name Execution of the contents reader
2600 2597
    /// @{
2601 2598

	
2602 2599
    /// \brief Starts the reading
2603 2600
    ///
2604 2601
    /// This function starts the reading.
2605 2602
    void run() {
2606 2603

	
2607 2604
      readLine();
2608 2605
      skipSection();
2609 2606

	
2610 2607
      while (readSuccess()) {
2611 2608

	
2612 2609
        char c;
2613 2610
        line >> c;
2614 2611

	
2615 2612
        std::string section, caption;
2616 2613
        _reader_bits::readToken(line, section);
2617 2614
        _reader_bits::readToken(line, caption);
2618 2615

	
2619 2616
        if (section == "nodes") {
2620 2617
          _node_sections.push_back(caption);
2621 2618
          _node_maps.push_back(std::vector<std::string>());
2622 2619
          readMaps(_node_maps.back());
2623 2620
          readLine(); skipSection();
2624 2621
        } else if (section == "arcs" || section == "edges") {
2625 2622
          _edge_sections.push_back(caption);
2626 2623
          _arc_sections.push_back(section == "arcs");
2627 2624
          _edge_maps.push_back(std::vector<std::string>());
2628 2625
          readMaps(_edge_maps.back());
2629 2626
          readLine(); skipSection();
2630 2627
        } else if (section == "attributes") {
2631 2628
          _attribute_sections.push_back(caption);
2632 2629
          _attributes.push_back(std::vector<std::string>());
2633 2630
          readAttributes(_attributes.back());
2634 2631
        } else {
2635 2632
          _extra_sections.push_back(section);
2636 2633
          readLine(); skipSection();
2637 2634
        }
2638 2635
      }
2639 2636
    }
2640 2637

	
2641 2638
    /// @}
2642 2639

	
2643 2640
  };
2644 2641
}
2645 2642

	
2646 2643
#endif
Ignore white space 131072 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
///\ingroup lemon_io
20 20
///\file
21 21
///\brief \ref lgf-format "LEMON Graph Format" writer.
22 22

	
23 23

	
24 24
#ifndef LEMON_LGF_WRITER_H
25 25
#define LEMON_LGF_WRITER_H
26 26

	
27 27
#include <iostream>
28 28
#include <fstream>
29 29
#include <sstream>
30 30

	
31 31
#include <algorithm>
32 32

	
33 33
#include <vector>
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 40
#include <lemon/concept_check.h>
41 41
#include <lemon/concepts/maps.h>
42 42

	
43 43
namespace lemon {
44 44

	
45 45
  namespace _writer_bits {
46 46

	
47 47
    template <typename Value>
48 48
    struct DefaultConverter {
49 49
      std::string operator()(const Value& value) {
50 50
        std::ostringstream os;
51 51
        os << value;
52 52
        return os.str();
53 53
      }
54 54
    };
55 55

	
56 56
    template <typename T>
57 57
    bool operator<(const T&, const T&) {
58 58
      throw FormatError("Label map is not comparable");
59 59
    }
60 60

	
61 61
    template <typename _Map>
62 62
    class MapLess {
63 63
    public:
64 64
      typedef _Map Map;
65 65
      typedef typename Map::Key Item;
66 66

	
67 67
    private:
68 68
      const Map& _map;
69 69

	
70 70
    public:
71 71
      MapLess(const Map& map) : _map(map) {}
72 72

	
73 73
      bool operator()(const Item& left, const Item& right) {
74 74
        return _map[left] < _map[right];
75 75
      }
76 76
    };
77 77

	
78 78
    template <typename _Graph, bool _dir, typename _Map>
79 79
    class GraphArcMapLess {
80 80
    public:
81 81
      typedef _Map Map;
82 82
      typedef _Graph Graph;
83 83
      typedef typename Graph::Edge Item;
84 84

	
85 85
    private:
86 86
      const Graph& _graph;
87 87
      const Map& _map;
88 88

	
89 89
    public:
90 90
      GraphArcMapLess(const Graph& graph, const Map& map)
91 91
        : _graph(graph), _map(map) {}
92 92

	
93 93
      bool operator()(const Item& left, const Item& right) {
94 94
        return _map[_graph.direct(left, _dir)] <
95 95
          _map[_graph.direct(right, _dir)];
96 96
      }
97 97
    };
98 98

	
99 99
    template <typename _Item>
100 100
    class MapStorageBase {
101 101
    public:
102 102
      typedef _Item Item;
103 103

	
104 104
    public:
105 105
      MapStorageBase() {}
106 106
      virtual ~MapStorageBase() {}
107 107

	
108 108
      virtual std::string get(const Item& item) = 0;
109 109
      virtual void sort(std::vector<Item>&) = 0;
110 110
    };
111 111

	
112 112
    template <typename _Item, typename _Map,
113 113
              typename _Converter = DefaultConverter<typename _Map::Value> >
114 114
    class MapStorage : public MapStorageBase<_Item> {
115 115
    public:
116 116
      typedef _Map Map;
117 117
      typedef _Converter Converter;
118 118
      typedef _Item Item;
119 119

	
120 120
    private:
121 121
      const Map& _map;
122 122
      Converter _converter;
123 123

	
124 124
    public:
125 125
      MapStorage(const Map& map, const Converter& converter = Converter())
126 126
        : _map(map), _converter(converter) {}
127 127
      virtual ~MapStorage() {}
128 128

	
129 129
      virtual std::string get(const Item& item) {
130 130
        return _converter(_map[item]);
131 131
      }
132 132
      virtual void sort(std::vector<Item>& items) {
133 133
        MapLess<Map> less(_map);
134 134
        std::sort(items.begin(), items.end(), less);
135 135
      }
136 136
    };
137 137

	
138 138
    template <typename _Graph, bool _dir, typename _Map,
139 139
              typename _Converter = DefaultConverter<typename _Map::Value> >
140 140
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
141 141
    public:
142 142
      typedef _Map Map;
143 143
      typedef _Converter Converter;
144 144
      typedef _Graph Graph;
145 145
      typedef typename Graph::Edge Item;
146 146
      static const bool dir = _dir;
147 147

	
148 148
    private:
149 149
      const Graph& _graph;
150 150
      const Map& _map;
151 151
      Converter _converter;
152 152

	
153 153
    public:
154 154
      GraphArcMapStorage(const Graph& graph, const Map& map,
155 155
                         const Converter& converter = Converter())
156 156
        : _graph(graph), _map(map), _converter(converter) {}
157 157
      virtual ~GraphArcMapStorage() {}
158 158

	
159 159
      virtual std::string get(const Item& item) {
160 160
        return _converter(_map[_graph.direct(item, dir)]);
161 161
      }
162 162
      virtual void sort(std::vector<Item>& items) {
163 163
        GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
164 164
        std::sort(items.begin(), items.end(), less);
165 165
      }
166 166
    };
167 167

	
168 168
    class ValueStorageBase {
169 169
    public:
170 170
      ValueStorageBase() {}
171 171
      virtual ~ValueStorageBase() {}
172 172

	
173 173
      virtual std::string get() = 0;
174 174
    };
175 175

	
176 176
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
177 177
    class ValueStorage : public ValueStorageBase {
178 178
    public:
179 179
      typedef _Value Value;
180 180
      typedef _Converter Converter;
181 181

	
182 182
    private:
183 183
      const Value& _value;
184 184
      Converter _converter;
185 185

	
186 186
    public:
187 187
      ValueStorage(const Value& value, const Converter& converter = Converter())
188 188
        : _value(value), _converter(converter) {}
189 189

	
190 190
      virtual std::string get() {
191 191
        return _converter(_value);
192 192
      }
193 193
    };
194 194

	
195 195
    template <typename Value>
196 196
    struct MapLookUpConverter {
197 197
      const std::map<Value, std::string>& _map;
198 198

	
199 199
      MapLookUpConverter(const std::map<Value, std::string>& map)
200 200
        : _map(map) {}
201 201

	
202 202
      std::string operator()(const Value& str) {
203 203
        typename std::map<Value, std::string>::const_iterator it =
204 204
          _map.find(str);
205 205
        if (it == _map.end()) {
206 206
          throw FormatError("Item not found");
207 207
        }
208 208
        return it->second;
209 209
      }
210 210
    };
211 211

	
212 212
    template <typename Graph>
213 213
    struct GraphArcLookUpConverter {
214 214
      const Graph& _graph;
215 215
      const std::map<typename Graph::Edge, std::string>& _map;
216 216

	
217 217
      GraphArcLookUpConverter(const Graph& graph,
218 218
                              const std::map<typename Graph::Edge,
219 219
                                             std::string>& map)
220 220
        : _graph(graph), _map(map) {}
221 221

	
222 222
      std::string operator()(const typename Graph::Arc& val) {
223 223
        typename std::map<typename Graph::Edge, std::string>
224 224
          ::const_iterator it = _map.find(val);
225 225
        if (it == _map.end()) {
226 226
          throw FormatError("Item not found");
227 227
        }
228 228
        return (_graph.direction(val) ? '+' : '-') + it->second;
229 229
      }
230 230
    };
231 231

	
232 232
    inline bool isWhiteSpace(char c) {
233 233
      return c == ' ' || c == '\t' || c == '\v' ||
234 234
        c == '\n' || c == '\r' || c == '\f';
235 235
    }
236 236

	
237 237
    inline bool isEscaped(char c) {
238 238
      return c == '\\' || c == '\"' || c == '\'' ||
239 239
        c == '\a' || c == '\b';
240 240
    }
241 241

	
242 242
    inline static void writeEscape(std::ostream& os, char c) {
243 243
      switch (c) {
244 244
      case '\\':
245 245
        os << "\\\\";
246 246
        return;
247 247
      case '\"':
248 248
        os << "\\\"";
249 249
        return;
250 250
      case '\a':
251 251
        os << "\\a";
252 252
        return;
253 253
      case '\b':
254 254
        os << "\\b";
255 255
        return;
256 256
      case '\f':
257 257
        os << "\\f";
258 258
        return;
259 259
      case '\r':
260 260
        os << "\\r";
261 261
        return;
262 262
      case '\n':
263 263
        os << "\\n";
264 264
        return;
265 265
      case '\t':
266 266
        os << "\\t";
267 267
        return;
268 268
      case '\v':
269 269
        os << "\\v";
270 270
        return;
271 271
      default:
272 272
        if (c < 0x20) {
273 273
          std::ios::fmtflags flags = os.flags();
274 274
          os << '\\' << std::oct << static_cast<int>(c);
275 275
          os.flags(flags);
276 276
        } else {
277 277
          os << c;
278 278
        }
279 279
        return;
280 280
      }
281 281
    }
282 282

	
283 283
    inline bool requireEscape(const std::string& str) {
284 284
      if (str.empty() || str[0] == '@') return true;
285 285
      std::istringstream is(str);
286 286
      char c;
287 287
      while (is.get(c)) {
288 288
        if (isWhiteSpace(c) || isEscaped(c)) {
289 289
          return true;
290 290
        }
291 291
      }
292 292
      return false;
293 293
    }
294 294

	
295 295
    inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
296 296

	
297 297
      if (requireEscape(str)) {
298 298
        os << '\"';
299 299
        for (std::string::const_iterator it = str.begin();
300 300
             it != str.end(); ++it) {
301 301
          writeEscape(os, *it);
302 302
        }
303 303
        os << '\"';
304 304
      } else {
305 305
        os << str;
306 306
      }
307 307
      return os;
308 308
    }
309 309

	
310 310
    class Section {
311 311
    public:
312 312
      virtual ~Section() {}
313 313
      virtual void process(std::ostream& os) = 0;
314 314
    };
315 315

	
316 316
    template <typename Functor>
317 317
    class LineSection : public Section {
318 318
    private:
319 319

	
320 320
      Functor _functor;
321 321

	
322 322
    public:
323 323

	
324 324
      LineSection(const Functor& functor) : _functor(functor) {}
325 325
      virtual ~LineSection() {}
326 326

	
327 327
      virtual void process(std::ostream& os) {
328 328
        std::string line;
329 329
        while (!(line = _functor()).empty()) os << line << std::endl;
330 330
      }
331 331
    };
332 332

	
333 333
    template <typename Functor>
334 334
    class StreamSection : public Section {
335 335
    private:
336 336

	
337 337
      Functor _functor;
338 338

	
339 339
    public:
340 340

	
341 341
      StreamSection(const Functor& functor) : _functor(functor) {}
342 342
      virtual ~StreamSection() {}
343 343

	
344 344
      virtual void process(std::ostream& os) {
345 345
        _functor(os);
346 346
      }
347 347
    };
348 348

	
349 349
  }
350 350

	
351 351
  template <typename Digraph>
352 352
  class DigraphWriter;
353 353

	
354 354
  template <typename Digraph>
355 355
  DigraphWriter<Digraph> digraphWriter(std::ostream& os,
356 356
                                       const Digraph& digraph);
357 357

	
358 358
  template <typename Digraph>
359 359
  DigraphWriter<Digraph> digraphWriter(const std::string& fn,
360 360
                                       const Digraph& digraph);
361 361

	
362 362
  template <typename Digraph>
363 363
  DigraphWriter<Digraph> digraphWriter(const char *fn,
364 364
                                       const Digraph& digraph);
365 365

	
366 366
  /// \ingroup lemon_io
367 367
  ///
368 368
  /// \brief \ref lgf-format "LGF" writer for directed graphs
369 369
  ///
370 370
  /// This utility writes an \ref lgf-format "LGF" file.
371 371
  ///
372 372
  /// The writing method does a batch processing. The user creates a
373 373
  /// writer object, then various writing rules can be added to the
374 374
  /// writer, and eventually the writing is executed with the \c run()
375 375
  /// member function. A map writing rule can be added to the writer
376 376
  /// with the \c nodeMap() or \c arcMap() members. An optional
377 377
  /// converter parameter can also be added as a standard functor
378 378
  /// converting from the value type of the map to \c std::string. If it
379 379
  /// is set, it will determine how the value type of the map is written to
380 380
  /// the output stream. If the functor is not set, then a default
381 381
  /// conversion will be used. The \c attribute(), \c node() and \c
382 382
  /// arc() functions are used to add attribute writing rules.
383 383
  ///
384 384
  ///\code
385 385
  /// DigraphWriter<Digraph>(std::cout, digraph).
386 386
  ///   nodeMap("coordinates", coord_map).
387 387
  ///   nodeMap("size", size).
388 388
  ///   nodeMap("title", title).
389 389
  ///   arcMap("capacity", cap_map).
390 390
  ///   node("source", src).
391 391
  ///   node("target", trg).
392 392
  ///   attribute("caption", caption).
393 393
  ///   run();
394 394
  ///\endcode
395 395
  ///
396 396
  ///
397 397
  /// By default, the writer does not write additional captions to the
398 398
  /// sections, but they can be give as an optional parameter of
399 399
  /// the \c nodes(), \c arcs() or \c
400 400
  /// attributes() functions.
401 401
  ///
402 402
  /// The \c skipNodes() and \c skipArcs() functions forbid the
403 403
  /// writing of the sections. If two arc sections should be written
404 404
  /// to the output, it can be done in two passes, the first pass
405 405
  /// writes the node section and the first arc section, then the
406 406
  /// second pass skips the node section and writes just the arc
407 407
  /// section to the stream. The output stream can be retrieved with
408 408
  /// the \c ostream() function, hence the second pass can append its
409 409
  /// output to the output of the first pass.
410 410
  template <typename _Digraph>
411 411
  class DigraphWriter {
412 412
  public:
413 413

	
414 414
    typedef _Digraph Digraph;
415 415
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
416 416

	
417 417
  private:
418 418

	
419 419

	
420 420
    std::ostream* _os;
421 421
    bool local_os;
422 422

	
423 423
    const Digraph& _digraph;
424 424

	
425 425
    std::string _nodes_caption;
426 426
    std::string _arcs_caption;
427 427
    std::string _attributes_caption;
428 428

	
429 429
    typedef std::map<Node, std::string> NodeIndex;
430 430
    NodeIndex _node_index;
431 431
    typedef std::map<Arc, std::string> ArcIndex;
432 432
    ArcIndex _arc_index;
433 433

	
434 434
    typedef std::vector<std::pair<std::string,
435 435
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
436 436
    NodeMaps _node_maps;
437 437

	
438 438
    typedef std::vector<std::pair<std::string,
439 439
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
440 440
    ArcMaps _arc_maps;
441 441

	
442 442
    typedef std::vector<std::pair<std::string,
443 443
      _writer_bits::ValueStorageBase*> > Attributes;
444 444
    Attributes _attributes;
445 445

	
446 446
    bool _skip_nodes;
447 447
    bool _skip_arcs;
448 448

	
449 449
  public:
450 450

	
451 451
    /// \brief Constructor
452 452
    ///
453 453
    /// Construct a directed graph writer, which writes to the given
454 454
    /// output stream.
455 455
    DigraphWriter(std::ostream& is, const Digraph& digraph)
456 456
      : _os(&is), local_os(false), _digraph(digraph),
457 457
        _skip_nodes(false), _skip_arcs(false) {}
458 458

	
459 459
    /// \brief Constructor
460 460
    ///
461 461
    /// Construct a directed graph writer, which writes to the given
462 462
    /// output file.
463 463
    DigraphWriter(const std::string& fn, const Digraph& digraph)
464 464
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
465 465
        _skip_nodes(false), _skip_arcs(false) {
466
      if (!(*_os)) throw IoError(fn, "Cannot write file");
466
      if (!(*_os)) throw IoError("Cannot write file", fn);
467 467
    }
468 468

	
469 469
    /// \brief Constructor
470 470
    ///
471 471
    /// Construct a directed graph writer, which writes to the given
472 472
    /// output file.
473 473
    DigraphWriter(const char* fn, const Digraph& digraph)
474 474
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
475 475
        _skip_nodes(false), _skip_arcs(false) {
476
      if (!(*_os)) throw IoError(fn, "Cannot write file");
476
      if (!(*_os)) throw IoError("Cannot write file", fn);
477 477
    }
478 478

	
479 479
    /// \brief Destructor
480 480
    ~DigraphWriter() {
481 481
      for (typename NodeMaps::iterator it = _node_maps.begin();
482 482
           it != _node_maps.end(); ++it) {
483 483
        delete it->second;
484 484
      }
485 485

	
486 486
      for (typename ArcMaps::iterator it = _arc_maps.begin();
487 487
           it != _arc_maps.end(); ++it) {
488 488
        delete it->second;
489 489
      }
490 490

	
491 491
      for (typename Attributes::iterator it = _attributes.begin();
492 492
           it != _attributes.end(); ++it) {
493 493
        delete it->second;
494 494
      }
495 495

	
496 496
      if (local_os) {
497 497
        delete _os;
498 498
      }
499 499
    }
500 500

	
501 501
  private:
502 502

	
503 503
    friend DigraphWriter<Digraph> digraphWriter<>(std::ostream& os,
504 504
                                                  const Digraph& digraph);
505 505
    friend DigraphWriter<Digraph> digraphWriter<>(const std::string& fn,
506 506
                                                  const Digraph& digraph);
507 507
    friend DigraphWriter<Digraph> digraphWriter<>(const char *fn,
508 508
                                                  const Digraph& digraph);
509 509

	
510 510
    DigraphWriter(DigraphWriter& other)
511 511
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
512 512
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
513 513

	
514 514
      other._os = 0;
515 515
      other.local_os = false;
516 516

	
517 517
      _node_index.swap(other._node_index);
518 518
      _arc_index.swap(other._arc_index);
519 519

	
520 520
      _node_maps.swap(other._node_maps);
521 521
      _arc_maps.swap(other._arc_maps);
522 522
      _attributes.swap(other._attributes);
523 523

	
524 524
      _nodes_caption = other._nodes_caption;
525 525
      _arcs_caption = other._arcs_caption;
526 526
      _attributes_caption = other._attributes_caption;
527 527
    }
528 528

	
529 529
    DigraphWriter& operator=(const DigraphWriter&);
530 530

	
531 531
  public:
532 532

	
533 533
    /// \name Writing rules
534 534
    /// @{
535 535

	
536 536
    /// \brief Node map writing rule
537 537
    ///
538 538
    /// Add a node map writing rule to the writer.
539 539
    template <typename Map>
540 540
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
541 541
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
542 542
      _writer_bits::MapStorageBase<Node>* storage =
543 543
        new _writer_bits::MapStorage<Node, Map>(map);
544 544
      _node_maps.push_back(std::make_pair(caption, storage));
545 545
      return *this;
546 546
    }
547 547

	
548 548
    /// \brief Node map writing rule
549 549
    ///
550 550
    /// Add a node map writing rule with specialized converter to the
551 551
    /// writer.
552 552
    template <typename Map, typename Converter>
553 553
    DigraphWriter& nodeMap(const std::string& caption, const Map& map,
554 554
                           const Converter& converter = Converter()) {
555 555
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
556 556
      _writer_bits::MapStorageBase<Node>* storage =
557 557
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
558 558
      _node_maps.push_back(std::make_pair(caption, storage));
559 559
      return *this;
560 560
    }
561 561

	
562 562
    /// \brief Arc map writing rule
563 563
    ///
564 564
    /// Add an arc map writing rule to the writer.
565 565
    template <typename Map>
566 566
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
567 567
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
568 568
      _writer_bits::MapStorageBase<Arc>* storage =
569 569
        new _writer_bits::MapStorage<Arc, Map>(map);
570 570
      _arc_maps.push_back(std::make_pair(caption, storage));
571 571
      return *this;
572 572
    }
573 573

	
574 574
    /// \brief Arc map writing rule
575 575
    ///
576 576
    /// Add an arc map writing rule with specialized converter to the
577 577
    /// writer.
578 578
    template <typename Map, typename Converter>
579 579
    DigraphWriter& arcMap(const std::string& caption, const Map& map,
580 580
                          const Converter& converter = Converter()) {
581 581
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
582 582
      _writer_bits::MapStorageBase<Arc>* storage =
583 583
        new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
584 584
      _arc_maps.push_back(std::make_pair(caption, storage));
585 585
      return *this;
586 586
    }
587 587

	
588 588
    /// \brief Attribute writing rule
589 589
    ///
590 590
    /// Add an attribute writing rule to the writer.
591 591
    template <typename Value>
592 592
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
593 593
      _writer_bits::ValueStorageBase* storage =
594 594
        new _writer_bits::ValueStorage<Value>(value);
595 595
      _attributes.push_back(std::make_pair(caption, storage));
596 596
      return *this;
597 597
    }
598 598

	
599 599
    /// \brief Attribute writing rule
600 600
    ///
601 601
    /// Add an attribute writing rule with specialized converter to the
602 602
    /// writer.
603 603
    template <typename Value, typename Converter>
604 604
    DigraphWriter& attribute(const std::string& caption, const Value& value,
605 605
                             const Converter& converter = Converter()) {
606 606
      _writer_bits::ValueStorageBase* storage =
607 607
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
608 608
      _attributes.push_back(std::make_pair(caption, storage));
609 609
      return *this;
610 610
    }
611 611

	
612 612
    /// \brief Node writing rule
613 613
    ///
614 614
    /// Add a node writing rule to the writer.
615 615
    DigraphWriter& node(const std::string& caption, const Node& node) {
616 616
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
617 617
      Converter converter(_node_index);
618 618
      _writer_bits::ValueStorageBase* storage =
619 619
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
620 620
      _attributes.push_back(std::make_pair(caption, storage));
621 621
      return *this;
622 622
    }
623 623

	
624 624
    /// \brief Arc writing rule
625 625
    ///
626 626
    /// Add an arc writing rule to writer.
627 627
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
628 628
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
629 629
      Converter converter(_arc_index);
630 630
      _writer_bits::ValueStorageBase* storage =
631 631
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
632 632
      _attributes.push_back(std::make_pair(caption, storage));
633 633
      return *this;
634 634
    }
635 635

	
636 636
    /// \name Section captions
637 637
    /// @{
638 638

	
639 639
    /// \brief Add an additional caption to the \c \@nodes section
640 640
    ///
641 641
    /// Add an additional caption to the \c \@nodes section.
642 642
    DigraphWriter& nodes(const std::string& caption) {
643 643
      _nodes_caption = caption;
644 644
      return *this;
645 645
    }
646 646

	
647 647
    /// \brief Add an additional caption to the \c \@arcs section
648 648
    ///
649 649
    /// Add an additional caption to the \c \@arcs section.
650 650
    DigraphWriter& arcs(const std::string& caption) {
651 651
      _arcs_caption = caption;
652 652
      return *this;
653 653
    }
654 654

	
655 655
    /// \brief Add an additional caption to the \c \@attributes section
656 656
    ///
657 657
    /// Add an additional caption to the \c \@attributes section.
658 658
    DigraphWriter& attributes(const std::string& caption) {
659 659
      _attributes_caption = caption;
660 660
      return *this;
661 661
    }
662 662

	
663 663
    /// \name Skipping section
664 664
    /// @{
665 665

	
666 666
    /// \brief Skip writing the node set
667 667
    ///
668 668
    /// The \c \@nodes section will not be written to the stream.
669 669
    DigraphWriter& skipNodes() {
670 670
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
671 671
      _skip_nodes = true;
672 672
      return *this;
673 673
    }
674 674

	
675 675
    /// \brief Skip writing arc set
676 676
    ///
677 677
    /// The \c \@arcs section will not be written to the stream.
678 678
    DigraphWriter& skipArcs() {
679 679
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
680 680
      _skip_arcs = true;
681 681
      return *this;
682 682
    }
683 683

	
684 684
    /// @}
685 685

	
686 686
  private:
687 687

	
688 688
    void writeNodes() {
689 689
      _writer_bits::MapStorageBase<Node>* label = 0;
690 690
      for (typename NodeMaps::iterator it = _node_maps.begin();
691 691
           it != _node_maps.end(); ++it) {
692 692
        if (it->first == "label") {
693 693
          label = it->second;
694 694
          break;
695 695
        }
696 696
      }
697 697

	
698 698
      *_os << "@nodes";
699 699
      if (!_nodes_caption.empty()) {
700 700
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
701 701
      }
702 702
      *_os << std::endl;
703 703

	
704 704
      if (label == 0) {
705 705
        *_os << "label" << '\t';
706 706
      }
707 707
      for (typename NodeMaps::iterator it = _node_maps.begin();
708 708
           it != _node_maps.end(); ++it) {
709 709
        _writer_bits::writeToken(*_os, it->first) << '\t';
710 710
      }
711 711
      *_os << std::endl;
712 712

	
713 713
      std::vector<Node> nodes;
714 714
      for (NodeIt n(_digraph); n != INVALID; ++n) {
715 715
        nodes.push_back(n);
716 716
      }
717 717

	
718 718
      if (label == 0) {
719 719
        IdMap<Digraph, Node> id_map(_digraph);
720 720
        _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
721 721
        std::sort(nodes.begin(), nodes.end(), id_less);
722 722
      } else {
723 723
        label->sort(nodes);
724 724
      }
725 725

	
726 726
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
727 727
        Node n = nodes[i];
728 728
        if (label == 0) {
729 729
          std::ostringstream os;
730 730
          os << _digraph.id(n);
731 731
          _writer_bits::writeToken(*_os, os.str());
732 732
          *_os << '\t';
733 733
          _node_index.insert(std::make_pair(n, os.str()));
734 734
        }
735 735
        for (typename NodeMaps::iterator it = _node_maps.begin();
736 736
             it != _node_maps.end(); ++it) {
737 737
          std::string value = it->second->get(n);
738 738
          _writer_bits::writeToken(*_os, value);
739 739
          if (it->first == "label") {
740 740
            _node_index.insert(std::make_pair(n, value));
741 741
          }
742 742
          *_os << '\t';
743 743
        }
744 744
        *_os << std::endl;
745 745
      }
746 746
    }
747 747

	
748 748
    void createNodeIndex() {
749 749
      _writer_bits::MapStorageBase<Node>* label = 0;
750 750
      for (typename NodeMaps::iterator it = _node_maps.begin();
751 751
           it != _node_maps.end(); ++it) {
752 752
        if (it->first == "label") {
753 753
          label = it->second;
754 754
          break;
755 755
        }
756 756
      }
757 757

	
758 758
      if (label == 0) {
759 759
        for (NodeIt n(_digraph); n != INVALID; ++n) {
760 760
          std::ostringstream os;
761 761
          os << _digraph.id(n);
762 762
          _node_index.insert(std::make_pair(n, os.str()));
763 763
        }
764 764
      } else {
765 765
        for (NodeIt n(_digraph); n != INVALID; ++n) {
766 766
          std::string value = label->get(n);
767 767
          _node_index.insert(std::make_pair(n, value));
768 768
        }
769 769
      }
770 770
    }
771 771

	
772 772
    void writeArcs() {
773 773
      _writer_bits::MapStorageBase<Arc>* label = 0;
774 774
      for (typename ArcMaps::iterator it = _arc_maps.begin();
775 775
           it != _arc_maps.end(); ++it) {
776 776
        if (it->first == "label") {
777 777
          label = it->second;
778 778
          break;
779 779
        }
780 780
      }
781 781

	
782 782
      *_os << "@arcs";
783 783
      if (!_arcs_caption.empty()) {
784 784
        _writer_bits::writeToken(*_os << ' ', _arcs_caption);
785 785
      }
786 786
      *_os << std::endl;
787 787

	
788 788
      *_os << '\t' << '\t';
789 789
      if (label == 0) {
790 790
        *_os << "label" << '\t';
791 791
      }
792 792
      for (typename ArcMaps::iterator it = _arc_maps.begin();
793 793
           it != _arc_maps.end(); ++it) {
794 794
        _writer_bits::writeToken(*_os, it->first) << '\t';
795 795
      }
796 796
      *_os << std::endl;
797 797

	
798 798
      std::vector<Arc> arcs;
799 799
      for (ArcIt n(_digraph); n != INVALID; ++n) {
800 800
        arcs.push_back(n);
801 801
      }
802 802

	
803 803
      if (label == 0) {
804 804
        IdMap<Digraph, Arc> id_map(_digraph);
805 805
        _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
806 806
        std::sort(arcs.begin(), arcs.end(), id_less);
807 807
      } else {
808 808
        label->sort(arcs);
809 809
      }
810 810

	
811 811
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
812 812
        Arc a = arcs[i];
813 813
        _writer_bits::writeToken(*_os, _node_index.
814 814
                                 find(_digraph.source(a))->second);
815 815
        *_os << '\t';
816 816
        _writer_bits::writeToken(*_os, _node_index.
817 817
                                 find(_digraph.target(a))->second);
818 818
        *_os << '\t';
819 819
        if (label == 0) {
820 820
          std::ostringstream os;
821 821
          os << _digraph.id(a);
822 822
          _writer_bits::writeToken(*_os, os.str());
823 823
          *_os << '\t';
824 824
          _arc_index.insert(std::make_pair(a, os.str()));
825 825
        }
826 826
        for (typename ArcMaps::iterator it = _arc_maps.begin();
827 827
             it != _arc_maps.end(); ++it) {
828 828
          std::string value = it->second->get(a);
829 829
          _writer_bits::writeToken(*_os, value);
830 830
          if (it->first == "label") {
831 831
            _arc_index.insert(std::make_pair(a, value));
832 832
          }
833 833
          *_os << '\t';
834 834
        }
835 835
        *_os << std::endl;
836 836
      }
837 837
    }
838 838

	
839 839
    void createArcIndex() {
840 840
      _writer_bits::MapStorageBase<Arc>* label = 0;
841 841
      for (typename ArcMaps::iterator it = _arc_maps.begin();
842 842
           it != _arc_maps.end(); ++it) {
843 843
        if (it->first == "label") {
844 844
          label = it->second;
845 845
          break;
846 846
        }
847 847
      }
848 848

	
849 849
      if (label == 0) {
850 850
        for (ArcIt a(_digraph); a != INVALID; ++a) {
851 851
          std::ostringstream os;
852 852
          os << _digraph.id(a);
853 853
          _arc_index.insert(std::make_pair(a, os.str()));
854 854
        }
855 855
      } else {
856 856
        for (ArcIt a(_digraph); a != INVALID; ++a) {
857 857
          std::string value = label->get(a);
858 858
          _arc_index.insert(std::make_pair(a, value));
859 859
        }
860 860
      }
861 861
    }
862 862

	
863 863
    void writeAttributes() {
864 864
      if (_attributes.empty()) return;
865 865
      *_os << "@attributes";
866 866
      if (!_attributes_caption.empty()) {
867 867
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
868 868
      }
869 869
      *_os << std::endl;
870 870
      for (typename Attributes::iterator it = _attributes.begin();
871 871
           it != _attributes.end(); ++it) {
872 872
        _writer_bits::writeToken(*_os, it->first) << ' ';
873 873
        _writer_bits::writeToken(*_os, it->second->get());
874 874
        *_os << std::endl;
875 875
      }
876 876
    }
877 877

	
878 878
  public:
879 879

	
880 880
    /// \name Execution of the writer
881 881
    /// @{
882 882

	
883 883
    /// \brief Start the batch processing
884 884
    ///
885 885
    /// This function starts the batch processing.
886 886
    void run() {
887 887
      if (!_skip_nodes) {
888 888
        writeNodes();
889 889
      } else {
890 890
        createNodeIndex();
891 891
      }
892 892
      if (!_skip_arcs) {
893 893
        writeArcs();
894 894
      } else {
895 895
        createArcIndex();
896 896
      }
897 897
      writeAttributes();
898 898
    }
899 899

	
900 900
    /// \brief Give back the stream of the writer
901 901
    ///
902 902
    /// Give back the stream of the writer.
903 903
    std::ostream& ostream() {
904 904
      return *_os;
905 905
    }
906 906

	
907 907
    /// @}
908 908
  };
909 909

	
910 910
  /// \brief Return a \ref DigraphWriter class
911 911
  ///
912 912
  /// This function just returns a \ref DigraphWriter class.
913 913
  /// \relates DigraphWriter
914 914
  template <typename Digraph>
915 915
  DigraphWriter<Digraph> digraphWriter(std::ostream& os,
916 916
                                       const Digraph& digraph) {
917 917
    DigraphWriter<Digraph> tmp(os, digraph);
918 918
    return tmp;
919 919
  }
920 920

	
921 921
  /// \brief Return a \ref DigraphWriter class
922 922
  ///
923 923
  /// This function just returns a \ref DigraphWriter class.
924 924
  /// \relates DigraphWriter
925 925
  template <typename Digraph>
926 926
  DigraphWriter<Digraph> digraphWriter(const std::string& fn,
927 927
                                       const Digraph& digraph) {
928 928
    DigraphWriter<Digraph> tmp(fn, digraph);
929 929
    return tmp;
930 930
  }
931 931

	
932 932
  /// \brief Return a \ref DigraphWriter class
933 933
  ///
934 934
  /// This function just returns a \ref DigraphWriter class.
935 935
  /// \relates DigraphWriter
936 936
  template <typename Digraph>
937 937
  DigraphWriter<Digraph> digraphWriter(const char* fn,
938 938
                                       const Digraph& digraph) {
939 939
    DigraphWriter<Digraph> tmp(fn, digraph);
940 940
    return tmp;
941 941
  }
942 942

	
943 943
  template <typename Graph>
944 944
  class GraphWriter;
945 945

	
946 946
  template <typename Graph>
947 947
  GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph);
948 948

	
949 949
  template <typename Graph>
950 950
  GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph);
951 951

	
952 952
  template <typename Graph>
953 953
  GraphWriter<Graph> graphWriter(const char *fn, const Graph& graph);
954 954

	
955 955
  /// \ingroup lemon_io
956 956
  ///
957 957
  /// \brief \ref lgf-format "LGF" writer for directed graphs
958 958
  ///
959 959
  /// This utility writes an \ref lgf-format "LGF" file.
960 960
  ///
961 961
  /// It can be used almost the same way as \c DigraphWriter.
962 962
  /// The only difference is that this class can handle edges and
963 963
  /// edge maps as well as arcs and arc maps.
964 964
  ///
965 965
  /// The arc maps are written into the file as two columns, the
966 966
  /// caption of the columns are the name of the map prefixed with \c
967 967
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
968 968
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
969 969
  /// of the arc) and the label of corresponding edge.
970 970
  template <typename _Graph>
971 971
  class GraphWriter {
972 972
  public:
973 973

	
974 974
    typedef _Graph Graph;
975 975
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
976 976

	
977 977
  private:
978 978

	
979 979

	
980 980
    std::ostream* _os;
981 981
    bool local_os;
982 982

	
983 983
    const Graph& _graph;
984 984

	
985 985
    std::string _nodes_caption;
986 986
    std::string _edges_caption;
987 987
    std::string _attributes_caption;
988 988

	
989 989
    typedef std::map<Node, std::string> NodeIndex;
990 990
    NodeIndex _node_index;
991 991
    typedef std::map<Edge, std::string> EdgeIndex;
992 992
    EdgeIndex _edge_index;
993 993

	
994 994
    typedef std::vector<std::pair<std::string,
995 995
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
996 996
    NodeMaps _node_maps;
997 997

	
998 998
    typedef std::vector<std::pair<std::string,
999 999
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1000 1000
    EdgeMaps _edge_maps;
1001 1001

	
1002 1002
    typedef std::vector<std::pair<std::string,
1003 1003
      _writer_bits::ValueStorageBase*> > Attributes;
1004 1004
    Attributes _attributes;
1005 1005

	
1006 1006
    bool _skip_nodes;
1007 1007
    bool _skip_edges;
1008 1008

	
1009 1009
  public:
1010 1010

	
1011 1011
    /// \brief Constructor
1012 1012
    ///
1013 1013
    /// Construct a directed graph writer, which writes to the given
1014 1014
    /// output stream.
1015 1015
    GraphWriter(std::ostream& is, const Graph& graph)
1016 1016
      : _os(&is), local_os(false), _graph(graph),
1017 1017
        _skip_nodes(false), _skip_edges(false) {}
1018 1018

	
1019 1019
    /// \brief Constructor
1020 1020
    ///
1021 1021
    /// Construct a directed graph writer, which writes to the given
1022 1022
    /// output file.
1023 1023
    GraphWriter(const std::string& fn, const Graph& graph)
1024 1024
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1025 1025
        _skip_nodes(false), _skip_edges(false) {
1026
      if (!(*_os)) throw IoError(fn, "Cannot write file");
1026
      if (!(*_os)) throw IoError("Cannot write file", fn);
1027 1027
    }
1028 1028

	
1029 1029
    /// \brief Constructor
1030 1030
    ///
1031 1031
    /// Construct a directed graph writer, which writes to the given
1032 1032
    /// output file.
1033 1033
    GraphWriter(const char* fn, const Graph& graph)
1034 1034
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1035 1035
        _skip_nodes(false), _skip_edges(false) {
1036
      if (!(*_os)) throw IoError(fn, "Cannot write file");
1036
      if (!(*_os)) throw IoError("Cannot write file", fn);
1037 1037
    }
1038 1038

	
1039 1039
    /// \brief Destructor
1040 1040
    ~GraphWriter() {
1041 1041
      for (typename NodeMaps::iterator it = _node_maps.begin();
1042 1042
           it != _node_maps.end(); ++it) {
1043 1043
        delete it->second;
1044 1044
      }
1045 1045

	
1046 1046
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1047 1047
           it != _edge_maps.end(); ++it) {
1048 1048
        delete it->second;
1049 1049
      }
1050 1050

	
1051 1051
      for (typename Attributes::iterator it = _attributes.begin();
1052 1052
           it != _attributes.end(); ++it) {
1053 1053
        delete it->second;
1054 1054
      }
1055 1055

	
1056 1056
      if (local_os) {
1057 1057
        delete _os;
1058 1058
      }
1059 1059
    }
1060 1060

	
1061 1061
  private:
1062 1062

	
1063 1063
    friend GraphWriter<Graph> graphWriter<>(std::ostream& os,
1064 1064
                                            const Graph& graph);
1065 1065
    friend GraphWriter<Graph> graphWriter<>(const std::string& fn,
1066 1066
                                            const Graph& graph);
1067 1067
    friend GraphWriter<Graph> graphWriter<>(const char *fn,
1068 1068
                                            const Graph& graph);
1069 1069

	
1070 1070
    GraphWriter(GraphWriter& other)
1071 1071
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
1072 1072
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1073 1073

	
1074 1074
      other._os = 0;
1075 1075
      other.local_os = false;
1076 1076

	
1077 1077
      _node_index.swap(other._node_index);
1078 1078
      _edge_index.swap(other._edge_index);
1079 1079

	
1080 1080
      _node_maps.swap(other._node_maps);
1081 1081
      _edge_maps.swap(other._edge_maps);
1082 1082
      _attributes.swap(other._attributes);
1083 1083

	
1084 1084
      _nodes_caption = other._nodes_caption;
1085 1085
      _edges_caption = other._edges_caption;
1086 1086
      _attributes_caption = other._attributes_caption;
1087 1087
    }
1088 1088

	
1089 1089
    GraphWriter& operator=(const GraphWriter&);
1090 1090

	
1091 1091
  public:
1092 1092

	
1093 1093
    /// \name Writing rules
1094 1094
    /// @{
1095 1095

	
1096 1096
    /// \brief Node map writing rule
1097 1097
    ///
1098 1098
    /// Add a node map writing rule to the writer.
1099 1099
    template <typename Map>
1100 1100
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1101 1101
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1102 1102
      _writer_bits::MapStorageBase<Node>* storage =
1103 1103
        new _writer_bits::MapStorage<Node, Map>(map);
1104 1104
      _node_maps.push_back(std::make_pair(caption, storage));
1105 1105
      return *this;
1106 1106
    }
1107 1107

	
1108 1108
    /// \brief Node map writing rule
1109 1109
    ///
1110 1110
    /// Add a node map writing rule with specialized converter to the
1111 1111
    /// writer.
1112 1112
    template <typename Map, typename Converter>
1113 1113
    GraphWriter& nodeMap(const std::string& caption, const Map& map,
1114 1114
                           const Converter& converter = Converter()) {
1115 1115
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1116 1116
      _writer_bits::MapStorageBase<Node>* storage =
1117 1117
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1118 1118
      _node_maps.push_back(std::make_pair(caption, storage));
1119 1119
      return *this;
1120 1120
    }
1121 1121

	
1122 1122
    /// \brief Edge map writing rule
1123 1123
    ///
1124 1124
    /// Add an edge map writing rule to the writer.
1125 1125
    template <typename Map>
1126 1126
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1127 1127
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1128 1128
      _writer_bits::MapStorageBase<Edge>* storage =
1129 1129
        new _writer_bits::MapStorage<Edge, Map>(map);
1130 1130
      _edge_maps.push_back(std::make_pair(caption, storage));
1131 1131
      return *this;
1132 1132
    }
1133 1133

	
1134 1134
    /// \brief Edge map writing rule
1135 1135
    ///
1136 1136
    /// Add an edge map writing rule with specialized converter to the
1137 1137
    /// writer.
1138 1138
    template <typename Map, typename Converter>
1139 1139
    GraphWriter& edgeMap(const std::string& caption, const Map& map,
1140 1140
                          const Converter& converter = Converter()) {
1141 1141
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1142 1142
      _writer_bits::MapStorageBase<Edge>* storage =
1143 1143
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1144 1144
      _edge_maps.push_back(std::make_pair(caption, storage));
1145 1145
      return *this;
1146 1146
    }
1147 1147

	
1148 1148
    /// \brief Arc map writing rule
1149 1149
    ///
1150 1150
    /// Add an arc map writing rule to the writer.
1151 1151
    template <typename Map>
1152 1152
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
1153 1153
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1154 1154
      _writer_bits::MapStorageBase<Edge>* forward_storage =
1155 1155
        new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1156 1156
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1157 1157
      _writer_bits::MapStorageBase<Edge>* backward_storage =
1158 1158
        new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1159 1159
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1160 1160
      return *this;
1161 1161
    }
1162 1162

	
1163 1163
    /// \brief Arc map writing rule
1164 1164
    ///
1165 1165
    /// Add an arc map writing rule with specialized converter to the
1166 1166
    /// writer.
1167 1167
    template <typename Map, typename Converter>
1168 1168
    GraphWriter& arcMap(const std::string& caption, const Map& map,
1169 1169
                          const Converter& converter = Converter()) {
1170 1170
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1171 1171
      _writer_bits::MapStorageBase<Edge>* forward_storage =
1172 1172
        new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1173 1173
        (_graph, map, converter);
1174 1174
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1175 1175
      _writer_bits::MapStorageBase<Edge>* backward_storage =
1176 1176
        new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1177 1177
        (_graph, map, converter);
1178 1178
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1179 1179
      return *this;
1180 1180
    }
1181 1181

	
1182 1182
    /// \brief Attribute writing rule
1183 1183
    ///
1184 1184
    /// Add an attribute writing rule to the writer.
1185 1185
    template <typename Value>
1186 1186
    GraphWriter& attribute(const std::string& caption, const Value& value) {
1187 1187
      _writer_bits::ValueStorageBase* storage =
1188 1188
        new _writer_bits::ValueStorage<Value>(value);
1189 1189
      _attributes.push_back(std::make_pair(caption, storage));
1190 1190
      return *this;
1191 1191
    }
1192 1192

	
1193 1193
    /// \brief Attribute writing rule
1194 1194
    ///
1195 1195
    /// Add an attribute writing rule with specialized converter to the
1196 1196
    /// writer.
1197 1197
    template <typename Value, typename Converter>
1198 1198
    GraphWriter& attribute(const std::string& caption, const Value& value,
1199 1199
                             const Converter& converter = Converter()) {
1200 1200
      _writer_bits::ValueStorageBase* storage =
1201 1201
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1202 1202
      _attributes.push_back(std::make_pair(caption, storage));
1203 1203
      return *this;
1204 1204
    }
1205 1205

	
1206 1206
    /// \brief Node writing rule
1207 1207
    ///
1208 1208
    /// Add a node writing rule to the writer.
1209 1209
    GraphWriter& node(const std::string& caption, const Node& node) {
1210 1210
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
1211 1211
      Converter converter(_node_index);
1212 1212
      _writer_bits::ValueStorageBase* storage =
1213 1213
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1214 1214
      _attributes.push_back(std::make_pair(caption, storage));
1215 1215
      return *this;
1216 1216
    }
1217 1217

	
1218 1218
    /// \brief Edge writing rule
1219 1219
    ///
1220 1220
    /// Add an edge writing rule to writer.
1221 1221
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
1222 1222
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1223 1223
      Converter converter(_edge_index);
1224 1224
      _writer_bits::ValueStorageBase* storage =
1225 1225
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1226 1226
      _attributes.push_back(std::make_pair(caption, storage));
1227 1227
      return *this;
1228 1228
    }
1229 1229

	
1230 1230
    /// \brief Arc writing rule
1231 1231
    ///
1232 1232
    /// Add an arc writing rule to writer.
1233 1233
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
1234 1234
      typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1235 1235
      Converter converter(_graph, _edge_index);
1236 1236
      _writer_bits::ValueStorageBase* storage =
1237 1237
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1238 1238
      _attributes.push_back(std::make_pair(caption, storage));
1239 1239
      return *this;
1240 1240
    }
1241 1241

	
1242 1242
    /// \name Section captions
1243 1243
    /// @{
1244 1244

	
1245 1245
    /// \brief Add an additional caption to the \c \@nodes section
1246 1246
    ///
1247 1247
    /// Add an additional caption to the \c \@nodes section.
1248 1248
    GraphWriter& nodes(const std::string& caption) {
1249 1249
      _nodes_caption = caption;
1250 1250
      return *this;
1251 1251
    }
1252 1252

	
1253 1253
    /// \brief Add an additional caption to the \c \@arcs section
1254 1254
    ///
1255 1255
    /// Add an additional caption to the \c \@arcs section.
1256 1256
    GraphWriter& edges(const std::string& caption) {
1257 1257
      _edges_caption = caption;
1258 1258
      return *this;
1259 1259
    }
1260 1260

	
1261 1261
    /// \brief Add an additional caption to the \c \@attributes section
1262 1262
    ///
1263 1263
    /// Add an additional caption to the \c \@attributes section.
1264 1264
    GraphWriter& attributes(const std::string& caption) {
1265 1265
      _attributes_caption = caption;
1266 1266
      return *this;
1267 1267
    }
1268 1268

	
1269 1269
    /// \name Skipping section
1270 1270
    /// @{
1271 1271

	
1272 1272
    /// \brief Skip writing the node set
1273 1273
    ///
1274 1274
    /// The \c \@nodes section will not be written to the stream.
1275 1275
    GraphWriter& skipNodes() {
1276 1276
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1277 1277
      _skip_nodes = true;
1278 1278
      return *this;
1279 1279
    }
1280 1280

	
1281 1281
    /// \brief Skip writing edge set
1282 1282
    ///
1283 1283
    /// The \c \@edges section will not be written to the stream.
1284 1284
    GraphWriter& skipEdges() {
1285 1285
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1286 1286
      _skip_edges = true;
1287 1287
      return *this;
1288 1288
    }
1289 1289

	
1290 1290
    /// @}
1291 1291

	
1292 1292
  private:
1293 1293

	
1294 1294
    void writeNodes() {
1295 1295
      _writer_bits::MapStorageBase<Node>* label = 0;
1296 1296
      for (typename NodeMaps::iterator it = _node_maps.begin();
1297 1297
           it != _node_maps.end(); ++it) {
1298 1298
        if (it->first == "label") {
1299 1299
          label = it->second;
1300 1300
          break;
1301 1301
        }
1302 1302
      }
1303 1303

	
1304 1304
      *_os << "@nodes";
1305 1305
      if (!_nodes_caption.empty()) {
1306 1306
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1307 1307
      }
1308 1308
      *_os << std::endl;
1309 1309

	
1310 1310
      if (label == 0) {
1311 1311
        *_os << "label" << '\t';
1312 1312
      }
1313 1313
      for (typename NodeMaps::iterator it = _node_maps.begin();
1314 1314
           it != _node_maps.end(); ++it) {
1315 1315
        _writer_bits::writeToken(*_os, it->first) << '\t';
1316 1316
      }
1317 1317
      *_os << std::endl;
1318 1318

	
1319 1319
      std::vector<Node> nodes;
1320 1320
      for (NodeIt n(_graph); n != INVALID; ++n) {
1321 1321
        nodes.push_back(n);
1322 1322
      }
1323 1323

	
1324 1324
      if (label == 0) {
1325 1325
        IdMap<Graph, Node> id_map(_graph);
1326 1326
        _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1327 1327
        std::sort(nodes.begin(), nodes.end(), id_less);
1328 1328
      } else {
1329 1329
        label->sort(nodes);
1330 1330
      }
1331 1331

	
1332 1332
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1333 1333
        Node n = nodes[i];
1334 1334
        if (label == 0) {
1335 1335
          std::ostringstream os;
1336 1336
          os << _graph.id(n);
1337 1337
          _writer_bits::writeToken(*_os, os.str());
1338 1338
          *_os << '\t';
1339 1339
          _node_index.insert(std::make_pair(n, os.str()));
1340 1340
        }
1341 1341
        for (typename NodeMaps::iterator it = _node_maps.begin();
1342 1342
             it != _node_maps.end(); ++it) {
1343 1343
          std::string value = it->second->get(n);
1344 1344
          _writer_bits::writeToken(*_os, value);
1345 1345
          if (it->first == "label") {
1346 1346
            _node_index.insert(std::make_pair(n, value));
1347 1347
          }
1348 1348
          *_os << '\t';
1349 1349
        }
1350 1350
        *_os << std::endl;
1351 1351
      }
1352 1352
    }
1353 1353

	
1354 1354
    void createNodeIndex() {
1355 1355
      _writer_bits::MapStorageBase<Node>* label = 0;
1356 1356
      for (typename NodeMaps::iterator it = _node_maps.begin();
1357 1357
           it != _node_maps.end(); ++it) {
1358 1358
        if (it->first == "label") {
1359 1359
          label = it->second;
1360 1360
          break;
1361 1361
        }
1362 1362
      }
1363 1363

	
1364 1364
      if (label == 0) {
1365 1365
        for (NodeIt n(_graph); n != INVALID; ++n) {
1366 1366
          std::ostringstream os;
1367 1367
          os << _graph.id(n);
1368 1368
          _node_index.insert(std::make_pair(n, os.str()));
1369 1369
        }
1370 1370
      } else {
1371 1371
        for (NodeIt n(_graph); n != INVALID; ++n) {
1372 1372
          std::string value = label->get(n);
1373 1373
          _node_index.insert(std::make_pair(n, value));
1374 1374
        }
1375 1375
      }
1376 1376
    }
1377 1377

	
1378 1378
    void writeEdges() {
1379 1379
      _writer_bits::MapStorageBase<Edge>* label = 0;
1380 1380
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1381 1381
           it != _edge_maps.end(); ++it) {
1382 1382
        if (it->first == "label") {
1383 1383
          label = it->second;
1384 1384
          break;
1385 1385
        }
1386 1386
      }
1387 1387

	
1388 1388
      *_os << "@edges";
1389 1389
      if (!_edges_caption.empty()) {
1390 1390
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
1391 1391
      }
1392 1392
      *_os << std::endl;
1393 1393

	
1394 1394
      *_os << '\t' << '\t';
1395 1395
      if (label == 0) {
1396 1396
        *_os << "label" << '\t';
1397 1397
      }
1398 1398
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1399 1399
           it != _edge_maps.end(); ++it) {
1400 1400
        _writer_bits::writeToken(*_os, it->first) << '\t';
1401 1401
      }
1402 1402
      *_os << std::endl;
1403 1403

	
1404 1404
      std::vector<Edge> edges;
1405 1405
      for (EdgeIt n(_graph); n != INVALID; ++n) {
1406 1406
        edges.push_back(n);
1407 1407
      }
1408 1408

	
1409 1409
      if (label == 0) {
1410 1410
        IdMap<Graph, Edge> id_map(_graph);
1411 1411
        _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1412 1412
        std::sort(edges.begin(), edges.end(), id_less);
1413 1413
      } else {
1414 1414
        label->sort(edges);
1415 1415
      }
1416 1416

	
1417 1417
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1418 1418
        Edge e = edges[i];
1419 1419
        _writer_bits::writeToken(*_os, _node_index.
1420 1420
                                 find(_graph.u(e))->second);
1421 1421
        *_os << '\t';
1422 1422
        _writer_bits::writeToken(*_os, _node_index.
1423 1423
                                 find(_graph.v(e))->second);
1424 1424
        *_os << '\t';
1425 1425
        if (label == 0) {
1426 1426
          std::ostringstream os;
1427 1427
          os << _graph.id(e);
1428 1428
          _writer_bits::writeToken(*_os, os.str());
1429 1429
          *_os << '\t';
1430 1430
          _edge_index.insert(std::make_pair(e, os.str()));
1431 1431
        }
1432 1432
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
1433 1433
             it != _edge_maps.end(); ++it) {
1434 1434
          std::string value = it->second->get(e);
1435 1435
          _writer_bits::writeToken(*_os, value);
1436 1436
          if (it->first == "label") {
1437 1437
            _edge_index.insert(std::make_pair(e, value));
1438 1438
          }
1439 1439
          *_os << '\t';
1440 1440
        }
1441 1441
        *_os << std::endl;
1442 1442
      }
1443 1443
    }
1444 1444

	
1445 1445
    void createEdgeIndex() {
1446 1446
      _writer_bits::MapStorageBase<Edge>* label = 0;
1447 1447
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1448 1448
           it != _edge_maps.end(); ++it) {
1449 1449
        if (it->first == "label") {
1450 1450
          label = it->second;
1451 1451
          break;
1452 1452
        }
1453 1453
      }
1454 1454

	
1455 1455
      if (label == 0) {
1456 1456
        for (EdgeIt e(_graph); e != INVALID; ++e) {
1457 1457
          std::ostringstream os;
1458 1458
          os << _graph.id(e);
1459 1459
          _edge_index.insert(std::make_pair(e, os.str()));
1460 1460
        }
1461 1461
      } else {
1462 1462
        for (EdgeIt e(_graph); e != INVALID; ++e) {
1463 1463
          std::string value = label->get(e);
1464 1464
          _edge_index.insert(std::make_pair(e, value));
1465 1465
        }
1466 1466
      }
1467 1467
    }
1468 1468

	
1469 1469
    void writeAttributes() {
1470 1470
      if (_attributes.empty()) return;
1471 1471
      *_os << "@attributes";
1472 1472
      if (!_attributes_caption.empty()) {
1473 1473
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1474 1474
      }
1475 1475
      *_os << std::endl;
1476 1476
      for (typename Attributes::iterator it = _attributes.begin();
1477 1477
           it != _attributes.end(); ++it) {
1478 1478
        _writer_bits::writeToken(*_os, it->first) << ' ';
1479 1479
        _writer_bits::writeToken(*_os, it->second->get());
1480 1480
        *_os << std::endl;
1481 1481
      }
1482 1482
    }
1483 1483

	
1484 1484
  public:
1485 1485

	
1486 1486
    /// \name Execution of the writer
1487 1487
    /// @{
1488 1488

	
1489 1489
    /// \brief Start the batch processing
1490 1490
    ///
1491 1491
    /// This function starts the batch processing.
1492 1492
    void run() {
1493 1493
      if (!_skip_nodes) {
1494 1494
        writeNodes();
1495 1495
      } else {
1496 1496
        createNodeIndex();
1497 1497
      }
1498 1498
      if (!_skip_edges) {
1499 1499
        writeEdges();
1500 1500
      } else {
1501 1501
        createEdgeIndex();
1502 1502
      }
1503 1503
      writeAttributes();
1504 1504
    }
1505 1505

	
1506 1506
    /// \brief Give back the stream of the writer
1507 1507
    ///
1508 1508
    /// Give back the stream of the writer
1509 1509
    std::ostream& ostream() {
1510 1510
      return *_os;
1511 1511
    }
1512 1512

	
1513 1513
    /// @}
1514 1514
  };
1515 1515

	
1516 1516
  /// \brief Return a \ref GraphWriter class
1517 1517
  ///
1518 1518
  /// This function just returns a \ref GraphWriter class.
1519 1519
  /// \relates GraphWriter
1520 1520
  template <typename Graph>
1521 1521
  GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph) {
1522 1522
    GraphWriter<Graph> tmp(os, graph);
1523 1523
    return tmp;
1524 1524
  }
1525 1525

	
1526 1526
  /// \brief Return a \ref GraphWriter class
1527 1527
  ///
1528 1528
  /// This function just returns a \ref GraphWriter class.
1529 1529
  /// \relates GraphWriter
1530 1530
  template <typename Graph>
1531 1531
  GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph) {
1532 1532
    GraphWriter<Graph> tmp(fn, graph);
1533 1533
    return tmp;
1534 1534
  }
1535 1535

	
1536 1536
  /// \brief Return a \ref GraphWriter class
1537 1537
  ///
1538 1538
  /// This function just returns a \ref GraphWriter class.
1539 1539
  /// \relates GraphWriter
1540 1540
  template <typename Graph>
1541 1541
  GraphWriter<Graph> graphWriter(const char* fn, const Graph& graph) {
1542 1542
    GraphWriter<Graph> tmp(fn, graph);
1543 1543
    return tmp;
1544 1544
  }
1545 1545

	
1546 1546
  class SectionWriter;
1547 1547

	
1548 1548
  SectionWriter sectionWriter(std::istream& is);
1549 1549
  SectionWriter sectionWriter(const std::string& fn);
1550 1550
  SectionWriter sectionWriter(const char* fn);
1551 1551

	
1552 1552
  /// \ingroup lemon_io
1553 1553
  ///
1554 1554
  /// \brief Section writer class
1555 1555
  ///
1556 1556
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
1557 1557
  /// which contain any data in arbitrary format. Such sections can be
1558 1558
  /// written with this class. A writing rule can be added to the
1559 1559
  /// class with two different functions. With the \c sectionLines()
1560 1560
  /// function a generator can write the section line-by-line, while
1561 1561
  /// with the \c sectionStream() member the section can be written to
1562 1562
  /// an output stream.
1563 1563
  class SectionWriter {
1564 1564
  private:
1565 1565

	
1566 1566
    std::ostream* _os;
1567 1567
    bool local_os;
1568 1568

	
1569 1569
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1570 1570
    Sections;
1571 1571

	
1572 1572
    Sections _sections;
1573 1573

	
1574 1574
  public:
1575 1575

	
1576 1576
    /// \brief Constructor
1577 1577
    ///
1578 1578
    /// Construct a section writer, which writes to the given output
1579 1579
    /// stream.
1580 1580
    SectionWriter(std::ostream& os)
1581 1581
      : _os(&os), local_os(false) {}
1582 1582

	
1583 1583
    /// \brief Constructor
1584 1584
    ///
1585 1585
    /// Construct a section writer, which writes into the given file.
1586 1586
    SectionWriter(const std::string& fn)
1587 1587
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
1588
      if (!(*_os)) throw IoError(fn, "Cannot write file");
1588
      if (!(*_os)) throw IoError("Cannot write file", fn);
1589 1589
    }
1590 1590

	
1591 1591
    /// \brief Constructor
1592 1592
    ///
1593 1593
    /// Construct a section writer, which writes into the given file.
1594 1594
    SectionWriter(const char* fn)
1595 1595
      : _os(new std::ofstream(fn)), local_os(true) {
1596
      if (!(*_os)) throw IoError(fn, "Cannot write file");
1596
      if (!(*_os)) throw IoError("Cannot write file", fn);
1597 1597
    }
1598 1598

	
1599 1599
    /// \brief Destructor
1600 1600
    ~SectionWriter() {
1601 1601
      for (Sections::iterator it = _sections.begin();
1602 1602
           it != _sections.end(); ++it) {
1603 1603
        delete it->second;
1604 1604
      }
1605 1605

	
1606 1606
      if (local_os) {
1607 1607
        delete _os;
1608 1608
      }
1609 1609

	
1610 1610
    }
1611 1611

	
1612 1612
  private:
1613 1613

	
1614 1614
    friend SectionWriter sectionWriter(std::ostream& os);
1615 1615
    friend SectionWriter sectionWriter(const std::string& fn);
1616 1616
    friend SectionWriter sectionWriter(const char* fn);
1617 1617

	
1618 1618
    SectionWriter(SectionWriter& other)
1619 1619
      : _os(other._os), local_os(other.local_os) {
1620 1620

	
1621 1621
      other._os = 0;
1622 1622
      other.local_os = false;
1623 1623

	
1624 1624
      _sections.swap(other._sections);
1625 1625
    }
1626 1626

	
1627 1627
    SectionWriter& operator=(const SectionWriter&);
1628 1628

	
1629 1629
  public:
1630 1630

	
1631 1631
    /// \name Section writers
1632 1632
    /// @{
1633 1633

	
1634 1634
    /// \brief Add a section writer with line oriented writing
1635 1635
    ///
1636 1636
    /// The first parameter is the type descriptor of the section, the
1637 1637
    /// second is a generator with std::string values. At the writing
1638 1638
    /// process, the returned \c std::string will be written into the
1639 1639
    /// output file until it is an empty string.
1640 1640
    ///
1641 1641
    /// For example, an integer vector is written into a section.
1642 1642
    ///\code
1643 1643
    ///  @numbers
1644 1644
    ///  12 45 23 78
1645 1645
    ///  4 28 38 28
1646 1646
    ///  23 6 16
1647 1647
    ///\endcode
1648 1648
    ///
1649 1649
    /// The generator is implemented as a struct.
1650 1650
    ///\code
1651 1651
    ///  struct NumberSection {
1652 1652
    ///    std::vector<int>::const_iterator _it, _end;
1653 1653
    ///    NumberSection(const std::vector<int>& data)
1654 1654
    ///      : _it(data.begin()), _end(data.end()) {}
1655 1655
    ///    std::string operator()() {
1656 1656
    ///      int rem_in_line = 4;
1657 1657
    ///      std::ostringstream ls;
1658 1658
    ///      while (rem_in_line > 0 && _it != _end) {
1659 1659
    ///        ls << *(_it++) << ' ';
1660 1660
    ///        --rem_in_line;
1661 1661
    ///      }
1662 1662
    ///      return ls.str();
1663 1663
    ///    }
1664 1664
    ///  };
1665 1665
    ///
1666 1666
    ///  // ...
1667 1667
    ///
1668 1668
    ///  writer.sectionLines("numbers", NumberSection(vec));
1669 1669
    ///\endcode
1670 1670
    template <typename Functor>
1671 1671
    SectionWriter& sectionLines(const std::string& type, Functor functor) {
1672 1672
      LEMON_ASSERT(!type.empty(), "Type is empty.");
1673 1673
      _sections.push_back(std::make_pair(type,
1674 1674
        new _writer_bits::LineSection<Functor>(functor)));
1675 1675
      return *this;
1676 1676
    }
1677 1677

	
1678 1678

	
1679 1679
    /// \brief Add a section writer with stream oriented writing
1680 1680
    ///
1681 1681
    /// The first parameter is the type of the section, the second is
1682 1682
    /// a functor, which takes a \c std::ostream& parameter. The
1683 1683
    /// functor writes the section to the output stream.
1684 1684
    /// \warning The last line must be closed with end-line character.
1685 1685
    template <typename Functor>
1686 1686
    SectionWriter& sectionStream(const std::string& type, Functor functor) {
1687 1687
      LEMON_ASSERT(!type.empty(), "Type is empty.");
1688 1688
      _sections.push_back(std::make_pair(type,
1689 1689
         new _writer_bits::StreamSection<Functor>(functor)));
1690 1690
      return *this;
1691 1691
    }
1692 1692

	
1693 1693
    /// @}
1694 1694

	
1695 1695
  public:
1696 1696

	
1697 1697

	
1698 1698
    /// \name Execution of the writer
1699 1699
    /// @{
1700 1700

	
1701 1701
    /// \brief Start the batch processing
1702 1702
    ///
1703 1703
    /// This function starts the batch processing.
1704 1704
    void run() {
1705 1705

	
1706 1706
      LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1707 1707

	
1708 1708
      for (Sections::iterator it = _sections.begin();
1709 1709
           it != _sections.end(); ++it) {
1710 1710
        (*_os) << '@' << it->first << std::endl;
1711 1711
        it->second->process(*_os);
1712 1712
      }
1713 1713
    }
1714 1714

	
1715 1715
    /// \brief Give back the stream of the writer
1716 1716
    ///
1717 1717
    /// Returns the stream of the writer
1718 1718
    std::ostream& ostream() {
1719 1719
      return *_os;
1720 1720
    }
1721 1721

	
1722 1722
    /// @}
1723 1723

	
1724 1724
  };
1725 1725

	
1726 1726
  /// \brief Return a \ref SectionWriter class
1727 1727
  ///
1728 1728
  /// This function just returns a \ref SectionWriter class.
1729 1729
  /// \relates SectionWriter
1730 1730
  inline SectionWriter sectionWriter(std::ostream& os) {
1731 1731
    SectionWriter tmp(os);
1732 1732
    return tmp;
1733 1733
  }
1734 1734

	
1735 1735
  /// \brief Return a \ref SectionWriter class
1736 1736
  ///
1737 1737
  /// This function just returns a \ref SectionWriter class.
1738 1738
  /// \relates SectionWriter
1739 1739
  inline SectionWriter sectionWriter(const std::string& fn) {
1740 1740
    SectionWriter tmp(fn);
1741 1741
    return tmp;
1742 1742
  }
1743 1743

	
1744 1744
  /// \brief Return a \ref SectionWriter class
1745 1745
  ///
1746 1746
  /// This function just returns a \ref SectionWriter class.
1747 1747
  /// \relates SectionWriter
1748 1748
  inline SectionWriter sectionWriter(const char* fn) {
1749 1749
    SectionWriter tmp(fn);
1750 1750
    return tmp;
1751 1751
  }
1752 1752
}
1753 1753

	
1754 1754
#endif
0 comments (0 inline)