gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Set inline functions in header files (ticket #115)
0 2 0
default
2 files changed with 14 insertions and 14 deletions:
↑ Collapse diff ↑
Ignore white space 1536 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
    bool isWhiteSpace(char c) {
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
    bool isOct(char c) {
203
    inline bool isOct(char c) {
204 204
      return '0' <= c && c <='7'; 
205 205
    }
206 206
    
207
    int valueOct(char c) {
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
    bool isHex(char c) {
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
    int valueHex(char c) {
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
    bool isIdentifierFirstChar(char c) {
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
    bool isIdentifierChar(char c) {
230
    inline bool isIdentifierChar(char c) {
231 231
      return isIdentifierFirstChar(c) ||
232 232
	('0' <= c && c <= '9');
233 233
    }
234 234

	
235
    char readEscape(std::istream& is) {
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
    std::istream& readToken(std::istream& is, std::string& str) {
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

	
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
    bool isWhiteSpace(char c) {
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
    bool isEscaped(char c) {
233
    inline bool isEscaped(char c) {
234 234
      return c == '\\' || c == '\"' || c == '\'' || 
235 235
	c == '\a' || c == '\b';
236 236
    }
237 237

	
238
    static void writeEscape(std::ostream& os, char c) {
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
    bool requireEscape(const std::string& str) {
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
    std::ostream& writeToken(std::ostream& os, const std::string& str) {
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 917
  template <typename _Graph>
918 918
  class GraphWriter {
919 919
  public:
920 920

	
921 921
    typedef _Graph Graph;
922 922
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
923 923
    
924 924
  private:
925 925

	
926 926

	
927 927
    std::ostream* _os;
928 928
    bool local_os;
929 929

	
930 930
    Graph& _graph;
931 931

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

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

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

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

	
953 953
    bool _skip_nodes;
954 954
    bool _skip_edges;
955 955

	
956 956
  public:
957 957

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

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

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

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

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

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

	
999 999
      if (local_os) {
1000 1000
	delete _os;
1001 1001
      }
1002 1002
    }
1003 1003
    
1004 1004
  private:
1005 1005

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

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

	
1017 1017
      other._os = 0;
1018 1018
      other.local_os = false;
1019 1019

	
1020 1020
      _node_index.swap(other._node_index);
1021 1021
      _edge_index.swap(other._edge_index);
1022 1022

	
1023 1023
      _node_maps.swap(other._node_maps);
1024 1024
      _edge_maps.swap(other._edge_maps);
1025 1025
      _attributes.swap(other._attributes);
1026 1026

	
1027 1027
      _nodes_caption = other._nodes_caption;
1028 1028
      _edges_caption = other._edges_caption;
1029 1029
      _attributes_caption = other._attributes_caption;
1030 1030
    }
1031 1031

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

	
1034 1034
  public:
1035 1035

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

	
1051 1051
    /// \brief Node map writing rule
1052 1052
    ///
1053 1053
    /// Add a node map writing rule with specialized converter to the
1054 1054
    /// writer.
1055 1055
    template <typename Map, typename Converter>
1056 1056
    GraphWriter& nodeMap(const std::string& caption, const Map& map, 
1057 1057
			   const Converter& converter = Converter()) {
1058 1058
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1059 1059
      _writer_bits::MapStorageBase<Node>* storage = 
0 comments (0 inline)