gravatar
deba@inf.elte.hu
deba@inf.elte.hu
More docs for undirected LGF IO
0 3 0
default
3 files changed with 22 insertions and 2 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1 1
/* -*- C++ -*-
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
namespace lemon {
20 20
/*!
21 21

	
22 22

	
23 23

	
24 24
\page lgf-format Lemon Graph Format (LGF)
25 25

	
26 26
The \e LGF is a <em>column oriented</em>
27 27
file format for storing graphs and associated data like
28 28
node and edge maps.
29 29

	
30 30
Each line with \c '#' first non-whitespace
31 31
character is considered as a comment line.
32 32

	
33 33
Otherwise the file consists of sections starting with
34 34
a header line. The header lines starts with an \c '@' character followed by the
35 35
type of section. The standard section types are \c \@nodes, \c
36 36
\@arcs and \c \@edges
37 37
and \@attributes. Each header line may also have an optional
38 38
\e name, which can be use to distinguish the sections of the same
39 39
type.
40 40

	
41 41
The standard sections are column oriented, each line consists of
42 42
<em>token</em>s separated by whitespaces. A token can be \e plain or
43 43
\e quoted. A plain token is just a sequence of non-whitespace characters,
44 44
while a quoted token is a
45 45
character sequence surrounded by double quotes, and it can also
46 46
contain whitespaces and escape sequences. 
47 47

	
48 48
The \c \@nodes section describes a set of nodes and associated
49 49
maps. The first is a header line, its columns are the names of the
50 50
maps appearing in the following lines.
51 51
One of the maps must be called \c
52 52
"label", which plays special role in the file.
53 53
The following
54 54
non-empty lines until the next section describes nodes of the
55 55
graph. Each line contains the values of the node maps
56 56
associated to the current node.
57 57

	
58 58
\code
59 59
 @nodes
60 60
 label   coordinates size    title
61 61
 1       (10,20)     10      "First node"
62 62
 2       (80,80)     8       "Second node"
63 63
 3       (40,10)     10      "Third node"
64 64
\endcode
65 65

	
66 66
The \c \@arcs section is very similar to the \c \@nodes section,
67 67
it again starts with a header line describing the names of the maps,
68 68
but the \c "label" map is not obligatory here. The following lines
69 69
describe the arcs. The first two tokens of each line are
70 70
the source and the target node of the arc, respectively, then come the map
71 71
values. The source and target tokens must be node labels.
72 72

	
73 73
\code
74 74
 @arcs
75 75
 	      capacity
76 76
 1   2   16
77 77
 1   3   12
78 78
 2   3   18
79 79
\endcode
80 80

	
81
The \c \@edges is just a synonym of \c \@arcs.
81
The \c \@edges is just a synonym of \c \@arcs. The @arcs section can
82
also store the edge set of an undirected graph. In such case there is
83
a conventional method for store arc maps in the file, if two columns
84
has the same caption with \c '+' and \c '-' prefix, then these columns
85
can be regarded as the values of an arc map.
82 86

	
83 87
The \c \@attributes section contains key-value pairs, each line
84
consists of two tokens, an attribute name, and then an attribute value.
88
consists of two tokens, an attribute name, and then an attribute
89
value. The value of the attribute could be also a label value of a
90
node or an edge, or even an edge label prefixed with \c '+' or \c '-',
91
which regards to the forward or backward directed arc of the
92
corresponding edge.
85 93

	
86 94
\code
87 95
 @attributes
88 96
 source 1
89 97
 target 3
90 98
 caption "LEMON test digraph"
91 99
\endcode
92 100

	
93 101
The \e LGF can contain extra sections, but there is no restriction on
94 102
the format of such sections.
95 103

	
96 104
*/
97 105
}
98 106

	
99 107
//  LocalWords:  whitespace whitespaces
Ignore white space 12288 line context
1 1
/* -*- C++ -*-
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/graph_utils.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
	is >> value;
52 52

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

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

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

	
73 73
    public:
74 74
      MapStorageBase() {}
75 75
      virtual ~MapStorageBase() {}
76 76

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

	
79 79
    };
80 80

	
81 81
    template <typename _Item, typename _Map, 
82 82
	      typename _Converter = DefaultConverter<typename _Map::Value> >
83 83
    class MapStorage : public MapStorageBase<_Item> {
84 84
    public:
85 85
      typedef _Map Map;
86 86
      typedef _Converter Converter;
87 87
      typedef _Item Item;
88 88
      
89 89
    private:
90 90
      Map& _map;
91 91
      Converter _converter;
92 92

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

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

	
103 103
    template <typename _Graph, bool _dir, typename _Map, 
104 104
	      typename _Converter = DefaultConverter<typename _Map::Value> >
105 105
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
106 106
    public:
107 107
      typedef _Map Map;
108 108
      typedef _Converter Converter;
109 109
      typedef _Graph Graph;
110 110
      typedef typename Graph::Edge Item;
111 111
      static const bool dir = _dir;
112 112
      
113 113
    private:
114 114
      const Graph& _graph;
115 115
      Map& _map;
116 116
      Converter _converter;
117 117

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

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

	
129 129
    class ValueStorageBase {
130 130
    public:
131 131
      ValueStorageBase() {}
132 132
      virtual ~ValueStorageBase() {}
133 133

	
134 134
      virtual void set(const std::string&) = 0;
135 135
    };
136 136

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

	
143 143
    private:
144 144
      Value& _value;
145 145
      Converter _converter;
146 146

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

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

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

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

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

	
175 175
    template <typename Graph>
176 176
    struct GraphArcLookUpConverter {
177 177
      const Graph& _graph;
178 178
      const std::map<std::string, typename Graph::Edge>& _map;
179 179
      
180 180
      GraphArcLookUpConverter(const Graph& graph, 
181 181
			      const std::map<std::string,
182 182
			                     typename Graph::Edge>& map) 
183 183
	: _graph(graph), _map(map) {}
184 184
      
185 185
      typename Graph::Arc operator()(const std::string& str) {
186 186
	if (str.empty() || (str[0] != '+' && str[0] != '-')) {
187 187
	  throw DataFormatError("Item must start with '+' or '-'");
188 188
	}
189 189
	typename std::map<std::string, typename Graph::Edge>
190 190
	  ::const_iterator it = _map.find(str.substr(1));
191 191
	if (it == _map.end()) {
192 192
	  throw DataFormatError("Item not found");
193 193
	}
194 194
	return _graph.direct(it->second, str[0] == '+');
195 195
      }
196 196
    };
197 197

	
198 198
    inline bool isWhiteSpace(char c) {
199 199
      return c == ' ' || c == '\t' || c == '\v' || 
200 200
        c == '\n' || c == '\r' || c == '\f'; 
201 201
    }
202 202
    
203 203
    inline bool isOct(char c) {
204 204
      return '0' <= c && c <='7'; 
205 205
    }
206 206
    
207 207
    inline int valueOct(char c) {
208 208
      LEMON_ASSERT(isOct(c), "The character is not octal.");
209 209
      return c - '0';
210 210
    }
211 211

	
212 212
    inline bool isHex(char c) {
213 213
      return ('0' <= c && c <= '9') || 
214 214
	('a' <= c && c <= 'z') || 
215 215
	('A' <= c && c <= 'Z'); 
216 216
    }
217 217
    
218 218
    inline int valueHex(char c) {
219 219
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
220 220
      if ('0' <= c && c <= '9') return c - '0';
221 221
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
222 222
      return c - 'A' + 10;
223 223
    }
224 224

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

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

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

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

	
290 290
      char c;
291 291
      is >> std::ws;
292 292
      
293 293
      if (!is.get(c)) 
294 294
	return is;
295 295

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

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

	
327 327
    template <typename Functor>
328 328
    class LineSection : public Section {
329 329
    private:
330 330

	
331 331
      Functor _functor;
332 332

	
333 333
    public:
334 334
      
335 335
      LineSection(const Functor& functor) : _functor(functor) {}
336 336
      virtual ~LineSection() {}
337 337

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

	
359 359
    template <typename Functor>
360 360
    class StreamSection : public Section {
361 361
    private:
362 362

	
363 363
      Functor _functor;
364 364

	
365 365
    public:
366 366
      
367 367
      StreamSection(const Functor& functor) : _functor(functor) {}
368 368
      virtual ~StreamSection() {} 
369 369

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

	
389 389
  template <typename Digraph>
390 390
  class DigraphReader;
391 391

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

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

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

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

	
454 454
    typedef _Digraph Digraph;
455 455
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
456 456
    
457 457
  private:
458 458

	
459 459

	
460 460
    std::istream* _is;
461 461
    bool local_is;
462 462

	
463 463
    Digraph& _digraph;
464 464

	
465 465
    std::string _nodes_caption;
466 466
    std::string _arcs_caption;
467 467
    std::string _attributes_caption;
468 468

	
469 469
    typedef std::map<std::string, Node> NodeIndex;
470 470
    NodeIndex _node_index;
471 471
    typedef std::map<std::string, Arc> ArcIndex;
472 472
    ArcIndex _arc_index;
473 473
    
474 474
    typedef std::vector<std::pair<std::string, 
475 475
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
476 476
    NodeMaps _node_maps; 
477 477

	
478 478
    typedef std::vector<std::pair<std::string,
479 479
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
480 480
    ArcMaps _arc_maps;
481 481

	
482 482
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
483 483
      Attributes;
484 484
    Attributes _attributes;
485 485

	
486 486
    bool _use_nodes;
487 487
    bool _use_arcs;
488 488

	
489 489
    bool _skip_nodes;
490 490
    bool _skip_arcs;
491 491

	
492 492
    int line_num;
493 493
    std::istringstream line;
494 494

	
495 495
  public:
496 496

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

	
506 506
    /// \brief Constructor
507 507
    ///
508 508
    /// Construct a directed graph reader, which reads from the given
509 509
    /// file.
510 510
    DigraphReader(const std::string& fn, Digraph& digraph) 
511 511
      : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
512 512
    	_use_nodes(false), _use_arcs(false),
513 513
	_skip_nodes(false), _skip_arcs(false) {}
514 514
    
515 515
    /// \brief Constructor
516 516
    ///
517 517
    /// Construct a directed graph reader, which reads from the given
518 518
    /// file.
519 519
    DigraphReader(const char* fn, Digraph& digraph) 
520 520
      : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
521 521
    	_use_nodes(false), _use_arcs(false),
522 522
	_skip_nodes(false), _skip_arcs(false) {}
523 523

	
524 524
    /// \brief Destructor
525 525
    ~DigraphReader() {
526 526
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
527 527
	   it != _node_maps.end(); ++it) {
528 528
	delete it->second;
529 529
      }
530 530

	
531 531
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
532 532
	   it != _arc_maps.end(); ++it) {
533 533
	delete it->second;
534 534
      }
535 535

	
536 536
      for (typename Attributes::iterator it = _attributes.begin(); 
537 537
	   it != _attributes.end(); ++it) {
538 538
	delete it->second;
539 539
      }
540 540

	
541 541
      if (local_is) {
542 542
	delete _is;
543 543
      }
544 544

	
545 545
    }
546 546

	
547 547
  private:
548 548

	
549 549
    friend DigraphReader<Digraph> digraphReader<>(std::istream& is, 
550 550
						  Digraph& digraph);    
551 551
    friend DigraphReader<Digraph> digraphReader<>(const std::string& fn, 
552 552
						  Digraph& digraph);   
553 553
    friend DigraphReader<Digraph> digraphReader<>(const char *fn, 
554 554
						  Digraph& digraph);    
555 555

	
556 556
    DigraphReader(DigraphReader& other) 
557 557
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
558 558
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
559 559
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
560 560

	
561 561
      other._is = 0;
562 562
      other.local_is = false;
563 563
      
564 564
      _node_index.swap(other._node_index);
565 565
      _arc_index.swap(other._arc_index);
566 566

	
567 567
      _node_maps.swap(other._node_maps);
568 568
      _arc_maps.swap(other._arc_maps);
569 569
      _attributes.swap(other._attributes);
570 570

	
571 571
      _nodes_caption = other._nodes_caption;
572 572
      _arcs_caption = other._arcs_caption;
573 573
      _attributes_caption = other._attributes_caption;
574 574

	
575 575
    }
576 576

	
577 577
    DigraphReader& operator=(const DigraphReader&);
578 578

	
579 579
  public:
580 580

	
581 581
    /// \name Reading rules
582 582
    /// @{
583 583
    
584 584
    /// \brief Node map reading rule
585 585
    ///
586 586
    /// Add a node map reading rule to the reader.
587 587
    template <typename Map>
588 588
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
589 589
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
590 590
      _reader_bits::MapStorageBase<Node>* storage = 
591 591
	new _reader_bits::MapStorage<Node, Map>(map);
592 592
      _node_maps.push_back(std::make_pair(caption, storage));
593 593
      return *this;
594 594
    }
595 595

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

	
610 610
    /// \brief Arc map reading rule
611 611
    ///
612 612
    /// Add an arc map reading rule to the reader.
613 613
    template <typename Map>
614 614
    DigraphReader& arcMap(const std::string& caption, Map& map) {
615 615
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
616 616
      _reader_bits::MapStorageBase<Arc>* storage = 
617 617
	new _reader_bits::MapStorage<Arc, Map>(map);
618 618
      _arc_maps.push_back(std::make_pair(caption, storage));
619 619
      return *this;
620 620
    }
621 621

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

	
636 636
    /// \brief Attribute reading rule
637 637
    ///
638 638
    /// Add an attribute reading rule to the reader.
639 639
    template <typename Value>
640 640
    DigraphReader& attribute(const std::string& caption, Value& value) {
641 641
      _reader_bits::ValueStorageBase* storage = 
642 642
	new _reader_bits::ValueStorage<Value>(value);
643 643
      _attributes.insert(std::make_pair(caption, storage));
644 644
      return *this;
645 645
    }
646 646

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

	
660 660
    /// \brief Node reading rule
661 661
    ///
662 662
    /// Add a node reading rule to reader.
663 663
    DigraphReader& node(const std::string& caption, Node& node) {
664 664
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
665 665
      Converter converter(_node_index);
666 666
      _reader_bits::ValueStorageBase* storage = 
667 667
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
668 668
      _attributes.insert(std::make_pair(caption, storage));
669 669
      return *this;
670 670
    }
671 671

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

	
684 684
    /// @}
685 685

	
686 686
    /// \name Select section by name
687 687
    /// @{
688 688

	
689 689
    /// \brief Set \c \@nodes section to be read
690 690
    ///
691 691
    /// Set \c \@nodes section to be read
692 692
    DigraphReader& nodes(const std::string& caption) {
693 693
      _nodes_caption = caption;
694 694
      return *this;
695 695
    }
696 696

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

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

	
713 713
    /// @}
714 714

	
715 715
    /// \name Using previously constructed node or arc set
716 716
    /// @{
717 717

	
718 718
    /// \brief Use previously constructed node set
719 719
    ///
720 720
    /// Use previously constructed node set, and specify the node
721 721
    /// label map.
722 722
    template <typename Map>
723 723
    DigraphReader& useNodes(const Map& map) {
724 724
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
725 725
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
726 726
      _use_nodes = true;
727 727
      _writer_bits::DefaultConverter<typename Map::Value> converter;
728 728
      for (NodeIt n(_digraph); n != INVALID; ++n) {
729 729
	_node_index.insert(std::make_pair(converter(map[n]), n));
730 730
      }
731 731
      return *this;
732 732
    }
733 733

	
734 734
    /// \brief Use previously constructed node set
735 735
    ///
736 736
    /// Use previously constructed node set, and specify the node
737 737
    /// label map and a functor which converts the label map values to
738 738
    /// \c std::string.
739 739
    template <typename Map, typename Converter>
740 740
    DigraphReader& useNodes(const Map& map, 
741 741
			    const Converter& converter = Converter()) {
742 742
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
743 743
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
744 744
      _use_nodes = true;
745 745
      for (NodeIt n(_digraph); n != INVALID; ++n) {
746 746
	_node_index.insert(std::make_pair(converter(map[n]), n));
747 747
      }
748 748
      return *this;
749 749
    }
750 750

	
751 751
    /// \brief Use previously constructed arc set
752 752
    ///
753 753
    /// Use previously constructed arc set, and specify the arc
754 754
    /// label map.
755 755
    template <typename Map>
756 756
    DigraphReader& useArcs(const Map& map) {
757 757
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
758 758
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
759 759
      _use_arcs = true;
760 760
      _writer_bits::DefaultConverter<typename Map::Value> converter;
761 761
      for (ArcIt a(_digraph); a != INVALID; ++a) {
762 762
	_arc_index.insert(std::make_pair(converter(map[a]), a));
763 763
      }
764 764
      return *this;
765 765
    }
766 766

	
767 767
    /// \brief Use previously constructed arc set
768 768
    ///
769 769
    /// Use previously constructed arc set, and specify the arc
770 770
    /// label map and a functor which converts the label map values to
771 771
    /// \c std::string.
772 772
    template <typename Map, typename Converter>
773 773
    DigraphReader& useArcs(const Map& map, 
774 774
			   const Converter& converter = Converter()) {
775 775
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
776 776
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); 
777 777
      _use_arcs = true;
778 778
      for (ArcIt a(_digraph); a != INVALID; ++a) {
779 779
	_arc_index.insert(std::make_pair(converter(map[a]), a));
780 780
      }
781 781
      return *this;
782 782
    }
783 783

	
784 784
    /// \brief Skips the reading of node section
785 785
    ///
786 786
    /// Omit the reading of the node section. This implies that each node
787 787
    /// map reading rule will be abandoned, and the nodes of the graph
788 788
    /// will not be constructed, which usually cause that the arc set
789 789
    /// could not be read due to lack of node name resolving.
790 790
    /// Therefore \c skipArcs() function should also be used, or
791 791
    /// \c useNodes() should be used to specify the label of the nodes.
792 792
    DigraphReader& skipNodes() {
793 793
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); 
794 794
      _skip_nodes = true;
795 795
      return *this;
796 796
    }
797 797

	
798 798
    /// \brief Skips the reading of arc section
799 799
    ///
800 800
    /// Omit the reading of the arc section. This implies that each arc
801 801
    /// map reading rule will be abandoned, and the arcs of the graph
802 802
    /// will not be constructed.
803 803
    DigraphReader& skipArcs() {
804 804
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set"); 
805 805
      _skip_arcs = true;
806 806
      return *this;
807 807
    }
808 808

	
809 809
    /// @}
810 810

	
811 811
  private:
812 812

	
813 813
    bool readLine() {
814 814
      std::string str;
815 815
      while(++line_num, std::getline(*_is, str)) {
816 816
	line.clear(); line.str(str);
817 817
	char c;
818 818
	if (line >> std::ws >> c && c != '#') {
819 819
	  line.putback(c);
820 820
	  return true;
821 821
	}
822 822
      }
823 823
      return false;
824 824
    }
825 825

	
826 826
    bool readSuccess() {
827 827
      return static_cast<bool>(*_is);
828 828
    }
829 829
    
830 830
    void skipSection() {
831 831
      char c;
832 832
      while (readSuccess() && line >> c && c != '@') {
833 833
	readLine();
834 834
      }
835 835
      line.putback(c);
836 836
    }
837 837

	
838 838
    void readNodes() {
839 839

	
840 840
      std::vector<int> map_index(_node_maps.size());
841 841
      int map_num, label_index;
842 842

	
843 843
      char c;
844 844
      if (!readLine() || !(line >> c) || c == '@') {
845 845
	if (readSuccess() && line) line.putback(c);
846 846
	if (!_node_maps.empty()) 
847 847
	  throw DataFormatError("Cannot find map names");
848 848
	return;
849 849
      }
850 850
      line.putback(c);
851 851

	
852 852
      {
853 853
	std::map<std::string, int> maps;
854 854
	
855 855
	std::string map;
856 856
	int index = 0;
857 857
	while (_reader_bits::readToken(line, map)) {
858 858
	  if (maps.find(map) != maps.end()) {
859 859
	    std::ostringstream msg;
860 860
	    msg << "Multiple occurence of node map: " << map;
861 861
	    throw DataFormatError(msg.str().c_str());
862 862
	  }
863 863
	  maps.insert(std::make_pair(map, index));
864 864
	  ++index;
865 865
	}
866 866
	
867 867
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
868 868
	  std::map<std::string, int>::iterator jt = 
869 869
	    maps.find(_node_maps[i].first);
870 870
	  if (jt == maps.end()) {
871 871
	    std::ostringstream msg;
872 872
	    msg << "Map not found in file: " << _node_maps[i].first;
873 873
	    throw DataFormatError(msg.str().c_str());
874 874
	  }
875 875
	  map_index[i] = jt->second;
876 876
	}
877 877

	
878 878
	{
879 879
	  std::map<std::string, int>::iterator jt = maps.find("label");
880 880
	  if (jt != maps.end()) {
881 881
	    label_index = jt->second;
882 882
	  } else {
883 883
	    label_index = -1;
884 884
	  }
885 885
	}
886 886
	map_num = maps.size();
887 887
      }
888 888

	
889 889
      while (readLine() && line >> c && c != '@') {
890 890
	line.putback(c);
891 891

	
892 892
	std::vector<std::string> tokens(map_num);
893 893
	for (int i = 0; i < map_num; ++i) {
894 894
	  if (!_reader_bits::readToken(line, tokens[i])) {
895 895
	    std::ostringstream msg;
896 896
	    msg << "Column not found (" << i + 1 << ")";
897 897
	    throw DataFormatError(msg.str().c_str());
898 898
	  }
899 899
	}
900 900
	if (line >> std::ws >> c)
901 901
	  throw DataFormatError("Extra character on the end of line");
902 902
	
903 903
	Node n;
904 904
	if (!_use_nodes) {
905 905
	  n = _digraph.addNode();
906 906
	  if (label_index != -1)
907 907
	    _node_index.insert(std::make_pair(tokens[label_index], n));
908 908
	} else {
909 909
	  if (label_index == -1) 
910 910
	    throw DataFormatError("Label map not found in file");
911 911
	  typename std::map<std::string, Node>::iterator it =
912 912
	    _node_index.find(tokens[label_index]);
913 913
	  if (it == _node_index.end()) {
914 914
	    std::ostringstream msg;
915 915
	    msg << "Node with label not found: " << tokens[label_index];
916 916
	    throw DataFormatError(msg.str().c_str());	    
917 917
	  }
918 918
	  n = it->second;
919 919
	}
920 920

	
921 921
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
922 922
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
923 923
	}
924 924

	
925 925
      }
926 926
      if (readSuccess()) {
927 927
	line.putback(c);
928 928
      }
929 929
    }
930 930

	
931 931
    void readArcs() {
932 932

	
933 933
      std::vector<int> map_index(_arc_maps.size());
934 934
      int map_num, label_index;
935 935

	
936 936
      char c;
937 937
      if (!readLine() || !(line >> c) || c == '@') {
938 938
	if (readSuccess() && line) line.putback(c);
939 939
	if (!_arc_maps.empty()) 
940 940
	  throw DataFormatError("Cannot find map names");
941 941
	return;
942 942
      }
943 943
      line.putback(c);
944 944
      
945 945
      {
946 946
	std::map<std::string, int> maps;
947 947
	
948 948
	std::string map;
949 949
	int index = 0;
950 950
	while (_reader_bits::readToken(line, map)) {
951 951
	  if (maps.find(map) != maps.end()) {
952 952
	    std::ostringstream msg;
953 953
	    msg << "Multiple occurence of arc map: " << map;
954 954
	    throw DataFormatError(msg.str().c_str());
955 955
	  }
956 956
	  maps.insert(std::make_pair(map, index));
957 957
	  ++index;
958 958
	}
959 959
	
960 960
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
961 961
	  std::map<std::string, int>::iterator jt = 
962 962
	    maps.find(_arc_maps[i].first);
963 963
	  if (jt == maps.end()) {
964 964
	    std::ostringstream msg;
965 965
	    msg << "Map not found in file: " << _arc_maps[i].first;
966 966
	    throw DataFormatError(msg.str().c_str());
967 967
	  }
968 968
	  map_index[i] = jt->second;
969 969
	}
970 970

	
971 971
	{
972 972
	  std::map<std::string, int>::iterator jt = maps.find("label");
973 973
	  if (jt != maps.end()) {
974 974
	    label_index = jt->second;
975 975
	  } else {
976 976
	    label_index = -1;
977 977
	  }
978 978
	}
979 979
	map_num = maps.size();
980 980
      }
981 981

	
982 982
      while (readLine() && line >> c && c != '@') {
983 983
	line.putback(c);
984 984

	
985 985
	std::string source_token;
986 986
	std::string target_token;
987 987

	
988 988
	if (!_reader_bits::readToken(line, source_token))
989 989
	  throw DataFormatError("Source not found");
990 990

	
991 991
	if (!_reader_bits::readToken(line, target_token))
992 992
	  throw DataFormatError("Target not found");
993 993
	
994 994
	std::vector<std::string> tokens(map_num);
995 995
	for (int i = 0; i < map_num; ++i) {
996 996
	  if (!_reader_bits::readToken(line, tokens[i])) {
997 997
	    std::ostringstream msg;
998 998
	    msg << "Column not found (" << i + 1 << ")";
999 999
	    throw DataFormatError(msg.str().c_str());
1000 1000
	  }
1001 1001
	}
1002 1002
	if (line >> std::ws >> c)
1003 1003
	  throw DataFormatError("Extra character on the end of line");
1004 1004
	
1005 1005
	Arc a;
1006 1006
	if (!_use_arcs) {
1007 1007

	
1008 1008
          typename NodeIndex::iterator it;
1009 1009
 
1010 1010
          it = _node_index.find(source_token);
1011 1011
          if (it == _node_index.end()) {
1012 1012
            std::ostringstream msg;
1013 1013
            msg << "Item not found: " << source_token;
1014 1014
            throw DataFormatError(msg.str().c_str());
1015 1015
          }
1016 1016
          Node source = it->second;
1017 1017

	
1018 1018
          it = _node_index.find(target_token);
1019 1019
          if (it == _node_index.end()) {       
1020 1020
            std::ostringstream msg;            
1021 1021
            msg << "Item not found: " << target_token;
1022 1022
            throw DataFormatError(msg.str().c_str());
1023 1023
          }                                          
1024 1024
          Node target = it->second;                            
1025 1025

	
1026 1026
	  a = _digraph.addArc(source, target);
1027 1027
	  if (label_index != -1) 
1028 1028
	    _arc_index.insert(std::make_pair(tokens[label_index], a));
1029 1029
	} else {
1030 1030
	  if (label_index == -1) 
1031 1031
	    throw DataFormatError("Label map not found in file");
1032 1032
	  typename std::map<std::string, Arc>::iterator it =
1033 1033
	    _arc_index.find(tokens[label_index]);
1034 1034
	  if (it == _arc_index.end()) {
1035 1035
	    std::ostringstream msg;
1036 1036
	    msg << "Arc with label not found: " << tokens[label_index];
1037 1037
	    throw DataFormatError(msg.str().c_str());	    
1038 1038
	  }
1039 1039
	  a = it->second;
1040 1040
	}
1041 1041

	
1042 1042
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1043 1043
	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
1044 1044
	}
1045 1045

	
1046 1046
      }
1047 1047
      if (readSuccess()) {
1048 1048
	line.putback(c);
1049 1049
      }
1050 1050
    }
1051 1051

	
1052 1052
    void readAttributes() {
1053 1053

	
1054 1054
      std::set<std::string> read_attr;
1055 1055

	
1056 1056
      char c;
1057 1057
      while (readLine() && line >> c && c != '@') {
1058 1058
	line.putback(c);
1059 1059
	
1060 1060
	std::string attr, token;
1061 1061
	if (!_reader_bits::readToken(line, attr))
1062 1062
	  throw DataFormatError("Attribute name not found");
1063 1063
	if (!_reader_bits::readToken(line, token))
1064 1064
	  throw DataFormatError("Attribute value not found");
1065 1065
	if (line >> c)
1066 1066
	  throw DataFormatError("Extra character on the end of line");	  
1067 1067

	
1068 1068
	{
1069 1069
	  std::set<std::string>::iterator it = read_attr.find(attr);
1070 1070
	  if (it != read_attr.end()) {
1071 1071
	    std::ostringstream msg;
1072 1072
	    msg << "Multiple occurence of attribute " << attr;
1073 1073
	    throw DataFormatError(msg.str().c_str());
1074 1074
	  }
1075 1075
	  read_attr.insert(attr);
1076 1076
	}
1077 1077
	
1078 1078
	{
1079 1079
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1080 1080
	  while (it != _attributes.end() && it->first == attr) {
1081 1081
	    it->second->set(token);
1082 1082
	    ++it;
1083 1083
	  }
1084 1084
	}
1085 1085

	
1086 1086
      }
1087 1087
      if (readSuccess()) {
1088 1088
	line.putback(c);
1089 1089
      }
1090 1090
      for (typename Attributes::iterator it = _attributes.begin();
1091 1091
	   it != _attributes.end(); ++it) {
1092 1092
	if (read_attr.find(it->first) == read_attr.end()) {
1093 1093
	  std::ostringstream msg;
1094 1094
	  msg << "Attribute not found in file: " << it->first;
1095 1095
	  throw DataFormatError(msg.str().c_str());
1096 1096
	}	
1097 1097
      }
1098 1098
    }
1099 1099

	
1100 1100
  public:
1101 1101

	
1102 1102
    /// \name Execution of the reader    
1103 1103
    /// @{
1104 1104

	
1105 1105
    /// \brief Start the batch processing
1106 1106
    ///
1107 1107
    /// This function starts the batch processing
1108 1108
    void run() {
1109 1109
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1110 1110
      if (!*_is) {
1111 1111
	throw DataFormatError("Cannot find file");
1112 1112
      }
1113 1113
      
1114 1114
      bool nodes_done = _skip_nodes;
1115 1115
      bool arcs_done = _skip_arcs;
1116 1116
      bool attributes_done = false;
1117 1117

	
1118 1118
      line_num = 0;      
1119 1119
      readLine();
1120 1120
      skipSection();
1121 1121

	
1122 1122
      while (readSuccess()) {
1123 1123
	try {
1124 1124
	  char c;
1125 1125
	  std::string section, caption;
1126 1126
	  line >> c;
1127 1127
	  _reader_bits::readToken(line, section);
1128 1128
	  _reader_bits::readToken(line, caption);
1129 1129

	
1130 1130
	  if (line >> c) 
1131 1131
	    throw DataFormatError("Extra character on the end of line");
1132 1132

	
1133 1133
	  if (section == "nodes" && !nodes_done) {
1134 1134
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1135 1135
	      readNodes();
1136 1136
	      nodes_done = true;
1137 1137
	    }
1138 1138
	  } else if ((section == "arcs" || section == "edges") && 
1139 1139
		     !arcs_done) {
1140 1140
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
1141 1141
	      readArcs();
1142 1142
	      arcs_done = true;
1143 1143
	    }
1144 1144
	  } else if (section == "attributes" && !attributes_done) {
1145 1145
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
1146 1146
	      readAttributes();
1147 1147
	      attributes_done = true;
1148 1148
	    }
1149 1149
	  } else {
1150 1150
	    readLine();
1151 1151
	    skipSection();
1152 1152
	  }
1153 1153
	} catch (DataFormatError& error) {
1154 1154
	  error.line(line_num);
1155 1155
	  throw;
1156 1156
	}	
1157 1157
      }
1158 1158

	
1159 1159
      if (!nodes_done) {
1160 1160
	throw DataFormatError("Section @nodes not found");
1161 1161
      }
1162 1162

	
1163 1163
      if (!arcs_done) {
1164 1164
	throw DataFormatError("Section @arcs not found");
1165 1165
      }
1166 1166

	
1167 1167
      if (!attributes_done && !_attributes.empty()) {
1168 1168
	throw DataFormatError("Section @attributes not found");
1169 1169
      }
1170 1170

	
1171 1171
    }
1172 1172

	
1173 1173
    /// @}
1174 1174
    
1175 1175
  };
1176 1176

	
1177 1177
  /// \brief Return a \ref DigraphReader class
1178 1178
  /// 
1179 1179
  /// This function just returns a \ref DigraphReader class.
1180 1180
  /// \relates DigraphReader
1181 1181
  template <typename Digraph>
1182 1182
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
1183 1183
    DigraphReader<Digraph> tmp(is, digraph);
1184 1184
    return tmp;
1185 1185
  }
1186 1186

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

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

	
1208 1208
  template <typename Graph>
1209 1209
  class GraphReader;
1210 1210

	
1211 1211
  template <typename Graph>
1212 1212
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph);    
1213 1213

	
1214 1214
  template <typename Graph>
1215 1215
  GraphReader<Graph> graphReader(const std::string& fn, Graph& graph);   
1216 1216

	
1217 1217
  template <typename Graph>
1218 1218
  GraphReader<Graph> graphReader(const char *fn, Graph& graph);    
1219 1219

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

	
1233 1239
    typedef _Graph Graph;
1234 1240
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1235 1241
    
1236 1242
  private:
1237 1243

	
1238 1244
    std::istream* _is;
1239 1245
    bool local_is;
1240 1246

	
1241 1247
    Graph& _graph;
1242 1248

	
1243 1249
    std::string _nodes_caption;
1244 1250
    std::string _edges_caption;
1245 1251
    std::string _attributes_caption;
1246 1252

	
1247 1253
    typedef std::map<std::string, Node> NodeIndex;
1248 1254
    NodeIndex _node_index;
1249 1255
    typedef std::map<std::string, Edge> EdgeIndex;
1250 1256
    EdgeIndex _edge_index;
1251 1257
    
1252 1258
    typedef std::vector<std::pair<std::string, 
1253 1259
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
1254 1260
    NodeMaps _node_maps; 
1255 1261

	
1256 1262
    typedef std::vector<std::pair<std::string,
1257 1263
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1258 1264
    EdgeMaps _edge_maps;
1259 1265

	
1260 1266
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
1261 1267
      Attributes;
1262 1268
    Attributes _attributes;
1263 1269

	
1264 1270
    bool _use_nodes;
1265 1271
    bool _use_edges;
1266 1272

	
1267 1273
    bool _skip_nodes;
1268 1274
    bool _skip_edges;
1269 1275

	
1270 1276
    int line_num;
1271 1277
    std::istringstream line;
1272 1278

	
1273 1279
  public:
1274 1280

	
1275 1281
    /// \brief Constructor
1276 1282
    ///
1277 1283
    /// Construct an undirected graph reader, which reads from the given
1278 1284
    /// input stream.
1279 1285
    GraphReader(std::istream& is, Graph& graph) 
1280 1286
      : _is(&is), local_is(false), _graph(graph),
1281 1287
	_use_nodes(false), _use_edges(false),
1282 1288
	_skip_nodes(false), _skip_edges(false) {}
1283 1289

	
1284 1290
    /// \brief Constructor
1285 1291
    ///
1286 1292
    /// Construct an undirected graph reader, which reads from the given
1287 1293
    /// file.
1288 1294
    GraphReader(const std::string& fn, Graph& graph) 
1289 1295
      : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
1290 1296
    	_use_nodes(false), _use_edges(false),
1291 1297
	_skip_nodes(false), _skip_edges(false) {}
1292 1298
    
1293 1299
    /// \brief Constructor
1294 1300
    ///
1295 1301
    /// Construct an undirected graph reader, which reads from the given
1296 1302
    /// file.
1297 1303
    GraphReader(const char* fn, Graph& graph) 
1298 1304
      : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
1299 1305
    	_use_nodes(false), _use_edges(false),
1300 1306
	_skip_nodes(false), _skip_edges(false) {}
1301 1307

	
1302 1308
    /// \brief Destructor
1303 1309
    ~GraphReader() {
1304 1310
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
1305 1311
	   it != _node_maps.end(); ++it) {
1306 1312
	delete it->second;
1307 1313
      }
1308 1314

	
1309 1315
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
1310 1316
	   it != _edge_maps.end(); ++it) {
1311 1317
	delete it->second;
1312 1318
      }
1313 1319

	
1314 1320
      for (typename Attributes::iterator it = _attributes.begin(); 
1315 1321
	   it != _attributes.end(); ++it) {
1316 1322
	delete it->second;
1317 1323
      }
1318 1324

	
1319 1325
      if (local_is) {
1320 1326
	delete _is;
1321 1327
      }
1322 1328

	
1323 1329
    }
1324 1330

	
1325 1331
  private:
1326 1332
    friend GraphReader<Graph> graphReader<>(std::istream& is, Graph& graph);    
1327 1333
    friend GraphReader<Graph> graphReader<>(const std::string& fn, 
1328 1334
					    Graph& graph);   
1329 1335
    friend GraphReader<Graph> graphReader<>(const char *fn, Graph& graph);    
1330 1336

	
1331 1337
    GraphReader(GraphReader& other) 
1332 1338
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1333 1339
	_use_nodes(other._use_nodes), _use_edges(other._use_edges),
1334 1340
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1335 1341

	
1336 1342
      other._is = 0;
1337 1343
      other.local_is = false;
1338 1344
      
1339 1345
      _node_index.swap(other._node_index);
1340 1346
      _edge_index.swap(other._edge_index);
1341 1347

	
1342 1348
      _node_maps.swap(other._node_maps);
1343 1349
      _edge_maps.swap(other._edge_maps);
1344 1350
      _attributes.swap(other._attributes);
1345 1351

	
1346 1352
      _nodes_caption = other._nodes_caption;
1347 1353
      _edges_caption = other._edges_caption;
1348 1354
      _attributes_caption = other._attributes_caption;
1349 1355

	
1350 1356
    }
1351 1357

	
1352 1358
    GraphReader& operator=(const GraphReader&);
1353 1359

	
1354 1360
  public:
1355 1361

	
1356 1362
    /// \name Reading rules
1357 1363
    /// @{
1358 1364
    
1359 1365
    /// \brief Node map reading rule
1360 1366
    ///
1361 1367
    /// Add a node map reading rule to the reader.
1362 1368
    template <typename Map>
1363 1369
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1364 1370
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1365 1371
      _reader_bits::MapStorageBase<Node>* storage = 
1366 1372
	new _reader_bits::MapStorage<Node, Map>(map);
1367 1373
      _node_maps.push_back(std::make_pair(caption, storage));
1368 1374
      return *this;
1369 1375
    }
1370 1376

	
1371 1377
    /// \brief Node map reading rule
1372 1378
    ///
1373 1379
    /// Add a node map reading rule with specialized converter to the
1374 1380
    /// reader.
1375 1381
    template <typename Map, typename Converter>
1376 1382
    GraphReader& nodeMap(const std::string& caption, Map& map, 
1377 1383
			   const Converter& converter = Converter()) {
1378 1384
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1379 1385
      _reader_bits::MapStorageBase<Node>* storage = 
1380 1386
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1381 1387
      _node_maps.push_back(std::make_pair(caption, storage));
1382 1388
      return *this;
1383 1389
    }
1384 1390

	
1385 1391
    /// \brief Edge map reading rule
1386 1392
    ///
1387 1393
    /// Add an edge map reading rule to the reader.
1388 1394
    template <typename Map>
1389 1395
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1390 1396
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1391 1397
      _reader_bits::MapStorageBase<Edge>* storage = 
1392 1398
	new _reader_bits::MapStorage<Edge, Map>(map);
1393 1399
      _edge_maps.push_back(std::make_pair(caption, storage));
1394 1400
      return *this;
1395 1401
    }
1396 1402

	
1397 1403
    /// \brief Edge map reading rule
1398 1404
    ///
1399 1405
    /// Add an edge map reading rule with specialized converter to the
1400 1406
    /// reader.
1401 1407
    template <typename Map, typename Converter>
1402 1408
    GraphReader& edgeMap(const std::string& caption, Map& map, 
1403 1409
			  const Converter& converter = Converter()) {
1404 1410
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1405 1411
      _reader_bits::MapStorageBase<Edge>* storage = 
1406 1412
	new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1407 1413
      _edge_maps.push_back(std::make_pair(caption, storage));
1408 1414
      return *this;
1409 1415
    }
1410 1416

	
1411 1417
    /// \brief Arc map reading rule
1412 1418
    ///
1413 1419
    /// Add an arc map reading rule to the reader.
1414 1420
    template <typename Map>
1415 1421
    GraphReader& arcMap(const std::string& caption, Map& map) {
1416 1422
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1417 1423
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
1418 1424
	new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1419 1425
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1420 1426
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
1421 1427
	new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1422 1428
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1423 1429
      return *this;
1424 1430
    }
1425 1431

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

	
1445 1451
    /// \brief Attribute reading rule
1446 1452
    ///
1447 1453
    /// Add an attribute reading rule to the reader.
1448 1454
    template <typename Value>
1449 1455
    GraphReader& attribute(const std::string& caption, Value& value) {
1450 1456
      _reader_bits::ValueStorageBase* storage = 
1451 1457
	new _reader_bits::ValueStorage<Value>(value);
1452 1458
      _attributes.insert(std::make_pair(caption, storage));
1453 1459
      return *this;
1454 1460
    }
1455 1461

	
1456 1462
    /// \brief Attribute reading rule
1457 1463
    ///
1458 1464
    /// Add an attribute reading rule with specialized converter to the
1459 1465
    /// reader.
1460 1466
    template <typename Value, typename Converter>
1461 1467
    GraphReader& attribute(const std::string& caption, Value& value, 
1462 1468
			     const Converter& converter = Converter()) {
1463 1469
      _reader_bits::ValueStorageBase* storage = 
1464 1470
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1465 1471
      _attributes.insert(std::make_pair(caption, storage));
1466 1472
      return *this;
1467 1473
    }
1468 1474

	
1469 1475
    /// \brief Node reading rule
1470 1476
    ///
1471 1477
    /// Add a node reading rule to reader.
1472 1478
    GraphReader& node(const std::string& caption, Node& node) {
1473 1479
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1474 1480
      Converter converter(_node_index);
1475 1481
      _reader_bits::ValueStorageBase* storage = 
1476 1482
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1477 1483
      _attributes.insert(std::make_pair(caption, storage));
1478 1484
      return *this;
1479 1485
    }
1480 1486

	
1481 1487
    /// \brief Edge reading rule
1482 1488
    ///
1483 1489
    /// Add an edge reading rule to reader.
1484 1490
    GraphReader& edge(const std::string& caption, Edge& edge) {
1485 1491
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1486 1492
      Converter converter(_edge_index);
1487 1493
      _reader_bits::ValueStorageBase* storage = 
1488 1494
	new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1489 1495
      _attributes.insert(std::make_pair(caption, storage));
1490 1496
      return *this;
1491 1497
    }
1492 1498

	
1493 1499
    /// \brief Arc reading rule
1494 1500
    ///
1495 1501
    /// Add an arc reading rule to reader.
1496 1502
    GraphReader& arc(const std::string& caption, Arc& arc) {
1497 1503
      typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
1498 1504
      Converter converter(_graph, _edge_index);
1499 1505
      _reader_bits::ValueStorageBase* storage = 
1500 1506
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1501 1507
      _attributes.insert(std::make_pair(caption, storage));
1502 1508
      return *this;
1503 1509
    }
1504 1510

	
1505 1511
    /// @}
1506 1512

	
1507 1513
    /// \name Select section by name
1508 1514
    /// @{
1509 1515

	
1510 1516
    /// \brief Set \c \@nodes section to be read
1511 1517
    ///
1512 1518
    /// Set \c \@nodes section to be read.
1513 1519
    GraphReader& nodes(const std::string& caption) {
1514 1520
      _nodes_caption = caption;
1515 1521
      return *this;
1516 1522
    }
1517 1523

	
1518 1524
    /// \brief Set \c \@edges section to be read
1519 1525
    ///
1520 1526
    /// Set \c \@edges section to be read.
1521 1527
    GraphReader& edges(const std::string& caption) {
1522 1528
      _edges_caption = caption;
1523 1529
      return *this;
1524 1530
    }
1525 1531

	
1526 1532
    /// \brief Set \c \@attributes section to be read
1527 1533
    ///
1528 1534
    /// Set \c \@attributes section to be read.
1529 1535
    GraphReader& attributes(const std::string& caption) {
1530 1536
      _attributes_caption = caption;
1531 1537
      return *this;
1532 1538
    }
1533 1539

	
1534 1540
    /// @}
1535 1541

	
1536 1542
    /// \name Using previously constructed node or edge set
1537 1543
    /// @{
1538 1544

	
1539 1545
    /// \brief Use previously constructed node set
1540 1546
    ///
1541 1547
    /// Use previously constructed node set, and specify the node
1542 1548
    /// label map.
1543 1549
    template <typename Map>
1544 1550
    GraphReader& useNodes(const Map& map) {
1545 1551
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1546 1552
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
1547 1553
      _use_nodes = true;
1548 1554
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1549 1555
      for (NodeIt n(_graph); n != INVALID; ++n) {
1550 1556
	_node_index.insert(std::make_pair(converter(map[n]), n));
1551 1557
      }
1552 1558
      return *this;
1553 1559
    }
1554 1560

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

	
1572 1578
    /// \brief Use previously constructed edge set
1573 1579
    ///
1574 1580
    /// Use previously constructed edge set, and specify the edge
1575 1581
    /// label map.
1576 1582
    template <typename Map>
1577 1583
    GraphReader& useEdges(const Map& map) {
1578 1584
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1579 1585
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1580 1586
      _use_edges = true;
1581 1587
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1582 1588
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1583 1589
	_edge_index.insert(std::make_pair(converter(map[a]), a));
1584 1590
      }
1585 1591
      return *this;
1586 1592
    }
1587 1593

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

	
1605 1611
    /// \brief Skip the reading of node section
1606 1612
    ///
1607 1613
    /// Omit the reading of the node section. This implies that each node
1608 1614
    /// map reading rule will be abandoned, and the nodes of the graph
1609 1615
    /// will not be constructed, which usually cause that the edge set
1610 1616
    /// could not be read due to lack of node name
1611 1617
    /// could not be read due to lack of node name resolving.
1612 1618
    /// Therefore \c skipEdges() function should also be used, or
1613 1619
    /// \c useNodes() should be used to specify the label of the nodes.
1614 1620
    GraphReader& skipNodes() {
1615 1621
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); 
1616 1622
      _skip_nodes = true;
1617 1623
      return *this;
1618 1624
    }
1619 1625

	
1620 1626
    /// \brief Skip the reading of edge section
1621 1627
    ///
1622 1628
    /// Omit the reading of the edge section. This implies that each edge
1623 1629
    /// map reading rule will be abandoned, and the edges of the graph
1624 1630
    /// will not be constructed.
1625 1631
    GraphReader& skipEdges() {
1626 1632
      LEMON_ASSERT(!_skip_edges, "Skip edges already set"); 
1627 1633
      _skip_edges = true;
1628 1634
      return *this;
1629 1635
    }
1630 1636

	
1631 1637
    /// @}
1632 1638

	
1633 1639
  private:
1634 1640

	
1635 1641
    bool readLine() {
1636 1642
      std::string str;
1637 1643
      while(++line_num, std::getline(*_is, str)) {
1638 1644
	line.clear(); line.str(str);
1639 1645
	char c;
1640 1646
	if (line >> std::ws >> c && c != '#') {
1641 1647
	  line.putback(c);
1642 1648
	  return true;
1643 1649
	}
1644 1650
      }
1645 1651
      return false;
1646 1652
    }
1647 1653

	
1648 1654
    bool readSuccess() {
1649 1655
      return static_cast<bool>(*_is);
1650 1656
    }
1651 1657
    
1652 1658
    void skipSection() {
1653 1659
      char c;
1654 1660
      while (readSuccess() && line >> c && c != '@') {
1655 1661
	readLine();
1656 1662
      }
1657 1663
      line.putback(c);
1658 1664
    }
1659 1665

	
1660 1666
    void readNodes() {
1661 1667

	
1662 1668
      std::vector<int> map_index(_node_maps.size());
1663 1669
      int map_num, label_index;
1664 1670

	
1665 1671
      char c;
1666 1672
      if (!readLine() || !(line >> c) || c == '@') {
1667 1673
	if (readSuccess() && line) line.putback(c);
1668 1674
	if (!_node_maps.empty()) 
1669 1675
	  throw DataFormatError("Cannot find map names");
1670 1676
	return;
1671 1677
      }
1672 1678
      line.putback(c);
1673 1679
      
1674 1680
      {
1675 1681
	std::map<std::string, int> maps;
1676 1682
	
1677 1683
	std::string map;
1678 1684
	int index = 0;
1679 1685
	while (_reader_bits::readToken(line, map)) {
1680 1686
	  if (maps.find(map) != maps.end()) {
1681 1687
	    std::ostringstream msg;
1682 1688
	    msg << "Multiple occurence of node map: " << map;
1683 1689
	    throw DataFormatError(msg.str().c_str());
1684 1690
	  }
1685 1691
	  maps.insert(std::make_pair(map, index));
1686 1692
	  ++index;
1687 1693
	}
1688 1694
	
1689 1695
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1690 1696
	  std::map<std::string, int>::iterator jt = 
1691 1697
	    maps.find(_node_maps[i].first);
1692 1698
	  if (jt == maps.end()) {
1693 1699
	    std::ostringstream msg;
1694 1700
	    msg << "Map not found in file: " << _node_maps[i].first;
1695 1701
	    throw DataFormatError(msg.str().c_str());
1696 1702
	  }
1697 1703
	  map_index[i] = jt->second;
1698 1704
	}
1699 1705

	
1700 1706
	{
1701 1707
	  std::map<std::string, int>::iterator jt = maps.find("label");
1702 1708
	  if (jt != maps.end()) {
1703 1709
	    label_index = jt->second;
1704 1710
	  } else {
1705 1711
	    label_index = -1;
1706 1712
	  }
1707 1713
	}
1708 1714
	map_num = maps.size();
1709 1715
      }
1710 1716

	
1711 1717
      while (readLine() && line >> c && c != '@') {
1712 1718
	line.putback(c);
1713 1719

	
1714 1720
	std::vector<std::string> tokens(map_num);
1715 1721
	for (int i = 0; i < map_num; ++i) {
1716 1722
	  if (!_reader_bits::readToken(line, tokens[i])) {
1717 1723
	    std::ostringstream msg;
1718 1724
	    msg << "Column not found (" << i + 1 << ")";
1719 1725
	    throw DataFormatError(msg.str().c_str());
1720 1726
	  }
1721 1727
	}
1722 1728
	if (line >> std::ws >> c)
1723 1729
	  throw DataFormatError("Extra character on the end of line");
1724 1730
	
1725 1731
	Node n;
1726 1732
	if (!_use_nodes) {
1727 1733
	  n = _graph.addNode();
1728 1734
	  if (label_index != -1) 
1729 1735
	    _node_index.insert(std::make_pair(tokens[label_index], n));
1730 1736
	} else {
1731 1737
	  if (label_index == -1) 
1732 1738
	    throw DataFormatError("Label map not found in file");
1733 1739
	  typename std::map<std::string, Node>::iterator it =
1734 1740
	    _node_index.find(tokens[label_index]);
1735 1741
	  if (it == _node_index.end()) {
1736 1742
	    std::ostringstream msg;
1737 1743
	    msg << "Node with label not found: " << tokens[label_index];
1738 1744
	    throw DataFormatError(msg.str().c_str());	    
1739 1745
	  }
1740 1746
	  n = it->second;
1741 1747
	}
1742 1748

	
1743 1749
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1744 1750
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
1745 1751
	}
1746 1752

	
1747 1753
      }
1748 1754
      if (readSuccess()) {
1749 1755
	line.putback(c);
1750 1756
      }
1751 1757
    }
1752 1758

	
1753 1759
    void readEdges() {
1754 1760

	
1755 1761
      std::vector<int> map_index(_edge_maps.size());
1756 1762
      int map_num, label_index;
1757 1763

	
1758 1764
      char c;
1759 1765
      if (!readLine() || !(line >> c) || c == '@') {
1760 1766
	if (readSuccess() && line) line.putback(c);
1761 1767
	if (!_edge_maps.empty()) 
1762 1768
	  throw DataFormatError("Cannot find map names");
1763 1769
	return;
1764 1770
      }
1765 1771
      line.putback(c);
1766 1772
      
1767 1773
      {
1768 1774
	std::map<std::string, int> maps;
1769 1775
	
1770 1776
	std::string map;
1771 1777
	int index = 0;
1772 1778
	while (_reader_bits::readToken(line, map)) {
1773 1779
	  if (maps.find(map) != maps.end()) {
1774 1780
	    std::ostringstream msg;
1775 1781
	    msg << "Multiple occurence of edge map: " << map;
1776 1782
	    throw DataFormatError(msg.str().c_str());
1777 1783
	  }
1778 1784
	  maps.insert(std::make_pair(map, index));
1779 1785
	  ++index;
1780 1786
	}
1781 1787
	
1782 1788
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1783 1789
	  std::map<std::string, int>::iterator jt = 
1784 1790
	    maps.find(_edge_maps[i].first);
1785 1791
	  if (jt == maps.end()) {
1786 1792
	    std::ostringstream msg;
1787 1793
	    msg << "Map not found in file: " << _edge_maps[i].first;
1788 1794
	    throw DataFormatError(msg.str().c_str());
1789 1795
	  }
1790 1796
	  map_index[i] = jt->second;
1791 1797
	}
1792 1798

	
1793 1799
	{
1794 1800
	  std::map<std::string, int>::iterator jt = maps.find("label");
1795 1801
	  if (jt != maps.end()) {
1796 1802
	    label_index = jt->second;
1797 1803
	  } else {
1798 1804
	    label_index = -1;
1799 1805
	  }
1800 1806
	}
1801 1807
	map_num = maps.size();
1802 1808
      }
1803 1809

	
1804 1810
      while (readLine() && line >> c && c != '@') {
1805 1811
	line.putback(c);
1806 1812

	
1807 1813
	std::string source_token;
1808 1814
	std::string target_token;
1809 1815

	
1810 1816
	if (!_reader_bits::readToken(line, source_token))
1811 1817
	  throw DataFormatError("Node u not found");
1812 1818

	
1813 1819
	if (!_reader_bits::readToken(line, target_token))
1814 1820
	  throw DataFormatError("Node v not found");
1815 1821
	
1816 1822
	std::vector<std::string> tokens(map_num);
1817 1823
	for (int i = 0; i < map_num; ++i) {
1818 1824
	  if (!_reader_bits::readToken(line, tokens[i])) {
1819 1825
	    std::ostringstream msg;
1820 1826
	    msg << "Column not found (" << i + 1 << ")";
1821 1827
	    throw DataFormatError(msg.str().c_str());
1822 1828
	  }
1823 1829
	}
1824 1830
	if (line >> std::ws >> c)
1825 1831
	  throw DataFormatError("Extra character on the end of line");
1826 1832
	
1827 1833
	Edge e;
1828 1834
	if (!_use_edges) {
1829 1835

	
1830 1836
          typename NodeIndex::iterator it;
1831 1837
 
1832 1838
          it = _node_index.find(source_token);
1833 1839
          if (it == _node_index.end()) {
1834 1840
            std::ostringstream msg;
1835 1841
            msg << "Item not found: " << source_token;
1836 1842
            throw DataFormatError(msg.str().c_str());
1837 1843
          }
1838 1844
          Node source = it->second;
1839 1845

	
1840 1846
          it = _node_index.find(target_token);
1841 1847
          if (it == _node_index.end()) {       
1842 1848
            std::ostringstream msg;            
1843 1849
            msg << "Item not found: " << target_token;
1844 1850
            throw DataFormatError(msg.str().c_str());
1845 1851
          }                                          
1846 1852
          Node target = it->second;                            
1847 1853

	
1848 1854
	  e = _graph.addEdge(source, target);
1849 1855
	  if (label_index != -1) 
1850 1856
	    _edge_index.insert(std::make_pair(tokens[label_index], e));
1851 1857
	} else {
1852 1858
	  if (label_index == -1) 
1853 1859
	    throw DataFormatError("Label map not found in file");
1854 1860
	  typename std::map<std::string, Edge>::iterator it =
1855 1861
	    _edge_index.find(tokens[label_index]);
1856 1862
	  if (it == _edge_index.end()) {
1857 1863
	    std::ostringstream msg;
1858 1864
	    msg << "Edge with label not found: " << tokens[label_index];
1859 1865
	    throw DataFormatError(msg.str().c_str());	    
1860 1866
	  }
1861 1867
	  e = it->second;
1862 1868
	}
1863 1869

	
1864 1870
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1865 1871
	  _edge_maps[i].second->set(e, tokens[map_index[i]]);
1866 1872
	}
1867 1873

	
1868 1874
      }
1869 1875
      if (readSuccess()) {
1870 1876
	line.putback(c);
1871 1877
      }
1872 1878
    }
1873 1879

	
1874 1880
    void readAttributes() {
1875 1881

	
1876 1882
      std::set<std::string> read_attr;
1877 1883

	
1878 1884
      char c;
1879 1885
      while (readLine() && line >> c && c != '@') {
1880 1886
	line.putback(c);
1881 1887
	
1882 1888
	std::string attr, token;
1883 1889
	if (!_reader_bits::readToken(line, attr))
1884 1890
	  throw DataFormatError("Attribute name not found");
1885 1891
	if (!_reader_bits::readToken(line, token))
1886 1892
	  throw DataFormatError("Attribute value not found");
1887 1893
	if (line >> c)
1888 1894
	  throw DataFormatError("Extra character on the end of line");	  
1889 1895

	
1890 1896
	{
1891 1897
	  std::set<std::string>::iterator it = read_attr.find(attr);
1892 1898
	  if (it != read_attr.end()) {
1893 1899
	    std::ostringstream msg;
1894 1900
	    msg << "Multiple occurence of attribute " << attr;
1895 1901
	    throw DataFormatError(msg.str().c_str());
1896 1902
	  }
1897 1903
	  read_attr.insert(attr);
1898 1904
	}
1899 1905
	
1900 1906
	{
1901 1907
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1902 1908
	  while (it != _attributes.end() && it->first == attr) {
1903 1909
	    it->second->set(token);
1904 1910
	    ++it;
1905 1911
	  }
1906 1912
	}
1907 1913

	
1908 1914
      }
1909 1915
      if (readSuccess()) {
1910 1916
	line.putback(c);
1911 1917
      }
1912 1918
      for (typename Attributes::iterator it = _attributes.begin();
1913 1919
	   it != _attributes.end(); ++it) {
1914 1920
	if (read_attr.find(it->first) == read_attr.end()) {
1915 1921
	  std::ostringstream msg;
1916 1922
	  msg << "Attribute not found in file: " << it->first;
1917 1923
	  throw DataFormatError(msg.str().c_str());
1918 1924
	}	
1919 1925
      }
1920 1926
    }
1921 1927

	
1922 1928
  public:
1923 1929

	
1924 1930
    /// \name Execution of the reader    
1925 1931
    /// @{
1926 1932

	
1927 1933
    /// \brief Start the batch processing
1928 1934
    ///
1929 1935
    /// This function starts the batch processing
1930 1936
    void run() {
1931 1937
      
1932 1938
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1933 1939
      
1934 1940
      bool nodes_done = _skip_nodes;
1935 1941
      bool edges_done = _skip_edges;
1936 1942
      bool attributes_done = false;
1937 1943

	
1938 1944
      line_num = 0;      
1939 1945
      readLine();
1940 1946
      skipSection();
1941 1947

	
1942 1948
      while (readSuccess()) {
1943 1949
	try {
1944 1950
	  char c;
1945 1951
	  std::string section, caption;
1946 1952
	  line >> c;
1947 1953
	  _reader_bits::readToken(line, section);
1948 1954
	  _reader_bits::readToken(line, caption);
1949 1955

	
1950 1956
	  if (line >> c) 
1951 1957
	    throw DataFormatError("Extra character on the end of line");
1952 1958

	
1953 1959
	  if (section == "nodes" && !nodes_done) {
1954 1960
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1955 1961
	      readNodes();
1956 1962
	      nodes_done = true;
1957 1963
	    }
1958 1964
	  } else if ((section == "edges" || section == "arcs") && 
1959 1965
		     !edges_done) {
1960 1966
	    if (_edges_caption.empty() || _edges_caption == caption) {
1961 1967
	      readEdges();
1962 1968
	      edges_done = true;
1963 1969
	    }
1964 1970
	  } else if (section == "attributes" && !attributes_done) {
1965 1971
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
1966 1972
	      readAttributes();
1967 1973
	      attributes_done = true;
1968 1974
	    }
1969 1975
	  } else {
1970 1976
	    readLine();
1971 1977
	    skipSection();
1972 1978
	  }
1973 1979
	} catch (DataFormatError& error) {
1974 1980
	  error.line(line_num);
1975 1981
	  throw;
1976 1982
	}	
1977 1983
      }
1978 1984

	
1979 1985
      if (!nodes_done) {
1980 1986
	throw DataFormatError("Section @nodes not found");
1981 1987
      }
1982 1988

	
1983 1989
      if (!edges_done) {
1984 1990
	throw DataFormatError("Section @edges not found");
1985 1991
      }
1986 1992

	
1987 1993
      if (!attributes_done && !_attributes.empty()) {
1988 1994
	throw DataFormatError("Section @attributes not found");
1989 1995
      }
1990 1996

	
1991 1997
    }
1992 1998

	
1993 1999
    /// @}
1994 2000
    
1995 2001
  };
1996 2002

	
1997 2003
  /// \brief Return a \ref GraphReader class
1998 2004
  /// 
1999 2005
  /// This function just returns a \ref GraphReader class.
2000 2006
  /// \relates GraphReader
2001 2007
  template <typename Graph>
2002 2008
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
2003 2009
    GraphReader<Graph> tmp(is, graph);
2004 2010
    return tmp;
2005 2011
  }
2006 2012

	
2007 2013
  /// \brief Return a \ref GraphReader class
2008 2014
  /// 
2009 2015
  /// This function just returns a \ref GraphReader class.
2010 2016
  /// \relates GraphReader
2011 2017
  template <typename Graph>
2012 2018
  GraphReader<Graph> graphReader(const std::string& fn, 
2013 2019
				       Graph& graph) {
2014 2020
    GraphReader<Graph> tmp(fn, graph);
2015 2021
    return tmp;
2016 2022
  }
2017 2023

	
2018 2024
  /// \brief Return a \ref GraphReader class
2019 2025
  /// 
2020 2026
  /// This function just returns a \ref GraphReader class.
2021 2027
  /// \relates GraphReader
2022 2028
  template <typename Graph>
2023 2029
  GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
2024 2030
    GraphReader<Graph> tmp(fn, graph);
2025 2031
    return tmp;
2026 2032
  }
2027 2033

	
2028 2034
  class SectionReader;
2029 2035

	
2030 2036
  SectionReader sectionReader(std::istream& is);
2031 2037
  SectionReader sectionReader(const std::string& fn);
2032 2038
  SectionReader sectionReader(const char* fn);
2033 2039
  
2034 2040
  /// \ingroup lemon_io
2035 2041
  ///
2036 2042
  /// \brief Section reader class
2037 2043
  ///
2038 2044
  /// In the \ref lgf-format "LGF" file extra sections can be placed, 
2039 2045
  /// which contain any data in arbitrary format. Such sections can be
2040 2046
  /// read with this class. A reading rule can be added to the class 
2041 2047
  /// with two different functions. With the \c sectionLines() function a
2042 2048
  /// functor can process the section line-by-line, while with the \c
2043 2049
  /// sectionStream() member the section can be read from an input
2044 2050
  /// stream.
2045 2051
  class SectionReader {
2046 2052
  private:
2047 2053
    
2048 2054
    std::istream* _is;
2049 2055
    bool local_is;
2050 2056

	
2051 2057
    typedef std::map<std::string, _reader_bits::Section*> Sections;
2052 2058
    Sections _sections;
2053 2059

	
2054 2060
    int line_num;
2055 2061
    std::istringstream line;
2056 2062

	
2057 2063
  public:
2058 2064

	
2059 2065
    /// \brief Constructor
2060 2066
    ///
2061 2067
    /// Construct a section reader, which reads from the given input
2062 2068
    /// stream.
2063 2069
    SectionReader(std::istream& is) 
2064 2070
      : _is(&is), local_is(false) {}
2065 2071

	
2066 2072
    /// \brief Constructor
2067 2073
    ///
2068 2074
    /// Construct a section reader, which reads from the given file.
2069 2075
    SectionReader(const std::string& fn) 
2070 2076
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2071 2077
    
2072 2078
    /// \brief Constructor
2073 2079
    ///
2074 2080
    /// Construct a section reader, which reads from the given file.
2075 2081
    SectionReader(const char* fn) 
2076 2082
      : _is(new std::ifstream(fn)), local_is(true) {}
2077 2083

	
2078 2084
    /// \brief Destructor
2079 2085
    ~SectionReader() {
2080 2086
      for (Sections::iterator it = _sections.begin(); 
2081 2087
	   it != _sections.end(); ++it) {
2082 2088
	delete it->second;
2083 2089
      }
2084 2090

	
2085 2091
      if (local_is) {
2086 2092
	delete _is;
2087 2093
      }
2088 2094

	
2089 2095
    }
2090 2096

	
2091 2097
  private:
2092 2098

	
2093 2099
    friend SectionReader sectionReader(std::istream& is);
2094 2100
    friend SectionReader sectionReader(const std::string& fn);
2095 2101
    friend SectionReader sectionReader(const char* fn);
2096 2102

	
2097 2103
    SectionReader(SectionReader& other) 
2098 2104
      : _is(other._is), local_is(other.local_is) {
2099 2105

	
2100 2106
      other._is = 0;
2101 2107
      other.local_is = false;
2102 2108
      
2103 2109
      _sections.swap(other._sections);
2104 2110
    }
2105 2111
    
2106 2112
    SectionReader& operator=(const SectionReader&);
2107 2113

	
2108 2114
  public:
2109 2115

	
2110 2116
    /// \name Section readers
2111 2117
    /// @{
2112 2118

	
2113 2119
    /// \brief Add a section processor with line oriented reading
2114 2120
    ///
2115 2121
    /// The first parameter is the type descriptor of the section, the
2116 2122
    /// second is a functor, which takes just one \c std::string
2117 2123
    /// parameter. At the reading process, each line of the section
2118 2124
    /// will be given to the functor object. However, the empty lines
2119 2125
    /// and the comment lines are filtered out, and the leading
2120 2126
    /// whitespaces are trimmed from each processed string.
2121 2127
    ///
2122 2128
    /// For example let's see a section, which contain several
2123 2129
    /// integers, which should be inserted into a vector.
2124 2130
    ///\code
2125 2131
    ///  @numbers
2126 2132
    ///  12 45 23
2127 2133
    ///  4
2128 2134
    ///  23 6
2129 2135
    ///\endcode
2130 2136
    ///
2131 2137
    /// The functor is implemented as a struct:
2132 2138
    ///\code
2133 2139
    ///  struct NumberSection {
2134 2140
    ///    std::vector<int>& _data;
2135 2141
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
2136 2142
    ///    void operator()(const std::string& line) {
2137 2143
    ///      std::istringstream ls(line);
2138 2144
    ///      int value;
2139 2145
    ///      while (ls >> value) _data.push_back(value);
2140 2146
    ///    }
2141 2147
    ///  };
2142 2148
    ///
2143 2149
    ///  // ...
2144 2150
    ///
2145 2151
    ///  reader.sectionLines("numbers", NumberSection(vec));  
2146 2152
    ///\endcode
2147 2153
    template <typename Functor>
2148 2154
    SectionReader& sectionLines(const std::string& type, Functor functor) {
2149 2155
      LEMON_ASSERT(!type.empty(), "Type is empty.");
2150 2156
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
2151 2157
		   "Multiple reading of section.");
2152 2158
      _sections.insert(std::make_pair(type, 
2153 2159
        new _reader_bits::LineSection<Functor>(functor)));
2154 2160
      return *this;
2155 2161
    }
2156 2162

	
2157 2163

	
2158 2164
    /// \brief Add a section processor with stream oriented reading
2159 2165
    ///
2160 2166
    /// The first parameter is the type of the section, the second is
2161 2167
    /// a functor, which takes an \c std::istream& and an \c int&
2162 2168
    /// parameter, the latter regard to the line number of stream. The
2163 2169
    /// functor can read the input while the section go on, and the
2164 2170
    /// line number should be modified accordingly.
2165 2171
    template <typename Functor>
2166 2172
    SectionReader& sectionStream(const std::string& type, Functor functor) {
2167 2173
      LEMON_ASSERT(!type.empty(), "Type is empty.");
2168 2174
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
2169 2175
		   "Multiple reading of section.");
2170 2176
      _sections.insert(std::make_pair(type, 
2171 2177
	 new _reader_bits::StreamSection<Functor>(functor)));
2172 2178
      return *this;
2173 2179
    }    
2174 2180
    
2175 2181
    /// @}
2176 2182

	
2177 2183
  private:
2178 2184

	
2179 2185
    bool readLine() {
2180 2186
      std::string str;
2181 2187
      while(++line_num, std::getline(*_is, str)) {
2182 2188
	line.clear(); line.str(str);
2183 2189
	char c;
2184 2190
	if (line >> std::ws >> c && c != '#') {
2185 2191
	  line.putback(c);
2186 2192
	  return true;
2187 2193
	}
2188 2194
      }
2189 2195
      return false;
2190 2196
    }
2191 2197

	
2192 2198
    bool readSuccess() {
2193 2199
      return static_cast<bool>(*_is);
2194 2200
    }
2195 2201
    
2196 2202
    void skipSection() {
2197 2203
      char c;
2198 2204
      while (readSuccess() && line >> c && c != '@') {
2199 2205
	readLine();
2200 2206
      }
2201 2207
      line.putback(c);
2202 2208
    }
2203 2209

	
2204 2210
  public:
2205 2211

	
2206 2212

	
2207 2213
    /// \name Execution of the reader    
2208 2214
    /// @{
2209 2215

	
2210 2216
    /// \brief Start the batch processing
2211 2217
    ///
2212 2218
    /// This function starts the batch processing.
2213 2219
    void run() {
2214 2220
      
2215 2221
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
2216 2222
      
2217 2223
      std::set<std::string> extra_sections;
2218 2224

	
2219 2225
      line_num = 0;      
2220 2226
      readLine();
2221 2227
      skipSection();
2222 2228

	
2223 2229
      while (readSuccess()) {
2224 2230
	try {
2225 2231
	  char c;
2226 2232
	  std::string section, caption;
2227 2233
	  line >> c;
2228 2234
	  _reader_bits::readToken(line, section);
2229 2235
	  _reader_bits::readToken(line, caption);
2230 2236

	
2231 2237
	  if (line >> c) 
2232 2238
	    throw DataFormatError("Extra character on the end of line");
2233 2239

	
2234 2240
	  if (extra_sections.find(section) != extra_sections.end()) {
2235 2241
	    std::ostringstream msg;
2236 2242
	    msg << "Multiple occurence of section " << section;
2237 2243
	    throw DataFormatError(msg.str().c_str());
2238 2244
	  }
2239 2245
	  Sections::iterator it = _sections.find(section);
2240 2246
	  if (it != _sections.end()) {
2241 2247
	    extra_sections.insert(section);
2242 2248
	    it->second->process(*_is, line_num);
2243 2249
	  }
2244 2250
	  readLine();
2245 2251
	  skipSection();
2246 2252
	} catch (DataFormatError& error) {
2247 2253
	  error.line(line_num);
2248 2254
	  throw;
2249 2255
	}	
2250 2256
      }
2251 2257
      for (Sections::iterator it = _sections.begin();
2252 2258
	   it != _sections.end(); ++it) {
2253 2259
	if (extra_sections.find(it->first) == extra_sections.end()) {
2254 2260
	  std::ostringstream os;
2255 2261
	  os << "Cannot find section: " << it->first;
2256 2262
	  throw DataFormatError(os.str().c_str());
2257 2263
	}
2258 2264
      }
2259 2265
    }
2260 2266

	
2261 2267
    /// @}
2262 2268
        
2263 2269
  };
2264 2270

	
2265 2271
  /// \brief Return a \ref SectionReader class
2266 2272
  /// 
2267 2273
  /// This function just returns a \ref SectionReader class.
2268 2274
  /// \relates SectionReader
2269 2275
  inline SectionReader sectionReader(std::istream& is) {
2270 2276
    SectionReader tmp(is);
2271 2277
    return tmp;
2272 2278
  }
2273 2279

	
2274 2280
  /// \brief Return a \ref SectionReader class
2275 2281
  /// 
2276 2282
  /// This function just returns a \ref SectionReader class.
2277 2283
  /// \relates SectionReader
2278 2284
  inline SectionReader sectionReader(const std::string& fn) {
2279 2285
    SectionReader tmp(fn);
2280 2286
    return tmp;
2281 2287
  }
2282 2288

	
2283 2289
  /// \brief Return a \ref SectionReader class
2284 2290
  /// 
2285 2291
  /// This function just returns a \ref SectionReader class.
2286 2292
  /// \relates SectionReader
2287 2293
  inline SectionReader sectionReader(const char* fn) {
2288 2294
    SectionReader tmp(fn);
2289 2295
    return tmp;
2290 2296
  }
2291 2297

	
2292 2298
  /// \ingroup lemon_io
2293 2299
  ///
2294 2300
  /// \brief Reader for the contents of the \ref lgf-format "LGF" file 
2295 2301
  ///
2296 2302
  /// This class can be used to read the sections, the map names and
2297 2303
  /// the attributes from a file. Usually, the Lemon programs know
2298 2304
  /// that, which type of graph, which maps and which attributes
2299 2305
  /// should be read from a file, but in general tools (like glemon)
2300 2306
  /// the contents of an LGF file should be guessed somehow. This class
2301 2307
  /// reads the graph and stores the appropriate information for
2302 2308
  /// reading the graph.
2303 2309
  ///
2304 2310
  ///\code 
2305 2311
  /// LgfContents contents("graph.lgf"); 
2306 2312
  /// contents.run();
2307 2313
  ///
2308 2314
  /// // Does it contain any node section and arc section?
2309 2315
  /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
2310 2316
  ///   std::cerr << "Failure, cannot find graph." << std::endl;
2311 2317
  ///   return -1;
2312 2318
  /// }
2313 2319
  /// std::cout << "The name of the default node section: " 
2314 2320
  ///           << contents.nodeSection(0) << std::endl;
2315 2321
  /// std::cout << "The number of the arc maps: " 
2316 2322
  ///           << contents.arcMaps(0).size() << std::endl;
2317 2323
  /// std::cout << "The name of second arc map: " 
2318 2324
  ///           << contents.arcMaps(0)[1] << std::endl;
2319 2325
  ///\endcode
2320 2326
  class LgfContents {    
2321 2327
  private:
2322 2328

	
2323 2329
    std::istream* _is;
2324 2330
    bool local_is;
2325 2331

	
2326 2332
    std::vector<std::string> _node_sections;
2327 2333
    std::vector<std::string> _edge_sections;
2328 2334
    std::vector<std::string> _attribute_sections;
2329 2335
    std::vector<std::string> _extra_sections;
2330 2336

	
2331 2337
    std::vector<bool> _arc_sections;
2332 2338

	
2333 2339
    std::vector<std::vector<std::string> > _node_maps;
2334 2340
    std::vector<std::vector<std::string> > _edge_maps;
2335 2341

	
2336 2342
    std::vector<std::vector<std::string> > _attributes;
2337 2343

	
2338 2344

	
2339 2345
    int line_num;
2340 2346
    std::istringstream line;
2341 2347
    
2342 2348
  public:
2343 2349

	
2344 2350
    /// \brief Constructor
2345 2351
    ///
2346 2352
    /// Construct an \e LGF contents reader, which reads from the given
2347 2353
    /// input stream.
2348 2354
    LgfContents(std::istream& is) 
2349 2355
      : _is(&is), local_is(false) {}
2350 2356

	
2351 2357
    /// \brief Constructor
2352 2358
    ///
2353 2359
    /// Construct an \e LGF contents reader, which reads from the given
2354 2360
    /// file.
2355 2361
    LgfContents(const std::string& fn) 
2356 2362
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2357 2363

	
2358 2364
    /// \brief Constructor
2359 2365
    ///
2360 2366
    /// Construct an \e LGF contents reader, which reads from the given
2361 2367
    /// file.
2362 2368
    LgfContents(const char* fn)
2363 2369
      : _is(new std::ifstream(fn)), local_is(true) {}
2364 2370
    
2365 2371
    /// \brief Destructor
2366 2372
    ~LgfContents() {
2367 2373
      if (local_is) delete _is;
2368 2374
    }
2369 2375

	
2370 2376
  private:
2371 2377
    
2372 2378
    LgfContents(const LgfContents&);
2373 2379
    LgfContents& operator=(const LgfContents&);
2374 2380

	
2375 2381
  public:
2376 2382

	
2377 2383

	
2378 2384
    /// \name Node sections
2379 2385
    /// @{
2380 2386

	
2381 2387
    /// \brief Gives back the number of node sections in the file.
2382 2388
    ///
2383 2389
    /// Gives back the number of node sections in the file.
2384 2390
    int nodeSectionNum() const {
2385 2391
      return _node_sections.size();
2386 2392
    }
2387 2393

	
2388 2394
    /// \brief Returns the node section name at the given position. 
2389 2395
    ///
2390 2396
    /// Returns the node section name at the given position. 
2391 2397
    const std::string& nodeSection(int i) const {
2392 2398
      return _node_sections[i];
2393 2399
    }
2394 2400

	
2395 2401
    /// \brief Gives back the node maps for the given section.
2396 2402
    ///
2397 2403
    /// Gives back the node maps for the given section.
2398 2404
    const std::vector<std::string>& nodeMapNames(int i) const {
2399 2405
      return _node_maps[i];
2400 2406
    }
2401 2407

	
2402 2408
    /// @}
2403 2409

	
2404 2410
    /// \name Arc/Edge sections 
2405 2411
    /// @{
2406 2412

	
2407 2413
    /// \brief Gives back the number of arc/edge sections in the file.
2408 2414
    ///
2409 2415
    /// Gives back the number of arc/edge sections in the file.
2410 2416
    /// \note It is synonym of \c edgeSectionNum().
2411 2417
    int arcSectionNum() const {
2412 2418
      return _edge_sections.size();
2413 2419
    }
2414 2420

	
2415 2421
    /// \brief Returns the arc/edge section name at the given position. 
2416 2422
    ///
2417 2423
    /// Returns the arc/edge section name at the given position. 
2418 2424
    /// \note It is synonym of \c edgeSection().
2419 2425
    const std::string& arcSection(int i) const {
2420 2426
      return _edge_sections[i];
2421 2427
    }
2422 2428

	
2423 2429
    /// \brief Gives back the arc/edge maps for the given section.
2424 2430
    ///
2425 2431
    /// Gives back the arc/edge maps for the given section.
2426 2432
    /// \note It is synonym of \c edgeMapNames().
2427 2433
    const std::vector<std::string>& arcMapNames(int i) const {
2428 2434
      return _edge_maps[i];
2429 2435
    }
2430 2436

	
2431 2437
    /// @}
2432 2438

	
2433 2439
    /// \name Synonyms
2434 2440
    /// @{
2435 2441

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

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

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

	
2460 2466
    /// @}
2461 2467

	
2462 2468
    /// \name Attribute sections   
2463 2469
    /// @{
2464 2470

	
2465 2471
    /// \brief Gives back the number of attribute sections in the file.
2466 2472
    ///
2467 2473
    /// Gives back the number of attribute sections in the file.
2468 2474
    int attributeSectionNum() const {
2469 2475
      return _attribute_sections.size();
2470 2476
    }
2471 2477

	
2472 2478
    /// \brief Returns the attribute section name at the given position. 
2473 2479
    ///
2474 2480
    /// Returns the attribute section name at the given position. 
2475 2481
    const std::string& attributeSectionNames(int i) const {
2476 2482
      return _attribute_sections[i];
2477 2483
    }
2478 2484

	
2479 2485
    /// \brief Gives back the attributes for the given section.
2480 2486
    ///
2481 2487
    /// Gives back the attributes for the given section.
2482 2488
    const std::vector<std::string>& attributes(int i) const {
2483 2489
      return _attributes[i];
2484 2490
    }
2485 2491

	
2486 2492
    /// @}
2487 2493

	
2488 2494
    /// \name Extra sections   
2489 2495
    /// @{
2490 2496

	
2491 2497
    /// \brief Gives back the number of extra sections in the file.
2492 2498
    ///
2493 2499
    /// Gives back the number of extra sections in the file.
2494 2500
    int extraSectionNum() const {
2495 2501
      return _extra_sections.size();
2496 2502
    }
2497 2503

	
2498 2504
    /// \brief Returns the extra section type at the given position. 
2499 2505
    ///
2500 2506
    /// Returns the section type at the given position. 
2501 2507
    const std::string& extraSection(int i) const {
2502 2508
      return _extra_sections[i];
2503 2509
    }
2504 2510

	
2505 2511
    /// @}
2506 2512

	
2507 2513
  private:
2508 2514

	
2509 2515
    bool readLine() {
2510 2516
      std::string str;
2511 2517
      while(++line_num, std::getline(*_is, str)) {
2512 2518
	line.clear(); line.str(str);
2513 2519
	char c;
2514 2520
	if (line >> std::ws >> c && c != '#') {
2515 2521
	  line.putback(c);
2516 2522
	  return true;
2517 2523
	}
2518 2524
      }
2519 2525
      return false;
2520 2526
    }
2521 2527

	
2522 2528
    bool readSuccess() {
2523 2529
      return static_cast<bool>(*_is);
2524 2530
    }
2525 2531

	
2526 2532
    void skipSection() {
2527 2533
      char c;
2528 2534
      while (readSuccess() && line >> c && c != '@') {
2529 2535
	readLine();
2530 2536
      }
2531 2537
      line.putback(c);
2532 2538
    }
2533 2539

	
2534 2540
    void readMaps(std::vector<std::string>& maps) {
2535 2541
      char c;
2536 2542
      if (!readLine() || !(line >> c) || c == '@') {
2537 2543
	if (readSuccess() && line) line.putback(c);
2538 2544
	return;
2539 2545
      }
2540 2546
      line.putback(c);
2541 2547
      std::string map;
2542 2548
      while (_reader_bits::readToken(line, map)) {
2543 2549
	maps.push_back(map);
2544 2550
      }
2545 2551
    }
2546 2552

	
2547 2553
    void readAttributes(std::vector<std::string>& attrs) {
2548 2554
      readLine();
2549 2555
      char c;
2550 2556
      while (readSuccess() && line >> c && c != '@') {
2551 2557
	line.putback(c);
2552 2558
	std::string attr;
2553 2559
	_reader_bits::readToken(line, attr);
2554 2560
	attrs.push_back(attr);
2555 2561
	readLine();
2556 2562
      }
2557 2563
      line.putback(c);
2558 2564
    }
2559 2565

	
2560 2566
  public:
2561 2567

	
2562 2568
    /// \name Execution of the contents reader    
2563 2569
    /// @{
2564 2570

	
2565 2571
    /// \brief Starts the reading
2566 2572
    ///
2567 2573
    /// This function starts the reading.
2568 2574
    void run() {
2569 2575

	
2570 2576
      readLine();
2571 2577
      skipSection();
2572 2578

	
2573 2579
      while (readSuccess()) {
2574 2580

	
2575 2581
	char c;
2576 2582
	line >> c;
2577 2583

	
2578 2584
	std::string section, caption;
2579 2585
	_reader_bits::readToken(line, section);
2580 2586
	_reader_bits::readToken(line, caption);
2581 2587

	
2582 2588
	if (section == "nodes") {
2583 2589
	  _node_sections.push_back(caption);
2584 2590
	  _node_maps.push_back(std::vector<std::string>());
2585 2591
	  readMaps(_node_maps.back());
2586 2592
	  readLine(); skipSection();
2587 2593
	} else if (section == "arcs" || section == "edges") {
2588 2594
	  _edge_sections.push_back(caption);
2589 2595
	  _arc_sections.push_back(section == "arcs");
2590 2596
	  _edge_maps.push_back(std::vector<std::string>());
2591 2597
	  readMaps(_edge_maps.back());
2592 2598
	  readLine(); skipSection();
2593 2599
	} else if (section == "attributes") {
2594 2600
	  _attribute_sections.push_back(caption);
2595 2601
	  _attributes.push_back(std::vector<std::string>());
2596 2602
	  readAttributes(_attributes.back());
2597 2603
	} else {
2598 2604
	  _extra_sections.push_back(section);
2599 2605
	  readLine(); skipSection();
2600 2606
	}
2601 2607
      }
2602 2608
    }
2603 2609

	
2604 2610
    /// @}
2605 2611
    
2606 2612
  };
2607 2613
}
2608 2614

	
2609 2615
#endif
Ignore white space 6 line context
1 1
/* -*- C++ -*-
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/graph_utils.h>
38 38

	
39 39
namespace lemon {
40 40

	
41 41
  namespace _writer_bits {
42 42

	
43 43
    template <typename Value>
44 44
    struct DefaultConverter {
45 45
      std::string operator()(const Value& value) {
46 46
	std::ostringstream os;
47 47
	os << value;
48 48
	return os.str();
49 49
      }
50 50
    };
51 51

	
52 52
    template <typename T>
53 53
    bool operator<(const T&, const T&) {
54 54
      throw DataFormatError("Label map is not comparable");
55 55
    }
56 56

	
57 57
    template <typename _Map>
58 58
    class MapLess {
59 59
    public:
60 60
      typedef _Map Map;
61 61
      typedef typename Map::Key Item;
62 62

	
63 63
    private:
64 64
      const Map& _map;
65 65
      
66 66
    public:
67 67
      MapLess(const Map& map) : _map(map) {}
68 68

	
69 69
      bool operator()(const Item& left, const Item& right) {
70 70
	return _map[left] < _map[right];
71 71
      }
72 72
    };
73 73

	
74 74
    template <typename _Graph, bool _dir, typename _Map>
75 75
    class GraphArcMapLess {
76 76
    public:
77 77
      typedef _Map Map;
78 78
      typedef _Graph Graph;
79 79
      typedef typename Graph::Edge Item;
80 80

	
81 81
    private:
82 82
      const Graph& _graph;
83 83
      const Map& _map;
84 84
      
85 85
    public:
86 86
      GraphArcMapLess(const Graph& graph, const Map& map) 
87 87
	: _graph(graph), _map(map) {}
88 88

	
89 89
      bool operator()(const Item& left, const Item& right) {
90 90
	return _map[_graph.direct(left, _dir)] < 
91 91
	  _map[_graph.direct(right, _dir)];
92 92
      }
93 93
    };
94 94

	
95 95
    template <typename _Item>    
96 96
    class MapStorageBase {
97 97
    public:
98 98
      typedef _Item Item;
99 99

	
100 100
    public:
101 101
      MapStorageBase() {}
102 102
      virtual ~MapStorageBase() {}
103 103

	
104 104
      virtual std::string get(const Item& item) = 0;
105 105
      virtual void sort(std::vector<Item>&) = 0;
106 106
    };
107 107

	
108 108
    template <typename _Item, typename _Map, 
109 109
	      typename _Converter = DefaultConverter<typename _Map::Value> >
110 110
    class MapStorage : public MapStorageBase<_Item> {
111 111
    public:
112 112
      typedef _Map Map;
113 113
      typedef _Converter Converter;
114 114
      typedef _Item Item;
115 115
      
116 116
    private:
117 117
      const Map& _map;
118 118
      Converter _converter;
119 119

	
120 120
    public:
121 121
      MapStorage(const Map& map, const Converter& converter = Converter()) 
122 122
	: _map(map), _converter(converter) {}
123 123
      virtual ~MapStorage() {}
124 124

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

	
134 134
    template <typename _Graph, bool _dir, typename _Map, 
135 135
	      typename _Converter = DefaultConverter<typename _Map::Value> >
136 136
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
137 137
    public:
138 138
      typedef _Map Map;
139 139
      typedef _Converter Converter;
140 140
      typedef _Graph Graph;
141 141
      typedef typename Graph::Edge Item;
142 142
      static const bool dir = _dir;
143 143
      
144 144
    private:
145 145
      const Graph& _graph;
146 146
      const Map& _map;
147 147
      Converter _converter;
148 148

	
149 149
    public:
150 150
      GraphArcMapStorage(const Graph& graph, const Map& map,  
151 151
			 const Converter& converter = Converter()) 
152 152
	: _graph(graph), _map(map), _converter(converter) {}
153 153
      virtual ~GraphArcMapStorage() {}
154 154

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

	
164 164
    class ValueStorageBase {
165 165
    public:
166 166
      ValueStorageBase() {}
167 167
      virtual ~ValueStorageBase() {}
168 168

	
169 169
      virtual std::string get() = 0;      
170 170
    };
171 171

	
172 172
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
173 173
    class ValueStorage : public ValueStorageBase {
174 174
    public:
175 175
      typedef _Value Value;
176 176
      typedef _Converter Converter;
177 177

	
178 178
    private:
179 179
      const Value& _value;
180 180
      Converter _converter;
181 181

	
182 182
    public:
183 183
      ValueStorage(const Value& value, const Converter& converter = Converter())
184 184
 	: _value(value), _converter(converter) {}
185 185

	
186 186
      virtual std::string get() {
187 187
	return _converter(_value);
188 188
      }
189 189
    };
190 190

	
191 191
    template <typename Value>
192 192
    struct MapLookUpConverter {
193 193
      const std::map<Value, std::string>& _map;
194 194
      
195 195
      MapLookUpConverter(const std::map<Value, std::string>& map) 
196 196
	: _map(map) {}
197 197
      
198 198
      std::string operator()(const Value& str) {
199 199
	typename std::map<Value, std::string>::const_iterator it = 
200 200
	  _map.find(str);
201 201
	if (it == _map.end()) {
202 202
	  throw DataFormatError("Item not found");
203 203
	}
204 204
	return it->second;
205 205
      }
206 206
    };
207 207

	
208 208
    template <typename Graph>
209 209
    struct GraphArcLookUpConverter {
210 210
      const Graph& _graph;
211 211
      const std::map<typename Graph::Edge, std::string>& _map;
212 212
      
213 213
      GraphArcLookUpConverter(const Graph& graph, 
214 214
			      const std::map<typename Graph::Edge, 
215 215
			                     std::string>& map) 
216 216
	: _graph(graph), _map(map) {}
217 217
      
218 218
      std::string operator()(const typename Graph::Arc& val) {
219 219
	typename std::map<typename Graph::Edge, std::string>
220 220
	  ::const_iterator it = _map.find(val);
221 221
	if (it == _map.end()) {
222 222
	  throw DataFormatError("Item not found");
223 223
	}
224 224
	return (_graph.direction(val) ? '+' : '-') + it->second;
225 225
      }
226 226
    };
227 227

	
228 228
    inline bool isWhiteSpace(char c) {
229 229
      return c == ' ' || c == '\t' || c == '\v' || 
230 230
        c == '\n' || c == '\r' || c == '\f'; 
231 231
    }
232 232

	
233 233
    inline bool isEscaped(char c) {
234 234
      return c == '\\' || c == '\"' || c == '\'' || 
235 235
	c == '\a' || c == '\b';
236 236
    }
237 237

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

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

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

	
306 306
  }
307 307

	
308 308
  template <typename Digraph>
309 309
  class DigraphWriter;
310 310

	
311 311
  template <typename Digraph>
312 312
  DigraphWriter<Digraph> digraphWriter(std::ostream& os, 
313 313
				       const Digraph& digraph);
314 314

	
315 315
  template <typename Digraph>
316 316
  DigraphWriter<Digraph> digraphWriter(const std::string& fn, 
317 317
				       const Digraph& digraph);
318 318

	
319 319
  template <typename Digraph>
320 320
  DigraphWriter<Digraph> digraphWriter(const char *fn, 
321 321
				       const Digraph& digraph);
322 322
  
323 323
  /// \ingroup lemon_io
324 324
  ///  
325 325
  /// \brief \ref lgf-format "LGF" writer for directed graphs
326 326
  ///
327 327
  /// This utility writes an \ref lgf-format "LGF" file.
328 328
  ///
329 329
  /// The writing method does a batch processing. The user creates a
330 330
  /// writer object, then various writing rules can be added to the
331 331
  /// writer, and eventually the writing is executed with the \c run()
332 332
  /// member function. A map writing rule can be added to the writer
333 333
  /// with the \c nodeMap() or \c arcMap() members. An optional
334 334
  /// converter parameter can also be added as a standard functor
335 335
  /// converting from the value type of the map to \c std::string. If it
336 336
  /// is set, it will determine how the value type of the map is written to
337 337
  /// the output stream. If the functor is not set, then a default
338 338
  /// conversion will be used. The \c attribute(), \c node() and \c
339 339
  /// arc() functions are used to add attribute writing rules.
340 340
  ///
341 341
  ///\code
342 342
  /// DigraphWriter<Digraph>(std::cout, digraph).
343 343
  ///   nodeMap("coordinates", coord_map).
344 344
  ///   nodeMap("size", size).
345 345
  ///   nodeMap("title", title).
346 346
  ///   arcMap("capacity", cap_map).
347 347
  ///   node("source", src).
348 348
  ///   node("target", trg).
349 349
  ///   attribute("caption", caption).
350 350
  ///   run();
351 351
  ///\endcode
352 352
  ///
353 353
  ///
354 354
  /// By default, the writer does not write additional captions to the
355 355
  /// sections, but they can be give as an optional parameter of
356 356
  /// the \c nodes(), \c arcs() or \c
357 357
  /// attributes() functions.
358 358
  ///
359 359
  /// The \c skipNodes() and \c skipArcs() functions forbid the
360 360
  /// writing of the sections. If two arc sections should be written
361 361
  /// to the output, it can be done in two passes, the first pass
362 362
  /// writes the node section and the first arc section, then the
363 363
  /// second pass skips the node section and writes just the arc
364 364
  /// section to the stream. The output stream can be retrieved with
365 365
  /// the \c ostream() function, hence the second pass can append its
366 366
  /// output to the output of the first pass.
367 367
  template <typename _Digraph>
368 368
  class DigraphWriter {
369 369
  public:
370 370

	
371 371
    typedef _Digraph Digraph;
372 372
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
373 373
    
374 374
  private:
375 375

	
376 376

	
377 377
    std::ostream* _os;
378 378
    bool local_os;
379 379

	
380 380
    const Digraph& _digraph;
381 381

	
382 382
    std::string _nodes_caption;
383 383
    std::string _arcs_caption;
384 384
    std::string _attributes_caption;
385 385
    
386 386
    typedef std::map<Node, std::string> NodeIndex;
387 387
    NodeIndex _node_index;
388 388
    typedef std::map<Arc, std::string> ArcIndex;
389 389
    ArcIndex _arc_index;
390 390

	
391 391
    typedef std::vector<std::pair<std::string, 
392 392
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
393 393
    NodeMaps _node_maps; 
394 394

	
395 395
    typedef std::vector<std::pair<std::string, 
396 396
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
397 397
    ArcMaps _arc_maps;
398 398

	
399 399
    typedef std::vector<std::pair<std::string, 
400 400
      _writer_bits::ValueStorageBase*> > Attributes;
401 401
    Attributes _attributes;
402 402

	
403 403
    bool _skip_nodes;
404 404
    bool _skip_arcs;
405 405

	
406 406
  public:
407 407

	
408 408
    /// \brief Constructor
409 409
    ///
410 410
    /// Construct a directed graph writer, which writes to the given
411 411
    /// output stream.
412 412
    DigraphWriter(std::ostream& is, const Digraph& digraph) 
413 413
      : _os(&is), local_os(false), _digraph(digraph),
414 414
	_skip_nodes(false), _skip_arcs(false) {}
415 415

	
416 416
    /// \brief Constructor
417 417
    ///
418 418
    /// Construct a directed graph writer, which writes to the given
419 419
    /// output file.
420 420
    DigraphWriter(const std::string& fn, const Digraph& digraph) 
421 421
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
422 422
	_skip_nodes(false), _skip_arcs(false) {}
423 423

	
424 424
    /// \brief Constructor
425 425
    ///
426 426
    /// Construct a directed graph writer, which writes to the given
427 427
    /// output file.
428 428
    DigraphWriter(const char* fn, const Digraph& digraph) 
429 429
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
430 430
	_skip_nodes(false), _skip_arcs(false) {}
431 431

	
432 432
    /// \brief Destructor
433 433
    ~DigraphWriter() {
434 434
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
435 435
	   it != _node_maps.end(); ++it) {
436 436
	delete it->second;
437 437
      }
438 438

	
439 439
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
440 440
	   it != _arc_maps.end(); ++it) {
441 441
	delete it->second;
442 442
      }
443 443

	
444 444
      for (typename Attributes::iterator it = _attributes.begin(); 
445 445
	   it != _attributes.end(); ++it) {
446 446
	delete it->second;
447 447
      }
448 448

	
449 449
      if (local_os) {
450 450
	delete _os;
451 451
      }
452 452
    }
453 453

	
454 454
  private:
455 455

	
456 456
    friend DigraphWriter<Digraph> digraphWriter<>(std::ostream& os, 
457 457
						  const Digraph& digraph);
458 458
    friend DigraphWriter<Digraph> digraphWriter<>(const std::string& fn, 
459 459
						  const Digraph& digraph);   
460 460
    friend DigraphWriter<Digraph> digraphWriter<>(const char *fn, 
461 461
						  const Digraph& digraph);
462 462

	
463 463
    DigraphWriter(DigraphWriter& other) 
464 464
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
465 465
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
466 466

	
467 467
      other._os = 0;
468 468
      other.local_os = false;
469 469

	
470 470
      _node_index.swap(other._node_index);
471 471
      _arc_index.swap(other._arc_index);
472 472

	
473 473
      _node_maps.swap(other._node_maps);
474 474
      _arc_maps.swap(other._arc_maps);
475 475
      _attributes.swap(other._attributes);
476 476

	
477 477
      _nodes_caption = other._nodes_caption;
478 478
      _arcs_caption = other._arcs_caption;
479 479
      _attributes_caption = other._attributes_caption;
480 480
    }
481 481
    
482 482
    DigraphWriter& operator=(const DigraphWriter&);
483 483

	
484 484
  public:
485 485

	
486 486
    /// \name Writing rules
487 487
    /// @{
488 488
    
489 489
    /// \brief Node map writing rule
490 490
    ///
491 491
    /// Add a node map writing rule to the writer.
492 492
    template <typename Map>
493 493
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
494 494
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
495 495
      _writer_bits::MapStorageBase<Node>* storage = 
496 496
	new _writer_bits::MapStorage<Node, Map>(map);
497 497
      _node_maps.push_back(std::make_pair(caption, storage));
498 498
      return *this;
499 499
    }
500 500

	
501 501
    /// \brief Node map writing rule
502 502
    ///
503 503
    /// Add a node map writing rule with specialized converter to the
504 504
    /// writer.
505 505
    template <typename Map, typename Converter>
506 506
    DigraphWriter& nodeMap(const std::string& caption, const Map& map, 
507 507
			   const Converter& converter = Converter()) {
508 508
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
509 509
      _writer_bits::MapStorageBase<Node>* storage = 
510 510
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
511 511
      _node_maps.push_back(std::make_pair(caption, storage));
512 512
      return *this;
513 513
    }
514 514

	
515 515
    /// \brief Arc map writing rule
516 516
    ///
517 517
    /// Add an arc map writing rule to the writer.
518 518
    template <typename Map>
519 519
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
520 520
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
521 521
      _writer_bits::MapStorageBase<Arc>* storage = 
522 522
	new _writer_bits::MapStorage<Arc, Map>(map);
523 523
      _arc_maps.push_back(std::make_pair(caption, storage));
524 524
      return *this;
525 525
    }
526 526

	
527 527
    /// \brief Arc map writing rule
528 528
    ///
529 529
    /// Add an arc map writing rule with specialized converter to the
530 530
    /// writer.
531 531
    template <typename Map, typename Converter>
532 532
    DigraphWriter& arcMap(const std::string& caption, const Map& map, 
533 533
			  const Converter& converter = Converter()) {
534 534
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
535 535
      _writer_bits::MapStorageBase<Arc>* storage = 
536 536
	new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
537 537
      _arc_maps.push_back(std::make_pair(caption, storage));
538 538
      return *this;
539 539
    }
540 540

	
541 541
    /// \brief Attribute writing rule
542 542
    ///
543 543
    /// Add an attribute writing rule to the writer.
544 544
    template <typename Value>
545 545
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
546 546
      _writer_bits::ValueStorageBase* storage = 
547 547
	new _writer_bits::ValueStorage<Value>(value);
548 548
      _attributes.push_back(std::make_pair(caption, storage));
549 549
      return *this;
550 550
    }
551 551

	
552 552
    /// \brief Attribute writing rule
553 553
    ///
554 554
    /// Add an attribute writing rule with specialized converter to the
555 555
    /// writer.
556 556
    template <typename Value, typename Converter>
557 557
    DigraphWriter& attribute(const std::string& caption, const Value& value, 
558 558
			     const Converter& converter = Converter()) {
559 559
      _writer_bits::ValueStorageBase* storage = 
560 560
	new _writer_bits::ValueStorage<Value, Converter>(value, converter);
561 561
      _attributes.push_back(std::make_pair(caption, storage));
562 562
      return *this;
563 563
    }
564 564

	
565 565
    /// \brief Node writing rule
566 566
    ///
567 567
    /// Add a node writing rule to the writer.
568 568
    DigraphWriter& node(const std::string& caption, const Node& node) {
569 569
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
570 570
      Converter converter(_node_index);
571 571
      _writer_bits::ValueStorageBase* storage = 
572 572
	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
573 573
      _attributes.push_back(std::make_pair(caption, storage));
574 574
      return *this;
575 575
    }
576 576

	
577 577
    /// \brief Arc writing rule
578 578
    ///
579 579
    /// Add an arc writing rule to writer.
580 580
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
581 581
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
582 582
      Converter converter(_arc_index);
583 583
      _writer_bits::ValueStorageBase* storage = 
584 584
	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
585 585
      _attributes.push_back(std::make_pair(caption, storage));
586 586
      return *this;
587 587
    }
588 588

	
589 589
    /// \name Section captions
590 590
    /// @{
591 591

	
592 592
    /// \brief Add an additional caption to the \c \@nodes section
593 593
    ///
594 594
    /// Add an additional caption to the \c \@nodes section.
595 595
    DigraphWriter& nodes(const std::string& caption) {
596 596
      _nodes_caption = caption;
597 597
      return *this;
598 598
    }
599 599

	
600 600
    /// \brief Add an additional caption to the \c \@arcs section
601 601
    ///
602 602
    /// Add an additional caption to the \c \@arcs section.
603 603
    DigraphWriter& arcs(const std::string& caption) {
604 604
      _arcs_caption = caption;
605 605
      return *this;
606 606
    }
607 607

	
608 608
    /// \brief Add an additional caption to the \c \@attributes section
609 609
    ///
610 610
    /// Add an additional caption to the \c \@attributes section.
611 611
    DigraphWriter& attributes(const std::string& caption) {
612 612
      _attributes_caption = caption;
613 613
      return *this;
614 614
    }
615 615

	
616 616
    /// \name Skipping section
617 617
    /// @{
618 618

	
619 619
    /// \brief Skip writing the node set
620 620
    ///
621 621
    /// The \c \@nodes section will not be written to the stream.
622 622
    DigraphWriter& skipNodes() {
623 623
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
624 624
      _skip_nodes = true;
625 625
      return *this;
626 626
    }
627 627

	
628 628
    /// \brief Skip writing arc set
629 629
    ///
630 630
    /// The \c \@arcs section will not be written to the stream.
631 631
    DigraphWriter& skipArcs() {
632 632
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
633 633
      _skip_arcs = true;
634 634
      return *this;
635 635
    }
636 636

	
637 637
    /// @}
638 638

	
639 639
  private:
640 640

	
641 641
    void writeNodes() {
642 642
      _writer_bits::MapStorageBase<Node>* label = 0;
643 643
      for (typename NodeMaps::iterator it = _node_maps.begin();
644 644
	   it != _node_maps.end(); ++it) {
645 645
        if (it->first == "label") {
646 646
	  label = it->second;
647 647
	  break;
648 648
	}
649 649
      }
650 650

	
651 651
      *_os << "@nodes";
652 652
      if (!_nodes_caption.empty()) {
653 653
	_writer_bits::writeToken(*_os << ' ', _nodes_caption);
654 654
      }
655 655
      *_os << std::endl;
656 656

	
657 657
      if (label == 0) {
658 658
	*_os << "label" << '\t';
659 659
      }
660 660
      for (typename NodeMaps::iterator it = _node_maps.begin();
661 661
	   it != _node_maps.end(); ++it) {
662 662
	_writer_bits::writeToken(*_os, it->first) << '\t';
663 663
      }
664 664
      *_os << std::endl;
665 665

	
666 666
      std::vector<Node> nodes;
667 667
      for (NodeIt n(_digraph); n != INVALID; ++n) {
668 668
	nodes.push_back(n);
669 669
      }
670 670
      
671 671
      if (label == 0) {
672 672
	IdMap<Digraph, Node> id_map(_digraph);
673 673
	_writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
674 674
	std::sort(nodes.begin(), nodes.end(), id_less);
675 675
      } else {
676 676
	label->sort(nodes);
677 677
      }
678 678

	
679 679
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
680 680
	Node n = nodes[i];
681 681
	if (label == 0) {
682 682
	  std::ostringstream os;
683 683
	  os << _digraph.id(n);
684 684
	  _writer_bits::writeToken(*_os, os.str());
685 685
	  *_os << '\t';
686 686
	  _node_index.insert(std::make_pair(n, os.str()));
687 687
	}
688 688
	for (typename NodeMaps::iterator it = _node_maps.begin();
689 689
	     it != _node_maps.end(); ++it) {
690 690
	  std::string value = it->second->get(n);
691 691
	  _writer_bits::writeToken(*_os, value);
692 692
	  if (it->first == "label") {
693 693
	    _node_index.insert(std::make_pair(n, value));
694 694
	  }
695 695
	  *_os << '\t';
696 696
	}
697 697
	*_os << std::endl;
698 698
      }
699 699
    }
700 700

	
701 701
    void createNodeIndex() {
702 702
      _writer_bits::MapStorageBase<Node>* label = 0;
703 703
      for (typename NodeMaps::iterator it = _node_maps.begin();
704 704
	   it != _node_maps.end(); ++it) {
705 705
        if (it->first == "label") {
706 706
	  label = it->second;
707 707
	  break;
708 708
	}
709 709
      }
710 710

	
711 711
      if (label == 0) {
712 712
	for (NodeIt n(_digraph); n != INVALID; ++n) {
713 713
	  std::ostringstream os;
714 714
	  os << _digraph.id(n);
715 715
	  _node_index.insert(std::make_pair(n, os.str()));	  
716 716
	}	
717 717
      } else {
718 718
	for (NodeIt n(_digraph); n != INVALID; ++n) {
719 719
	  std::string value = label->get(n);	  
720 720
	  _node_index.insert(std::make_pair(n, value));
721 721
	}
722 722
      }
723 723
    }
724 724

	
725 725
    void writeArcs() {
726 726
      _writer_bits::MapStorageBase<Arc>* label = 0;
727 727
      for (typename ArcMaps::iterator it = _arc_maps.begin();
728 728
	   it != _arc_maps.end(); ++it) {
729 729
        if (it->first == "label") {
730 730
	  label = it->second;
731 731
	  break;
732 732
	}
733 733
      }
734 734

	
735 735
      *_os << "@arcs";
736 736
      if (!_arcs_caption.empty()) {
737 737
	_writer_bits::writeToken(*_os << ' ', _arcs_caption);
738 738
      }
739 739
      *_os << std::endl;
740 740

	
741 741
      *_os << '\t' << '\t';
742 742
      if (label == 0) {
743 743
	*_os << "label" << '\t';
744 744
      }
745 745
      for (typename ArcMaps::iterator it = _arc_maps.begin();
746 746
	   it != _arc_maps.end(); ++it) {
747 747
	_writer_bits::writeToken(*_os, it->first) << '\t';
748 748
      }
749 749
      *_os << std::endl;
750 750

	
751 751
      std::vector<Arc> arcs;
752 752
      for (ArcIt n(_digraph); n != INVALID; ++n) {
753 753
	arcs.push_back(n);
754 754
      }
755 755
      
756 756
      if (label == 0) {
757 757
	IdMap<Digraph, Arc> id_map(_digraph);
758 758
	_writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
759 759
	std::sort(arcs.begin(), arcs.end(), id_less);
760 760
      } else {
761 761
	label->sort(arcs);
762 762
      }
763 763

	
764 764
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
765 765
	Arc a = arcs[i];
766 766
	_writer_bits::writeToken(*_os, _node_index.
767 767
				 find(_digraph.source(a))->second);
768 768
	*_os << '\t';
769 769
	_writer_bits::writeToken(*_os, _node_index.
770 770
				 find(_digraph.target(a))->second);
771 771
	*_os << '\t';
772 772
	if (label == 0) {
773 773
	  std::ostringstream os;
774 774
	  os << _digraph.id(a);
775 775
	  _writer_bits::writeToken(*_os, os.str());
776 776
	  *_os << '\t';
777 777
	  _arc_index.insert(std::make_pair(a, os.str()));
778 778
	}
779 779
	for (typename ArcMaps::iterator it = _arc_maps.begin();
780 780
	     it != _arc_maps.end(); ++it) {
781 781
	  std::string value = it->second->get(a);
782 782
	  _writer_bits::writeToken(*_os, value);
783 783
	  if (it->first == "label") {
784 784
	    _arc_index.insert(std::make_pair(a, value));
785 785
	  }
786 786
	  *_os << '\t';
787 787
	}
788 788
	*_os << std::endl;
789 789
      }
790 790
    }
791 791

	
792 792
    void createArcIndex() {
793 793
      _writer_bits::MapStorageBase<Arc>* label = 0;
794 794
      for (typename ArcMaps::iterator it = _arc_maps.begin();
795 795
	   it != _arc_maps.end(); ++it) {
796 796
        if (it->first == "label") {
797 797
	  label = it->second;
798 798
	  break;
799 799
	}
800 800
      }
801 801

	
802 802
      if (label == 0) {
803 803
	for (ArcIt a(_digraph); a != INVALID; ++a) {
804 804
	  std::ostringstream os;
805 805
	  os << _digraph.id(a);
806 806
	  _arc_index.insert(std::make_pair(a, os.str()));	  
807 807
	}	
808 808
      } else {
809 809
	for (ArcIt a(_digraph); a != INVALID; ++a) {
810 810
	  std::string value = label->get(a);	  
811 811
	  _arc_index.insert(std::make_pair(a, value));
812 812
	}
813 813
      }
814 814
    }
815 815

	
816 816
    void writeAttributes() {
817 817
      if (_attributes.empty()) return;
818 818
      *_os << "@attributes";
819 819
      if (!_attributes_caption.empty()) {
820 820
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
821 821
      }
822 822
      *_os << std::endl;
823 823
      for (typename Attributes::iterator it = _attributes.begin();
824 824
	   it != _attributes.end(); ++it) {
825 825
	_writer_bits::writeToken(*_os, it->first) << ' ';
826 826
	_writer_bits::writeToken(*_os, it->second->get());
827 827
	*_os << std::endl;
828 828
      }
829 829
    }
830 830
    
831 831
  public:
832 832
    
833 833
    /// \name Execution of the writer    
834 834
    /// @{
835 835

	
836 836
    /// \brief Start the batch processing
837 837
    ///
838 838
    /// This function starts the batch processing.
839 839
    void run() {
840 840
      if (!_skip_nodes) {
841 841
	writeNodes();
842 842
      } else {
843 843
	createNodeIndex();
844 844
      }
845 845
      if (!_skip_arcs) {      
846 846
	writeArcs();
847 847
      } else {
848 848
	createArcIndex();
849 849
      }
850 850
      writeAttributes();
851 851
    }
852 852

	
853 853
    /// \brief Give back the stream of the writer
854 854
    ///
855 855
    /// Give back the stream of the writer.
856 856
    std::ostream& ostream() {
857 857
      return *_os;
858 858
    }
859 859

	
860 860
    /// @}
861 861
  };
862 862

	
863 863
  /// \brief Return a \ref DigraphWriter class
864 864
  /// 
865 865
  /// This function just returns a \ref DigraphWriter class.
866 866
  /// \relates DigraphWriter
867 867
  template <typename Digraph>
868 868
  DigraphWriter<Digraph> digraphWriter(std::ostream& os, 
869 869
				       const Digraph& digraph) {
870 870
    DigraphWriter<Digraph> tmp(os, digraph);
871 871
    return tmp;
872 872
  }
873 873

	
874 874
  /// \brief Return a \ref DigraphWriter class
875 875
  /// 
876 876
  /// This function just returns a \ref DigraphWriter class.
877 877
  /// \relates DigraphWriter
878 878
  template <typename Digraph>
879 879
  DigraphWriter<Digraph> digraphWriter(const std::string& fn, 
880 880
				       const Digraph& digraph) {
881 881
    DigraphWriter<Digraph> tmp(fn, digraph);
882 882
    return tmp;
883 883
  }
884 884

	
885 885
  /// \brief Return a \ref DigraphWriter class
886 886
  /// 
887 887
  /// This function just returns a \ref DigraphWriter class.
888 888
  /// \relates DigraphWriter
889 889
  template <typename Digraph>
890 890
  DigraphWriter<Digraph> digraphWriter(const char* fn, 
891 891
				       const Digraph& digraph) {
892 892
    DigraphWriter<Digraph> tmp(fn, digraph);
893 893
    return tmp;
894 894
  }
895 895

	
896 896
  template <typename Graph>
897 897
  class GraphWriter;
898 898

	
899 899
  template <typename Graph>
900 900
  GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph);    
901 901

	
902 902
  template <typename Graph>
903 903
  GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph);   
904 904

	
905 905
  template <typename Graph>
906 906
  GraphWriter<Graph> graphWriter(const char *fn, const Graph& graph);    
907 907

	
908 908
  /// \ingroup lemon_io
909 909
  ///  
910 910
  /// \brief \ref lgf-format "LGF" writer for directed graphs
911 911
  ///
912 912
  /// This utility writes an \ref lgf-format "LGF" file.
913 913
  ///
914 914
  /// It can be used almost the same way as \c DigraphWriter.
915 915
  /// The only difference is that this class can handle edges and
916 916
  /// edge maps as well as arcs and arc maps.
917
  ///
918
  /// The arc maps are written into the file as two columns, the
919
  /// caption of the columns are the name of the map prefixed with \c
920
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
921
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
922
  /// of the arc) and the label of corresponding edge.
917 923
  template <typename _Graph>
918 924
  class GraphWriter {
919 925
  public:
920 926

	
921 927
    typedef _Graph Graph;
922 928
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
923 929
    
924 930
  private:
925 931

	
926 932

	
927 933
    std::ostream* _os;
928 934
    bool local_os;
929 935

	
930 936
    Graph& _graph;
931 937

	
932 938
    std::string _nodes_caption;
933 939
    std::string _edges_caption;
934 940
    std::string _attributes_caption;
935 941
    
936 942
    typedef std::map<Node, std::string> NodeIndex;
937 943
    NodeIndex _node_index;
938 944
    typedef std::map<Edge, std::string> EdgeIndex;
939 945
    EdgeIndex _edge_index;
940 946

	
941 947
    typedef std::vector<std::pair<std::string, 
942 948
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
943 949
    NodeMaps _node_maps; 
944 950

	
945 951
    typedef std::vector<std::pair<std::string, 
946 952
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
947 953
    EdgeMaps _edge_maps;
948 954

	
949 955
    typedef std::vector<std::pair<std::string, 
950 956
      _writer_bits::ValueStorageBase*> > Attributes;
951 957
    Attributes _attributes;
952 958

	
953 959
    bool _skip_nodes;
954 960
    bool _skip_edges;
955 961

	
956 962
  public:
957 963

	
958 964
    /// \brief Constructor
959 965
    ///
960 966
    /// Construct a directed graph writer, which writes to the given
961 967
    /// output stream.
962 968
    GraphWriter(std::ostream& is, const Graph& graph) 
963 969
      : _os(&is), local_os(false), _graph(graph),
964 970
	_skip_nodes(false), _skip_edges(false) {}
965 971

	
966 972
    /// \brief Constructor
967 973
    ///
968 974
    /// Construct a directed graph writer, which writes to the given
969 975
    /// output file.
970 976
    GraphWriter(const std::string& fn, const Graph& graph) 
971 977
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
972 978
	_skip_nodes(false), _skip_edges(false) {}
973 979

	
974 980
    /// \brief Constructor
975 981
    ///
976 982
    /// Construct a directed graph writer, which writes to the given
977 983
    /// output file.
978 984
    GraphWriter(const char* fn, const Graph& graph) 
979 985
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
980 986
	_skip_nodes(false), _skip_edges(false) {}
981 987

	
982 988
    /// \brief Destructor
983 989
    ~GraphWriter() {
984 990
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
985 991
	   it != _node_maps.end(); ++it) {
986 992
	delete it->second;
987 993
      }
988 994

	
989 995
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
990 996
	   it != _edge_maps.end(); ++it) {
991 997
	delete it->second;
992 998
      }
993 999

	
994 1000
      for (typename Attributes::iterator it = _attributes.begin(); 
995 1001
	   it != _attributes.end(); ++it) {
996 1002
	delete it->second;
997 1003
      }
998 1004

	
999 1005
      if (local_os) {
1000 1006
	delete _os;
1001 1007
      }
1002 1008
    }
1003 1009
    
1004 1010
  private:
1005 1011

	
1006 1012
    friend GraphWriter<Graph> graphWriter<>(std::ostream& os, 
1007 1013
					    const Graph& graph);    
1008 1014
    friend GraphWriter<Graph> graphWriter<>(const std::string& fn, 
1009 1015
					    const Graph& graph);   
1010 1016
    friend GraphWriter<Graph> graphWriter<>(const char *fn, 
1011 1017
					    const Graph& graph);    
1012 1018

	
1013 1019
    GraphWriter(GraphWriter& other) 
1014 1020
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
1015 1021
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1016 1022

	
1017 1023
      other._os = 0;
1018 1024
      other.local_os = false;
1019 1025

	
1020 1026
      _node_index.swap(other._node_index);
1021 1027
      _edge_index.swap(other._edge_index);
1022 1028

	
1023 1029
      _node_maps.swap(other._node_maps);
1024 1030
      _edge_maps.swap(other._edge_maps);
1025 1031
      _attributes.swap(other._attributes);
1026 1032

	
1027 1033
      _nodes_caption = other._nodes_caption;
1028 1034
      _edges_caption = other._edges_caption;
1029 1035
      _attributes_caption = other._attributes_caption;
1030 1036
    }
1031 1037

	
1032 1038
    GraphWriter& operator=(const GraphWriter&);
1033 1039

	
1034 1040
  public:
1035 1041

	
1036 1042
    /// \name Writing rules
1037 1043
    /// @{
1038 1044
    
1039 1045
    /// \brief Node map writing rule
1040 1046
    ///
1041 1047
    /// Add a node map writing rule to the writer.
1042 1048
    template <typename Map>
1043 1049
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1044 1050
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1045 1051
      _writer_bits::MapStorageBase<Node>* storage = 
1046 1052
	new _writer_bits::MapStorage<Node, Map>(map);
1047 1053
      _node_maps.push_back(std::make_pair(caption, storage));
1048 1054
      return *this;
1049 1055
    }
1050 1056

	
1051 1057
    /// \brief Node map writing rule
1052 1058
    ///
1053 1059
    /// Add a node map writing rule with specialized converter to the
1054 1060
    /// writer.
1055 1061
    template <typename Map, typename Converter>
1056 1062
    GraphWriter& nodeMap(const std::string& caption, const Map& map, 
1057 1063
			   const Converter& converter = Converter()) {
1058 1064
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1059 1065
      _writer_bits::MapStorageBase<Node>* storage = 
1060 1066
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1061 1067
      _node_maps.push_back(std::make_pair(caption, storage));
1062 1068
      return *this;
1063 1069
    }
1064 1070

	
1065 1071
    /// \brief Edge map writing rule
1066 1072
    ///
1067 1073
    /// Add an edge map writing rule to the writer.
1068 1074
    template <typename Map>
1069 1075
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1070 1076
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1071 1077
      _writer_bits::MapStorageBase<Edge>* storage = 
1072 1078
	new _writer_bits::MapStorage<Edge, Map>(map);
1073 1079
      _edge_maps.push_back(std::make_pair(caption, storage));
1074 1080
      return *this;
1075 1081
    }
1076 1082

	
1077 1083
    /// \brief Edge map writing rule
1078 1084
    ///
1079 1085
    /// Add an edge map writing rule with specialized converter to the
1080 1086
    /// writer.
1081 1087
    template <typename Map, typename Converter>
1082 1088
    GraphWriter& edgeMap(const std::string& caption, const Map& map, 
1083 1089
			  const Converter& converter = Converter()) {
1084 1090
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1085 1091
      _writer_bits::MapStorageBase<Edge>* storage = 
1086 1092
	new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1087 1093
      _edge_maps.push_back(std::make_pair(caption, storage));
1088 1094
      return *this;
1089 1095
    }
1090 1096

	
1091 1097
    /// \brief Arc map writing rule
1092 1098
    ///
1093 1099
    /// Add an arc map writing rule to the writer.
1094 1100
    template <typename Map>
1095 1101
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
1096 1102
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1097 1103
      _writer_bits::MapStorageBase<Edge>* forward_storage = 
1098 1104
	new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1099 1105
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1100 1106
      _writer_bits::MapStorageBase<Edge>* backward_storage = 
1101 1107
	new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1102 1108
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1103 1109
      return *this;
1104 1110
    }
1105 1111

	
1106 1112
    /// \brief Arc map writing rule
1107 1113
    ///
1108 1114
    /// Add an arc map writing rule with specialized converter to the
1109 1115
    /// writer.
1110 1116
    template <typename Map, typename Converter>
1111 1117
    GraphWriter& arcMap(const std::string& caption, const Map& map, 
1112 1118
			  const Converter& converter = Converter()) {
1113 1119
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1114 1120
      _writer_bits::MapStorageBase<Edge>* forward_storage = 
1115 1121
	new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1116 1122
	(_graph, map, converter);
1117 1123
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1118 1124
      _writer_bits::MapStorageBase<Edge>* backward_storage = 
1119 1125
	new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1120 1126
	(_graph, map, converter);
1121 1127
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1122 1128
      return *this;
1123 1129
    }
1124 1130

	
1125 1131
    /// \brief Attribute writing rule
1126 1132
    ///
1127 1133
    /// Add an attribute writing rule to the writer.
1128 1134
    template <typename Value>
1129 1135
    GraphWriter& attribute(const std::string& caption, const Value& value) {
1130 1136
      _writer_bits::ValueStorageBase* storage = 
1131 1137
	new _writer_bits::ValueStorage<Value>(value);
1132 1138
      _attributes.push_back(std::make_pair(caption, storage));
1133 1139
      return *this;
1134 1140
    }
1135 1141

	
1136 1142
    /// \brief Attribute writing rule
1137 1143
    ///
1138 1144
    /// Add an attribute writing rule with specialized converter to the
1139 1145
    /// writer.
1140 1146
    template <typename Value, typename Converter>
1141 1147
    GraphWriter& attribute(const std::string& caption, const Value& value, 
1142 1148
			     const Converter& converter = Converter()) {
1143 1149
      _writer_bits::ValueStorageBase* storage = 
1144 1150
	new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1145 1151
      _attributes.push_back(std::make_pair(caption, storage));
1146 1152
      return *this;
1147 1153
    }
1148 1154

	
1149 1155
    /// \brief Node writing rule
1150 1156
    ///
1151 1157
    /// Add a node writing rule to the writer.
1152 1158
    GraphWriter& node(const std::string& caption, const Node& node) {
1153 1159
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
1154 1160
      Converter converter(_node_index);
1155 1161
      _writer_bits::ValueStorageBase* storage = 
1156 1162
	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1157 1163
      _attributes.push_back(std::make_pair(caption, storage));
1158 1164
      return *this;
1159 1165
    }
1160 1166

	
1161 1167
    /// \brief Edge writing rule
1162 1168
    ///
1163 1169
    /// Add an edge writing rule to writer.
1164 1170
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
1165 1171
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1166 1172
      Converter converter(_edge_index);
1167 1173
      _writer_bits::ValueStorageBase* storage = 
1168 1174
	new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1169 1175
      _attributes.push_back(std::make_pair(caption, storage));
1170 1176
      return *this;
1171 1177
    }
1172 1178

	
1173 1179
    /// \brief Arc writing rule
1174 1180
    ///
1175 1181
    /// Add an arc writing rule to writer.
1176 1182
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
1177 1183
      typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1178 1184
      Converter converter(_graph, _edge_index);
1179 1185
      _writer_bits::ValueStorageBase* storage = 
1180 1186
	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1181 1187
      _attributes.push_back(std::make_pair(caption, storage));
1182 1188
      return *this;
1183 1189
    }
1184 1190

	
1185 1191
    /// \name Section captions
1186 1192
    /// @{
1187 1193

	
1188 1194
    /// \brief Add an additional caption to the \c \@nodes section
1189 1195
    ///
1190 1196
    /// Add an additional caption to the \c \@nodes section.
1191 1197
    GraphWriter& nodes(const std::string& caption) {
1192 1198
      _nodes_caption = caption;
1193 1199
      return *this;
1194 1200
    }
1195 1201

	
1196 1202
    /// \brief Add an additional caption to the \c \@arcs section
1197 1203
    ///
1198 1204
    /// Add an additional caption to the \c \@arcs section.
1199 1205
    GraphWriter& edges(const std::string& caption) {
1200 1206
      _edges_caption = caption;
1201 1207
      return *this;
1202 1208
    }
1203 1209

	
1204 1210
    /// \brief Add an additional caption to the \c \@attributes section
1205 1211
    ///
1206 1212
    /// Add an additional caption to the \c \@attributes section.
1207 1213
    GraphWriter& attributes(const std::string& caption) {
1208 1214
      _attributes_caption = caption;
1209 1215
      return *this;
1210 1216
    }
1211 1217

	
1212 1218
    /// \name Skipping section
1213 1219
    /// @{
1214 1220

	
1215 1221
    /// \brief Skip writing the node set
1216 1222
    ///
1217 1223
    /// The \c \@nodes section will not be written to the stream.
1218 1224
    GraphWriter& skipNodes() {
1219 1225
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1220 1226
      _skip_nodes = true;
1221 1227
      return *this;
1222 1228
    }
1223 1229

	
1224 1230
    /// \brief Skip writing edge set
1225 1231
    ///
1226 1232
    /// The \c \@edges section will not be written to the stream.
1227 1233
    GraphWriter& skipEdges() {
1228 1234
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1229 1235
      _skip_edges = true;
1230 1236
      return *this;
1231 1237
    }
1232 1238

	
1233 1239
    /// @}
1234 1240

	
1235 1241
  private:
1236 1242

	
1237 1243
    void writeNodes() {
1238 1244
      _writer_bits::MapStorageBase<Node>* label = 0;
1239 1245
      for (typename NodeMaps::iterator it = _node_maps.begin();
1240 1246
	   it != _node_maps.end(); ++it) {
1241 1247
        if (it->first == "label") {
1242 1248
	  label = it->second;
1243 1249
	  break;
1244 1250
	}
1245 1251
      }
1246 1252

	
1247 1253
      *_os << "@nodes";
1248 1254
      if (!_nodes_caption.empty()) {
1249 1255
	_writer_bits::writeToken(*_os << ' ', _nodes_caption);
1250 1256
      }
1251 1257
      *_os << std::endl;
1252 1258

	
1253 1259
      if (label == 0) {
1254 1260
	*_os << "label" << '\t';
1255 1261
      }
1256 1262
      for (typename NodeMaps::iterator it = _node_maps.begin();
1257 1263
	   it != _node_maps.end(); ++it) {
1258 1264
	_writer_bits::writeToken(*_os, it->first) << '\t';
1259 1265
      }
1260 1266
      *_os << std::endl;
1261 1267

	
1262 1268
      std::vector<Node> nodes;
1263 1269
      for (NodeIt n(_graph); n != INVALID; ++n) {
1264 1270
	nodes.push_back(n);
1265 1271
      }
1266 1272
      
1267 1273
      if (label == 0) {
1268 1274
	IdMap<Graph, Node> id_map(_graph);
1269 1275
	_writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1270 1276
	std::sort(nodes.begin(), nodes.end(), id_less);
1271 1277
      } else {
1272 1278
	label->sort(nodes);
1273 1279
      }
1274 1280

	
1275 1281
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1276 1282
	Node n = nodes[i];
1277 1283
	if (label == 0) {
1278 1284
	  std::ostringstream os;
1279 1285
	  os << _graph.id(n);
1280 1286
	  _writer_bits::writeToken(*_os, os.str());
1281 1287
	  *_os << '\t';
1282 1288
	  _node_index.insert(std::make_pair(n, os.str()));
1283 1289
	}
1284 1290
	for (typename NodeMaps::iterator it = _node_maps.begin();
1285 1291
	     it != _node_maps.end(); ++it) {
1286 1292
	  std::string value = it->second->get(n);
1287 1293
	  _writer_bits::writeToken(*_os, value);
1288 1294
	  if (it->first == "label") {
1289 1295
	    _node_index.insert(std::make_pair(n, value));
1290 1296
	  }
1291 1297
	  *_os << '\t';
1292 1298
	}
1293 1299
	*_os << std::endl;
1294 1300
      }
1295 1301
    }
1296 1302

	
1297 1303
    void createNodeIndex() {
1298 1304
      _writer_bits::MapStorageBase<Node>* label = 0;
1299 1305
      for (typename NodeMaps::iterator it = _node_maps.begin();
1300 1306
	   it != _node_maps.end(); ++it) {
1301 1307
        if (it->first == "label") {
1302 1308
	  label = it->second;
1303 1309
	  break;
1304 1310
	}
1305 1311
      }
1306 1312

	
1307 1313
      if (label == 0) {
1308 1314
	for (NodeIt n(_graph); n != INVALID; ++n) {
1309 1315
	  std::ostringstream os;
1310 1316
	  os << _graph.id(n);
1311 1317
	  _node_index.insert(std::make_pair(n, os.str()));	  
1312 1318
	}	
1313 1319
      } else {
1314 1320
	for (NodeIt n(_graph); n != INVALID; ++n) {
1315 1321
	  std::string value = label->get(n);	  
1316 1322
	  _node_index.insert(std::make_pair(n, value));
1317 1323
	}
1318 1324
      }
1319 1325
    }
1320 1326

	
1321 1327
    void writeEdges() {
1322 1328
      _writer_bits::MapStorageBase<Edge>* label = 0;
1323 1329
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1324 1330
	   it != _edge_maps.end(); ++it) {
1325 1331
        if (it->first == "label") {
1326 1332
	  label = it->second;
1327 1333
	  break;
1328 1334
	}
1329 1335
      }
1330 1336

	
1331 1337
      *_os << "@edges";
1332 1338
      if (!_edges_caption.empty()) {
1333 1339
	_writer_bits::writeToken(*_os << ' ', _edges_caption);
1334 1340
      }
1335 1341
      *_os << std::endl;
1336 1342

	
1337 1343
      *_os << '\t' << '\t';
1338 1344
      if (label == 0) {
1339 1345
	*_os << "label" << '\t';
1340 1346
      }
1341 1347
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1342 1348
	   it != _edge_maps.end(); ++it) {
1343 1349
	_writer_bits::writeToken(*_os, it->first) << '\t';
1344 1350
      }
1345 1351
      *_os << std::endl;
1346 1352

	
1347 1353
      std::vector<Edge> edges;
1348 1354
      for (EdgeIt n(_graph); n != INVALID; ++n) {
1349 1355
	edges.push_back(n);
1350 1356
      }
1351 1357
      
1352 1358
      if (label == 0) {
1353 1359
	IdMap<Graph, Edge> id_map(_graph);
1354 1360
	_writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1355 1361
	std::sort(edges.begin(), edges.end(), id_less);
1356 1362
      } else {
1357 1363
	label->sort(edges);
1358 1364
      }
1359 1365

	
1360 1366
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1361 1367
	Edge e = edges[i];
1362 1368
	_writer_bits::writeToken(*_os, _node_index.
1363 1369
				 find(_graph.u(e))->second);
1364 1370
	*_os << '\t';
1365 1371
	_writer_bits::writeToken(*_os, _node_index.
1366 1372
				 find(_graph.v(e))->second);
1367 1373
	*_os << '\t';
1368 1374
	if (label == 0) {
1369 1375
	  std::ostringstream os;
1370 1376
	  os << _graph.id(e);
1371 1377
	  _writer_bits::writeToken(*_os, os.str());
1372 1378
	  *_os << '\t';
1373 1379
	  _edge_index.insert(std::make_pair(e, os.str()));
1374 1380
	}
1375 1381
	for (typename EdgeMaps::iterator it = _edge_maps.begin();
1376 1382
	     it != _edge_maps.end(); ++it) {
1377 1383
	  std::string value = it->second->get(e);
1378 1384
	  _writer_bits::writeToken(*_os, value);
1379 1385
	  if (it->first == "label") {
1380 1386
	    _edge_index.insert(std::make_pair(e, value));
1381 1387
	  }
1382 1388
	  *_os << '\t';
1383 1389
	}
1384 1390
	*_os << std::endl;
1385 1391
      }
1386 1392
    }
1387 1393

	
1388 1394
    void createEdgeIndex() {
1389 1395
      _writer_bits::MapStorageBase<Edge>* label = 0;
1390 1396
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1391 1397
	   it != _edge_maps.end(); ++it) {
1392 1398
        if (it->first == "label") {
1393 1399
	  label = it->second;
1394 1400
	  break;
1395 1401
	}
1396 1402
      }
1397 1403

	
1398 1404
      if (label == 0) {
1399 1405
	for (EdgeIt e(_graph); e != INVALID; ++e) {
1400 1406
	  std::ostringstream os;
1401 1407
	  os << _graph.id(e);
1402 1408
	  _edge_index.insert(std::make_pair(e, os.str()));	  
1403 1409
	}	
1404 1410
      } else {
1405 1411
	for (EdgeIt e(_graph); e != INVALID; ++e) {
1406 1412
	  std::string value = label->get(e);	  
1407 1413
	  _edge_index.insert(std::make_pair(e, value));
1408 1414
	}
1409 1415
      }
1410 1416
    }
1411 1417

	
1412 1418
    void writeAttributes() {
1413 1419
      if (_attributes.empty()) return;
1414 1420
      *_os << "@attributes";
1415 1421
      if (!_attributes_caption.empty()) {
1416 1422
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
1417 1423
      }
1418 1424
      *_os << std::endl;
1419 1425
      for (typename Attributes::iterator it = _attributes.begin();
1420 1426
	   it != _attributes.end(); ++it) {
1421 1427
	_writer_bits::writeToken(*_os, it->first) << ' ';
1422 1428
	_writer_bits::writeToken(*_os, it->second->get());
1423 1429
	*_os << std::endl;
1424 1430
      }
1425 1431
    }
1426 1432
    
1427 1433
  public:
1428 1434
    
1429 1435
    /// \name Execution of the writer    
1430 1436
    /// @{
1431 1437

	
1432 1438
    /// \brief Start the batch processing
1433 1439
    ///
1434 1440
    /// This function starts the batch processing.
1435 1441
    void run() {
1436 1442
      if (!_skip_nodes) {
1437 1443
	writeNodes();
1438 1444
      } else {
1439 1445
	createNodeIndex();
1440 1446
      }
1441 1447
      if (!_skip_edges) {      
1442 1448
	writeEdges();
1443 1449
      } else {
1444 1450
	createEdgeIndex();
1445 1451
      }
1446 1452
      writeAttributes();
1447 1453
    }
1448 1454

	
1449 1455
    /// \brief Give back the stream of the writer
1450 1456
    ///
1451 1457
    /// Give back the stream of the writer
1452 1458
    std::ostream& ostream() {
1453 1459
      return *_os;
1454 1460
    }
1455 1461

	
1456 1462
    /// @}
1457 1463
  };
1458 1464

	
1459 1465
  /// \brief Return a \ref GraphWriter class
1460 1466
  /// 
1461 1467
  /// This function just returns a \ref GraphWriter class.
1462 1468
  /// \relates GraphWriter
1463 1469
  template <typename Graph>
1464 1470
  GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph) {
1465 1471
    GraphWriter<Graph> tmp(os, graph);
1466 1472
    return tmp;
1467 1473
  }
1468 1474

	
1469 1475
  /// \brief Return a \ref GraphWriter class
1470 1476
  /// 
1471 1477
  /// This function just returns a \ref GraphWriter class.
1472 1478
  /// \relates GraphWriter
1473 1479
  template <typename Graph>
1474 1480
  GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph) {
1475 1481
    GraphWriter<Graph> tmp(fn, graph);
1476 1482
    return tmp;
1477 1483
  }
1478 1484

	
1479 1485
  /// \brief Return a \ref GraphWriter class
1480 1486
  /// 
1481 1487
  /// This function just returns a \ref GraphWriter class.
1482 1488
  /// \relates GraphWriter
1483 1489
  template <typename Graph>
1484 1490
  GraphWriter<Graph> graphWriter(const char* fn, const Graph& graph) {
1485 1491
    GraphWriter<Graph> tmp(fn, graph);
1486 1492
    return tmp;
1487 1493
  }
1488 1494
}
1489 1495

	
1490 1496
#endif
0 comments (0 inline)